feat(i18n): add internationalization support with English and Spanish translations
feat(kiosk): implement kiosk report submission functionality with offline support test(outbox): add tests for outbox functionality including report submission and error handling feat(outbox): create outbox management for queued reports with IndexedDB persistence feat(uuid): add UUID generation utility for client IDs feat(qr): implement QR code generation for reporting links by site and area feat(kiosk): create Kiosk page for reporting incidents without an account
This commit is contained in:
1 parent
3f6dff5f24
commit
3e964d1176
64 files changed
+10056
-267
No files matched your search
+20
-1
@@ -68,6 +68,8 @@ Addressed by number (`/api/incidents/42` is `INC-0042`). Numbers are sequential
|
||||
|
||||
**List and export filters:** `page`, `pageSize` (1–100, default 25), `q` (title, description, location; `INC-0042` or `42` matches the number), `type`, `severity`, `status`, `siteId`.
|
||||
|
||||
Send a random `clientId` (UUID) with each report. Resubmitting the same `clientId` returns the original report (200 instead of 201) instead of creating a duplicate, so devices can safely retry after a dropped connection.
|
||||
|
||||
**Create body:**
|
||||
|
||||
```json
|
||||
@@ -81,7 +83,8 @@ Addressed by number (`/api/incidents/42` is `INC-0042`). Numbers are sequential
|
||||
"locationDetail": "Loading bay C",
|
||||
"description": "…",
|
||||
"immediateAction": "Area cordoned off",
|
||||
"anonymous": false
|
||||
"anonymous": false,
|
||||
"clientId": "6f1c…"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -119,6 +122,22 @@ Addressed by number (`/api/incidents/42` is `INC-0042`). Numbers are sequential
|
||||
|
||||
Each action has `overdue: true` when it's open or in progress and its due date has passed (server time zone, `TZ`). Assignees get one email digest per day listing their actions due tomorrow or overdue.
|
||||
|
||||
## Reporting links (kiosks and QR codes)
|
||||
|
||||
Reporting links let people file reports without an account. Each has a token that can **only** create reports.
|
||||
|
||||
| Method | Path | Who | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| GET | `/api/kiosks` | safety_manager | All links, including their tokens (to reprint QR codes) |
|
||||
| POST | `/api/kiosks` | safety_manager | `{ name, siteId? }`. `siteId` restricts the link to one site |
|
||||
| PATCH | `/api/kiosks/:id` | safety_manager | `{ name?, siteId?, revoked? }` |
|
||||
| GET | `/api/kiosk/config` | link token | Organization name, link name, and the sites/areas it may report on |
|
||||
| POST | `/api/kiosk/reports` | link token | Multipart: `report` (JSON: the create body minus `anonymous`, plus optional `reporterName`) and up to 5 `files`. Returns `{ reference, failedFiles }`. 30 reports per link per 10 minutes |
|
||||
|
||||
The token goes in the `X-Kiosk-Token` header. Browsers can't send custom headers cross-site without a CORS preflight, which the API doesn't allow, so other websites can't submit through a link. Reports without `reporterName` are anonymous. Incidents filed this way have `channel: "kiosk"` and `kiosk: { id, name }`.
|
||||
|
||||
The web app opens links at `/k/<token>`, optionally with `?site=<id>&area=<id>` to pre-fill the location (as QR codes do).
|
||||
|
||||
## Stats
|
||||
|
||||
| Method | Path | Who | Notes |
|
||||
|
||||
Reference in new issue
Block a user