diff --git a/src/api/book-club/bookClubMainAPI.ts b/src/api/book-club/bookClubMainAPI.ts index e5dce58f..12ad39cc 100644 --- a/src/api/book-club/bookClubMainAPI.ts +++ b/src/api/book-club/bookClubMainAPI.ts @@ -1,5 +1,5 @@ import apiClient from '@/lib/utils/apiClient'; -import { BookClubParams } from '@/types/bookclubs'; +import { BookClubParams, MyProfileParams } from '@/types/bookclubs'; export const bookClubMainAPI = { //북클럽 삭제 @@ -10,18 +10,43 @@ export const bookClubMainAPI = { //북클럽 목록 조회 getBookClubs: async (params?: BookClubParams) => { - return await apiClient.get('/book-clubs', { params }); + const response = await apiClient.get('/book-clubs', { params }); + return response.data; }, //단일 북클럽 조회 + getBookClubDetail: async (bookClubId: number) => { + const response = await apiClient.get(`/book-clubs/${bookClubId}`); + return response.data; + }, //유저가 참가한 북클럽 조회 + userJoined: async (userId: number, params?: MyProfileParams) => { + const response = await apiClient.get(`/book-clubs/user/${userId}/joined`, { + params, + }); + return response.data; + }, //유저가 만든 북클럽 조회 + userCreated: async (userId: number, params?: MyProfileParams) => { + const response = await apiClient.get(`/book-clubs/user/${userId}/created`, { + params, + }); + return response.data; + }, //내가 참여한 북클럽 조회 + myJoined: async (params?: MyProfileParams) => { + const response = await apiClient.get('/book-clubs/my-joined', { params }); + return response.data; + }, //내가 만든 북클럽 조회 + myCreated: async (params?: MyProfileParams) => { + const response = await apiClient.get('/book-clubs/my-created', { params }); + return response.data; + }, //북클럽 생성 create: async (formData: FormData) => { diff --git a/src/api/book-club/bookClubReviewAPI.ts b/src/api/book-club/bookClubReviewAPI.ts index 1c73422c..eca1fffa 100644 --- a/src/api/book-club/bookClubReviewAPI.ts +++ b/src/api/book-club/bookClubReviewAPI.ts @@ -1,5 +1,6 @@ import apiClient from '@/lib/utils/apiClient'; import { WriteReviewParams, DetailClubReviewParams } from './types'; +import { MyProfileParams } from '@/types/bookclubs'; export const bookClubReviewAPI = { //리뷰 삭제하기 @@ -7,15 +8,40 @@ export const bookClubReviewAPI = { //단일 북클럽 리뷰 목록 조회 getReviews: async ({ bookClubId, - params, + params = { order: 'DESC' }, }: { bookClubId: number; params?: DetailClubReviewParams; }) => { - await apiClient.get(`book-clubs/${bookClubId}/reviews`, { params }); + return await apiClient.get(`book-clubs/${bookClubId}/reviews`, { + params, + }); + }, + + //특정 유저의 리뷰 조회 + userReviews: async ({ + userId, + params = { order: 'DESC' }, + }: { + userId: number; + params?: MyProfileParams; + }) => { + const response = await apiClient.get( + `/book-clubs/users/${userId}/reviews`, + { + params, + }, + ); + return response.data; }, //내가 작성한 리뷰 조회 + myReviews: async (params?: MyProfileParams) => { + const response = await apiClient.get('/book-clubs/my-reviews', { + params, + }); + return response.data; + }, //리뷰 작성하기 write: async ({ bookClubId, rating, content }: WriteReviewParams) => { diff --git a/src/api/book-club/react-query/customHooks.ts b/src/api/book-club/react-query/customHooks.ts index b9138e33..b3d66f67 100644 --- a/src/api/book-club/react-query/customHooks.ts +++ b/src/api/book-club/react-query/customHooks.ts @@ -17,14 +17,12 @@ export function useBookClubCreateMutation() { mutationFn: (formData: FormData) => bookClubMainAPI.create(formData), onSuccess: () => { queryClient.invalidateQueries({ - queryKey: bookClubs.all().queryKey, + queryKey: bookClubs.list().queryKey, }); queryClient.invalidateQueries({ - queryKey: bookClubs.myCreated().queryKey, - }); - queryClient.invalidateQueries({ - queryKey: bookClubs.myJoined().queryKey, + queryKey: bookClubs.my().queryKey, }); + showToast({ message: '북클럽이 성공적으로 생성되었습니다.', type: 'success', @@ -41,12 +39,9 @@ export function useJoinBookClub() { return useMutation, number>({ mutationFn: (id: number) => bookClubMemberAPI.join(id), - onSuccess: (_, id) => { - queryClient.invalidateQueries({ - queryKey: bookClubs.detail(id).queryKey, - }); + onSuccess: () => { queryClient.invalidateQueries({ - queryKey: bookClubs.myJoined().queryKey, + queryKey: bookClubs._def, }); }, }); @@ -57,12 +52,9 @@ export function useLeaveBookClub() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: number) => bookClubMemberAPI.leave(id), - onSuccess: (_, id) => { - queryClient.invalidateQueries({ - queryKey: bookClubs.detail(id).queryKey, - }); + onSuccess: () => { queryClient.invalidateQueries({ - queryKey: bookClubs.myJoined().queryKey, + queryKey: bookClubs._def, }); }, }); @@ -84,7 +76,7 @@ export function useWriteReview() { }); queryClient.invalidateQueries({ - queryKey: bookClubs.myReviews().queryKey, + queryKey: bookClubs.my()._ctx.reviews().queryKey, }); showToast({ message: '리뷰 작성을 완료하였습니다', type: 'success' }); }, @@ -103,10 +95,10 @@ export function useCancelBookClub() { mutationFn: (id: number) => bookClubMainAPI.cancel(id), onSuccess: () => { queryClient.invalidateQueries({ - queryKey: bookClubs.myCreated().queryKey, + queryKey: bookClubs.my()._ctx.created().queryKey, }); queryClient.invalidateQueries({ - queryKey: bookClubs.myJoined().queryKey, + queryKey: bookClubs.my()._ctx.joined().queryKey, }); }, }); @@ -119,7 +111,7 @@ export function useLikeBookClub() { mutationFn: (id: number) => bookClubLikeAPI.like(id), onSuccess: (_, id) => { queryClient.invalidateQueries({ - queryKey: bookClubs.all().queryKey, + queryKey: bookClubs.list().queryKey, }); queryClient.invalidateQueries({ queryKey: bookClubs.detail(id).queryKey, @@ -135,7 +127,7 @@ export function useUnLikeBookClub() { mutationFn: (id: number) => bookClubLikeAPI.unlike(id), onSuccess: (_, id) => { queryClient.invalidateQueries({ - queryKey: bookClubs.all().queryKey, + queryKey: bookClubs.list().queryKey, }); queryClient.invalidateQueries({ queryKey: bookClubs.detail(id).queryKey, diff --git a/src/api/book-club/react-query/queries.ts b/src/api/book-club/react-query/queries.ts index 5df00639..92f84752 100644 --- a/src/api/book-club/react-query/queries.ts +++ b/src/api/book-club/react-query/queries.ts @@ -1,116 +1,63 @@ import { createQueryKeys } from '@lukemorales/query-key-factory'; -import apiClient from '@/lib/utils/apiClient'; import { BookClubParams, MyProfileParams } from '@/types/bookclubs'; - import { ClubDetailReviewFilters } from '@/types/review'; -// TODO: 추후 각자 구현하는 api 명세에 맞게 filter 타입 정의해주세요 +import { bookClubReviewAPI } from '@/api/book-club/bookClubReviewAPI'; +import { bookClubMainAPI } from '@/api/book-club/bookClubMainAPI'; export const bookClubs = createQueryKeys('bookClubs', { - all: (filters?: BookClubParams) => ({ + list: (filters?: BookClubParams) => ({ queryKey: [{ filters: filters || {} }], - queryFn: (ctx) => - apiClient.get('/book-clubs', { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, - }), + queryFn: () => bookClubMainAPI.getBookClubs(filters), }), detail: (bookClubId: number) => ({ queryKey: [bookClubId], - queryFn: () => apiClient.get(`/book-clubs/${bookClubId}`), + queryFn: () => bookClubMainAPI.getBookClubDetail(bookClubId), contextQueries: { reviews: (filters?: ClubDetailReviewFilters) => ({ queryKey: [{ filters: filters || {} }], - queryFn: (ctx) => - apiClient.get(`/book-clubs/${bookClubId}/reviews`, { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, - }), + queryFn: () => + bookClubReviewAPI.getReviews({ bookClubId, params: filters }), }), }, }), - //유저가 참여한 북클럽 조회 - userJoined: (userId: number, filters?: MyProfileParams) => ({ - queryKey: [userId, { filter: filters || {} }], - queryFn: (ctx) => - apiClient.get(`/book-clubs/user/${userId}/joined`, { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + my: () => ({ + queryKey: [{}], + queryFn: () => ({}), + contextQueries: { + joined: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => bookClubMainAPI.myJoined(filters), }), - }), - - //유저가 만든 북클럽 조회 - userCreated: (userId: number, filters?: MyProfileParams) => ({ - queryKey: [userId, { filter: filters || {} }], - queryFn: (ctx) => - apiClient.get(`/book-clubs/user/${userId}/created`, { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + created: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => bookClubMainAPI.myCreated(filters), }), - }), - - //유저가 작성한 리뷰 조회 - userReviewd: (userId: number, filters?: MyProfileParams) => ({ - queryKey: [userId, { filter: filters || {} }], - queryFn: (ctx) => - apiClient.get(`/book-clubs/users/${userId}/reviews`, { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + reviews: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => bookClubReviewAPI.myReviews(filters), }), + }, }), - //내가 참여한 북클럽 조회 - myJoined: (filters?: MyProfileParams) => ({ - queryKey: [{ filters: filters || {} }], - queryFn: (ctx) => - apiClient.get('/book-clubs/my-joined', { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + user: (userId: number) => ({ + queryKey: [userId], + queryFn: () => ({}), + contextQueries: { + joined: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => bookClubMainAPI.userJoined(userId, filters), }), - }), - - //내가 만든 북클럽 조회 - myCreated: (filters?: MyProfileParams) => ({ - queryKey: [{ filters: filters || {} }], - queryFn: (ctx) => - apiClient.get('/book-clubs/my-created', { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + created: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => bookClubMainAPI.userCreated(userId, filters), }), - }), - - //내가 작성한 리뷰 조회 - myReviews: (filters?: MyProfileParams) => ({ - queryKey: [{ filters: filters || {} }], - queryFn: (ctx) => - apiClient.get('/book-clubs/my-reviews', { - params: { - ...filters, - page: ctx.pageParam ?? 1, - size: 10, - }, + reviews: (filters?: MyProfileParams) => ({ + queryKey: [{ filters: filters || {} }], + queryFn: () => + bookClubReviewAPI.userReviews({ userId, params: filters }), }), + }, }), }); diff --git a/src/api/book-club/types.ts b/src/api/book-club/types.ts index 7217edbd..7b89d277 100644 --- a/src/api/book-club/types.ts +++ b/src/api/book-club/types.ts @@ -1,5 +1,5 @@ export interface DetailClubReviewParams { - bookClubId: number; + // bookClubId: number; order?: 'DESC' | 'RATE_DESC' | 'RATE_ASC'; size?: number; page?: number; diff --git a/src/features/auth/api/auth.ts b/src/features/auth/api/auth.ts index c9577c6d..74799a40 100644 --- a/src/features/auth/api/auth.ts +++ b/src/features/auth/api/auth.ts @@ -1,3 +1,5 @@ +'use client'; + import apiClient from '@/lib/utils/apiClient'; import { LoginFormData } from '../types/loginFormSchema'; import { useAuthStore } from '@/store/authStore'; @@ -6,6 +8,7 @@ import { showToast } from '@/components/toast/toast'; import { getCookie } from '@/features/auth/utils/cookies'; import { SignUpFormData } from '../types/sign-up.schema'; import { User } from '@/types/user'; +import { queryClient } from '@/lib/utils/reactQueryProvider'; export const login = async (data: LoginFormData) => { try { @@ -16,6 +19,8 @@ export const login = async (data: LoginFormData) => { throw new Error(response.error); } + queryClient.clear(); + const { setIsLoggedIn } = useAuthStore.getState(); setIsLoggedIn(true); await getUserInfo(); diff --git a/src/features/bookclub/components/ClubListSection.tsx b/src/features/bookclub/components/ClubListSection.tsx index 9c7a6ee9..4ea72db9 100644 --- a/src/features/bookclub/components/ClubListSection.tsx +++ b/src/features/bookclub/components/ClubListSection.tsx @@ -25,7 +25,7 @@ function ClubListSection({ bookClubs = [] }: ClubListSectionProps) { }; return ( -
+
{bookClubs?.length > 0 ? ( bookClubs.map((club) => ( { }); const { data, isLoading, error } = useQuery({ - ...bookClubs.all(filters), + ...bookClubs.list(filters), }); - const clubInfo = data?.data.bookClubs; + const clubInfo = data?.bookClubs; // TODO: param 추가시, useEffect 대신 clubInfo 직접 사용 useEffect(() => { diff --git a/src/features/club-details/components/ReviewList.tsx b/src/features/club-details/components/ReviewList.tsx index 4daee8be..0e4cd347 100644 --- a/src/features/club-details/components/ReviewList.tsx +++ b/src/features/club-details/components/ReviewList.tsx @@ -12,11 +12,14 @@ function ReviewList({ setFilters, }: { reviewInfo: ClubReviewResponse; - setFilters: (newFilters: Partial) => void; + setFilters: React.Dispatch>; }) { const setSortingOrder = (selectedLabel: string | undefined) => { if (['DESC', 'RATE_DESC', 'RATE_ASC'].includes(selectedLabel || '')) { - setFilters({ order: selectedLabel as 'DESC' | 'RATE_DESC' | 'RATE_ASC' }); + setFilters((prev) => ({ + ...prev, + order: selectedLabel as 'DESC' | 'RATE_DESC' | 'RATE_ASC', + })); } }; diff --git a/src/features/club-details/hooks/useClubDetails.ts b/src/features/club-details/hooks/useClubDetails.ts index 2c21f798..72f37a46 100644 --- a/src/features/club-details/hooks/useClubDetails.ts +++ b/src/features/club-details/hooks/useClubDetails.ts @@ -2,11 +2,9 @@ import { bookClubs } from '@/api/book-club/react-query'; import { useQuery } from '@tanstack/react-query'; export function useClubDetails(idAsNumber: number) { - const { data, isLoading, error } = useQuery({ - ...bookClubs.detail(idAsNumber), - }); + const { data, isLoading, error } = useQuery(bookClubs.detail(idAsNumber)); - const clubInfo = data?.data; + const clubInfo = data; return { clubInfo, diff --git a/src/features/profile/container/CreatedClubList.tsx b/src/features/profile/container/CreatedClubList.tsx index e60ff98f..9ba14695 100644 --- a/src/features/profile/container/CreatedClubList.tsx +++ b/src/features/profile/container/CreatedClubList.tsx @@ -16,15 +16,11 @@ export default function CreatedClubList({ order }: ClubListProps) { const router = useRouter(); const user = useGetUserByPath(); - const { queryKey, queryFn } = bookClubs.userCreated(user?.id, { - order: order, - }); - const { data, isLoading, error } = useQuery({ - queryKey, - queryFn, - }); + const { data, isLoading, error } = useQuery( + bookClubs.user(user?.id)._ctx.created({ order, page: 1, size: 10 }), + ); - const CreatedList: BookClub[] = data?.data?.bookClubs || []; + const CreatedList: BookClub[] = data?.bookClubs ?? []; const today = new Date(); // 카드 클릭 이벤트 diff --git a/src/features/profile/container/JoinedClubList.tsx b/src/features/profile/container/JoinedClubList.tsx index 20efe589..6c14f7dd 100644 --- a/src/features/profile/container/JoinedClubList.tsx +++ b/src/features/profile/container/JoinedClubList.tsx @@ -18,15 +18,11 @@ export default function JoinedClubList({ order }: ClubListProps) { const router = useRouter(); const user = useGetUserByPath(); - const { queryKey, queryFn } = bookClubs.userJoined(user?.id, { - order: order, - }); - const { data, isLoading, isError, error } = useQuery({ - queryKey, - queryFn, - }); + const { data, isLoading, isError, error } = useQuery( + bookClubs.user(user?.id)._ctx.joined({ order, page: 1, size: 10 }), + ); - const JoinedList: BookClub[] = data?.data?.bookClubs || []; + const JoinedList: BookClub[] = data?.bookClubs ?? []; const today = new Date(); diff --git a/src/features/profile/container/MyCreatedClubList.tsx b/src/features/profile/container/MyCreatedClubList.tsx index a2db2374..a4091782 100644 --- a/src/features/profile/container/MyCreatedClubList.tsx +++ b/src/features/profile/container/MyCreatedClubList.tsx @@ -15,15 +15,14 @@ import Loading from '@/components/loading/Loading'; export default function MyCreatedClubList({ order }: ClubListProps) { const router = useRouter(); - - const { queryKey, queryFn } = bookClubs.myCreated({ - order: order, - }); - const { data, isLoading, error } = useQuery({ queryKey, queryFn }); const { popUpState, onCancel, onConfirmCancel, onClosePopUp } = useCancelClub(); - const myCreatedList: BookClub[] = data?.data?.bookClubs || []; + const { data, isLoading, error } = useQuery( + bookClubs.my()._ctx.created({ order, page: 1, size: 10 }), + ); + + const myCreatedList: BookClub[] = data?.bookClubs || []; const today = new Date(); diff --git a/src/features/profile/container/MyJoinedClubList.tsx b/src/features/profile/container/MyJoinedClubList.tsx index 842f4afa..ba64a463 100644 --- a/src/features/profile/container/MyJoinedClubList.tsx +++ b/src/features/profile/container/MyJoinedClubList.tsx @@ -29,13 +29,10 @@ export default function MyJoinedClubList({ order }: ClubListProps) { const today = new Date(); - const { queryKey, queryFn } = bookClubs.myJoined({ - order: order, - }); - const { data, isLoading, error } = useQuery({ - queryKey, - queryFn, - }); + const { data, isLoading, error } = useQuery( + bookClubs.my()._ctx.joined({ order, page: 1, size: 10 }), + ); + const { mutateAsync: leaveClub } = useLeaveBookClub(); const { mutate: writeReview } = useWriteReview(); @@ -50,7 +47,7 @@ export default function MyJoinedClubList({ order }: ClubListProps) { // if (!user) return null; - const myJoinedList: BookClub[] = data?.data?.bookClubs || []; + const myJoinedList: BookClub[] = data?.bookClubs || []; // 카드 클릭 이벤트 const onClick = (clubId: number) => { diff --git a/src/features/profile/container/MyWrittenReviewList.tsx b/src/features/profile/container/MyWrittenReviewList.tsx index de5bb005..b7faf989 100644 --- a/src/features/profile/container/MyWrittenReviewList.tsx +++ b/src/features/profile/container/MyWrittenReviewList.tsx @@ -9,13 +9,11 @@ import Loading from '@/components/loading/Loading'; import ProfileWrittenReview from '../components/clubs/ProfileWrittenReview'; export default function MyWrittenReviewList({ order }: ClubListProps) { - const { queryKey, queryFn } = bookClubs.myReviews({ order }); - const { data, isLoading, error } = useQuery({ - queryKey, - queryFn, - }); + const { data, isLoading, error } = useQuery( + bookClubs.my()._ctx.reviews({ order, page: 1, size: 10 }), + ); - const myReviewList: Review[] = data?.data?.reviews || []; + const myReviewList: Review[] = data?.reviews || []; return (
diff --git a/src/features/profile/container/WrittenReviewList.tsx b/src/features/profile/container/WrittenReviewList.tsx index 0fc157ac..94b80ca8 100644 --- a/src/features/profile/container/WrittenReviewList.tsx +++ b/src/features/profile/container/WrittenReviewList.tsx @@ -12,13 +12,11 @@ import Loading from '@/components/loading/Loading'; export default function WrittenReviewList({ order }: ClubListProps) { const user = useGetUserByPath(); - const { queryKey, queryFn } = bookClubs.userReviewd(user?.id, { order }); - const { data, isLoading, error } = useQuery({ - queryKey, - queryFn, - }); + const { data, isLoading, error } = useQuery( + bookClubs.user(user?.id)._ctx.reviews({ order, page: 1, size: 10 }), + ); - const ReviewList: Review[] = data?.data?.reviews || []; + const ReviewList: Review[] = data?.reviews || []; return (
diff --git a/src/lib/utils/filterUtils.ts b/src/lib/utils/filterUtils.ts index 6e459676..593eacba 100644 --- a/src/lib/utils/filterUtils.ts +++ b/src/lib/utils/filterUtils.ts @@ -8,7 +8,7 @@ export const getMemberLimit = (selectedValue: string | undefined) => { return { min: 6, max: 8 }; case 'NINE_ELEVEN': return { min: 9, max: 11 }; - case 'TWELVE': + case 'OVER_TWELVE': return { min: 12, max: 20 }; default: return { min: 3, max: 20 }; diff --git a/src/lib/utils/reactQueryProvider.tsx b/src/lib/utils/reactQueryProvider.tsx index 226b947e..28efda55 100644 --- a/src/lib/utils/reactQueryProvider.tsx +++ b/src/lib/utils/reactQueryProvider.tsx @@ -1,29 +1,26 @@ 'use client'; import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; -import { useState } from 'react'; + +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, // 윈도우가 다시 포커스될 때 데이터를 다시 가져올지 여부 + refetchOnMount: true, // 컴포넌트가 마운트될 때 데이터를 다시 가져올지 여부 + retry: 0, // 실패한 쿼리 재시도 횟수 + refetchOnReconnect: false, // 네트워크 재연결시 데이터를 다시 가져올지 여부 + retryOnMount: false, // 마운트 시 실패한 쿼리 재시도 여부 + staleTime: 1000 * 60 * 5, // 데이터가 'fresh'한 상태로 유지되는 시간 (5분) + gcTime: 1000 * 60 * 10, // 사용하지 않는 캐시 데이터가 메모리에서 제거되기까지의 시간 (10분) + }, + }, +}); export default function ReactQueryProviders({ children, }: React.PropsWithChildren) { - const [client] = useState( - new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, // 윈도우 다시 포커스되었을때 데이터 refetch X - refetchOnMount: false, // 컴포넌트 마운트될 때 데이터 refetch X - retry: 0, // API 요청 실패시 재시도 X - refetchOnReconnect: false, // 네트워크가 재연결될 때 데이터를 refetch X - retryOnMount: false, // 컴포넌트가 마운트될 때 실패한 쿼리를 재시도 X - staleTime: 1000 * 60 * 5, - gcTime: 1000 * 60 * 10, - }, - }, - }), - ); - return ( - + {children} diff --git a/src/middleware.ts b/src/middleware.ts index d311625c..b56b78fc 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -15,7 +15,7 @@ export async function middleware(request: NextRequest) { const data = await refreshAccessToken(refreshToken.value); const nextResponse = NextResponse.next(); nextResponse.cookies.set('auth_token', data.accessToken, { - maxAge: 60 * 15, + maxAge: 60 * 60, }); return nextResponse; } catch (error) { diff --git a/src/types/bookclubs.ts b/src/types/bookclubs.ts index 15fb3a96..353bd46c 100644 --- a/src/types/bookclubs.ts +++ b/src/types/bookclubs.ts @@ -14,6 +14,8 @@ export interface BookClubParams { export interface MyProfileParams { order?: orderType; + page?: number; + size?: number; } //TODO: imageUrl. isPast, clubStatus, reviewScore 수정