diff --git a/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/_hooks/useSubmitStudyDetailInfo.ts b/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/_hooks/useSubmitStudyDetailInfo.ts
new file mode 100644
index 00000000..efcf46f0
--- /dev/null
+++ b/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/_hooks/useSubmitStudyDetailInfo.ts
@@ -0,0 +1,38 @@
+import { createStudyApi } from "apis/study/createStudyApi";
+import { routerPath } from "constants/router/routerPath";
+import { tags } from "constants/tags";
+import { useRouter } from "next/navigation";
+import { useState } from "react";
+import type { CreateStudyDetailInfoApiRequestDto } from "types/dtos/studyDetailInfo";
+import { revalidateTagByName } from "utils/revalidateTagByName";
+
+const useSubmitStudyDetailInfo = (
+ studyId: number,
+ studyDetailData: CreateStudyDetailInfoApiRequestDto
+) => {
+ const [isSuccess, setIsSuccess] = useState(false);
+ const router = useRouter();
+
+ const handleSubmitDetailInfo = async () => {
+ const data = await createStudyApi.postStudyDetailInfo(
+ studyDetailData,
+ studyId
+ );
+ if (data.success) {
+ setIsSuccess(true);
+ revalidateTagByName(tags.curriculums);
+ const timerId = setTimeout(() => {
+ router.push(`${routerPath.root.href}/${studyId}`);
+ }, 500);
+ return () => clearTimeout(timerId);
+ } else {
+ setIsSuccess(false);
+ window.alert("스터디 상세 정보 저장에 실패했어요.");
+ router.push(`${routerPath.root.href}`);
+ }
+ };
+
+ return { isSuccess, handleSubmitDetailInfo };
+};
+
+export default useSubmitStudyDetailInfo;
diff --git a/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/page.tsx b/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/page.tsx
new file mode 100644
index 00000000..814e4458
--- /dev/null
+++ b/apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/page.tsx
@@ -0,0 +1,112 @@
+"use client";
+
+import { Flex } from "@styled-system/jsx";
+import { Modal, Space, Text } from "@wow-class/ui";
+import { useModalRoute } from "@wow-class/ui/hooks";
+import { studyApi } from "apis/study/studyApi";
+import useParseSearchParams from "hooks/useParseSearchParams";
+import { useSearchParams } from "next/navigation";
+import { useEffect, useState } from "react";
+import type { CreateStudyDetailInfoApiRequestDto } from "types/dtos/studyDetailInfo";
+import Button from "wowds-ui/Button";
+
+import useSubmitStudyDetailInfo from "./_hooks/useSubmitStudyDetailInfo";
+
+const StudyDetailInfoCheckModal = () => {
+ const [studyName, setStudyName] = useState("");
+ const { onClose } = useModalRoute();
+ const { parseQueryString } = useParseSearchParams();
+ const searchParams = useSearchParams();
+ const { studyId, ...formData } = parseQueryString<
+ CreateStudyDetailInfoApiRequestDto & { studyId: string }
+ >(searchParams.toString());
+
+ const { isSuccess, handleSubmitDetailInfo } = useSubmitStudyDetailInfo(
+ parseInt(studyId, 10),
+ formData
+ );
+
+ useEffect(() => {
+ const fetchStudyData = async () => {
+ const response = await studyApi.getStudyBasicInfo(parseInt(studyId, 10));
+ if (response) setStudyName(response.title);
+ };
+ fetchStudyData();
+ }, [studyId]);
+
+ return (
+
+
+
+
+ );
+};
+
+export default StudyDetailInfoCheckModal;
+
+const SubmitSuccessMessage = ({
+ success,
+ studyName,
+}: {
+ success: boolean;
+ studyName: string;
+}) => {
+ return (
+ <>
+ {success && (
+
+
+ {studyName}
+
+
+ 상세 정보가 저장되었어요.
+
+
+ )}
+ >
+ );
+};
+
+const SubmitConfirmMessage = ({
+ success,
+ studyName,
+ closeModal,
+ handleSubmitDetailInfo,
+}: {
+ success: boolean;
+ studyName: string;
+ closeModal: () => void;
+ handleSubmitDetailInfo: () => void;
+}) => {
+ if (!success) {
+ return (
+
+
+
+ {studyName}
+
+
+ 의 상세정보
+
+
+
+ 입력 내용을 저장하시겠어요?
+
+
+
+
+
+
+
+ );
+ } else {
+ return;
+ }
+};
diff --git a/apps/admin/app/studies/detail-info/[studyId]/@modal/default.tsx b/apps/admin/app/studies/detail-info/[studyId]/@modal/default.tsx
new file mode 100644
index 00000000..395785b9
--- /dev/null
+++ b/apps/admin/app/studies/detail-info/[studyId]/@modal/default.tsx
@@ -0,0 +1,5 @@
+const Default = () => {
+ return null;
+};
+
+export default Default;
diff --git a/apps/admin/app/studies/detail-info/[studyId]/default.tsx b/apps/admin/app/studies/detail-info/[studyId]/default.tsx
new file mode 100644
index 00000000..395785b9
--- /dev/null
+++ b/apps/admin/app/studies/detail-info/[studyId]/default.tsx
@@ -0,0 +1,5 @@
+const Default = () => {
+ return null;
+};
+
+export default Default;
diff --git a/apps/admin/constants/date.ts b/apps/admin/constants/date.ts
new file mode 100644
index 00000000..e69de29b
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/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/assignmentSubmissionStatusMap.ts b/apps/client/constants/assignmentSubmissionStatusMap.ts
new file mode 100644
index 00000000..9a6dc670
--- /dev/null
+++ b/apps/client/constants/assignmentSubmissionStatusMap.ts
@@ -0,0 +1,12 @@
+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/hooks/useFetchAttendanceCheckModalInfoData.ts b/apps/client/hooks/useFetchAttendanceCheckModalInfoData.ts
new file mode 100644
index 00000000..f53ba8b3
--- /dev/null
+++ b/apps/client/hooks/useFetchAttendanceCheckModalInfoData.ts
@@ -0,0 +1,45 @@
+import { myStudyApi } from "apis/myStudyApi";
+import { useEffect, useState } from "react";
+
+const useFetchAttendanceCheckModalInfoData = () => {
+ const [studyInfo, setStudyInfo] = useState({
+ currentWeek: 0,
+ studyName: "",
+ });
+
+ useEffect(() => {
+ const fetchAttendanceCheckModalInfoData = async () => {
+ const myOngoingStudyData = await myStudyApi.getMyOngoingStudyInfo();
+
+ if (!myOngoingStudyData?.studyId) {
+ return null;
+ }
+
+ const dailyTaskListData = await myStudyApi.getDailyTaskList(
+ myOngoingStudyData?.studyId
+ );
+ const basicStudyInfoData = await myStudyApi.getBasicStudyInfo(
+ myOngoingStudyData?.studyId
+ );
+
+ const attendanceDailyTask = dailyTaskListData?.find(
+ (dailyTask) => dailyTask.todoType === "ATTENDANCE"
+ );
+
+ if (!attendanceDailyTask?.week || !basicStudyInfoData?.title) {
+ return null;
+ }
+
+ setStudyInfo({
+ currentWeek: attendanceDailyTask?.week,
+ studyName: basicStudyInfoData?.title,
+ });
+ };
+
+ fetchAttendanceCheckModalInfoData();
+ }, []);
+
+ return { studyInfo };
+};
+
+export default useFetchAttendanceCheckModalInfoData;
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/utils/index.ts b/apps/client/utils/index.ts
new file mode 100644
index 00000000..de1e7667
--- /dev/null
+++ b/apps/client/utils/index.ts
@@ -0,0 +1 @@
+export { default as isDeadlinePassed } from "./isDeadlinePassed";