Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(time): 타임테이블 모달 api 연동 #211

Merged
merged 18 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3b3cb40
feat(time): add day status constant in region & add campus status con…
SWARVY Aug 17, 2024
59104f3
chore(time): install react-query & react-query-devtools (#97)
SWARVY Aug 17, 2024
bccc52f
chore(time): service rename '경기타임' -> '경기플러스' (#97)
SWARVY Aug 17, 2024
7ef2e26
feat(time): create util hook 'useDebounce' (#97)
SWARVY Aug 17, 2024
b216950
feat(time): add fetch function getLectureList / getMajorList & add en…
SWARVY Aug 17, 2024
a7f3a80
feat(time): add custom-hook useLectureList / useMajorList & add query…
SWARVY Aug 17, 2024
ed7bf6f
chore(time): add missing index.ts files (#97)
SWARVY Aug 17, 2024
3743ce0
chore(time): fix typo 'GetLectureListReponseValue' -> 'GetLectureList…
SWARVY Aug 18, 2024
c6141e5
feat(time): add TimeTable components / split LectureTable & integrate…
SWARVY Aug 18, 2024
0fc8218
chore(time): fix incorrect type definition 'GetLectureListResponseVal…
SWARVY Aug 18, 2024
e5a44ac
Merge branch 'main' of https://github.com/KGU-C-Lab/clab-platforms in…
SWARVY Aug 18, 2024
5474564
Create grumpy-beers-travel.md
gwansikk Aug 18, 2024
51b6f3e
refactor(time): add generic in `useDebounce` for correct type inference
SWARVY Aug 18, 2024
944877d
refactor(time): add `getAPIURL` util function to reduce redundant logic
SWARVY Aug 18, 2024
3e670eb
chore(time): rename input change function '-Input' -> 'InputChange'
SWARVY Aug 18, 2024
8c3fd38
Merge branch 'feature/#97' of https://github.com/KGU-C-Lab/clab-platf…
SWARVY Aug 18, 2024
23ea19d
refactor(time): apply missing generic type in `useDebounce`
SWARVY Aug 18, 2024
290fb41
refactor(time): rename endpoint object attributes to upper snake case
SWARVY Aug 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/grumpy-beers-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clab-platforms/time": patch
---

feat(time): 타임테이블 모달 api 연동
2 changes: 2 additions & 0 deletions apps/time/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"@clab-platforms/design-system": "workspace:*",
"@clab-platforms/icon": "workspace:^",
"@clab-platforms/utils": "workspace:*",
"@tanstack/react-query": "^5.51.23",
"@tanstack/react-query-devtools": "^5.40.1",
"jotai": "^2.9.2",
"next": "14.1.4",
"react": "^18",
Expand Down
2 changes: 1 addition & 1 deletion apps/time/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import './globals.css';
const inter = Noto_Sans_KR({ subsets: ['latin'] });

export const metadata: Metadata = {
title: '경기타임',
title: '경기플러스',
description: '경기대학교에 계신 모든 순간을 도와드릴게요.',
icons: {
icon: '/favicon.ico',
Expand Down
1 change: 1 addition & 0 deletions apps/time/src/shared/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { default as useEditableSearchParams } from './useEditableSearchParams';
export { default as useOutsideClick } from './useOutsideClick';
export { default as useModalAction } from './useModalAction';
export { default as useModalState } from './useModalState';
export { default as useDebounce } from './useDebounce';
19 changes: 19 additions & 0 deletions apps/time/src/shared/hooks/useDebounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect, useState } from 'react';

interface UseDebounceParams<T> {
value: T;
delay: number;
}

export default function useDebounce<T>({ value, delay }: UseDebounceParams<T>) {
const [debouncedValue, setDebouncedValue] = useState<T>(value);

useEffect(() => {
const delayDebounceTimer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(delayDebounceTimer);
}, [value, delay]);

return debouncedValue;
}
12 changes: 11 additions & 1 deletion apps/time/src/shared/utils/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@

import { PropsWithChildren } from 'react';

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

import { Provider } from 'jotai';

export default function Providers({ children }: PropsWithChildren) {
return <Provider>{children}</Provider>;
const queryClient = new QueryClient();

return (
<QueryClientProvider client={queryClient}>
<Provider>{children}</Provider>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
3 changes: 3 additions & 0 deletions apps/time/src/shared/utils/getAPIURL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function getAPIURL(endPoint: string) {
return new URL(`${process.env.NEXT_PUBLIC_API_URL}/api/${endPoint}`);
}
1 change: 1 addition & 0 deletions apps/time/src/shared/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as Providers } from './Providers';
export { default as getAPIURL } from './getAPIURL';
10 changes: 5 additions & 5 deletions apps/time/src/widgets/menu/ui/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const actions = [
</button>,
] as const;

const Nav = () => {
export default function Nav() {
return (
<nav className="fixed top-0 w-full border-b bg-white">
<div className="container flex h-14 items-center justify-between text-nowrap">
Expand All @@ -45,7 +45,9 @@ const Nav = () => {
height={200}
className="size-8"
/>
<h1 className="text-xl font-semibold">경기타임</h1>
<Link href="/">
<h1 className="select-none text-xl font-semibold">경기플러스</h1>
</Link>
</div>
<ul className="hidden w-3/5 items-center justify-center gap-4 text-sm sm:flex">
{links.map((link) => link)}
Expand All @@ -56,6 +58,4 @@ const Nav = () => {
</div>
</nav>
);
};

export default Nav;
}
6 changes: 6 additions & 0 deletions apps/time/src/widgets/time-table/api/endpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const TIMETABLE_ENDPOINT = {
lectureList: 'v1/lecture/retrieve',
majorList: 'v1/lecture/retrieve/major',
};

export default TIMETABLE_ENDPOINT;
74 changes: 74 additions & 0 deletions apps/time/src/widgets/time-table/api/getLectureList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { DayKor } from '@/shared/types';
import { getAPIURL } from '@/shared/utils';
import type {
DayCampus,
DayPeriod,
Grade,
LectureKey,
NightCampus,
NightPeriod,
} from '@/widgets/time-table';
import { TIMETABLE_ENDPOINT } from '@/widgets/time-table';

export interface GetLectureListParams {
campus: (DayCampus | NightCampus)[];
type: LectureKey[];
grade: Grade[];
day: DayKor[];
time: (DayPeriod | NightPeriod)[];
major: string[];
lectureName: string;
cursor: number;
limit: number;
}

export interface GetLectureListResponseValue {
id: number;
campus: string;
category: string;
code: string;
credit: number;
grade: number;
groupName: string;
isExceeded: true;
major: string;
name: string;
professor: string;
room: string;
year: number;
semester: string;
time: string;
type: LectureKey;
}

export interface GetLectureListResponse {
success: boolean;
data: {
values: GetLectureListResponseValue[];
};
hasPrevious: boolean;
hasNext: boolean;
}

export async function getLectureList({
...params
}: GetLectureListParams): Promise<GetLectureListResponse> {
const apiURL = getAPIURL(TIMETABLE_ENDPOINT.lectureList);

Object.entries(params).forEach(([key, value]) => {
if (value) {
apiURL.searchParams.set(
key,
Array.isArray(value) ? value.join(',') : String(value),
);
}
});

const res = await fetch(apiURL);

if (!res.ok) {
throw new Error('강의 정보 불러오기에 실패했습니다.');
}

return res.json();
}
27 changes: 27 additions & 0 deletions apps/time/src/widgets/time-table/api/getMajorList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getAPIURL } from '@/shared/utils';
import { TIMETABLE_ENDPOINT } from '@/widgets/time-table';

export interface GetMajorListParams {
major: string;
}

export interface GetMajorListResponse {
success: boolean;
data: string[];
}

export async function getMajorList({
major,
}: GetMajorListParams): Promise<GetMajorListResponse> {
const apiURL = getAPIURL(TIMETABLE_ENDPOINT.majorList);

apiURL.searchParams.set('major', major);

const res = await fetch(apiURL);

if (!res.ok) {
throw new Error('전공 리스트 불러오기에 실패했습니다.');
}

return res.json();
}
3 changes: 3 additions & 0 deletions apps/time/src/widgets/time-table/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as TIMETABLE_ENDPOINT } from './endpoint';
export * from './getLectureList';
export * from './getMajorList';
1 change: 1 addition & 0 deletions apps/time/src/widgets/time-table/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ui';
export * from './model';
export * from './types';
export * from './api';
24 changes: 5 additions & 19 deletions apps/time/src/widgets/time-table/model/constants/period.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const DAY_PERIOD = {
export const DAY_PERIOD = {
'1': {
start: { hour: 9, minute: 0 },
end: { hour: 9, minute: 50 },
Expand Down Expand Up @@ -91,7 +91,7 @@ const DAY_PERIOD = {
},
} as const;

const NIGHT_PERIOD = {
export const NIGHT_PERIOD = {
'1': {
start: { hour: 17, minute: 50 },
end: { hour: 18, minute: 35 },
Expand Down Expand Up @@ -124,7 +124,7 @@ const NIGHT_PERIOD = {
},
} as const;

const DAY_PERIOD_ARRAY = Object.entries(DAY_PERIOD).sort(
export const DAY_PERIOD_ARRAY = Object.entries(DAY_PERIOD).sort(
([, periodA], [, periodB]) => {
const timeA = periodA.start.hour * 60 + periodA.start.minute;
const timeB = periodB.start.hour * 60 + periodB.start.minute;
Expand All @@ -133,7 +133,7 @@ const DAY_PERIOD_ARRAY = Object.entries(DAY_PERIOD).sort(
},
);

const NIGHT_PERIOD_ARRAY = Object.entries(NIGHT_PERIOD).sort(
export const NIGHT_PERIOD_ARRAY = Object.entries(NIGHT_PERIOD).sort(
([, periodA], [, periodB]) => {
const timeA = periodA.start.hour * 60 + periodA.start.minute;
const timeB = periodB.start.hour * 60 + periodB.start.minute;
Expand All @@ -142,18 +142,4 @@ const NIGHT_PERIOD_ARRAY = Object.entries(NIGHT_PERIOD).sort(
},
);

const DAY_STATUS = {
day: '주간',
night: '야간',
} as const;

const SPECIAL_PERIOD = ['이러닝', '교외수업', '사회봉사'] as const;

export {
DAY_PERIOD,
NIGHT_PERIOD,
SPECIAL_PERIOD,
DAY_PERIOD_ARRAY,
NIGHT_PERIOD_ARRAY,
DAY_STATUS,
};
export const SPECIAL_PERIOD = ['이러닝', '교외수업', '사회봉사'] as const;
16 changes: 16 additions & 0 deletions apps/time/src/widgets/time-table/model/constants/region.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,20 @@ export const REGION = {
campus2: '서울',
} as const;

export const DAY_STATUS = {
day: '주간',
night: '야간',
} as const;

export const CAMPUS_STATUS = {
day: [
`${REGION.campus1}${DAY_STATUS.day}`,
`${REGION.campus2}${DAY_STATUS.day}`,
],
night: [
`${REGION.campus1}${DAY_STATUS.night}`,
`${REGION.campus2}${DAY_STATUS.night}`,
],
} as const;

export const REGION_VALUE_ARRAY = Object.values(REGION);
3 changes: 3 additions & 0 deletions apps/time/src/widgets/time-table/model/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { default as timeTableQueryKeys } from './timeTableQueryKeys';
export { default as useTimeTableParams } from './useTimeTableParams';
export { default as useMajorList } from './useMajorList';
export { default as useLectureList } from './useLectureList';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { GetLectureListParams, GetMajorListParams } from '@/widgets/time-table';

const timeTableQueryKeys = {
getLectureList: (params: GetLectureListParams) => ['getLectureList', params],
getMajorList: (params: GetMajorListParams) => ['getMajorList', params],
};

export default timeTableQueryKeys;
14 changes: 14 additions & 0 deletions apps/time/src/widgets/time-table/model/hooks/useLectureList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useSuspenseQuery } from '@tanstack/react-query';

import {
type GetLectureListParams,
getLectureList,
timeTableQueryKeys,
} from '@/widgets/time-table';

export default function useLectureList({ ...params }: GetLectureListParams) {
return useSuspenseQuery({
queryKey: timeTableQueryKeys.getLectureList(params),
queryFn: () => getLectureList(params),
});
}
17 changes: 17 additions & 0 deletions apps/time/src/widgets/time-table/model/hooks/useMajorList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';

import {
type GetMajorListParams,
getMajorList,
timeTableQueryKeys,
} from '@/widgets/time-table';

export default function useMajorList({ major }: GetMajorListParams) {
const { data } = useQuery({
queryKey: timeTableQueryKeys.getMajorList({ major }),
queryFn: () => getMajorList({ major }),
enabled: major.length > 0,
});

return data ? data.data : [];
}
5 changes: 0 additions & 5 deletions apps/time/src/widgets/time-table/types/day-status.ts

This file was deleted.

1 change: 0 additions & 1 deletion apps/time/src/widgets/time-table/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './day-status';
export * from './grade';
export * from './period';
export * from './lecture';
Expand Down
8 changes: 7 additions & 1 deletion apps/time/src/widgets/time-table/types/region.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { REGION } from '@/widgets/time-table';
import { CAMPUS_STATUS, DAY_STATUS, REGION } from '@/widgets/time-table';

export type Region = (typeof REGION)[keyof typeof REGION];

export type DayStatus = keyof typeof DAY_STATUS;

export type DayCampus = (typeof CAMPUS_STATUS.day)[number];

export type NightCampus = (typeof CAMPUS_STATUS.night)[number];
Loading
Loading