Conversation
Mascot 的 4 階段進化(蛋→貓頭鷹,700 XP 封頂)換成星際塵埃到黑洞的 12 階段 宇宙演化史,拉長成長曲線到 7000 XP 做長期目標,取代原本規劃另開一套等級稱號 系統的做法。Stats 頁新增 GitHub 風格的月曆熱力圖呈現近半年做題量,色階已用 dataviz skill 的 validate_palette.js 驗證過。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
未登入時「個人資料」分頁改成獨立登入頁,navbar 文字動態顯示「登入」; 登入後可上傳大頭貼並拖曳調整顯示位置、編輯單欄名稱,個人資料頁改成卡片式排版, 新增「查看成長史」可展開列表預覽全部 12 個吉祥物成長階段,登出按鈕改用實心描邊樣式。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 34 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThe application migrates from Vite to Next.js, adds Clerk authentication and account management, introduces Prisma/PostgreSQL progress persistence with synchronized APIs, and expands XP progression and activity visualization with growth history and a 26-week heatmap. ChangesNext.js, Clerk, and cloud progress platform
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Visitor
participant Clerk
participant App
participant ProgressAPI
participant Prisma
Visitor->>Clerk: sign in
Clerk-->>App: provide authenticated user
App->>ProgressAPI: load or migrate progress
ProgressAPI->>Prisma: read or persist user progress
Prisma-->>ProgressAPI: return progress records
ProgressAPI-->>App: return synchronized progress
App-->>Visitor: render account and learning state
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/roadmap.md`:
- Around line 133-134: Update the roadmap entry for “全真模考” to state that the
navbar placeholder/disabled tab was removed, aligning it with the earlier
roadmap note that no UI placeholder remains; preserve the existing
prioritization and user-demand wording.
In `@src/components/AccountHeader.tsx`:
- Around line 47-50: Add try/catch handling to the Clerk mutation flows in
saveMetadata and saveName, including their callers confirmReposition and
handleAvatarFile as needed, so update failures are caught rather than escaping
event handlers and the avatar UI remains synchronized. Reuse the existing
error-handling or user-feedback pattern in AccountHeader for both metadata and
name mutations.
- Line 1: Update AccountHeader’s saveMetadata, handleAvatarFile,
confirmReposition, and saveName flows to catch rejected Clerk requests, record
an appropriate error state, and preserve the current edit/reposition state when
persistence fails. Ensure success-only UI transitions occur after the awaited
operations complete, including avatar upload and position persistence.
- Around line 102-112: Update saveName to catch user.update failures, preserve
the editing state, and set an appropriate user-visible error message or error
state while still clearing savingName in finally. Reuse the component’s existing
error-display mechanism if available.
- Around line 52-64: Update handleAvatarFile to catch failures from
user.setProfileImage or saveMetadata and display the established avatar-upload
error feedback, while retaining the finally block so uploading is always reset
and allowing successful uploads to keep their current behavior.
- Around line 76-79: Update confirmReposition so it awaits saveMetadata(pos)
before calling setIsRepositioning(false), and ensure a rejected save leaves
repositioning mode open without clearing the unsaved avatar position.
- Line 107: Update the first-name edit flow in AccountHeader to pass only the
trimmed firstName to user.update, omitting lastName so an existing surname is
preserved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 75a69de2-d867-4ebe-8666-cc3981d4ec46
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (16)
.env.example.gitignoredocs/roadmap.mdpackage.jsonsrc/components/AccountHeader.tsxsrc/components/GrowthHistory.tsxsrc/components/Icons.tsxsrc/components/Mascot.tsxsrc/components/Navbar.tsxsrc/index.csssrc/main.tsxsrc/screens/Notes.tsxsrc/screens/Profile.tsxsrc/screens/Quiz.tsxsrc/screens/Stats.tsxsrc/vite-env.d.ts
💤 Files with no reviewable changes (1)
- src/screens/Notes.tsx
- 框架從 Vite 換成 Next.js(App Router),進度儲存改走 PostgreSQL(Supabase)透過 Prisma, 已登入時以資料庫為主、未登入沿用 localStorage - 新增 DELETE /api/account:刪除帳號同時清除資料庫資料與 Clerk 帳號 - 個人資料頁移除進度備份/匯出區塊,登出按鈕旁新增刪除帳號按鈕 - 修正學習熱力圖橫向捲軸只在窄螢幕出現(含 CSS source order 修正) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Vercel 每次 deploy 都是全新環境重新 install,沒有這一步的話 next build 會因為 找不到 @prisma/client 產出而失敗。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- confirmReposition 改成存檔成功才關閉調整模式,失敗時保留未存的位置 - handleAvatarFile、saveName 補上 catch,Clerk 請求失敗時提示使用者 - saveName 移除多餘的 lastName: '',避免改名時把既有姓氏清空 - roadmap.md 更新全真模考項目,對齊「navbar 佔位分頁已移除」的說明 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/roadmap.md (1)
73-79: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUpdate the Clerk setup notes for Next.js.
These lines still instruct readers to use the removed Vite integration,
main.tsx, andVITE_CLERK_PUBLISHABLE_KEY. The new setup uses Next.js andNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYas shown in.env.example; following this roadmap section can leave authentication unconfigured.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/roadmap.md` around lines 73 - 79, Update the Clerk setup notes in the roadmap to describe the current Next.js integration instead of the removed Vite setup: replace references to `@clerk/react`, main.tsx, and VITE_CLERK_PUBLISHABLE_KEY with the Next.js setup and NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY used in .env.example. Keep the existing authentication behavior notes unchanged.
🧹 Nitpick comments (3)
src/app/api/progress/answer/route.ts (1)
24-55: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winWrap the multi-step mutation in a transaction for atomicity. The
wrongEntry,dailyStat, andchapterStatwrites run as independent awaits. If a later write fails, the earlier ones are already committed and no response is returned, leaving the server-authoritative progress inconsistent with the client's optimistic state until the next full reload.prisma.$transaction([...])(or the interactive form) keeps the answer update atomic.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/api/progress/answer/route.ts` around lines 24 - 55, Wrap the wrongEntry mutation logic, dailyStat upsert, and conditional chapterStat upsert in a single Prisma transaction using prisma.$transaction. Ensure all three writes use the transaction client and preserve the existing branching and update values so either every answer-progress mutation commits or none does.tsconfig.json (1)
16-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSet
jsxtopreserveintsconfig.json:16Next.js manages this value and will resetreact-jsxback topreserve, so keeping it here just creates config churn.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tsconfig.json` at line 16, Update the jsx compiler option in tsconfig.json from react-jsx to preserve, allowing Next.js to manage the setting and preventing configuration churn.src/app/api/progress/migrate-local/route.ts (1)
15-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winEliminate the redundant
loadFullProgresscall.When
!isNew,loadFullProgressis called twice — once forisNew(line 15) and again forprogress(line 17). Destructure both from a single call.♻️ Proposed refactor
- const { isNew } = await loadFullProgress(userId) + const { progress, isNew } = await loadFullProgress(userId) if (!isNew) { - const current = await loadFullProgress(userId) - return NextResponse.json({ progress: current.progress }) + return NextResponse.json({ progress }) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/api/progress/migrate-local/route.ts` around lines 15 - 19, Update the migrate-local route’s loadFullProgress usage to call it once, destructuring both isNew and progress from the returned object. Use the destructured progress in the existing !isNew response while preserving the current behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/api/account/route.ts`:
- Around line 11-16: Update the account deletion flow around clerkClient and
client.users.deleteUser to delete the Clerk user before removing the local
Prisma user record. Ensure errors from either deletion propagate and prevent the
success response, so return NextResponse.json({ ok: true }) only after both
operations complete.
In `@src/app/api/progress/finish-review/route.ts`:
- Around line 18-31: Validate xpEarned and today immediately after parsing
FinishReviewBody and before findUniqueOrThrow or any persistence: require
xpEarned to be a non-negative integer within the endpoint’s reasonable maximum,
and require today to match the YYYY-MM-DD format (reject invalid dates as well).
Return the route’s established client-error response for invalid input, while
preserving the existing streak and transaction flow for valid values.
In `@src/app/api/progress/migrate-local/route.ts`:
- Around line 15-52: Wrap the migration prisma.$transaction in a try/catch and
handle Prisma unique-constraint errors (P2002) by calling
loadFullProgress(userId) and returning the existing progress response. Preserve
the current migration flow for successful transactions and rethrow all other
errors; keep the existing !isNew early return unchanged.
In `@src/app/api/progress/save-toggle/route.ts`:
- Around line 18-23: Update the toggle logic around the existing
findUnique/delete/create operations to handle concurrent requests safely: catch
Prisma P2002 duplicate-create and P2025 missing-delete errors and return the
intended toggle response instead of allowing an unhandled 500, or replace the
check-then-act flow with an equivalent conflict-safe upsert/delete strategy.
---
Outside diff comments:
In `@docs/roadmap.md`:
- Around line 73-79: Update the Clerk setup notes in the roadmap to describe the
current Next.js integration instead of the removed Vite setup: replace
references to `@clerk/react`, main.tsx, and VITE_CLERK_PUBLISHABLE_KEY with the
Next.js setup and NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY used in .env.example. Keep
the existing authentication behavior notes unchanged.
---
Nitpick comments:
In `@src/app/api/progress/answer/route.ts`:
- Around line 24-55: Wrap the wrongEntry mutation logic, dailyStat upsert, and
conditional chapterStat upsert in a single Prisma transaction using
prisma.$transaction. Ensure all three writes use the transaction client and
preserve the existing branching and update values so either every
answer-progress mutation commits or none does.
In `@src/app/api/progress/migrate-local/route.ts`:
- Around line 15-19: Update the migrate-local route’s loadFullProgress usage to
call it once, destructuring both isNew and progress from the returned object.
Use the destructured progress in the existing !isNew response while preserving
the current behavior.
In `@tsconfig.json`:
- Line 16: Update the jsx compiler option in tsconfig.json from react-jsx to
preserve, allowing Next.js to manage the setting and preventing configuration
churn.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 65e07b8c-c847-4d97-a4e8-ee4765ef4044
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (34)
.env.example.gitignoredocs/roadmap.mdindex.htmlnext.config.tspackage.jsonprisma.config.tsprisma/migrations/20260711114101_init/migration.sqlprisma/migrations/migration_lock.tomlprisma/schema.prismasrc/App.tsxsrc/app/api/account/route.tssrc/app/api/progress/answer/route.tssrc/app/api/progress/finish-level/route.tssrc/app/api/progress/finish-review/route.tssrc/app/api/progress/migrate-local/route.tssrc/app/api/progress/route.tssrc/app/api/progress/save-toggle/route.tssrc/app/layout.tsxsrc/app/page.tsxsrc/components/AccountHeader.tsxsrc/components/Icons.tsxsrc/components/Navbar.tsxsrc/hooks/useProgress.tssrc/index.csssrc/lib/prisma.tssrc/lib/progressLogic.tssrc/lib/progressStore.tssrc/main.tsxsrc/proxy.tssrc/screens/Profile.tsxsrc/vite-env.d.tstsconfig.jsonvite.config.ts
💤 Files with no reviewable changes (4)
- index.html
- src/main.tsx
- vite.config.ts
- src/vite-env.d.ts
✅ Files skipped from review due to trivial changes (6)
- src/app/page.tsx
- prisma/migrations/migration_lock.toml
- prisma/migrations/20260711114101_init/migration.sql
- src/lib/prisma.ts
- .gitignore
- next.config.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/components/Navbar.tsx
- src/components/Icons.tsx
- src/components/AccountHeader.tsx
- src/index.css
- account: 先刪 Clerk 帳號再刪本地資料,避免刪除失敗時進度已清空但帳號還在 - finish-review: 驗證 xpEarned/today 輸入,避免不合法值直接寫入 - migrate-local: 合併重複查詢、處理併發搬遷撞到 unique constraint 的情況 - save-toggle: 處理併發 toggle 造成的 P2002/P2025 race condition - answer: 三個寫入操作包進同一個 transaction,避免部分寫入
Summary by CodeRabbit