,
+ ) => {
+ const { value } = e.target;
+ if (value.length > 4) return;
+ if (Number.isNaN(+value)) return;
+ if (+value[0] > 3 || +value[0] === 0) return;
+ if (+value[1] > 4 || +value[1] === 0) return;
+ if (+value[2] > 1) return;
+ if (+(value[2] + value[3]) > 16 || +(value[2] + value[3]) === 0) return;
+ setStudentNumber(value);
+ };
+
+ const handleStudentSearchClick = () => {
+ meisterDetail.refetch();
+ };
+
+ React.useEffect(() => {
+ if (meisterDetail.isSuccess) {
+ const A = meisterDetail.data.scoreHtmlContent as string;
+ setStudentInfo(
+ A.substring(
+ A.indexOf(
+ // eslint-disable-next-line
+ ``,
+ ),
+ A.indexOf(`
`),
+ ).replace(
+ '',
+ "",
+ ),
+ );
+ }
+ }, [meisterDetail]);
+
+ const meisterPointPostProcessing = () => {
+ document.querySelectorAll(".fas.fa-sad-cry").forEach((item) => {
+ item?.parentElement?.parentElement?.parentElement?.parentElement?.classList.add(
+ "bad",
+ );
+ });
+ document.querySelectorAll("li").forEach((item) => {
+ item?.parentElement?.parentElement?.parentElement?.parentElement?.classList.add(
+ "ssyan",
+ );
+ });
+ };
+
+ React.useEffect(meisterPointPostProcessing, [meisterDetail]);
+
React.useEffect(() => {
if (meisterData.isSuccess) {
setMeister(meisterData.data);
@@ -51,7 +109,7 @@ const MeisterPage = () => {
조회 형식
- {["내 정보", "랭킹"].map((title) => (
+ {["분석", "랭킹"].map((title) => (
{
/>
))}
- {checked === "내 정보" && (
+
+
+ 학번 입력
+
+
+
+ {checked === "분석" && meisterDetail.isSuccess && (
<>
-
-
- {meisterList.map(({ name, color: status }) => (
-
- ))}
-
-
- {meisterData.isSuccess && (
-
- )}
-
-
+
+ {studentInfo.includes(user.name) && (
+ <>
+
+ {meisterList.map(({ name, color: status }) => (
+
+ ))}
+
+
+ {meisterData.isSuccess && (
+
+ )}
+
+
+ >
+ )}
💼 직업 기초 능력
{meisterDetail.isSuccess &&
@@ -238,20 +317,103 @@ const ScoreHTMLContent = styled.div`
`;
const PointHTMLContent = styled.div`
- width: 100%;
- & > div {
- display: none;
+ margin-top: 2.5rem;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 10px;
+
+ div {
+ flex: 100% !important;
+ font-size: 18px !important;
+ font-weight: bold !important;
}
li {
- width: 100%;
- background-color: ${color.white};
+ display: flex !important;
+ flex-direction: column !important;
+ justify-content: center !important;
+ align-items: center !important;
+ width: calc(50% - 0.5rem) !important;
+ height: 12.5rem !important;
+ background-color: #ccffd8 !important;
+ border-radius: 1rem !important;
+ transition: var(--hover-transition) !important;
+ }
- & > div {
- border: none;
- box-shadow: 0;
- }
+ li:hover {
+ background-color: #9effb5 !important;
+ }
+
+ .bad {
+ color: black !important;
+ background-color: #ffd7d5 !important;
}
+
+ .bad:hover {
+ background-color: #ffc9c6 !important;
+ }
+
+ li > div {
+ display: flex !important;
+ flex-direction: column !important;
+ justify-content: center !important;
+ align-items: center !important;
+ border: none !important;
+ box-shadow: none !important;
+ padding: 1rem 2rem !important;
+ }
+
+ li:not(.bad) > div {
+ font-weight: normal !important;
+ }
+
+ li > div > div {
+ font-size: 20px !important;
+ font-weight: 500 !important;
+ text-align: center !important;
+ white-space: pre-wrap !important;
+ color: ${color.gray};
+ padding-top: 10px !important;
+ }
+
+ li > div > div:first-child > div {
+ font-size: 20px !important;
+ font-weight: 500 !important;
+ color: black !important;
+ }
+`;
+
+const InputWrap = styled.div`
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+`;
+
+const InputTitle = styled.span`
+ ${font.p3};
+`;
+
+const StyledInput = styled.input`
+ width: 70px;
+ padding: 8px 6px;
+ box-shadow: 2px 2px 15px 0 rgba(0, 0, 0, 0.05);
+ background-color: ${color.white};
+`;
+
+const StyledButton = styled.button`
+ width: fit-content;
+ padding: 6px 14px;
+ background-color: ${color.primary_blue};
+ border-radius: 6px;
+ color: white;
+`;
+
+const Form = styled.form`
+ display: flex;
+ align-items: center;
+ gap: 12px;
`;
export default MeisterPage;
diff --git a/src/templates/meister/layouts/MeisterProfileBox.tsx b/src/templates/meister/layouts/MeisterProfileBox.tsx
index b45e0028..219133cd 100644
--- a/src/templates/meister/layouts/MeisterProfileBox.tsx
+++ b/src/templates/meister/layouts/MeisterProfileBox.tsx
@@ -1,6 +1,4 @@
-import { defaultProfile } from "@/assets/images";
import { Column, Row } from "@/components/Flex";
-import { ImageWithFallback } from "@/components/atoms";
import useUser from "@/hooks/useUser";
import { color, font } from "@/styles";
import React from "react";
@@ -12,39 +10,19 @@ interface IMeisterProfileBoxProps {
positivePoint: number;
negativePoint: number;
};
+ name: string;
}
-const MeisterProfileBox = ({ meister }: IMeisterProfileBoxProps) => {
- const { user, isLogined } = useUser();
+const MeisterProfileBox = ({ meister, name }: IMeisterProfileBoxProps) => {
+ const { isLogined } = useUser();
return (
{isLogined && (
<>
-
-
- {user.grade >= 2 ? (
- <>
- {user.classNum <= 2 && "소프트웨어"}
- {user.classNum >= 3 && "임베디드소프트웨어"}
- >
- ) : (
- "통합"
- )}
-
- {user.grade}
- {user.classNum}
- {user.studentNumber}
- {user.name}
+ {name}
{meister.score}
@@ -74,30 +52,6 @@ const InfomationText = styled.span`
color: ${color.black};
`;
-const Department = styled(InfomationText)`
- &:after {
- content: "개발과";
- }
-`;
-
-const Grade = styled(InfomationText)`
- &:after {
- content: "학년";
- }
-`;
-
-const ClassNo = styled(InfomationText)`
- &:after {
- content: "반";
- }
-`;
-
-const StudentNo = styled(InfomationText)`
- &:after {
- content: "번";
- }
-`;
-
const Name = styled(InfomationText)``;
const RewardPointText = styled.span`
diff --git a/src/templates/meister/services/api.service.ts b/src/templates/meister/services/api.service.ts
index 7c0697ef..e2262cf8 100644
--- a/src/templates/meister/services/api.service.ts
+++ b/src/templates/meister/services/api.service.ts
@@ -10,11 +10,11 @@ export const getMeisterRanking = async (grade: number) => {
return data;
};
-export const getMeisterDetail = async () => {
+export const getMeisterDetail = async (student: string) => {
const { data } = await httpClient.meister.getDetail({
- grade: 2,
- classNo: 3,
- studentNo: 1,
+ grade: student[0],
+ classNo: student[1],
+ studentNo: +(student[2] + student[3]),
pw: "",
});
return data;
diff --git a/src/templates/meister/services/query.service.ts b/src/templates/meister/services/query.service.ts
index 91a6b23b..8cf9ca94 100644
--- a/src/templates/meister/services/query.service.ts
+++ b/src/templates/meister/services/query.service.ts
@@ -1,5 +1,7 @@
import { KEY } from "@/constants";
import { useQuery } from "@tanstack/react-query";
+import { useRecoilValue } from "recoil";
+import { searchStudentNumberStore } from "@/store/searchStudentNumber.store";
import { getMeister, getMeisterDetail, getMeisterRanking } from "./api.service";
export const useMeisterQuery = () => {
@@ -23,8 +25,9 @@ export const useMeisterRankingQuery = ({
};
export const useMeisterDetailQuery = () => {
+ const student = useRecoilValue(searchStudentNumberStore);
const { data, ...queryRest } = useQuery([KEY.MEISTER_DETAIL], async () =>
- getMeisterDetail(),
+ getMeisterDetail(student),
);
return { data, ...queryRest };
};
diff --git a/src/templates/oauth/services/mutation.service.ts b/src/templates/oauth/services/mutation.service.ts
index 9ca7b931..9fe9a579 100644
--- a/src/templates/oauth/services/mutation.service.ts
+++ b/src/templates/oauth/services/mutation.service.ts
@@ -6,8 +6,8 @@ import { KEY, ROUTER, TOKEN } from "@/constants";
import { ILoginParams, login } from "./api.service";
export const useLoginMutation = ({ authCode }: ILoginParams) => {
- const router = useRouter();
const queryClient = useQueryClient();
+ const router = useRouter();
return useMutation(() => login({ authCode }), {
onSuccess: ({ accessToken, refreshToken }) => {
@@ -15,7 +15,7 @@ export const useLoginMutation = ({ authCode }: ILoginParams) => {
Storage.setItem(TOKEN.REFRESH, refreshToken);
queryClient.invalidateQueries([KEY.USER]);
- router.push(ROUTER.HOME);
+ router.push(Storage.getItem(TOKEN.PATH) ?? ROUTER.HOME);
},
onError: (err) => {
throwAxiosError(err);
diff --git a/src/templates/reserve/services/mutation.service.ts b/src/templates/reserve/services/mutation.service.ts
index 0f7d7838..71d419f3 100644
--- a/src/templates/reserve/services/mutation.service.ts
+++ b/src/templates/reserve/services/mutation.service.ts
@@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { KEY } from "@/constants";
import { ICreateReserve } from "@/interfaces";
import { toast } from "react-toastify";
+import Swal from "sweetalert2";
import { createReserve, deleteReserve } from "./api.service";
export const useCreateReserveMutation = () => {
@@ -14,6 +15,14 @@ export const useCreateReserveMutation = () => {
queryClient.invalidateQueries([KEY.RESERVE]);
toast.success("베르실 예약에 성공했어요!");
},
+ onError: () => {
+ Swal.fire({
+ title: "오류 발생",
+ text: "예약 가능한 날짜에 예약했는지, 혹은 같은 날에 중복으로 예약하진 않았는지 확인해주세요.",
+ icon: "error",
+ confirmButtonText: "확인",
+ });
+ },
},
);
};
diff --git a/src/templates/timetable/index.tsx b/src/templates/timetable/index.tsx
index f83f5b40..21089843 100644
--- a/src/templates/timetable/index.tsx
+++ b/src/templates/timetable/index.tsx
@@ -1,12 +1,33 @@
import styled from "styled-components";
+import { flex } from "@/styles";
+import useUser from "@/hooks/useUser";
+import useModal from "@/hooks/useModal";
+import React from "react";
+import LoginModal from "@/components/common/Modal/LoginModal";
+import { useDidMountEffect } from "@/hooks/useDidMountEffect";
+import Storage from "@/apis/storage";
+import { TOKEN } from "@/constants";
import TimeTableBox from "./layouts/TimeTableBox";
const TimeTablePage = () => {
+ const { isLogined } = useUser();
+ const { openModal } = useModal();
+
+ useDidMountEffect(() => {
+ if (!Storage.getItem(TOKEN.ACCESS)) {
+ openModal({
+ component: ,
+ });
+ }
+ }, []);
+
return (
-
-
-
+ {isLogined && (
+
+
+
+ )}
);
};
@@ -17,9 +38,8 @@ const Layout = styled.div`
`;
const Container = styled.div`
- width: 76%;
- display: flex;
- justify-content: center;
+ width: 100%;
+ ${flex.CENTER}
gap: 8px;
`;
diff --git a/src/templates/timetable/layouts/TimeTableBar.tsx b/src/templates/timetable/layouts/TimeTableBar.tsx
index dffd3eec..677cde5f 100644
--- a/src/templates/timetable/layouts/TimeTableBar.tsx
+++ b/src/templates/timetable/layouts/TimeTableBar.tsx
@@ -4,13 +4,19 @@ import { ITimetable } from "@/interfaces";
import useTimetableBar from "@/hooks/useTimetableBar";
import useDate from "@/hooks/useDate";
import React from "react";
+import dayjs from "dayjs";
interface ITimeTableBarProps {
weekday: string;
dayTimeTable: ITimetable;
+ setSelectedDay: React.Dispatch>;
}
-const TimeTableBar = ({ weekday, dayTimeTable }: ITimeTableBarProps) => {
+const TimeTableBar = ({
+ weekday,
+ dayTimeTable,
+ setSelectedDay,
+}: ITimeTableBarProps) => {
const {
scrollRef,
isScrollBox,
@@ -18,11 +24,18 @@ const TimeTableBar = ({ weekday, dayTimeTable }: ITimeTableBarProps) => {
handleTimetableBarScroll,
handleTimetableButtonClick,
} = useTimetableBar();
- const { getDiffDayTime } = useDate();
+ const { weekdaysKOR, getDiffDayTime } = useDate();
+
+ const handleTimetable동기화ButtonClick = () => {
+ setSelectedDay(weekdaysKOR[dayjs().day()]);
+ handleTimetableButtonClick();
+ };
return (
- {isScrollBox && }
+ {isScrollBox && (
+
+ )}
{nowDate}
diff --git a/src/templates/timetable/layouts/TimeTableBox.tsx b/src/templates/timetable/layouts/TimeTableBox.tsx
index a7923435..4ae34518 100644
--- a/src/templates/timetable/layouts/TimeTableBox.tsx
+++ b/src/templates/timetable/layouts/TimeTableBox.tsx
@@ -3,6 +3,7 @@ import styled from "styled-components";
import useDate from "@/hooks/useDate";
import { useQueryClient } from "@tanstack/react-query";
import { KEY } from "@/constants";
+import Storage from "@/apis/storage";
import { emptyTimetable } from "@/assets/data";
import TimeTableBar from "./TimeTableBar";
import { useTimetableListQuery } from "../services/query.service";
@@ -16,7 +17,7 @@ const TimeTableBox = () => {
getNowWeekDay({ type: "KOR" }),
);
const [timetableType, setTimetableType] = React.useState<"bar" | "table">(
- "bar",
+ (Storage.getItem("timetable_type") as "bar" | "table") ?? "bar",
);
const [dayTimeTable, setDayTimeTable] = React.useState(emptyTimetable);
@@ -32,21 +33,28 @@ const TimeTableBox = () => {
return (
-
- {timetableType === "bar" && (
-
+
- )}
- {timetableType === "table" && (
-
+
+ {!!dayTimeTable[translateDay(selectedDay, { to: "ENG_DETAIL" })] && (
+ <>
+ {timetableType === "bar" && (
+
+ )}
+ {timetableType === "table" && (
+
+ )}
+ >
)}
);
@@ -55,9 +63,15 @@ const TimeTableBox = () => {
const Container = styled.div`
display: flex;
flex-direction: column;
- width: 100%;
+ width: fit-content;
justify-content: center;
+ align-items: center;
gap: 4vh;
+ width: 56%;
+`;
+
+const TimeTableLayoutBox = styled.div`
+ margin-right: auto;
`;
export default TimeTableBox;
diff --git a/src/templates/timetable/layouts/TimeTableCategory.tsx b/src/templates/timetable/layouts/TimeTableCategory.tsx
index 931e4442..52d6e9df 100644
--- a/src/templates/timetable/layouts/TimeTableCategory.tsx
+++ b/src/templates/timetable/layouts/TimeTableCategory.tsx
@@ -3,6 +3,7 @@ import { Column } from "@/components/Flex";
import { Category } from "@/components/atoms";
import { font } from "@/styles";
import { getTimetableType } from "@/helpers";
+import Storage from "@/apis/storage";
interface ITimeTableCategoryProps {
weekdays: Array;
@@ -19,9 +20,31 @@ const TimeTableCategory = ({
timetableType,
setTimetableType,
}: ITimeTableCategoryProps) => {
+ const handleTimetableTypeChange = (
+ e: React.ChangeEvent,
+ ) => {
+ setTimetableType(e.target.id as "bar" | "table");
+ Storage.setItem("timetable_type", e.target.id);
+ };
+
return (
+
+
+
+ {["bar", "table"].map((type) => (
+
+ ))}
+
+
{timetableType === "bar" && (
@@ -39,21 +62,6 @@ const TimeTableCategory = ({
)}
-
-
-
- {["bar", "table"].map((type) => (
- setTimetableType(e.target.id as "bar" | "table")}
- name="date"
- />
- ))}
-
-
);
};
diff --git a/src/templates/timetable/layouts/TimeTableTable.tsx b/src/templates/timetable/layouts/TimeTableTable.tsx
index cb312049..a2baa3b4 100644
--- a/src/templates/timetable/layouts/TimeTableTable.tsx
+++ b/src/templates/timetable/layouts/TimeTableTable.tsx
@@ -12,7 +12,7 @@ interface ITimeTableTableProps {
const TimeTableTable = ({ dayTimeTable }: ITimeTableTableProps) => {
const { weekdaysENGDetail: weekdays, translateDay } = useDate();
- return (
+ return Object.entries(dayTimeTable).length ? (
{Array.from({ length: 8 }).map((_, i) => (
@@ -39,6 +39,8 @@ const TimeTableTable = ({ dayTimeTable }: ITimeTableTableProps) => {
);
})}
+ ) : (
+ <> >
);
};
diff --git a/src/types/storageSettingKey.type.ts b/src/types/storageSettingKey.type.ts
index c020c394..f8789a60 100644
--- a/src/types/storageSettingKey.type.ts
+++ b/src/types/storageSettingKey.type.ts
@@ -1,3 +1,9 @@
-type StorageSettingKey = "theme" | "viewAllChildComments" | "post_render_limit";
+type StorageSettingKey =
+ | "theme"
+ | "viewAllChildComments"
+ | "post_render_limit"
+ | "timetable_type"
+ | "display"
+ | "path";
export default StorageSettingKey;