124 Commits

Author SHA1 Message Date
CC Worker
66f35b8ae4 fix(exam): compact top bar, collapsible guide panel
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Top bar reduced to single-line height: Back becomes an icon button, caption
line removed (detail lives in the guide), Save button size=small. Guide
panel defaults collapsed and toggles via a ? icon button at bottom-right
so it doesn't occupy permanent canvas real estate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 13:37:47 +00:00
CC Worker
fe5dbe7fa8 feat(exam): doc-view camera constraints and sidebar layout
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Replaces infinite-canvas free-pan with a constrained vertical-scroll doc
view: tldraw setCameraOptions with behavior='contain', fit-x-100, and top
origin so the PDF never drifts side-to-side. Layout restructured from
floating overlays to flex column (top bar + sidebar/canvas row). Tool
panel is now a left sidebar, guide panel overlays canvas bottom-right.

PAGE_START_X changed from 260 → 0 so pages are flush left; camera
applyDocViewConstraints() called incrementally as pages stream in and
with resetZoom() once all pages are loaded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:36:21 +00:00
CC Worker
15a519748d fix(exam): keep region shapes overlaid on PDF in setup canvas
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Three z-order fixes in ExamTemplateSetupPage:

1. loadShapes: early-return before deletion when models is empty, so
   seed guide shapes aren't wiped for a fresh template that has no
   saved regions yet.

2. Incremental PDF loading (onPageReady): replace per-page sendToBack
   (unreliable when all shapes are moving — reorderToBack no-ops) with
   bringToFront on existing domain shapes after each page is added.

3. Final load sequence: call bringDomainShapesToFront after syncPdfPages
   + loadShapes to guarantee correct z-order regardless of how tldraw's
   fractional indexer placed newly created shapes. Also called from
   onMount for the same reason.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 10:12:16 +00:00
CC Worker
3389fdcb5b feat(exam): S4-11 marking flow, results table, CSV, ResultsWidget
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
- /exam-marker/:batchId/mark — ExamMarkingPage: student queue, per-part mark entry, upsert marks
- /exam-marker/:batchId/results — ExamResultsPage: results table with absent rows, CSV download
- ResultsWidget on ClassDetailPage: last batch summary, class average, absent count, batch creation
- New types: MarkingBatch, StudentSubmission, BatchQueueResponse, BatchResultsResponse, MarkUpsertPayload
- New repo methods: createBatch, listBatches, getBatchQueue, getBatchResults, getBatchCsv, upsertMark

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 04:35:34 +00:00
CC Worker
b3f71c5749 Merge S4-10: mark scheme editor + SpecPoint picker
- Add /exam-marker/:templateId/marks route with MarkSchemePage
- Per-Part mark scheme editor: points/levels/parts/checklist/free forms
- SpecPoint picker via GET /api/exam/specs/{spec_code}/points (falls back to manual spec_ref when endpoint 404s)
- Manual neo4j-sync button; ASSESSES edge verified in cc.public.exams
- Edit marks button on each template card in dashboard
- Merge-resolved: AppRoutes, index.ts, exam.types.ts, ExamDashboardPage (kept grouped UI + added Edit marks button)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 04:30:41 +00:00
3eac792ced feat(exam-setup): UX polish — icons, dark/light palette tokens, multi-page boundary hint 2026-06-07 05:10:11 +01:00
CC Worker
8e8a345e61 fix: incremental PDF page rendering for exam setup backdrop
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Rendering a 36-page AQA exam PDF sequentially created 36 large canvas
elements, causing memory pressure and keeping pdfStatus='loading' for
60–120s in headless Chrome. Two changes:

1. pdfLoader.ts: reuse a single canvas (reduces peak memory from ~120MB
   to ~4MB) and fire onPageReady callback after each page so callers can
   stream pages to the canvas as they render.

2. ExamTemplateSetupPage.tsx: use the callback to add each PDF page
   shape to the tldraw canvas the moment it renders, making the first
   page visible within a few seconds rather than after all pages load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 03:35:09 +00:00
