-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/156/review list #158
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/156/review list #158
Changes from all commits
f9bbb8e
37d9d12
1b2142a
1a1e0e3
53c7303
a0eed32
f130c0c
717d967
47625b5
780a561
6a25e38
8ba59e2
cb19454
6c368ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { fetchApi } from '@/src/utils/api'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ApiResponse, MyReviewResponse } from '@/src/types/review'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function getMyReviews(page: number, size: number): Promise<MyReviewResponse> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ์ต์ข ๋ฐํ ํ์ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = `/api/review/memberReviews?page=${page}&size=${size}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fetchApi<ApiResponse<MyReviewResponse>>(url, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'GET', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }).then((response) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return response.data; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ๋ฆฌ๋ทฐ ์ญ์ API | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function deleteReview(reviewId: number): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = `/api/review/${reviewId}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fetchApi<void>(url, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'DELETE', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ์ ๋ ฅ๊ฐ ๊ฒ์ฆ๊ณผ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ๋ฆฌ๋ทฐ ์ญ์ API์์ ๋ค์ ์ฌํญ๋ค์ด ๋ณด์๋๋ฉด ์ข๊ฒ ์ต๋๋ค:
๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ ๊ฒ์ ์ ์๋๋ฆฝ๋๋ค: export function deleteReview(reviewId: number): Promise<void> {
+ if (!Number.isInteger(reviewId) || reviewId <= 0) {
+ throw new Error('์ ํจํ์ง ์์ ๋ฆฌ๋ทฐ ID์
๋๋ค.');
+ }
const url = `/api/review/${reviewId}`;
return fetchApi<void>(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
- });
+ }).catch((error) => {
+ throw new Error(`๋ฆฌ๋ทฐ ์ญ์ ์คํจ: ${error.message}`);
+ });
}๐ Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,12 @@ | ||||||||||
| import { getMyReviews } from '@/src/_apis/review/my-review-apis'; | ||||||||||
| import { MyReviewResponse } from '@/src/types/review'; | ||||||||||
|
|
||||||||||
| export function useGetMyReviewsQuery({ size }: { size: number }) { | ||||||||||
| return { | ||||||||||
| queryKey: ['myReviews'], | ||||||||||
| queryFn: ({ pageParam = 0 }: { pageParam?: number }) => getMyReviews(pageParam, size), | ||||||||||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ์บ์ ํค ๊ตฌ์กฐ ๊ฒํ ํ์ ํ์ฌ ์บ์ ํค๊ฐ - queryKey: ['myReviews'],
+ queryKey: ['myReviews', size],๐ Committable suggestion
Suggested change
|
||||||||||
| getNextPageParam: (lastPage: MyReviewResponse, allPages: MyReviewResponse[]) => { | ||||||||||
| return lastPage.hasNext ? allPages.length : undefined; | ||||||||||
| }, | ||||||||||
| }; | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| import ProfileCardContainer from '@/src/app/(crew)/my-page/_components/profile-card/container'; | ||
| import ReviewTabs from './_components/review-tabs'; | ||
|
|
||
| export default function MyPage() { | ||
| export default function MyPage({ children }: { children: React.ReactNode }) { | ||
| return ( | ||
| <div className="container mx-auto my-0 min-h-screen max-w-pc bg-gray-50 px-3 py-11 md:px-8 lg:px-11"> | ||
| <div className="lg:gap-4.5 flex flex-col gap-3 md:gap-4"> | ||
| <ProfileCardContainer /> | ||
| </div> | ||
| <ReviewTabs /> | ||
| <div>{children}</div> | ||
| <div /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ๋ถํ์ํ ๋น div ์์๋ฅผ ์ ๊ฑฐํด์ฃผ์ธ์. ๋ง์ง๋ง ์ค์ ๋น div ์์๋ ์๋ฌด๋ฐ ์ญํ ์ ํ์ง ์์ผ๋ฏ๋ก ์ ๊ฑฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ฃผ์ธ์: <div>{children}</div>
- <div />
|
||
| </div> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,40 @@ | ||
| 'use client'; | ||
|
|
||
| import { toast } from 'react-toastify'; | ||
| import { Loader } from '@mantine/core'; | ||
| import { useGetMyReviewsQuery } from '@/src/_queries/review/my-review-queries'; | ||
| import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; | ||
| import ReviewCardList from '@/src/components/common/review-list/review-card-list'; | ||
|
|
||
| export default function MyReviewPage() { | ||
| return <div>my review list component</div>; | ||
| const size = 6; | ||
|
|
||
| const { data, isLoading, error, ref, isFetchingNextPage, refetch } = useInfiniteScroll( | ||
| useGetMyReviewsQuery({ size }), | ||
| ); | ||
|
|
||
| if (isLoading) { | ||
| return ( | ||
| <div className="flex h-full items-center justify-center"> | ||
| <Loader /> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| if (error) { | ||
| toast.error('๋ฆฌ๋ทฐ๋ฅผ ๋ถ๋ฌ์ค๋ ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.'); | ||
| return null; | ||
| } | ||
|
Comment on lines
+24
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ๊ฐ์ ํ ์ ์์ต๋๋ค. ํ์ฌ ๊ตฌํ๋ ์๋ฌ ์ฒ๋ฆฌ์ ๋ค์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค:
- if (error) {
- toast.error('๋ฆฌ๋ทฐ๋ฅผ ๋ถ๋ฌ์ค๋ ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.');
- return null;
- }
+ if (error) {
+ const errorMessage = error instanceof Error
+ ? error.message
+ : '๋ฆฌ๋ทฐ๋ฅผ ๋ถ๋ฌ์ค๋ ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.';
+
+ return (
+ <div className="flex flex-col items-center justify-center gap-4">
+ <p className="text-red-500">{errorMessage}</p>
+ <button
+ onClick={() => refetch()}
+ className="rounded bg-blue-500 px-4 py-2 text-white"
+ >
+ ๋ค์ ์๋
+ </button>
+ </div>
+ );
+ }
|
||
|
|
||
| return ( | ||
| <div className="mt-8"> | ||
| <ReviewCardList data={data ?? { pages: [], pageParams: [] }} refetch={refetch} /> | ||
| {isFetchingNextPage && ( | ||
| <div className="mt-4 flex items-center justify-center"> | ||
| <Loader /> | ||
| </div> | ||
| )} | ||
| <div ref={ref} className="h-[1px]" /> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,4 +4,5 @@ import { redirect } from 'next/navigation'; | |||||||||
|
|
||||||||||
| export default function MyPage() { | ||||||||||
| redirect('/my-page/reviewable'); | ||||||||||
| return null; | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ๋๋ฌํ ์ ์๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ์ธ์.
๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ธ์: export default function MyPage() {
redirect('/my-page/reviewable');
- return null;
}๐ Committable suggestion
Suggested change
|
||||||||||
| } | ||||||||||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,75 +1,23 @@ | ||
| import type { Meta, StoryObj } from '@storybook/react'; | ||
| import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; | ||
| import { fetchMyReviewData } from '@/src/app/api/mock-api/review'; | ||
| import { ReviewInformResponse } from '@/src/types/review'; | ||
| import ClientProvider from '../../client-provider'; | ||
| import { MyReviewData } from '@/src/mock/review-data'; | ||
| import ReviewCardList from './review-card-list'; | ||
|
|
||
| const meta: Meta<typeof ReviewCardList> = { | ||
| title: 'components/ReviewCardList', | ||
| component: ReviewCardList, | ||
| parameters: { | ||
| layout: 'centered', | ||
| layout: 'fullscreen', | ||
| nextjs: { | ||
| appDirectory: true, | ||
| }, | ||
| }, | ||
| tags: ['autodocs'], | ||
| decorators: [ | ||
| (Story) => ( | ||
| <ClientProvider> | ||
| <Story /> | ||
| </ClientProvider> | ||
| ), | ||
| ], | ||
| } satisfies Meta<typeof ReviewCardList>; | ||
| }; | ||
|
|
||
| export default meta; | ||
| type Story = StoryObj<typeof ReviewCardList>; | ||
|
|
||
| // function RenderCrewReviewCardList({ isMine = false, clickable = false }) { | ||
| // const { data, ref, isFetchingNextPage } = useInfiniteScroll<ReviewInformResponse>({ | ||
| // queryKey: ['review'], | ||
| // queryFn: ({ pageParam = 0 }) => fetchCrewReviewData(pageParam, 3), | ||
| // getNextPageParam: (lastPage, allPages) => | ||
| // lastPage.hasNextPage ? allPages.length + 1 : undefined, | ||
| // }); | ||
| // return ( | ||
| // <ReviewCardList | ||
| // data={data} | ||
| // ref={ref} | ||
| // isMine={isMine} | ||
| // clickable={clickable} | ||
| // isFetchingNextPage={isFetchingNextPage} | ||
| // /> | ||
| // ); | ||
| // } | ||
|
|
||
| function RenderMyReviewCardList({ isMine = true, clickable = false }) { | ||
| const { data, ref, isFetchingNextPage } = useInfiniteScroll<ReviewInformResponse>({ | ||
| queryKey: ['review'], | ||
| queryFn: ({ pageParam = 0 }) => fetchMyReviewData(pageParam, 3), | ||
| getNextPageParam: (lastPage, allPages) => | ||
| lastPage.hasNextPage ? allPages.length + 1 : undefined, | ||
| }); | ||
|
|
||
| return ( | ||
| <ReviewCardList | ||
| data={data} | ||
| ref={ref} | ||
| isMine={isMine} | ||
| clickable={clickable} | ||
| isFetchingNextPage={isFetchingNextPage} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| // export const CrewReviewCardList: Story = { | ||
| // render: () => <RenderCrewReviewCardList />, | ||
| // args: {}, | ||
| // }; | ||
| type Story = StoryObj<typeof ReviewCardList>; | ||
|
|
||
| export const MyReviewCardList: Story = { | ||
| render: () => <RenderMyReviewCardList clickable />, | ||
| args: {}, | ||
| render: () => <ReviewCardList data={MyReviewData} refetch={() => {}} />, | ||
| }; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,48 +1,47 @@ | ||||||||||||||||||||||||||||||||||||||
| import { forwardRef } from 'react'; | ||||||||||||||||||||||||||||||||||||||
| import { InfiniteData } from '@tanstack/react-query'; | ||||||||||||||||||||||||||||||||||||||
| import { ReviewInformResponse } from '@/src/types/review'; | ||||||||||||||||||||||||||||||||||||||
| import { MyReview } from '@/src/types/review'; | ||||||||||||||||||||||||||||||||||||||
| import ReviewCard from './review-card'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ReviewCardListProps ํ์ ์ ์ | ||||||||||||||||||||||||||||||||||||||
| interface ReviewCardListProps { | ||||||||||||||||||||||||||||||||||||||
| data: InfiniteData<ReviewInformResponse> | undefined; | ||||||||||||||||||||||||||||||||||||||
| isFetchingNextPage: boolean; | ||||||||||||||||||||||||||||||||||||||
| clickable?: boolean; | ||||||||||||||||||||||||||||||||||||||
| isMine?: boolean; | ||||||||||||||||||||||||||||||||||||||
| data: InfiniteData<{ | ||||||||||||||||||||||||||||||||||||||
| content: MyReview[]; | ||||||||||||||||||||||||||||||||||||||
| hasNext: boolean; | ||||||||||||||||||||||||||||||||||||||
| }>; | ||||||||||||||||||||||||||||||||||||||
| refetch: () => void; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function ReviewCardList( | ||||||||||||||||||||||||||||||||||||||
| { data, isFetchingNextPage, clickable = false, isMine = false }: ReviewCardListProps, | ||||||||||||||||||||||||||||||||||||||
| ref: React.Ref<HTMLDivElement>, | ||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||
| const reviewDataList = data?.pages.flatMap((page) => [...page.data]) ?? []; | ||||||||||||||||||||||||||||||||||||||
| export default function ReviewCardList({ data, refetch }: ReviewCardListProps) { | ||||||||||||||||||||||||||||||||||||||
| const reviewDataList = data.pages.flatMap((page) => page.content || []); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (!reviewDataList) return <p>Loading...</p>; | ||||||||||||||||||||||||||||||||||||||
| // ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒฝ์ฐ ์ฒ๋ฆฌ | ||||||||||||||||||||||||||||||||||||||
| if (!reviewDataList.length) { | ||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
| <div className="flex justify-center py-10"> | ||||||||||||||||||||||||||||||||||||||
| <p className="text-xl font-semibold">๋จ๊ธด ๋ฆฌ๋ทฐ๊ฐ ์์ต๋๋ค</p> | ||||||||||||||||||||||||||||||||||||||
| <p className="text-lg font-semibold">ํฌ๋ฃจ์ ๊ฐ์ ํ๊ณ ์ฝ์์ ์ก์๋ณด์ธ์!</p> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ๋น ์ํ UI์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ๊ทผ์ฑ ๊ฐ์ ์ด ํ์ํฉ๋๋ค ํ์ฌ ๊ตฌํ์ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๋ฌธ์ ๊ฐ ์์ง๋ง, ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ ์ฌํญ์ด ์์ต๋๋ค:
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํด๋ณด์ธ์: - <div className="flex justify-center py-10">
- <p className="text-xl font-semibold">๋จ๊ธด ๋ฆฌ๋ทฐ๊ฐ ์์ต๋๋ค</p>
- <p className="text-lg font-semibold">ํฌ๋ฃจ์ ๊ฐ์
ํ๊ณ ์ฝ์์ ์ก์๋ณด์ธ์!</p>
- </div>
+ <div className="flex flex-col items-center py-10" role="alert" aria-label="๋ฆฌ๋ทฐ ์์ ์๋ด">
+ <strong className="text-xl mb-2">๋จ๊ธด ๋ฆฌ๋ทฐ๊ฐ ์์ต๋๋ค</strong>
+ <span className="text-lg">ํฌ๋ฃจ์ ๊ฐ์
ํ๊ณ ์ฝ์์ ์ก์๋ณด์ธ์!</span>
+ </div>๐ Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||
| <ul className={`mx-auto flex h-full w-full flex-col ${isMine ? 'gap-8' : ''}`}> | ||||||||||||||||||||||||||||||||||||||
| {reviewDataList.map((review, index) => ( | ||||||||||||||||||||||||||||||||||||||
| <li key={`${review.rate - index}`} className="h-auto min-h-[112px]"> | ||||||||||||||||||||||||||||||||||||||
| <ReviewCard | ||||||||||||||||||||||||||||||||||||||
| crewId={review.crewId} | ||||||||||||||||||||||||||||||||||||||
| comment={review.comment} | ||||||||||||||||||||||||||||||||||||||
| createdAt={review.createdAt} | ||||||||||||||||||||||||||||||||||||||
| rate={review.rate} | ||||||||||||||||||||||||||||||||||||||
| isMine={isMine} | ||||||||||||||||||||||||||||||||||||||
| clickable={clickable} | ||||||||||||||||||||||||||||||||||||||
| crewName={'crewName' in review ? review.crewName : undefined} | ||||||||||||||||||||||||||||||||||||||
| gatheringName={'gatheringName' in review ? review.gatheringName : undefined} | ||||||||||||||||||||||||||||||||||||||
| reviewer={'reviewer' in review ? review.reviewer : undefined} | ||||||||||||||||||||||||||||||||||||||
| gatheringLocation={ | ||||||||||||||||||||||||||||||||||||||
| 'gatheringLocation' in review ? review.gatheringLocation : undefined | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| </li> | ||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||
| </ul> | ||||||||||||||||||||||||||||||||||||||
| {isFetchingNextPage ? <p>loading...</p> : <div ref={ref} className="h-[1px]" />} | ||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||
| <ul className="mx-auto flex h-full w-full flex-col gap-8"> | ||||||||||||||||||||||||||||||||||||||
| {reviewDataList.map((review) => ( | ||||||||||||||||||||||||||||||||||||||
| <li key={review.id} className="h-auto min-h-[112px]"> | ||||||||||||||||||||||||||||||||||||||
| <ReviewCard | ||||||||||||||||||||||||||||||||||||||
| crewId={review.crewId} | ||||||||||||||||||||||||||||||||||||||
| id={review.id} | ||||||||||||||||||||||||||||||||||||||
| comment={review.comment} | ||||||||||||||||||||||||||||||||||||||
| createdAt={review.createdAt} | ||||||||||||||||||||||||||||||||||||||
| rate={review.rate} | ||||||||||||||||||||||||||||||||||||||
| clickable | ||||||||||||||||||||||||||||||||||||||
| isMine | ||||||||||||||||||||||||||||||||||||||
| crewName={review.crewName} | ||||||||||||||||||||||||||||||||||||||
| gatheringName={review.gatheringName} | ||||||||||||||||||||||||||||||||||||||
| refetch={refetch} | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| </li> | ||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||
| </ul> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| export default forwardRef(ReviewCardList); | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ ๏ธ Refactor suggestion
์๋ฌ ์ฒ๋ฆฌ ๋ก์ง ์ถ๊ฐ๊ฐ ํ์ํฉ๋๋ค.
ํ์ฌ ๊ตฌํ์์๋ API ํธ์ถ ์คํจ ์์ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋์ด ์์ต๋๋ค. ์ฌ์ฉ์ ๊ฒฝํ ํฅ์์ ์ํด ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข๊ฒ ์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ ๊ฒ์ ์ ์๋๋ฆฝ๋๋ค:
export function getMyReviews(page: number, size: number): Promise<MyReviewResponse> { - // ์ต์ข ๋ฐํ ํ์ + // ํ์ด์ง๋ค์ด์ ๋ ์ฌ์ฉ์ ๋ฆฌ๋ทฐ ๋ชฉ๋ก์ ์กฐํํฉ๋๋ค. + // @param page ์กฐํํ ํ์ด์ง ๋ฒํธ (0๋ถํฐ ์์) + // @param size ํ์ด์ง๋น ํญ๋ชฉ ์ + // @throws Error API ํธ์ถ ์คํจ ์ const url = `/api/review/memberReviews?page=${page}&size=${size}`; return fetchApi<ApiResponse<MyReviewResponse>>(url, { method: 'GET', headers: { 'Content-Type': 'application/json', }, }).then((response) => { return response.data; + }).catch((error) => { + throw new Error(`๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ ์คํจ: ${error.message}`); }); }๐ Committable suggestion