diff --git a/frontend/src/app/dev/forms/page.tsx b/frontend/src/app/dev/forms/page.tsx new file mode 100644 index 0000000..f450529 --- /dev/null +++ b/frontend/src/app/dev/forms/page.tsx @@ -0,0 +1,591 @@ +/** + * Form Patterns Demo + * Interactive demonstrations of form patterns with validation + * Access: /dev/forms + */ + +'use client'; + +import { useState } from 'react'; +import Link from 'next/link'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { z } from 'zod'; +import { ArrowLeft, CheckCircle2, Loader2 } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +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 { Checkbox } from '@/components/ui/checkbox'; +import { Badge } from '@/components/ui/badge'; +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; +import { Example, ExampleSection } from '@/components/dev/Example'; +import { BeforeAfter } from '@/components/dev/BeforeAfter'; + +// Example schemas +const loginSchema = z.object({ + email: z.string().email('Invalid email address'), + password: z.string().min(8, 'Password must be at least 8 characters'), +}); + +const contactSchema = z.object({ + name: z.string().min(1, 'Name is required'), + email: z.string().email('Invalid email address'), + message: z.string().min(10, 'Message must be at least 10 characters'), + category: z.string().min(1, 'Please select a category'), +}); + +type LoginForm = z.infer; +type ContactForm = z.infer; + +export default function FormsPage() { + const [isSubmitting, setIsSubmitting] = useState(false); + const [submitSuccess, setSubmitSuccess] = useState(false); + + // Login form + const { + register: registerLogin, + handleSubmit: handleSubmitLogin, + formState: { errors: errorsLogin }, + } = useForm({ + resolver: zodResolver(loginSchema), + }); + + // Contact form + const { + register: registerContact, + handleSubmit: handleSubmitContact, + formState: { errors: errorsContact }, + setValue: setValueContact, + } = useForm({ + resolver: zodResolver(contactSchema), + }); + + const onSubmitLogin = async (data: LoginForm) => { + setIsSubmitting(true); + setSubmitSuccess(false); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1500)); + console.log('Login form data:', data); + setIsSubmitting(false); + setSubmitSuccess(true); + }; + + const onSubmitContact = async (data: ContactForm) => { + setIsSubmitting(true); + setSubmitSuccess(false); + // Simulate API call + await new Promise((resolve) => setTimeout(resolve, 1500)); + console.log('Contact form data:', data); + setIsSubmitting(false); + setSubmitSuccess(true); + }; + + return ( +
+ {/* Header */} +
+
+ + + +
+

Form Patterns

+

+ react-hook-form + Zod validation examples +

+
+
+
+ + {/* Content */} +
+
+ {/* Introduction */} +
+

+ Complete form implementations using react-hook-form for state management + and Zod for validation. Includes error handling, loading states, and + accessibility features. +

+
+ react-hook-form + Zod + Validation + ARIA +
+
+ + {/* Basic Form */} + + +
+ + + {errors.email && ( +

+ {errors.email.message} +

+ )} +
+ +`} + > +
+
+ {/* Email */} +
+ + + {errorsLogin.email && ( + + )} +
+ + {/* Password */} +
+ + + {errorsLogin.password && ( + + )} +
+ + {/* Submit */} + + + {/* Success Message */} + {submitSuccess && ( + + + Success! + Form submitted successfully. + + )} +
+
+
+
+ + {/* Complete Form */} + + + {/* Input field */} +
+ + + {errors.name &&

{errors.name.message}

} +
+ + {/* Textarea field */} +
+ +