[FEAT] 강사 마이페이지 퍼블리싱#28
Conversation
📝 WalkthroughWalkthrough강사 마이페이지를 API 명세 기반으로 퍼블리싱합니다. 공유 UI 컴포넌트를 확장하고, 커미션 히스토리 도메인 모델과 UI 계층을 정의한 후, 페이지네이션 기능과 함께 마이페이지 레이아웃에 통합합니다. Changes강사 마이페이지 퍼블리싱
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/features/instructor/my/model/my.ts (1)
4-22: ⚡ Quick win카테고리 타입을 문자열에서 유니온으로 고정해주세요.
category: string과Record<string, BadgeVariant>조합은 카테고리 오타/누락을 컴파일 단계에서 못 잡습니다. 배지 매핑을 쓰는 현재 구조에서는 카테고리 코드셋을 타입으로 고정하는 편이 안전합니다.제안 diff
+type CommissionCategory = "FLYER_TEXTBOOK_COVER_INNER"; + export type CommissionHistoryItem = { commissionId: number; - category: string; + category: CommissionCategory; title: string; createdAt: string; plan: "BASIC" | "PLUS" | "MAX"; totalAmount: number; status: "COMPLETED" | "ONGOING"; }; -export const CATEGORY_BADGE_MAP: Record<string, BadgeVariant> = { +export const CATEGORY_BADGE_MAP: Record<CommissionHistoryItem["category"], BadgeVariant> = { FLYER_TEXTBOOK_COVER_INNER: "교재", };🤖 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/instructor/my/model/my.ts` around lines 4 - 22, Change the loose string category to a strict union and align the badge map type: define a Category union type (e.g. type Category = "FLYER_TEXTBOOK_COVER_INNER" | "...") or derive it from the keys of CATEGORY_BADGE_MAP, update CommissionHistoryItem to use category: Category, and change CATEGORY_BADGE_MAP to Record<Category, BadgeVariant> (or Record<CommissionHistoryItem["category"], BadgeVariant>) so the compiler catches unknown/missing categories; ensure BadgeVariant is imported/available for the new map type.
🤖 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/features/instructor/my/ui/CommissionsHistoryRow.tsx`:
- Around line 13-19: The row in CommissionsHistoryRow renders as clickable
(cursor-pointer and ArrowRightIcon) but has no click handler or navigation;
either make it truly interactive by wrapping the row content in a semantic
interactive element (e.g., Link or button) and add the onClick/navigation logic
to open the detail (ensure accessibility attributes and keyboard handling) or
remove the interactive affordances (remove "cursor-pointer" class and
ArrowRightIcon) so it isn't misleading; update the JSX around the outer div (the
element with className including "cursor-pointer") and the ArrowRightIcon usage
accordingly.
In `@src/widgets/instructor/my/model/my.ts`:
- Around line 14-17: The stats mock in the my model is inconsistent with the
commission list; update the stats object so totalCommissionCount and
ongoingCommissionCount reflect the actual mock data (set totalCommissionCount to
10 and ongoingCommissionCount to 3) in the stats block (symbols: stats,
totalCommissionCount, ongoingCommissionCount) inside the my.ts model.
In `@src/widgets/instructor/my/ui/CommissionsHistorySection.tsx`:
- Around line 29-31: Wrap the PrevButton and NextButton icon components with
semantic <button> elements (rather than using the icon as the clickable
element), move onClick handlers (handlePrev, handleNext) to those buttons, add
descriptive aria-labels (e.g., "Previous page"/"Next page") and set disabled
when at boundaries using current and totalPages so keyboard and screen-reader
users can operate pagination; ensure PageIndicator usage remains unchanged and
that any existing className/aria props are forwarded to the button wrapper.
---
Nitpick comments:
In `@src/features/instructor/my/model/my.ts`:
- Around line 4-22: Change the loose string category to a strict union and align
the badge map type: define a Category union type (e.g. type Category =
"FLYER_TEXTBOOK_COVER_INNER" | "...") or derive it from the keys of
CATEGORY_BADGE_MAP, update CommissionHistoryItem to use category: Category, and
change CATEGORY_BADGE_MAP to Record<Category, BadgeVariant> (or
Record<CommissionHistoryItem["category"], BadgeVariant>) so the compiler catches
unknown/missing categories; ensure BadgeVariant is imported/available for the
new map type.
🪄 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: 682a37aa-fb54-4414-b589-4aabf3334163
📒 Files selected for processing (16)
src/app/instructor/my/page.tsxsrc/features/instructor/my/index.tssrc/features/instructor/my/model/my.tssrc/features/instructor/my/ui/CommissionsHeader.tsxsrc/features/instructor/my/ui/CommissionsHistoryRow.tsxsrc/shared/lib/hooks/usePagination.tssrc/shared/ui/Badge.tsxsrc/shared/ui/PageIndicator.tsxsrc/widgets/instructor/home/ui/DraftSubmissionStatusSection.tsxsrc/widgets/instructor/home/ui/MatchingCommissionsSection.tsxsrc/widgets/instructor/home/ui/ModifyingCommissionsSection.tsxsrc/widgets/instructor/my/config/my.tssrc/widgets/instructor/my/index.tssrc/widgets/instructor/my/model/my.tssrc/widgets/instructor/my/ui/CommissionsHistorySection.tsxsrc/widgets/instructor/my/ui/MyInfoSection.tsx
| <div className="hover:bg-gray-5 border-b-gray-20 flex h-19.25 w-full shrink-0 cursor-pointer items-center justify-between border-b bg-white px-3 py-5 transition-colors duration-150"> | ||
| <div className="flex flex-row gap-6"> | ||
| <Badge variant={CATEGORY_BADGE_MAP[category] ?? "교재"} /> | ||
| <div className="text-gray-90 flex flex-row items-center gap-1"> | ||
| <p className="text-heading3-m max-w-70 truncate">{title}</p> | ||
| <ArrowRightIcon className="size-6" /> | ||
| </div> |
There was a problem hiding this comment.
클릭 가능한 UI처럼 보이지만 실제 동작이 없습니다.
cursor-pointer와 화살표 아이콘으로 이동 가능한 행처럼 보이는데, 현재는 클릭 동작이 없어 사용자에게 오해를 줍니다. 상세 이동을 아직 연결하지 않았다면 인터랙티브 스타일을 제거하거나, 지금 연결할 수 있다면 Link/button으로 semantics까지 맞춰주세요.
제안 diff (미구현 상태 유지 시)
- <div className="hover:bg-gray-5 border-b-gray-20 flex h-19.25 w-full shrink-0 cursor-pointer items-center justify-between border-b bg-white px-3 py-5 transition-colors duration-150">
+ <div className="hover:bg-gray-5 border-b-gray-20 flex h-19.25 w-full shrink-0 items-center justify-between border-b bg-white px-3 py-5 transition-colors duration-150">🤖 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/instructor/my/ui/CommissionsHistoryRow.tsx` around lines 13 -
19, The row in CommissionsHistoryRow renders as clickable (cursor-pointer and
ArrowRightIcon) but has no click handler or navigation; either make it truly
interactive by wrapping the row content in a semantic interactive element (e.g.,
Link or button) and add the onClick/navigation logic to open the detail (ensure
accessibility attributes and keyboard handling) or remove the interactive
affordances (remove "cursor-pointer" class and ArrowRightIcon) so it isn't
misleading; update the JSX around the outer div (the element with className
including "cursor-pointer") and the ArrowRightIcon usage accordingly.
There was a problem hiding this comment.
추후 연결 예정 - PR 기타 사항 부분에 작성되어있음
There was a problem hiding this comment.
@waldls, PR 기타 사항에 명시되어 있군요 — 확인했습니다. 추후 상세 페이지 이동을 연결할 때 div 대신 Link 또는 button으로 교체하고 키보드 접근성도 함께 맞춰주시면 좋을 것 같습니다.
혹시 이 작업을 추적하기 위한 별도 이슈를 생성해 드릴까요?
🧠 Learnings used
Learnt from: waldls
Repo: Ditda-Official/Ditda-Frontend PR: 18
File: src/constants/write.ts:65-82
Timestamp: 2026-05-27T08:26:49.054Z
Learning: In Ditda-Frontend (TypeScript/Next.js), exported constants should be named in SCREAMING_SNAKE_CASE (e.g., BASIC_INFO_FIELDS, PAGE_OPTIONS). The camelCase naming guideline should apply to functions and non-exported/regular variables, but not to exported constants.
| stats: { | ||
| totalCommissionCount: 5, | ||
| ongoingCommissionCount: 5, | ||
| }, |
There was a problem hiding this comment.
통계 목데이터가 외주 내역 데이터와 불일치합니다.
현재 목데이터 기준으로 외주 내역은 총 10건/진행중 3건인데, 여기서는 5/5로 노출됩니다. 동일 페이지에서 함께 보여주므로 수치를 맞춰두는 게 안전합니다.
제안 diff
stats: {
- totalCommissionCount: 5,
- ongoingCommissionCount: 5,
+ totalCommissionCount: 10,
+ ongoingCommissionCount: 3,
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| stats: { | |
| totalCommissionCount: 5, | |
| ongoingCommissionCount: 5, | |
| }, | |
| stats: { | |
| totalCommissionCount: 10, | |
| ongoingCommissionCount: 3, | |
| }, |
🤖 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/widgets/instructor/my/model/my.ts` around lines 14 - 17, The stats mock
in the my model is inconsistent with the commission list; update the stats
object so totalCommissionCount and ongoingCommissionCount reflect the actual
mock data (set totalCommissionCount to 10 and ongoingCommissionCount to 3) in
the stats block (symbols: stats, totalCommissionCount, ongoingCommissionCount)
inside the my.ts model.
There was a problem hiding this comment.
@waldls 목데이터임을 인지하지 못했습니다, 지적 감사합니다. 해당 코멘트는 무시해 주세요.
🐇
✏️ Learnings added
Learnt from: waldls
Repo: Ditda-Official/Ditda-Frontend PR: 28
File: src/widgets/instructor/my/model/my.ts:14-17
Timestamp: 2026-06-07T17:37:21.449Z
Learning: In Ditda-Frontend, `myInfoData` in `src/widgets/instructor/my/model/my.ts` and `commissionHistoryData` in `src/features/instructor/my/model/my.ts` are independent mock/dummy data objects. Their stat fields (e.g., `totalCommissionCount`, `ongoingCommissionCount`) do not need to match the actual length or contents of the commission history mock array — they are placeholder values only.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: waldls
Repo: Ditda-Official/Ditda-Frontend PR: 18
File: src/constants/write.ts:65-82
Timestamp: 2026-05-27T08:26:49.054Z
Learning: In Ditda-Frontend (TypeScript/Next.js), exported constants should be named in SCREAMING_SNAKE_CASE (e.g., BASIC_INFO_FIELDS, PAGE_OPTIONS). The camelCase naming guideline should apply to functions and non-exported/regular variables, but not to exported constants.
| <PrevButton className="size-12 cursor-pointer" onClick={handlePrev} /> | ||
| <PageIndicator total={totalPages} current={current} variant="my" /> | ||
| <NextButton className="size-12 cursor-pointer" onClick={handleNext} /> |
There was a problem hiding this comment.
아이콘을 직접 클릭 요소로 쓰지 말고 버튼 시맨틱으로 감싸주세요.
Line 29, Line 31은 키보드 포커스/스크린리더 접근성이 보장되지 않아 페이지네이션 조작이 막힐 수 있습니다. <button>으로 감싸고 aria-label/disabled 상태를 추가하는 쪽이 안전합니다.
수정 예시
- <div className="flex flex-row items-center justify-center gap-8">
- <PrevButton className="size-12 cursor-pointer" onClick={handlePrev} />
- <PageIndicator total={totalPages} current={current} variant="my" />
- <NextButton className="size-12 cursor-pointer" onClick={handleNext} />
- </div>
+ <div className="flex flex-row items-center justify-center gap-8">
+ <button
+ type="button"
+ onClick={handlePrev}
+ aria-label="이전 페이지"
+ disabled={current === 0}
+ className="cursor-pointer disabled:cursor-not-allowed disabled:opacity-40"
+ >
+ <PrevButton className="size-12" />
+ </button>
+ <PageIndicator total={totalPages} current={current} variant="my" />
+ <button
+ type="button"
+ onClick={handleNext}
+ aria-label="다음 페이지"
+ disabled={current >= totalPages - 1}
+ className="cursor-pointer disabled:cursor-not-allowed disabled:opacity-40"
+ >
+ <NextButton className="size-12" />
+ </button>
+ </div>🤖 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/widgets/instructor/my/ui/CommissionsHistorySection.tsx` around lines 29 -
31, Wrap the PrevButton and NextButton icon components with semantic <button>
elements (rather than using the icon as the clickable element), move onClick
handlers (handlePrev, handleNext) to those buttons, add descriptive aria-labels
(e.g., "Previous page"/"Next page") and set disabled when at boundaries using
current and totalPages so keyboard and screen-reader users can operate
pagination; ensure PageIndicator usage remains unchanged and that any existing
className/aria props are forwarded to the button wrapper.
📢 PR 유형
어떤 변경 사항이 있었나요?
📌 관련 이슈번호
✅ Key Changes
강사 - 마이페이지 퍼블리싱 진행했습니다.
MyInfoSection) 구현CommissionsHistorySection) 구현CommissionsHistoryRow) 컴포넌트 추가usePagination훅을 shared로 이동하여 이전/다음 버튼 페이지네이션 연결Badge,PageIndicator컴포넌트 타입 및 스타일 확장 (교재 뱃지, my variant 추가)📸 스크린샷 or 실행영상
my.mp4
🎸 기타 사항 or 추가 코멘트
프로필 이미지 적용(우선 아이콘으로 렌더링) / 외주 내역 각 행 클릭 시 상세 페이지로 이동하는 경로 연결은 추후 진행 예정입니다.
Summary by CodeRabbit
출시 노트
새로운 기능
UI/스타일