Skip to content

Commit

Permalink
feat: 스터디 신청 api 연결 및 응답 포맷팅 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
SeieunYoo committed Aug 17, 2024
1 parent be97dde commit e952f5b
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 32 deletions.
48 changes: 48 additions & 0 deletions apps/client/apis/studyApplyApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { fetcher } from "@wow-class/utils";
import { apiPath } from "constants/apiPath";
import { tags } from "constants/tags";
import type { StudyListApiResponseDto } from "types/dtos/apply-study";

export const studyApplyApi = {
getStudyList: async () => {
const response = await fetcher.get<StudyListApiResponseDto[]>(
apiPath.applyStudy,
{
next: { tags: [tags.studyApply] },
headers: {
Authorization: `Bearer ${process.env.DEV_AUTH_TOKEN}`,
},
}
);

return response.data;
},
applyStudy: async (studyId: number) => {
const response = await fetcher.post(`${apiPath.applyStudy}/${studyId}`, {
headers: {
Authorization: `Bearer ${process.env.NEXT_PUBLIC_DEV_AUTH_TOKEN}`,
},
});

if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData);
}

return response.data;
},
cancelStudyApplication: async (studyId: number) => {
const response = await fetcher.delete(`${apiPath.applyStudy}/${studyId}`, {
headers: {
Authorization: `Bearer ${process.env.NEXT_PUBLIC_DEV_AUTH_TOKEN}`,
},
});

if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData);
}

return response.data;
},
};
90 changes: 90 additions & 0 deletions apps/client/app/(afterLogin)/study-apply/_components/StudyItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"use client";

import { css } from "@styled-system/css";
import { styled } from "@styled-system/jsx";
import { Table, Text } from "@wow-class/ui";
import { parseDate, splitTime } from "@wow-class/utils";
import { studyApplyApi } from "apis/studyApplyApi";
import { dayToKorean } from "constants/dayToKorean";
import type { ComponentProps } from "react";
import type { StudyListApiResponseDto } from "types/dtos/apply-study";
import Button from "wowds-ui/Button";
import Tag from "wowds-ui/Tag";

interface StudyItemProps {
study: StudyListApiResponseDto;
}
const StudyItem = ({ study }: StudyItemProps) => {
//NOTE: 모달이 열리도록 수정 예정
const handleApplyButtonClick = () => {
studyApplyApi
.applyStudy(study.studyId)
.then(() => {
console.log("success");
})
.catch((error) => {
console.error("스터디 신청 실패:", error.errorMessage || error);
});
};

//NOTE: 임시로 신청 취소 버튼 만듬 (추후에 응답에 신청 여부에 따라 하나의 버튼에서 이루어질 수 있도록 수정)
const handleCancelButtonClick = () => {
studyApplyApi
.cancelStudyApplication(study.studyId)
.then(() => {
console.log("success");
})
.catch((error) => {
console.error("스터디 취소 실패:", error.errorMessage || error);
});
};

return (
<Table>
<Table.Content
subText={`${study.introduction}-${study.notionLink}`}
text={study.title}
rightContent={
<Tag
variant="solid1"
color={
sessionColors[study.studyType] as ComponentProps<
typeof Tag
>["color"]
}
>
{study.studyType}
</Tag>
}
/>
<Text className={textCellStyle}>{study.mentorName}</Text>
<Text
className={textCellStyle}
>{`${dayToKorean[study.dayOfWeek.toLocaleUpperCase()]} ${splitTime(study.startTime).hours}:${splitTime(study.startTime).minutes}-${Number(splitTime(study.startTime).hours) + 1}:${splitTime(study.startTime).minutes}`}</Text>
<Text className={textCellStyle}>{study.totalWeek}주 코스</Text>
<Text
className={textCellStyle}
>{`${parseDate(study.openingDate).month}.${parseDate(study.openingDate).day} 개강`}</Text>
<styled.div paddingX="24px">
<Button size="sm" variant="solid" onClick={handleApplyButtonClick}>
수강 신청
</Button>
<Button size="sm" variant="solid" onClick={handleCancelButtonClick}>
신청 취소
</Button>
</styled.div>
</Table>
);
};

const textCellStyle = css({
paddingX: "28px",
});

