# Notes, Issues & Support Tickets — UI Remaining Work

> Backend is fully built and deployed. Alembic migrations applied.
> This file tracks ONLY the remaining frontend work.
> Migration strategy has moved to DATABASE_MIGRATION.md.

## What's done

- [x] `backend/notes/` — ORM, models, service, router (mounted at `/api/notes`)
- [x] `backend/tickets/` — ORM, models, service, router (mounted at `/api/tickets`)
- [x] Alembic migrations applied: `entries`, `entry_links`, `support_tickets`, `ticket_messages`
- [x] `frontend/src/pages/crm/comms/helpdesk/TicketsTab.jsx` — tickets tab on comms page
- [x] `frontend/src/modals/crm/helpdesk/CreateTicketModal.jsx`

---

## What's remaining

### 7.1 Global Notes & Issues page

Page at `frontend/src/pages/crm/notes/NotesPage.jsx`, route `/crm/notes`.

Features:
- `<Tabs>` with "Notes" and "Issues" tabs — filters `type` on `GET /api/notes`
- `<DataTable>` columns: title, type badge, status badge, severity badge, linked entities (chips), author, date
- Create button → opens `<EntryFormModal>`
- Click row → opens `<EntryDetailModal>`
- Filters: status, severity
- `<Pagination>`

### 7.2 Entry form modal

Modal at `frontend/src/modals/crm/notes/EntryFormModal.jsx`.

Fields:
- Type selector (note / issue) — conditionally shows status + severity when type = issue
- Title (`<FormField type="text">`)
- Body (`<FormField type="textarea">`)
- Status selector (issue only, `<FormField type="select">`)
- Severity selector (issue only, `<FormField type="select">`)
- Linked entities: searchable selects for devices, app users, customers

### 7.3 Device detail page — Notes & Issues tab

Add a "Notes & Issues" tab to the existing device detail page.
Calls `GET /api/notes/by-entity/device/:deviceId`.
Shows compact entry list. Inline "Add note" / "Add issue" buttons that pre-fill the device link.

### 7.4 Customer detail page — Notes, Issues & Tickets tabs

**Notes & Issues tab:** calls `GET /api/notes/by-entity/customer/:customerId`

**Support Tickets tab:**
- Calls `GET /api/tickets/by-customer/:customerId`
- Ticket list with status + priority badges
- Click row → opens `<TicketThreadModal>`

### 7.5 Global Support Tickets page

Page at `frontend/src/pages/crm/tickets/TicketsPage.jsx`, route `/crm/tickets`.

Features:
- `<DataTable>` columns: subject, customer name, device serial, status badge, priority badge, opened via, last updated
- Click row → opens ticket thread view
- Create ticket button
- Filters: status, priority, customer, device
- `<Pagination>`

### 7.6 Ticket thread modal

Modal at `frontend/src/modals/crm/tickets/TicketThreadModal.jsx`.

- Ticket subject, customer, device, status, priority at the top
- Message thread — chronological, oldest first
- Internal notes visually distinct (different background, lock icon) — never shown to customers
- Reply form at the bottom: toggle between "Reply to customer" and "Internal note"
- Status change accessible from the thread view
- "Escalate to issue" button — links to an existing issue entry

---

## API quick reference

```
GET  /api/notes                          list notes/issues (type, status, severity, page, limit)
GET  /api/notes/by-entity/:type/:id      notes for a device or customer
POST /api/notes                          create note or issue
PATCH /api/notes/:id                     update
PATCH /api/notes/:id/links               replace entity links
DELETE /api/notes/:id

GET  /api/tickets                        list tickets (status, priority, customer_id, page, limit)
GET  /api/tickets/by-customer/:id
GET  /api/tickets/by-device/:id
POST /api/tickets
PATCH /api/tickets/:id
POST /api/tickets/:id/messages
POST /api/tickets/:id/escalate
```

## Entry type rules

| Field      | Note         | Issue                    |
|------------|--------------|--------------------------|
| `type`     | `'note'`     | `'issue'`                |
| `status`   | always null  | required: open / in_progress / resolved |
| `severity` | always null  | optional: low / medium / high / critical |

## Ticket status flow

```
open → waiting_on_customer → waiting_on_staff → resolved → closed
         (staff replied)        (customer replied)
```
