diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/_components/Navigation.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/_components/Navigation.tsx new file mode 100644 index 00000000..515d6105 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/_components/Navigation.tsx @@ -0,0 +1,67 @@ +"use client"; + +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { Alarm } from "components/Icon/Alarm"; +import { Calendar } from "components/Icon/Calendar"; +import { Home } from "components/Icon/Home"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +const Navigation = () => { + const pathname = usePathname(); + + return ( + + ); +}; + +export default Navigation; + +const navigationStyle = css({ + position: "fixed", + left: 0, + bottom: 0, + backgroundColor: "backgroundNormal", + height: "90px", + width: "100%", + paddingTop: "16px", + boxShadow: "0px -2px 10px 0px rgba(0, 0, 0, 0.10)", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/_components/PageHeader.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/_components/PageHeader.tsx new file mode 100644 index 00000000..c6daaf03 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/_components/PageHeader.tsx @@ -0,0 +1,21 @@ +import { css } from "@styled-system/css"; +import { membersApi } from "apis/membersApi"; +import Header from "wowds-ui/Header"; + +const PageHeader = async () => { + const myInfo = await membersApi.getMyAccountInfo(); + + return ( +
+
+
+ ); +}; + +const headerStyle = css({ + position: "fixed", + backgroundColor: "backgroundNormal", + width: "100%", +}); + +export default PageHeader; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/layout.tsx new file mode 100644 index 00000000..87bfa702 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/layout.tsx @@ -0,0 +1,23 @@ +import { css } from "@styled-system/css"; +import type { Metadata } from "next"; + +import Navigation from "../_components/Navigation"; + +export const metadata: Metadata = { + title: "스터디 공지", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return ( + <> +
{children}
+ + + ); +}; + +export default Layout; + +const layoutContainerStyle = css({ + marginBottom: "90px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/page.tsx new file mode 100644 index 00000000..eb8c96ff --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/announcement/page.tsx @@ -0,0 +1,85 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { formatISODateWithDot } from "@wow-class/utils"; +import { myStudyApi } from "apis/myStudyApi"; +import Image from "next/image"; + +const MobileStudyAnnouncementPage = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; + } + + const studyAnnouncementListData = await myStudyApi.getStudyAnnouncementList( + myOngoingStudyInfoData?.studyId + ); + + return ( +
+ + 스터디 공지 + + + {studyAnnouncementListData?.length ? ( + studyAnnouncementListData?.map( + ({ studyAnnounceId, title, createdDate }) => ( +
+ + {title} + + + {formatISODateWithDot(createdDate)} + +
+ ) + ) + ) : ( + + empty-study + + 올라온 공지가 없어요. + + + )} +
+
+ ); +}; + +export default MobileStudyAnnouncementPage; + +const studyAnnouncementListHeadingStyle = css({ + marginBottom: "md", +}); + +const studyAnnouncementListBoxStyle = css({ + alignItems: "center", + borderRadius: "10px", + height: "72px", + display: "flex", + justifyContent: "space-between", + border: "1px solid", + borderColor: "outline", + backgroundColor: "backgroundNormal", + padding: "24px", +}); + +const studyAnnouncementTitleStyle = css({ + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/_components/AttendanceCheckBox.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/_components/AttendanceCheckBox.tsx new file mode 100644 index 00000000..4e216f84 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/_components/AttendanceCheckBox.tsx @@ -0,0 +1,57 @@ +"use client"; + +import { Divider, Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { parseISODate } from "@wow-class/utils"; +import useAttendanceCheckSearchParams from "hooks/useAttendanceCheckSearchParams"; +import Link from "next/link"; +import Button from "wowds-ui/Button"; + +export const AttendanceCheckBox = () => { + const { studyDetailId, studyName, deadLine, currentWeek, mentorName } = + useAttendanceCheckSearchParams(); + + const { year, month, day, hours, minutes } = parseISODate(deadLine); + + const { + year: currentYear, + month: currentMonth, + day: currentDay, + } = parseISODate(new Date().toISOString()); + + return ( + <> + + {studyName} + + {mentorName} + + + + + + 출석 체크 + {currentWeek}주차 + + + 수강 날짜 + + {currentYear}년 {currentMonth}월 {currentDay}일 + + + + 출석 인정 시간 + + {year}년 {month}월 {day}일 00:00 - {hours}:{minutes} + + + + + + ); +}; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/layout.tsx new file mode 100644 index 00000000..4cc7ba6e --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/layout.tsx @@ -0,0 +1,11 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "출석 체크", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return <>{children}; +}; + +export default Layout; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/page.tsx new file mode 100644 index 00000000..7852bc6e --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-info/page.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { Space, Text } from "@wow-class/ui"; +import { Suspense } from "react"; + +import { AttendanceCheckBox } from "./_components/AttendanceCheckBox"; + +const MobileAttendanceCheckInfoPage = () => { + return ( + <> + + 출석 체크 + + + + + + + ); +}; + +export default MobileAttendanceCheckInfoPage; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/AttendanceCheckForm.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/AttendanceCheckForm.tsx new file mode 100644 index 00000000..4c9fcced --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/AttendanceCheckForm.tsx @@ -0,0 +1,112 @@ +"use client"; + +import { myStudyApi } from "apis/myStudyApi"; +import { tags } from "constants/tags"; +import useAttendanceCheckSearchParams from "hooks/useAttendanceCheckSearchParams"; +import type { CSSProperties, KeyboardEventHandler } from "react"; +import { useState } from "react"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import { validateAttendanceNumber } from "utils/validateAttendanceNumber"; +import { color } from "wowds-tokens"; +import Button from "wowds-ui/Button"; +import TextField from "wowds-ui/TextField"; + +const AttendanceCheckForm = ({ + onAttendanceSuccess, +}: { + onAttendanceSuccess: () => void; +}) => { + const { studyDetailId } = useAttendanceCheckSearchParams(); + + const [error, setError] = useState(false); + const [attendanceNumber, setAttendanceNumber] = useState(""); + + const handleChangeAttendanceNumber = (value: string) => { + setAttendanceNumber(value); + }; + + const isAttendanceNumberValid = (attendanceNumber: string) => { + return validateAttendanceNumber(attendanceNumber); + }; + + const checkAttendance = async ( + studyDetailId: number, + attendanceNumber: string + ) => { + const { success } = await myStudyApi.checkAttendance( + studyDetailId, + attendanceNumber + ); + return success; + }; + + const handleClickAttendanceCheckButton = async () => { + const trimmedAttendanceNumber = attendanceNumber.trim(); + + if (!isAttendanceNumberValid(trimmedAttendanceNumber)) { + return setError(true); + } + + const success = await checkAttendance( + +studyDetailId, + trimmedAttendanceNumber + ); + + if (!success) { + return setError(true); + } + + handleAttendanceSuccess(); + }; + + const handleAttendanceSuccess = () => { + onAttendanceSuccess(); + setError(false); + revalidateTagByName(tags.dailyTask); + }; + + const handleKeyDown: KeyboardEventHandler = (event) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + } + }; + return ( + <> + + + + ); +}; + +export default AttendanceCheckForm; + +const textfieldHelperText =
• 출석 실패! 출결번호를 확인해주세요.
; + +const buttonStyle: CSSProperties = { + bottom: "20px", + position: "absolute", + width: "calc(100% - 32px)", + color: color.white, +}; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/StudyInfo.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/StudyInfo.tsx new file mode 100644 index 00000000..69f14ccb --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/_components/StudyInfo.tsx @@ -0,0 +1,17 @@ +"use client"; + +import { Text } from "@wow-class/ui"; +import useAttendanceCheckSearchParams from "hooks/useAttendanceCheckSearchParams"; +const StudyInfo = () => { + const { studyName, currentWeek } = useAttendanceCheckSearchParams(); + return ( + <> + + {studyName} + {currentWeek}주차 + + + ); +}; + +export default StudyInfo; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/layout.tsx new file mode 100644 index 00000000..4cc7ba6e --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/layout.tsx @@ -0,0 +1,11 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "출석 체크", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return <>{children}; +}; + +export default Layout; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/page.tsx new file mode 100644 index 00000000..263e0133 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/attendance-check-input/page.tsx @@ -0,0 +1,69 @@ +"use client"; + +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import Image from "next/image"; +import Link from "next/link"; +import { Suspense, useState } from "react"; +import { color } from "wowds-tokens"; +import Button from "wowds-ui/Button"; + +import AttendanceCheckForm from "./_components/AttendanceCheckForm"; +import StudyInfo from "./_components/StudyInfo"; + +const MobileAttendanceCheckInputPage = () => { + const [attended, setAttended] = useState(false); + + return attended ? ( + + attendance-success + + 출석이 완료되었어요 + + + + + + + ) : ( + + + 출석 체크 + + + + 스터디 시작 후 멘토의 안내에 따라
+ 출결번호를 입력해주세요. +
+ + + { + setAttended(true); + }} + /> + +
+ ); +}; + +export default MobileAttendanceCheckInputPage; + +const buttonStyle: React.CSSProperties = { + bottom: "20px", + position: "absolute", + width: "calc(100% - 32px)", + color: color.white, +}; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/auth/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/auth/page.tsx new file mode 100644 index 00000000..9add65cc --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/auth/page.tsx @@ -0,0 +1,51 @@ +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { routePath } from "constants/routePath"; +import Image from "next/image"; +import Link from "next/link"; +import type { CSSProperties } from "react"; +import { color } from "wowds-tokens"; +import Button from "wowds-ui/Button"; + +const MobileAuthPage = async () => { + return ( + <> + + 로그인 + + + 와우클래스는 GDGoC 정회원만 이용 가능해요.
+ GDGoC 가입을 위해선 GitHub 계정이 필요해요. +
+
+ + + ); +}; + +const githubLogoIcon = ( + github-logo +); + +export default MobileAuthPage; + +const githubLoginButtonStyle: CSSProperties = { + backgroundColor: `${color.github}`, + marginTop: "40px", + bottom: "20px", + position: "absolute", + width: "calc(100% - 32px)", +}; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/layout.tsx new file mode 100644 index 00000000..228019da --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/layout.tsx @@ -0,0 +1,23 @@ +import { css } from "@styled-system/css"; +import type { Metadata } from "next"; + +import Navigation from "../_components/Navigation"; + +export const metadata: Metadata = { + title: "커리큘럼", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return ( + <> +
{children}
+ + + ); +}; + +export default Layout; + +const layoutContainerStyle = css({ + marginBottom: "90px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/page.tsx new file mode 100644 index 00000000..05068a88 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/curriculum/page.tsx @@ -0,0 +1,169 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; +import { attendanceStatusMap } from "constants/attendanceStatusMap"; +import { routePath } from "constants/routePath"; +import Link from "next/link"; +import type { ComponentProps } from "react"; +import type { + AssignmentSubmissionStatusType, + StudyDifficultyType, +} from "types/entities/myStudy"; +import Tag from "wowds-ui/Tag"; + +const MobileStudyCurriculumPage = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoData?.studyId) { + return; + } + + const studyCurriculumData = await myStudyApi.getStudyCurriculumList( + myOngoingStudyInfoData?.studyId + ); + + return ( +
+ 커리큘럼 + + + {studyCurriculumData?.map( + ( + { + week, + title, + description, + difficulty, + attendanceStatus, + assignmentStatus, + assignmentSubmissionStatus, + curriculumStatus, + }, + index + ) => { + const { label: difficultyLabel, color: difficultyColor } = + difficultyMap[difficulty || "LOW"]; + const { + label: attendanceStatusLabel, + color: attendanceStatusColor, + } = + attendanceStatusMap[ + curriculumStatus === "CANCELED" ? "ATTENDED" : attendanceStatus + ]; + const { + label: assignmentSubmissionStatusLabel, + color: assignmentSubmissionStatusColor, + } = + assignmentStatus === "CANCELED" + ? { + label: "과제 휴강", + color: "grey" as ComponentProps["color"], + } + : assignmentMap[assignmentSubmissionStatus || "NOT_SUBMITTED"]; + + return ( + + +
+
+ + {week}주차 + +
+
+ {curriculumStatus === "CANCELED" ? ( + + 휴강 주차 + + ) : description ? ( + + + + {title} + + + {difficultyLabel} + + + + ) : ( + + 작성된 내용이 없어요 + + )} +
+
+
+ + + {attendanceStatusLabel} + + + {assignmentSubmissionStatusLabel} + + +
+
+ + ); + } + )} +
+
+ ); +}; + +export default MobileStudyCurriculumPage; + +const difficultyMap: Record< + StudyDifficultyType, + { label: string; color: ComponentProps["color"] } +> = { + BASIC: { label: "기초", color: "blue" }, + LOW: { label: "초급", color: "yellow" }, + MEDIUM: { label: "중급", color: "green" }, + HIGH: { label: "고급", color: "red" }, +}; + +const assignmentMap: Record< + AssignmentSubmissionStatusType, + { label: string; color: ComponentProps["color"] } +> = { + SUCCESS: { label: "과제 제출", color: "blue" }, + FAILURE: { label: "과제 미제출", color: "red" }, + NOT_SUBMITTED: { label: "과제 진행전", color: "grey" }, +}; +const boxContainerStyle = css({ + backgroundColor: "backgroundNormal", + border: "1px solid", + borderColor: "outline", + padding: "24px", + borderRadius: "10px", + justifyContent: "space-between", +}); + +const weekContainerStyle = css({ + minWidth: "84px", + display: "flex", + alignItems: "center", + gap: "4px", +}); + +const tagStyle = { + margin: "auto", +}; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/layout.tsx new file mode 100644 index 00000000..64120006 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/layout.tsx @@ -0,0 +1,40 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Space } from "@wow-class/ui"; +import type { Metadata } from "next"; + +import PageHeader from "./_components/PageHeader"; + +export const metadata: Metadata = { + robots: { + index: false, + follow: true, + }, +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return ( + + +
+ + {children} +
+
+ ); +}; + +export default Layout; + +const layoutContainerStyle = css({ + left: 0, + lg: { + maxWidth: "390px", + }, + width: "100%", + backgroundColor: "#f8f8f8", + paddingX: "16px", + marginTop: "66px", + minHeight: "calc(100vh - 66px)", + paddingBottom: "20px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AssignmentStatusBox.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AssignmentStatusBox.tsx new file mode 100644 index 00000000..28512225 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AssignmentStatusBox.tsx @@ -0,0 +1,103 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import type { ComponentProps } from "react"; +import type { AssignmentSubmissionStatusType } from "types/entities/myStudy"; +import Box from "wowds-ui/Box"; +import Tag from "wowds-ui/Tag"; + +interface AssignmentStatusBoxProps { + week: number; + name: string; + assignmentSubmissionStatus: AssignmentSubmissionStatusType; + deadLine: string; +} + +const AssignmentStatusBox = ({ + week, + name, + assignmentSubmissionStatus, + deadLine, +}: AssignmentStatusBoxProps) => { + const { year, month, day, hours, minutes } = parseISODate(deadLine); + + const attendanceDeadline = `${year}년 ${month}월 ${day}일 ${padWithZero(hours)}:${padWithZero(minutes)}까지`; + const { + label: assignmentSubmissionStatusLabel, + color: assignmentSubmissionStatusColor, + } = assignmentSubmissionStatusMap[assignmentSubmissionStatus]; + + return ( + + + 과제 + + + + + + {week}주차 과제 + + {assignmentSubmissionStatusLabel && ( + + {assignmentSubmissionStatusLabel} + + )} + + + {name} + + + {attendanceDeadline} + + + + + } + /> + ); +}; + +export default AssignmentStatusBox; + +const assignmentSubmissionStatusMap: Record< + AssignmentSubmissionStatusType, + { label: string; color: ComponentProps["color"] } +> = { + SUCCESS: { label: "제출 완료", color: "blue" }, + FAILURE: { label: "제출 실패", color: "red" }, + NOT_SUBMITTED: { label: "", color: "grey" }, +}; + +const dailyTaskBoxStyle = { + paddingBottom: "24px", +}; + +const dailyTaskBoxContentContainerStyle = css({}); + +const assignmentNameStyle = css({ + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", +}); + +const tagStyle = css({ + height: "20px", +}); + +const assignmentTextStyle = css({ + paddingTop: "3.5px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AttendanceStatusBox.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AttendanceStatusBox.tsx new file mode 100644 index 00000000..3c0d2dd2 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/AttendanceStatusBox.tsx @@ -0,0 +1,117 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import { myStudyApi } from "apis/myStudyApi"; +import { attendanceStatusMap } from "constants/attendanceStatusMap"; +import Link from "next/link"; +import type { AttendanceStatusType } from "types/entities/myStudy"; +import Box from "wowds-ui/Box"; +import Button from "wowds-ui/Button"; +import Tag from "wowds-ui/Tag"; + +interface AttendanceStatusBoxProps { + week: number; + studyDetailId: number; + attendanceStatus: AttendanceStatusType; + deadLine: string; +} + +const AttendanceStatusBox = async ({ + week, + attendanceStatus, + studyDetailId, + deadLine, +}: AttendanceStatusBoxProps) => { + const myOngoingStudyInfoResponse = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyInfoResponse?.studyId) { + return null; + } + + const basicStudyInfoResponse = await myStudyApi.getBasicStudyInfo( + myOngoingStudyInfoResponse?.studyId + ); + const studyName = basicStudyInfoResponse?.title; + const mentorName = basicStudyInfoResponse?.mentorName; + const { + year: startYear, + month: startMonth, + day: startDay, + hours: endHours, + minutes: endMinutes, + } = parseISODate(deadLine); + + const attendancePeriod = `${startYear}년 ${startMonth}월 ${startDay}일 00:00 - ${padWithZero(endHours)}:${padWithZero(endMinutes)}까지`; + const { label: attendanceStatusLabel, color: attendanceStatusColor } = + attendanceStatusMap[attendanceStatus]; + + const attendanceButtonText = + attendanceStatus === "ATTENDED" ? "출석 체크 완료" : "출석 체크하기"; + return ( + + + + 출석 + + + + + + {week}주차 출석체크 + + + {attendanceStatusLabel} + + + + {attendancePeriod} + + + + + + + } + /> + ); +}; + +export default AttendanceStatusBox; + +const dailyTaskBoxStyle = { + paddingBottom: "24px", + gap: "0px", +}; + +const dailyTaskBoxContentContainerStyle = css({}); + +const attendanceButtonStyle = {}; + +const attendanceTextStyle = css({ + paddingTop: "3.5px", +}); + +const tagStyle = css({ + height: "20px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTaskItem.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTaskItem.tsx new file mode 100644 index 00000000..5fb68aed --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTaskItem.tsx @@ -0,0 +1,43 @@ +import type { DailyTaskDto } from "types/dtos/myStudy"; +import type { DailyTaskType } from "types/entities/myStudy"; + +import AssignmentStatusBox from "./AssignmentStatusBox"; +import AttendanceStatusBox from "./AttendanceStatusBox"; + +const DailyTaskItem = ({ + dailyTask, + index, +}: { + dailyTask: DailyTaskDto; + index: number; +}) => { + const { + taskType, + week, + deadLine, + attendanceStatus, + assignmentTitle, + assignmentSubmissionStatus, + studyDetailId, + } = dailyTask; + + return taskType === "ATTENDANCE" ? ( + + ) : ( + + ); +}; + +export default DailyTaskItem; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTasks.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTasks.tsx new file mode 100644 index 00000000..372af9a1 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/DailyTasks.tsx @@ -0,0 +1,50 @@ +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; +import Image from "next/image"; + +import DailyTaskItem from "./DailyTaskItem"; + +const DailyTasks = async () => { + const myOngoingStudyData = await myStudyApi.getMyOngoingStudyInfo(); + + if (!myOngoingStudyData?.studyId) { + return null; + } + + const dailyTaskData = await myStudyApi.getDailyTaskList( + myOngoingStudyData?.studyId + ); + + return ( + <> + 오늘의 할 일 + + + {dailyTaskData?.length ? ( + dailyTaskData.map((dailyTask, index) => ( + + )) + ) : ( + + empty-study + + 아직 할 일이 없어요. + + + )} + + + ); +}; + +export default DailyTasks; diff --git a/apps/client/app/(afterLogin)/my-study/_components/EmptyStudy.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/EmptyStudy.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/EmptyStudy.tsx rename to apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/EmptyStudy.tsx diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/Header.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/Header.tsx new file mode 100644 index 00000000..eae73d94 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/_components/Header.tsx @@ -0,0 +1,21 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; + +const Header = async ({ studyId }: { studyId: number }) => { + const basicStudyInfoData = await myStudyApi.getBasicStudyInfo(studyId); + return ( +
+ + + 수강 중인 스터디 + + + {basicStudyInfoData?.title} + + +
+ ); +}; + +export default Header; diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/layout.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/layout.tsx new file mode 100644 index 00000000..90000bf3 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/layout.tsx @@ -0,0 +1,23 @@ +import { css } from "@styled-system/css"; +import type { Metadata } from "next"; + +import Navigation from "../_components/Navigation"; + +export const metadata: Metadata = { + title: "나의 스터디", +}; + +const Layout = ({ children }: { children: React.ReactNode }) => { + return ( + <> +
{children}
+ + + ); +}; + +export default Layout; + +const layoutContainerStyle = css({ + marginBottom: "90px", +}); diff --git a/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/page.tsx b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/page.tsx new file mode 100644 index 00000000..bc108d61 --- /dev/null +++ b/apps/client/app/(afterLogin)/(mobile)/mobile/my-study/page.tsx @@ -0,0 +1,21 @@ +import { Space } from "@wow-class/ui"; +import { myStudyApi } from "apis/myStudyApi"; + +import DailyTasks from "./_components/DailyTasks"; +import EmptyStudy from "./_components/EmptyStudy"; +import Header from "./_components/Header"; + +const MobileMyStudyPage = async () => { + const myOngoingStudyInfoData = await myStudyApi.getMyOngoingStudyInfo(); + return myOngoingStudyInfoData?.studyId ? ( + <> +
+ + + + ) : ( + + ); +}; + +export default MobileMyStudyPage; diff --git a/apps/client/app/(afterLogin)/layout.tsx b/apps/client/app/(afterLogin)/(pc)/layout.tsx similarity index 100% rename from apps/client/app/(afterLogin)/layout.tsx rename to apps/client/app/(afterLogin)/(pc)/layout.tsx diff --git a/apps/client/app/(afterLogin)/my-page/@modal/(.)logout/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/@modal/(.)logout/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/@modal/(.)logout/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/@modal/(.)logout/page.tsx diff --git a/apps/client/app/(afterLogin)/my-page/@modal/default.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/@modal/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/@modal/default.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/@modal/default.tsx diff --git a/apps/client/app/(afterLogin)/my-page/_components/CompletedStudy.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/_components/CompletedStudy.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/_components/CompletedStudy.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/_components/CompletedStudy.tsx diff --git a/apps/client/app/(afterLogin)/my-page/_components/MyInfoBox.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/_components/MyInfoBox.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/_components/MyInfoBox.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/_components/MyInfoBox.tsx diff --git a/apps/client/app/(afterLogin)/my-page/default.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/default.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/default.tsx diff --git a/apps/client/app/(afterLogin)/my-page/layout.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/layout.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/layout.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/layout.tsx diff --git a/apps/client/app/(afterLogin)/my-page/logout/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/logout/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/logout/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/logout/page.tsx diff --git a/apps/client/app/(afterLogin)/my-page/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-page/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-page/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-page/page.tsx diff --git a/apps/client/app/(afterLogin)/my-study/@modal/(.)attendance-check/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/@modal/(.)attendance-check/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/@modal/(.)attendance-check/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/@modal/(.)attendance-check/page.tsx diff --git a/apps/client/app/(afterLogin)/my-study/@modal/default.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/@modal/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/@modal/default.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/@modal/default.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/AssignmentStatusBox.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/AssignmentStatusBox.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/AssignmentStatusBox.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/AssignmentStatusBox.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/AttendanceStatusBox.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/AttendanceStatusBox.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/AttendanceStatusBox.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/AttendanceStatusBox.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/DailyTaskCarousel.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTaskCarousel.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/DailyTaskCarousel.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTaskCarousel.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/DailyTaskItem.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTaskItem.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/DailyTaskItem.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTaskItem.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/DailyTasks.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTasks.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/DailyTasks.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/DailyTasks.tsx diff --git a/apps/client/app/(afterLogin)/(pc)/my-study/_components/EmptyStudy.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/EmptyStudy.tsx new file mode 100644 index 00000000..9b41450c --- /dev/null +++ b/apps/client/app/(afterLogin)/(pc)/my-study/_components/EmptyStudy.tsx @@ -0,0 +1,27 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import Image from "next/image"; + +const EmptyStudy = () => { + return ( + + empty-study + + 현재 수강 중인 스터디가 없어요 + + + ); +}; + +export default EmptyStudy; diff --git a/apps/client/app/(afterLogin)/my-study/_components/Header.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/Header.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/Header.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/Header.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/StudyAnnouncementList.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/StudyAnnouncementList.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/StudyAnnouncementList.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/StudyAnnouncementList.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/StudyCurriculum.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/_components/StudyCurriculum.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/StudyCurriculum.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/StudyCurriculum.tsx diff --git a/apps/client/app/(afterLogin)/my-study/_components/index.ts b/apps/client/app/(afterLogin)/(pc)/my-study/_components/index.ts similarity index 100% rename from apps/client/app/(afterLogin)/my-study/_components/index.ts rename to apps/client/app/(afterLogin)/(pc)/my-study/_components/index.ts diff --git a/apps/client/app/(afterLogin)/my-study/attendance-check/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/attendance-check/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/attendance-check/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/attendance-check/page.tsx diff --git a/apps/client/app/(afterLogin)/my-study/default.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/default.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/default.tsx diff --git a/apps/client/app/(afterLogin)/my-study/layout.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/layout.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/layout.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/layout.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/index.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentContent/index.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentDescription.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentDescription.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHeader.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHeader.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHistory/index.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/AssignmentHistory/index.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/_components/index.ts b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/_components/index.ts similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/_components/index.ts rename to apps/client/app/(afterLogin)/(pc)/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)/(pc)/my-study/my-assignment/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/default.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/layout.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/layout.tsx diff --git a/apps/client/app/(afterLogin)/my-study/my-assignment/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/my-assignment/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/my-assignment/page.tsx diff --git a/apps/client/app/(afterLogin)/my-study/page.tsx b/apps/client/app/(afterLogin)/(pc)/my-study/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/my-study/page.tsx rename to apps/client/app/(afterLogin)/(pc)/my-study/page.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/@modal/(.)study-application/[studyId]/page.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/@modal/(.)study-application/[studyId]/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/@modal/(.)study-application/[studyId]/page.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/@modal/(.)study-application/[studyId]/page.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/@modal/(.)study-cancellation/[studyId]/page.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/@modal/(.)study-cancellation/[studyId]/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/@modal/(.)study-cancellation/[studyId]/page.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/@modal/(.)study-cancellation/[studyId]/page.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/@modal/default.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/@modal/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/@modal/default.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/@modal/default.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/_components/EmptyStudyApplication.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/_components/EmptyStudyApplication.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/_components/EmptyStudyApplication.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/_components/EmptyStudyApplication.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/_components/StudyItem.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/_components/StudyItem.tsx similarity index 99% rename from apps/client/app/(afterLogin)/study-apply/_components/StudyItem.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/_components/StudyItem.tsx index 7f39fbf1..fe205104 100644 --- a/apps/client/app/(afterLogin)/study-apply/_components/StudyItem.tsx +++ b/apps/client/app/(afterLogin)/(pc)/study-apply/_components/StudyItem.tsx @@ -48,6 +48,7 @@ const StudyItem = ({ study, appliedStudyId }: StudyItemProps) => { const isApplicable = appliedStudyId === null; const isCancelable = appliedStudyId === studyId; const isNotApplicable = !isApplicable && !isCancelable; + console.log(appliedStudyId, studyId); return ( diff --git a/apps/client/app/(afterLogin)/study-apply/_components/index.ts b/apps/client/app/(afterLogin)/(pc)/study-apply/_components/index.ts similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/_components/index.ts rename to apps/client/app/(afterLogin)/(pc)/study-apply/_components/index.ts diff --git a/apps/client/app/(afterLogin)/study-apply/default.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/default.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/default.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/default.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/layout.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/layout.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/layout.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/layout.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/page.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/page.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/page.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/study-application/[studyId]/page.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/study-application/[studyId]/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/study-application/[studyId]/page.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/study-application/[studyId]/page.tsx diff --git a/apps/client/app/(afterLogin)/study-apply/study-cancellation/[studyId]/page.tsx b/apps/client/app/(afterLogin)/(pc)/study-apply/study-cancellation/[studyId]/page.tsx similarity index 100% rename from apps/client/app/(afterLogin)/study-apply/study-cancellation/[studyId]/page.tsx rename to apps/client/app/(afterLogin)/(pc)/study-apply/study-cancellation/[studyId]/page.tsx diff --git a/apps/client/components/Icon/Alarm.tsx b/apps/client/components/Icon/Alarm.tsx new file mode 100644 index 00000000..e437851c --- /dev/null +++ b/apps/client/components/Icon/Alarm.tsx @@ -0,0 +1,29 @@ +import { color } from "wowds-tokens"; + +export const Alarm = ({ selected = false }: { selected?: boolean }) => { + return ( + + + + + + ); +}; diff --git a/apps/client/components/Icon/Calendar.tsx b/apps/client/components/Icon/Calendar.tsx new file mode 100644 index 00000000..0f38550e --- /dev/null +++ b/apps/client/components/Icon/Calendar.tsx @@ -0,0 +1,46 @@ +import { color } from "wowds-tokens"; + +export const Calendar = ({ selected = false }: { selected?: boolean }) => { + return ( + <> + + + + + + + + + + ); +}; diff --git a/apps/client/components/Icon/Home.tsx b/apps/client/components/Icon/Home.tsx new file mode 100644 index 00000000..9415c394 --- /dev/null +++ b/apps/client/components/Icon/Home.tsx @@ -0,0 +1,30 @@ +import { color } from "wowds-tokens"; + +export const Home = ({ selected = false }: { selected?: boolean }) => { + return ( + + + + + + ); +}; diff --git a/apps/client/hooks/useAttendanceCheckSearchParams.ts b/apps/client/hooks/useAttendanceCheckSearchParams.ts index b8d6302e..78004156 100644 --- a/apps/client/hooks/useAttendanceCheckSearchParams.ts +++ b/apps/client/hooks/useAttendanceCheckSearchParams.ts @@ -1,3 +1,5 @@ +"use client"; + import { useSearchParams } from "next/navigation"; const useAttendanceCheckSearchParams = () => { @@ -7,8 +9,9 @@ const useAttendanceCheckSearchParams = () => { const studyName = searchParams.get("study-name"); const deadLine = searchParams.get("deadline") || ""; const currentWeek = searchParams.get("week"); + const mentorName = searchParams.get("mentor"); - return { studyDetailId, studyName, deadLine, currentWeek }; + return { studyDetailId, studyName, deadLine, currentWeek, mentorName }; }; export default useAttendanceCheckSearchParams; diff --git a/apps/client/middleware.ts b/apps/client/middleware.ts index 21eb5885..d59d3d18 100644 --- a/apps/client/middleware.ts +++ b/apps/client/middleware.ts @@ -4,20 +4,35 @@ import { routePath } from "constants/routePath"; import { cookies } from "next/headers"; import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; +import { isMobileUser } from "utils/isMobileUser"; export const config = { - matcher: ["/my-page/:path*", "/my-study/:path*", "/study-apply/:path*"], + matcher: [ + "/my-page/:path*", + "/my-study/:path*", + "/study-apply/:path*", + "/mobile/:path*", + ], }; const middleware = async (req: NextRequest) => { const cookieStore = cookies(); const accessToken = cookieStore.get(cookieKey.accessToken)?.value; const middlewareExecuted = cookieStore.get(cookieKey["middleware-executed"]); + const userAgent = req.headers.get("user-agent") || ""; + const isMobile = isMobileUser(userAgent); + + const url = new URL(req.url); if (!accessToken) { return NextResponse.redirect(new URL(routePath.auth, req.url)); } + if (isMobile && (url.pathname === "/my-study" || url.pathname === "/auth")) { + url.pathname = `/mobile/${url.pathname}`; + return NextResponse.redirect(url); + } + if (!middlewareExecuted) { const { memberRole } = await dashboardApi.getDashboardInfo(); diff --git a/apps/client/public/images/success.svg b/apps/client/public/images/success.svg new file mode 100644 index 00000000..b6ebb9d4 --- /dev/null +++ b/apps/client/public/images/success.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/client/utils/isMobileUser.ts b/apps/client/utils/isMobileUser.ts new file mode 100644 index 00000000..14844706 --- /dev/null +++ b/apps/client/utils/isMobileUser.ts @@ -0,0 +1,5 @@ +export const isMobileUser = (userAgent: string) => { + const mobileRegex = + /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i; + return mobileRegex.test(userAgent); +};