aa2f35e467 feat(exam): render template PDFs behind setup canvas 2026-06-07 03:56:09 +01:00
CC Worker
61a189a7a2 fix: tldraw user prefs colorScheme and indicator method for shape utils
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
- updateUserPreferences: isDarkMode → colorScheme ('dark'|'light') per
  tldraw 3.6.1 TLUserPreferences type (isDarkMode is read-only computed)
- BaseBoxShapeUtil subclasses: add required indicator() method returning
  bounding rect; fixes non-abstract class missing abstract member error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 02:30:57 +00:00
CC Worker
ab6f0b09d7 fix: remove duplicate bindingUtils causing tldraw arrow double-registration
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Tldraw 3.6.1 Tldraw component already registers defaultBindingUtils
internally; passing them explicitly via the bindingUtils prop caused
"Binding type 'arrow' is defined more than once" runtime crash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 02:21:32 +00:00
CC Worker
16ae3aa089 fix(exam): setup toolbar crash — MUI Button color 'default' is invalid in v5
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Select + Furniture tool buttons used color='default', which MUI v5 resolves to
theme.palette.default (undefined) -> TypeError reading 'main'/'dark' at render,
tripping the ErrorBoundary ('Template setup canvas crashed'). Use 'inherit'.

Caught by live browser-verify t_11f5a049; model-level tests never rendered the toolbar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 01:03:08 +00:00
dea3275f23 [verified] Add exam template setup canvas 2026-06-07 01:27:44 +01:00
1ab8aab43c feat(exam): add mark scheme editor 2026-06-07 00:34:56 +01:00
fdbc19cf0d feat(exam): version templates on dashboard 2026-06-07 00:33:06 +01:00
CC Worker
29554ebdbd feat(exam): Assessment dashboard + /exam-marker route; remove old CCExamMarker (S4-8)
- New examRepository (R2.1 seam): the only module talking to /api/exam (Supabase
  JWT → Bearer, axios to API_BASE). list/get/create/archive templates.
- ExamDashboardPage (/exam-marker): lists institute templates, create dialog,
  archive; cards link to setup (S4-9). Wrapped in ErrorBoundary (R6.4).
- exam.types.ts mirrors the API contract.
- Dashboard 'Exam Marker' quick action (top-level discovery, R1.3/R6.1).
  Note: the in-canvas TeacherNavigation is unsuitable for a nav section (it's
  the worker prev/next tab bar) — flagged; used the dashboard entry instead.
- R1.1 removal: deleted src/pages/tldraw/CCExamMarker/ (old 3-PDF viewer) and
  the now-dead CCExamMarkerPanel + its wiring in CCPanel/BasePanel (examMarkerProps
  was only ever passed by the deleted page).
- Fixed pre-existing broken AppRoutes test (missing TimetableListPage mock export).

Build green (vite); AppRoutes route tests pass; typecheck clean for new files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 19:47:02 +00:00
CC Worker
313ab724b8 fix(my-classes): add selectedInstituteId to fetch dependency, silence unhandled rejection
Re-fetch classes when NeoInstitute context changes. Catch fetchMyClasses rejection with
logger.warn so unhandled promise rejections don't break the component boundary silently.
Use CircularProgress (MUI) for loading skeleton.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 23:28:26 +00:00
CC Worker
ee7d7f7cac fix(timetable): fall through to empty state on fetch error — endpoint not yet in API
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
GET /database/timetable/timetables returns 404 (endpoint not implemented). Treat any
fetch error as empty state so the page renders gracefully rather than showing error UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 22:33:41 +00:00
CC Worker
0dd18c4fd4 fix(timetable): use fetchTimetables instead of fetchMyTimetables — service stub unimplemented
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
timetableOnlyService.getMyTimetables is referenced but never defined; calling it throws
'is not a function' at runtime. fetchTimetables calls the implemented listTimetables endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 22:15:58 +00:00
CC Worker
5869c741d7 fix(routing): add TimetableListPage for /timetable — detail view required :timetableId
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Bare /timetable routed to TimetablePage which called useParams<{timetableId}>() and
immediately hit !currentTimetable → "Error Loading Timetable". New TimetableListPage
uses fetchMyTimetables() from timetableStore. AppRoutes now: /timetable →
TimetableListPage, /timetable/:timetableId → TimetablePage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 21:36:57 +00:00
CC Worker
5b6e461706 fix(canvas): separate store lifecycle from snapshot lifecycle — one store per user session prevents disposed-store crash
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
Root cause: disposing store while React's async state update (storeReady=false) hadn't
unmounted Tldraw yet caused tldraw's reactive signals to read currentPageId on a disposed store.

