import React, { useEffect, useMemo, useState } from 'react'; import { useForm, usePage } from '@inertiajs/react'; import { useTranslation } from 'react-i18next'; import toast from 'react-hot-toast'; import { LoaderCircle, User, Mail, Phone, Lock, MapPin } from 'lucide-react'; import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/ui/dialog'; declare const route: (name: string, params?: Record) => string; export interface RegisterSuccessPayload { user: any | null; redirect?: string | null; pending_purchase?: boolean; } interface RegisterFormProps { packageId?: number; onSuccess?: (payload: RegisterSuccessPayload) => void; privacyHtml: string; locale?: string; } export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale }: RegisterFormProps) { const [privacyOpen, setPrivacyOpen] = useState(false); const [hasTriedSubmit, setHasTriedSubmit] = useState(false); const { t } = useTranslation(['auth', 'common']); const page = usePage<{ errors: Record; locale?: string; auth?: { user?: any | null } }>(); const resolvedLocale = locale ?? page.props.locale ?? 'de'; const { data, setData, errors, clearErrors, reset, setError } = useForm({ username: '', email: '', password: '', password_confirmation: '', first_name: '', last_name: '', address: '', phone: '', privacy_consent: false, package_id: packageId || null, }); useEffect(() => { if (hasTriedSubmit && Object.keys(errors).length > 0) { toast.error(Object.values(errors).join(' ')); } }, [errors, hasTriedSubmit]); const registerEndpoint = useMemo(() => { if (typeof route === 'function') { try { return route('checkout.register'); } catch (error) { // ignore ziggy errors and fall back } } return `/${resolvedLocale}/register`; }, [resolvedLocale]); const submit = async (event: React.FormEvent) => { event.preventDefault(); setHasTriedSubmit(true); setIsSubmitting(true); clearErrors(); const body = { ...data, locale: resolvedLocale, package_id: data.package_id ?? packageId ?? null, }; try { const response = await fetch(registerEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', 'X-CSRF-TOKEN': (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? '', }, credentials: 'same-origin', body: JSON.stringify(body), }); if (response.ok) { const json = await response.json(); toast.success(t('register.success_toast', 'Registrierung erfolgreich')); onSuccess?.({ user: json?.user ?? null, redirect: json?.redirect ?? null, pending_purchase: json?.pending_purchase ?? json?.user?.pending_purchase ?? false, }); reset(); setHasTriedSubmit(false); return; } if (response.status === 422) { const json = await response.json(); const fieldErrors = json?.errors ?? {}; Object.entries(fieldErrors).forEach(([key, message]) => { if (Array.isArray(message) && message.length > 0) { setError(key, message[0] as string); } else if (typeof message === 'string') { setError(key, message); } }); toast.error(t('register.validation_failed', 'Bitte pruefen Sie Ihre Eingaben.')); return; } toast.error(t('register.unexpected_error', 'Registrierung nicht moeglich.')); } catch (error) { console.error('Register request failed', error); toast.error(t('register.unexpected_error', 'Registrierung nicht moeglich.')); } finally { setIsSubmitting(false); } }; useEffect(() => { if (!hasTriedSubmit) { return; } const errorKeys = Object.keys(errors); if (errorKeys.length === 0) { return; } const firstError = errorKeys[0]; const field = document.querySelector(`[name="${firstError}"]`); if (field) { field.scrollIntoView({ behavior: 'smooth', block: 'center' }); field.focus(); } }, [errors, hasTriedSubmit]); return (
{ setData('first_name', e.target.value); if (e.target.value.trim() && errors.first_name) { clearErrors('first_name'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.first_name ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.first_name_placeholder')} />
{errors.first_name &&

{errors.first_name}

}
{ setData('last_name', e.target.value); if (e.target.value.trim() && errors.last_name) { clearErrors('last_name'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.last_name ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.last_name_placeholder')} />
{errors.last_name &&

{errors.last_name}

}
{ setData('email', e.target.value); if (e.target.value.trim() && errors.email) { clearErrors('email'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.email ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.email_placeholder')} />
{errors.email &&

{errors.email}

}
{ setData('address', e.target.value); if (e.target.value.trim() && errors.address) { clearErrors('address'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.address ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.address_placeholder')} />
{errors.address &&

{errors.address}

}
{ setData('phone', e.target.value); if (e.target.value.trim() && errors.phone) { clearErrors('phone'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.phone ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.phone_placeholder')} />
{errors.phone &&

{errors.phone}

}
{ setData('username', e.target.value); if (e.target.value.trim() && errors.username) { clearErrors('username'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.username ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.username_placeholder')} />
{errors.username &&

{errors.username}

}
{ setData('password', e.target.value); if (e.target.value.trim() && errors.password) { clearErrors('password'); } if (data.password_confirmation && e.target.value === data.password_confirmation) { clearErrors('password_confirmation'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.password ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.password_placeholder')} />
{errors.password &&

{errors.password}

}
{ setData('password_confirmation', e.target.value); if (e.target.value.trim() && errors.password_confirmation) { clearErrors('password_confirmation'); } if (data.password && e.target.value === data.password) { clearErrors('password_confirmation'); } }} className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.password_confirmation ? 'border-red-500' : 'border-gray-300'}`} placeholder={t('register.confirm_password_placeholder')} />
{errors.password_confirmation &&

{errors.password_confirmation}

}
{ setData('privacy_consent', e.target.checked); if (e.target.checked && errors.privacy_consent) { clearErrors('privacy_consent'); } }} className="h-4 w-4 text-[#FFB6C1] focus:ring-[#FFB6C1] border-gray-300 rounded" /> {errors.privacy_consent &&

{errors.privacy_consent}

}
{Object.keys(errors).length > 0 && (

{t('register.errors_title')}

    {Object.entries(errors).map(([key, value]) => (
  • {t(`register.errors.${key}`)}: {value}
  • ))}
)} Datenschutzerklärung Lesen Sie unsere Datenschutzerklärung.
); }