From bc1c665f3b2562a05adabf0f0c1ce29b5dee3cb7 Mon Sep 17 00:00:00 2001 From: SeieunYoo <101736358+SeieunYoo@users.noreply.github.com> Date: Sat, 24 Aug 2024 02:41:45 +0900 Subject: [PATCH] =?UTF-8?q?[Feature]=20=EB=A0=88=ED=8F=AC=EC=A7=80?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=9E=85=EB=A0=A5=ED=95=A0=20=EB=95=8C=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 신청 모달, 취소 모달 * feat: 컴포넌트 로직 분리 * chore: 문구 수정 * chore: 헤더 제거 * chore: fetcher 주석 해제 * feat: 레포지토리 입력 모달 * feat: 헤더 제거 * feat: match되는 studyHistoryId 찾는 훅 추가 * chore: modal 라우팅 경로 수정 * chore: my-study/my-assignment 로 이동 * chore: 이전 브랜치에 남은 로직 삭제 * feat: modal 라우팅 수정, url 쿼리paramter 넘기는 것으로 수정 * feat: 분기문 수정 * chore: 컴포넌트명 수정 * refactor: AssignmentBoxButtons 리팩토링 * feat: AssignmentBoxInfo 로 수정 * refactor: RepositorySubmissionBox 리팩토링 * feat: customRevalidate 삭제 * chore: 스타일 객체 하단으로 분리, 문구 수정 * feat: 추가된 히스토리 api dto 반영, 과제 없을 때 ui 추가 * feat: 입력할 때 빈 문자에 대한 validate 추가, 컴포넌트 하단 분리 * chore: 프로퍼티 스프레드로 * feat: 모달 url 변경 * feat: 에러 상태 핸들링 수정, 텍스트필드 height 고정 * chore: ui css반영 * feat: 모달 플로우 수정, 입력하기 버튼 누르면 모달 열리게 --- .../AssignmenBoxButtons.tsx | 122 ------------ .../RepositorySubmissionBox.tsx | 125 ------------ .../(.)repository-url/confirmation/page.tsx | 46 +++++ .../@modal/(.)repository-url/default.tsx | 5 + .../my-study/my-assignment/@modal/default.tsx | 5 + .../AssignmentBoxButtons.tsx | 119 +++++++++++ .../AssignmentBoxInfo.tsx} | 12 +- .../AssignmentBoxTitle.tsx | 0 .../AssignmentOverviewBox/index.tsx | 10 +- .../AssignmentContent/EmptyAssignmentBox.tsx | 25 +++ .../RepositorySubmissionBox.tsx | 185 ++++++++++++++++++ .../_components/AssignmentContent/index.tsx | 21 +- .../AssignmentHistoryItem.tsx | 0 .../_components/AssignmentHistory/index.tsx | 6 +- .../my-assignment/_components/index.ts | 0 .../my-study/my-assignment/default.tsx | 5 + .../my-study/my-assignment/layout.tsx | 18 ++ .../{ => my-study}/my-assignment/page.tsx | 0 .../repository-url/confirmation/page.tsx | 8 + apps/client/constants/assignmentMockData.ts | 2 +- apps/client/constants/routePath.ts | 6 +- apps/client/hooks/useMatchedStudyHistoryId.ts | 33 ++++ apps/client/middleware.ts | 7 +- apps/client/types/dtos/studyHistory.ts | 6 +- apps/client/types/entities/myAssignment.ts | 5 +- packages/ui/src/styles.css | 3 + 26 files changed, 495 insertions(+), 279 deletions(-) delete mode 100644 apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmenBoxButtons.tsx delete mode 100644 apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx rename apps/client/app/(afterLogin)/{my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmetBoxInfo.tsx => my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx} (82%) rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx (100%) rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx (82%) create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/AssignmentContent/index.tsx (56%) rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx (100%) rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/AssignmentHistory/index.tsx (87%) rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/_components/index.ts (100%) create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx rename apps/client/app/(afterLogin)/{ => my-study}/my-assignment/page.tsx (100%) create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx create mode 100644 apps/client/hooks/useMatchedStudyHistoryId.ts diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmenBoxButtons.tsx b/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmenBoxButtons.tsx deleted file mode 100644 index 65a34f46..00000000 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmenBoxButtons.tsx +++ /dev/null @@ -1,122 +0,0 @@ -"use client"; - -import { Space } from "@wow-class/ui"; -import { studyHistoryApi } from "apis/studyHistoryApi"; -import { tags } from "constants/tags"; -import { revalidateTag } from "next/cache"; -import Link from "next/dist/client/link"; -import type { Assignment } from "types/dtos/studyDetail"; -import { isDeadlinePassed } from "utils"; -import { Link as LinkIcon, Reload as ReloadIcon } from "wowds-icons"; -import Button from "wowds-ui/Button"; - -interface AssignmentButtonsProps { - assignment: Assignment; - buttonsDisabled?: boolean; -} - -export const AssignmentButtons = ({ - assignment, - buttonsDisabled, -}: AssignmentButtonsProps) => { - const { - assignmentSubmissionStatus, - submissionFailureType, - submissionLink, - deadline, - committedAt, - studyDetailId, - } = assignment; - - const handleClickSubmissionComplete = async () => { - const response = await studyHistoryApi.submitAssignment(studyDetailId); - if (response.success) { - //TODO: 과제 제출 이후에는 과제 상태에 대한 업데이트 필요 - //이번주 과제 조회 api, 대시보드 api revaliate - //revalidateTag() - } - }; - - const getButtonProps = () => { - if (assignmentSubmissionStatus === "PENDING") { - const stroke = buttonsDisabled ? "mono100" : "backgroundNormal"; - return { - primaryButtonText: "제출하러 가기", - secondaryButtonText: "제출 완료하기", - icon: , - }; - } else if (assignmentSubmissionStatus === "SUCCESS") { - return { - primaryButtonText: "제출한 과제 보러가기", - secondaryButtonText: "제출 갱신하기", - icon: , - }; - } else { - return { - primaryButtonText: "제출한 과제 보러가기", - secondaryButtonText: "제출 완료하기", - icon: , - }; - } - }; - - const renderPrimaryButton = (text: string) => { - if ( - assignmentSubmissionStatus === "FAILURE" && - submissionFailureType === "NOT_SUBMITTED" - ) { - return null; - } - const stroke = buttonsDisabled ? "mono100" : "primary"; - return ( - - - - ); - }; - - const renderSecondaryButton = (text: string, icon: JSX.Element) => { - if (isDeadlinePassed(deadline)) { - return ( - - ); - } - return ( - - ); - }; - - const { primaryButtonText, secondaryButtonText, icon } = getButtonProps(); - - return ( - <> - {renderPrimaryButton(primaryButtonText)} - - {renderSecondaryButton(secondaryButtonText, icon)} - - ); -}; - -const buttonStyle = { - maxWidth: "100%", -}; diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx b/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx deleted file mode 100644 index 46dd4632..00000000 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx +++ /dev/null @@ -1,125 +0,0 @@ -"use client"; - -import { css } from "@styled-system/css"; -import { Flex } from "@styled-system/jsx"; -import { Space, Text } from "@wow-class/ui"; -import { useCallback, useEffect, useState } from "react"; -import type { RepositorySubmissionStatusType } from "types/entities/myAssignment"; -import { Edit, Trash, Warn } from "wowds-icons"; -import Box from "wowds-ui/Box"; -import Button from "wowds-ui/Button"; -import Tag from "wowds-ui/Tag"; -import TextField from "wowds-ui/TextField"; -interface RepositorySubmissionBoxProps { - repositoryLink: string; -} - -export const RepositorySubmissionBox = ({ - repositoryLink, -}: RepositorySubmissionBoxProps) => { - const [url, setUrl] = useState(repositoryLink); - const [isInitialSubmit, setIsInitialSubmit] = useState(true); - const [repositorySubmissionStatus, setRepositorySubmissionStatus] = - useState("EDITING"); - - const handleClickChange = useCallback((value: string) => { - setUrl(value); - }, []); - - const handleClickEditButton = useCallback(() => { - setRepositorySubmissionStatus("EDITING"); - }, []); - - const handleClickSubmitButton = useCallback(async () => { - if (isInitialSubmit) { - setIsInitialSubmit(false); - } else { - console.log("모달 오픈"); - } - setRepositorySubmissionStatus("SUBMITTED"); - //TODO: studyHistoryId 넣어주기 - //await studyHistoryApi.putRepository(1, url); - }, [isInitialSubmit]); - - useEffect(() => { - if (isInitialSubmit) { - setRepositorySubmissionStatus(repositoryLink ? "SUBMITTED" : "EDITING"); - } - }, [isInitialSubmit, repositoryLink]); - - return ( - - - 레포지토리 - - - - - 과제 제출을 위한 레포지토리 URL 입력하기 - - {repositorySubmissionStatus === "SUBMITTED" && ( - - 제출 완료 - - )} - - - {isInitialSubmit && repositorySubmissionStatus === "EDITING" && ( - - - - 입력하지 않으면 앞으로의 과제를 제출할 수 없어요. - - - )} - {repositorySubmissionStatus === "SUBMITTED" && ( - 최초 과제 제출 전 까지만 수정이 가능해요. - )} - - {repositorySubmissionStatus === "EDITING" && ( - - )} - {repositorySubmissionStatus === "SUBMITTED" && ( - - {url} - - - - - - )} - - - - } - /> - ); -}; - -const urlBoxStyle = css({ - backgroundColor: "backgroundAlternative", - borderRadius: "5px", - color: "sub", - justifyContent: "space-between", - paddingX: "24px", - paddingY: "18px", - textStyle: "h2", -}); - -const boxStyle = { - minWidth: "484px", -}; 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 new file mode 100644 index 00000000..4c98645a --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx @@ -0,0 +1,46 @@ +"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 new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx @@ -0,0 +1,5 @@ +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 new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx @@ -0,0 +1,5 @@ +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 new file mode 100644 index 00000000..ea9b7bbe --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx @@ -0,0 +1,119 @@ +"use client"; + +import { Space } from "@wow-class/ui"; +import { studyHistoryApi } from "apis/studyHistoryApi"; +import { tags } from "constants/tags"; +import Link from "next/link"; +import type { Assignment } from "types/dtos/studyDetail"; +import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment"; +import { isDeadlinePassed } from "utils"; +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 +}: AssignmentBoxButtonsProps) => { + return ( + <> + + + + + ); +}; +const PrimaryButton = ({ + assignment, + buttonsDisabled, +}: AssignmentBoxButtonsProps) => { + const { assignmentSubmissionStatus, submissionFailureType, submissionLink } = + assignment; + const { primaryButtonText } = buttonProps[assignmentSubmissionStatus]; + + if ( + assignmentSubmissionStatus === "FAILURE" && + submissionFailureType === "NOT_SUBMITTED" + ) { + return; + } + const stroke = buttonsDisabled ? "mono100" : "primary"; + return ( + + + + ); +}; + +const SecondaryButton = ({ + assignment, + buttonsDisabled, +}: AssignmentBoxButtonsProps) => { + const { assignmentSubmissionStatus, studyDetailId, deadline, committedAt } = + assignment; + const { secondaryButtonText } = buttonProps[assignmentSubmissionStatus]; + const handleClickSubmissionComplete = async () => { + const response = await studyHistoryApi.submitAssignment(studyDetailId); + if (response.success) { + //TODO: 과제 제출 이후에는 과제 상태에 대한 업데이트 필요 + //이번주 과제 조회 api, 대시보드 api revaliate + revalidateTagByName(tags.studyDetailDashboard); + } + }; + + if (isDeadlinePassed(deadline)) { + return ( + + ); + } + const stroke = buttonsDisabled ? "mono100" : "backgroundNormal"; + return ( + + ); +}; + +const buttonStyle = { + maxWidth: "100%", +}; + +const buttonProps: Record< + AssignmentSubmissionStatusType, + { primaryButtonText: string; secondaryButtonText: string } +> = { + PENDING: { + primaryButtonText: "제출하러 가기", + secondaryButtonText: "제출 완료하기", + }, + SUCCESS: { + primaryButtonText: "제출한 과제 보러가기", + secondaryButtonText: "제출 갱신하기", + }, + FAILURE: { + primaryButtonText: "제출한 과제 보러가기", + secondaryButtonText: "제출 완료하기", + }, +}; diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmetBoxInfo.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx similarity index 82% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmetBoxInfo.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx index b5ab9c3b..051499cd 100644 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmetBoxInfo.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx @@ -4,13 +4,11 @@ import { padWithZero, parseISODate } from "@wow-class/utils"; import Image from "next/image"; import type { Assignment } from "types/dtos/studyDetail"; -interface AssignmentSubmissionInfoProps { +interface AssignmentBoxInfoProps { assignment: Assignment; } -export const AssignmentSubmissionInfo = ({ - assignment, -}: AssignmentSubmissionInfoProps) => { +export const AssignmentBoxInfo = ({ assignment }: AssignmentBoxInfoProps) => { const { deadline, title, assignmentSubmissionStatus, submissionFailureType } = assignment; @@ -20,14 +18,14 @@ export const AssignmentSubmissionInfo = ({ hours )}:${padWithZero(minutes)}까지`; + const isSuccess = assignmentSubmissionStatus === "SUCCESS"; const isFailure = assignmentSubmissionStatus === "FAILURE"; - const isPending = assignmentSubmissionStatus === "PENDING"; - const isNotSubmitted = submissionFailureType === "NOT_SUBMITTED"; + const isNotSubmitted = isFailure && submissionFailureType === "NOT_SUBMITTED"; return ( <> {deadlineText} - {!(isPending || isNotSubmitted) && ( + {(isSuccess || (isFailure && !isNotSubmitted)) && ( 제출한 과제 diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx similarity index 82% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx index 296c33d5..29f916ad 100644 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx @@ -4,9 +4,9 @@ import type { Assignment } from "types/dtos/studyDetail"; import Box from "wowds-ui/Box"; import TextButton from "wowds-ui/TextButton"; -import { AssignmentButtons } from "./AssignmenBoxButtons"; +import { AssignmentBoxButtons } from "./AssignmentBoxButtons"; +import { AssignmentBoxInfo } from "./AssignmentBoxInfo"; import { AssignmentBoxTitle } from "./AssignmentBoxTitle"; -import { AssignmentSubmissionInfo } from "./AssignmetBoxInfo"; interface AssignmentOverviewBoxProps { assignments: Assignment[]; @@ -27,13 +27,12 @@ export const AssignmentOverviewBox = ({ text={ <> - - + - @@ -52,4 +51,5 @@ const textButtonstyle = { const boxStyle = { minWidth: "484px", + height: "fit-content", }; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx new file mode 100644 index 00000000..08a61c66 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx @@ -0,0 +1,25 @@ +import { Space, Text } from "@wow-class/ui"; +import Box from "wowds-ui/Box"; + +export const EmptyAssignmentBox = ({ week }: { week: number }) => { + return ( + + + {week}주차 + + + + 과제가 없어요 + + + } + /> + ); +}; + +const boxStyle = { + paddingBottom: "50px", +}; 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 new file mode 100644 index 00000000..d59197c5 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx @@ -0,0 +1,185 @@ +"use client"; + +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 { useCallback, useState } from "react"; +import type { RepositorySubmissionStatusType } from "types/entities/myAssignment"; +import { Edit, Trash, Warn } from "wowds-icons"; +import Box from "wowds-ui/Box"; +import Button from "wowds-ui/Button"; +import Tag from "wowds-ui/Tag"; +import TextField from "wowds-ui/TextField"; + +interface RepositorySubmissionBoxProps { + repositoryLink: string; +} + +export const RepositorySubmissionBox = ({ + repositoryLink: initialRepositoryUrl, +}: RepositorySubmissionBoxProps) => { + const [repositoryUrl, setRepositoryUrl] = useState(initialRepositoryUrl); + const [repositorySubmissionStatus, setRepositorySubmissionStatus] = + useState( + initialRepositoryUrl ? "SUBMITTED" : "EDITING_WITH_WARNING" + ); + const [error, setError] = useState(false); + + const router = useRouter(); + + const handleClickEditButton = useCallback(() => { + setError(false); + setRepositorySubmissionStatus("EDITING"); + }, []); + + const handleClickDeleteButton = useCallback(() => { + setRepositoryUrl(""); + setError(false); + setRepositorySubmissionStatus("EDITING_WITH_WARNING"); + }, []); + + const handleChange = useCallback( + (value: string) => { + setRepositoryUrl(value); + }, + [setRepositoryUrl] + ); + + const handleClickSubmitButton = useCallback(async () => { + if (!repositoryUrl) { + setError(true); + } else { + router.push( + `${routePath["my-assignment-repository-url-confirmation"]}?repositoryUrl=${repositoryUrl}` + ); + } + }, [router, repositoryUrl]); + + return ( + + + 레포지토리 + + + + + 과제 제출을 위한 레포지토리 URL 입력하기 + + {repositorySubmissionStatus !== "EDITING_WITH_WARNING" && ( + + 제출 완료 + + )} + + + <> + {repositorySubmissionStatus === "SUBMITTED" && ( + <> + + 최초 과제 제출 전 까지만 수정이 가능해요. + + + + {repositoryUrl} + + + + + + + )} + {repositorySubmissionStatus === "EDITING_WITH_WARNING" && ( + <> + + + + 입력하지 않으면 앞으로의 과제를 제출할 수 없어요. + + + + + + + + )} + {repositorySubmissionStatus === "EDITING" && ( + <> + + + + + + )} + + + } + /> + ); +}; + +const errorMessage =
  • 빈 URL은 입력할 수 없습니다.
  • ; + +const urlBoxStyle = css({ + backgroundColor: "backgroundAlternative", + borderRadius: "5px", + color: "sub", + justifyContent: "space-between", + paddingX: "24px", + paddingY: "18px", + textStyle: "h2", +}); + +const boxStyle = { + minWidth: "484px", +}; + +const iconStyle = { + cursor: "pointer", +}; + +const buttonStyle = { + maxWidth: "100%", +}; + +const textFieldStyle = { + gap: "0px", + height: "58px !important", +}; diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx similarity index 56% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/index.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx index 076e3d6c..34c8ed71 100644 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentContent/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx @@ -6,29 +6,36 @@ import { } from "constants/assignmentMockData"; import { AssignmentOverviewBox } from "./AssignmentOverviewBox"; +import { EmptyAssignmentBox } from "./EmptyAssignmentBox"; import { RepositorySubmissionBox } from "./RepositorySubmissionBox"; export const AssignmentContent = () => { - // const studyDashboard = await studyDetailApi.getStudyDetailDashboard(1); + //TODO:수강 중인 스터디 api 호출 + //const studyId = await myStudyApi.getMyOngoingStudyInfo(); + //const studyDashboard = await studyDetailApi.getStudyDetailDashboard(studyId); //TODO: studyDashboard.isLinkEditable 가 false 면 이번 주 과제 조회 api 사용 const studyDashboard = studyDashBoardData; + const currentAssignments = assignmentData; return ( <> - {studyDashBoardData.isLinkEditable && ( + {studyDashboard.isLinkEditable && ( <> )} - {!studyDashBoardData.isLinkEditable && ( - - )} + {!studyDashboard.isLinkEditable && + (currentAssignments ? ( + + ) : ( + + ))} ); diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentHistory/index.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx similarity index 87% rename from apps/client/app/(afterLogin)/my-assignment/_components/AssignmentHistory/index.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx index 1393bb40..4fc5e560 100644 --- a/apps/client/app/(afterLogin)/my-assignment/_components/AssignmentHistory/index.tsx +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx @@ -1,14 +1,16 @@ import { Flex } from "@styled-system/jsx"; import { Space, Text } from "@wow-class/ui"; +import { studyHistoryApi } from "apis/studyHistoryApi"; import { history } from "constants/assignmentMockData"; import Image from "next/image"; import { AssignmentHistoryItem } from "./AssignmentHistoryItem"; export const AssignmentHistory = async () => { - // const studyHistory = await studyHistoryApi.getStudyHistory(1); + //TODO: 수강 중인 스터디 api 호출 + //const studyId = await myStudyApi.getMyOngoingStudyInfo(); + // const studyHistory = await studyHistoryApi.getStudyHistory(studyId); const studyHistories = history; - if (studyHistories.length === 0) { return ( <> diff --git a/apps/client/app/(afterLogin)/my-assignment/_components/index.ts b/apps/client/app/(afterLogin)/my-study/my-assignment/_components/index.ts similarity index 100% rename from apps/client/app/(afterLogin)/my-assignment/_components/index.ts rename to apps/client/app/(afterLogin)/my-study/my-assignment/_components/index.ts diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx new file mode 100644 index 00000000..df47c7d9 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx @@ -0,0 +1,18 @@ +const Layout = ({ + children, + modal, +}: { + children: React.ReactNode; + modal: React.ReactNode; +}) => { + return ( + <> +
    + {children} + {modal} +
    + + ); +}; + +export default Layout; diff --git a/apps/client/app/(afterLogin)/my-assignment/page.tsx b/apps/client/app/(afterLogin)/my-study/my-assignment/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-assignment/page.tsx rename to apps/client/app/(afterLogin)/my-study/my-assignment/page.tsx 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 new file mode 100644 index 00000000..8a3c9090 --- /dev/null +++ b/apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx @@ -0,0 +1,8 @@ +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/constants/assignmentMockData.ts b/apps/client/constants/assignmentMockData.ts index b895c887..e867f1b6 100644 --- a/apps/client/constants/assignmentMockData.ts +++ b/apps/client/constants/assignmentMockData.ts @@ -27,7 +27,7 @@ export const history: AssignmentHistoryDto[] = [ export const studyDashBoardData: StudyDetailDashboardDto = { repositoryLink: "", - isLinkEditable: false, + isLinkEditable: true, submittableAssignments: [ { studyDetailId: 1, diff --git a/apps/client/constants/routePath.ts b/apps/client/constants/routePath.ts index aba26b8e..c4217f62 100644 --- a/apps/client/constants/routePath.ts +++ b/apps/client/constants/routePath.ts @@ -2,12 +2,14 @@ export const routePath = { auth: "/auth", landing: "/landing", ["my-study"]: "/my-study", - ["my-assignment"]: "/my-assignment", + ["attendance-check"]: "/my-study/attendance-check", + ["my-assignment"]: "/my-study/my-assignment", + ["my-assignment-repository-url-confirmation"]: + "/my-study/my-assignment/repository-url/confirmation", ["study-apply"]: "/study-apply", ["study-application-modal"]: "/study-apply/study-application", ["study-cancellation-modal"]: "/study-apply/study-cancellation", ["auth-error-during-recruitment"]: "/auth-error-during-recruitment", ["auth-error-after-recruitment"]: "/auth-error-after-recruitment", - ["attendance-check"]: "/my-study/attendance-check", onboarding: "https://onboarding.gdschongik.com", } as const; diff --git a/apps/client/hooks/useMatchedStudyHistoryId.ts b/apps/client/hooks/useMatchedStudyHistoryId.ts new file mode 100644 index 00000000..afff0ea9 --- /dev/null +++ b/apps/client/hooks/useMatchedStudyHistoryId.ts @@ -0,0 +1,33 @@ +"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/middleware.ts b/apps/client/middleware.ts index bea40fba..8f0f5baf 100644 --- a/apps/client/middleware.ts +++ b/apps/client/middleware.ts @@ -6,12 +6,7 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; export const config = { - matcher: [ - "/my-page/:path*", - "/my-study/:path*", - "/study-apply/:path*", - "/my-assignment/:path*", - ], + matcher: ["/my-page/:path*", "/my-study/:path*", "/study-apply/:path*"], }; const middleware = async (req: NextRequest) => { diff --git a/apps/client/types/dtos/studyHistory.ts b/apps/client/types/dtos/studyHistory.ts index 74f28e46..cfe91e03 100644 --- a/apps/client/types/dtos/studyHistory.ts +++ b/apps/client/types/dtos/studyHistory.ts @@ -1,4 +1,7 @@ -import type { AssignmentSubmissionStatusType } from "types/entities/common/assignment"; +import type { + AssignmentSubmissionStatusType, + SubmissionFailureType, +} from "types/entities/common/assignment"; export interface AssignmentHistoryDto { assignmentHistoryId: number; @@ -7,5 +10,6 @@ export interface AssignmentHistoryDto { descriptionLink?: string; submissionLink?: string; assignmentSubmissionStatus: AssignmentSubmissionStatusType; //TODO: 과제 휴강 여부 추가 + submissionFailureType?: SubmissionFailureType; week: number; } diff --git a/apps/client/types/entities/myAssignment.ts b/apps/client/types/entities/myAssignment.ts index 31b42b3c..b52c6f4a 100644 --- a/apps/client/types/entities/myAssignment.ts +++ b/apps/client/types/entities/myAssignment.ts @@ -1 +1,4 @@ -export type RepositorySubmissionStatusType = "EDITING" | "SUBMITTED"; +export type RepositorySubmissionStatusType = + | "EDITING" + | "SUBMITTED" + | "EDITING_WITH_WARNING"; diff --git a/packages/ui/src/styles.css b/packages/ui/src/styles.css index 18f3f9ee..9bbe6b47 100644 --- a/packages/ui/src/styles.css +++ b/packages/ui/src/styles.css @@ -803,6 +803,9 @@ progress { .jc_center:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { justify-content: center; } +.flex-d_column:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { + flex-direction: column; +} .top_0:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#) { top: 0; }