import React, { useEffect, useMemo, useState } from 'react'; import { useForm } from '@inertiajs/react'; import { useTranslation } from 'react-i18next'; import { LoaderCircle, User, Mail, Phone, Lock, MapPin } from 'lucide-react'; import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@/components/ui/dialog'; import { Alert, AlertDescription } from '@/components/ui/alert'; interface RegisterFormProps { packageId?: number; onSuccess?: (payload: any) => void; privacyHtml: string; } const getCsrfToken = () => (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? ''; export default function RegisterForm({ packageId, onSuccess, privacyHtml }: RegisterFormProps) { const { t } = useTranslation(['auth', 'common']); const csrfToken = useMemo(getCsrfToken, []); const { data, setData, errors, setError, clearErrors, reset } = useForm({ username: '', email: '', password: '', password_confirmation: '', first_name: '', last_name: '', address: '', phone: '', privacy_consent: false, package_id: packageId ?? null, }); const [privacyOpen, setPrivacyOpen] = useState(false); const [hasTriedSubmit, setHasTriedSubmit] = useState(false); const [submitting, setSubmitting] = useState(false); const [formError, setFormError] = useState(null); useEffect(() => { setData('package_id', packageId ?? null); }, [packageId]); 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]); const parseJson = async (response: Response) => { if (response.headers.get('Content-Type')?.includes('application/json')) { const json = await response.json().catch(() => null); if (json) return json; } const text = await response.text(); throw new Error(text || 'Invalid server response (unexpected end of data or non-JSON).'); }; const submit = async (event: React.FormEvent) => { event.preventDefault(); setHasTriedSubmit(true); setSubmitting(true); setFormError(null); clearErrors(); try { const response = await fetch('/purchase/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json', 'X-CSRF-TOKEN': csrfToken, 'X-Requested-With': 'XMLHttpRequest', }, body: JSON.stringify({ ...data, privacy_consent: Boolean(data.privacy_consent), }), }); if (response.ok) { const payload = await parseJson(response); reset({ username: '', email: '', password: '', password_confirmation: '', first_name: '', last_name: '', address: '', phone: '', privacy_consent: false, package_id: packageId ?? null, }); setHasTriedSubmit(false); if (onSuccess) { onSuccess(payload); } return; } if (response.status === 422) { const body = await parseJson(response); const validationErrors = body.errors ?? {}; let fallbackMessage: string | null = body.message ?? null; Object.entries(validationErrors).forEach(([key, value]) => { const message = Array.isArray(value) ? value[0] : value; if (typeof message === 'string') { setError(key, message); if (!fallbackMessage) { fallbackMessage = message; } } }); if (fallbackMessage) { setFormError(fallbackMessage); } return; } setFormError(t('register.generic_error', { defaultValue: 'Registrierung fehlgeschlagen. Bitte versuche es erneut.' })); } catch (error) { const message = (error as Error).message || t('register.generic_error', { defaultValue: 'Registrierung fehlgeschlagen. Bitte versuche es erneut.' }); setFormError(message); } finally { setSubmitting(false); } }; return (
{ setData('first_name', event.target.value); if (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', event.target.value); if (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', event.target.value); if (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('username', event.target.value); if (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('phone', event.target.value); if (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}

}