diff --git a/docs/roadmap.md b/docs/roadmap.md index 0aa6720..813dc8f 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -180,10 +180,16 @@ Each phase keeps the system working and is its own spec → plan → build cycle **3a implemented** (`apps/admin`; plan `docs/superpowers/plans/2026-06-17-phase-3a-admin-panel.md`): admin-only login (rejects non-admins via `role` on `/api/me`), the sidebar shell, the live active-work view (`/api/admin/sessions/active`, 5 s auto-refresh, read-only), and activity - management (handelingen CRUD on `/api/activities`). **3b remaining:** reports/export - (all-users filtered CSV — current `/api/export` is self-scoped), user management - (better-auth `/api/auth/admin/*`), and manual entry/edit + admin stop/fix of a running - session (needs new backend endpoints). + management (handelingen CRUD on `/api/activities`). + **3b·1 implemented** (plan `docs/superpowers/plans/2026-06-17-phase-3b1-manual-sessions.md`): + manual session entry/edit + admin stop/discard of a running session (new admin write + endpoints `POST/PUT /api/admin/sessions[/:id]`, `…/:id/stop`, `…/:id/discard`, plus a + `GET /api/admin/users` roster), an admin **Sessies** screen (list + status filter + + create/edit form + row actions), Stop/Annuleer on the Live cards, and a worker stopwatch + that polls (15 s) and reconciles to server truth (converges within ~15 s when an admin + stops/cancels/edits a session — no stuck state). **3b remaining:** reports/export + (all-users filtered CSV — current `/api/export` is self-scoped) and user management + (better-auth `/api/auth/admin/*`). Activity management (add/edit/delete handelingen + their `insole_types`) was removed from the worker client in the Phase 2 follow-up because it is admin-only; it must be **ported here**. The backend already exists (`/api/activities` writes are admin-gated; `useActivities`/the legacy diff --git a/docs/sessions/2026-06-17-phase-3b1-manual-sessions.md b/docs/sessions/2026-06-17-phase-3b1-manual-sessions.md new file mode 100644 index 0000000..4f3c06a --- /dev/null +++ b/docs/sessions/2026-06-17-phase-3b1-manual-sessions.md @@ -0,0 +1,98 @@ +# Session: 2026-06-17 — Phase 3b·1 (Manual session entry/edit + admin stop/fix + worker convergence) + +## Goal + +Let an admin take full control of sessions: list/filter every session, manually create a +completed session for a worker, edit any session (server recomputes duration), and +stop/cancel a worker's active session — and make the worker's stopwatch converge to those +admin changes within ~15 s with no stuck state. No DB migration (reuses the existing +`work_sessions` columns, incl. the pause fields from the prior cycle). +Spec: `docs/superpowers/specs/2026-06-17-phase-3b1-manual-sessions-design.md`; +plan: `docs/superpowers/plans/2026-06-17-phase-3b1-manual-sessions.md`. + +## Work done + +Implemented task-by-task per the plan (TDD throughout), one commit per task: + +- **Task 1 — Shared contracts** (`00993c6`). `@solelog/shared` gains + `CreateManualSessionInput` (worker id + activity + insole type + pair count + + `start_time`/`end_time` + `paused_seconds` default 0 + optional `notes`) and + `AdminUpdateSessionInput` (editable fields incl. nullable `end_time`/`insole_type` and a + `status`), with their inferred types. Duration is never accepted from the client. +- **Task 2 — Backend admin session write endpoints + users roster** (`53c66ee`). In + `apps/api/src/routes/admin.ts` (behind the existing `/api/admin/*` admin guard): + `GET /api/admin/users` (id/name/email, ordered by name), `POST /api/admin/sessions` + (validates the worker + activity, rejects `end < start` and `paused > span`, stores + `source='manual'`, `status='completed'`, server-computed `duration_seconds`), + `PUT /api/admin/sessions/:id` (recomputes duration; nullable `end_time` keeps an active + row open), and `POST …/:id/stop` (folds any open pause span, `end=now`, completes) / + `…/:id/discard` (`status='discarded'`, `end=now`). All session responses go through + `toWorkSession`. Workers hitting any of these get 403; stop/discard on an + already-closed session → 409. +- **Task 3 — Admin api hooks + Sessions screen** (`b536641`). `api/admin-sessions.ts`: + `useAllSessions`, `useAdminUsers`, `useCreateManualSession`, `useUpdateSession`, + `useAdminStopSession`, `useAdminDiscardSession` (mutations invalidate + `['admin','sessions']`). New `screens/Sessions.tsx` (title "Sessies", status ``, insole-type toggles, pair-count stepper, + start/end `datetime-local` (built into ISO), paused input, status `