'use server'; import { z } from 'zod'; import { headers } from 'next/headers'; import { getProductBySlug } from '@/content/products'; import { escapeHtml, rateLimit, verifyRecaptcha, baseContactSchema } from '@/lib/security'; import { getMailClient } from '@/lib/mail'; const orderSchema = baseContactSchema.extend({ address: z.string().optional(), notes: z.string().optional(), products: z.string(), total: z.string(), // We don't trust this total, just checking if it exists }); const productItemSchema = z.array(z.object({ slug: z.string(), quantity: z.number().int().min(1).max(100), })); export async function submitOrderForm(prevState: unknown, formData: FormData) { try { const ip = (await headers()).get('x-forwarded-for') || 'unknown'; if (!rateLimit(ip)) { return { success: false, message: 'Wysłano zbyt wiele zapytań. Spróbuj ponownie później.' }; } if (process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY && process.env.RECAPTCHA_SECRET_KEY) { const token = formData.get('recaptchaToken') as string; if (!token) { return { success: false, message: "Weryfikacja bezpieczeństwa nie powiodła się. Odśwież stronę i spróbuj ponownie." }; } const success = await verifyRecaptcha(token); if (!success) { return { success: false, message: "Weryfikacja bezpieczeństwa nie powiodła się. Odśwież stronę i spróbuj ponownie." }; } } const mailClient = getMailClient(); if (!mailClient) { return { success: false, message: "Funkcja wysyłania wiadomości jest tymczasowo niedostępna." }; } const data = orderSchema.parse({ name: formData.get('name'), phone: formData.get('phone'), email: formData.get('email'), address: formData.get('address') || '', notes: formData.get('notes') || '', consent: formData.get('consent'), products: formData.get('products'), total: formData.get('total'), }); let rawProducts; try { rawProducts = JSON.parse(data.products); } catch { return { success: false, message: "Błąd przetwarzania koszyka." }; } const parsedProducts = productItemSchema.parse(rawProducts); if (parsedProducts.length === 0) { return { success: false, message: "Koszyk jest pusty." }; } let calculatedTotal = 0; const validatedProducts = []; for (const p of parsedProducts) { const dbProduct = getProductBySlug(p.slug); if (!dbProduct || !dbProduct.price) { return { success: false, message: "Jeden z produktów w koszyku jest niedostępny." }; } validatedProducts.push({ name: dbProduct.name, quantity: p.quantity, price: dbProduct.price }); calculatedTotal += dbProduct.price * p.quantity; } const productRows = validatedProducts.map(p => `${escapeHtml(p.name)}${p.quantity}${(p.price * p.quantity).toLocaleString('pl-PL')} zł` ).join(''); const { data: emailData, error } = await mailClient.resend.emails.send({ from: mailClient.fromEmail, to: mailClient.toEmail, replyTo: data.email, subject: `Nowe zamówienie od ${escapeHtml(data.name)} — ${calculatedTotal.toLocaleString('pl-PL')} zł`, html: `

Nowe zamówienie — ThermCool

Dane klienta

Imię: ${escapeHtml(data.name)}

Telefon: ${escapeHtml(data.phone)}

Email: ${escapeHtml(data.email)}

${data.address ? `

Adres: ${escapeHtml(data.address)}

` : ''} ${data.notes ? `

Uwagi: ${escapeHtml(data.notes)}

` : ''}

Zamówione produkty

${productRows}
Produkt Ilość Wartość
Łącznie (urządzenia) ${calculatedTotal.toLocaleString('pl-PL')} zł

+ koszt montażu do ustalenia telefonicznie

`, }); if (error) { console.error("Resend Error:", error); return { success: false, message: "Nie udało się wysłać wiadomości ze względu na błąd serwera pocztowego." }; } console.log("Wysłano e-mail (ID):", emailData?.id); return { success: true, message: 'Dziękujemy! Skontaktujemy się z Tobą w ciągu 24 godzin, aby potwierdzić zamówienie i ustalić termin montażu.' }; } catch (error) { console.error("Błąd formularza:", error); return { success: false, message: 'Wystąpił błąd podczas wysyłania zamówienia. Spróbuj ponownie.' }; } }