From 09ac371a4c0552759b43237539362f0248a95c04 Mon Sep 17 00:00:00 2001 From: SeieunYoo <101736358+SeieunYoo@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:53:53 +0200 Subject: [PATCH] =?UTF-8?q?[Refactor]=20=EA=B3=BC=EC=A0=9C=20api=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20=EB=B0=8F=20=EB=B0=94=EB=80=90=20dto=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20(#114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 큐에이 반영 * fix: 소문자로 변경 * refactor: api dto 반영, 이번 주 과제 조회 api 연결 * feat: 히스토리 api 수정된 dto 반영 * feat: 히스토리 api 수정된 거 반영, 레포지토리 입력 api 반영 * refactor: 레포 모달 창 상태 관리 컴포넌트로 벼녕 * feat: 필요없는 로직 삭제 * feat: 이번 주 과제 조회 스터디 추가 * feat: 모달 라우팅 삭제 * feat: submissionLink 에서 폴더 * chore: 안쓰는 상수 삭제 * chore: 말줄임 처리, github url 인지 체크 * feat: 스터디 시작 날짜가 현재 날짜인지 확인하고 disabled 처리 * feat: 공통 타입은 common 으로 옮기기, 리뷰 반영 * fix: 빠진 네이밍 수정 반영 * feat: Button asProp 으로 Link 전달, css 수정 * refactor: NonNullable 처리, Initial 로 관리 * feat: github 관련 유틸 분리,css 수정 * chore: 필요없는 프래그먼트 삭제 * chore: cache 속서 추가 * feat: currentPath href 매치될 때만 active 되게 navItem 수정 * chore: myStudy 용 타입 추가 * chore: EDITING_WITH_WARNING 타입 삭제, 상태 네이밍 변경 * chore: 조건식 간소화 * chore: submissionLink null 로 내려오는 부분 우선 삭제 --- apps/client/apis/studyDetailApi.ts | 17 +- .../(.)repository-url/confirmation/page.tsx | 46 --- .../@modal/(.)repository-url/default.tsx | 5 - .../my-study/my-assignment/@modal/default.tsx | 5 - .../AssignmentBoxButtons.tsx | 122 ++++++-- .../AssignmentBoxInfo.tsx | 14 +- .../AssignmentBoxTitle.tsx | 21 +- .../AssignmentOverviewBox/FailurePopover.tsx | 4 +- .../AssignmentOverviewBox/index.tsx | 12 +- .../AssignmentContent/EmptyAssignmentBox.tsx | 16 +- .../RepositorySubmissionBox.tsx | 275 +++++++++++------- .../_components/AssignmentContent/index.tsx | 39 ++- .../_components/AssignmentDescription.tsx | 25 +- .../_components/AssignmentHeader.tsx | 16 +- .../AssignmentHistoryItem.tsx | 81 ++++-- .../_components/AssignmentHistory/index.tsx | 19 +- .../my-study/my-assignment/layout.tsx | 17 +- .../repository-url/confirmation/page.tsx | 8 - apps/client/components/Navbar.tsx | 2 +- apps/client/components/Tooltip.tsx | 1 + apps/client/constants/assignmentMockData.ts | 51 ++-- .../assignmentSubmissionStatusMap.ts | 12 - apps/client/constants/navMenu.ts | 18 +- apps/client/constants/routePath.ts | 2 - apps/client/constants/tags.ts | 1 + apps/client/hooks/useMatchedStudyHistoryId.ts | 33 --- apps/client/types/dtos/myStudy.ts | 6 +- apps/client/types/dtos/studyDetail.ts | 9 +- apps/client/types/dtos/studyHistory.ts | 8 +- .../types/entities/common/assignment.ts | 6 +- apps/client/types/entities/myAssignment.ts | 5 +- apps/client/types/entities/myStudy.ts | 13 +- .../utils/getAssignmentGithubFolderName.ts | 10 + apps/client/utils/getIsAfterStartDate.ts | 5 + apps/client/utils/index.ts | 1 - apps/client/utils/isDeadlinePassed.ts | 4 +- apps/client/utils/isGithubRepositoryUrl.ts | 5 + packages/ui/src/components/NavItem/index.tsx | 5 +- 38 files changed, 535 insertions(+), 404 deletions(-) delete mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx delete mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx delete mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx delete mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx delete mode 100644 apps/client/constants/assignmentSubmissionStatusMap.ts delete mode 100644 apps/client/hooks/useMatchedStudyHistoryId.ts create mode 100644 apps/client/utils/getAssignmentGithubFolderName.ts create mode 100644 apps/client/utils/getIsAfterStartDate.ts delete mode 100644 apps/client/utils/index.ts create mode 100644 apps/client/utils/isGithubRepositoryUrl.ts diff --git a/apps/client/apis/studyDetailApi.ts b/apps/client/apis/studyDetailApi.ts index 06e2a04e..508e8372 100644 --- a/apps/client/apis/studyDetailApi.ts +++ b/apps/client/apis/studyDetailApi.ts @@ -1,7 +1,10 @@ import { fetcher } from "@wow-class/utils"; import { apiPath } from "constants/apiPath"; import { tags } from "constants/tags"; -import type { StudyDetailDashboardDto } from "types/dtos/studyDetail"; +import type { + StudyDetailDashboardDto, + UpcomingStudyDto, +} from "types/dtos/studyDetail"; export const studyDetailApi = { getStudyDetailDashboard: async (studyId: number) => { @@ -9,6 +12,18 @@ export const studyDetailApi = { `${apiPath.studyDetail}/dashboard?studyId=${studyId}`, { next: { tags: [tags.studyDetailDashboard] }, + cache: "force-cache", + } + ); + + return response.data; + }, + getUpcomingStudy: async (studyId: number) => { + const response = await fetcher.get( + `${apiPath.studyDetail}/upcoming?studyId=${studyId}`, + { + next: { tags: [tags.upcomingStudy] }, + cache: "force-cache", } ); diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx deleted file mode 100644 index 4c98645a..00000000 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx +++ /dev/null @@ -1,46 +0,0 @@ -"use client"; - -import { css } from "@styled-system/css"; -import { Flex } from "@styled-system/jsx"; -import { Modal, Space, Text } from "@wow-class/ui"; -import { tags } from "constants/tags"; -import useMatchedStudyHistoryId from "hooks/useMatchedStudyHistoryId"; -import { useSearchParams } from "next/navigation"; -import { revalidateTagByName } from "utils/revalidateTagByName"; -import Button from "wowds-ui/Button"; - -const RepositoryUrlConfirmationModal = () => { - const searchParams = useSearchParams(); - const url = searchParams.get("repositoryUrl"); - //const studyHistoryId = useMatchedStudyHistoryId(); - - const handleClickSubmitButton = async () => { - //await studyHistoryApi.putRepository(studyHistoryId, url); - //TODO: 제출 후에 RepositoryBox 를 SUBMITTED 로 상태로 바꿔줘야함. - revalidateTagByName(tags.studyDetailDashboard); - }; - return ( - - - 레포지토리를 입력하시겠어요? - - 최초 과제 제출 전까지 수정이 가능해요. - -
{url}
- - -
-
- ); -}; - -export default RepositoryUrlConfirmationModal; - -const urlBoxStyle = css({ - backgroundColor: "backgroundAlternative", - borderRadius: "5px", - color: "sub", - paddingX: "lg", - paddingY: "md", - textStyle: "h2", -}); diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx deleted file mode 100644 index 395785b9..00000000 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const Default = () => { - return null; -}; - -export default Default; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx deleted file mode 100644 index 395785b9..00000000 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const Default = () => { - return null; -}; - -export default Default; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx index ea9b7bbe..32c7ab77 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx @@ -1,29 +1,67 @@ "use client"; import { Space } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; +import { studyDetailApi } from "apis/studyDetailApi"; import { studyHistoryApi } from "apis/studyHistoryApi"; import { tags } from "constants/tags"; import Link from "next/link"; +import { useEffect, useState } from "react"; import type { Assignment } from "types/dtos/studyDetail"; import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment"; -import { isDeadlinePassed } from "utils"; +import { getIsAfterStartDate } from "utils/getIsAfterStartDate"; +import { isDeadlinePassed } from "utils/isDeadlinePassed"; import { revalidateTagByName } from "utils/revalidateTagByName"; import { Link as LinkIcon, Reload as ReloadIcon } from "wowds-icons"; import Button from "wowds-ui/Button"; - interface AssignmentBoxButtonsProps { assignment: Assignment; buttonsDisabled?: boolean; } export const AssignmentBoxButtons = ({ - ...rest + buttonsDisabled: buttonDisabledProp, + assignment, }: AssignmentBoxButtonsProps) => { + const [startDate, setStartDate] = useState(""); + + const targetWeek = assignment.week; + + useEffect(() => { + const fetchAssignmentStartDate = async () => { + const ongoingStudyInfo = await myStudyApi.getMyOngoingStudyInfo(); + + if (ongoingStudyInfo?.studyId) { + const curriculumData = await myStudyApi.getStudyCurriculumList( + ongoingStudyInfo.studyId + ); + + const matchingWeek = curriculumData?.find( + (item) => item.week === targetWeek + ); + + if (matchingWeek) { + setStartDate(matchingWeek.period.startDate); + } + } + }; + + fetchAssignmentStartDate(); + }, [targetWeek]); + + const buttonsDisabled = buttonDisabledProp || !getIsAfterStartDate(startDate); + return ( <> - + - + ); }; @@ -31,9 +69,34 @@ const PrimaryButton = ({ assignment, buttonsDisabled, }: AssignmentBoxButtonsProps) => { + const [repositoryLink, setRepositoryLink] = useState(""); + + useEffect(() => { + const fetchStudyDashBoard = async () => { + const ongoingStudyInfo = await myStudyApi.getMyOngoingStudyInfo(); + if (!ongoingStudyInfo) { + return; + } + const studyDashboard = await studyDetailApi.getStudyDetailDashboard( + ongoingStudyInfo.studyId + ); + + if (!studyDashboard) { + return; + } else { + setRepositoryLink(studyDashboard.repositoryLink); + } + }; + + fetchStudyDashBoard(); + }, []); + const { assignmentSubmissionStatus, submissionFailureType, submissionLink } = assignment; - const { primaryButtonText } = buttonProps[assignmentSubmissionStatus]; + const { primaryButtonText } = + assignmentSubmissionStatus === null + ? buttonTextMap.INITIAL + : buttonTextMap[assignmentSubmissionStatus]; if ( assignmentSubmissionStatus === "FAILURE" && @@ -42,17 +105,21 @@ const PrimaryButton = ({ return; } const stroke = buttonsDisabled ? "mono100" : "primary"; + const link = + assignmentSubmissionStatus === null ? repositoryLink : submissionLink; + return ( - - - + ); }; @@ -62,13 +129,21 @@ const SecondaryButton = ({ }: AssignmentBoxButtonsProps) => { const { assignmentSubmissionStatus, studyDetailId, deadline, committedAt } = assignment; - const { secondaryButtonText } = buttonProps[assignmentSubmissionStatus]; + const { secondaryButtonText } = + assignmentSubmissionStatus === null + ? buttonTextMap.INITIAL + : buttonTextMap[assignmentSubmissionStatus]; const handleClickSubmissionComplete = async () => { const response = await studyHistoryApi.submitAssignment(studyDetailId); if (response.success) { //TODO: 과제 제출 이후에는 과제 상태에 대한 업데이트 필요 //이번주 과제 조회 api, 대시보드 api revaliate - revalidateTagByName(tags.studyDetailDashboard); + revalidateTagByName( + assignmentSubmissionStatus === null + ? tags.studyDetailDashboard + : tags.upcomingStudy + ); + revalidateTagByName(tags.studyHistory); } }; @@ -98,13 +173,16 @@ const SecondaryButton = ({ const buttonStyle = { maxWidth: "100%", + height: "48px !important", }; -const buttonProps: Record< - AssignmentSubmissionStatusType, +const buttonTextMap: Record< + NonNullable, { primaryButtonText: string; secondaryButtonText: string } -> = { - PENDING: { +> & { + INITIAL: { primaryButtonText: string; secondaryButtonText: string }; +} = { + INITIAL: { primaryButtonText: "제출하러 가기", secondaryButtonText: "제출 완료하기", }, diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx index ffe1a2e3..496d14dc 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx @@ -9,9 +9,15 @@ interface AssignmentBoxInfoProps { assignment: Assignment; } -export const AssignmentBoxInfo = ({ assignment }: AssignmentBoxInfoProps) => { - const { deadline, title, assignmentSubmissionStatus, submissionFailureType } = - assignment; +export const AssignmentBoxInfo = async ({ + assignment, +}: AssignmentBoxInfoProps) => { + const { + deadline, + assignmentSubmissionStatus, + submissionFailureType, + submissionLink, + } = assignment; const { year, month, day, hours, minutes } = parseISODate(deadline); @@ -31,7 +37,7 @@ export const AssignmentBoxInfo = ({ assignment }: AssignmentBoxInfoProps) => { 제출한 과제 - {title} + 과제 이름 dot diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx index 1709d13e..9089dbc4 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx @@ -12,7 +12,9 @@ interface AssignmentBoxTitleProps { export const AssignmentBoxTitle = ({ assignment }: AssignmentBoxTitleProps) => { const { week, title, assignmentSubmissionStatus } = assignment; const { color, message } = - assignmentSubmissionMap[assignmentSubmissionStatus]; + assignmentSubmissionStatus === null + ? assignmentSubmissionMap.INITIAL + : assignmentSubmissionMap[assignmentSubmissionStatus]; return ( <> @@ -21,10 +23,10 @@ export const AssignmentBoxTitle = ({ assignment }: AssignmentBoxTitleProps) => { - + {title} - {assignmentSubmissionStatus !== "PENDING" && ( + {assignmentSubmissionStatus !== null && ( {message} @@ -34,10 +36,17 @@ export const AssignmentBoxTitle = ({ assignment }: AssignmentBoxTitleProps) => { ); }; +const textStyle = { + textOverflow: "ellipsis", + whiteSpace: "nowrap", + overflow: "hidden", +}; const assignmentSubmissionMap: Record< - AssignmentSubmissionStatusType, + NonNullable, { message: string; color: ComponentProps["color"] } -> = { +> & { + INITIAL: { message: string; color: ComponentProps["color"] }; +} = { FAILURE: { message: "제출 실패", color: "red", @@ -46,7 +55,7 @@ const assignmentSubmissionMap: Record< message: "제출 완료", color: "blue", }, - PENDING: { + INITIAL: { message: "", color: "grey", }, diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx index a899d8cf..9e9b98cb 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx @@ -1,11 +1,11 @@ import { Flex } from "@styled-system/jsx"; import { Text } from "@wow-class/ui"; import Popover from "components/Popover"; -import type { SubmissionFailureType } from "types/entities/common/assignment"; +import type { AssignmentSubmissionFailureType } from "types/entities/common/assignment"; import { Help as HelpIcon } from "wowds-icons"; interface FailurePopoverProps { - submissionFailureType: SubmissionFailureType; + submissionFailureType: AssignmentSubmissionFailureType; } export const FailurePopover = ({ submissionFailureType, diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx index ba4c72e4..5104abad 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx @@ -27,9 +27,13 @@ export const AssignmentOverviewBox = ({ text={ <> - - - + { +export const EmptyAssignmentBox = () => { return ( - - {week}주차 - - - - 과제가 없어요 - - + + 과제가 없어요 + } /> ); diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx index d59197c5..83db2729 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx @@ -2,12 +2,16 @@ import { css } from "@styled-system/css"; import { Flex } from "@styled-system/jsx"; -import { Space, Text } from "@wow-class/ui"; -import { routePath } from "constants/routePath"; -import { useRouter } from "next/navigation"; +import { Modal, Space, Text } from "@wow-class/ui"; +import { useOpenState } from "@wow-class/ui/hooks"; +import { myStudyApi } from "apis/myStudyApi"; +import { studyHistoryApi } from "apis/studyHistoryApi"; +import { tags } from "constants/tags"; import { useCallback, useState } from "react"; import type { RepositorySubmissionStatusType } from "types/entities/myAssignment"; -import { Edit, Trash, Warn } from "wowds-icons"; +import { isGithubRepositoryUrl } from "utils/isGithubRepositoryUrl"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import { Edit, Trash } from "wowds-icons"; import Box from "wowds-ui/Box"; import Button from "wowds-ui/Button"; import Tag from "wowds-ui/Tag"; @@ -23,21 +27,32 @@ export const RepositorySubmissionBox = ({ const [repositoryUrl, setRepositoryUrl] = useState(initialRepositoryUrl); const [repositorySubmissionStatus, setRepositorySubmissionStatus] = useState( - initialRepositoryUrl ? "SUBMITTED" : "EDITING_WITH_WARNING" + initialRepositoryUrl ? "SUBMITTED" : "EDITING" ); - const [error, setError] = useState(false); - - const router = useRouter(); + const [errorState, setErrorState] = useState<{ + isError: boolean; + errorMessage: string; + }>({ + isError: false, + errorMessage: "", + }); + const { open, onOpen, onClose } = useOpenState(); const handleClickEditButton = useCallback(() => { - setError(false); + setErrorState({ + isError: false, + errorMessage: "", + }); setRepositorySubmissionStatus("EDITING"); }, []); const handleClickDeleteButton = useCallback(() => { setRepositoryUrl(""); - setError(false); - setRepositorySubmissionStatus("EDITING_WITH_WARNING"); + setErrorState({ + isError: false, + errorMessage: "", + }); + setRepositorySubmissionStatus("EDITING"); }, []); const handleChange = useCallback( @@ -49,114 +64,143 @@ export const RepositorySubmissionBox = ({ const handleClickSubmitButton = useCallback(async () => { if (!repositoryUrl) { - setError(true); + setErrorState({ + isError: true, + errorMessage: "빈 URL은 입력할 수 없습니다.", + }); + } else if (!isGithubRepositoryUrl(repositoryUrl)) { + setErrorState({ + isError: true, + errorMessage: "GitHub repository URL을 제출해야 합니다.", + }); } else { - router.push( - `${routePath["my-assignment-repository-url-confirmation"]}?repositoryUrl=${repositoryUrl}` - ); + setErrorState({ + isError: false, + errorMessage: "", + }); + onOpen(); + } + }, [repositoryUrl, onOpen]); + + const handleClickModalSubmitButton = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; } - }, [router, repositoryUrl]); + const { success } = await studyHistoryApi.putRepository( + myOngoingStudyInfoData.studyId, + repositoryUrl + ); + if (success) { + revalidateTagByName(tags.studyDetailDashboard); + setRepositorySubmissionStatus("SUBMITTED"); + onClose(); + } + }; return ( - - - 레포지토리 - - - - - 과제 제출을 위한 레포지토리 URL 입력하기 + <> + + + 레포지토리 - {repositorySubmissionStatus !== "EDITING_WITH_WARNING" && ( - - 제출 완료 - - )} - - - <> - {repositorySubmissionStatus === "SUBMITTED" && ( - <> - - 최초 과제 제출 전 까지만 수정이 가능해요. - - - - {repositoryUrl} - - - + + + + 과제 제출을 위한 레포지토리 URL 입력하기 + + {repositorySubmissionStatus === "SUBMITTED" && ( + + 제출 완료 + + )} + + + <> + {repositorySubmissionStatus === "SUBMITTED" && ( + <> + + 최초 과제 제출 전 까지만 수정이 가능해요. + + + +
{repositoryUrl}
+ + + +
-
- - )} - {repositorySubmissionStatus === "EDITING_WITH_WARNING" && ( - <> - - + + )} + {repositorySubmissionStatus === "EDITING" && ( + <> - 입력하지 않으면 앞으로의 과제를 제출할 수 없어요. + * 입력하지 않으면 앞으로의 과제를 제출할 수 없어요. + + + * 레포지토리가 Private 상태면 입력할 수 없어요. - - - - - - - )} - {repositorySubmissionStatus === "EDITING" && ( - <> - - - - - - )} - -
- } - /> + + {errorState.errorMessage}, + })} + label="" + placeholder="URL 을 입력하세요" + style={textFieldStyle} + value={repositoryUrl} + onChange={handleChange} + /> + + + + )} + +
+ } + /> + {open && ( + + + 레포지토리를 입력하시겠어요? + + 최초 과제 제출 전까지 수정이 가능해요. + +
{repositoryUrl}
+ + +
+
+ )} + ); }; -const errorMessage =
  • 빈 URL은 입력할 수 없습니다.
  • ; - +const overflowTextStyle = css({ + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", +}); const urlBoxStyle = css({ backgroundColor: "backgroundAlternative", borderRadius: "5px", @@ -165,10 +209,25 @@ const urlBoxStyle = css({ paddingX: "24px", paddingY: "18px", textStyle: "h2", + width: "436px", }); +const modalUrlBoxStyle = css({ + backgroundColor: "backgroundAlternative", + borderRadius: "5px", + color: "sub", + paddingX: "lg", + paddingY: "sm", + textStyle: "h2", + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap", + width: "375px", +}); const boxStyle = { minWidth: "484px", + width: "484px", + height: "fit-content", }; const iconStyle = { diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx index 7876fc3d..418fe119 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx @@ -1,21 +1,32 @@ import { css } from "@styled-system/css"; import { Flex } from "@styled-system/jsx"; -import { - assignmentData, - studyDashBoardData, -} from "constants/assignmentMockData"; +import { myStudyApi } from "apis/myStudyApi"; +import { studyDetailApi } from "apis/studyDetailApi"; +import { routePath } from "constants/routePath"; +import { redirect } from "next/navigation"; import { AssignmentOverviewBox } from "./AssignmentOverviewBox"; import { EmptyAssignmentBox } from "./EmptyAssignmentBox"; import { RepositorySubmissionBox } from "./RepositorySubmissionBox"; -export const AssignmentContent = () => { - //TODO:수강 중인 스터디 api 호출 - //const studyId = await myStudyApi.getMyOngoingStudyInfo(); - //const studyDashboard = await studyDetailApi.getStudyDetailDashboard(studyId); - //TODO: studyDashboard.isLinkEditable 가 false 면 이번 주 과제 조회 api 사용 - const studyDashboard = studyDashBoardData; - const currentAssignments = assignmentData; +export const AssignmentContent = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return redirect(routePath["my-study"]); + } + const studyDashboard = await studyDetailApi.getStudyDetailDashboard( + myOngoingStudyInfoData.studyId + ); + + const upcomingStudy = await studyDetailApi.getUpcomingStudy( + myOngoingStudyInfoData.studyId + ); + + if (!studyDashboard) { + return; + } + return (
    @@ -31,10 +42,10 @@ export const AssignmentContent = () => { )} {!studyDashboard.isLinkEditable && - (currentAssignments ? ( - + (upcomingStudy ? ( + ) : ( - + ))}
    diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx index 42815cc0..1e1899e6 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx @@ -1,23 +1,29 @@ import { css } from "@styled-system/css"; +import { myStudyApi } from "apis/myStudyApi"; import { studyDetailApi } from "apis/studyDetailApi"; import Tooltip from "components/Tooltip"; -import { studyDashBoardData } from "constants/assignmentMockData"; import Link from "next/link"; export const AssignmentDescription = async () => { - //const studyDashboard = await studyDetailApi.getStudyDetailDashboard(1); + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; + } + const studyDashboard = await studyDetailApi.getStudyDetailDashboard( + myOngoingStudyInfoData.studyId + ); - const studyDashboard = studyDashBoardData; return (

    제출 완료하기 버튼을 누르면 등록한{" "} - {studyDashboard.isLinkEditable ? ( - GitHub 레포지토리 + {!studyDashboard?.repositoryLink ? ( + GitHub 레포지토리 ) : ( - https://github.com/123456789012345678 + + {studyDashboard?.repositoryLink} } > @@ -31,6 +37,11 @@ export const AssignmentDescription = async () => { ); }; +const nonCursorStyle = css({ + color: "blueHover", + cursor: "auto", + textDecoration: "none", +}); const githubTextStyle = css({ color: "blueHover", cursor: "pointer", diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx index 64078c56..85627897 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx @@ -1,17 +1,23 @@ import { Flex, styled } from "@styled-system/jsx"; +import { myStudyApi } from "apis/myStudyApi"; import Image from "next/image"; -export const AssignmentHeader = () => { - //TODO: 스터디 정보 연결, 내가 수강 중인 스터디 api 호출 - //const studyId = await myStudyApi.getMyOngoingStudyInfo() - //const { title } = await myStudyApi.getBasicStudyInfo(studyId) +export const AssignmentHeader = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; + } + const myBasicInfoData = await myStudyApi.getBasicStudyInfo( + myOngoingStudyInfoData.studyId + ); return (

    나의 과제 dot - 기초 웹 스터디 + {myBasicInfoData?.title}
    ); diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx index 251329be..e4ed7767 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx @@ -1,11 +1,15 @@ import { css } from "@styled-system/css"; -import { Flex, styled } from "@styled-system/jsx"; +import { Flex } from "@styled-system/jsx"; import { Space, Table, Text } from "@wow-class/ui"; import { padWithZero, parseISODate } from "@wow-class/utils"; import Link from "next/link"; import type { ComponentProps } from "react"; +import type { Assignment } from "types/dtos/studyDetail"; import type { AssignmentHistoryDto } from "types/dtos/studyHistory"; -import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment"; +import type { + AssignmentStatusType, + AssignmentSubmissionStatusType, +} from "types/entities/common/assignment"; import Button from "wowds-ui/Button"; import Tag from "wowds-ui/Tag"; import TextButton from "wowds-ui/TextButton"; @@ -23,13 +27,17 @@ export const AssignmentHistoryItem = ({ title, descriptionLink, assignmentSubmissionStatus, + submissionFailureType, submissionLink, + status, } = history; const { year, month, day, hours, minutes } = parseISODate(deadline); const deadlineText = `종료: ${year}년 ${month}월 ${day}일 ${padWithZero(hours)}:${padWithZero(minutes)}`; + const { tagText, tagColor } = getTagProps(status, assignmentSubmissionStatus); + return ( @@ -54,14 +62,15 @@ export const AssignmentHistoryItem = ({ "-" )} - - - {assignmentSubmissionMap[assignmentSubmissionStatus].message} +
    + + {tagText} - + + {assignmentSubmissionStatus === "FAILURE" && + failMapping[submissionFailureType ?? "NONE"]} + +
    {submissionLink ? ( @@ -78,25 +87,47 @@ export const AssignmentHistoryItem = ({ ); }; -const assignmentSubmissionMap: Record< - AssignmentSubmissionStatusType, - { message: string; color: ComponentProps["color"] } -> = { - FAILURE: { - message: "제출 실패", - color: "red", - }, - SUCCESS: { - message: "제출 완료", - color: "blue", - }, - PENDING: { - message: "과제 휴강", - color: "grey", - }, +const getTagProps = ( + status: AssignmentStatusType, + assignmentSubmissionStatus: AssignmentSubmissionStatusType +) => { + if (status === "CANCELLED") { + return assignmentSubmissionMap.CANCELLED; + } + + if ( + assignmentSubmissionStatus && + assignmentSubmissionMap[assignmentSubmissionStatus] + ) { + return assignmentSubmissionMap[assignmentSubmissionStatus]; + } + return assignmentSubmissionMap.CANCELLED; }; const buttonContainerStyle = css({ justifyContent: "center", textStyle: "body1", }); + +const tagContainerStyle = css({ + display: "flex", + paddingX: "22px", + width: "129px", + alignItems: "center", + flexDirection: "column", +}); + +const assignmentSubmissionMap: Record< + "CANCELLED" | "FAILURE" | "SUCCESS", + { tagText: string; tagColor: ComponentProps["color"] } +> = { + CANCELLED: { tagText: "과제 휴강", tagColor: "grey" }, + FAILURE: { tagText: "제출 실패", tagColor: "red" }, + SUCCESS: { tagText: "제출 완료", tagColor: "blue" }, +}; +const failMapping: Record = { + LOCATION_UNIDENTIFIABLE: "위치확인불가", + WORD_COUNT_INSUFFICIENT: "글자수부족", + NOT_SUBMITTED: "미제출", + NONE: "", +}; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx index efafca6e..7330f570 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx @@ -1,16 +1,25 @@ import { Flex } from "@styled-system/jsx"; import { Space, Text } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; import { studyHistoryApi } from "apis/studyHistoryApi"; -import { history } from "constants/assignmentMockData"; import Image from "next/image"; import { AssignmentHistoryItem } from "./AssignmentHistoryItem"; export const AssignmentHistory = async () => { - //TODO: 수강 중인 스터디 api 호출 - //const studyId = await myStudyApi.getMyOngoingStudyInfo(); - // const studyHistory = await studyHistoryApi.getStudyHistory(studyId); - const studyHistories = history; + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; + } + + const studyHistories = await studyHistoryApi.getStudyHistory( + myOngoingStudyInfoData.studyId + ); + if (!studyHistories) { + return; + } + if (studyHistories.length === 0) { return (
    diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx index a9c6eae1..1d26f66e 100644 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx @@ -4,21 +4,8 @@ export const metadata: Metadata = { title: "나의 과제 | GDSC Hongik 스터디 서비스, 와우클래스", }; -const Layout = ({ - children, - modal, -}: { - children: React.ReactNode; - modal: React.ReactNode; -}) => { - return ( - <> -
    - {children} - {modal} -
    - - ); +const Layout = ({ children }: { children: React.ReactNode }) => { + return
    {children}
    ; }; export default Layout; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx deleted file mode 100644 index 8a3c9090..00000000 --- a/apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { routePath } from "constants/routePath"; -import { redirect } from "next/navigation"; - -const RepositoryUrlConfirmationPage = () => { - return redirect(routePath["my-assignment"]); -}; - -export default RepositoryUrlConfirmationPage; diff --git a/apps/client/components/Navbar.tsx b/apps/client/components/Navbar.tsx index 17066953..172586e4 100644 --- a/apps/client/components/Navbar.tsx +++ b/apps/client/components/Navbar.tsx @@ -47,7 +47,7 @@ const Navbar = async () => { alt={menu.alt} href={menu.href} imageUrl={menu.imageUrl} - // items={menu.items} + items={menu.items} key={menu.name} name={menu.name} /> diff --git a/apps/client/components/Tooltip.tsx b/apps/client/components/Tooltip.tsx index bfb68b07..e0aa338a 100644 --- a/apps/client/components/Tooltip.tsx +++ b/apps/client/components/Tooltip.tsx @@ -50,4 +50,5 @@ const tooltipStyle = css({ boxShadow: "mono", backdropFilter: "blur(15px)", color: "textWhite", + whiteSpace: "nowrap", }); diff --git a/apps/client/constants/assignmentMockData.ts b/apps/client/constants/assignmentMockData.ts index 37f88ab8..3b415cd3 100644 --- a/apps/client/constants/assignmentMockData.ts +++ b/apps/client/constants/assignmentMockData.ts @@ -1,48 +1,53 @@ -import type { - Assignment, - StudyDetailDashboardDto, -} from "types/dtos/studyDetail"; +import type { Assignment } from "types/dtos/studyDetail"; import type { AssignmentHistoryDto } from "types/dtos/studyHistory"; export const history: AssignmentHistoryDto[] = [ { assignmentHistoryId: 1, + status: "CANCELLED", title: "Assignment 1", deadline: "2024-08-17T06:02:17.417Z", descriptionLink: "", submissionLink: "http://example.com/submission1", assignmentSubmissionStatus: "SUCCESS", + submissionFailureType: "NONE", week: 1, }, { assignmentHistoryId: 2, + status: "OPEN", title: "Assignment 2", deadline: "2024-08-24T06:02:17.417Z", descriptionLink: "http://example.com/assignment2", submissionLink: "", assignmentSubmissionStatus: "FAILURE", + submissionFailureType: "WORD_COUNT_INSUFFICIENT", week: 2, }, + { + assignmentHistoryId: 3, + status: "OPEN", + title: "Assignment 2", + deadline: "2024-08-24T06:02:17.417Z", + descriptionLink: "http://example.com/assignment2", + submissionLink: "", + assignmentSubmissionStatus: "FAILURE", + submissionFailureType: "LOCATION_UNIDENTIFIABLE", + week: 3, + }, + { + assignmentHistoryId: 3, + status: "OPEN", + title: "Assignment 2", + deadline: "2024-08-24T06:02:17.417Z", + descriptionLink: "http://example.com/assignment2", + submissionLink: "", + assignmentSubmissionStatus: "SUCCESS", + submissionFailureType: "NONE", + week: 3, + }, ]; -export const studyDashBoardData: StudyDetailDashboardDto = { - repositoryLink: "", - isLinkEditable: false, - submittableAssignments: [ - { - studyDetailId: 1, - assignmentStatus: "OPEN", - week: 1, - title: "React Basics", - assignmentSubmissionStatus: "PENDING", - descriptionLink: "https://example.com/assignments/react-basics", - deadline: "2024-08-25T23:59:59", - submissionLink: "https://example.com/submissions/react-basics", - submissionFailureType: "NONE", - }, - ], -}; - export const assignmentData: Assignment[] = [ { studyDetailId: 121, @@ -61,7 +66,7 @@ export const assignmentData: Assignment[] = [ assignmentStatus: "OPEN", week: 3, title: "Database Design Assignment", - assignmentSubmissionStatus: "PENDING", + assignmentSubmissionStatus: "FAILURE", descriptionLink: "https://example.com/assignment/123", deadline: "2024-08-26T14:30:00", submissionLink: "https://github.com/GDSC-Hongik/wow-class", diff --git a/apps/client/constants/assignmentSubmissionStatusMap.ts b/apps/client/constants/assignmentSubmissionStatusMap.ts deleted file mode 100644 index 9a6dc670..00000000 --- a/apps/client/constants/assignmentSubmissionStatusMap.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { ComponentProps } from "react"; -import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment"; -import type Tag from "wowds-ui/Tag"; - -export const assignmentSubmissionStatusMap: Record< - AssignmentSubmissionStatusType, - { label: string; color: ComponentProps["color"] } -> = { - SUCCESS: { label: "제출 완료", color: "blue" }, - FAILURE: { label: "제출 실패", color: "red" }, - PENDING: { label: "과제 휴강", color: "grey" }, -}; diff --git a/apps/client/constants/navMenu.ts b/apps/client/constants/navMenu.ts index 65859465..e2297fe8 100644 --- a/apps/client/constants/navMenu.ts +++ b/apps/client/constants/navMenu.ts @@ -1,4 +1,4 @@ -// import folderImageUrl from "../public/images/folder.svg"; +import folderImageUrl from "../public/images/folder.svg"; import homeImageUrl from "../public/images/home.svg"; import personImageUrl from "../public/images/person.svg"; import scheduleImageUrl from "../public/images/schedule.svg"; @@ -9,14 +9,14 @@ export const navMenu = [ imageUrl: homeImageUrl, alt: "home-icon", name: "나의 스터디", - // items: [ - // { - // href: "my-assignment", - // imageUrl: folderImageUrl, - // alt: "folder-icon", - // name: "나의 과제", - // }, - // ], + items: [ + { + href: "my-assignment", + imageUrl: folderImageUrl, + alt: "folder-icon", + name: "나의 과제", + }, + ], }, { href: "/study-apply", diff --git a/apps/client/constants/routePath.ts b/apps/client/constants/routePath.ts index 0016856d..d32ff338 100644 --- a/apps/client/constants/routePath.ts +++ b/apps/client/constants/routePath.ts @@ -13,8 +13,6 @@ export const routePath = { ["study-application-modal"]: "/study-apply/study-application", ["study-cancellation-modal"]: "/study-apply/study-cancellation", ["my-assignment"]: "/my-study/my-assignment", - ["my-assignment-repository-url-confirmation"]: - "/my-study/my-assignment/repository-url/confirmation", ["my-page"]: "/my-page", ["my-page-logout"]: "/my-page/logout", onboarding: "https://onboarding.gdschongik.com", diff --git a/apps/client/constants/tags.ts b/apps/client/constants/tags.ts index b519b2cb..a3e60f2e 100644 --- a/apps/client/constants/tags.ts +++ b/apps/client/constants/tags.ts @@ -6,6 +6,7 @@ export const enum tags { myOngoingStudy = "myOngoingStudy", studyHistory = "studyHistory", studyDetailDashboard = "studyDetailDashboard", + upcomingStudy = "upcomingStudy", studyCurriculum = "studyCurriculum", dailyTask = "dailyTask", myAccountInfo = "myAccountInfo", diff --git a/apps/client/hooks/useMatchedStudyHistoryId.ts b/apps/client/hooks/useMatchedStudyHistoryId.ts deleted file mode 100644 index afff0ea9..00000000 --- a/apps/client/hooks/useMatchedStudyHistoryId.ts +++ /dev/null @@ -1,33 +0,0 @@ -"use client"; - -import { studyDetailApi } from "apis/studyDetailApi"; -import { studyHistoryApi } from "apis/studyHistoryApi"; -import { history, studyDashBoardData } from "constants/assignmentMockData"; -import { useEffect, useState } from "react"; - -export default function useMatchedStudyHistoryId() { - const [matchedStudyHistoryId, setMatchedStudyHistoryId] = useState(); - useEffect(() => { - const fetchData = async () => { - //TODO: 수강 중인 스터디 api 호출 - //const studyId = await myStudyApi.getMyOngoingStudyInfo(); - //const studyHistories = await studyHistoryApi.getStudyHistory(studyId); - const studyHistories = history; - // const studyDashboard = - // await studyDetailApi.getStudyDetailDashboard(studyId); - const studyDashboard = studyDashBoardData; - if (studyHistories && studyDashboard) { - const submittableWeek = studyDashboard.submittableAssignments[0]?.week; - const matchedHistory = studyHistories.find( - (item) => item.week === submittableWeek - ); - - setMatchedStudyHistoryId(matchedHistory?.assignmentHistoryId); - } - }; - - fetchData(); - }, []); - - return { matchedStudyHistoryId }; -} diff --git a/apps/client/types/dtos/myStudy.ts b/apps/client/types/dtos/myStudy.ts index 614ebec9..df6bba1c 100644 --- a/apps/client/types/dtos/myStudy.ts +++ b/apps/client/types/dtos/myStudy.ts @@ -1,11 +1,13 @@ +import type { + AssignmentStatusType, + AssignmentSubmissionFailureType, +} from "types/entities/common/assignment"; import type { DayOfWeekType, SemesterType, Time, } from "types/entities/common/time"; import type { - AssignmentStatusType, - AssignmentSubmissionFailureType, AssignmentSubmissionStatusType, AttendanceStatusType, DailyTaskType, diff --git a/apps/client/types/dtos/studyDetail.ts b/apps/client/types/dtos/studyDetail.ts index 22e1f0ad..78172c91 100644 --- a/apps/client/types/dtos/studyDetail.ts +++ b/apps/client/types/dtos/studyDetail.ts @@ -1,7 +1,7 @@ import type { - AssignmentStatus, + AssignmentStatusType, + AssignmentSubmissionFailureType, AssignmentSubmissionStatusType, - SubmissionFailureType, } from "types/entities/common/assignment"; export interface StudyDetailDashboardDto { @@ -10,16 +10,17 @@ export interface StudyDetailDashboardDto { submittableAssignments: Assignment[]; } +export type UpcomingStudyDto = Assignment[]; export interface Assignment { studyDetailId: number; - assignmentStatus: AssignmentStatus; + assignmentStatus: AssignmentStatusType; week: number; title: string; assignmentSubmissionStatus: AssignmentSubmissionStatusType; descriptionLink: string; deadline: string; submissionLink: string; - submissionFailureType: SubmissionFailureType; + submissionFailureType: AssignmentSubmissionFailureType; committedAt?: string; } diff --git a/apps/client/types/dtos/studyHistory.ts b/apps/client/types/dtos/studyHistory.ts index cfe91e03..7cfade33 100644 --- a/apps/client/types/dtos/studyHistory.ts +++ b/apps/client/types/dtos/studyHistory.ts @@ -1,15 +1,17 @@ import type { + AssignmentStatusType, + AssignmentSubmissionFailureType, AssignmentSubmissionStatusType, - SubmissionFailureType, } from "types/entities/common/assignment"; export interface AssignmentHistoryDto { assignmentHistoryId: number; + status: AssignmentStatusType; title: string; deadline: string; descriptionLink?: string; submissionLink?: string; - assignmentSubmissionStatus: AssignmentSubmissionStatusType; //TODO: 과제 휴강 여부 추가 - submissionFailureType?: SubmissionFailureType; + assignmentSubmissionStatus: AssignmentSubmissionStatusType; + submissionFailureType: AssignmentSubmissionFailureType; week: number; } diff --git a/apps/client/types/entities/common/assignment.ts b/apps/client/types/entities/common/assignment.ts index 5a447a17..f6f91ea8 100644 --- a/apps/client/types/entities/common/assignment.ts +++ b/apps/client/types/entities/common/assignment.ts @@ -1,6 +1,6 @@ -export type AssignmentSubmissionStatusType = "FAILURE" | "SUCCESS" | "PENDING"; //TODO: 제출 전, 과제 휴강 여부 추가 -export type AssignmentStatus = "NONE" | "OPEN" | "CANCELLED"; -export type SubmissionFailureType = +export type AssignmentSubmissionStatusType = "FAILURE" | "SUCCESS" | null; +export type AssignmentStatusType = "NONE" | "OPEN" | "CANCELLED"; +export type AssignmentSubmissionFailureType = | "NONE" | "NOT_SUBMITTED" | "WORD_COUNT_INSUFFICIENT" diff --git a/apps/client/types/entities/myAssignment.ts b/apps/client/types/entities/myAssignment.ts index b52c6f4a..31b42b3c 100644 --- a/apps/client/types/entities/myAssignment.ts +++ b/apps/client/types/entities/myAssignment.ts @@ -1,4 +1 @@ -export type RepositorySubmissionStatusType = - | "EDITING" - | "SUBMITTED" - | "EDITING_WITH_WARNING"; +export type RepositorySubmissionStatusType = "EDITING" | "SUBMITTED"; diff --git a/apps/client/types/entities/myStudy.ts b/apps/client/types/entities/myStudy.ts index 6ab4fcd9..d30377c9 100644 --- a/apps/client/types/entities/myStudy.ts +++ b/apps/client/types/entities/myStudy.ts @@ -5,20 +5,11 @@ export type AttendanceStatusType = export type StudyDifficultyType = "BASIC" | "LOW" | "MEDIUM" | "HIGH"; -export type AssignmentStatusType = "NONE" | "OPEN" | "CANCELLED"; - -export type AssignmentSubmissionFailureType = - | "NONE" - | "NOT_SUBMITTED" - | "WORD_COUNT_INSUFFICIENT" - | "LOCATION_UNIDENTIFIABLE" - | "UNKNOWN"; - export type StudyCurriculumStatusType = "NONE" | "OPEN" | "CANCELLED"; +export type DailyTaskType = "ATTENDANCE" | "ASSIGNMENT"; + export type AssignmentSubmissionStatusType = | "NOT_SUBMITTED" | "FAILURE" | "SUCCESS"; - -export type DailyTaskType = "ATTENDANCE" | "ASSIGNMENT"; diff --git a/apps/client/utils/getAssignmentGithubFolderName.ts b/apps/client/utils/getAssignmentGithubFolderName.ts new file mode 100644 index 00000000..bbc727d9 --- /dev/null +++ b/apps/client/utils/getAssignmentGithubFolderName.ts @@ -0,0 +1,10 @@ +export const getAssignmentGithubFolderName = (submissionLink: string) => { + const regex = /github\.com\/[^/]+\/([^/]+)\/([^/]+)/; + const match = submissionLink.match(regex); + + if (match) { + const repoName = match[1]; + const folderName = match[2]; + return `${repoName}/${folderName}`; + } +}; diff --git a/apps/client/utils/getIsAfterStartDate.ts b/apps/client/utils/getIsAfterStartDate.ts new file mode 100644 index 00000000..f4c4e359 --- /dev/null +++ b/apps/client/utils/getIsAfterStartDate.ts @@ -0,0 +1,5 @@ +export const getIsAfterStartDate = (startDate: string): boolean => { + const now = new Date(); + const start = new Date(startDate); + return now >= start; +}; diff --git a/apps/client/utils/index.ts b/apps/client/utils/index.ts deleted file mode 100644 index de1e7667..00000000 --- a/apps/client/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as isDeadlinePassed } from "./isDeadlinePassed"; diff --git a/apps/client/utils/isDeadlinePassed.ts b/apps/client/utils/isDeadlinePassed.ts index af954427..694a1d18 100644 --- a/apps/client/utils/isDeadlinePassed.ts +++ b/apps/client/utils/isDeadlinePassed.ts @@ -1,7 +1,5 @@ -const isDeadlinePassed = (deadline: string) => { +export const isDeadlinePassed = (deadline: string) => { const now = new Date(); const deadlineDate = new Date(deadline); return now > deadlineDate; }; - -export default isDeadlinePassed; diff --git a/apps/client/utils/isGithubRepositoryUrl.ts b/apps/client/utils/isGithubRepositoryUrl.ts new file mode 100644 index 00000000..3499407b --- /dev/null +++ b/apps/client/utils/isGithubRepositoryUrl.ts @@ -0,0 +1,5 @@ +export const isGithubRepositoryUrl = (url: string) => { + const githubUrlPattern = + /^(https?:\/\/)?(www\.)?github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/?$/; + return githubUrlPattern.test(url); +}; diff --git a/packages/ui/src/components/NavItem/index.tsx b/packages/ui/src/components/NavItem/index.tsx index 29e345f5..24dc32e7 100644 --- a/packages/ui/src/components/NavItem/index.tsx +++ b/packages/ui/src/components/NavItem/index.tsx @@ -46,8 +46,11 @@ const NavItem = ({ href, imageUrl, alt, name, items }: NavItemProps) => { } }; + const currentPath = `/${segment.join("/")}`; + const navItemType = - (!segment[1] && `${segment[0]}` === href) || `/${segment[0]}` === href + currentPath === href && + ((!segment[1] && `${segment[0]}` === href) || `/${segment[0]}` === href) ? "active" : "inactive";