From b2b92a46c8ce96e3c605ce7a096bfb62b0c1fa03 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Sun, 11 Jan 2026 19:44:45 +0900 Subject: [PATCH 01/31] =?UTF-8?q?chore:=20SVG=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20public=EC=97=90=EC=84=9C=20src/assets?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/vite.svg | 1 - {public => src/assets}/svg/addIcon.svg | 0 {public => src/assets}/svg/arrowdownIcon.svg | 0 {public => src/assets}/svg/arrowleftIcon.svg | 0 {public => src/assets}/svg/arrowrightIcon.svg | 0 {public => src/assets}/svg/chatIcon.svg | 0 {public => src/assets}/svg/chevrondown.svg | 0 {public => src/assets}/svg/deleteIcon.svg | 0 {public => src/assets}/svg/dragAndDropIcon.svg | 0 {public => src/assets}/svg/editIcon.svg | 0 {public => src/assets}/svg/ellipsisIcon.svg | 0 {public => src/assets}/svg/file.svg | 0 {public => src/assets}/svg/notificationIcon.svg | 0 {public => src/assets}/svg/profileImage.svg | 0 {public => src/assets}/svg/search.svg | 0 {public => src/assets}/svg/signoutIcon.svg | 0 {public => src/assets}/svg/singleEllipsisIcon.svg | 0 {public => src/assets}/svg/userIcon.svg | 0 src/components/admin/assignments/AssignmentCard.tsx | 8 ++++---- src/components/admin/assignments/AssignmentPageLayout.tsx | 2 +- src/components/admin/assignments/CourseSelector.tsx | 2 +- src/components/admin/form/FileUpload.tsx | 2 +- src/components/admin/form/LabeledDropdown.tsx | 2 +- src/components/common/CourseOverview/UnitHeader.tsx | 1 - src/components/common/Dashboard/CourseCard.tsx | 2 +- src/components/common/Dashboard/CourseList.tsx | 2 +- src/layout/Layout.tsx | 8 ++++---- src/pages/admin/student/studentManagementPage.tsx | 2 +- src/pages/common/LandingPage.tsx | 2 +- src/pages/common/UserIdInputPage.tsx | 2 +- 30 files changed, 17 insertions(+), 19 deletions(-) delete mode 100644 public/vite.svg rename {public => src/assets}/svg/addIcon.svg (100%) rename {public => src/assets}/svg/arrowdownIcon.svg (100%) rename {public => src/assets}/svg/arrowleftIcon.svg (100%) rename {public => src/assets}/svg/arrowrightIcon.svg (100%) rename {public => src/assets}/svg/chatIcon.svg (100%) rename {public => src/assets}/svg/chevrondown.svg (100%) rename {public => src/assets}/svg/deleteIcon.svg (100%) rename {public => src/assets}/svg/dragAndDropIcon.svg (100%) rename {public => src/assets}/svg/editIcon.svg (100%) rename {public => src/assets}/svg/ellipsisIcon.svg (100%) rename {public => src/assets}/svg/file.svg (100%) rename {public => src/assets}/svg/notificationIcon.svg (100%) rename {public => src/assets}/svg/profileImage.svg (100%) rename {public => src/assets}/svg/search.svg (100%) rename {public => src/assets}/svg/signoutIcon.svg (100%) rename {public => src/assets}/svg/singleEllipsisIcon.svg (100%) rename {public => src/assets}/svg/userIcon.svg (100%) diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/svg/addIcon.svg b/src/assets/svg/addIcon.svg similarity index 100% rename from public/svg/addIcon.svg rename to src/assets/svg/addIcon.svg diff --git a/public/svg/arrowdownIcon.svg b/src/assets/svg/arrowdownIcon.svg similarity index 100% rename from public/svg/arrowdownIcon.svg rename to src/assets/svg/arrowdownIcon.svg diff --git a/public/svg/arrowleftIcon.svg b/src/assets/svg/arrowleftIcon.svg similarity index 100% rename from public/svg/arrowleftIcon.svg rename to src/assets/svg/arrowleftIcon.svg diff --git a/public/svg/arrowrightIcon.svg b/src/assets/svg/arrowrightIcon.svg similarity index 100% rename from public/svg/arrowrightIcon.svg rename to src/assets/svg/arrowrightIcon.svg diff --git a/public/svg/chatIcon.svg b/src/assets/svg/chatIcon.svg similarity index 100% rename from public/svg/chatIcon.svg rename to src/assets/svg/chatIcon.svg diff --git a/public/svg/chevrondown.svg b/src/assets/svg/chevrondown.svg similarity index 100% rename from public/svg/chevrondown.svg rename to src/assets/svg/chevrondown.svg diff --git a/public/svg/deleteIcon.svg b/src/assets/svg/deleteIcon.svg similarity index 100% rename from public/svg/deleteIcon.svg rename to src/assets/svg/deleteIcon.svg diff --git a/public/svg/dragAndDropIcon.svg b/src/assets/svg/dragAndDropIcon.svg similarity index 100% rename from public/svg/dragAndDropIcon.svg rename to src/assets/svg/dragAndDropIcon.svg diff --git a/public/svg/editIcon.svg b/src/assets/svg/editIcon.svg similarity index 100% rename from public/svg/editIcon.svg rename to src/assets/svg/editIcon.svg diff --git a/public/svg/ellipsisIcon.svg b/src/assets/svg/ellipsisIcon.svg similarity index 100% rename from public/svg/ellipsisIcon.svg rename to src/assets/svg/ellipsisIcon.svg diff --git a/public/svg/file.svg b/src/assets/svg/file.svg similarity index 100% rename from public/svg/file.svg rename to src/assets/svg/file.svg diff --git a/public/svg/notificationIcon.svg b/src/assets/svg/notificationIcon.svg similarity index 100% rename from public/svg/notificationIcon.svg rename to src/assets/svg/notificationIcon.svg diff --git a/public/svg/profileImage.svg b/src/assets/svg/profileImage.svg similarity index 100% rename from public/svg/profileImage.svg rename to src/assets/svg/profileImage.svg diff --git a/public/svg/search.svg b/src/assets/svg/search.svg similarity index 100% rename from public/svg/search.svg rename to src/assets/svg/search.svg diff --git a/public/svg/signoutIcon.svg b/src/assets/svg/signoutIcon.svg similarity index 100% rename from public/svg/signoutIcon.svg rename to src/assets/svg/signoutIcon.svg diff --git a/public/svg/singleEllipsisIcon.svg b/src/assets/svg/singleEllipsisIcon.svg similarity index 100% rename from public/svg/singleEllipsisIcon.svg rename to src/assets/svg/singleEllipsisIcon.svg diff --git a/public/svg/userIcon.svg b/src/assets/svg/userIcon.svg similarity index 100% rename from public/svg/userIcon.svg rename to src/assets/svg/userIcon.svg diff --git a/src/components/admin/assignments/AssignmentCard.tsx b/src/components/admin/assignments/AssignmentCard.tsx index 214f459..9dfc275 100644 --- a/src/components/admin/assignments/AssignmentCard.tsx +++ b/src/components/admin/assignments/AssignmentCard.tsx @@ -1,8 +1,8 @@ import {useState} from 'react'; -import SingleEllipsisIcon from '/svg/singleEllipsisIcon.svg?react'; -import DragAndDropIcon from '/svg/dragAndDropIcon.svg?react'; -import DeleteIcon from '/svg/deleteIcon.svg?react'; -import EditIcon from '/svg/editIcon.svg?react'; +import SingleEllipsisIcon from '@/assets/svg/singleEllipsisIcon.svg?react'; +import DragAndDropIcon from '@/assets/svg/dragAndDropIcon.svg?react'; +import DeleteIcon from '@/assets/svg/deleteIcon.svg?react'; +import EditIcon from '@/assets/svg/editIcon.svg?react'; import type {Assignment} from './dummy/types'; interface AssignmentCardProps extends Assignment { diff --git a/src/components/admin/assignments/AssignmentPageLayout.tsx b/src/components/admin/assignments/AssignmentPageLayout.tsx index 66327d1..490c9f2 100644 --- a/src/components/admin/assignments/AssignmentPageLayout.tsx +++ b/src/components/admin/assignments/AssignmentPageLayout.tsx @@ -2,7 +2,7 @@ import CourseSelector from './CourseSelector'; import AssignmentList from './AssignmentList'; import Button from '@/components/common/Button'; import type {Course} from './dummy/types'; -import AddIcon from '/svg/addIcon.svg?react'; +import AddIcon from '@/assets/svg/addIcon.svg?react'; import {useState} from 'react'; interface AssignmentPageLayoutProps { diff --git a/src/components/admin/assignments/CourseSelector.tsx b/src/components/admin/assignments/CourseSelector.tsx index aef0a1a..5d248a4 100644 --- a/src/components/admin/assignments/CourseSelector.tsx +++ b/src/components/admin/assignments/CourseSelector.tsx @@ -1,5 +1,5 @@ import {useState} from 'react'; -import ArrowdownIcon from '/svg/arrowdownIcon.svg?react'; +import ArrowdownIcon from '@/assets/svg/arrowdownIcon.svg?react'; import type {Course} from './dummy/types'; interface CourseSelectorProps { diff --git a/src/components/admin/form/FileUpload.tsx b/src/components/admin/form/FileUpload.tsx index b86e3e7..0da270b 100644 --- a/src/components/admin/form/FileUpload.tsx +++ b/src/components/admin/form/FileUpload.tsx @@ -1,6 +1,6 @@ import {useRef, useState} from 'react'; import type {ChangeEvent} from 'react'; -import FileIcon from '/svg/file.svg?react'; +import FileIcon from '@/assets/svg/file.svg?react'; type FileUploadProps = { label: string; diff --git a/src/components/admin/form/LabeledDropdown.tsx b/src/components/admin/form/LabeledDropdown.tsx index 20e22cb..d55c0f6 100644 --- a/src/components/admin/form/LabeledDropdown.tsx +++ b/src/components/admin/form/LabeledDropdown.tsx @@ -1,5 +1,5 @@ import {useState, useRef} from 'react'; -import Chevrondown from '/svg/chevrondown.svg?react'; +import Chevrondown from '@/assets/svg/chevrondown.svg?react'; import useClickOutside from '@/hooks/useClickOutside'; interface LabeledDropdownProps diff --git a/src/components/common/CourseOverview/UnitHeader.tsx b/src/components/common/CourseOverview/UnitHeader.tsx index 290bfbc..b4822d5 100644 --- a/src/components/common/CourseOverview/UnitHeader.tsx +++ b/src/components/common/CourseOverview/UnitHeader.tsx @@ -1,5 +1,4 @@ import UnitLabel from './UnitLabel'; -import UnitLabel from './UnitLabel'; import lock from '@/assets/images/lock.svg'; interface UnitHeaderProps { diff --git a/src/components/common/Dashboard/CourseCard.tsx b/src/components/common/Dashboard/CourseCard.tsx index dc60025..3934de2 100644 --- a/src/components/common/Dashboard/CourseCard.tsx +++ b/src/components/common/Dashboard/CourseCard.tsx @@ -1,5 +1,5 @@ import {useState} from 'react'; -import EllipsisIcon from '/svg/ellipsisIcon.svg?react'; +import EllipsisIcon from '@/assets/svg/ellipsisIcon.svg?react'; import type {Course, UserType} from './types'; import {getSemesterLabel} from '@/utils/getSemesterLabel'; diff --git a/src/components/common/Dashboard/CourseList.tsx b/src/components/common/Dashboard/CourseList.tsx index 537ef9a..b5fd526 100644 --- a/src/components/common/Dashboard/CourseList.tsx +++ b/src/components/common/Dashboard/CourseList.tsx @@ -1,6 +1,6 @@ import logo from '@/assets/images/snowCode_logo_mini.svg'; import CourseCard from './CourseCard'; -import AddIcon from '/svg/addIcon.svg?react'; +import AddIcon from '@/assets/svg/addIcon.svg?react'; import type {Course, UserType} from './types'; const courses: Course[] = [ diff --git a/src/layout/Layout.tsx b/src/layout/Layout.tsx index 09eeeae..9470d27 100644 --- a/src/layout/Layout.tsx +++ b/src/layout/Layout.tsx @@ -1,10 +1,10 @@ // Layout.js import {useLocation, Outlet} from 'react-router-dom'; import BaseHeader from '@/components/common/BaseHeader'; -import NotificationIcon from '/svg/notificationIcon.svg?react'; -import SignoutIcon from '/svg/signoutIcon.svg?react'; -import UserIcon from '/svg/userIcon.svg?react'; -import ChatIcon from '/svg/chatIcon.svg?react'; +import NotificationIcon from '@/assets/svg/notificationIcon.svg?react'; +import SignoutIcon from '@/assets/svg/signoutIcon.svg?react'; +import UserIcon from '@/assets/svg/userIcon.svg?react'; +import ChatIcon from '@/assets/svg/chatIcon.svg?react'; import IconButton from '@/components/common/IconButton'; import React from 'react'; diff --git a/src/pages/admin/student/studentManagementPage.tsx b/src/pages/admin/student/studentManagementPage.tsx index 270fe17..a59b9a9 100644 --- a/src/pages/admin/student/studentManagementPage.tsx +++ b/src/pages/admin/student/studentManagementPage.tsx @@ -1,5 +1,5 @@ import AssignmentFormLayout from '@/components/admin/assignments/AssignmentFormLayout'; -import Search from '/svg/search.svg?react'; +import Search from '@/assets/svg/search.svg?react'; import {useSearchParams} from 'react-router-dom'; export default function StudentManagementPage() { diff --git a/src/pages/common/LandingPage.tsx b/src/pages/common/LandingPage.tsx index b6ccf21..074719a 100644 --- a/src/pages/common/LandingPage.tsx +++ b/src/pages/common/LandingPage.tsx @@ -5,7 +5,7 @@ import snowCodeEntry from '/src/assets/images/snowCode_entry.svg'; import snowCodeStudent from '/src/assets/images/snowCode_student.svg'; import snowCodeAdmin from '/src/assets/images/snowCode_admin.svg'; import googleLogo from '/src/assets/images/google_logo.svg'; -import ArrowrightIcon from '/svg/arrowrightIcon.svg?react'; +import ArrowrightIcon from '@/assets/svg/arrowrightIcon.svg?react'; import ActionButton from '@/components/common/ActionButton'; type HoverState = 'none' | 'student' | 'admin'; diff --git a/src/pages/common/UserIdInputPage.tsx b/src/pages/common/UserIdInputPage.tsx index a9963a8..2a85fff 100644 --- a/src/pages/common/UserIdInputPage.tsx +++ b/src/pages/common/UserIdInputPage.tsx @@ -2,7 +2,7 @@ import {useState, useRef, useEffect} from 'react'; import {useNavigate, useLocation} from 'react-router-dom'; import ActionButton from '@/components/common/ActionButton'; import SnowCodeEntryMini from '@/assets/images/snowCode_entry_mini.svg'; -import ArrowleftIcon from '/svg/arrowleftIcon.svg?react'; +import ArrowleftIcon from '@/assets/svg/arrowleftIcon.svg?react'; export default function UserIdInputPage() { const navigate = useNavigate(); From 7daabe17c806b4b21555f0b7fc57366683fb7850 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Sun, 11 Jan 2026 21:01:12 +0900 Subject: [PATCH 02/31] =?UTF-8?q?chore:=20import=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svg/Correct.tsx | 12 ------------ src/assets/svg/Incorrect.tsx | 17 ----------------- src/assets/svg/Unsubmitted.tsx | 19 ------------------- src/assets/svg/index.ts | 18 ------------------ src/components/common/Badge.tsx | 4 +++- .../assignments/AssignmentCreatePage.tsx | 2 +- src/pages/common/LandingPage.tsx | 8 ++++---- 7 files changed, 8 insertions(+), 72 deletions(-) delete mode 100644 src/assets/svg/Correct.tsx delete mode 100644 src/assets/svg/Incorrect.tsx delete mode 100644 src/assets/svg/Unsubmitted.tsx delete mode 100644 src/assets/svg/index.ts diff --git a/src/assets/svg/Correct.tsx b/src/assets/svg/Correct.tsx deleted file mode 100644 index d5a68d2..0000000 --- a/src/assets/svg/Correct.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgCorrect = (props: SVGProps) => ( - - - -); -export default SvgCorrect; diff --git a/src/assets/svg/Incorrect.tsx b/src/assets/svg/Incorrect.tsx deleted file mode 100644 index 435cbb2..0000000 --- a/src/assets/svg/Incorrect.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgIncorrect = (props: SVGProps) => ( - - - -); -export default SvgIncorrect; diff --git a/src/assets/svg/Unsubmitted.tsx b/src/assets/svg/Unsubmitted.tsx deleted file mode 100644 index a91456d..0000000 --- a/src/assets/svg/Unsubmitted.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgUnsubmitted = (props: SVGProps) => ( - - - -); -export default SvgUnsubmitted; diff --git a/src/assets/svg/index.ts b/src/assets/svg/index.ts deleted file mode 100644 index 28c2871..0000000 --- a/src/assets/svg/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export {default as AddIcon} from './AddIcon'; -export {default as ArrowdownIcon} from './ArrowdownIcon'; -export {default as ArrowleftIcon} from './ArrowleftIcon'; -export {default as ArrowrightIcon} from './ArrowrightIcon'; -export {default as ChatIcon} from './ChatIcon'; -export {default as Chevrondown} from './Chevrondown'; -export {default as Correct} from './Correct'; -export {default as DeleteIcon} from './DeleteIcon'; -export {default as DragAndDropIcon} from './DragAndDropIcon'; -export {default as EditIcon} from './EditIcon'; -export {default as EllipsisIcon} from './EllipsisIcon'; -export {default as File} from './File'; -export {default as Incorrect} from './Incorrect'; -export {default as NotificationIcon} from './NotificationIcon'; -export {default as SignoutIcon} from './SignoutIcon'; -export {default as SingleEllipsisIcon} from './SingleEllipsisIcon'; -export {default as Unsubmitted} from './Unsubmitted'; -export {default as UserIcon} from './UserIcon'; diff --git a/src/components/common/Badge.tsx b/src/components/common/Badge.tsx index eed8d2b..e75c5c7 100644 --- a/src/components/common/Badge.tsx +++ b/src/components/common/Badge.tsx @@ -1,5 +1,7 @@ import {tv, type VariantProps} from 'tailwind-variants/lite'; -import {Correct, Incorrect, Unsubmitted} from '@/assets/svg'; +import Correct from '@/assets/svg/correct.svg?react'; +import Incorrect from '@/assets/svg/incorrect.svg?react'; +import Unsubmitted from '@/assets/svg/unsubmitted.svg?react'; const badgeStyles = tv({ base: 'rounded-full px-3.5 py-1.5 leading-[19px] text-center text-base font-medium border whitespace-nowrap', diff --git a/src/pages/admin/assignments/AssignmentCreatePage.tsx b/src/pages/admin/assignments/AssignmentCreatePage.tsx index 967fcda..24babde 100644 --- a/src/pages/admin/assignments/AssignmentCreatePage.tsx +++ b/src/pages/admin/assignments/AssignmentCreatePage.tsx @@ -4,7 +4,7 @@ import FileUpload from '@/components/admin/form/FileUpload'; import {useState} from 'react'; import LabeledDropdown from '@/components/admin/form/LabeledDropdown'; import Button from '@/components/common/Button'; -import {AddIcon} from '@/assets/svg'; +import AddIcon from '@/assets/svg/addIcon.svg?react'; const AssignmentCreatePage = () => { const [examples, setExamples] = useState([{input: '', output: '', 공개: ''}]); diff --git a/src/pages/common/LandingPage.tsx b/src/pages/common/LandingPage.tsx index 49f73a8..1b2b1e5 100644 --- a/src/pages/common/LandingPage.tsx +++ b/src/pages/common/LandingPage.tsx @@ -1,10 +1,10 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; -import snowCodeEntry from '/src/assets/images/snowCode_entry.svg'; -import snowCodeStudent from '/src/assets/images/snowCode_student.svg'; -import snowCodeAdmin from '/src/assets/images/snowCode_admin.svg'; -import googleLogo from '/src/assets/images/google_logo.svg'; +import snowCodeEntry from '@/assets/images/snowCode_entry.svg'; +import snowCodeStudent from '@/assets/images/snowCode_student.svg'; +import snowCodeAdmin from '@/assets/images/snowCode_admin.svg'; +import googleLogo from '@/assets/images/google_logo.svg'; import ArrowrightIcon from '@/assets/svg/arrowrightIcon.svg?react'; import Button from '@/components/common/Button'; From 6c4604afd74e50c38f0a14012cf1f887d5706613 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 14:37:40 +0900 Subject: [PATCH 03/31] =?UTF-8?q?#27=20refactor:=20course-overview=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=8F=B4=EB=8D=94=20=EB=B0=8F=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EA=B5=AC=EC=A1=B0=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 2 +- .../{common => course-overview}/CourseOverviewPage.tsx | 8 ++++---- .../dummy => pages/course-overview/models}/response.ts | 0 .../dummy => pages/course-overview/models}/types.ts | 0 .../course-overview/ui}/AssignmentItem.tsx | 2 +- .../course-overview/ui}/AssignmentList.tsx | 0 .../course-overview/ui}/CourseActionsBar.tsx | 0 .../course-overview/ui}/CourseContent.tsx | 2 +- .../course-overview/ui}/CourseHero.tsx | 0 .../course-overview/ui}/CourseStat.tsx | 0 .../course-overview/ui}/EmptyCourse.tsx | 0 .../course-overview/ui}/SubmissionBadge.tsx | 0 .../CourseOverview => pages/course-overview/ui}/Unit.tsx | 0 .../course-overview/ui}/UnitHeader.tsx | 2 +- 14 files changed, 8 insertions(+), 8 deletions(-) rename src/pages/{common => course-overview}/CourseOverviewPage.tsx (76%) rename src/{components/common/CourseOverview/dummy => pages/course-overview/models}/response.ts (100%) rename src/{components/common/CourseOverview/dummy => pages/course-overview/models}/types.ts (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/AssignmentItem.tsx (96%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/AssignmentList.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/CourseActionsBar.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/CourseContent.tsx (88%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/CourseHero.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/CourseStat.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/EmptyCourse.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/SubmissionBadge.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/Unit.tsx (100%) rename src/{components/common/CourseOverview => pages/course-overview/ui}/UnitHeader.tsx (95%) diff --git a/src/App.tsx b/src/App.tsx index 313d1b5..b0139e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,7 @@ import UserIdInputPage from './pages/common/UserIdInputPage'; import Dashboard from './pages/common/Dashboard'; import AssignmentsPage from './pages/admin/assignments/AssignmentsPage'; import AssignmentSelectPage from './pages/admin/assignments/AssignmentSelectPage'; -import CourseOverviewPage from './pages/common/CourseOverviewPage'; +import CourseOverviewPage from './pages/course-overview/CourseOverviewPage'; import AssignmentCreatePage from './pages/admin/assignments/AssignmentCreatePage'; import CourseCreatePage from './pages/admin/courses/CourseCreatePage'; import StudentManagementPage from './pages/admin/student/studentManagementPage'; diff --git a/src/pages/common/CourseOverviewPage.tsx b/src/pages/course-overview/CourseOverviewPage.tsx similarity index 76% rename from src/pages/common/CourseOverviewPage.tsx rename to src/pages/course-overview/CourseOverviewPage.tsx index ba392a3..67a313a 100644 --- a/src/pages/common/CourseOverviewPage.tsx +++ b/src/pages/course-overview/CourseOverviewPage.tsx @@ -1,7 +1,7 @@ -import CourseContent from '@/components/common/CourseOverview/CourseContent'; -import CourseHero from '@/components/common/CourseOverview/CourseHero'; -import {courseResponse} from '@/components/common/CourseOverview/dummy/response'; -import EmptyCourse from '@/components/common/CourseOverview/EmptyCourse'; +import CourseContent from './ui/CourseContent'; +import CourseHero from './ui/CourseHero'; +import {courseResponse} from '@/pages/course-overview/models/response'; +import EmptyCourse from './ui/EmptyCourse'; function countAssignments() { let assignmentCount = 0; diff --git a/src/components/common/CourseOverview/dummy/response.ts b/src/pages/course-overview/models/response.ts similarity index 100% rename from src/components/common/CourseOverview/dummy/response.ts rename to src/pages/course-overview/models/response.ts diff --git a/src/components/common/CourseOverview/dummy/types.ts b/src/pages/course-overview/models/types.ts similarity index 100% rename from src/components/common/CourseOverview/dummy/types.ts rename to src/pages/course-overview/models/types.ts diff --git a/src/components/common/CourseOverview/AssignmentItem.tsx b/src/pages/course-overview/ui/AssignmentItem.tsx similarity index 96% rename from src/components/common/CourseOverview/AssignmentItem.tsx rename to src/pages/course-overview/ui/AssignmentItem.tsx index 3167e46..79ddc82 100644 --- a/src/components/common/CourseOverview/AssignmentItem.tsx +++ b/src/pages/course-overview/ui/AssignmentItem.tsx @@ -1,5 +1,5 @@ import type {Assignment} from '@/components/admin/assignments/dummy/types'; -import Badge from '../Badge'; +import Badge from '@/components/common/Badge'; interface AssignmentItemProps extends Assignment { index: number; diff --git a/src/components/common/CourseOverview/AssignmentList.tsx b/src/pages/course-overview/ui/AssignmentList.tsx similarity index 100% rename from src/components/common/CourseOverview/AssignmentList.tsx rename to src/pages/course-overview/ui/AssignmentList.tsx diff --git a/src/components/common/CourseOverview/CourseActionsBar.tsx b/src/pages/course-overview/ui/CourseActionsBar.tsx similarity index 100% rename from src/components/common/CourseOverview/CourseActionsBar.tsx rename to src/pages/course-overview/ui/CourseActionsBar.tsx diff --git a/src/components/common/CourseOverview/CourseContent.tsx b/src/pages/course-overview/ui/CourseContent.tsx similarity index 88% rename from src/components/common/CourseOverview/CourseContent.tsx rename to src/pages/course-overview/ui/CourseContent.tsx index 1a36212..039719c 100644 --- a/src/components/common/CourseOverview/CourseContent.tsx +++ b/src/pages/course-overview/ui/CourseContent.tsx @@ -1,4 +1,4 @@ -import type {UnitInfo} from './dummy/types'; +import type {UnitInfo} from '../models/types'; import Unit from './Unit'; interface CourseContentProps { diff --git a/src/components/common/CourseOverview/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx similarity index 100% rename from src/components/common/CourseOverview/CourseHero.tsx rename to src/pages/course-overview/ui/CourseHero.tsx diff --git a/src/components/common/CourseOverview/CourseStat.tsx b/src/pages/course-overview/ui/CourseStat.tsx similarity index 100% rename from src/components/common/CourseOverview/CourseStat.tsx rename to src/pages/course-overview/ui/CourseStat.tsx diff --git a/src/components/common/CourseOverview/EmptyCourse.tsx b/src/pages/course-overview/ui/EmptyCourse.tsx similarity index 100% rename from src/components/common/CourseOverview/EmptyCourse.tsx rename to src/pages/course-overview/ui/EmptyCourse.tsx diff --git a/src/components/common/CourseOverview/SubmissionBadge.tsx b/src/pages/course-overview/ui/SubmissionBadge.tsx similarity index 100% rename from src/components/common/CourseOverview/SubmissionBadge.tsx rename to src/pages/course-overview/ui/SubmissionBadge.tsx diff --git a/src/components/common/CourseOverview/Unit.tsx b/src/pages/course-overview/ui/Unit.tsx similarity index 100% rename from src/components/common/CourseOverview/Unit.tsx rename to src/pages/course-overview/ui/Unit.tsx diff --git a/src/components/common/CourseOverview/UnitHeader.tsx b/src/pages/course-overview/ui/UnitHeader.tsx similarity index 95% rename from src/components/common/CourseOverview/UnitHeader.tsx rename to src/pages/course-overview/ui/UnitHeader.tsx index 3f3bf47..dcc5eff 100644 --- a/src/components/common/CourseOverview/UnitHeader.tsx +++ b/src/pages/course-overview/ui/UnitHeader.tsx @@ -1,5 +1,5 @@ import lock from '@/assets/images/lock.svg'; -import Badge from '../Badge'; +import Badge from '@/components/common/Badge'; interface UnitHeaderProps { index: number; From 4500ca895c550e88c9a91ec681813a85d63e41f4 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 15:42:49 +0900 Subject: [PATCH 04/31] =?UTF-8?q?#27=20feat:=20API=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=83=80=EC=9E=85(ApiResponse)=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/common.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/models/common.ts diff --git a/src/models/common.ts b/src/models/common.ts new file mode 100644 index 0000000..dfba890 --- /dev/null +++ b/src/models/common.ts @@ -0,0 +1,8 @@ +/** + * API 공통 응답 타입 + */ + +export interface ApiResponse { + success: boolean; + response: T; +} From 045a289b0b16926f2ce32829cde90edba74ebc26 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 15:46:27 +0900 Subject: [PATCH 05/31] =?UTF-8?q?#27=20refactor:=20=EC=BD=94=EC=8A=A4=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=ED=83=80=EC=9E=85=EC=9D=84=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EB=B3=84=20=EC=A0=95=EC=9D=98?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=9E=AC=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=ED=99=94=20(course.ts=EB=A1=9C=20=ED=86=B5=ED=95=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/course.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/models/course.ts diff --git a/src/models/course.ts b/src/models/course.ts new file mode 100644 index 0000000..c9c502d --- /dev/null +++ b/src/models/course.ts @@ -0,0 +1,44 @@ +import type {ApiResponse} from './common'; + +// 학기 및 제출 상태 상수 타입 정의 +export type SemesterCode = 'FIRST' | 'SECOND' | 'SUMMER' | 'WINTER'; +export type SubmissionStatus = 'NOT_SUBMITTED' | 'CORRECT' | 'INCORRECT'; + +// 과제(Assignment) 인터페이스 정의 +export interface Assignment { + id: number; + title: string; + submittedStatus: SubmissionStatus; +} + +// 단원(Unit) 인터페이스 정의 +export interface Unit { + id: number; + title: string; + releaseDate: string; + dueDate: string; + isOpen?: boolean; + assignmentCount: number; + assignments: Assignment[]; +} + +// 베이스 강의(Course) 인터페이스 정의 (공통 필드) +export interface BaseCourse { + id: number; + title: string; + year: number; + semester: SemesterCode; + section: string; + unitCount: number; +} + +/** + * 강의 상세 페이지용 (course-overview) 인터페이스 정의 + * 기본 정보 + 단원, 과제 상세 리스트 + */ +export interface CourseOverview extends BaseCourse { + studentCount?: number; + units: Unit[]; +} + +export type CourseOverviewResponse = ApiResponse; From f4fe1888c24ef655ebd39248f72a4717c01473db Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 16:55:43 +0900 Subject: [PATCH 06/31] =?UTF-8?q?#27=20refactor:=20CourseHeroProps=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20=EB=B0=A9=EC=8B=9D=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=EB=B0=8F=20import=20=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course-overview/CourseOverviewPage.tsx | 10 ++---- src/pages/course-overview/models/response.ts | 4 +-- src/pages/course-overview/models/types.ts | 33 ------------------- src/pages/course-overview/ui/CourseHero.tsx | 26 +++++---------- src/pages/course-overview/ui/Unit.tsx | 2 +- 5 files changed, 15 insertions(+), 60 deletions(-) delete mode 100644 src/pages/course-overview/models/types.ts diff --git a/src/pages/course-overview/CourseOverviewPage.tsx b/src/pages/course-overview/CourseOverviewPage.tsx index 67a313a..fd6c273 100644 --- a/src/pages/course-overview/CourseOverviewPage.tsx +++ b/src/pages/course-overview/CourseOverviewPage.tsx @@ -12,19 +12,15 @@ function countAssignments() { return assignmentCount; } -const isActiveCourse = courseResponse.response.unitCount !== 0; +const courseData = courseResponse.response; +const isActiveCourse = courseData.unitCount > 0; const CourseOverviewPage = () => { return (
{isActiveCourse ? ( diff --git a/src/pages/course-overview/models/response.ts b/src/pages/course-overview/models/response.ts index 7a83642..622f875 100644 --- a/src/pages/course-overview/models/response.ts +++ b/src/pages/course-overview/models/response.ts @@ -1,6 +1,6 @@ -import type {CourseResponse} from './types'; +import type {CourseOverviewResponse} from '@/models/Course'; -export const courseResponse: CourseResponse = { +export const courseResponse: CourseOverviewResponse = { success: true, response: { id: 1, diff --git a/src/pages/course-overview/models/types.ts b/src/pages/course-overview/models/types.ts deleted file mode 100644 index 1d01bec..0000000 --- a/src/pages/course-overview/models/types.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { - Assignment, - SemesterCode, -} from '@/components/admin/assignments/dummy/types'; - -// unit branch merge되면 삭제 -interface UnitInfo { - id: number; - title: string; - releaseDate: string; - dueDate: string; - isOpen?: boolean; - assignmentCount: number; - assignments: Assignment[]; -} - -interface CourseInfo { - id: number; - title: string; - year: number; - semester: SemesterCode; - section: string; - studentCount?: number; - unitCount: number; - units: UnitInfo[]; -} - -interface CourseResponse { - success: boolean; - response: CourseInfo; -} - -export type {UnitInfo, CourseInfo, CourseResponse}; diff --git a/src/pages/course-overview/ui/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx index a9dcd4a..c3c7616 100644 --- a/src/pages/course-overview/ui/CourseHero.tsx +++ b/src/pages/course-overview/ui/CourseHero.tsx @@ -1,34 +1,26 @@ -import {useLocation} from 'react-router-dom'; import snowcodeOverviewMini from '@/assets/images/snowcode_overview_mini.svg'; +import {useLocation} from 'react-router-dom'; import {getSemesterLabel} from '@/utils/getSemesterLabel'; -import type {SemesterCode} from '@/components/admin/assignments/dummy/types'; import CourseActionsBar from './CourseActionsBar'; -import CourseStat from './CourseStat'; +import CourseStat from './CourseStats'; +import type {CourseOverview} from '@/models/Course'; -interface CoursHeroProps { - title: string; - year: number; - semester: SemesterCode; - section: string; - unitCount: number; +interface CourseHeroProps { + courseData: Omit; assignmentCount: number; - studentCount?: number; isActiveCourse: boolean; } const CourseHero = ({ - title, - year, - semester, - section, - unitCount, + courseData, assignmentCount, - studentCount, isActiveCourse, -}: CoursHeroProps) => { +}: CourseHeroProps) => { const pathname = useLocation().pathname; const isAdmin = pathname.startsWith('/admin'); + const {title, year, semester, section, unitCount, studentCount} = courseData; + return (
{isAdmin && isActiveCourse && ( diff --git a/src/pages/course-overview/ui/Unit.tsx b/src/pages/course-overview/ui/Unit.tsx index 3fe5e11..da21b56 100644 --- a/src/pages/course-overview/ui/Unit.tsx +++ b/src/pages/course-overview/ui/Unit.tsx @@ -1,5 +1,5 @@ import AssignmentList from './AssignmentList'; -import type {UnitInfo} from './dummy/types'; +import type {UnitInfo} from '../models/types'; import UnitHeader from './UnitHeader'; interface UnitProps extends UnitInfo { From 889eaeaf6d8ad2e94f526684a476b4f3c14d34e9 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 16:58:30 +0900 Subject: [PATCH 07/31] =?UTF-8?q?#27=20refactor:=20=ED=95=99=EA=B8=B0=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=ED=8C=85=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20=EB=B0=8F=20=ED=83=80=EC=9E=85=20=EC=95=88=EC=A0=95?= =?UTF-8?q?=EC=84=B1=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course-overview/ui/CourseHero.tsx | 6 +++--- src/utils/course.ts | 13 +++++++++++++ src/utils/getSemesterLabel.ts | 12 ------------ 3 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 src/utils/course.ts delete mode 100644 src/utils/getSemesterLabel.ts diff --git a/src/pages/course-overview/ui/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx index c3c7616..b69c4f2 100644 --- a/src/pages/course-overview/ui/CourseHero.tsx +++ b/src/pages/course-overview/ui/CourseHero.tsx @@ -1,9 +1,9 @@ import snowcodeOverviewMini from '@/assets/images/snowcode_overview_mini.svg'; import {useLocation} from 'react-router-dom'; -import {getSemesterLabel} from '@/utils/getSemesterLabel'; import CourseActionsBar from './CourseActionsBar'; import CourseStat from './CourseStats'; -import type {CourseOverview} from '@/models/Course'; +import type {CourseOverview} from '@/models/course'; +import {formatSemester} from '@/utils/course'; interface CourseHeroProps { courseData: Omit; @@ -36,7 +36,7 @@ const CourseHero = ({ {title} - {`${year}년 ${getSemesterLabel( + {`${year}년 ${formatSemester( semester )}학기 ${section}분반`} {isActiveCourse && ( diff --git a/src/utils/course.ts b/src/utils/course.ts new file mode 100644 index 0000000..2a13d1e --- /dev/null +++ b/src/utils/course.ts @@ -0,0 +1,13 @@ +import type {SemesterCode} from '@/models/Course'; + +const SEMESTER_MAP: Record = { + FIRST: '1', + SECOND: '2', + SUMMER: '여름', + WINTER: '겨울', +} as const; + +export const formatSemester = (semester: SemesterCode) => { + const label = SEMESTER_MAP[semester]; + return `${label}학기`; +}; diff --git a/src/utils/getSemesterLabel.ts b/src/utils/getSemesterLabel.ts deleted file mode 100644 index f7d03a8..0000000 --- a/src/utils/getSemesterLabel.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type {SemesterCode} from '@/components/admin/assignments/dummy/types'; - -const SEMESTER_LABEL: Record = { - FIRST: '1', - SECOND: '2', - SUMMER: '여름', - WINTER: '겨울', -}; - -export const getSemesterLabel = (semester: SemesterCode) => { - return SEMESTER_LABEL[semester]; -}; From 169deab328fdbce2a574dd0cb8684e68a170465c Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 18:22:28 +0900 Subject: [PATCH 08/31] =?UTF-8?q?#27=20style:=20bg-radial-gradient=20?= =?UTF-8?q?=EC=9C=A0=ED=8B=B8=EB=A6=AC=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/index.css b/src/index.css index 26c7fe3..0749065 100644 --- a/src/index.css +++ b/src/index.css @@ -62,6 +62,10 @@ @apply flex items-center justify-center; } +@utility bg-radial-gradient { + @apply bg-radial-[80%_74%_at_34%_0%] from-[#AC9BFF] from-0% to-[#7D63FF] to-100%; +} + .header-btn { @apply bg-primary w-16 h-16 rounded-full flex-center; } From 0b822025d816836fc24a079f7da8db112a01c8d3 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 18:23:41 +0900 Subject: [PATCH 09/31] =?UTF-8?q?#27=20refactor:=20CourseHero=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course-overview/ui/CourseHero.tsx | 74 +++++++++++++++------ src/pages/course-overview/ui/CourseStat.tsx | 21 ------ 2 files changed, 54 insertions(+), 41 deletions(-) delete mode 100644 src/pages/course-overview/ui/CourseStat.tsx diff --git a/src/pages/course-overview/ui/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx index b69c4f2..792417e 100644 --- a/src/pages/course-overview/ui/CourseHero.tsx +++ b/src/pages/course-overview/ui/CourseHero.tsx @@ -1,9 +1,8 @@ import snowcodeOverviewMini from '@/assets/images/snowcode_overview_mini.svg'; import {useLocation} from 'react-router-dom'; -import CourseActionsBar from './CourseActionsBar'; -import CourseStat from './CourseStats'; import type {CourseOverview} from '@/models/course'; import {formatSemester} from '@/utils/course'; +import Button from '@/components/common/Button'; interface CourseHeroProps { courseData: Omit; @@ -11,7 +10,7 @@ interface CourseHeroProps { isActiveCourse: boolean; } -const CourseHero = ({ +export const CourseHero = ({ courseData, assignmentCount, isActiveCourse, @@ -22,31 +21,66 @@ const CourseHero = ({ const {title, year, semester, section, unitCount, studentCount} = courseData; return ( -
+
{isAdmin && isActiveCourse && ( -
- -
+ )} - logo - - {title} - - {`${year}년 ${formatSemester( - semester - )}학기 ${section}분반`} + + + {isActiveCourse && ( - )} -
+ + ); +}; + +const CourseInfo = ({title, year, semester, section}: any) => { + const courseInfo = `${year}년 ${formatSemester(semester)} ${section}분반`; + + return ( +
+ logo +

{title}

+

{courseInfo}

+
+ ); +}; + +const CourseStats = ({ + unitCount, + assignmentCount, + studentCount, + isAdmin, +}: any) => { + const studentInfo = isAdmin && studentCount ? ` | ${studentCount}명` : ''; + const courseStats = `${unitCount}단원 | ${assignmentCount}문제${studentInfo}`; + + return ( +
+ {courseStats} +
+ ); +}; + +const CourseActionsBar = () => { + return ( +
+ + +
); }; diff --git a/src/pages/course-overview/ui/CourseStat.tsx b/src/pages/course-overview/ui/CourseStat.tsx deleted file mode 100644 index 4d3046a..0000000 --- a/src/pages/course-overview/ui/CourseStat.tsx +++ /dev/null @@ -1,21 +0,0 @@ -interface CourseStatProps { - unitCount: number; - assignmentCount: number; - studentCount?: number; -} - -const CourseStat = ({ - unitCount, - assignmentCount, - studentCount, -}: CourseStatProps) => { - return ( -
- {`${unitCount}단원 | ${assignmentCount}문제 ${ - studentCount ? `| ${studentCount}명` : '' - }`} -
- ); -}; - -export default CourseStat; From 3a90705250624418175dc5560f1819b5b3d7022d Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 19:00:47 +0900 Subject: [PATCH 10/31] =?UTF-8?q?#27=20refactor:=20CourseActionsBar=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course-overview/ui/CourseActionsBar.tsx | 25 ----------- src/pages/course-overview/ui/CourseHero.tsx | 44 ++++++++++++------- 2 files changed, 29 insertions(+), 40 deletions(-) delete mode 100644 src/pages/course-overview/ui/CourseActionsBar.tsx diff --git a/src/pages/course-overview/ui/CourseActionsBar.tsx b/src/pages/course-overview/ui/CourseActionsBar.tsx deleted file mode 100644 index c2087b3..0000000 --- a/src/pages/course-overview/ui/CourseActionsBar.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import {useNavigate} from 'react-router-dom'; -import Button from '@/components/common/Button'; - -interface CourseActionsBarProps { - isActive: boolean; - title: string; - section: string; -} - -const CourseActionsBar = ({isActive, title, section}: CourseActionsBarProps) => { - const navigate = useNavigate(); - - const handleStudentListClick = () => { - navigate(`/admin/student?course=${title} (${section})`); - }; - - return ( -
- - -
- ); -}; - -export default CourseActionsBar; diff --git a/src/pages/course-overview/ui/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx index 792417e..53864e1 100644 --- a/src/pages/course-overview/ui/CourseHero.tsx +++ b/src/pages/course-overview/ui/CourseHero.tsx @@ -1,5 +1,5 @@ import snowcodeOverviewMini from '@/assets/images/snowcode_overview_mini.svg'; -import {useLocation} from 'react-router-dom'; +import {Link, useLocation} from 'react-router-dom'; import type {CourseOverview} from '@/models/course'; import {formatSemester} from '@/utils/course'; import Button from '@/components/common/Button'; @@ -21,12 +21,8 @@ export const CourseHero = ({ const {title, year, semester, section, unitCount, studentCount} = courseData; return ( -
- {isAdmin && isActiveCourse && ( - - )} +
+ {isAdmin && isActiveCourse && } { +type CourseInfoProps = Pick< + CourseHeroProps['courseData'], + 'title' | 'year' | 'semester' | 'section' +>; + +const CourseInfo = ({title, year, semester, section}: CourseInfoProps) => { const courseInfo = `${year}년 ${formatSemester(semester)} ${section}분반`; return (
- logo + snowCode logo

{title}

{courseInfo}

); }; +interface CourseStatsProps + extends Pick { + assignmentCount: CourseHeroProps['assignmentCount']; + isAdmin: boolean; +} + const CourseStats = ({ unitCount, assignmentCount, studentCount, isAdmin, -}: any) => { - const studentInfo = isAdmin && studentCount ? ` | ${studentCount}명` : ''; +}: CourseStatsProps) => { + const studentInfo = + isAdmin && studentCount !== undefined ? ` | ${studentCount}명` : ''; const courseStats = `${unitCount}단원 | ${assignmentCount}문제${studentInfo}`; return ( @@ -77,10 +85,16 @@ const CourseStats = ({ const CourseActionsBar = () => { return ( -
- - -
+ ); }; From 8c699a25d1118dadaa46d9bd6b201c555dbecf7c Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 19:01:54 +0900 Subject: [PATCH 11/31] =?UTF-8?q?#27=20fix:=20import=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course-overview/models/response.ts | 2 +- src/utils/course.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/course-overview/models/response.ts b/src/pages/course-overview/models/response.ts index 622f875..9f00196 100644 --- a/src/pages/course-overview/models/response.ts +++ b/src/pages/course-overview/models/response.ts @@ -1,4 +1,4 @@ -import type {CourseOverviewResponse} from '@/models/Course'; +import type {CourseOverviewResponse} from '@/models/course'; export const courseResponse: CourseOverviewResponse = { success: true, diff --git a/src/utils/course.ts b/src/utils/course.ts index 2a13d1e..097324b 100644 --- a/src/utils/course.ts +++ b/src/utils/course.ts @@ -1,4 +1,4 @@ -import type {SemesterCode} from '@/models/Course'; +import type {SemesterCode} from '@/models/course'; const SEMESTER_MAP: Record = { FIRST: '1', From 4e4e771bb83c492ff360da74dd8b0e8b533ef6f9 Mon Sep 17 00:00:00 2001 From: suminb99 Date: Wed, 14 Jan 2026 19:05:35 +0900 Subject: [PATCH 12/31] =?UTF-8?q?#27=20feat:=20CourseHero=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/course-overview/ui/CourseHero.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/course-overview/ui/CourseHero.tsx b/src/pages/course-overview/ui/CourseHero.tsx index 53864e1..7cc9a81 100644 --- a/src/pages/course-overview/ui/CourseHero.tsx +++ b/src/pages/course-overview/ui/CourseHero.tsx @@ -4,6 +4,7 @@ import type {CourseOverview} from '@/models/course'; import {formatSemester} from '@/utils/course'; import Button from '@/components/common/Button'; +// 강의 상세 페이지 - Hero 섹션 interface CourseHeroProps { courseData: Omit; assignmentCount: number; @@ -15,6 +16,7 @@ export const CourseHero = ({ assignmentCount, isActiveCourse, }: CourseHeroProps) => { + // 관리자 경로 확인 const pathname = useLocation().pathname; const isAdmin = pathname.startsWith('/admin'); @@ -43,6 +45,7 @@ export const CourseHero = ({ ); }; +// 강의 정보 표시 type CourseInfoProps = Pick< CourseHeroProps['courseData'], 'title' | 'year' | 'semester' | 'section' @@ -60,6 +63,7 @@ const CourseInfo = ({title, year, semester, section}: CourseInfoProps) => { ); }; +// 강의 Stats 표시 interface CourseStatsProps extends Pick { assignmentCount: CourseHeroProps['assignmentCount']; @@ -83,6 +87,7 @@ const CourseStats = ({ ); }; +// 강의 관리 버튼 바 (관리자 전용) const CourseActionsBar = () => { return (