import { zodResolver } from '@hookform/resolvers/zod'; import { SignupFormInput, signupInputSchema } from '@dorfteich/shared'; import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; import { Resolver, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { Field, FormError, applyFieldErrors } from '../../components/forms'; import { apiGet, apiPost } from '../../lib/api'; import { useDocumentTitle } from '../../lib/use-document-title'; export function SignupPage(): React.JSX.Element { const { t, i18n } = useTranslation(); useDocumentTitle(t('auth:signup.title')); const [error, setError] = useState(null); const [registered, setRegistered] = useState(null); const registration = useQuery({ queryKey: ['auth', 'registration'], queryFn: () => apiGet<{ mode: 'open' | 'closed' }>('/auth/registration'), }); type SignupFormValues = SignupFormInput; // One confined cast: RHF cannot express Zod's input/output split // (locale is optional on input, defaulted on output) without it. const form = useForm({ resolver: zodResolver(signupInputSchema) as Resolver, defaultValues: { locale: i18n.language === 'de' ? 'de' : 'en' }, }); const onSubmit = form.handleSubmit(async (input) => { setError(null); try { await apiPost('/auth/signup', input); setRegistered(input.email); } catch (err) { setError(err); applyFieldErrors(err, (name, fieldError) => form.setError(name as keyof SignupFormValues, fieldError), ); } }); if (registration.data?.mode === 'closed') { return (

{t('auth:signup.title')}

{t('auth:signup.closed')}

{t('auth:signup.loginLink')}

); } if (registered) { return (

{t('auth:signup.success.title')}

{t('auth:signup.success.body', { email: registered })}

); } return (

{t('auth:signup.title')}

{t('auth:signup.haveAccount')} {t('auth:signup.loginLink')}

); }