diff --git a/src/components/Lecture/IsTestInfo.tsx b/src/components/Lecture/IsTestInfo.tsx index 241ab7f..c09d527 100644 --- a/src/components/Lecture/IsTestInfo.tsx +++ b/src/components/Lecture/IsTestInfo.tsx @@ -3,17 +3,16 @@ import { User } from 'api'; import { Button, SearchTestInfoList, Spinner } from 'components'; import { fakeEvaluationList } from 'constants/placeholderData'; import useLectureQuery from 'hooks/useLectureQuery'; +import { useSearchParams } from 'react-router-dom'; import { isLoginStorage } from 'utils/loginStorage'; -interface IsTestInfoProps { - selectId: string; - setWritten: React.Dispatch>; -} - -const IsTestInfo = ({ selectId, setWritten }: IsTestInfoProps) => { +const IsTestInfo = () => { const { testInfo } = useLectureQuery(); const isLogin = isLoginStorage(); - const { data, isLoading, isFetchingNextPage, ref } = testInfo(selectId, setWritten); + const { data, isLoading, isFetchingNextPage, ref } = testInfo; + + const [searchParams] = useSearchParams(); + const selectId = searchParams.get('id') || ''; if (!isLogin) { return ; diff --git a/src/components/Lecture/LectureDetail.tsx b/src/components/Lecture/LectureDetail.tsx index aa73ab0..f859ec4 100644 --- a/src/components/Lecture/LectureDetail.tsx +++ b/src/components/Lecture/LectureDetail.tsx @@ -4,9 +4,9 @@ import useLectureQuery from 'hooks/useLectureQuery'; const LectureDetail = () => { const { detail } = useLectureQuery(); - const { data, isLogin } = detail(); + const { data } = detail; - return ; + return ; }; export default LectureDetail; diff --git a/src/components/Lecture/LectureInfoBox.tsx b/src/components/Lecture/LectureInfoBox.tsx index 5cc48db..7198aa7 100644 --- a/src/components/Lecture/LectureInfoBox.tsx +++ b/src/components/Lecture/LectureInfoBox.tsx @@ -4,18 +4,20 @@ import { useNavigate } from 'react-router-dom'; import type { SetNumber, SetTeamNumber } from 'types/common'; import type { LectureDetailItem } from 'types/lecture'; import { floatFix } from 'utils/floatFix'; +import { isLoginStorage } from 'utils/loginStorage'; interface LectureInfoBoxProps { current: LectureDetailItem; - isLogin?: boolean; } -const LectureInfoBox = ({ current, isLogin = false }: LectureInfoBoxProps) => { +const LectureInfoBox = ({ current }: LectureInfoBoxProps) => { const navigate = useNavigate(); const teamSet = Math.floor(current.lectureTeamAvg ?? 0) as SetTeamNumber; const homeworkSet = Math.floor(current.lectureHomeworkAvg ?? 0) as SetNumber; const difficultySet = Math.floor(current.lectureDifficultyAvg ?? 0) as SetNumber; + const isLogin = isLoginStorage(); + return (
diff --git a/src/components/List/LectureList.tsx b/src/components/List/LectureList.tsx index 28d7d27..63430d3 100644 --- a/src/components/List/LectureList.tsx +++ b/src/components/List/LectureList.tsx @@ -20,7 +20,7 @@ interface LectureListProps { const LectureList = ({ count, pages }: LectureListProps) => { const { search } = useLectureQuery(); - const { nextLoading, value, ref } = search(); + const { nextLoading, value, ref } = search; return count ? ( <> diff --git a/src/components/List/MainList.tsx b/src/components/List/MainList.tsx index 35291bf..a2d8b7e 100644 --- a/src/components/List/MainList.tsx +++ b/src/components/List/MainList.tsx @@ -7,7 +7,7 @@ const MainList = () => { return ( ); }; diff --git a/src/components/List/SearchEvaluationList.tsx b/src/components/List/SearchEvaluationList.tsx index f34f59c..987f350 100644 --- a/src/components/List/SearchEvaluationList.tsx +++ b/src/components/List/SearchEvaluationList.tsx @@ -7,6 +7,7 @@ import { Fragment, useState } from 'react'; import StarRatings from 'react-star-ratings'; import type { Review } from 'types/evaluate'; import { floatFix } from 'utils/floatFix'; +import { isLoginStorage } from 'utils/loginStorage'; export const FakeList = () => { return ( @@ -20,15 +21,10 @@ export const FakeList = () => { ); }; -interface SearchEvaluationListProps { - selectId: string; - setWritten: React.Dispatch>; - isLogin: boolean; -} - -const SearchEvaluationList = ({ selectId, setWritten, isLogin }: SearchEvaluationListProps) => { +const SearchEvaluationList = () => { const { evaluation } = useLectureQuery(); - const { data, isLoading, isFetchingNextPage, ref } = evaluation(selectId, setWritten); + const { data, isLoading, isFetchingNextPage, ref } = evaluation; + const isLogin = isLoginStorage(); if (isLoading) return ; diff --git a/src/hooks/useLectureQuery.ts b/src/hooks/useLectureQuery.ts index e064780..62d2ae0 100644 --- a/src/hooks/useLectureQuery.ts +++ b/src/hooks/useLectureQuery.ts @@ -1,6 +1,7 @@ import { Lecture } from 'api'; import { lectureState } from 'app/recoilStore'; import { CACHE_TIME } from 'constants/cacheTime'; +import type { Category } from 'pages/LectureInfo'; import { useEffect } from 'react'; import { useInView } from 'react-intersection-observer'; import { useInfiniteQuery, useQuery } from 'react-query'; @@ -8,7 +9,6 @@ import { useSearchParams } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; import { isLoginStorage } from 'utils/loginStorage'; -// 애러가 날 수 있는 hook const useLectureQuery = () => { const [searchParams] = useSearchParams(); const setLectureInfo = useSetRecoilState(lectureState); @@ -19,136 +19,119 @@ const useLectureQuery = () => { const majorType = searchParams.get('majorType') || '전체'; const major = majorType === '전체' ? '' : majorType; const value = searchValue === 'all' ? '' : searchValue; - + const selectCategory = (searchParams.get('category') as Category) || '강의평가'; const isLogin = isLoginStorage(); - // 메인 쿼리(key: 정렬,전공) - const { data: getMainLecture } = useQuery( - ['main', option, major], - () => lecture.main(option, 1, major), - { keepPreviousData: true, suspense: true }, + const getMainLecture = useQuery(['main', option, major], () => lecture.main(option, 1, major), { + keepPreviousData: true, + suspense: true, + }); + + const { ref: searchRef, inView: searchInView } = useInView(); + const search = useInfiniteQuery( + ['search', value, option, major], + ({ pageParam = 1 }) => lecture.search(value, pageParam, option, major), + { + getNextPageParam: (lastPage) => + lastPage && !lastPage.isLast ? lastPage.nextPage : undefined, + keepPreviousData: true, + }, ); - // 검색 쿼리(key: 검색어,정렬,전공) - const search = () => { - const { ref, inView } = useInView(); - const { - data, - isLoading: searchLoading, - fetchNextPage: getNextSearch, - isFetchingNextPage: nextLoading, - } = useInfiniteQuery( - ['search', value, option, major], - ({ pageParam = 1 }) => lecture.search(value, pageParam, option, major), - { - getNextPageParam: (lastPage) => { - if (lastPage && !lastPage.isLast) return lastPage.nextPage; - - return undefined; - }, - keepPreviousData: true, - }, - ); - useEffect(() => { - if (inView) { - getNextSearch(); - } - }, [inView, getNextSearch]); - - return { data, searchLoading, nextLoading, value, ref }; - }; - - // 강의 상세 쿼리(key: 강의id) - const detail = () => { - const { data, isLoading } = useQuery( - ['lecture', 'detail', selectId], - () => lecture.detail(selectId), - { - cacheTime: CACHE_TIME.MINUTE_0, - staleTime: CACHE_TIME.MINUTE_0, - enabled: isLogin, - onSuccess: (lecture) => { - setLectureInfo({ - id: Number(selectId), - lectureName: lecture!.data.lectureName, - professor: lecture!.data.professor, - semesterList: lecture!.data.semesterList, - selectedSemester: '선택', - satisfaction: 0.5, - honey: 0.5, - learning: 0.5, - team: 0, - homework: 0, - difficulty: 0, - examInfo: '', - examType: '선택', - examDifficulty: '', - content: '', - majorType: '', - totalAvg: 0, - }); - }, - }, - ); - - return { data, isLoading, isLogin: isLogin }; - }; - - // 강의평가 쿼리(key: 강의id) - const evaluation = (id: string, setWritten: React.Dispatch>) => { - const { ref, inView } = useInView(); - const { data, isFetchingNextPage, isLoading, fetchNextPage } = useInfiniteQuery( - ['lecture', 'evaluationList', id], - ({ pageParam = 1 }) => lecture.evaluation(id, pageParam), - { - getNextPageParam: (lastPage) => { - if (lastPage && !lastPage.isLast) return lastPage.nextPage; - - return undefined; - }, - onSuccess: (data) => setWritten(!!data.pages[0]?.written), - cacheTime: CACHE_TIME.MINUTE_0, - staleTime: CACHE_TIME.MINUTE_0, - enabled: isLogin, - }, - ); - useEffect(() => { - if (inView && isLogin) { - fetchNextPage(); - } - }, [inView, fetchNextPage]); - - return { data, isFetchingNextPage, isLoading, ref }; - }; - - // 시험정보 쿼리(key: 강의id) - const testInfo = (id: string, setWritten: React.Dispatch>) => { - const { ref, inView } = useInView(); - const { data, isFetchingNextPage, isLoading, fetchNextPage } = useInfiniteQuery( - ['lecture', 'examList', id], - ({ pageParam = 1 }) => lecture.examInfo(id, pageParam), - { - getNextPageParam: (lastPage) => { - if (lastPage && !lastPage.isLast) return lastPage.nextPage; + const detail = useQuery(['lecture', 'detail', selectId], () => lecture.detail(selectId), { + cacheTime: CACHE_TIME.MINUTE_0, + staleTime: CACHE_TIME.MINUTE_0, + enabled: isLogin && selectId !== '', + onSuccess: (lecture) => { + setLectureInfo({ + id: Number(selectId), + lectureName: lecture!.data.lectureName, + professor: lecture!.data.professor, + semesterList: lecture!.data.semesterList, + selectedSemester: '선택', + satisfaction: 0.5, + honey: 0.5, + learning: 0.5, + team: 0, + homework: 0, + difficulty: 0, + examInfo: '', + examType: '선택', + examDifficulty: '', + content: '', + majorType: '', + totalAvg: 0, + }); + }, + }); + + const { ref: evaluationRef, inView: evaluationInView } = useInView(); + const evaluation = useInfiniteQuery( + ['lecture', 'evaluationList', selectId], + ({ pageParam = 1 }) => lecture.evaluation(selectId, pageParam), + { + getNextPageParam: (lastPage) => + lastPage && !lastPage.isLast ? lastPage.nextPage : undefined, + cacheTime: CACHE_TIME.MINUTE_0, + staleTime: CACHE_TIME.MINUTE_0, + enabled: isLogin && selectId !== '' && selectCategory === '강의평가', + }, + ); - return undefined; - }, - onSuccess: (data) => setWritten(!!data.pages[0]?.data.written), - cacheTime: CACHE_TIME.MINUTE_0, - staleTime: CACHE_TIME.MINUTE_0, - enabled: isLogin, - }, - ); - useEffect(() => { - if (inView && isLogin) { - fetchNextPage(); - } - }, [inView, fetchNextPage]); + const { ref: testInfoRef, inView: testInfoInView } = useInView(); + const testInfo = useInfiniteQuery( + ['lecture', 'examList', selectId], + ({ pageParam = 1 }) => lecture.examInfo(selectId, pageParam), + { + getNextPageParam: (lastPage) => + lastPage && !lastPage.isLast ? lastPage.nextPage : undefined, + cacheTime: CACHE_TIME.MINUTE_0, + staleTime: CACHE_TIME.MINUTE_0, + enabled: isLogin && selectId !== '' && selectCategory === '시험정보', + }, + ); - return { data, isFetchingNextPage, isLoading, ref }; + useEffect(() => { + if (searchInView) { + search.fetchNextPage(); + } + }, [searchInView, search.fetchNextPage, search]); + + useEffect(() => { + if (evaluationInView && isLogin) { + evaluation.fetchNextPage(); + } + }, [evaluationInView, evaluation.fetchNextPage, isLogin, evaluation]); + + useEffect(() => { + if (testInfoInView && isLogin) { + testInfo.fetchNextPage(); + } + }, [testInfoInView, testInfo.fetchNextPage, isLogin, testInfo]); + + return { + getMainLecture, + search: { + data: search.data, + searchLoading: search.isLoading, + nextLoading: search.isFetchingNextPage, + value, + ref: searchRef, + }, + detail, + evaluation: { + data: evaluation.data, + isFetchingNextPage: evaluation.isFetchingNextPage, + isLoading: evaluation.isLoading, + ref: evaluationRef, + }, + testInfo: { + data: testInfo.data, + isFetchingNextPage: testInfo.isFetchingNextPage, + isLoading: testInfo.isLoading, + ref: testInfoRef, + }, }; - - return { getMainLecture, search, detail, evaluation, testInfo }; }; export default useLectureQuery; diff --git a/src/pages/LectureInfo.tsx b/src/pages/LectureInfo.tsx index e8c875b..1309604 100644 --- a/src/pages/LectureInfo.tsx +++ b/src/pages/LectureInfo.tsx @@ -9,6 +9,7 @@ import { WriteEvaluation, WriteTestInfo, } from 'components'; +import useLectureQuery from 'hooks/useLectureQuery'; import { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; @@ -16,21 +17,22 @@ import { AppContainer } from 'styles/common'; import { isLoginStorage } from 'utils/loginStorage'; const CATEGORY = ['강의평가', '시험정보'] as const; -type Category = (typeof CATEGORY)[number]; +export type Category = (typeof CATEGORY)[number]; const LectureInfo = () => { - const [written, setWritten] = useState(false); const [modalIsOpen, setModalIsOpen] = useState(false); const lectureInfo = useRecoilValue(lectureState); - const [searchparams, setSearchParams] = useSearchParams(); - const selectId = searchparams.get('id') || ''; - const selectCategory = (searchparams.get('category') as Category) || '강의평가'; + const [searchParams, setSearchParams] = useSearchParams(); + const selectCategory = (searchParams.get('category') as Category) || '강의평가'; const isLogin = isLoginStorage(); + const { evaluation, testInfo } = useLectureQuery(); const handleCategory = (newCategory: Category) => { setSearchParams({ category: newCategory }); }; + const isWritten = !!evaluation.data?.pages[0]?.written || !!testInfo.data?.pages[0]?.written; + return ( @@ -59,17 +61,13 @@ const LectureInfo = () => { onClick={() => !isLogin ? alert('로그인해 주세요') - : !written + : !isWritten ? setModalIsOpen(true) : alert(`이미 작성한 ${selectCategory}가 있습니다`) } /> - {selectCategory === '강의평가' ? ( - - ) : ( - - )} + {selectCategory === '강의평가' ? : } diff --git a/src/pages/Search.tsx b/src/pages/Search.tsx index 304dc4a..f463367 100644 --- a/src/pages/Search.tsx +++ b/src/pages/Search.tsx @@ -5,7 +5,7 @@ import useLectureQuery from 'hooks/useLectureQuery'; const Search = () => { const { search } = useLectureQuery(); - const { data } = search(); + const { data } = search; const count = data?.pages[0]?.data.count ?? 0;