> ## 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.

# ConfigurableForm Integration Guide

> The ConfigurableForm component (PF-17) provides a dynamic, configuration-driven form renderer that eliminates the need for hardcoded forms. It supports:

## Overview

The `ConfigurableForm` component (PF-17) provides a dynamic, configuration-driven form renderer that eliminates the need for hardcoded forms. It supports:

* **Standard fields** from entity table columns
* **Custom fields** from `pf_custom_field_definitions`
* **Picklist-based selects** from `pf_picklists`
* **Lookup fields** for entity references (accounts, customers, etc.)
* **Field visibility** based on roles and conditional rules
* **Configurable layouts** with sections and column spans

## Quick Start

### Basic Usage

```tsx theme={null}
import { ConfigurableForm } from '@/platform/field-config';

function MyEntityForm({ entity, onSubmit, onCancel }) {
  return (
    <ConfigurableForm
      entityType="fa_customers"
      viewContext={entity ? 'edit_form' : 'create_form'}
      initialData={entity || {}}
      onSubmit={onSubmit}
      onCancel={onCancel}
      isSubmitting={false}
      submitLabel="Save Customer"
    />
  );
}
```

### Props

| Prop           | Type                  | Required | Description                                                                             |
| -------------- | --------------------- | -------- | --------------------------------------------------------------------------------------- |
| `entityType`   | `string`              | Yes      | Entity type key (e.g., `fa_customers`, `hr_employees`)                                  |
| `viewContext`  | `ViewContext`         | No       | One of: `create_form`, `edit_form`, `detail_view`, `list_view`. Defaults to `edit_form` |
| `initialData`  | `Record<string, any>` | No       | Initial values for form fields                                                          |
| `onSubmit`     | `(data) => void`      | Yes      | Callback when form is submitted                                                         |
| `onCancel`     | `() => void`          | No       | Callback when Cancel button is clicked                                                  |
| `userRole`     | `string`              | No       | Current user's role for field visibility checks                                         |
| `isSubmitting` | `boolean`             | No       | Shows loading state on submit button                                                    |
| `submitLabel`  | `string`              | No       | Custom text for submit button                                                           |

## Field Types

### Standard Field Types

The following types are supported in `STANDARD_FIELDS`:

| Type       | Renderer                        | Description                  |
| ---------- | ------------------------------- | ---------------------------- |
| `text`     | `<Input>`                       | Basic text input             |
| `email`    | `<Input type="email">`          | Email input with validation  |
| `number`   | `<Input type="number">`         | Numeric input                |
| `date`     | `<Input type="date">`           | Date picker                  |
| `datetime` | `<Input type="datetime-local">` | Date and time picker         |
| `boolean`  | `<Switch>`                      | Toggle switch                |
| `textarea` | `<Textarea>`                    | Multi-line text              |
| `select`   | `<PicklistSelectRenderer>`      | Dropdown using picklist data |
| `lookup`   | `<LookupFieldRenderer>`         | Entity reference selector    |

### Adding Select Fields with Picklists

To use a picklist for a select field, add `picklistName` to the field definition:

```typescript theme={null}
// In types.ts STANDARD_FIELDS
{
  field_key: 'customer_type',
  label: 'Customer Type',
  type: 'select',
  picklistName: 'fa_customer_type' // Links to pf_picklists.name
}
```

### Adding Lookup Fields

Lookup fields reference other entities. Configure them in `LookupFieldRenderer.tsx`:

```typescript theme={null}
const LOOKUP_CONFIGS = {
  'default_revenue_account_id': {
    table: 'fa_accounts',
    valueField: 'id',
    labelField: 'name',
    displayFormat: (item) => `${item.account_number} - ${item.name}`,
    filter: { account_type: 'revenue' },
  },
};
```

## Database Configuration

### Field Configs Table (`pf_entity_field_configs`)

Each visible field needs a config entry:

```sql theme={null}
INSERT INTO pf_entity_field_configs (
  organization_id,
  entity_type,
  view_context,
  field_source,
  field_key,
  is_visible,
  is_editable,
  display_order,
  column_span,
  field_section
) VALUES (
  'your-org-id',
  'fa_customers',
  'edit_form',
  'standard',
  'customer_name',
  true,
  true,
  1,
  1,
  'Basic Information'
);
```

### Custom Fields

Custom fields are automatically included when:

1. They exist in `pf_custom_field_definitions` for the entity type
2. A config entry exists with `field_source = 'custom'`

## Migration Example

Converting an existing form to ConfigurableForm:

### Before (Hardcoded)

```tsx theme={null}
export function CustomerForm({ customer, onSubmit, onCancel }) {
  const form = useForm({...});
  
  return (
    <Form {...form}>
      <FormField name="customer_name" ... />
      <FormField name="customer_type" ... />
      {/* 50+ lines of form fields */}
    </Form>
  );
}
```

### After (ConfigurableForm)

```tsx theme={null}
export function CustomerForm({ customer, onSubmit, onCancel, isSubmitting }) {
  return (
    <ConfigurableForm
      entityType="fa_customers"
      viewContext={customer ? 'edit_form' : 'create_form'}
      initialData={customer}
      onSubmit={onSubmit}
      onCancel={onCancel}
      isSubmitting={isSubmitting}
    />
  );
}
```

## Fallback Behavior

If no field configs exist for an entity/context, ConfigurableForm falls back to rendering all fields from `STANDARD_FIELDS` in a default layout.

## Best Practices

1. **Seed field configs for all view contexts** - create\_form, edit\_form, detail\_view, list\_view
2. **Use meaningful section names** - Groups fields visually in the UI
3. **Set column\_span = 2** for full-width fields like textarea
4. **Configure conditional\_rules** for dependent field visibility
5. **Use picklists** instead of hardcoded select options for flexibility

## Architecture

```
ConfigurableForm
    └── DynamicFormRenderer
            ├── useEntityFieldConfigs (fetch configs)
            ├── useConditionalVisibility (show/hide logic)
            └── For each field:
                    ├── StandardFieldRenderer (text, email, number, etc.)
                    │       ├── PicklistSelectRenderer (select with picklist)
                    │       └── LookupFieldRenderer (entity references)
                    └── CustomFieldInput (custom fields)
```

## Related Documentation

* [PF-15: Picklist System](../../specs/pf/specs/PF-15-picklist-system.md)
* [PF-16: Custom Field Definitions](../../specs/pf/specs/PF-16-custom-field-definitions.md)
* [PF-17: Entity Field Configuration](./use-cases/field-configuration.md)
* [Picklist Migration Guide](./picklist-migration-guide.md)
