Skip to main content

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:
ComponentDescription
TextFieldSingle-line text input
TextareaFieldMulti-line text input
NumberFieldNumeric input
SelectFieldDropdown with static/lookup/picklist support
CheckboxFieldBoolean checkbox
DateFieldDate picker
DateTimeFieldDateTime picker
EmailFieldEmail input with validation
PhoneFieldPhone 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

Updating Existing Forms to Use Picklists

  1. Identify candidates: Forms using static select options that should be centrally managed
  2. Create picklist: In Settings → Picklists, create the picklist with items
  3. 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

  1. Prefer picklists over static options when values are reused across forms or need central management
  2. Use shared field components to ensure consistent styling and behavior
  3. Map to custom_fields for organization-specific data that doesn’t fit standard columns
  4. Test entity mappings with create before enabling update/upsert operations