Documentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide documents the integration between the Forms & Workflow (FW) module and the Platform Foundation modules:
- PF-15: Picklist System
- PF-16: Custom Field Definitions
- PF-17: Entity Field Configuration
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Shared Infrastructure │
├─────────────────────────────────────────────────────────────────┤
│ FIELD_TYPE_REGISTRY (src/platform/field-config/fieldTypes.ts) │
│ Shared Field Renderers (src/platform/forms/components/fields/)│
└─────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ FW Form Builder │ │ PF-17 Entity Forms │
│ (Standalone Forms) │ │ (Database Entities)│
├─────────────────────┤ ├─────────────────────┤
│ FieldEditorDialog │ │ DynamicFormRenderer │
│ FormRenderer │ │ ConfigurableForm │
│ LookupConfigPanel │ │ STANDARD_FIELDS │
│ PicklistConfigPanel │◄──────────►│ PicklistSelector │
└─────────────────────┘ └─────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Data Sources │
├─────────────────────┬─────────────────────┬────────────────────┤
│ Static Options │ Table Lookups │ PF-15 Picklists │
│ (hardcoded) │ (fw_lookup_tables)│ (pf_picklists) │
└─────────────────────┴─────────────────────┴────────────────────┘
Integration Points
1. Unified Field Type System (Step 6.2)
Location: src/platform/field-config/fieldTypes.ts
The FIELD_TYPE_REGISTRY provides a single source of truth for field types across both FW and PF-17.
import { FIELD_TYPE_REGISTRY, getFWFieldTypes } from '@/platform/field-config/fieldTypes';
// Get all field types (for PF-17)
const allTypes = Object.values(FIELD_TYPE_REGISTRY);
// Get FW-compatible types only (excludes PF-17 specific like 'lookup', 'currency')
const fwTypes = getFWFieldTypes();
2. Picklist Data Source (Steps 6.1 & 6.4)
FW Form Builder now supports PF-15 picklists as a data source option alongside static options and table lookups.
Usage in FieldEditorDialog:
// Data source options: 'static' | 'lookup' | 'picklist'
const [dataSource, setDataSource] = useState<'static' | 'lookup' | 'picklist'>('static');
// When picklist is selected, use PicklistConfigPanel
{dataSource === 'picklist' && (
<PicklistConfigPanel
picklistName={picklistConfig.picklistName}
onChange={(name) => setPicklistConfig({ picklistName: name })}
/>
)}
Saved Field Settings:
// Picklist data source
settings: {
dataSource: 'picklist',
picklistName: 'employment_status'
}
3. Shared Field Renderers (Step 6.3)
Location: src/platform/forms/components/fields/
Common field components used by both FormRenderer and DynamicFormRenderer:
| Component | Description |
|---|
TextField | Single-line text input |
TextareaField | Multi-line text input |
NumberField | Numeric input |
SelectField | Dropdown with static/lookup/picklist support |
CheckboxField | Boolean checkbox |
DateField | Date picker |
DateTimeField | DateTime picker |
EmailField | Email input with validation |
PhoneField | Phone number input |
SelectField automatically handles all three data sources:
<SelectField
fieldKey="status"
label="Status"
value={formData.status}
onChange={(val) => handleChange('status', val)}
// Pick ONE of these data sources:
staticOptions={[{ label: 'Active', value: 'active' }]} // OR
picklistName="employee_status" // OR
lookupSettings={{ lookupTable: 'hr_departments', ... }}
/>
4. Section/Page Mapping (Step 6.5)
Location: src/platform/forms/utils/sectionPageMapping.ts
Maps PF-17 field_section to FW-05 form pages:
import { mapSectionsToPages, getUniqueSections } from '@/platform/forms/utils/sectionPageMapping';
// Convert entity field configs to form pages
const pages = mapSectionsToPages(fieldConfigs);
// Get unique section names
const sections = getUniqueSections(fieldConfigs);
5. Entity Mapping Workflow Action (Step 6.6)
Component: src/cores/fw/components/EntityMappingActionConfig.tsx
Edge Function: supabase/functions/process-entity-mapping/
Maps form submission data to entity table columns and custom_fields JSONB.
Configuration:
const config: EntityMappingConfig = {
targetEntity: 'fa_customers',
operation: 'create', // 'create' | 'update' | 'upsert'
lookupField: 'email', // Required for update/upsert
fieldMappings: [
{ formField: 'full_name', entityField: 'customer_name', isCustomField: false },
{ formField: 'notes', entityField: 'custom_fields.intake_notes', isCustomField: true },
],
};
Edge Function Usage:
const response = await supabase.functions.invoke('process-entity-mapping', {
body: {
submissionData: formSubmission.submission_data,
actionConfig: config,
organizationId: org.id,
userId: user.id,
},
});
Migration Guide
- Identify candidates: Forms using static select options that should be centrally managed
- Create picklist: In Settings → Picklists, create the picklist with items
- Update form field: Edit the field, change Data Source to “Picklist”, select the picklist
Using Shared Field Components
Before (inline rendering in FormRenderer):
case 'text':
return (
<div className="space-y-2">
<Label>{field.label}</Label>
<Input value={value} onChange={...} />
</div>
);
After (using shared components):
import { TextField } from '@/platform/forms/components/fields';
case 'text':
return (
<TextField
fieldKey={field.field_key}
label={field.label}
value={value}
onChange={(val) => handleChange(field.field_key, val)}
required={field.required}
error={errors[field.field_key]}
/>
);
Best Practices
- Prefer picklists over static options when values are reused across forms or need central management
- Use shared field components to ensure consistent styling and behavior
- Map to custom_fields for organization-specific data that doesn’t fit standard columns
- Test entity mappings with create before enabling update/upsert operations