Skip to content

[FEAT] 강사 마이페이지 퍼블리싱#28

Merged
waldls merged 5 commits into
mainfrom
feature/#27-instructor-mypage
Jun 7, 2026
Merged

[FEAT] 강사 마이페이지 퍼블리싱#28
waldls merged 5 commits into
mainfrom
feature/#27-instructor-mypage

Conversation

@waldls

@waldls waldls commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

📢 PR 유형

어떤 변경 사항이 있었나요?

  • 새로운 기능 추가
  • 버그 수정
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

📌 관련 이슈번호


✅ Key Changes

강사 - 마이페이지 퍼블리싱 진행했습니다.

  • 본인 정보 섹션(MyInfoSection) 구현
    • 이름, 외주 이용 횟수, 진행 중인 외주 건수 표시
  • 외주 내역 확인 섹션(CommissionsHistorySection) 구현
    • 헤더 및 행(CommissionsHistoryRow) 컴포넌트 추가
    • usePagination 훅을 shared로 이동하여 이전/다음 버튼 페이지네이션 연결
  • Badge, PageIndicator 컴포넌트 타입 및 스타일 확장 (교재 뱃지, my variant 추가)
  • mockData 스펙 정리 및 외주 내역 확인 행 구조 리팩토링

📸 스크린샷 or 실행영상

my.mp4

🎸 기타 사항 or 추가 코멘트

프로필 이미지 적용(우선 아이콘으로 렌더링) / 외주 내역 각 행 클릭 시 상세 페이지로 이동하는 경로 연결은 추후 진행 예정입니다.

Summary by CodeRabbit

출시 노트

  • 새로운 기능

    • 강사 마이페이지에서 개인 정보(이름, 프로필, 통계)를 확인할 수 있습니다.
    • 외주 내역을 페이지 형식으로 조회할 수 있으며, 외주 상태(진행중/완료), 플랜, 금액 정보를 확인할 수 있습니다.
  • UI/스타일

    • 배지에 새로운 스타일이 추가되었습니다.
    • 페이지 인디케이터의 디자인이 개선되었습니다.

@waldls waldls self-assigned this Jun 7, 2026
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

강사 마이페이지를 API 명세 기반으로 퍼블리싱합니다. 공유 UI 컴포넌트를 확장하고, 커미션 히스토리 도메인 모델과 UI 계층을 정의한 후, 페이지네이션 기능과 함께 마이페이지 레이아웃에 통합합니다.

Changes

강사 마이페이지 퍼블리싱

Layer / File(s) Summary
공유 UI 컴포넌트 확장
src/shared/ui/Badge.tsx, src/shared/ui/PageIndicator.tsx
Badge 컴포넌트에 "교재" 배리언트 추가 및 스타일 매핑. PageIndicatorvariant 옵션(home, my) 추가로 스타일 조건부 적용 (간격, 크기, 라운딩, 활성 색상 분기).
커미션 히스토리 도메인 모델
src/features/instructor/my/model/my.ts
CommissionHistoryItem 타입 정의 (id, 카테고리, 제목, 생성일, 플랜, 금액, 상태). PLAN_DISPLAY_MAP (플랜 → 한글 표시명), CATEGORY_BADGE_MAP (카테고리 → 배지 배리언트) 맵핑 상수. commissionHistoryData 정적 배열 (10개 더미 레코드).
커미션 히스토리 UI 컴포넌트
src/features/instructor/my/ui/CommissionsHeader.tsx, src/features/instructor/my/ui/CommissionsHistoryRow.tsx
CommissionsHeader: 헤더 라벨(외주, 외주 신청 일자, 플랜, 금액) 렌더. CommissionsHistoryRow: 아이템 수신 후 배지(카테고리 매핑, 기본 "교재"), 제목/화살표, 생성일(포맷), 플랜 표시, 금액(로케일 문자열) 렌더.
본인 정보 모델 및 UI
src/widgets/instructor/my/model/my.ts, src/widgets/instructor/my/ui/MyInfoSection.tsx
MyInfo 타입 (이름, 프로필 이미지, 통계). myInfoData 더미 객체. MyInfoSection UI: 프로필, 사용자명, 총/진행 중인 커미션 카운트 표시.
커미션 히스토리 섹션 및 페이지네이션
src/widgets/instructor/my/config/my.ts, src/widgets/instructor/my/ui/CommissionsHistorySection.tsx
COMMISSION_HISTORY_ITEMS_PER_PAGE = 3 설정. CommissionsHistorySection: usePagination 훅으로 데이터 페이지네이션, CommissionsHeader/CommissionsHistoryRow 목록 렌더, 이전/다음 버튼과 PageIndicator (my 변형) 배치.
마이페이지 메인 페이지
src/app/instructor/my/page.tsx
기존 문자열 렌더링을 마이페이지 레이아웃으로 교체. MyInfoSectionCommissionsHistorySection을 세로 배치, 타이틀 및 컨테이너 스타일 추가.
모듈 내보내기 정리
src/features/instructor/my/index.ts, src/widgets/instructor/my/index.ts
features 레벨: CommissionHistoryItem 타입, 맵핑/데이터 상수, UI 컴포넌트 명명 재내보내기. widgets 레벨: CommissionsHistorySection, MyInfoSection 명명 재내보내기로 공개 API 표면 정의.
기존 페이지 import 경로 정리
src/widgets/instructor/home/ui/DraftSubmissionStatusSection.tsx, src/widgets/instructor/home/ui/MatchingCommissionsSection.tsx, src/widgets/instructor/home/ui/ModifyingCommissionsSection.tsx
usePagination 임포트를 공유 훅 경로(@/shared/lib/hooks/usePagination)로 통일, PageIndicator 및 페이지당 항목 수 상수와 함께 import 순서 정렬.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

