import * as React from 'react'; import { TextField, FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox, Typography, Box, Divider, } from '@mui/material'; import { ResourceField } from '../../types/config'; import { getFieldOptions } from '../../utils/options'; import ImageUploadField from './ImageUploadField'; interface FormFieldProps { name: string; field: ResourceField; value: any; onChange: (val: any) => void; disabled?: boolean; uploadFile: (file: File) => Promise; uploading: boolean; baseUrl: string; relationDataMap?: Record; // Map of relation name to data array } export default function FormField({ name, field, value, onChange, disabled, uploadFile, uploading, baseUrl, relationDataMap = {}, }: FormFieldProps) { const label = field.label; // 1. Recursive Rendering for Objects (Not Relations) if (field.type === 'object' && field.schema && !field.relation) { return ( {label} {Object.entries(field.schema).map(([subKey, subField]) => ( { const updated = { ...(value || {}), [subKey]: newVal }; onChange(updated); }} disabled={disabled} uploadFile={uploadFile} uploading={uploading} baseUrl={baseUrl} relationDataMap={relationDataMap} /> ))} ); } // 2. Relation Handling (Select / Multi-Select) if (field.relation && relationDataMap[field.relation]) { const relationData = relationDataMap[field.relation].data; const isArrayRelation = field.type === 'array'; const options = getFieldOptions(field, relationData); const keyField = field.enumOption?.key ?? 'id'; // Normalize value: API returns whole objects on GET, but form uses key strings const normalizedValue = (() => { if (isArrayRelation && Array.isArray(value)) { return value.map((v: any) => (v != null && typeof v === 'object' ? String(v[keyField] ?? '') : String(v))); } if (value != null && typeof value === 'object') { return String(value[keyField] ?? ''); } return value ?? (isArrayRelation ? [] : ""); })(); return ( {label} ); } // 3. Image Handling if (field.type === 'image') { return ( { const url = await uploadFile(file); if (url) onChange(url); }} uploading={uploading} baseUrl={baseUrl} disabled={disabled} /> ); } // 4. Boolean Handling if (field.type === 'boolean') { return ( onChange(e.target.checked)} disabled={disabled} /> } label={label} /> ); } // 5. Enum Handling if (field.type === 'enum' && field.options) { const options = getFieldOptions(field); return ( {label} ); } // 6. Common Text Fields if (field.type === 'datetime' || field.type === 'date') { return ( onChange(e.target.value)} disabled={disabled} required={field.required} /> ); } if (field.type === 'markdown' || field.type === 'string') { return ( onChange(e.target.value)} disabled={disabled} required={field.required} /> ); } if (field.type === 'number') { return ( onChange(e.target.value === '' ? '' : Number(e.target.value))} disabled={disabled} required={field.required} /> ); } return ( ); }