Fix: Effect 1 creates store once per user.id (never recreated on node navigation).
     Effect 2 loads/reloads snapshots when context.node changes, store stays alive.
     Store is only disposed when user changes or component unmounts — after setStoreReady(false)
     has had time to unmount Tldraw cleanly via React's synchronous cleanup.
2026-06-01 06:25:15 +00:00
CC Worker
53adc74a1c fix(canvas): defer store disposal until next store is ready — prevent tldraw reactive signals reading disposed store during async React unmount
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 06:18:24 +00:00
CC Worker
9a7cc86a75 fix(canvas): bypass localStoreService singleton — create store directly in effect to eliminate disposed-store reuse
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 06:16:07 +00:00
CC Worker
6cba932146 fix(canvas): move ensureStoreIsUsable() to AFTER snapshot load — loadSnapshot() overwrites TLINSTANCE before it could be pre-initialized
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 06:13:49 +00:00
CC Worker
ba829be8e9 fix(canvas): call ensureStoreIsUsable() before tldraw mount — pre-initializes TLINSTANCE/page/camera records in empty store preventing currentPageId crash
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 06:10:11 +00:00
CC Worker
9f58917c39 fix(canvas): sanitize snapshot session.currentPageId before loadSnapshot — stale snapshots with missing pages caused currentPageId crash
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
- Pre-load: if session.currentPageId not in snapshot pages, reset to first available page
- Post-load: if store instance.currentPageId still invalid, clear store for fresh start
- On loadSnapshot error: clear store instead of silently failing with corrupt state
- Root cause: teacher1 had a saved snapshot with currentPageId pointing to a deleted page
2026-06-01 06:02:19 +00:00
CC Worker
a375fbe37f fix(canvas): clear localStoreService singleton on unmount — disposed store was returned to next mount causing currentPageId crash
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 03:04:29 +00:00
CC Worker
38ca23dc3e fix(theme): add CssBaseline — MUI dark theme on Android was white text on white body background
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 02:52:41 +00:00
CC Worker
8fe8edb341 fix(auth): RequireAuth must use Outlet not children — React Router v6 requires Route guards to be Route elements
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 02:45:20 +00:00
CC Worker
143fff6414 merge: R4 error boundaries — ErrorBoundary wraps Tldraw canvas (resolve singlePlayerPage.tsx conflict with R3 state machine refactor)
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled
2026-06-01 02:40:28 +00:00
CC Worker
c216df8021 merge: R4 auth reliability — PKCE race fix + RequireAuth loading skeleton 2026-06-01 02:38:54 +00:00
CC Worker
f7bb84f9b8 merge: R4 TypeScript hardening H1-H6 — reduce errors 177→152 (resolve cc-graph-shapes/CCGraphNavPanel conflicts with R3) 2026-06-01 02:38:50 +00:00
CC Worker
cbff4deef2 merge: R3 TypeScript fixes — cc-graph-shapes duplicates, CCGraphNavPanel, snapshotService, App.tsx simplification 2026-06-01 02:37:21 +00:00
CC Worker
85ecae7147 merge: R2 E2E canvas tests — 3 Playwright specs with beforeAll skip guards 2026-06-01 02:37:15 +00:00
CC Worker
6951bc1700 merge: R2 remove Tailwind — drop build pipeline, add tailwind-compat.css shim 2026-06-01 02:37:15 +00:00
CC Worker
e6f6bd5c3a merge: R2 tldraw token bridge + DarkModeSync — bridge --cc-* to tldraw --color-* layer 2026-06-01 02:37:10 +00:00
CC Worker
765573163d feat(ts): R4 TypeScript hardening H1-H6 — reduce errors 177→152
H1: CCGraphNavPanel — useMemo import + LogCategory fix
H2: CCTimetableLessonNodeShapeUtil — props type alignment (cc-graph-props.ts)
H3: cc-graph-shapes — add missing CCTimetableLessonNode* import (was never imported)
H4: CCNodeSnapshotPanel — RestartAlt import from @mui/icons-material
H5: CCExamMarkerPanel + CCFilesPanelEnhanced — BlobPart cast + webkitdirectory @ts-ignore
H6: TranscriptionManager — setTranscriptionCallback interface fix
Plus: CCExportPdfButton BlobPart cast, SimpleUploadTest icon imports, graph-sidebar LogCategory

