363 lines
8.7 KiB
Markdown
363 lines
8.7 KiB
Markdown
# Reusable Form Components and Validation
|
|
|
|
This document describes the enhanced reusable form components and validation utilities implemented for the car maintenance management system.
|
|
|
|
## Overview
|
|
|
|
The system now includes a comprehensive set of reusable form components with RTL support, client-side and server-side validation, and enhanced data table functionality with Arabic text support.
|
|
|
|
## Components
|
|
|
|
### Form Input Components
|
|
|
|
#### Input Component (`app/components/ui/Input.tsx`)
|
|
Enhanced input component with RTL support, validation, and icons.
|
|
|
|
```tsx
|
|
import { Input } from '~/components/ui/Input';
|
|
|
|
<Input
|
|
label="اسم العميل"
|
|
placeholder="أدخل اسم العميل"
|
|
error={errors.name}
|
|
helperText="الاسم مطلوب"
|
|
startIcon={<UserIcon />}
|
|
required
|
|
/>
|
|
```
|
|
|
|
**Props:**
|
|
- `label`: Field label
|
|
- `error`: Error message to display
|
|
- `helperText`: Helper text below input
|
|
- `startIcon`/`endIcon`: Icons for input decoration
|
|
- `fullWidth`: Whether input takes full width (default: true)
|
|
- All standard HTML input props
|
|
|
|
#### Select Component (`app/components/ui/Select.tsx`)
|
|
Dropdown select component with RTL support and validation.
|
|
|
|
```tsx
|
|
import { Select } from '~/components/ui/Select';
|
|
|
|
<Select
|
|
label="نوع الوقود"
|
|
placeholder="اختر نوع الوقود"
|
|
options={[
|
|
{ value: 'gasoline', label: 'بنزين' },
|
|
{ value: 'diesel', label: 'ديزل' },
|
|
]}
|
|
error={errors.fuel}
|
|
/>
|
|
```
|
|
|
|
**Props:**
|
|
- `options`: Array of `{ value, label, disabled? }` objects
|
|
- `placeholder`: Placeholder text
|
|
- Other props same as Input component
|
|
|
|
#### Textarea Component (`app/components/ui/Textarea.tsx`)
|
|
Multi-line text input with RTL support.
|
|
|
|
```tsx
|
|
import { Textarea } from '~/components/ui/Textarea';
|
|
|
|
<Textarea
|
|
label="العنوان"
|
|
placeholder="أدخل العنوان"
|
|
rows={3}
|
|
resize="vertical"
|
|
error={errors.address}
|
|
/>
|
|
```
|
|
|
|
**Props:**
|
|
- `resize`: Resize behavior ('none', 'vertical', 'horizontal', 'both')
|
|
- `rows`: Number of visible rows
|
|
- Other props same as Input component
|
|
|
|
#### FormField Component (`app/components/ui/FormField.tsx`)
|
|
Wrapper component for consistent field styling and validation display.
|
|
|
|
```tsx
|
|
import { FormField } from '~/components/ui/FormField';
|
|
|
|
<FormField
|
|
label="اسم العميل"
|
|
required
|
|
error={errors.name}
|
|
helperText="أدخل الاسم الكامل"
|
|
>
|
|
<input type="text" name="name" />
|
|
</FormField>
|
|
```
|
|
|
|
### Form Layout Components
|
|
|
|
#### Form Component (`app/components/ui/Form.tsx`)
|
|
Main form wrapper with title, description, and error handling.
|
|
|
|
```tsx
|
|
import { Form, FormActions, FormSection, FormGrid } from '~/components/ui/Form';
|
|
|
|
<Form
|
|
title="إضافة عميل جديد"
|
|
description="أدخل بيانات العميل"
|
|
loading={isLoading}
|
|
error={generalError}
|
|
success={successMessage}
|
|
>
|
|
<FormSection title="المعلومات الأساسية">
|
|
<FormGrid columns={2}>
|
|
{/* Form fields */}
|
|
</FormGrid>
|
|
</FormSection>
|
|
|
|
<FormActions>
|
|
<Button variant="outline">إلغاء</Button>
|
|
<Button type="submit">حفظ</Button>
|
|
</FormActions>
|
|
</Form>
|
|
```
|
|
|
|
**Components:**
|
|
- `Form`: Main form wrapper
|
|
- `FormActions`: Action buttons container
|
|
- `FormSection`: Grouped form fields with title
|
|
- `FormGrid`: Responsive grid layout for fields
|
|
|
|
### Enhanced Data Table
|
|
|
|
#### DataTable Component (`app/components/ui/DataTable.tsx`)
|
|
Advanced data table with search, filtering, sorting, and pagination.
|
|
|
|
```tsx
|
|
import { DataTable } from '~/components/ui/DataTable';
|
|
|
|
<DataTable
|
|
data={customers}
|
|
columns={[
|
|
{
|
|
key: 'name',
|
|
header: 'الاسم',
|
|
sortable: true,
|
|
filterable: true,
|
|
render: (customer) => <strong>{customer.name}</strong>
|
|
},
|
|
{
|
|
key: 'phone',
|
|
header: 'الهاتف',
|
|
filterable: true,
|
|
filterType: 'text'
|
|
}
|
|
]}
|
|
searchable
|
|
searchPlaceholder="البحث في العملاء..."
|
|
filterable
|
|
pagination={{
|
|
enabled: true,
|
|
pageSize: 10,
|
|
currentPage: 1,
|
|
onPageChange: handlePageChange
|
|
}}
|
|
actions={{
|
|
label: 'الإجراءات',
|
|
render: (item) => (
|
|
<Button onClick={() => edit(item)}>تعديل</Button>
|
|
)
|
|
}}
|
|
/>
|
|
```
|
|
|
|
**Features:**
|
|
- Search across multiple fields
|
|
- Column-based filtering
|
|
- Sorting with Arabic text support
|
|
- Pagination
|
|
- Custom action buttons
|
|
- RTL layout support
|
|
- Loading and empty states
|
|
|
|
## Validation
|
|
|
|
### Server-Side Validation (`app/lib/form-validation.ts`)
|
|
|
|
Zod-based validation schemas with Arabic error messages.
|
|
|
|
```tsx
|
|
import { validateCustomerData } from '~/lib/form-validation';
|
|
|
|
const result = validateCustomerData(formData);
|
|
if (!result.success) {
|
|
return json({ errors: result.errors });
|
|
}
|
|
```
|
|
|
|
**Available Validators:**
|
|
- `validateUserData(data)`
|
|
- `validateCustomerData(data)`
|
|
- `validateVehicleData(data)`
|
|
- `validateMaintenanceVisitData(data)`
|
|
- `validateExpenseData(data)`
|
|
|
|
### Client-Side Validation Hook (`app/hooks/useFormValidation.ts`)
|
|
|
|
React hook for real-time form validation.
|
|
|
|
```tsx
|
|
import { useFormValidation } from '~/hooks/useFormValidation';
|
|
import { customerSchema } from '~/lib/form-validation';
|
|
|
|
const {
|
|
values,
|
|
errors,
|
|
isValid,
|
|
setValue,
|
|
getFieldProps,
|
|
validate
|
|
} = useFormValidation({
|
|
schema: customerSchema,
|
|
initialValues: { name: '', email: '' },
|
|
validateOnChange: true,
|
|
validateOnBlur: true
|
|
});
|
|
|
|
// Use with form fields
|
|
<Input {...getFieldProps('name')} />
|
|
```
|
|
|
|
### Validation Utilities (`app/lib/validation-utils.ts`)
|
|
|
|
Utility functions for field-level validation.
|
|
|
|
```tsx
|
|
import { validateField, validateEmail, PATTERNS } from '~/lib/validation-utils';
|
|
|
|
// Single field validation
|
|
const result = validateField(value, {
|
|
required: true,
|
|
minLength: 3,
|
|
email: true
|
|
});
|
|
|
|
// Specific validators
|
|
const emailResult = validateEmail('test@example.com');
|
|
const phoneResult = validatePhone('+966501234567');
|
|
|
|
// Pattern matching
|
|
const isValidEmail = PATTERNS.email.test(email);
|
|
```
|
|
|
|
## Table Utilities (`app/lib/table-utils.ts`)
|
|
|
|
Utilities for data processing with Arabic text support.
|
|
|
|
```tsx
|
|
import {
|
|
searchData,
|
|
filterData,
|
|
sortData,
|
|
processTableData
|
|
} from '~/lib/table-utils';
|
|
|
|
// Process table data with search, filter, sort, and pagination
|
|
const result = processTableData(
|
|
data,
|
|
{
|
|
search: 'محمد',
|
|
filters: { status: 'active' },
|
|
sort: { key: 'name', direction: 'asc' },
|
|
pagination: { page: 1, pageSize: 10 }
|
|
},
|
|
['name', 'email'] // searchable fields
|
|
);
|
|
```
|
|
|
|
## Example Forms
|
|
|
|
### Enhanced Customer Form (`app/components/forms/EnhancedCustomerForm.tsx`)
|
|
|
|
Complete example showing all components working together:
|
|
|
|
```tsx
|
|
import { EnhancedCustomerForm } from '~/components/forms/EnhancedCustomerForm';
|
|
|
|
<EnhancedCustomerForm
|
|
customer={customer}
|
|
onCancel={() => setShowForm(false)}
|
|
errors={actionData?.errors}
|
|
isLoading={navigation.state === 'submitting'}
|
|
onSubmit={(data) => submit(data, { method: 'post' })}
|
|
/>
|
|
```
|
|
|
|
### Enhanced Vehicle Form (`app/components/forms/EnhancedVehicleForm.tsx`)
|
|
|
|
Complex form with multiple sections and validation:
|
|
|
|
```tsx
|
|
import { EnhancedVehicleForm } from '~/components/forms/EnhancedVehicleForm';
|
|
|
|
<EnhancedVehicleForm
|
|
vehicle={vehicle}
|
|
customers={customers}
|
|
onCancel={() => setShowForm(false)}
|
|
errors={actionData?.errors}
|
|
isLoading={isSubmitting}
|
|
/>
|
|
```
|
|
|
|
## Features
|
|
|
|
### RTL Support
|
|
- All components support right-to-left layout
|
|
- Arabic text rendering and alignment
|
|
- Proper icon and element positioning
|
|
|
|
### Validation
|
|
- Client-side real-time validation
|
|
- Server-side validation with Zod schemas
|
|
- Arabic error messages
|
|
- Field-level and form-level validation
|
|
|
|
### Accessibility
|
|
- Proper ARIA labels and descriptions
|
|
- Keyboard navigation support
|
|
- Screen reader compatibility
|
|
- Focus management
|
|
|
|
### Performance
|
|
- Memoized components to prevent unnecessary re-renders
|
|
- Debounced search functionality
|
|
- Efficient data processing utilities
|
|
- Lazy loading for large datasets
|
|
|
|
## Usage Guidelines
|
|
|
|
1. **Always use FormField wrapper** for consistent styling and error display
|
|
2. **Implement both client and server validation** for security and UX
|
|
3. **Use the validation hook** for real-time feedback
|
|
4. **Leverage table utilities** for consistent data processing
|
|
5. **Follow RTL design patterns** for Arabic text and layout
|
|
6. **Test with Arabic content** to ensure proper rendering
|
|
|
|
## Migration from Old Components
|
|
|
|
To migrate existing forms to use the new components:
|
|
|
|
1. Replace basic inputs with the new Input/Select/Textarea components
|
|
2. Wrap fields with FormField for consistent styling
|
|
3. Add validation using the useFormValidation hook
|
|
4. Update data tables to use the enhanced DataTable component
|
|
5. Use Form layout components for better structure
|
|
|
|
## Testing
|
|
|
|
All components include comprehensive tests:
|
|
- `app/lib/__tests__/form-validation.test.ts`
|
|
- `app/lib/__tests__/validation-utils.test.ts`
|
|
|
|
Run tests with:
|
|
```bash
|
|
npm run test -- --run app/lib/__tests__/form-validation.test.ts
|
|
``` |