--- name: form description: Generate forms with React Hook Form and Zod validation following established patterns. Use when creating forms, input validation, modal forms, or handling user input. --- # Form Generator Generate forms using React Hook Form with Zod validation following established patterns. ## Directory Structure ``` src/ ├── schema/ │ └── myFeature.ts # Zod schemas + default values ├── constants/ │ └── message.ts # Validation error messages └── components/ └── MyForm/ └── index.tsx ``` ## Schema File Pattern ```tsx // src/schema/user.ts import { z } from 'zod'; import { FORM_VALIDATION } from '@/constants/message'; const amountAboveZeroRefiner = (value: string) => 0 < Number(value); export const userSchema = z.object({ name: z.string().min(1, FORM_VALIDATION.NAME_REQUIRED), email: z.string().email(FORM_VALIDATION.INVALID_EMAIL), amount: z.string() .min(1, FORM_VALIDATION.AMOUNT_REQUIRED) .refine(amountAboveZeroRefiner, { message: FORM_VALIDATION.AMOUNT_MUST_BE_POSITIVE, }), frequency: z.enum(['weekly', 'fortnightly', 'monthly']), startDate: z.date(), endDate: z.date().optional(), }); export type UserFormData = z.infer; export const userDefaultValues: UserFormData = { name: '', email: '', amount: '', frequency: 'monthly', startDate: new Date(), endDate: undefined, }; ``` ## Validation Messages ```tsx // src/constants/message.ts export enum FORM_VALIDATION { NAME_REQUIRED = 'Name is required', INVALID_EMAIL = 'Please enter a valid email address', AMOUNT_REQUIRED = 'Amount is required', AMOUNT_MUST_BE_POSITIVE = 'Amount must be greater than zero', DATE_REQUIRED = 'Date is required', DATE_MUST_BE_FUTURE = 'Date must be in the future', PASSWORD_MIN_LENGTH = 'Password must be at least 8 characters', } ``` ## Basic Form Pattern ```tsx import React from 'react'; import { View } from 'react-native'; import { useForm, Controller, FormProvider } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { Button, Input } from '@/components'; import { userSchema, userDefaultValues, UserFormData } from '@/schema/user'; interface UserFormProps { onSubmit: (data: UserFormData) => void; initialValues?: Partial; } const UserForm: React.FC = ({ onSubmit, initialValues }) => { const form = useForm({ resolver: zodResolver(userSchema), defaultValues: { ...userDefaultValues, ...initialValues }, }); const { control, handleSubmit, formState: { errors, isSubmitting } } = form; return ( ( )} /> ( )} />