diff --git a/app/zamowienie/page.tsx b/app/zamowienie/page.tsx index 0f630a1..89ce929 100644 --- a/app/zamowienie/page.tsx +++ b/app/zamowienie/page.tsx @@ -4,8 +4,9 @@ import { useCartStore } from '@/lib/cart-store'; import { useActionState, useEffect, startTransition } from 'react'; import Link from 'next/link'; import { submitOrderForm } from './actions'; -import { ArrowLeft, CheckCircle } from 'lucide-react'; +import { ArrowLeft, CheckCircle2 } from 'lucide-react'; import { buttonClasses } from '@/components/ui/Button'; +import { getRecaptchaToken } from '@/lib/getRecaptchaToken'; const initialState = { success: false, message: '' }; @@ -34,14 +35,16 @@ Wróć do sklepu if (state.success) { return ( -
-
- -

Zamówienie przyjęte!

-

{state.message}

- -Wróć do sklepu - +
+
+
+ +

Zamówienie przyjęte!

+

{state.message}

+ + Wróć do sklepu + +
); @@ -78,11 +81,8 @@ Wróć do sklepu
{ e.preventDefault(); const formData = new FormData(e.currentTarget); - if (process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY) { - const token = await (window as any).grecaptcha.execute( - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY, - { action: 'submit' } - ); + const token = await getRecaptchaToken('submit'); + if (token) { formData.append('recaptchaToken', token); } startTransition(() => { diff --git a/components/awaria/AwariaClient.tsx b/components/awaria/AwariaClient.tsx index 6a6dd1c..48f5e10 100644 --- a/components/awaria/AwariaClient.tsx +++ b/components/awaria/AwariaClient.tsx @@ -1,10 +1,11 @@ 'use client'; import { useState } from 'react'; -import { AlertTriangle, Wrench, Phone, Check, Clock, Zap } from 'lucide-react'; +import { Wrench, Zap, Info, Clock, Check, AlertTriangle, Phone, CheckCircle2 } from 'lucide-react'; import Link from 'next/link'; import { companyDetails } from '@/content/company'; import { submitAwariaForm } from '@/app/zgloszenie-awarii/actions'; +import { getRecaptchaToken } from '@/lib/getRecaptchaToken'; // Kody błędów popularnych marek const ERROR_CODES: Record> = { @@ -125,15 +126,8 @@ export function AwariaClient() { } setIsSubmitting(true); - let recaptchaToken = ''; - if (process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY) { - recaptchaToken = await (window as any).grecaptcha.execute( - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY, - { action: 'submit' } - ); - } - - await submitAwariaForm({ + const recaptchaToken = await getRecaptchaToken('submit'); + const formDataObj: any = { isUrgent, brand, model, @@ -147,8 +141,10 @@ export function AwariaClient() { city, preferredDate: '', preferredTime: '', - recaptchaToken, - }); + }; + if (recaptchaToken) formDataObj.recaptchaToken = recaptchaToken; + + await submitAwariaForm(formDataObj); setIsSubmitting(false); setStep('success'); @@ -157,31 +153,25 @@ export function AwariaClient() { if (step === 'success') { return (
-
-
- -
-

- Zgłoszenie przyjęte! -

-

- {isUrgent - ? 'Twoje zgłoszenie oznaczono jako PILNE — skontaktujemy się z Tobą w ciągu 2 godzin.' - : 'Skontaktujemy się z Tobą w ciągu 24 godzin, aby ustalić termin wizyty serwisanta.'} -

-

- Jeśli sprawa jest pilna — zadzwoń bezpośrednio: -

- - - - - - Wróć na stronę główną - - +
); diff --git a/components/forms/ContactForm.tsx b/components/forms/ContactForm.tsx index 0a03218..a1e5764 100644 --- a/components/forms/ContactForm.tsx +++ b/components/forms/ContactForm.tsx @@ -6,6 +6,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Loader2, CheckCircle2, AlertCircle, Check } from 'lucide-react'; import { submitContactForm } from '@/app/kontakt/actions'; +import { getRecaptchaToken } from '@/lib/getRecaptchaToken'; const contactFormSchema = z.object({ name: z.string().min(2, "Imię musi mieć min. 2 znaki"), @@ -49,11 +50,8 @@ export function ContactForm() { }); formData.append("consent", consent ? 'true' : 'false'); - if (process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY) { - const token = await (window as any).grecaptcha.execute( - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY, - { action: 'submit' } - ); + const token = await getRecaptchaToken('submit'); + if (token) { formData.append('recaptchaToken', token); } @@ -187,9 +185,6 @@ export function ContactForm() { - - - {errors.subject &&

{errors.subject.message}

} diff --git a/components/shop/MultisplitContactForm.tsx b/components/shop/MultisplitContactForm.tsx index 9a7b3b5..debd058 100644 --- a/components/shop/MultisplitContactForm.tsx +++ b/components/shop/MultisplitContactForm.tsx @@ -1,8 +1,9 @@ 'use client'; import { useState } from 'react'; -import { Check, Loader2 } from 'lucide-react'; +import { Check, Loader2, CheckCircle2 } from 'lucide-react'; import { submitMultisplitForm } from '@/app/zapytanie-multisplit/actions'; +import { getRecaptchaToken } from '@/lib/getRecaptchaToken'; interface Props { productName: string; @@ -39,13 +40,8 @@ export default function MultisplitContactForm({ productName, productSku }: Props setLoading(true); setError(''); try { - let recaptchaToken = ''; - if (process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY) { - recaptchaToken = await (window as any).grecaptcha.execute( - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY, - { action: 'submit' } - ); - } + const token = await getRecaptchaToken('submit'); + const recaptchaToken = token || ''; const res = await submitMultisplitForm({ name: form.name, @@ -69,12 +65,16 @@ export default function MultisplitContactForm({ productName, productSku }: Props if (sent) { return ( -
-
- -
-

Zapytanie wysłane!

-

Oddzwonimy w ciągu 24 godzin z bezpłatną wyceną.

+
+ +

Zapytanie wysłane!

+

Oddzwonimy w ciągu 24 godzin z bezpłatną wyceną.

+
); } diff --git a/lib/getRecaptchaToken.ts b/lib/getRecaptchaToken.ts new file mode 100644 index 0000000..baeb605 --- /dev/null +++ b/lib/getRecaptchaToken.ts @@ -0,0 +1,21 @@ +'use client'; + +export function getRecaptchaToken(action: string = 'submit'): Promise { + return new Promise((resolve) => { + const siteKey = process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY; + if (typeof window === 'undefined' || !siteKey || !(window as any).grecaptcha) { + resolve(null); + return; + } + try { + (window as any).grecaptcha.ready(() => { + (window as any).grecaptcha + .execute(siteKey, { action }) + .then((token: string) => resolve(token)) + .catch(() => resolve(null)); + }); + } catch { + resolve(null); + } + }); +}