♻️ Refactor

Suggested reviewers

  • KOJ50
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경 사항을 명확하게 요약합니다. 강사 마이페이지 퍼블리싱이 변경 사항의 핵심이며, 추가된 모든 컴포넌트와 기능이 이를 중심으로 구성되어 있습니다.
Linked Issues check ✅ Passed PR이 연결된 이슈 #27의 모든 코딩 요구사항을 충족합니다. 본인 정보 섹션(MyInfoSection), 외주 내역 섹션(CommissionsHistorySection), 페이지네이션, 컴포넌트 확장이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 강사 마이페이지 퍼블리싱 범위 내입니다. 지원 컴포넌트 확장(Badge, PageIndicator)과 공유 훅 이동(usePagination)은 마이페이지 구현을 직접 지원하는 필요한 변경입니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#27-instructor-mypage

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/features/instructor/my/model/my.ts (1)

4-22: ⚡ Quick win

카테고리 타입을 문자열에서 유니온으로 고정해주세요.

category: stringRecord<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

📥 Commits

Reviewing files that changed from the base of the PR and between accec95 and 9214d64.

📒 Files selected for processing (16)
  • src/app/instructor/my/page.tsx
  • src/features/instructor/my/index.ts
  • src/features/instructor/my/model/my.ts
  • src/features/instructor/my/ui/CommissionsHeader.tsx
  • src/features/instructor/my/ui/CommissionsHistoryRow.tsx
  • src/shared/lib/hooks/usePagination.ts
  • src/shared/ui/Badge.tsx
  • src/shared/ui/PageIndicator.tsx
  • src/widgets/instructor/home/ui/DraftSubmissionStatusSection.tsx
  • src/widgets/instructor/home/ui/MatchingCommissionsSection.tsx
  • src/widgets/instructor/home/ui/ModifyingCommissionsSection.tsx
  • src/widgets/instructor/my/config/my.ts
  • src/widgets/instructor/my/index.ts
  • src/widgets/instructor/my/model/my.ts
  • src/widgets/instructor/my/ui/CommissionsHistorySection.tsx
  • src/widgets/instructor/my/ui/MyInfoSection.tsx

Comment on lines +13 to +19
<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>

@coderabbitai coderabbitai Bot Jun 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

클릭 가능한 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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 연결 예정 - PR 기타 사항 부분에 작성되어있음

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines +14 to +17
stats: {
totalCommissionCount: 5,
ongoingCommissionCount: 5,
},

@coderabbitai coderabbitai Bot Jun 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

통계 목데이터가 외주 내역 데이터와 불일치합니다.

현재 목데이터 기준으로 외주 내역은 총 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.

Suggested change
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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mockData임

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines +29 to +31
<PrevButton className="size-12 cursor-pointer" onClick={handlePrev} />
<PageIndicator total={totalPages} current={current} variant="my" />
<NextButton className="size-12 cursor-pointer" onClick={handleNext} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

아이콘을 직접 클릭 요소로 쓰지 말고 버튼 시맨틱으로 감싸주세요.

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.

@waldls waldls merged commit f257f3e into main Jun 7, 2026
2 checks passed
@waldls waldls deleted the feature/#27-instructor-mypage branch June 7, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 강사 마이페이지 퍼블리싱

1 participant