795 lines
26 KiB
TypeScript
795 lines
26 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
FormField,
|
|
useForm,
|
|
useFormWithHelpers,
|
|
type ValidationRules
|
|
} from './index';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { Card, CardBody, CardHeader } from '@/components/ui/Card';
|
|
import { Container } from '@/components/ui/Container';
|
|
|
|
/**
|
|
* Form Examples
|
|
* Comprehensive examples showing all form patterns and usage
|
|
*/
|
|
|
|
// Example 1: Simple Contact Form
|
|
export const ContactFormExample: React.FC = () => {
|
|
const form = useForm({
|
|
initialValues: {
|
|
name: '',
|
|
email: '',
|
|
message: '',
|
|
},
|
|
validationRules: {
|
|
name: { required: 'Name is required', minLength: { value: 2, message: 'Name must be at least 2 characters' } },
|
|
email: { required: 'Email is required', email: true },
|
|
message: { required: 'Message is required', minLength: { value: 10, message: 'Message must be at least 10 characters' } },
|
|
},
|
|
onSubmit: async (values) => {
|
|
console.log('Form submitted:', values);
|
|
// Simulate API call
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
alert('Form submitted successfully!');
|
|
form.reset();
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">Contact Form</h3>
|
|
<p className="text-sm text-text-secondary">Simple contact form with validation</p>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<form {...form.getFormProps()} className="space-y-4">
|
|
<FormField
|
|
type="text"
|
|
name="name"
|
|
label="Full Name"
|
|
placeholder="Enter your name"
|
|
required
|
|
value={form.values.name}
|
|
error={form.errors.name?.[0]}
|
|
touched={form.touched.name}
|
|
onChange={(e) => form.setFieldValue('name', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="email"
|
|
name="email"
|
|
label="Email Address"
|
|
placeholder="your@email.com"
|
|
required
|
|
value={form.values.email}
|
|
error={form.errors.email?.[0]}
|
|
touched={form.touched.email}
|
|
onChange={(e) => form.setFieldValue('email', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="textarea"
|
|
name="message"
|
|
label="Message"
|
|
placeholder="How can we help you?"
|
|
required
|
|
rows={5}
|
|
showCharCount
|
|
maxLength={500}
|
|
value={form.values.message}
|
|
error={form.errors.message?.[0]}
|
|
touched={form.touched.message}
|
|
onChange={(e) => form.setFieldValue('message', e.target.value)}
|
|
/>
|
|
|
|
<div className="flex gap-2">
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={form.isSubmitting || !form.isValid}
|
|
loading={form.isSubmitting}
|
|
>
|
|
Send Message
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={form.reset}
|
|
disabled={form.isSubmitting}
|
|
>
|
|
Reset
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardBody>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
// Example 2: Registration Form with Multiple Field Types
|
|
export const RegistrationFormExample: React.FC = () => {
|
|
const form = useForm({
|
|
initialValues: {
|
|
firstName: '',
|
|
lastName: '',
|
|
email: '',
|
|
password: '',
|
|
confirmPassword: '',
|
|
country: '',
|
|
interests: [] as string[],
|
|
newsletter: false,
|
|
terms: false,
|
|
},
|
|
validationRules: {
|
|
firstName: { required: true, minLength: { value: 2, message: 'Too short' } },
|
|
lastName: { required: true, minLength: { value: 2, message: 'Too short' } },
|
|
email: { required: true, email: true },
|
|
password: {
|
|
required: true,
|
|
minLength: { value: 8, message: 'Password must be at least 8 characters' },
|
|
pattern: { value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, message: 'Must contain uppercase, lowercase, and number' }
|
|
},
|
|
confirmPassword: {
|
|
required: true,
|
|
custom: (value) => value === form.values.password ? null : 'Passwords do not match'
|
|
},
|
|
country: { required: 'Please select your country' },
|
|
interests: { required: 'Select at least one interest' },
|
|
newsletter: {},
|
|
terms: {
|
|
required: 'You must accept the terms',
|
|
custom: (value) => value ? null : 'You must accept the terms'
|
|
},
|
|
},
|
|
onSubmit: async (values) => {
|
|
console.log('Registration:', values);
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
alert('Registration successful!');
|
|
form.reset();
|
|
},
|
|
});
|
|
|
|
const countryOptions = [
|
|
{ value: 'de', label: 'Germany' },
|
|
{ value: 'us', label: 'United States' },
|
|
{ value: 'uk', label: 'United Kingdom' },
|
|
{ value: 'fr', label: 'France' },
|
|
];
|
|
|
|
const interestOptions = [
|
|
{ value: 'technology', label: 'Technology' },
|
|
{ value: 'business', label: 'Business' },
|
|
{ value: 'innovation', label: 'Innovation' },
|
|
{ value: 'sustainability', label: 'Sustainability' },
|
|
];
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">Registration Form</h3>
|
|
<p className="text-sm text-text-secondary">Complete registration with multiple field types</p>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<form {...form.getFormProps()} className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<FormField
|
|
type="text"
|
|
name="firstName"
|
|
label="First Name"
|
|
required
|
|
value={form.values.firstName}
|
|
error={form.errors.firstName?.[0]}
|
|
onChange={(e) => form.setFieldValue('firstName', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="text"
|
|
name="lastName"
|
|
label="Last Name"
|
|
required
|
|
value={form.values.lastName}
|
|
error={form.errors.lastName?.[0]}
|
|
onChange={(e) => form.setFieldValue('lastName', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<FormField
|
|
type="email"
|
|
name="email"
|
|
label="Email Address"
|
|
required
|
|
value={form.values.email}
|
|
error={form.errors.email?.[0]}
|
|
onChange={(e) => form.setFieldValue('email', e.target.value)}
|
|
/>
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<FormField
|
|
type="password"
|
|
name="password"
|
|
label="Password"
|
|
required
|
|
helpText="Min 8 chars with uppercase, lowercase, and number"
|
|
value={form.values.password}
|
|
error={form.errors.password?.[0]}
|
|
onChange={(e) => form.setFieldValue('password', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="password"
|
|
name="confirmPassword"
|
|
label="Confirm Password"
|
|
required
|
|
value={form.values.confirmPassword}
|
|
error={form.errors.confirmPassword?.[0]}
|
|
onChange={(e) => form.setFieldValue('confirmPassword', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<FormField
|
|
type="select"
|
|
name="country"
|
|
label="Country"
|
|
required
|
|
options={countryOptions}
|
|
value={form.values.country}
|
|
error={form.errors.country?.[0]}
|
|
onChange={(e) => form.setFieldValue('country', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="checkbox"
|
|
name="interests"
|
|
label="Areas of Interest"
|
|
required
|
|
options={interestOptions}
|
|
value={form.values.interests}
|
|
error={form.errors.interests?.[0]}
|
|
onChange={(values) => form.setFieldValue('interests', values)}
|
|
/>
|
|
|
|
<div className="space-y-2">
|
|
<FormField
|
|
type="checkbox"
|
|
name="newsletter"
|
|
label="Subscribe to newsletter"
|
|
checked={form.values.newsletter}
|
|
onChange={(values) => form.setFieldValue('newsletter', values.length > 0)}
|
|
/>
|
|
|
|
<FormField
|
|
type="checkbox"
|
|
name="terms"
|
|
label="I accept the terms and conditions"
|
|
required
|
|
checked={form.values.terms}
|
|
error={form.errors.terms?.[0]}
|
|
onChange={(values) => form.setFieldValue('terms', values.length > 0)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-2 pt-4 border-t border-neutral-dark">
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={form.isSubmitting || !form.isValid}
|
|
loading={form.isSubmitting}
|
|
>
|
|
Register
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
onClick={form.reset}
|
|
disabled={form.isSubmitting}
|
|
>
|
|
Clear
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardBody>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
// Example 3: Search and Filter Form
|
|
export const SearchFormExample: React.FC = () => {
|
|
const form = useForm({
|
|
initialValues: {
|
|
search: '',
|
|
category: '',
|
|
status: '',
|
|
sortBy: 'name',
|
|
},
|
|
validationRules: {
|
|
search: {},
|
|
category: {},
|
|
status: {},
|
|
sortBy: {},
|
|
},
|
|
onSubmit: async (values) => {
|
|
console.log('Search filters:', values);
|
|
// Handle search/filter logic
|
|
},
|
|
});
|
|
|
|
const categoryOptions = [
|
|
{ value: '', label: 'All Categories' },
|
|
{ value: 'cables', label: 'Cables' },
|
|
{ value: 'connectors', label: 'Connectors' },
|
|
{ value: 'accessories', label: 'Accessories' },
|
|
];
|
|
|
|
const statusOptions = [
|
|
{ value: '', label: 'All Status' },
|
|
{ value: 'active', label: 'Active' },
|
|
{ value: 'inactive', label: 'Inactive' },
|
|
];
|
|
|
|
const sortOptions = [
|
|
{ value: 'name', label: 'Name (A-Z)' },
|
|
{ value: 'name-desc', label: 'Name (Z-A)' },
|
|
{ value: 'date', label: 'Date (Newest)' },
|
|
{ value: 'date-asc', label: 'Date (Oldest)' },
|
|
];
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">Search & Filter</h3>
|
|
<p className="text-sm text-text-secondary">Advanced search with multiple filters</p>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<form {...form.getFormProps()} className="space-y-4">
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<FormField
|
|
type="text"
|
|
name="search"
|
|
label="Search"
|
|
placeholder="Search products..."
|
|
prefix={
|
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
</svg>
|
|
}
|
|
showClear
|
|
value={form.values.search}
|
|
onChange={(e) => form.setFieldValue('search', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="select"
|
|
name="category"
|
|
label="Category"
|
|
options={categoryOptions}
|
|
value={form.values.category}
|
|
onChange={(e) => form.setFieldValue('category', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="select"
|
|
name="status"
|
|
label="Status"
|
|
options={statusOptions}
|
|
value={form.values.status}
|
|
onChange={(e) => form.setFieldValue('status', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-2 items-center justify-between">
|
|
<FormField
|
|
type="select"
|
|
name="sortBy"
|
|
label="Sort By"
|
|
options={sortOptions}
|
|
value={form.values.sortBy}
|
|
onChange={(e) => form.setFieldValue('sortBy', e.target.value)}
|
|
containerClassName="w-48"
|
|
/>
|
|
|
|
<div className="flex gap-2">
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
size="sm"
|
|
>
|
|
Apply Filters
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={form.reset}
|
|
>
|
|
Reset
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</CardBody>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
// Example 4: Radio Button Form
|
|
export const RadioFormExample: React.FC = () => {
|
|
const form = useForm({
|
|
initialValues: {
|
|
paymentMethod: '',
|
|
shippingMethod: '',
|
|
deliveryTime: '',
|
|
},
|
|
validationRules: {
|
|
paymentMethod: { required: 'Please select a payment method' },
|
|
shippingMethod: { required: 'Please select a shipping method' },
|
|
deliveryTime: { required: 'Please select preferred delivery time' },
|
|
},
|
|
onSubmit: async (values) => {
|
|
console.log('Selections:', values);
|
|
await new Promise(resolve => setTimeout(resolve, 800));
|
|
alert('Preferences saved!');
|
|
},
|
|
});
|
|
|
|
const paymentOptions = [
|
|
{ value: 'credit-card', label: 'Credit Card', description: 'Visa, Mastercard, Amex' },
|
|
{ value: 'paypal', label: 'PayPal', description: 'Secure payment via PayPal' },
|
|
{ value: 'bank-transfer', label: 'Bank Transfer', description: 'Direct bank transfer' },
|
|
];
|
|
|
|
const shippingOptions = [
|
|
{ value: 'standard', label: 'Standard (5-7 days)', description: 'Free shipping on orders over €50' },
|
|
{ value: 'express', label: 'Express (2-3 days)', description: '€9.99 shipping fee' },
|
|
{ value: 'overnight', label: 'Overnight', description: '€24.99 shipping fee' },
|
|
];
|
|
|
|
const deliveryOptions = [
|
|
{ value: 'morning', label: 'Morning (8am-12pm)' },
|
|
{ value: 'afternoon', label: 'Afternoon (12pm-6pm)' },
|
|
{ value: 'evening', label: 'Evening (6pm-9pm)' },
|
|
];
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">Preferences Selection</h3>
|
|
<p className="text-sm text-text-secondary">Radio buttons for single choice selection</p>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<form {...form.getFormProps()} className="space-y-6">
|
|
<FormField
|
|
type="radio"
|
|
name="paymentMethod"
|
|
label="Payment Method"
|
|
required
|
|
options={paymentOptions}
|
|
value={form.values.paymentMethod}
|
|
error={form.errors.paymentMethod?.[0]}
|
|
onChange={(value) => form.setFieldValue('paymentMethod', value)}
|
|
layout="vertical"
|
|
/>
|
|
|
|
<FormField
|
|
type="radio"
|
|
name="shippingMethod"
|
|
label="Shipping Method"
|
|
required
|
|
options={shippingOptions}
|
|
value={form.values.shippingMethod}
|
|
error={form.errors.shippingMethod?.[0]}
|
|
onChange={(value) => form.setFieldValue('shippingMethod', value)}
|
|
layout="vertical"
|
|
/>
|
|
|
|
<FormField
|
|
type="radio"
|
|
name="deliveryTime"
|
|
label="Preferred Delivery Time"
|
|
required
|
|
options={deliveryOptions}
|
|
value={form.values.deliveryTime}
|
|
error={form.errors.deliveryTime?.[0]}
|
|
onChange={(value) => form.setFieldValue('deliveryTime', value)}
|
|
layout="horizontal"
|
|
/>
|
|
|
|
<div className="flex gap-2 pt-4 border-t border-neutral-dark">
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={form.isSubmitting || !form.isValid}
|
|
loading={form.isSubmitting}
|
|
>
|
|
Save Preferences
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
onClick={form.reset}
|
|
>
|
|
Reset
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardBody>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
// Example 5: Complete Form with All Features
|
|
export const CompleteFormExample: React.FC = () => {
|
|
const [submittedData, setSubmittedData] = useState<any>(null);
|
|
|
|
const form = useForm({
|
|
initialValues: {
|
|
// Text inputs
|
|
fullName: '',
|
|
phone: '',
|
|
website: '',
|
|
|
|
// Textarea
|
|
description: '',
|
|
|
|
// Select
|
|
industry: '',
|
|
budget: '',
|
|
|
|
// Checkbox group
|
|
services: [] as string[],
|
|
|
|
// Radio
|
|
contactPreference: '',
|
|
|
|
// Single checkbox
|
|
agreeToTerms: false,
|
|
},
|
|
validationRules: {
|
|
fullName: { required: true, minLength: { value: 3, message: 'Minimum 3 characters' } },
|
|
phone: { required: true, pattern: { value: /^[0-9+\-\s()]+$/, message: 'Invalid phone format' } },
|
|
website: { url: 'Invalid URL format' },
|
|
description: { required: true, minLength: { value: 20, message: 'Please provide more details' } },
|
|
industry: { required: true },
|
|
budget: { required: true },
|
|
services: { required: 'Select at least one service' },
|
|
contactPreference: { required: true },
|
|
agreeToTerms: {
|
|
required: 'You must accept the terms',
|
|
custom: (value) => value ? null : 'Required'
|
|
},
|
|
},
|
|
onSubmit: async (values) => {
|
|
console.log('Complete form submitted:', values);
|
|
setSubmittedData(values);
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
alert('Form submitted successfully! Check console for data.');
|
|
form.reset();
|
|
},
|
|
});
|
|
|
|
const industryOptions = [
|
|
{ value: '', label: 'Select Industry' },
|
|
{ value: 'manufacturing', label: 'Manufacturing' },
|
|
{ value: 'construction', label: 'Construction' },
|
|
{ value: 'energy', label: 'Energy' },
|
|
{ value: 'technology', label: 'Technology' },
|
|
];
|
|
|
|
const budgetOptions = [
|
|
{ value: '', label: 'Select Budget Range' },
|
|
{ value: 'small', label: '€1,000 - €5,000' },
|
|
{ value: 'medium', label: '€5,000 - €20,000' },
|
|
{ value: 'large', label: '€20,000+' },
|
|
];
|
|
|
|
const serviceOptions = [
|
|
{ value: 'consulting', label: 'Consulting' },
|
|
{ value: 'installation', label: 'Installation' },
|
|
{ value: 'maintenance', label: 'Maintenance' },
|
|
{ value: 'training', label: 'Training' },
|
|
{ value: 'support', label: '24/7 Support' },
|
|
];
|
|
|
|
const contactOptions = [
|
|
{ value: 'email', label: 'Email', description: 'We\'ll respond within 24 hours' },
|
|
{ value: 'phone', label: 'Phone', description: 'Call us during business hours' },
|
|
{ value: 'both', label: 'Both', description: 'Email and phone contact' },
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<Card>
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">Complete Form Example</h3>
|
|
<p className="text-sm text-text-secondary">All form components working together</p>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<form {...form.getFormProps()} className="space-y-6">
|
|
{/* Personal Information */}
|
|
<div className="space-y-4">
|
|
<h4 className="font-semibold text-lg">Personal Information</h4>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<FormField
|
|
type="text"
|
|
name="fullName"
|
|
label="Full Name"
|
|
required
|
|
placeholder="John Doe"
|
|
value={form.values.fullName}
|
|
error={form.errors.fullName?.[0]}
|
|
onChange={(e) => form.setFieldValue('fullName', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="tel"
|
|
name="phone"
|
|
label="Phone Number"
|
|
required
|
|
placeholder="+1 234 567 8900"
|
|
value={form.values.phone}
|
|
error={form.errors.phone?.[0]}
|
|
onChange={(e) => form.setFieldValue('phone', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<FormField
|
|
type="url"
|
|
name="website"
|
|
label="Website (Optional)"
|
|
placeholder="https://example.com"
|
|
showClear
|
|
value={form.values.website}
|
|
error={form.errors.website?.[0]}
|
|
onChange={(e) => form.setFieldValue('website', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Business Information */}
|
|
<div className="space-y-4 pt-4 border-t border-neutral-dark">
|
|
<h4 className="font-semibold text-lg">Business Information</h4>
|
|
|
|
<FormField
|
|
type="textarea"
|
|
name="description"
|
|
label="Project Description"
|
|
required
|
|
rows={5}
|
|
showCharCount
|
|
maxLength={500}
|
|
placeholder="Describe your project requirements..."
|
|
value={form.values.description}
|
|
error={form.errors.description?.[0]}
|
|
onChange={(e) => form.setFieldValue('description', e.target.value)}
|
|
/>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<FormField
|
|
type="select"
|
|
name="industry"
|
|
label="Industry"
|
|
required
|
|
options={industryOptions}
|
|
value={form.values.industry}
|
|
error={form.errors.industry?.[0]}
|
|
onChange={(e) => form.setFieldValue('industry', e.target.value)}
|
|
/>
|
|
|
|
<FormField
|
|
type="select"
|
|
name="budget"
|
|
label="Budget Range"
|
|
required
|
|
options={budgetOptions}
|
|
value={form.values.budget}
|
|
error={form.errors.budget?.[0]}
|
|
onChange={(e) => form.setFieldValue('budget', e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Services & Preferences */}
|
|
<div className="space-y-4 pt-4 border-t border-neutral-dark">
|
|
<h4 className="font-semibold text-lg">Services & Preferences</h4>
|
|
|
|
<FormField
|
|
type="checkbox"
|
|
name="services"
|
|
label="Required Services"
|
|
required
|
|
options={serviceOptions}
|
|
value={form.values.services}
|
|
error={form.errors.services?.[0]}
|
|
onChange={(values) => form.setFieldValue('services', values)}
|
|
/>
|
|
|
|
<FormField
|
|
type="radio"
|
|
name="contactPreference"
|
|
label="Preferred Contact Method"
|
|
required
|
|
options={contactOptions}
|
|
value={form.values.contactPreference}
|
|
error={form.errors.contactPreference?.[0]}
|
|
onChange={(value) => form.setFieldValue('contactPreference', value)}
|
|
layout="vertical"
|
|
/>
|
|
</div>
|
|
|
|
{/* Terms */}
|
|
<div className="space-y-4 pt-4 border-t border-neutral-dark">
|
|
<FormField
|
|
type="checkbox"
|
|
name="agreeToTerms"
|
|
label="I agree to the terms and conditions and privacy policy"
|
|
required
|
|
checked={form.values.agreeToTerms}
|
|
error={form.errors.agreeToTerms?.[0]}
|
|
onChange={(values) => form.setFieldValue('agreeToTerms', values.length > 0)}
|
|
/>
|
|
</div>
|
|
|
|
{/* Actions */}
|
|
<div className="flex gap-2 pt-4 border-t border-neutral-dark">
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={form.isSubmitting || !form.isValid}
|
|
loading={form.isSubmitting}
|
|
>
|
|
Submit Application
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={form.reset}
|
|
disabled={form.isSubmitting}
|
|
>
|
|
Reset Form
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</CardBody>
|
|
</Card>
|
|
|
|
{/* Debug Output */}
|
|
{submittedData && (
|
|
<Card>
|
|
<CardHeader>
|
|
<h4 className="font-semibold">Submitted Data</h4>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<pre className="bg-neutral-dark p-4 rounded-md overflow-x-auto text-sm">
|
|
{JSON.stringify(submittedData, null, 2)}
|
|
</pre>
|
|
</CardBody>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Main Examples Page Component
|
|
export const FormExamplesPage: React.FC = () => {
|
|
return (
|
|
<Container className="py-8">
|
|
<div className="space-y-8">
|
|
<div className="text-center space-y-2">
|
|
<h1 className="text-4xl font-bold">Form System Examples</h1>
|
|
<p className="text-lg text-text-secondary">
|
|
Comprehensive examples of all form components and patterns
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-8">
|
|
<ContactFormExample />
|
|
<RegistrationFormExample />
|
|
<SearchFormExample />
|
|
<RadioFormExample />
|
|
<CompleteFormExample />
|
|
</div>
|
|
</div>
|
|
</Container>
|
|
);
|
|
};
|
|
|
|
export default FormExamplesPage; |