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>
1.7 KiB
1.7 KiB
type, title, description, resource, tags, timestamp
| type | title | description | resource | tags | timestamp | ||
|---|---|---|---|---|---|---|---|
| API Endpoint | Attendance routes | POST /api/attendance/event, GET /api/attendance/state, GET /api/attendance/me — the employee's own clock in/out and stats. | backend/src/routes/attendance.ts |
|
2026-08-12T00:00:00Z |
Attendance routes
Mounted at /api/attendance. Every route requires requireAuth +
requireEmployee — admins with no employee row get 403 here, by design
(the owner isn't necessarily clocking in themselves).
Examples
POST /api/attendance/event
Body: { "type": "clock_in" | "clock_out" | "break_start" | "break_end" }
201 -> { "event": AttendanceEvent, "status": LiveStatus }
400 -> invalid type
409 -> invalid transition for the current status, e.g. break_start while
already clocked_out — { "error": string, "status": LiveStatus }
GET /api/attendance/state
200 -> { "status": "clocked_out" | "working" | "on_break" }
GET /api/attendance/me?month=YYYY-MM (or ?from=YYYY-MM-DD&to=YYYY-MM-DD)
Defaults to the current calendar month if no query params are given
— see parseRange in backend/src/util/dateRange.ts.
200 -> {
"range": { "from": string, "to": string },
"sessions": Session[],
"totalWorkedMs": number,
"totalBreakMs": number,
"shiftCount": number
}
Session and the state machine behind these responses are documented at
attendance_events.
Related
- attendance_events
- Admin routes — same stats shape, but for any employee
- Frontend stores —
attendanceStorepollsGET /state+GET /meevery 60s and ticks a local clock every second between polls