const sessionColors: Record<string, ComponentProps<typeof Tag>["color"]> = {
"과제 스터디": "green",
"온라인 세션": "blue",
"오프라인 세션": "yellow",
};

export default StudyItem;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as StudytItem } from "./StudyItem";
41 changes: 9 additions & 32 deletions apps/client/app/(afterLogin)/study-apply/page.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,22 @@
import { css } from "@styled-system/css";
import { styled } from "@styled-system/jsx";
import { Space, Table, Text } from "@wow-class/ui";
import Button from "wowds-ui/Button";
import Tag from "wowds-ui/Tag";
import { Space, Text } from "@wow-class/ui";
import { studyApplyApi } from "apis/studyApplyApi";

import StudyItem from "./_components/StudyItem";

const StudyApplyPage = async () => {
const studyList = await studyApplyApi.getStudyList();

const StudyApplyPage = () => {
const array = [0, 1, 2];
return (
<>
<Text as="h1" typo="h1">
신청 가능한 스터디
</Text>
<Space height={19} />
{array.map(() => (
<Table>
<Table.Content
subText="(스터디 한 줄 소개-스터디 상세 설명 노션 링크로 연결)"
text="기초 웹 스터디"
rightContent={
<Tag color="yellow" variant="solid1">
신규
</Tag>
}
/>
<Text className={textCellStyle}>강가은 멘토</Text>
<Text className={textCellStyle}>화 18:00-19:00</Text>
<Text className={textCellStyle}>4주 코스</Text>
<Text className={textCellStyle}>06.18 개강</Text>
<styled.div paddingX="24px">
<Button size="sm" variant="solid">
수강 신청
</Button>
</styled.div>
</Table>
{studyList?.map((study) => (
<StudyItem key={study.studyId} study={study} />
))}
</>
);
};

export default StudyApplyPage;

const textCellStyle = css({
paddingX: "28px",
});
2 changes: 2 additions & 0 deletions apps/client/constants/apiPath.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const enum apiPath {
dashboard = "/onboarding/members/me/dashboard",

applyStudy = "/studies/apply",
}
9 changes: 9 additions & 0 deletions apps/client/constants/dayToKorean.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const dayToKorean: Record<string, string> = {
MONDAY: "월",
TUESDAY: "화",
WEDNESDAY: "수",
THURSDAY: "목",
FRIDAY: "금",
SATURDAY: "토",
SUNDAY: "일",
};
1 change: 1 addition & 0 deletions apps/client/constants/tags.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const enum tags {
dashboard = "dashboard",
studyApply = "studyApply",
}
19 changes: 19 additions & 0 deletions apps/client/types/dtos/apply-study.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface StudyListApiResponseDto {
studyId: number;
title: string;
studyType: string;
notionLink: string;
introduction: string;
mentorName: string;
dayOfWeek:
| "MONDAY"
| "TUESDAY"
| "WEDNESDAY"
| "THURSDAY"
| "FRIDAY"
| "SATURDAY"
| "SUNDAY";
startTime: string;
totalWeek: number;
openingDate: string;
}
2 changes: 2 additions & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default as fetcher } from "./fetcher";
export { default as parseDate } from "./parseDate";
export { default as splitTime } from "./splitTime";
20 changes: 20 additions & 0 deletions packages/utils/src/parseDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
*
* @description ISO Date 형식의 string 을 hours, minutes, seconds, year, month, day 로 파싱합니다.
* @example parseDate("2021-08-31T00:00:00.000Z") -> { year: 2021, month: 8, day: 31, hours: 0, minutes: 0, seconds: 0 }
*/

const parseDate = (dateString: string) => {
const date = new Date(dateString);

return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
};
};

export default parseDate;
15 changes: 15 additions & 0 deletions packages/utils/src/splitTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @description 시간을 받아 시간, 분, 초로 나누어 반환합니다.
* @example splitTime("12:30:00") -> { hours: "12", minutes: "30", seconds: "00" }
*/

const splitTime = (timeString: string) => {
const [hours, minutes, seconds] = timeString.split(":");
return {
hours,
minutes,
seconds,
};
};

export default splitTime;

0 comments on commit e952f5b

Please sign in to comment.