# Multi-Step Forms and Wizards

Multi-step forms let administrators guide users through a sequence of forms. Each wizard is stored in the `form_wizards` table with its steps defined in `form_wizard_steps`.

## Database Tables

`form_wizards`
:  Top level wizard records. Columns:
  - `id` – primary key
  - `name` – unique display name
  - `description` – optional help text
  - `tenant_id` and `branch_id` – scope of the wizard
  - `isDeleted` – soft delete flag

`form_wizard_steps`
:  Stores the forms that make up a wizard. Columns:
  - `wizard_id` – reference to `form_wizards`
  - `step_number` – order index starting at 1
  - `form_id` – form rendered for the step
  - `condition_field` and `condition_value` – optional values used to conditionally include the step

Steps are resolved by `FormConfigService->getWizardSteps()`. When `condition_field` is set the service compares the supplied form data with `condition_value` and only returns the step when they match.

## Triggering a Wizard

The `openWizard(id)` helper fetches a wizard definition from `/api/form_wizards/{id}` and creates a `MultiStepFormManager` instance. The endpoint returns the wizard record with a `steps` array containing the resolved form steps. Each step is rendered with `FormRenderer` and displayed inside a modal. When the first step is validated the helper filters later steps using their conditions so only relevant forms appear.

You can reference a wizard from any button element defined in `ModalBuilder` by including either `wizardId` or `wizardName`.

To expose a wizard in the UI include a button definition with `wizardId` (or `wizardName`).
`ModalBuilder` automatically calls `openWizard()` when such a button is clicked.
The example below comes from the default incident module:

```json
{
  "title": "OHS Incidents",
  "header": [
    { "type": "button", "label": "Add Incident", "wizardId": 1 }
  ]
}
```

### `open-form` Button Action

Buttons inside a wizard step can branch to another form using the `open-form` action. The `action_payload` is a JSON object:

```json
{
  "lookupTable": "table mapping the selection to a form id",
  "lookupField": "field name or id holding the user's choice",
  "valueColumn": "column in lookupTable that matches the selection",
  "formColumn": "column containing the form id"
}
```

When clicked the manager reads the value from `lookupField`, searches `lookupTable` for a row where `valueColumn` equals that value and opens the form referenced by `formColumn`.

## OHS Incident Wizard Example

`sql/defaults.sql` seeds the **OHS Incident Wizard** with eight steps. The first step collects the incident classification. Subsequent steps are only shown when the classification matches their `condition_value`:

```sql
INSERT INTO form_wizard_steps (wizard_id, step_number, form_id, condition_field, condition_value) VALUES
  (1, 1, 59, NULL, NULL),
  (1, 2, 13, 'classification', 'property_damage'),
  (1, 3, 14, 'classification', 'environmental'),
  (1, 4, 15, 'classification', 'near_miss'),
  (1, 5, 16, 'classification', 'first_aid'),
  (1, 6, 17, 'classification', 'medical_treatment'),
  (1, 7, 18, 'classification', 'lti'),
  (1, 8, 19, 'classification', 'fatality');
```

The **OHS Incident Classification** step also defines an `open-form` button so the wizard can load a form based on the selected incident type:

```sql
INSERT INTO form_buttons (form_id, label, action_type, action_payload, order_index)
VALUES
  (59, 'Open Form', 'open-form',
   '{"lookupTable":"ohs_incident_types","lookupField":"classification","valueColumn":"name","formColumn":"form_id"}',
   1);
```

This button looks up the chosen classification in `ohs_incident_types` and opens the referenced form. Other wizard steps can include similar buttons to branch into additional forms.

Users click **Add Incident** in the **OHS Incidents** modal, which triggers `openWizard(1)` via the `wizardId` property and guides them through the appropriate forms.

The **OHS Inspection Wizard** now begins with a similar classification step. Form ID 96
(`OHS Inspection Start`) collects the inspection type and location, then its **Open Form**
button loads the specific checklist linked to that type.
