import type { Field, NameSubField, AddressSubField } from '@/types/field' function safeParse(json: string | null | undefined): Record { if (!json) return {} try { return JSON.parse(json) as Record } catch { return {} } } export function normalizeFieldsForBuilder(apiFields: Field[]): Field[] { if (!Array.isArray(apiFields) || apiFields.length === 0) return [] const parents: Field[] = [] const childrenByParent: Record = {} for (const f of apiFields) { if (f.parentId && typeof f.parentId === 'number' && f.parentId > 0) { if (!childrenByParent[f.parentId]) childrenByParent[f.parentId] = [] childrenByParent[f.parentId].push(f) } else { parents.push(f) } } return parents.map((parent) => { if (parent.type === 'name') { const children = childrenByParent[parent.id] ?? [] const nameFields: NameSubField[] = children.map((child) => { const s = safeParse((child as Field & { settings?: string }).settings) const label = (child as Partial).label ?? String(s['label'] ?? '') return { type: 'text', id: String(child.id ?? ''), modelValue: (child as Partial).defaultValue ?? '', label, required: !!(child as Partial).required || Boolean(s['required']), optionHide: !!(child as Partial).hideLabel || Boolean(s['hideLabel']), description: String((child as Partial).description ?? s['description'] ?? ''), placeholder: String((child as Partial).placeholder ?? s['placeholder'] ?? ''), } }) const nameFieldTypes = nameFields.map((_, idx) => `nameField${idx + 1}`) return { ...parent, nameFields, nameFieldTypes, } as Field } if (parent.type === 'address') { const children = childrenByParent[parent.id] ?? [] const defaultAddressOrder = [ 'streetAddress', 'addressLine2', 'city', 'state', 'zip', 'country', ] const addressFields: AddressSubField[] = children.map((child, idx) => { const s = safeParse((child as Field & { settings?: string }).settings) const explicitType = (child as Partial).addressType || String(s['type'] ?? '') const type = explicitType && explicitType.trim() !== '' ? explicitType : (defaultAddressOrder[idx] ?? `addressPart${idx + 1}`) return { type, id: String(child.id ?? ''), label: (child as Partial).label ?? String(s['label'] ?? ''), value: (child as Partial).defaultValue ?? String(s['value'] ?? ''), placeholder: (child as Partial).placeholder ?? String(s['placeholder'] ?? ''), required: !!(child as Partial).required || Boolean(s['required']), hideLabel: !!(child as Partial).hideLabel || Boolean(s['hideLabel']), description: String((child as Partial).description ?? s['description'] ?? ''), requiredMessage: String( (child as Partial).requiredMessage ?? s['requiredMessage'] ?? '', ), visible: !!(child as Partial).visible || Boolean(s['visible'] ?? true), } }) const addressFieldTypes = addressFields.map((af) => af.type) return { ...parent, addressFields, addressFieldTypes, } as Field } // Regular field return { ...parent, } }) } export function denormalizeFieldsForApi(fields: Field[]): Field[] { const result: Field[] = [] for (const field of fields) { if (field.type === 'name') { if (Array.isArray(field.nameFields)) { const { nameFields, ...parentRest } = field result.push({ ...parentRest, type: 'name' } as Field) nameFields.forEach((sub, idx) => { result.push({ id: sub.id ? parseInt(sub.id, 10) || 0 : 0, formId: field.formId, fieldIndex: field.fieldIndex, type: 'text', label: sub.label, defaultValue: sub.modelValue, required: sub.required, placeholder: sub.placeholder, position: field.position, value: sub.modelValue, hideLabel: sub.optionHide, description: sub.description, requiredMessage: '', parentId: field.id, subFieldIndex: idx, } as Field) }) continue } } if (field.type === 'address') { if (Array.isArray(field.addressFields)) { const { addressFields, ...parentRest } = field result.push(parentRest as Field) addressFields.forEach((sub, idx) => { const settings = JSON.stringify({ hideLabel: sub.hideLabel, description: sub.description, placeholder: sub.placeholder, type: sub.type, requiredMessage: sub.requiredMessage, visible: typeof sub.visible === 'boolean' ? sub.visible : true, }) result.push({ id: sub.id ? parseInt(sub.id, 10) || 0 : 0, formId: field.formId, fieldIndex: field.fieldIndex, type: 'text', label: sub.label, defaultValue: sub.value, required: sub.required, placeholder: sub.placeholder, position: field.position, value: sub.value, hideLabel: sub.hideLabel, description: sub.description, requiredMessage: sub.requiredMessage, parentId: field.id, addressType: sub.type, settings, subFieldIndex: idx, visible: sub.visible, } as Field) }) continue } } // Regular field result.push({ ...field, id: typeof field.id === 'string' ? parseInt(field.id, 10) || 0 : field.id || 0, } as Field) } return result }