fix: 관리자 코스 수강 상태 분기 반영#683
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughPR은 코스 수강 권한 상태 판별 로직을 중앙화하는 헬퍼 함수 체계를 도입하고, 세 개의 주요 컴포넌트(ClassDetailPage, ClassDetailSidebar, RoadmapTab)에서 기존 Changes코스 뷰어 상태 판별 헬퍼 시스템
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/types/api/course.types.ts (1)
47-52:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
src/types직접 수정 금지 가이드 위반입니다.
ViewerStatus변경 자체는 의도에 맞지만, Line 47-52처럼src/types내 타입을 직접 수정하면 저장소 규칙을 깨게 됩니다. API 스키마/코드젠 원천에서 타입을 갱신한 뒤 반영해 주세요.As per coding guidelines,
src/types/**/*.ts: "Type definitions intypes/directory must never be auto-modified".🤖 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/types/api/course.types.ts` around lines 47 - 52, You modified the generated ViewerStatus type in src/types/api/course.types.ts which violates the rule that files under src/types must not be edited directly; revert any manual edits to ViewerStatus and instead update the authoritative API schema or OpenAPI/GraphQL source that defines ViewerStatus, then run the project’s codegen task (the generator that produces src/types) to regenerate the type so the change is persisted properly; ensure the regenerated ViewerStatus includes the intended variants ('ANONYMOUS', 'LOGIN_ONLY', 'FREE_ENROLLED', 'PAID', 'ADMIN') and commit only the source schema and generated output produced by the codegen.src/app/(landing)/class/[slug]/page.tsx (1)
143-147:⚠️ Potential issue | 🟠 Major | ⚡ Quick win무료수강 성공 후 재조회 실패가 학습 진입을 막고 있습니다.
Line 143에서 재조회 실패가 발생하면 catch로 떨어져
router.push가 실행되지 않습니다. 등록이 이미 성공한 케이스까지 실패 처리되어 UX가 끊깁니다. 재조회는 비차단으로 처리하고 이동은 계속 진행하는 편이 안전합니다.수정 예시 diff
if (canShowCourseFreeEnrollCta(courseDetail)) { try { await createCourseFreeEnrollment.mutateAsync(courseDetail.courseId); - await refetchCourseDetail(); + try { + await refetchCourseDetail(); + } catch { + showToast('수강 상태 갱신에 실패했지만 학습은 바로 시작할 수 있어요.', 'info'); + } showToast('무료 코스 등록이 완료되었어요.'); } catch { showToast('무료 코스 등록 중 오류가 발생했어요.', 'error'); return; } }🤖 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/`(landing)/class/[slug]/page.tsx around lines 143 - 147, The catch block currently treats refetchCourseDetail failures as fatal and prevents router.push; change the flow so refetchCourseDetail is non-blocking: after the registration call, call refetchCourseDetail().catch(err => { showToast('재조회 실패', 'warning') /* or log */ }); then always call showToast('무료 코스 등록이 완료되었어요.') and router.push(...) regardless of refetch result; i.e., remove refetchCourseDetail from the try/catch that blocks navigation or handle it with its own .catch so registration success still navigates.src/components/pages/class/roadmap-tab.tsx (1)
167-195:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winOptional chaining 사용이 일관되지 않습니다.
Line 170, 195에서
course.freeLessonCount는 optional chaining 없이 접근하지만, line 171에서course?.canPurchase는 optional chaining을 사용합니다.course가undefined일 가능성이 있으므로 일관성과 안전성을 위해 통일하는 것이 좋습니다.🛡️ 권장 수정
isFreeEnrolled && !hasFullAccess && - completedLessons >= (course.freeLessonCount ?? 0) && + completedLessons >= (course?.freeLessonCount ?? 0) && course?.canPurchase ? ((hasFullAccess || (isFreeEnrolled && completedLessons > 0 && - completedLessons < (course.freeLessonCount ?? 0))) ? ( + completedLessons < (course?.freeLessonCount ?? 0))) ? (🤖 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/components/pages/class/roadmap-tab.tsx` around lines 167 - 195, The conditional uses optional chaining inconsistently — replace direct access to course.freeLessonCount with course?.freeLessonCount (and keep the existing nullish fallback) so all checks around completedLessons, isFreeEnrolled, hasFullAccess, and course?.canPurchase are safe when course is undefined; update both occurrences in the ternary branches that reference freeLessonCount (the conditions around the payment CTA and the nextAccessibleLesson branch) to use course?.freeLessonCount.
🤖 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.
Outside diff comments:
In `@src/app/`(landing)/class/[slug]/page.tsx:
- Around line 143-147: The catch block currently treats refetchCourseDetail
failures as fatal and prevents router.push; change the flow so
refetchCourseDetail is non-blocking: after the registration call, call
refetchCourseDetail().catch(err => { showToast('재조회 실패', 'warning') /* or log */
}); then always call showToast('무료 코스 등록이 완료되었어요.') and router.push(...)
regardless of refetch result; i.e., remove refetchCourseDetail from the
try/catch that blocks navigation or handle it with its own .catch so
registration success still navigates.
In `@src/components/pages/class/roadmap-tab.tsx`:
- Around line 167-195: The conditional uses optional chaining inconsistently —
replace direct access to course.freeLessonCount with course?.freeLessonCount
(and keep the existing nullish fallback) so all checks around completedLessons,
isFreeEnrolled, hasFullAccess, and course?.canPurchase are safe when course is
undefined; update both occurrences in the ternary branches that reference
freeLessonCount (the conditions around the payment CTA and the
nextAccessibleLesson branch) to use course?.freeLessonCount.
In `@src/types/api/course.types.ts`:
- Around line 47-52: You modified the generated ViewerStatus type in
src/types/api/course.types.ts which violates the rule that files under src/types
must not be edited directly; revert any manual edits to ViewerStatus and instead
update the authoritative API schema or OpenAPI/GraphQL source that defines
ViewerStatus, then run the project’s codegen task (the generator that produces
src/types) to regenerate the type so the change is persisted properly; ensure
the regenerated ViewerStatus includes the intended variants ('ANONYMOUS',
'LOGIN_ONLY', 'FREE_ENROLLED', 'PAID', 'ADMIN') and commit only the source
schema and generated output produced by the codegen.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 454ef9b5-1b1a-4725-a503-75f6cf4fbf44
📒 Files selected for processing (6)
src/app/(landing)/class/[slug]/page.tsxsrc/components/pages/class/class-detail-sidebar.tsxsrc/components/pages/class/course-viewer-status.test.tssrc/components/pages/class/course-viewer-status.tssrc/components/pages/class/roadmap-tab.tsxsrc/types/api/course.types.ts
작업 내용
viewerStatus=ADMIN을 프론트 타입/분기에서 별도 상태로 추가했습니다.PAID단일 판단이 아니라hasFullAccess,isFreeEnrolled,isPaidEnrolled,canFreeEnroll기준으로 분리했습니다.백엔드 계약 확인
study-platform-mvp origin/dev의ViewerStatus.ADMINenum 확인CourseDetailResponse.admin(...)에서viewerStatus=ADMIN,hasFullAccess=true, 실제 수강 플래그(isFreeEnrolled/isPaidEnrolled) 별도 반환 확인검증
vitest run --project unit src/components/pages/class/course-viewer-status.test.ts통과yarn lint:fix통과 (기존 warning 유지)yarn prettier:fix통과yarn typecheck통과Summary by CodeRabbit
Release Notes
New Features
Refactor
Tests