diff --git a/admin-spa/src/components/MetaFields.tsx b/admin-spa/src/components/MetaFields.tsx new file mode 100644 index 0000000..b223950 --- /dev/null +++ b/admin-spa/src/components/MetaFields.tsx @@ -0,0 +1,157 @@ +import { Card, CardContent, 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 { Checkbox } from '@/components/ui/checkbox'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; + +export interface MetaField { + key: string; + label: string; + type: 'text' | 'textarea' | 'number' | 'select' | 'date' | 'checkbox'; + options?: Array<{ value: string; label: string }>; + section?: string; + description?: string; + placeholder?: string; +} + +interface MetaFieldsProps { + meta: Record; + fields: MetaField[]; + onChange: (key: string, value: any) => void; + readOnly?: boolean; +} + +/** + * MetaFields Component + * + * Generic component to display/edit custom meta fields from plugins. + * Part of Level 1 compatibility - allows plugins using standard WP/WooCommerce + * meta storage to have their fields displayed automatically. + * + * Zero coupling with specific plugins - renders any registered fields. + */ +export function MetaFields({ meta, fields, onChange, readOnly = false }: MetaFieldsProps) { + // Don't render if no fields registered + if (fields.length === 0) { + return null; + } + + // Group fields by section + const sections = fields.reduce((acc, field) => { + const section = field.section || 'Additional Fields'; + if (!acc[section]) acc[section] = []; + acc[section].push(field); + return acc; + }, {} as Record); + + return ( +
+ {Object.entries(sections).map(([section, sectionFields]) => ( + + + {section} + + + {sectionFields.map((field) => ( +
+ + + {field.type === 'text' && ( + onChange(field.key, e.target.value)} + disabled={readOnly} + placeholder={field.placeholder} + /> + )} + + {field.type === 'textarea' && ( +