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: 전체 방 조회 API 연결 및 기능 구현 #164

Merged
merged 11 commits into from
Nov 18, 2023
50 changes: 41 additions & 9 deletions src/RoomSearch/components/ResultList.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
import { Room } from '@/RoomList/mocks/types/rooms';
import { RoomSelectType } from '@/core/types';
import { useInfiniteSearch } from '@/core/api/queries';
import useIntersectionObserver from '../hooks/useIntersectionObserver';
import ResultListFallback from './ResultListFallback';
import { RoomAccordion } from '@/RoomList';
import { Deffered } from '@/shared/Deffered';

interface ResultListProps {
rooms: Room[];
type: RoomSelectType;
size: number;
}

const ResultList = ({ rooms }: ResultListProps) => {
const ResultList = ({ type, size }: ResultListProps) => {
const { fetchNextPage, data, isFetchingNextPage, hasNextPage } =
useInfiniteSearch({
type,
size
});
const intersectionRef = useIntersectionObserver({
threshold: 0.5,
onObserve: fetchNextPage
});

return (
<div className="flex flex-col gap-2">
{rooms.map((room) => (
<RoomAccordion
room={room}
key={room.id}
/>
))}
{data.map((rooms) =>
rooms.map((room) => (
<RoomAccordion
room={room}
key={room.id}
/>
))
)}
{isFetchingNextPage && (
<Deffered>
<ResultListFallback size={size} />
</Deffered>
)}
{hasNextPage ? (
<div
ref={intersectionRef}
className="h-4"
></div>
) : (
<div className="my-4 text-center text-sm text-dark-gray">
모든 방을 다 불러왔어요.
</div>
)}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 추후에 hasNextPage 속성을 이용해서 방이 더 이상 없다는 문구도 표시해주면 더 좋을 것 같습니다 ㄷㄷ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그렇네유 ! 문구 추천 부탁드립니다 꾸벅 ( _ _ )
더 이상 방이 없네요! 이거 .. ?

);
};
Expand Down
20 changes: 20 additions & 0 deletions src/RoomSearch/components/ResultListFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

interface ResultListFallbackProps {
size?: number;
}

const ResultListFallback = ({ size = 10 }: ResultListFallbackProps) => {
return (
<div className="flex flex-col gap-2 opacity-60">
{Array.from({ length: size }, (_, index) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 size를 인수로 받아 개수를 자유롭게 설정할 수 있군요👍🏻👍🏻

<div
key={index}
className="my-1 h-24 w-full animate-pulse rounded-2xl bg-light-gray dark:bg-dark-gray"
></div>
))}
</div>
);
};

export default ResultListFallback;
41 changes: 41 additions & 0 deletions src/RoomSearch/hooks/useIntersectionObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useCallback, useEffect, useRef } from 'react';

interface ObserverOptions {
root?: Element | null;
rootMargin?: string;
threshold?: number;
onObserve: VoidFunction;
}

const useIntersectionObserver = ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오.. IntersectionObserver API를 쉽게 활용할 수 있게 hooks로 만들어주셨군요! 👍👍

onObserve,
...options
}: ObserverOptions) => {
const intersectionRef = useRef<HTMLDivElement>(null);

const handleIntersect: IntersectionObserverCallback = useCallback(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
onObserve();
}
});
},
[onObserve]
);

useEffect(() => {
const observer = new IntersectionObserver(handleIntersect, options);
const intersectionElement = intersectionRef.current;

intersectionElement && observer.observe(intersectionElement);

return () => {
intersectionElement && observer.unobserve(intersectionElement);
};
}, [handleIntersect, options]);

return intersectionRef;
};

export default useIntersectionObserver;
2 changes: 1 addition & 1 deletion src/core/api/functions/couponAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CouponStatus } from '@/core/types';
import { baseInstance } from '../instance';

const couponAPI = {
postAllCoupons: async (body: CouponStatus) => {
postCouponsByStatus: async (body: CouponStatus) => {
return await baseInstance.post<Coupons>('/coupons/search', body);
}
};
Expand Down
6 changes: 6 additions & 0 deletions src/core/api/functions/roomAPI.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { RoomsRequestParams, TotalRooms } from '@/core/types';
import { baseInstance } from '../instance';
import { MyJoinRoom } from '@/core/types/MyJoinRoom';
import { RoomInfo } from '@/core/types/Room';
Expand Down Expand Up @@ -49,6 +50,11 @@ const roomAPI = {
return await baseInstance.put(
`/rooms/${roomId}/members/${memberId}/delegation`
);
},

getRoomsAll: async (params?: RoomsRequestParams) => {
const response: TotalRooms = await baseInstance.get('/rooms', { params });
return response.rooms;
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/core/api/options/coupon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const couponOptions = {
all: (body: CouponStatus) =>
queryOptions({
queryKey: ['coupons', body] as const,
queryFn: () => couponAPI.postAllCoupons(body)
queryFn: () => couponAPI.postCouponsByStatus(body)
})
};

Expand Down
7 changes: 7 additions & 0 deletions src/core/api/options/room.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { queryOptions } from '@tanstack/react-query';
import { RoomsRequestParams } from '@/core/types';
import roomAPI from '../functions/roomAPI';

const roomOptions = {
Expand All @@ -12,6 +13,12 @@ const roomOptions = {
queryOptions({
queryKey: ['rooms', 'myJoin'] as const,
queryFn: () => roomAPI.getMyJoinRoom()
}),

all: (params?: RoomsRequestParams) =>
queryOptions({
queryKey: ['rooms', params?.type || 'all'] as const,
queryFn: () => roomAPI.getRoomsAll(params)
})
};

Expand Down
1 change: 1 addition & 0 deletions src/core/api/queries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useInfiniteSearch } from './useInfiniteSearch';
27 changes: 27 additions & 0 deletions src/core/api/queries/useInfiniteSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
import { RoomSelectType } from '@/core/types';
import roomAPI from '../functions/roomAPI';

const useInfiniteSearch = ({
type,
size
}: {
type: RoomSelectType;
size: number;
}) => {
return useSuspenseInfiniteQuery({
queryKey: ['rooms', type],

queryFn: ({ pageParam }) =>
roomAPI.getRoomsAll({ page: pageParam, type, size }),

initialPageParam: 1,

getNextPageParam: (lastPage, allPages, lastPageParam) =>
lastPage.length < size ? null : lastPageParam + 1,

select: ({ pages }) => pages
});
};

export default useInfiniteSearch;
Loading