Files
solelog/docs/sessions/2026-06-17-phase-3a-admin-panel.md
2026-06-17 19:17:20 +02:00

4.3 KiB

Session: 2026-06-17 — Phase 3a (Admin panel MVP)

Goal

Build apps/admin: a Vite + React desktop SPA where an admin logs in, watches who is working live (auto-refreshing, read-only), and manages handelingen (activities). Everything rides on existing backend endpoints plus one tiny backend touch (role on /api/me). Reports/export, user management, and manual session entry/edit are deferred to Phase 3b. Spec: docs/superpowers/specs/2026-06-17-phase-3a-admin-panel-design.md; plan: docs/superpowers/plans/2026-06-17-phase-3a-admin-panel.md.

Work done

Implemented Phase 3a task-by-task per the plan (TDD throughout):

  • Task 1 — role on /api/me + admin-origin CORS (02b7522). Added role: Role to PublicUser in @solelog/shared; apps/api/src/routes/me.ts now returns the session user's role (default 'worker'). Added http://localhost:5174 (admin dev origin) to the default WEB_ORIGINS in env.ts + .env.example (it drives both hono/cors and better-auth trustedOrigins). Extended me.test.ts and cors.test.ts. Worker client ignores the extra field — no worker change needed.
  • Task 2 — Scaffold apps/admin (682a9dc). New @solelog/admin workspace mirroring apps/worker's toolchain (Vite 7, React 18.3, react-router 6, react-query 5, vitest 3, TS 5.7). Copied lib/api.ts + lib/auth-storage.ts verbatim (shared solelog.token key; separate localStorage because the admin runs on a different port). Dev port 5174.
  • Task 3 — Auth context + admin gate + Login (77659ed). auth/AuthContext.tsx: signIn calls the worker signIn, fetches /api/me, and rejects non-admins (clearToken() + throw) so Login shows "Geen toegang — alleen beheerders."; other failures show "Inloggen mislukt".
  • Task 4 — Sidebar shell + routing (286e2d2). Left-sidebar shell: brand "SoleLog Admin", NavLinks Live / Handelingen, a muted "Binnenkort" group (Rapporten / Gebruikers / Handmatig) hinting 3b, and a header strip with the signed-in email + an Uitloggen button (aria-label="Uitloggen").
  • Task 5 — Live active-work view (67dd0d3). useActiveSessions() polls /api/admin/sessions/active with refetchInterval: 5000; lib/elapsed.ts formatTime ported verbatim from the worker stopwatch. One card per session (worker name, activity, insole-type pill, pair count, ticking elapsed timer). Header "Actief nu (N)"; empty state "Niemand is nu aan het werk.".
  • Task 6 — Activity management (c0d9d21). Ported the legacy worker Settings.tsx (git decb158) near-verbatim: api/activities.ts hooks (useActivities + create/update/delete, all invalidating ['activities']) and screens/Activities.tsx (add form with insole-type toggles, list with inline edit, delete-with-confirm). Title "Handelingen".
  • Task 7 — Docs, lint, verification (this task). Lint/format clean, full green matrix, live smoke, docs.

Verification (Task 7)

  • npx oxlint — clean (exit 0).
  • npx oxfmt --list-different over the phase-3a files — nothing to change (all formatted).
  • yarn workspace @solelog/api typecheck — pass; test46 passed (11 files).
  • yarn workspace @solelog/admin typecheck — pass; test14 passed (5 files); build — pass (vite build, 89 modules).
  • yarn workspace @solelog/worker test (regression) — 22 passed (7 files).
  • Live smoke (API started, seeded, then server tree killed + port 3000 freed):
    • admin sign-in → GET /api/me{ ..., "role": "admin" }.
    • GET /api/admin/sessions/active with the admin bearer → [], HTTP 200.
    • worker sign-in → GET /api/me{ ..., "role": "worker" }.

Outcome

Phase 3a is implemented and green. An admin can sign in to the admin app, see who is working right now (5s auto-refresh, read-only), and add/edit/delete handelingen; a worker who signs in with valid credentials is rejected with "Geen toegang". Roadmap Phase 3 status updated to "3a implemented; 3b remaining"; apps/admin/README.md filled.

Next (Phase 3b)

  • Reports + all-users filtered CSV export (current /api/export is self-scoped).
  • User management via better-auth /api/auth/admin/*.
  • Manual session entry/edit + admin stop/fix of another worker's session (needs new backend endpoints).