Files
klz-cables.com/components/forms/FormExamples.tsx
2025-12-29 18:18:48 +01:00

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;