import { FIELD_TYPE_SPECS, FIELD_TYPES, type FieldType } from '@/lib/fieldTypes' import { DEFAULT_RELATION_KIND, type RelationKind } from '@/lib/relationField' export { FIELD_TYPES, type FieldType } export type KeyMode = 'auto' | 'manual' export type KeyDisplayMode = KeyMode | 'empty' export type BuilderStatus = | 'saving' | 'offline' | 'failed' | 'problems' | 'dirty' | 'saved' | 'none' export const BUILDER_LIMITS = { nameMax: 100, typeKeyMin: 2, typeKeyMax: 40, fieldsMax: 50, fieldKeyMax: 40, choicesMax: 50, } export const RESERVED_TYPE_KEYS = ['new'] export const PREVIEW_KEY_FALLBACK = 'events' export const STARTER_LABEL = 'Title' export const STARTER_KEY = 'title' export interface BuilderField { uid: number label: string key: string keyMode: KeyMode type: FieldType required: boolean unique: boolean defaultValue: string defaultOn: boolean min: string max: string options: string[] relationType: string relationKind: RelationKind saved: boolean } export interface BuilderForm { name: string key: string keyMode: KeyMode keyLocked: boolean fields: BuilderField[] } export function keyDisplayMode(mode: KeyMode, key: string): KeyDisplayMode { if (mode === 'manual') { return 'manual' } return key ? 'auto' : 'empty' } export function createField(uid: number, overrides: Partial = {}): BuilderField { return { uid, label: '', key: '', keyMode: 'auto', type: 'text', required: false, unique: false, defaultValue: '', defaultOn: false, min: '', max: '', options: [], relationType: '', relationKind: DEFAULT_RELATION_KIND, saved: false, ...overrides, } } export function starterField(uid: number): BuilderField { return createField(uid, { label: STARTER_LABEL, key: STARTER_KEY }) } export function blankForm(uid: number): BuilderForm { return { name: '', key: '', keyMode: 'auto', keyLocked: false, fields: [starterField(uid)], } } export function changeFieldType(field: BuilderField, type: FieldType): BuilderField { if (field.type === type) { return field } return createField(field.uid, { label: field.label, key: field.key, keyMode: field.keyMode, required: field.required, type, }) } export function supportsUnique(type: FieldType) { return FIELD_TYPE_SPECS[type].supportsUnique } export function supportsChoices(type: FieldType) { return FIELD_TYPE_SPECS[type].supportsChoices } export function holdsRelation(type: FieldType) { return FIELD_TYPE_SPECS[type].holdsRelation } export function supportsLimits(type: FieldType) { return FIELD_TYPE_SPECS[type].supportsLimits } export function hasDefaultValue(field: BuilderField) { return !field.unique && field.defaultValue !== '' } export function trimmedOptions(field: BuilderField) { return field.options.map((option) => option.trim()) } export function clearStaleDefault(field: BuilderField): BuilderField { if (field.type !== 'select' || field.defaultValue === '') { return field } return trimmedOptions(field).includes(field.defaultValue) ? field : { ...field, defaultValue: '' } } export function isUnique(field: BuilderField) { return field.unique && supportsUnique(field.type) } export function supportsDefault(type: FieldType) { return FIELD_TYPE_SPECS[type].supportsDefault } export function effectiveDefault(field: BuilderField) { if (!supportsDefault(field.type) || isUnique(field) || field.defaultValue === '') { return '' } if (field.type === 'select') { return trimmedOptions(field).includes(field.defaultValue) ? field.defaultValue : '' } return field.defaultValue }