tsc before: 177 (master)
tsc after:  152 (reduction of 25 errors, well below 160 acceptable threshold)
2026-06-01 02:29:38 +00:00
CC Worker
1505adb154 feat(ux): R4 error boundaries — wrap Tldraw in ErrorBoundary (J1)
- Added import for ErrorBoundary from src/components/ErrorBoundary.tsx
- Wrapped {store && <Tldraw>} block in ErrorBoundary with 'Canvas failed to load — Reload' fallback
- ErrorBoundary.tsx already existed with full error/reload UI
- Timetable pages (J2) already have loading states via timetableStore loading flags
- tsc: 177 (master baseline) → 173 on this branch (no regression)
2026-06-01 02:20:34 +00:00
CC Worker
ade0be97f6 feat(auth): R4 auth reliability — fix PKCE race condition + RequireAuth loading skeleton 2026-06-01 02:16:05 +00:00
CC Worker
96db086ecb fix: resolve duplicate identifier in cc-graph-shapes, useMemo import in CCGraphNavPanel 2026-06-01 01:36:37 +00:00
CC Worker
6610abbd72 fix: resolve duplicate identifier in cc-graph-shapes 2026-06-01 01:35:11 +00:00
CC Worker
489c2208c5 fix: add DarkModeSync to propagate tldraw dark mode to document root
tldraw v3.6 sets tl-theme__dark class on .tl-container, not data-color-mode
on document.documentElement. DarkModeSync lives inside TLDrawProvider and
mirrors the active color scheme to [data-color-mode] on <html>, activating
--cc-* token overrides in cc-design-system.css globally.
2026-06-01 00:47:24 +00:00
CC Worker
3db843a6f9 test: add Playwright E2E tests for canvas mount, node navigation, transcription toggle 2026-05-31 23:50:35 +00:00
CC Worker
79e7d4df9c test: add Playwright E2E tests for canvas mount, node navigation, transcription
Three spec files with beforeAll skip guards:
- Skip if VITE_TEST_TEACHER_EMAIL/PASSWORD not set
- Skip if dev server at 192.168.0.251:13000 unreachable
Tests exit 0 (3 skipped) when env is unconfigured.
Requires: live dev server + real teacher credentials to run live.
2026-05-31 23:49:41 +00:00
CC Worker
a0afbc90f5 feat: replace last hardcoded hex colors (#666, #333) with --cc-* tokens in cc-youtube-embed-styles 2026-05-31 23:17:55 +00:00
CC Worker
57429f3a75 chore: remove Tailwind CSS build pipeline; replace with tailwind-compat.css shim
244 utility classes across 8 files (timetable pages, Modal, CCShapesPanel).
Rather than blind inline conversion, replace @tailwind directives with a
self-contained 230-line CSS shim covering all classes actually used.
Build passes. Shim entries can be converted to --cc-* tokens incrementally.
2026-05-31 23:09:08 +00:00
CC Worker
01a8a59349 feat: bridge --cc-* tokens to tldraw --color-* variable layer; fix first-render theme fallback 2026-05-31 22:56:31 +00:00
CC Worker
33b9278085 merge: replace console.log with logger in CCLiveTranscriptionShapeUtil (P3b) 2026-05-31 22:25:07 +00:00
CC Worker
9196af12f8 merge: static shape styles to CSS classes + pointer-events fix (P3a) — resolve CCBaseShapeUtil conflict, update panel.css shape-title to --cc-text-inverse 2026-05-31 22:24:46 +00:00
CC Worker
f6e2ab63dd merge: hoist ThemeProvider to App.tsx root (P2b) — resolve BasePanel conflict by keeping MUI-free version 2026-05-31 22:23:21 +00:00
CC Worker
f1c1a72f44 merge: remove MUI/styled-components from BasePanel — cc- CSS classes (P2a) 2026-05-31 22:22:31 +00:00