106 lines
5.2 KiB
TypeScript
106 lines
5.2 KiB
TypeScript
"use server";
|
|
|
|
import { z } from "zod";
|
|
import { headers } from "next/headers";
|
|
import { escapeHtml, rateLimit, verifyRecaptcha, baseContactSchema } from "@/lib/security";
|
|
import { getMailClient } from "@/lib/mail";
|
|
|
|
const multisplitFormSchema = baseContactSchema.extend({
|
|
city: z.string().min(1, "Wybierz miasto"),
|
|
rooms: z.string().optional(),
|
|
message: z.string().optional(),
|
|
productName: z.string(),
|
|
productSku: z.string(),
|
|
recaptchaToken: z.string().optional(),
|
|
});
|
|
|
|
export async function submitMultisplitForm(data: Record<string, unknown>) {
|
|
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) {
|
|
if (!data.recaptchaToken || typeof data.recaptchaToken !== 'string') {
|
|
return { success: false, message: "Weryfikacja bezpieczeństwa nie powiodła się. Odśwież stronę i spróbuj ponownie." };
|
|
}
|
|
const success = await verifyRecaptcha(data.recaptchaToken);
|
|
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." };
|
|
}
|
|
|
|
// Convert boolean consent to string for base schema compatibility if it comes as boolean
|
|
const processData = { ...data };
|
|
if (typeof processData.consent === 'boolean') {
|
|
processData.consent = processData.consent ? "true" : "false";
|
|
}
|
|
|
|
const validatedData = multisplitFormSchema.parse(processData);
|
|
|
|
const { data: emailData, error } = await mailClient.resend.emails.send({
|
|
from: mailClient.fromEmail,
|
|
to: mailClient.toEmail,
|
|
replyTo: validatedData.email || undefined,
|
|
subject: `Zapytanie o multisplit: ${escapeHtml(validatedData.productName)} (${escapeHtml(validatedData.productSku)})`,
|
|
html: `
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; background-color: #ffffff;">
|
|
<div style="background-color: #0F2A47; padding: 20px; text-align: center;">
|
|
<h1 style="color: #ffffff; margin: 0; font-size: 24px;">Zapytanie o multisplit</h1>
|
|
</div>
|
|
<div style="padding: 24px; color: #1e293b;">
|
|
<table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9; width: 120px;"><strong>Imię:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.name)}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;"><strong>Telefon:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.phone)}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;"><strong>E-mail:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.email || 'Brak')}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;"><strong>Miasto:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.city)}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;"><strong>Produkt:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.productName)} (${escapeHtml(validatedData.productSku)})</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;"><strong>Pokoje:</strong></td>
|
|
<td style="padding: 8px 0; border-bottom: 1px solid #f1f5f9;">${escapeHtml(validatedData.rooms || '')}</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h2 style="font-size: 18px; border-bottom: 2px solid #f1f5f9; padding-bottom: 10px;">Dodatkowe informacje:</h2>
|
|
<div style="background-color: #f8fafc; padding: 15px; border-radius: 6px; font-size: 15px; line-height: 1.6; white-space: pre-wrap;">
|
|
${escapeHtml(validatedData.message || 'Brak')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
});
|
|
|
|
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 za zapytanie! Skontaktujemy się z Tobą najszybciej jak to możliwe." };
|
|
} catch (error) {
|
|
console.error("Błąd formularza:", error);
|
|
return { success: false, message: "Błąd walidacji lub błąd serwera. Spróbuj ponownie później." };
|
|
}
|
|
}
|