68 lines
2.5 KiB
TypeScript
68 lines
2.5 KiB
TypeScript
import { FormControl, InputLabel, Select, MenuItem } from '@mui/material';
|
||
import { getFieldOptions } from '../../utils/options';
|
||
import { FieldComponentProps } from '../../types/overrides';
|
||
|
||
export default function RelationField({ field, value, onChange, disabled, relationDataMap = {} }: FieldComponentProps) {
|
||
// console.log('RelationField render', field.label, 'enumOption:', field.enumOption, 'value prop:', value);
|
||
const relationName = field.relation ?? (field as any).refers;
|
||
if (!relationName || !relationDataMap[relationName]) {
|
||
throw new Error(`Relation data for "${relationName}" is missing – cannot render options for field "${field.label}"`);
|
||
}
|
||
|
||
|
||
const relationData = relationDataMap[relationName];
|
||
const isArrayRelation = field.type === 'array';
|
||
const options = getFieldOptions(field, relationData);
|
||
// console.log('Options for', field.label, 'keys:', options.map(o=>o.key));
|
||
if (options.length === 0) {
|
||
throw new Error(`No selectable options available for field "${field.label}" (relation "${relationName}")`);
|
||
}
|
||
const keyField = field.enumOption?.key ?? 'id';
|
||
|
||
|
||
const normalizedValue = (() => {
|
||
if (isArrayRelation && Array.isArray(value)) {
|
||
return value.map((v: any) => {
|
||
if (v != null && typeof v === 'object') {
|
||
return String(v[keyField] ?? '');
|
||
}
|
||
return String(v);
|
||
});
|
||
}
|
||
if (value != null && typeof value === 'object') {
|
||
return String(value[keyField] ?? '');
|
||
}
|
||
// Primitive (number/string) – coerce to string for Select compatibility
|
||
return value != null ? String(value) : (isArrayRelation ? [] : "");
|
||
})();
|
||
|
||
return (
|
||
<FormControl fullWidth>
|
||
<InputLabel shrink>{field.label}</InputLabel>
|
||
<Select
|
||
multiple={isArrayRelation}
|
||
value={normalizedValue}
|
||
label={field.label}
|
||
displayEmpty
|
||
onChange={(e) => onChange(e.target.value)}
|
||
disabled={disabled}
|
||
renderValue={(selected: any) => {
|
||
// console.log('Select renderValue for', field.label, 'selected:', selected);
|
||
if (isArrayRelation) {
|
||
return (selected as string[]).map(k => options.find(o => o.key === k)?.value ?? k).join(', ');
|
||
}
|
||
const display = options.find(o => o.key === selected)?.value ?? selected;
|
||
// console.log('Display value for', field.label, ':', display);
|
||
return display;
|
||
}}
|
||
>
|
||
{options.map((opt) => (
|
||
<MenuItem key={opt.key} value={opt.key}>
|
||
{opt.value}
|
||
</MenuItem>
|
||
))}
|
||
</Select>
|
||
</FormControl>
|
||
);
|
||
}
|