feat: 복습 화면 (오답노트/즐겨찾기/최근 푼 문제) - #8
Conversation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…failures The prescribed fix (moving setLoading(true) into the effect/call sites) still tripped react-hooks/set-state-in-effect, since the rule flags any function invoked from useEffect that transitively calls a state setter anywhere in its body, regardless of await position. Restructured to derive `loading` from a loadedTab comparison instead of an effect-driven boolean, and moved the fetch's state application into an inline .then() callback (the pattern React's own docs use), which the rule doesn't trace. Also logs the actual error via console.error on tab-load failure instead of silently showing an empty list.
|
Warning Review limit reached
Next review available in: 49 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: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough오답노트·즐겨찾기·최근 풀이를 제공하는 Changes복습 화면 구현
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant ReviewPage
participant ProgressRepository
participant QuestionRepository
participant ReviewList
participant PracticeSession
ReviewPage->>ProgressRepository: 탭 데이터 조회
ReviewPage->>QuestionRepository: 질문과 이론 맵 조회
QuestionRepository-->>ReviewPage: 복원된 질문 목록 반환
ReviewPage->>ReviewList: 목록 및 동작 전달
ReviewList->>PracticeSession: 전체 다시 풀기 실행
PracticeSession-->>ReviewPage: 복습 완료 결과 전달
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 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: 4
🧹 Nitpick comments (1)
src/features/practice/PracticeSession.tsx (1)
23-23: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift기존 즐겨찾기 상태를 세션 초기값에 반영하세요.
복습 화면의 즐겨찾기 탭에서 재도전하더라도
favorited는 항상 빈 맵으로 시작하므로, 이미 저장된 문제에☆ 즐겨찾기가 표시됩니다. 저장소의 기존 즐겨찾기 ID를 초기 상태로 주입하거나 세션 시작 전에 조회해야 합니다.Also applies to: 109-111
🤖 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/features/practice/PracticeSession.tsx` at line 23, Initialize the favorited state in PracticeSession using the existing persisted favorite question IDs instead of always starting with an empty map. Load or derive those IDs before the session renders, map each ID to true, and preserve the current toggle behavior through setFavorited.
🤖 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/superpowers/plans/2026-07-31-review-screen.md`:
- Around line 927-933: Update the Task 5 code block in the self-review section
to match the current review page implementation: document derived loading state
and the request-token guard in loadTab, rather than a standalone loading state
and unguarded requests. Ensure the documented implementation preserves
protection against tab response races.
In `@src/app/review/page.tsx`:
- Around line 106-112: Update handleRemove so setQuestions runs only after the
relevant progressRepository removal succeeds. Do not swallow removal failures
and continue to the state update; preserve the existing tab-specific
removeWrongNote and removeFavorite behavior while keeping failed items in the
list.
In `@src/features/practice/PracticeSession.tsx`:
- Around line 62-67: Update toggleFavorite to support both states: when
favorited[current] is true, clear that entry and call
progressRepository.removeFavorite with question.questionId; otherwise preserve
the existing state update and progressRepository.addFavorite flow.
- Around line 62-67: Update toggleFavorite in
src/features/practice/PracticeSession.tsx#L62-L67 to call addFavorite when the
current question is not favorited and removeFavorite when it is, updating state
for both outcomes while preserving error handling. In
src/features/practice/QuestionCard.tsx#L37-L43, disable the button only while
the favorite operation is processing and provide an appropriate
remove/unfavorite label when the question is already favorited.
---
Nitpick comments:
In `@src/features/practice/PracticeSession.tsx`:
- Line 23: Initialize the favorited state in PracticeSession using the existing
persisted favorite question IDs instead of always starting with an empty map.
Load or derive those IDs before the session renders, map each ID to true, and
preserve the current toggle behavior through setFavorited.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a8315429-a937-49ee-8261-1c3d56858120
📒 Files selected for processing (14)
docs/superpowers/plans/2026-07-31-review-screen.mdsrc/app/page.tsxsrc/app/practice/page.tsxsrc/app/review/page.tsxsrc/features/practice/PracticeSession.tsxsrc/features/practice/QuestionCard.tsxsrc/features/review/ReviewList.tsxsrc/lib/recentlySolved.test.tssrc/lib/recentlySolved.tssrc/repositories/ProgressRepository.test.tssrc/repositories/ProgressRepository.tssrc/repositories/QuestionRepository.test.tssrc/repositories/QuestionRepository.tssrc/types/progress.ts
| function toggleFavorite() { | ||
| if (favorited[current]) return; | ||
| setFavorited((prev) => ({ ...prev, [current]: true })); | ||
| progressRepository | ||
| .addFavorite(question.questionId) | ||
| .catch((err) => console.error("addFavorite failed:", err)); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
toggleFavorite에 해제 경로가 없습니다.
이미 즐겨찾기된 질문은 즉시 반환하고 addFavorite만 호출합니다. ProgressRepository에 removeFavorite가 있으므로 현재 상태가 true이면 삭제하도록 연결해야 합니다.
🤖 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/features/practice/PracticeSession.tsx` around lines 62 - 67, Update
toggleFavorite to support both states: when favorited[current] is true, clear
that entry and call progressRepository.removeFavorite with question.questionId;
otherwise preserve the existing state update and progressRepository.addFavorite
flow.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
즐겨찾기 토글을 추가/삭제 모두 지원하도록 맞춰야 합니다.
현재 상태가 true이면 아무 동작도 하지 않고, UI도 버튼을 비활성화합니다. ProgressRepository.removeFavorite를 사용해 true 상태에서는 삭제하고, 버튼은 처리 중일 때만 비활성화하도록 변경하세요.
src/features/practice/PracticeSession.tsx#L62-L67:favorited상태에 따라addFavorite또는removeFavorite를 호출합니다.src/features/practice/QuestionCard.tsx#L37-L43:disabled조건을 저장 중 상태로 변경하고 해제 라벨을 제공합니다.
📍 Affects 2 files
src/features/practice/PracticeSession.tsx#L62-L67(this comment)src/features/practice/QuestionCard.tsx#L37-L43
🤖 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/features/practice/PracticeSession.tsx` around lines 62 - 67, Update
toggleFavorite in src/features/practice/PracticeSession.tsx#L62-L67 to call
addFavorite when the current question is not favorited and removeFavorite when
it is, updating state for both outcomes while preserving error handling. In
src/features/practice/QuestionCard.tsx#L37-L43, disable the button only while
the favorite operation is processing and provide an appropriate
remove/unfavorite label when the question is already favorited.
Codex 리뷰 지적(SDD 최종리뷰 minor7과 동일 지점, 두 리뷰어 독립 확인) — handleRemove가 기존 loadTab/effect의 latestRequestId 가드에 참여 안 해서, 삭제 완료 전 탭 전환하면 새 탭의 목록에 필터가 잘못 적용될 수 있었음
CodeRabbit 리뷰 지적(SDD 최종리뷰 ledger2와 동일 지점, 두 리뷰어 독립 확인) — removeWrongNote/removeFavorite 실패를 .catch로 삼키고도 무조건 목록에서 필터링하던 것을 실패 시 조기 반환하도록 수정
요약
ProgressRepository에getWrongNotes/getFavorites/removeWrongNote/removeFavorite추가(기존 시그니처는 무변경, 추가만)QuestionRepository.getTheoryMap()추가 —practice/page.tsx가 theory_map.json 직접 fetch하던 것도 같이 해소(이전 최종리뷰 이월 항목)최종 리뷰에서 발견·수정한 것
npm run lint가 이 브랜치에서 처음으로 실패(react-hooks/set-state-in-effect) — 계획의 검증 스텝에 lint가 빠져있던 게 원인. loading을 파생값으로 바꾸는 리팩터로 해소console.error추가이월(비차단, 기술부채로 기록)
WrongNote/Favorite타입이db.ts에 익명 인라인으로 중복정의 — 다음에 Repository 건드릴 때 정리테스트
npx vitest run51/51 통과,npm run lint0 에러,npx tsc --noEmit클린,npm run build클린 —/,/practice,/review라우트 정상참고문서
docs/superpowers/plans/2026-07-31-review-screen.mdSummary by CodeRabbit
새로운 기능
개선 사항