# Form Management

| | |
|---|---|
| **Nav ID** | `form-management` |
| **Component** | `AdminFormManagementPage.jsx` |
| **Services** | `formsApi.js` |

Uses `useMasterData()` for `ptw_form_type` and `ptw_job_type` dropdowns.

---

## Endpoints

See endpoint list in prior version. Key paths: `/ptw_form_details`, `/ptw_form_section_map`, `/form-builder`.

---

## SQL queries

### List / get forms

```sql
SELECT * FROM `ptw_form_details`;

SELECT * FROM `ptw_form_details` WHERE `form_id` = ? LIMIT 1;
```

### Create form (transaction)

```sql
INSERT INTO ptw_form_details (`title`, `form_type_id`, `job_type_id`, ...)
VALUES (?, ?, ?, ...);

-- optional location links:
INSERT INTO ptw_location_forms_details (form_id, location_id) VALUES (?, ?);

-- if form_parent_id set, archive old version:
INSERT INTO ptw_archive_form (form_id, ...) SELECT ... FROM ptw_form_details WHERE form_id = ?;
```

### Update form (transaction)

Audit snapshot first:

```sql
INSERT INTO ptw_form_logs
  (user_id, form_id, form_parent_id, title, description, form_type_name,
   job_type_name, created_by, created_date, location_name, action, created_at)
SELECT ?, f.form_id, f.form_parent_id, f.title, f.description,
       ft.form_type_name, jt.job_type_name, f.created_by, f.created_date,
       (SELECT GROUP_CONCAT(DISTINCT loc.location_name SEPARATOR ', ')
          FROM ptw_location_forms_details lfd
          JOIN locations loc ON loc.location_id = lfd.location_id
         WHERE lfd.form_id = f.form_id),
       'UPDATE', NOW()
FROM ptw_form_details f
LEFT JOIN ptw_form_type ft ON ft.form_type_id = f.form_type_id
LEFT JOIN ptw_job_type jt ON jt.job_type_id = f.job_type_id
WHERE f.form_id = ? LIMIT 1;

UPDATE ptw_form_details SET `title` = ?, ... WHERE form_id = ?;

-- replace location maps if location_ids sent:
DELETE FROM ptw_location_forms_details WHERE form_id = ?;
INSERT INTO ptw_location_forms_details (form_id, location_id) VALUES (?, ?);
```

### Form–section map

```sql
SELECT * FROM `ptw_form_section_map` WHERE `form_id` = ?;

-- getFormWithSections (ordered):
SELECT fsm.section_id, fsm.section_in_form_order, fsm.skipable, s.title, ...
FROM ptw_form_section_map fsm
JOIN ptw_section_details s ON s.section_id = fsm.section_id
WHERE fsm.form_id = ?
ORDER BY COALESCE(fsm.section_in_form_order, 999999), fsm.section_id;

-- attach section:
INSERT INTO ptw_form_section_map (form_id, section_id, section_in_form_order, skipable)
VALUES (?, ?, ?, ?);

-- reorder (transaction, one UPDATE per section):
UPDATE ptw_form_section_map SET section_in_form_order = ?
WHERE form_id = ? AND section_id = ?;

DELETE FROM ptw_form_section_map WHERE form_id = ? AND section_id = ?;
```

### POST `/form-builder` (nested publish, single transaction)

Sequential inserts across:

```sql
INSERT INTO ptw_form_details (...) VALUES (...);
INSERT INTO ptw_location_forms_details (form_id, location_id) VALUES (?, ?);

-- per section (new or reused section_id):
INSERT INTO ptw_section_details (...) VALUES (...);
INSERT INTO ptw_form_section_map (form_id, section_id, section_in_form_order) VALUES (?, ?, ?);

-- per question:
INSERT INTO ptw_questions (...) VALUES (...);
INSERT INTO ptw_question_options (question_id, _options) VALUES (?, ?);
INSERT INTO ptw_section_question_map (section_id, question_id) VALUES (?, ?);

-- skip logic:
INSERT INTO ptw_alternative_sections (skipable_section_id, other_section_id) VALUES (?, ?);
```

**Controllers:** `ptwFormController.js`, `ptwFormSectionMapController.js`, `ptwFormBuilderController.js`
