Skip to content

feat(journal): W1 「我的手帐」 — /me/journal page for logged-in users#51

Open
emptylower wants to merge 13 commits into
mainfrom
claude/pensive-benz-fc2325
Open

feat(journal): W1 「我的手帐」 — /me/journal page for logged-in users#51
emptylower wants to merge 13 commits into
mainfrom
claude/pensive-benz-fc2325

Conversation

@emptylower

Copy link
Copy Markdown
Owner

Summary

W1 of the 6-week MVP: new private route /me/journal that renders a logged-in user's personal "pilgrimage handbook" — cover + 7 data-viz sections + 4 explore cards + LBS floating button, in a paper-journal visual style.

  • New lib/journal/ domain following the existing 3-layer pattern (api factory → handler → repo Prisma + Memory double)
  • 6 reusable visual primitives (PaperCard, RedSeal, WashiTape, InkDivider, StitchedBorder, PageFoldCorner) under app/(authed)/me/journal/primitives/
  • 10 section components composed into a server-rendered page with auth gate
  • 43 unit tests across vitest node + jsdom projects, all green

Out of scope (W1 NOT-doing list)

Per the W1 plan and product charter §9, these are explicitly deferred:

  • Default post-login route is unchanged (/me/journal is a new route, not a redirect target — W4 handles route migration)
  • recentNotes always returns [] (notes write/read system is W2+)
  • travelModeBreakdown is a static stub (real per-user calculation is W2+)
  • Favorite tables are NOT merged (W2)
  • No journal public/private toggle (W5/W6)

Charter compliance (docs/product-charter.md)

  • §3 五条设计原则: respected
  • §4 词汇表: page text uses only allowed vocabulary (no "朱印 / 誊抄 / 想去笺 / 路书 / 番剧")
  • §5 IA: 手帐 is the destination, not a Nav tab
  • §8 视觉系统: paper / 朱印 / washi / 缝纫边 all present via primitives
  • §10 反 Feature: LBS in floating button (not Nav), no 作品 Tab, no 手帐 Tab

One plan deviation worth flagging

Task 4's Prisma repo uses state: 'checked_in' instead of the plan's 'visited'. The valid enum in lib/userPointState/repo.ts is 'want_to_go' | 'planned' | 'checked_in'; without the correction, every user's check-in count would have been 0 in production.

Follow-ups for W2 (non-blocking)

  • listCheckins has no take limit; heavy users force large fetches + in-memory haversine on every page hit.
  • countDistinctWorksVisited uses distinct: ['pointId'] + JS Set; a groupBy({ by: ['bangumiId'] }) would be cheaper.
  • unlockedAt = now is computed at view time; AchievementWall tooltip will show "unlocked today" for all unlocked badges until W2 introduces persistent unlock timestamps.

Test plan

  • npx vitest run tests/journal/ → 43 passed (21 node + 22 jsdom)
  • npx tsc -p tsconfig.app.json --noEmit → no new journal type errors
  • Manual QA on a temp Worker preview URL: unauth redirect, new-user empty render, data-rich user render, charter §10 anti-feature check, visual match against docs/wireframes/owner-journal-target.png

🤖 Generated with Claude Code

emptylower and others added 13 commits May 13, 2026 21:11
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ames

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying seichigo with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7217ba8
Status:🚫  Build failed.

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant