Kairo-Jinkendo/frontend/src/components/FieldRenderer.jsx

130 lines
3.2 KiB
React
Raw Normal View History

export function FieldRenderer({ definitions, values, onChange, disabled = false, actors = [] }) {
if (!definitions?.length) {
return null
}
return (
<fieldset className="field-renderer">
<legend className="field-renderer__legend">Zusatzfelder (Archetyp)</legend>
{definitions.map((def) => (
<DynamicField
key={def.field_key}
definition={def}
value={values?.[def.field_key]}
onChange={(next) => onChange(def.field_key, next)}
disabled={disabled}
actors={actors}
/>
))}
</fieldset>
)
}
function DynamicField({ definition, value, onChange, disabled, actors = [] }) {
const { field_key, field_type, label, required, validation_json: validation } = definition
const inputId = `field-${field_key}`
if (field_type === 'longtext') {
return (
<label htmlFor={inputId}>
{label}
{required && ' *'}
<textarea
id={inputId}
name={field_key}
rows={4}
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
required={required}
disabled={disabled}
/>
</label>
)
}
if (field_type === 'boolean') {
return (
<label className="checkbox-label" htmlFor={inputId}>
<input
id={inputId}
name={field_key}
type="checkbox"
checked={Boolean(value)}
onChange={(e) => onChange(e.target.checked)}
disabled={disabled}
/>
{label}
{required && ' *'}
</label>
)
}
if (field_type === 'enum') {
const options = validation?.options || []
return (
<label htmlFor={inputId}>
{label}
{required && ' *'}
<select
id={inputId}
name={field_key}
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
required={required}
disabled={disabled}
>
<option value="">—</option>
{options.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
</label>
)
}
if (field_type === 'actor_ref') {
return (
<label htmlFor={inputId}>
{label}
{required && ' *'}
<select
id={inputId}
name={field_key}
value={value ?? ''}
onChange={(e) => onChange(e.target.value || null)}
required={required}
disabled={disabled}
>
<option value="">—</option>
{actors.map((actor) => (
<option key={actor.id} value={actor.id}>
{actor.name}
</option>
))}
</select>
</label>
)
}
const inputType =
field_type === 'number' ? 'number' : field_type === 'date' ? 'date' : field_type === 'url' ? 'url' : 'text'
return (
<label htmlFor={inputId}>
{label}
{required && ' *'}
<input
id={inputId}
name={field_key}
type={inputType}
value={value ?? ''}
onChange={(e) => onChange(field_type === 'number' ? e.target.value : e.target.value)}
required={required}
disabled={disabled}
/>
</label>
)
}