Google-SSO PWA for bistro employee clock-in/out, admin employee management, and stats with CSV export. Express + SQLite backend, React + Zustand frontend in the light-mono-tui design language. Multi-stage Dockerfile, compose.yaml for image-based deploys, nginx reverse-proxy template, and an OKF documentation bundle in docs/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.3 KiB
2.3 KiB
type, title, description, resource, tags, timestamp
| type | title | description | resource | tags | timestamp | ||
|---|---|---|---|---|---|---|---|
| API Endpoint | Admin routes | Employee CRUD (add/soft-delete), org-wide and per-employee stats, and CSV export — all requireAdmin. | backend/src/routes/admin.ts |
|
2026-08-12T00:00:00Z |
Admin routes
Mounted at /api/admin. Every route requires requireAuth + requireAdmin
(role resolved from ADMIN_EMAILS, see Auth flow).
Examples
GET /api/admin/employees
200 -> { "employees": Employee[] } // includes inactive (soft-deleted) rows
POST /api/admin/employees
Body: { "email": string, "name"?: string }
201 -> { "employee": Employee }
Upserts by email — see employees for the reactivate-on-re-add behavior.
DELETE /api/admin/employees/:id
204 on success, 404 if not found.
Soft delete only (active = 0) — never removes the row or its attendance
history.
GET /api/admin/stats?month=YYYY-MM
200 -> {
"range": { "from": string, "to": string },
"totals": { "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number },
"employees": [{ "employee": Employee, "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number }]
}
Same calendar-month default as the employee's own stats endpoint.
GET /api/admin/stats/:id?month=YYYY-MM
200 -> { "employee": Employee, "range": {...}, "sessions": Session[], "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number }
404 -> employee not found
GET /api/admin/stats/:id/export?month=YYYY-MM
200, Content-Type: text/csv; charset=utf-8
Content-Disposition: attachment; filename="<email>_<YYYY-MM>.csv"
Columns: Datum, Příchod, Odchod, Pauza (h:mm), Odpracováno (h:mm), one row
per shift, sorted chronologically (backend/src/util/csv.ts). Prefixed with
a UTF-8 BOM so Excel renders the Czech diacritics correctly. Downloaded from
the frontend as a plain <a href=... download> — the session cookie rides
along automatically since it's a same-origin GET.
Related
- employees
- attendance_events
- Attendance routes
- Frontend stores —
adminStoreowns the selected month and drives both the summary table and the per-employee chart off it