import { Field, SelectInput, TextArea, TextInput } from '../ui' /** * Renders one Zino activity field per builder definition, matching its * data_type. Field order, labels and select options come straight from the * builder, so the form always mirrors the activity. * * Computed fields (id_gen) are skipped — the builder's Fields tab does not * list them and the workflow fills them in. */ export default function ActivityFields({ fields, values, errors = {}, onChange, disabled }) { return fields.filter((f) => !f.computed).map((field) => { const value = values[field.id] ?? '' const set = (v) => onChange(field.id, v) const isWide = field.type === 'longtext' || field.type === 'image' return ( {(id) => renderControl(field, id, value, set, disabled)} ) }) } function hintFor(field) { switch (field.type) { case 'geolocation': return 'Latitude, longitude' case 'image': if (field.slots?.length) return `One photo per view, each up to ${field.maxSizeMb || 5} MB.` return field.maxSizeMb ? `Image up to ${field.maxSizeMb} MB.` : 'Image' case 'select': return field.options?.length ? undefined : 'No options configured in the builder.' default: return undefined } } function renderControl(field, id, value, set, disabled) { const common = { id, disabled } switch (field.type) { case 'select': return ( set(e.target.value)} options={field.options || []} placeholder={field.options?.length ? `Select ${field.label.trim()}` : 'No options'} disabled={disabled || !field.options?.length} /> ) case 'longtext': return