import { zodResolver } from '@hookform/resolvers/zod' import { useEffect } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Home, Info, Loader2, UserPlus, Users } from 'lucide-react' import { Controller, useForm, useWatch } from 'react-hook-form' import { Link, useSearchParams } from 'react-router' import { toast } from 'sonner' import { FormError, FormField, PasswordInput } from '@/components/form-field' import { paths } from '@/components/layout/nav-items' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { api, ApiError } from '@/lib/api' import { useRegister } from '@/lib/auth' import { queryKeys } from '@/lib/query' import { t } from '@/lib/strings' import { cn } from '@/lib/utils' import { AuthShell } from './auth-shell' import type { RegistrationInfo } from '@/types/RegistrationInfo' import { normalizeInviteCode, registerSchema, type RegisterForm } from './schemas' const s = t.auth.register export function RegisterPage() { const registerAccount = useRegister() const [params] = useSearchParams() // Davet bağlantısı: /kayit?davet=ABCD-EFGH → "Davetle katıl" seçili ve kod dolu const invite = params.get('davet') ?? '' // Sunucu politikası (REGISTRATION): yeni hane kurulabilir mi? const qc = useQueryClient() const info = useQuery({ queryKey: queryKeys.registration, queryFn: () => api.get('/auth/registration'), }) const newAllowed = info.data?.new_household_allowed ?? true const { register, control, handleSubmit, setError, setValue, formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(registerSchema), mode: 'onTouched', defaultValues: { name: '', email: '', password: '', mode: invite ? 'join' : 'new', household_name: '', invite_code: invite, }, }) // Kayıt kapalıysa yalnızca "Davetle katıl" useEffect(() => { if (!newAllowed) setValue('mode', 'join') }, [newAllowed, setValue]) const mode = useWatch({ control, name: 'mode' }) const name = useWatch({ control, name: 'name' }).trim() const onSubmit = handleSubmit(async (v) => { try { const me = await registerAccount.mutateAsync({ name: v.name, email: v.email, password: v.password, ...(v.mode === 'join' ? { invite_code: normalizeInviteCode(v.invite_code) } : { household_name: v.household_name || undefined }), }) toast.success(v.mode === 'join' ? s.joined(me.household.name) : s.welcome(me.household.name)) } catch (e) { if (!(e instanceof ApiError)) return setError('root', { message: String(e) }) // Sunucu hatasını ilgili alana bağla if (e.code === 'conflict') setError('email', { message: e.message }, { shouldFocus: true }) else if (e.code === 'registration_closed') { // Bu arada başka biri ilk haneyi kurmuş olabilir → bilgiyi tazele, formu davete çevir await qc.invalidateQueries({ queryKey: queryKeys.registration }) setError('root', { message: e.message }) } else if (v.mode === 'join' && e.code === 'bad_request' && e.message.includes('Davet')) setError('invite_code', { message: e.message }, { shouldFocus: true }) else setError('root', { message: e.message }) } }) const donus = params.get('donus') const loginLink = donus ? `${paths.login}?donus=${encodeURIComponent(donus)}` : paths.login return ( {s.hasAccount}{' '} {s.toLogin} } >
{(f) => } {(f) => ( )} {(f) => } {/* Yeni hane mi, davetle katılma mı? */}
{s.modeLabel} {!newAllowed && (

{s.closedNote}

)} {newAllowed && ( (
{( [ ['new', s.modeNew, Home], ['join', s.modeJoin, Users], ] as const ).map(([value, label, Icon]) => ( ))}
)} /> )} {mode === 'new' ? ( {(f) => ( )} ) : ( {(f) => ( )} )}
) }