4.1 KiB
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
backend/notes/— ORM, models, service, router (mounted at/api/notes)backend/tickets/— ORM, models, service, router (mounted at/api/tickets)- Alembic migrations applied:
entries,entry_links,support_tickets,ticket_messages frontend/src/pages/crm/comms/helpdesk/TicketsTab.jsx— tickets tab on comms pagefrontend/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 — filterstypeonGET /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)