@solelog/admin
The SoleLog Admin panel: a Vite + React + TypeScript single-page app for the
shop-floor administrator. An admin logs in (email + password → bearer token in
localStorage), watches who is working live, and manages the handelingen
(activities). It is a client only — it talks to the @solelog/api backend over HTTP
with Authorization: Bearer <token>; it never touches the database.
Admin-only. Sign-in confirms
role === 'admin'viaGET /api/me. A worker who signs in with valid credentials is rejected with "Geen toegang — alleen beheerders." and the token is cleared. The UI is in Dutch.
It mirrors apps/worker's toolchain and conventions (same Vite/React/react-query/vitest
versions, the same lib/api.ts + lib/auth-storage.ts), so it shares proven patterns.
What Phase 3a covers
- Login — Dutch email + password form (no self-signup), with the admin-only gate.
- Sidebar shell — left sidebar with the signed-in email + an Uitloggen button, nav to Live and Handelingen, and a muted "Binnenkort" group (Rapporten / Gebruikers / Handmatig) hinting at Phase 3b.
- Live (
/) — who is working right now, fromGET /api/admin/sessions/active, auto-refreshing every 5 s (read-only in 3a). One card per session: worker name, activity, insole-type pill, pair count, and a client-side ticking elapsed timer. Empty state: "Niemand is nu aan het werk.". - Handelingen (
/handelingen) — add / inline-edit / delete activities and their insole types (Kurk/Berk/3D), against/api/activities(writes are admin-gated server-side; the admin bearer satisfies them).
Deferred to Phase 3b: reports + all-users CSV export, user management
(/api/auth/admin/*), and manual session entry/edit + admin stop/fix of a running session
(needs new backend endpoints).
Prerequisites
-
Node + Corepack (Yarn 4 is pinned in the repo).
-
From the repo root, install everything once:
yarn install
Run it
Two processes: the API on :3000 and the admin SPA on :5174.
1. Backend API (:3000)
From the repo root:
yarn workspace @solelog/api db:migrate # apply migrations (creates ./data/app.db on first run)
yarn workspace @solelog/api db:seed # idempotent: seeds reference activities + dev logins
yarn workspace @solelog/api start # Hono server on http://localhost:3000
db:seed creates two dev logins (dev-only — skipped when NODE_ENV=production):
admin admin@solelog.local / werkplaats-admin and worker
worker@solelog.local / werkplaats123. Only the admin can use this app.
The API's default WEB_ORIGINS already allows http://localhost:5174 (this app's dev
origin), so cross-origin sign-in and requests work out of the box. Override with
CORS_ORIGINS for other origins (e.g. a LAN IP).
2. Admin SPA (:5174)
From the repo root:
yarn workspace @solelog/admin dev # Vite dev server on http://localhost:5174
Open http://localhost:5174 and sign in as the admin. The API base URL comes from
VITE_API_URL (default http://localhost:3000).
Scripts
yarn workspace @solelog/admin dev # dev server (:5174, LAN-exposed)
yarn workspace @solelog/admin build # tsc -b && vite build → dist/
yarn workspace @solelog/admin preview # preview the production build
yarn workspace @solelog/admin typecheck # tsc -b
yarn workspace @solelog/admin test # vitest run
Architecture
- Auth.
lib/api.ts+lib/auth-storage.tsare copied from the worker: sign-in reads the bearer token from theset-auth-tokenresponse header intolocalStorage, andapiFetch<T>attachesAuthorization: Bearer <token>to every request.auth/AuthContext.tsxadds the admin gate (re-fetch/api/me, reject non-admins). - Live data.
api/admin-sessions.tsuseActiveSessions()uses react-query withrefetchInterval: 5000; each card computes elapsed time from the serverstart_timewith a 1 s client tick (lib/elapsed.tsformatTime). - Activities.
api/activities.tshooks (useActivities+ create/update/delete) invalidate the['activities']query on every mutation. - Shared contracts. Request/response shapes are zod schemas in
@solelog/shared, imported here for a typed client.