feat(history): mirror detail page + rich day cards + review hardening#64
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…r/$id - DayDetailCard renders mirror reflections as rich rows: context badge, time, story-reframe headline, highlight-phrase pull quote, transcript snippet, plus a "Show more →" link for backend-backed entries - New MirrorDetailSheet at /mirror/$id shows the full mirror: Story reframe, Validation, Inferred meaning, Transcript, with Confirm / Forget actions for pending reviews; sidebar carries date, time, context, status, and mood tags - Route lives at /mirror/$id (not /history/mirror/$id) because TanStack's matcher picks /history/$tab over the more specific /history/mirror/$id when both sit under _app/history - Distinguish "Loading…" (captures slice not yet hydrated) from "couldn't find that mirror" (genuinely missing) - backend-snapshot: validation flows from MirrorEntryRow into the snapshot (optional on the type so incremental captures.patch writes are unaffected)
9909ce6 to
abcafdd
Compare
"Mirror" is the agent name; "reflection" is the student-facing capture. The list heading is user-facing copy, so match the noun the user owns.
…t status line - Shift all seed timestamps forward 182 days so demo data lands in the 2026-04 to 2026-05 window (was 2025-07 to 2025-11). Demo-a's 8 reflections are then re-spread across May 18–30 so the calendar's default 'this week' view shows reflection markers on multiple days - Day detail card: drop the literal `status: confirmed` text — review state is already implicit (Confirm/Forget appear only when pending), and the detail page surfaces the status badge explicitly
- Each reflection card is now itself a link to /mirror/$id (when backend-backed); no separate "Show more" button - Drop the per-card "Reflection" label — the section heading already says "Reflections", repeating it on every row is noise - Drop Confirm/Forget buttons + status text from the card; reviews live on the detail page where there's room for the full context - Generic non-ask captures keep their text-only render with the kind label removed for the same reason
…hite when selected DayDetailCard: - Remove CaptureActions component, reviewCapture / retryCaptureSync handlers, patchReviewCapture, syncLine helper, and their state. All unused now that the day card is a passive list of clickable cards. CalendarPane: - Mood Smile icon flips to text-white when its day cell is selected, matching the reflection/event icons that already do.
resetSeedStudent ran unqualified DELETEs and relied on the RLS policy to scope them to the current student. The seed CLI typically runs as neondb_owner which has BYPASSRLS, so those DELETEs wiped every student's rows on each iteration — only the last student's seed survived. Same problem made the 'existing count' check see other students' rows and skip them on subsequent runs. Fix: filter every reset DELETE by studentId, and filter the existing count query the same way. Correct under both RLS-enforced and BYPASSRLS roles.
Replace the single lucide Smile icon (color-tinted per emotion) with the existing 3D-style shape art from `mood-shapes.ts`: - Calendar cell mood markers render the shape image (sphere / teardrop / octahedron / cube / torus / capsule / egg / halfcube / disk) - Day-detail card "Moods" list shows the shape next to the emotion name in place of the small colored dot Drop the local MOOD_HEX color maps in both files — the shape SVG owns its own palette via EMOTIONS, so duplicated hex constants were stale and prone to drift.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/history/mirror/$idshows the full mirror reflection (story reframe, validation, inferred meaning, transcript) with Confirm / Forget review actionsDayDetailCardnow renders mirrors as rich cards (context badge, headline, highlight, transcript snippet) with a "Show more" affordance opening the detail pageReviewActions, sharedCaptures.acquireReviewlock prevents concurrent submissions across surfaces, stale-status guard skips patches when the slice has moved past the in-flight callrefreshSnapshot, then falls back to a newloadMirrorEntryserver fn so forgotten captures remain reachable by URL; distinct loading vs not-found UIDayDetailCardandMirrorDetailSheet:mirror-review.ts—applyMirrorReview()+CONTEXT_LABELmirror-review-types.ts— shared engine-state contractformat-date.ts—formatLongDate/formatTime(plustoEntryDateexported frombackend-snapshot)use-mirror-engine-state.ts— centralizes the engine castuse-overlay-body-class.ts— ref-countedbody.has-overlay(replaces 6 duplicateduseEffectcopies; fixes a navigation-time class-stomp race)usePageEscapenow stops immediate propagation so stacked sheets don't both fire;surfaceFromPathnameno-ops on/history/mirror/*so the engine doesn't open History behind the detail pagebackend-snapshot.ts:validationflows fromMirrorEntryRowinto the capture (optional on the wire type to match incremental patches);updateReflectionReviewreturn now carriesvalidationandapplyMirrorReviewwrites it throughvalidationadded toConnectorContextPayload.mirrorand rendered informatNewReflectionBlockso Connector/Cartographer see the same field the user doesPageSurfaceshapeTests
test/components/student-space/sheets/mirror-detail-sheet.test.tsx(10/10 passing): not-found, NaN guard, loading state, capture-found rendering, Confirm patch flow, capture-id fallback, error alert, refresh-failure swallow, post-mount hydration, body-class lifecycleTestCapturewithvalidation?/reframe?and added two new cases for theMirrorRowShow-more link visibilitybackend-snapshotmapping test now assertsvalidationround-tripsVerification
pnpm typecheck: PASSpnpm lint: PASS (warnings only, all pre-existing)vitest: new + extended tests pass; 4 pre-existing date-drift failures inhistory-sheet.test.tsx(TODAY = '2026-05-22'vs system clock2026-05-24) are unchanged frommainand unrelated to this branchTest plan
/history/mirror/$idopens with sidebar meta (date, time, context, status, moods) and full detail (Story reframe / Validation / Inferred meaning / Transcript)/history/mirror/$id→ confirm the entry is still reachable (vialoadMirrorEntryfallback) instead of showing "We couldn't find that mirror"/history/mirror/99999(non-existent id) → confirm clean "couldn't find" copy, no console errors/history/mirror/abc(non-numeric id) → confirm same not-found copy/history/mirror/$id→ confirm "Loading…" copy briefly, then the capture detail/history(not/) and the engine History overlay does not flash open