# Submitted Forms (Permit Preview)

| | |
|---|---|
| **Nav ID** | `permit-preview` |
| **Component** | `AdminPermitPreviewPage.jsx` |
| **Services** | `permitsApi.js`, `formsApi.js` + `permitPreviewHelpers.js` |

Uses `useMasterData()` for question type labels.

---

## Endpoints

### GET `/ptw_permits`

List permits for the selector table.

---

### GET `/ptw_submissions?permit_id=42`

Loads all submissions for the selected permit.

---

### GET `/submissions/:submission_id/answers`

Primary preview data source — answers + media metadata.

---

### GET `/ptw_answers_media/:answers_id/:occurrence/file`

Stream answer media blob.

---

### GET `/ptw_opening_closing_map?permit_id=42`

Opening/closing submission linkage.

---

### Form structure chain

- `GET /ptw_form_section_map/form/:form_id`
- `GET /ptw_section_question_map/section/:section_id`

---

## SQL queries

### List submissions for permit

```sql
SELECT * FROM `ptw_submissions` WHERE `permit_id` = ?;
```

### Get submission + answers (with question metadata)

```sql
SELECT * FROM ptw_submissions WHERE submission_id = ? LIMIT 1;

SELECT
  a.answers_id, a.submission_id, a.question_id, a.is_media, a.answer_value,
  q.question, q.question_type_id, qt.question_type
FROM ptw_answers a
LEFT JOIN ptw_questions q ON q.question_id = a.question_id
LEFT JOIN ptw_question_type qt ON qt.question_type_id = q.question_type_id
WHERE a.submission_id = ?
ORDER BY a.answers_id;
```

### Media metadata per answer (no LONGBLOB in list)

```sql
SELECT answers_id, occurrence
FROM ptw_answers_media
WHERE answers_id IN (?)
ORDER BY answers_id, occurrence;
```

### Serve media file

```sql
SELECT media FROM ptw_answers_media
WHERE answers_id = ? AND occurrence = ? LIMIT 1;
```

### Opening/closing map

```sql
SELECT * FROM `ptw_opening_closing_map` WHERE `permit_id` = ?;
```

### Form with ordered sections

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

SELECT
  fsm.section_id, fsm.section_in_form_order, fsm.skipable,
  s.title, s.section_parent_id, s.created_by, s.created_date
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;
```

### Section with questions + options

```sql
SELECT * FROM ptw_section_details WHERE section_id = ? LIMIT 1;

SELECT q.question_id, q.question, q.question_type_id, q.allows_media, qt.question_type
FROM ptw_section_question_map m
JOIN ptw_questions q ON q.question_id = m.question_id
LEFT JOIN ptw_question_type qt ON qt.question_type_id = q.question_type_id
WHERE m.section_id = ?
ORDER BY q.question_id;

SELECT question_options_id, question_id, _options
FROM ptw_question_options
WHERE question_id IN (?)
ORDER BY question_options_id;
```

### Permit header

```sql
SELECT * FROM ptw_permits WHERE permit_id = ? LIMIT 1;
```

---

## Preview assembly

`permitPreviewHelpers.js` groups submissions by `submission_role`:

- **General / specialized** — opening form pages
- **Audit** — all `submission_role = 'audit'` rows, rendered with the audit table layout
- **Handover** — validity extensions
- **Handback** — closing step

Audit steps are ordered chronologically and labeled `Audit`, `Audit 2 of N`, etc. when multiple audits exist for one permit.
