Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
Forms & Validation
GrantMaster is a data-intensive application. We use a standardized stack to handle complex forms with dozens of fields and cross-field validation rules.1. The Stack
- Hook:
useZodFormfrom@/hooks/useZodForm(wraps react-hook-form + Zod). - Engine:
react-hook-form(RHF). - Validation:
zod. - UI Components:
shadcn/ui(built on Radix UI) +FormComponents.tsx(FormField,FormSection,FormActions,FormGrid).
Deprecation notice:useValidatedFormis deprecated. Always useuseZodForm.
2. Standard Pattern: useZodForm
The useZodForm hook (@/hooks/useZodForm) is the standard way to build forms. It wraps react-hook-form with Zod validation and provides built-in toast notifications, error handling via handleError(), and convenience helpers.
API
Example
3. Form Layout Components
Use the standardized layout components from@/components/ui/FormComponents:
<FormSection title="..." description="...">: Groups related fields with a heading.<FormField label="..." required error="..." hint="...">: Wraps an input with label, required indicator, error/hint text, and accessiblearia-attributes.<FormGrid columns={2}>: Responsive grid for laying out fields.<FormActions>: Right-aligned action bar for submit/cancel buttons.
4. Best Practices
Validation Source of Truth
Whenever possible, re-use the Zod schemas defined insrc/schemas/. This ensures that frontend validation exactly matches the BaseService validation on the backend.
Real-time vs. On-Submit
- Default:
useZodFormdefaults tomode: 'onBlur'— fields are validated when the user leaves them. - Critical Fields: For unique fields (like “Project Code”), use
onBlurto check for duplicates in the background. - Eager validation: Pass
mode: 'onChange'for real-time feedback (use sparingly).
Handling Large Forms
For multi-tab forms (e.g., Grant Application):- Split the form into smaller sub-components.
- Pass the
formobject down via props or useuseFormContext(). - Only use
reset()when necessary to prevent losing user progress.
Error Handling
useZodForm integrates with the centralized error handler (handleError) and toast system automatically:
- On success: shows
successMessagetoast if provided. - On error: calls
handleError()(logs to console + Sentry) and shows an error toast witherrorMessagePrefix. - Custom error handling: pass
onErrorcallback for additional logic.
Maintenance
Update this document when:- Upgrading to a major new version of
react-hook-form. - Introducing a new global validation utility.
- Changing the standard for how error messages are displayed.