Skip to content
46 changes: 46 additions & 0 deletions src/app/instructor/choose/[commissionId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client";

import { notFound, useRouter } from "next/navigation";
import { use, useState } from "react";

import { commissionDraftsData } from "@/features/instructor/choose";
import Button from "@/shared/ui/Button";
import { DraftCheckSection } from "@/widgets/instructor/choose";

interface PageProps {
params: Promise<{ commissionId: string }>;
}

const Page = ({ params }: PageProps) => {
const router = useRouter();
const { commissionId } = use(params);
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);

const commission = commissionDraftsData.find(c => c.commissionId === Number(commissionId));

if (!commission) return notFound();

return (
<div className="mx-auto flex w-235 flex-col items-center gap-10 pt-16">
<div>
<h1 className="text-title2-sb mb-6.5 w-full py-4 text-left text-black">
{commission.title}
</h1>
<DraftCheckSection
drafts={commission.drafts}
selectedIndex={selectedIndex}
onSelect={setSelectedIndex}
/>
</div>
<Button
variant={selectedIndex !== null ? "medium_primary" : "medium_disabled"}
className="w-fit self-end"
onClick={selectedIndex !== null ? () => router.push("/instructor") : undefined}
>
제출하기
</Button>
</div>
);
};

export default Page;
6 changes: 5 additions & 1 deletion src/app/instructor/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ const InstructorLayout = ({ children }: { children: ReactNode }) => {
<div className="bg-gray-10 flex flex-1 overflow-hidden">
<Sidebar bottom={<SidebarMenu label="로그아웃" />}>
<SidebarMenu label="새 외주 작성" href="/instructor/write" />
<SidebarMenu label="진행 중 외주" href="/instructor" matchPrefix="/instructor/revision" />
<SidebarMenu
label="진행 중 외주"
href="/instructor"
matchPrefix={["/instructor/revision", "/instructor/choose"]}
/>
<SidebarMenu label="마이페이지" href="/instructor/my" />
</Sidebar>
<main className="scrollbar-hide flex flex-1 flex-col overflow-y-auto">{children}</main>
Expand Down
6 changes: 5 additions & 1 deletion src/app/instructor/revision/[commissionId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ const Page = () => {
>
최종 시안으로 선택하기
</Button>
<Button className="w-fit" variant={isSubmitActive ? "medium_primary" : "medium_disabled"}>
<Button
className="w-fit"
variant={isSubmitActive ? "medium_primary" : "medium_disabled"}
onClick={isSubmitActive ? () => router.push("/instructor") : undefined}
>
수정사항 전달하기
</Button>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/features/instructor/choose/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type { CommissionWithDrafts, Draft, DraftDetail } from "./model/choose";
export { commissionDraftsData, draftDetailsData } from "./model/choose";
export { default as DraftCard } from "./ui/DraftCard";
144 changes: 144 additions & 0 deletions src/features/instructor/choose/model/choose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// [강사] 제출된 1차 시안 목록 조회
export type Draft = {
draftId: number;
thumbnailUrl: string;
};

export type CommissionWithDrafts = {
commissionId: number;
title: string;
drafts: Draft[];
};

export const commissionDraftsData: CommissionWithDrafts[] = [
{
commissionId: 11,
title: "해커스톡 왕초보 영어 - 기초 문법편",
drafts: [
{ draftId: 41, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 42, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 43, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 44, thumbnailUrl: "/images/thumbnail_mock.jpg" },
],
},
{
commissionId: 15,
title: "고등 국어 문학 - 현대시 집중",
drafts: [
{ draftId: 51, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 52, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 53, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 54, thumbnailUrl: "/images/thumbnail_mock.jpg" },
{ draftId: 55, thumbnailUrl: "/images/thumbnail_mock.jpg" },
],
},
];
Comment on lines +13 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

exported 상수는 SCREAMING_SNAKE_CASE 명명 규칙을 따라야 합니다.

commissionDraftsDatadraftDetailsData는 exported 상수이므로 프로젝트의 명명 규칙에 따라 COMMISSION_DRAFTS_DATADRAFT_DETAILS_DATA로 작성해야 합니다.

♻️ 제안하는 수정
-export const commissionDraftsData: CommissionWithDrafts[] = [
+export const COMMISSION_DRAFTS_DATA: CommissionWithDrafts[] = [
   {
     commissionId: 11,
-export const draftDetailsData: Record<number, DraftDetail> = {
+export const DRAFT_DETAILS_DATA: Record<number, DraftDetail> = {
     commissionId: 11,

이 변경을 적용하는 경우, 해당 상수를 import하는 모든 파일도 함께 수정해야 합니다:

  • src/features/instructor/choose/index.ts
  • src/features/instructor/choose/ui/DraftCard.tsx
  • src/app/instructor/choose/[commissionId]/page.tsx

Based on learnings: "exported constants should be named in SCREAMING_SNAKE_CASE (e.g., BASIC_INFO_FIELDS, PAGE_OPTIONS)."

Also applies to: 44-144

🤖 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/choose/model/choose.ts` around lines 13 - 35, The
exported constant names commissionDraftsData (and the related exported
draftDetailsData) violate the SCREAMING_SNAKE_CASE rule; rename them to
COMMISSION_DRAFTS_DATA and DRAFT_DETAILS_DATA respectively, update all internal
references and exports in the defining module (e.g., change the export
identifiers in choose.ts) and then update every import site that consumes these
symbols (notably index.ts, ui/DraftCard.tsx, and
app/instructor/choose/[commissionId]/page.tsx) so imports use the new names.

Source: Learnings


// [강사] 제출된 1차 시안 상세 조회
export type DraftDetail = {
commissionId: number;
draftId: number;
fileUrls: string[];
};

export const draftDetailsData: Record<number, DraftDetail> = {
41: {
commissionId: 11,
draftId: 41,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
42: {
commissionId: 11,
draftId: 42,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
43: {
commissionId: 11,
draftId: 43,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
44: {
commissionId: 11,
draftId: 44,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
51: {
commissionId: 15,
draftId: 51,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
52: {
commissionId: 15,
draftId: 52,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
53: {
commissionId: 15,
draftId: 53,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
54: {
commissionId: 15,
draftId: 54,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
55: {
commissionId: 15,
draftId: 55,
fileUrls: [
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
"/images/thumbnail_mock.jpg",
],
},
};
56 changes: 56 additions & 0 deletions src/features/instructor/choose/ui/DraftCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"use client";

import { useState } from "react";

import { draftDetailsData } from "@/features/instructor/choose";
import Button from "@/shared/ui/Button";
import DraftModal from "@/shared/ui/modal/DraftModal";
import Thumbnail from "@/shared/ui/Thumbnail";

interface DraftCardProps {
index: number;
draftId: number;
thumbnailUrl: string;
isSelected: boolean;
onSelect: (index: number) => void;
}

const DraftCard = ({ index, draftId, thumbnailUrl, isSelected, onSelect }: DraftCardProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);

const detail = draftDetailsData[draftId];

return (
<>
<div className="border-gray-30 rounded-12 border-[1.5px] bg-white p-4">
<div className="flex justify-between pb-6">
<span className="text-gray-70 text-body1-sb">시안 {index + 1}</span>
<Button
variant="choose"
aria-pressed={isSelected}
className="w-fit"
onClick={() => onSelect(index)}
>
이 디자인으로 할게요
</Button>
</div>
<Thumbnail
src={thumbnailUrl}
alt={`시안 ${draftId}`}
className="h-63.75 w-full shrink-0"
onDetailClick={() => setIsModalOpen(true)}
/>
</div>
{detail && (
<DraftModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title={`시안 ${index + 1}`}
fileUrls={detail.fileUrls}
/>
)}
</>
);
};

export default DraftCard;
18 changes: 7 additions & 11 deletions src/features/instructor/home/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
export { getDDay } from "@/features/instructor/home/lib/getDDay";
export type {
DraftSubmissionItem,
MatchingItem,
ModifyingItem,
} from "@/features/instructor/home/model/home";
export { getDDay } from "./lib/getDDay";
export type { DraftSubmissionItem, MatchingItem, ModifyingItem } from "./model/home";
export {
CATEGORY_DISPLAY_MAP,
draftSubmissionStatusData,
matchingStatusData,
modifyingStatusData,
} from "@/features/instructor/home/model/home";
export { default as CommissionsHeader } from "@/features/instructor/home/ui/CommissionsHeader";
export { default as DraftSubmissionStatusRow } from "@/features/instructor/home/ui/DraftSubmissionStatusRow";
export { default as MatchingCommissionsRow } from "@/features/instructor/home/ui/MatchingCommissionsRow";
export { default as ModifyingCommissionsRow } from "@/features/instructor/home/ui/ModifyingCommissionsRow";
} from "./model/home";
export { default as CommissionsHeader } from "./ui/CommissionsHeader";
export { default as DraftSubmissionStatusRow } from "./ui/DraftSubmissionStatusRow";
export { default as MatchingCommissionsRow } from "./ui/MatchingCommissionsRow";
export { default as ModifyingCommissionsRow } from "./ui/ModifyingCommissionsRow";
4 changes: 2 additions & 2 deletions src/features/instructor/home/model/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const draftSubmissionStatusData: DraftSubmissionItem[] = [
commissionId: 11,
title: "해커스톡 왕초보 영어 - 기초 문법편",
category: "FLYER_TEXTBOOK_COVER_INNER",
draftSubmission: { submitted: 1, total: 4 },
draftSubmission: { submitted: 4, total: 4 },
firstDraftDeadline: "2026-06-10",
},
{
Expand Down Expand Up @@ -47,7 +47,7 @@ export const draftSubmissionStatusData: DraftSubmissionItem[] = [
commissionId: 15,
title: "고등 국어 문학 - 현대시 집중",
category: "FLYER_TEXTBOOK_COVER_INNER",
draftSubmission: { submitted: 4, total: 5 },
draftSubmission: { submitted: 5, total: 5 },
firstDraftDeadline: "2026-06-28",
},
];
Expand Down
43 changes: 31 additions & 12 deletions src/features/instructor/home/ui/DraftSubmissionStatusRow.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useRouter } from "next/navigation";

import { getDDay } from "@/features/instructor/home/lib/getDDay";
import { CATEGORY_DISPLAY_MAP, DraftSubmissionItem } from "@/features/instructor/home/model/home";
import { ArrowRightIcon, MatchingOffIcon, MatchingOnIcon } from "@/shared/assets/icons";
import Button from "@/shared/ui/Button";
import Tag from "@/shared/ui/Tag";

const DraftSubmissionStatusRow = ({ item }: { item: DraftSubmissionItem }) => {
const { title, category, draftSubmission, firstDraftDeadline } = item;
const { commissionId, title, category, draftSubmission, firstDraftDeadline } = item;
const { submitted, total } = draftSubmission;
const categoryLabel = CATEGORY_DISPLAY_MAP[category] ?? category;
const router = useRouter();

return (
<div className="border-b-gray-10 hover:bg-gray-5 flex h-15 cursor-pointer items-center border-b py-3 transition-colors duration-150">
Expand All @@ -19,18 +23,33 @@ const DraftSubmissionStatusRow = ({ item }: { item: DraftSubmissionItem }) => {
<ArrowRightIcon className="text-gray-90 size-5" />
</div>
</div>
<div className="flex w-53 flex-row items-center justify-between py-0.5">
<div className="flex flex-row">
{Array.from({ length: submitted }).map((_, i) => (
<MatchingOnIcon key={i} className="size-8" />
))}
{Array.from({ length: total - submitted }).map((_, i) => (
<MatchingOffIcon key={i} className="size-8" />
))}
<div className="flex w-85.75 flex-row justify-between">
<div className="flex w-53 flex-row items-center justify-between py-0.5">
<div className="flex flex-row">
{Array.from({ length: submitted }).map((_, i) => (
<MatchingOnIcon key={i} className="size-8" />
))}
{Array.from({ length: total - submitted }).map((_, i) => (
<MatchingOffIcon key={i} className="size-8" />
))}
</div>
<p className="text-heading3-sb text-gray-60">
(<span className="text-main-main">{submitted}</span>/{total})
</p>
</div>
<p className="text-heading3-sb text-gray-60">
(<span className="text-main-main">{submitted}</span>/{total})
</p>
{submitted === total ? (
<Button
variant="small_primary"
className="w-fit"
onClick={() => router.push(`/instructor/choose/${commissionId}`)}
>
확인하기
</Button>
) : (
<Button variant="small_disabled" className="w-fit">
대기중
</Button>
)}
</div>
</div>
</div>
Expand Down
12 changes: 4 additions & 8 deletions src/features/instructor/my/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
export type { CommissionHistoryItem } from "@/features/instructor/my/model/my";
export {
CATEGORY_BADGE_MAP,
commissionHistoryData,
PLAN_DISPLAY_MAP,
} from "@/features/instructor/my/model/my";
export { default as CommissionsHeader } from "@/features/instructor/my/ui/CommissionsHeader";
export { default as CommissionsHistoryRow } from "@/features/instructor/my/ui/CommissionsHistoryRow";
export type { CommissionHistoryItem } from "./model/my";
export { CATEGORY_BADGE_MAP, commissionHistoryData, PLAN_DISPLAY_MAP } from "./model/my";
export { default as CommissionsHeader } from "./ui/CommissionsHeader";
export { default as CommissionsHistoryRow } from "./ui/CommissionsHistoryRow";
Loading
Loading