diff --git a/app/business/result/result.query.ts b/app/business/result/result.query.ts index 0763d40a..6ba5cba9 100644 --- a/app/business/result/result.query.ts +++ b/app/business/result/result.query.ts @@ -1,37 +1,30 @@ import { API_PATH } from '../api-path'; -import { cookies } from 'next/headers'; -import { httpErrorHandler } from '@/app/utils/http/http-error-handler'; import { CreditResponse, ResultCategoryDetailResponse } from './result.type'; +import axios from 'axios'; +import { getToken } from '../auth'; -export const fetchResultCategoryDetailInfo = async (category: string): Promise => { +export const fetchResultCategoryDetailInfo = async (category: string) => { //FIX : category를 querystring으로 호출하는 건은 mock단계에서는 불필요할 것으로 예상, 실제 api 연결시 변경 예정 try { - const response = await fetch(API_PATH.resultCategoryDetailInfo, { + const { data } = await axios(API_PATH.resultCategoryDetailInfo, { headers: { - Authorization: `Bearer ${cookies().get('accessToken')?.value}`, + Authorization: `Bearer ${getToken()}`, }, }); - const result = await response.json(); - httpErrorHandler(response, result); - - return result; + return data; } catch (error) { throw error; } }; -export const fetchCredits = async (): Promise => { +export const fetchCredits = async () => { try { - const response = await fetch(API_PATH.credits, { + const { data } = await axios(API_PATH.credits, { headers: { - Authorization: `Bearer ${cookies().get('accessToken')?.value}`, + Authorization: `Bearer ${getToken()}`, }, }); - const result = await response.json(); - - httpErrorHandler(response, result); - - return result; + return data; } catch (error) { throw error; } diff --git a/app/business/user/user.query.ts b/app/business/user/user.query.ts index 2512ed97..82364da8 100644 --- a/app/business/user/user.query.ts +++ b/app/business/user/user.query.ts @@ -1,9 +1,8 @@ -import { httpErrorHandler } from '@/app/utils/http/http-error-handler'; import { API_PATH } from '../api-path'; - -import { cookies } from 'next/headers'; -import { isValidation } from '@/app/utils/zod/validation.util'; import { InitUserInfoResponse, UserInfoResponse } from './user.type'; +import axios from 'axios'; +import { getToken } from '../auth'; +import { isValidation } from '@/app/utils/zod/validation.util'; import { UserInfoResponseSchema, InitUserInfoResponseSchema } from './user.validation'; import { UnauthorizedError } from '@/app/utils/http/http-error'; @@ -19,20 +18,16 @@ export async function auth(): Promise { +export async function fetchUserInfo() { try { - const response = await fetch(`${API_PATH.user}`, { + const { data } = await axios(API_PATH.user, { headers: { - Authorization: `Bearer ${cookies().get('accessToken')?.value}`, + Authorization: `Bearer ${await getToken()}`, }, }); - const result = await response.json(); - - httpErrorHandler(response, result); - - if (isValidation(result, UserInfoResponseSchema || InitUserInfoResponseSchema)) { - return result; + if (isValidation(data, UserInfoResponseSchema || InitUserInfoResponseSchema)) { + return data; } else { throw 'Invalid user info response schema.'; } diff --git a/app/hooks/useDialog.tsx b/app/hooks/useDialog.tsx index 5147f610..d46f2212 100644 --- a/app/hooks/useDialog.tsx +++ b/app/hooks/useDialog.tsx @@ -11,11 +11,6 @@ export default function useDialog(key: DialogKey, onClose?: () => void) { setOpenDialogList([key, true]); }; - const close = () => { - setOpenDialogList([key, false]); - onClose?.(); - }; - const toggle = () => { const prevState = isOpenDialogList[key]; setOpenDialogList([key, !prevState]); @@ -23,5 +18,5 @@ export default function useDialog(key: DialogKey, onClose?: () => void) { if (prevState) onClose?.(); }; - return { isOpen, open, close, toggle }; + return { isOpen, open, toggle }; } diff --git a/app/ui/result/result-category-card/result-category-card.tsx b/app/ui/result/result-category-card/result-category-card.tsx index 3cc2ea86..2142a23f 100644 --- a/app/ui/result/result-category-card/result-category-card.tsx +++ b/app/ui/result/result-category-card/result-category-card.tsx @@ -19,7 +19,6 @@ import Button from '../../view/atom/button/button'; import { getPercentage } from '@/app/utils/chart.util'; import PieChart from '../../view/molecule/pie-chart/pie-chart'; import Responsive from '../../responsive'; -import { useMediaQuery } from 'usehooks-ts'; interface ResultCategoryCardProps { category: ResultCategoryKey; diff --git a/app/ui/result/result-category-detail/result-category-detail.tsx b/app/ui/result/result-category-detail/result-category-detail.tsx index 48dca3ca..ea14db77 100644 --- a/app/ui/result/result-category-detail/result-category-detail.tsx +++ b/app/ui/result/result-category-detail/result-category-detail.tsx @@ -1,8 +1,12 @@ +'use client'; import ResultCategoryDetailContent from '@/app/ui/result/result-category-detail-content/result-category-detail-content'; import { fetchResultCategoryDetailInfo } from '@/app/business/result/result.query'; import ResultCategoryDetailContentSkeleton from '@/app/ui/result/result-category-detail-content/result-category-detail-content.skeleton'; import ResultCategoryDetailDialog from './result-category-detail-dialog'; import { Suspense } from 'react'; +import { QUERY_KEY } from '@/app/utils/query/react-query-key'; +import { ResultCategoryDetailResponse } from '@/app/business/result/result.type'; +import { useSuspenseQuery } from '@tanstack/react-query'; export default function ResultCategoryDetail({ category }: { category: string }) { return ( @@ -14,7 +18,12 @@ export default function ResultCategoryDetail({ category }: { category: string }) ); } -async function ResultCategoryDetailInfo({ category }: { category: string }) { - const data = await fetchResultCategoryDetailInfo(category); +function ResultCategoryDetailInfo({ category }: { category: string }) { + const { data } = useSuspenseQuery({ + queryKey: [QUERY_KEY.CATEGORY], + staleTime: Infinity, + queryFn: () => fetchResultCategoryDetailInfo(category), + }); + return ; } diff --git a/app/ui/result/result-category/result-category.skeleton.tsx b/app/ui/result/result-category/result-category.skeleton.tsx index 2d2a02ba..e5477e4e 100644 --- a/app/ui/result/result-category/result-category.skeleton.tsx +++ b/app/ui/result/result-category/result-category.skeleton.tsx @@ -6,7 +6,7 @@ async function ResultCategorySkeleton() {
- {Array.from({ length: 3 }).map((_, index) => ( + {Array.from({ length: 4 }).map((_, index) => ( ))}
diff --git a/app/ui/result/result-category/result-category.tsx b/app/ui/result/result-category/result-category.tsx index 6731ced5..198f4069 100644 --- a/app/ui/result/result-category/result-category.tsx +++ b/app/ui/result/result-category/result-category.tsx @@ -1,10 +1,18 @@ +'use client'; import { cn } from '@/app/utils/shadcn/utils'; import ResultCategoryCard from '../result-category-card/result-category-card'; import { fetchCredits } from '@/app/business/result/result.query'; import { RESULT_CATEGORY } from '@/app/utils/key/result-category.key'; +import { useSuspenseQuery } from '@tanstack/react-query'; +import { CreditResponse } from '@/app/business/result/result.type'; +import { QUERY_KEY } from '@/app/utils/query/react-query-key'; -async function ResultCategory() { - const categorys = await fetchCredits(); +function ResultCategory() { + const { data: categorys } = useSuspenseQuery({ + queryKey: [QUERY_KEY.CREDIT], + staleTime: Infinity, + queryFn: fetchCredits, + }); return (
: ; -} +function UserInfoCard() { + const { data } = useSuspenseQuery({ + queryKey: [QUERY_KEY.USER], + staleTime: Infinity, + queryFn: fetchUserInfo, + }); + + function isInitUser(x: UserInfoResponse | InitUserInfoResponse): x is InitUserInfoResponse { + return typeof x.studentName === null; + } + + function renderUserInfo(data: UserInfoResponse | InitUserInfoResponse) { + return isInitUser(data) ? : ; + } -async function UserInfoCard() { - const data = await fetchUserInfo(); return <>{renderUserInfo(data)}; } diff --git a/app/ui/user/user-info-card/user-info-content.tsx b/app/ui/user/user-info-card/user-info-content.tsx index f854e209..5cf7221b 100644 --- a/app/ui/user/user-info-card/user-info-content.tsx +++ b/app/ui/user/user-info-card/user-info-content.tsx @@ -11,6 +11,8 @@ interface UserInfoContentProps { function UserInfoContent({ data }: UserInfoContentProps) { const { studentNumber, studentName, completionDivision: majors, totalCredit, takenCredit, graduated } = data; + const percentage = getPercentage(takenCredit, totalCredit); + const displaySeveralMajor = (notation: 'major' | 'title'): React.ReactNode => { return majors.map((major, index) => { const { major: majorName, majorType } = major; @@ -44,7 +46,7 @@ function UserInfoContent({ data }: UserInfoContentProps) {
- +

diff --git a/app/ui/view/molecule/drawer/drawer.tsx b/app/ui/view/molecule/drawer/drawer.tsx index c2747552..07119108 100644 --- a/app/ui/view/molecule/drawer/drawer.tsx +++ b/app/ui/view/molecule/drawer/drawer.tsx @@ -13,13 +13,13 @@ interface DrawerProps extends React.PropsWithChildren { } const Drawer = ({ children, drawerKey, onClose, className }: DrawerProps) => { - const { isOpen, close } = useDialog(drawerKey, onClose); + const { isOpen, toggle } = useDialog(drawerKey, onClose); return ( - + diff --git a/app/utils/query/react-query-key.ts b/app/utils/query/react-query-key.ts index cbb47777..69f1d76a 100644 --- a/app/utils/query/react-query-key.ts +++ b/app/utils/query/react-query-key.ts @@ -1,3 +1,6 @@ export const QUERY_KEY = { SEARCH_LECTURE: 'search-lecture', + CREDIT: 'credit', + USER: 'user', + CATEGORY: 'category', } as const;