Skip to content

Commit

Permalink
Merge pull request #30 from bomin0830/master
Browse files Browse the repository at this point in the history
Feat: 예약 내역 페이지 무한스크롤 구현
  • Loading branch information
bomin0830 authored Jul 15, 2024
2 parents 6f24b6b + edc9999 commit 9dd3898
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 48 deletions.
52 changes: 39 additions & 13 deletions hooks/useReservationList.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
import { useQuery } from '@tanstack/react-query';
import { useInfiniteQuery } from '@tanstack/react-query';
import { apiMyReservationList } from '@/pages/api/myReservations/apiMyReservations';
import { useUserData } from './useUserData';
import { MyReservationListResponse } from '@/pages/api/myReservations/apiMyReservations.types';
import { useMemo } from 'react';
import { statusType } from '@/components/ReservationFilter/myReservationTypes.types';

export const useReservationList = () => {
const INITIAL_SIZE = 4;
const REFETCH_SIZE = 1;

export const useReservationList = (filterOption: statusType | undefined) => {
const userData = useUserData();

const { data: myReservationList } = useQuery<MyReservationListResponse>({
queryKey: ['myReservationList', userData.id],
queryFn: () =>
apiMyReservationList({
cursorId: undefined,
size: undefined,
status: undefined,
}),
enabled: !!userData.id,
});
const { data, fetchNextPage, hasNextPage, isLoading, isFetchingNextPage } =
useInfiniteQuery<MyReservationListResponse>({
queryKey: ['myReservationList', userData.id, filterOption],
queryFn: ({ pageParam = undefined }) => {
const size = pageParam === undefined ? INITIAL_SIZE : REFETCH_SIZE;
return apiMyReservationList({
size: size,
cursorId: pageParam as number | undefined,
status: filterOption ?? undefined,
});
},
enabled: !!userData.id,
getNextPageParam: (lastPage) => {
return lastPage.totalCount === lastPage.reservations.length
? undefined
: lastPage.cursorId;
},
initialPageParam: undefined,
});

const myReservationList = useMemo(() => {
if (data) {
return data.pages.flatMap((page) => page.reservations);
}
}, [data]);

return myReservationList;
return {
myReservationList,
fetchNextPage,
hasNextPage,
isLoading,
isFetchingNextPage,
};
};
3 changes: 1 addition & 2 deletions hooks/useUserData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const useUserData = () => {
const [userData, setUserData] = useRecoilState(userState);
const { isLoggedIn } = useLoginState();

const { data: userResponseData, isError } = useQuery({
const { data: userResponseData } = useQuery({
queryKey: ['user', userId],
queryFn: apiMyInfo,
enabled: !!isLoggedIn,
Expand All @@ -23,7 +23,6 @@ export const useUserData = () => {
}, [userResponseData]);

useEffect(() => {
console.log('hi');
const userId = localStorage.getItem('userId') || '';
setUserId(userId);
}, []);
Expand Down
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
"react-calendar": "^5.0.0",
"react-dom": "^18",
"react-hook-form": "^7.52.1",
"recoil": "^0.7.7",
"tailwind-scrollbar-hide": "^1.1.7",
"react-intersection-observer": "^9.13.0",
"react-slick": "^0.30.2",
"slick-carousel": "^1.8.1"
"recoil": "^0.7.7",
"slick-carousel": "^1.8.1",
"tailwind-scrollbar-hide": "^1.1.7"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
66 changes: 36 additions & 30 deletions pages/reservation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,28 @@ import {
MyReservationProps,
statusType,
} from '@/components/ReservationFilter/myReservationTypes.types';
import { useInView } from 'react-intersection-observer';

export default function MyReservationPage() {
const [filterOption, setFilterOption] = useState<statusType>();
const [filterOption, setFilterOption] = useState<statusType | undefined>();
const [reservationListByFilter, setReservationListByFilter] = useState<
MyReservationProps[]
>([]);
const myReservationList = useReservationList();
const { ref, inView } = useInView();
const { fetchNextPage, myReservationList, hasNextPage } =
useReservationList(filterOption);

useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView]);

useEffect(() => {
if (myReservationList) {
const reservationList = myReservationList.reservations;
if (filterOption) {
const filteredData = reservationList.filter(
(card) => card.status === filterOption
);
setReservationListByFilter(filteredData);
} else {
setReservationListByFilter(reservationList);
}
setReservationListByFilter(myReservationList);
}
}, [myReservationList, filterOption]);
}, [myReservationList]);

return (
<div className="flex justify-center w-full mt-[72px] gap-[24px] t:mt-[24px] t:gap-[16px]">
Expand All @@ -43,33 +44,38 @@ export default function MyReservationPage() {
/>
)}
</div>
<div className="flex flex-col animate-slideDown overflow-auto scrollbar-hide h-[calc(100vh-380px)] gap-[24px] pr-[10px]">
{reservationListByFilter.length > 0 ? (
reservationListByFilter.map(
{reservationListByFilter.length > 0 ? (
<div className="flex flex-col animate-slideDown gap-[24px] overflow-auto scrollbar-hide h-[calc(100vh-220px)] pr-[10px]">
{reservationListByFilter.map(
(reservationData: MyReservationProps) => {
return (
<div key={reservationData.id}>
<ReservationListCard reservationData={reservationData} />
</div>
);
}
)
) : (
<div className="flex flex-col h-[500px] items-center justify-center">
<div>
<Image
src="/icon/empty_reservation.svg"
alt="등록된 체험이 없어요"
width={240}
height={240}
/>
)}
{hasNextPage && (
<div className="text-[35px] font-bold text-center" ref={ref}>
...
</div>
<span className="text-var-gray7 text-[24px]">
등록된 체험이 없어요
</span>
)}
</div>
) : (
<div className="flex flex-col h-[500px] items-center justify-center">
<div>
<Image
src="/icon/empty_reservation.svg"
alt="등록된 체험이 없어요"
width={240}
height={240}
/>
</div>
)}
</div>
<span className="text-var-gray7 text-[24px]">
등록된 체험이 없어요
</span>
</div>
)}
</div>
</div>
);
Expand Down

0 comments on commit 9dd3898

Please sign in to comment.