'use client' import { useEffect, useMemo } from 'react' import { useForm, Controller } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' import { format } from 'date-fns' import { isSaneDateString } from '@/lib/utils' import { useTranslations } from 'next-intl' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Loader2 } from 'lucide-react' import type { CreateTransactionInput, Currency } from '@/types' interface TransactionFormProps { onSubmit: (data: CreateTransactionInput) => Promise isLoading: boolean } const currencies: Currency[] = ['SEK', 'EUR', 'USD', 'GBP', 'NOK', 'DKK'] export default function TransactionForm({ onSubmit, isLoading }: TransactionFormProps) { const t = useTranslations('tx_form') const schema = useMemo( () => z.object({ date: z .string() .min(1, t('date_required')) // Single source of truth for the date rule, shared with the server // CreateTransactionSchema: rejects the 6-digit-year corruption a // native date input can emit ('202403-02-05') plus impossible / // out-of-range dates. .refine((s) => !s || isSaneDateString(s), t('date_invalid')), description: z.string().min(1, t('description_required')), amount: z.number().refine((n) => n !== 0, t('amount_required')), currency: z.enum(['SEK', 'EUR', 'USD', 'GBP', 'NOK', 'DKK']), notes: z.string().optional(), }), [t] ) type FormData = z.infer const { register, handleSubmit, control, setValue, formState: { errors }, } = useForm({ resolver: zodResolver(schema), defaultValues: { date: '', description: '', amount: 0, currency: 'SEK', notes: '', }, }) // Set date default on client only to avoid hydration mismatch useEffect(() => { setValue('date', format(new Date(), 'yyyy-MM-dd')) }, []) const onFormSubmit = (data: FormData) => { onSubmit({ date: data.date, description: data.description, amount: data.amount, currency: data.currency, notes: data.notes, }) } return (
{errors.date && (

{errors.date.message}

)}
( )} />
{errors.description && (

{errors.description.message}

)}
{errors.amount && (

{errors.amount.message}

)}

{t('amount_help')}