Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
f9bbb8e
๐Ÿš‘ fix: npm i changed
HaeJungg Nov 21, 2024
37d9d12
๐Ÿš‘ fix: ํŽ˜์ด์ง€ ๋žœ๋”๋ง ์•ˆ๋˜๋Š” ๋ฌธ์ œ ์ˆ˜์ •
HaeJungg Nov 21, 2024
1b2142a
๐Ÿš‘ fix: ๋งฅ ์Šคํ† ๋ฆฌ๋ถ์œ„ํ•ด esbuild์„ค์น˜
HaeJungg Nov 21, 2024
1a1e0e3
๐Ÿ’„ design: fontweignt์‚ญ์ œ
HaeJungg Nov 21, 2024
53c7303
๐Ÿ› fix: ํฌ๋ฉง ๋ฐ์ดํ„ฐ ๋””์ž์ธ์— ๋งž๊ฒŒ ์ˆ˜์ •
HaeJungg Nov 21, 2024
a0eed32
๐Ÿ› fix: ํƒ€์ž… ์ˆ˜์ •
HaeJungg Nov 21, 2024
f130c0c
๐Ÿ› fix: ์Šคํ† ๋ฆฌ๋ถ ๋ชฉ๋ฐ์ดํ„ฐ ์ˆ˜์ •
HaeJungg Nov 21, 2024
717d967
๐Ÿ’„ design: ๋””์ž์ธ์— ๋งž๊ฒŒ ๋‚ ์งœ ์ˆ˜์ •
HaeJungg Nov 21, 2024
47625b5
โœจ feat: ๋‚˜์˜๋ฆฌ๋ทฐ, ๋ฆฌ๋ทฐ ์‚ญ์ œํ•˜๊ธฐ ์ถ”๊ฐ€
HaeJungg Nov 21, 2024
780a561
๐Ÿ› fix: ํ† ์ŠคํŠธ๋กœ ๋ณ€๊ฒฝ
HaeJungg Nov 21, 2024
6a25e38
โœจ feat: ๋‚˜์˜ ๋ฆฌ๋ทฐ ๋ฆฌ์ŠคํŠธ ๋ฌดํ•œ์Šคํฌ๋กค ๊ตฌํ˜„, ๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐ
HaeJungg Nov 21, 2024
8ba59e2
๐Ÿ“ docs: ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ ์‚ญ์ œ, ์ฃผ์„์ฒ˜๋ฆฌ
HaeJungg Nov 21, 2024
cb19454
๐Ÿš‘ fix: ์ค‘๋ณต ์ฝ”๋“œ ์‚ญ์ œ, ์ด๋™๊ฒฝ๋กœ ์ˆ˜์ •
HaeJungg Nov 21, 2024
6c368ca
๐Ÿ’„ design: ๋งˆ์ง„ ์ถ”๊ฐ€
HaeJungg Nov 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
465 changes: 465 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions src/_apis/review/my-review-apis.ts
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;
});
}
Comment on lines +4 to +15
Copy link

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

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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;
});
}
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}`);
});
}


// ๋ฆฌ๋ทฐ ์‚ญ์ œ 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
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ๊ณผ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ๋ทฐ ์‚ญ์ œ API์—์„œ ๋‹ค์Œ ์‚ฌํ•ญ๋“ค์ด ๋ณด์™„๋˜๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค:

  1. reviewId์˜ ์œ ํšจ์„ฑ ๊ฒ€์ฆ
  2. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋กœ์ง ์ถ”๊ฐ€

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์ œ์•ˆ๋“œ๋ฆฝ๋‹ˆ๋‹ค:

 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

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// ๋ฆฌ๋ทฐ ์‚ญ์ œ API
export function deleteReview(reviewId: number): Promise<void> {
const url = `/api/review/${reviewId}`;
return fetchApi<void>(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
});
}
// ๋ฆฌ๋ทฐ ์‚ญ์ œ 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}`);
});
}

12 changes: 12 additions & 0 deletions src/_queries/review/my-review-queries.ts
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
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

์บ์‹œ ํ‚ค ๊ตฌ์กฐ ๊ฒ€ํ†  ํ•„์š”

ํ˜„์žฌ ์บ์‹œ ํ‚ค๊ฐ€ ['myReviews']๋กœ๋งŒ ๋˜์–ด์žˆ๋Š”๋ฐ, size ํŒŒ๋ผ๋ฏธํ„ฐ๋„ ์บ์‹œ ํ‚ค์— ํฌํ•จํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ํฌ๊ธฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์บ์‹œ๋ฅผ ์ ์ ˆํžˆ ๋ฌดํšจํ™”ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.

-    queryKey: ['myReviews'],
+    queryKey: ['myReviews', size],
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
queryKey: ['myReviews'],
queryFn: ({ pageParam = 0 }: { pageParam?: number }) => getMyReviews(pageParam, size),
queryKey: ['myReviews', size],
queryFn: ({ pageParam = 0 }: { pageParam?: number }) => getMyReviews(pageParam, size),

getNextPageParam: (lastPage: MyReviewResponse, allPages: MyReviewResponse[]) => {
return lastPage.hasNext ? allPages.length : undefined;
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function CrewReviewList({
return (
<div className="flex flex-col justify-between p-6">
<div className="mb-6 grid flex-grow gap-4">
{reviews.map((review) => (
{/* {reviews.map((review) => (
<ReviewCard
key={review.id}
rate={review.rate}
Expand All @@ -30,7 +30,7 @@ export default function CrewReviewList({
crewId={review.crewId}
reviewer={review.reviewer}
/>
))}
))} */}
</div>
<div className="mt-6 flex justify-center">
<Pagination
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function ProfileCard() {
const file = (event.target as HTMLInputElement)?.files?.[0];
if (file) {
if (file.size > 5 * 1024 * 1024) {
alert('5MB ์ดํ•˜์˜ ํŒŒ์ผ๋งŒ ์—…๋กœ๋“œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.');
toast.error('5MB ์ดํ•˜์˜ ํŒŒ์ผ๋งŒ ์—…๋กœ๋“œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.');
return;
}

Expand Down
7 changes: 0 additions & 7 deletions src/app/(crew)/my-page/_components/review-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,7 @@
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { Divider } from '@mantine/core';
import { getReviewableGatherings } from '@/src/_apis/gathering/reviewable-gathering';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import { fetchMyReviewData } from '@/src/app/api/mock-api/review';
import ReviewCardList from '@/src/components/common/review-list/review-card-list';
import Tabs from '@/src/components/common/tab';
import ReviewableGatheringCardList from '@/src/components/my-page/reviewable-gatherings/reviewable-gathering-card-list';
import { ReviewInformResponse } from '@/src/types/review';
import { ReviewableGatheringCardInformResponse } from '@/src/types/reviewable-gathering-card';

export default function ReviewTabs() {
const myPageTabs = [
Expand Down
3 changes: 2 additions & 1 deletion src/app/(crew)/my-page/layout.tsx
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 />
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

๋ถˆํ•„์š”ํ•œ ๋นˆ div ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”.

๋งˆ์ง€๋ง‰ ์ค„์˜ ๋นˆ div ์š”์†Œ๋Š” ์•„๋ฌด๋Ÿฐ ์—ญํ• ์„ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”:

      <div>{children}</div>
-     <div />

Committable suggestion skipped: line range outside the PR's diff.

</div>
);
Expand Down
39 changes: 38 additions & 1 deletion src/app/(crew)/my-page/my-review/page.tsx
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
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ตฌํ˜„๋œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์— ๋‹ค์Œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  • ์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • ๊ตฌ์ฒด์ ์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
  • ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ๋Œ€์ฒด UI ์ œ๊ณต
-  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>
+    );
+  }

Committable suggestion skipped: line range outside the PR's diff.


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>
);
}
1 change: 1 addition & 0 deletions src/app/(crew)/my-page/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import { redirect } from 'next/navigation';

export default function MyPage() {
redirect('/my-page/reviewable');
return null;
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

๋„๋‹ฌํ•  ์ˆ˜ ์—†๋Š” ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•˜์„ธ์š”.

redirect() ํ•จ์ˆ˜๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์—๋Ÿฌ๋ฅผ throwํ•˜๊ธฐ ๋•Œ๋ฌธ์— return null ๊ตฌ๋ฌธ์€ ์ ˆ๋Œ€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ์ด๋ฏ€๋กœ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์„ธ์š”:

export default function MyPage() {
  redirect('/my-page/reviewable');
-  return null;
}
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return null;
export default function MyPage() {
redirect('/my-page/reviewable');
}

}
41 changes: 0 additions & 41 deletions src/app/api/mock-api/review.ts

This file was deleted.

62 changes: 5 additions & 57 deletions src/components/common/review-list/review-card-list.stories.tsx
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={() => {}} />,
};
73 changes: 36 additions & 37 deletions src/components/common/review-list/review-card-list.tsx
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
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

๋นˆ ์ƒํƒœ UI์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์ ‘๊ทผ์„ฑ ๊ฐœ์„ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

ํ˜„์žฌ ๊ตฌํ˜„์€ ๊ธฐ๋Šฅ์ ์œผ๋กœ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ์„ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ํ…์ŠคํŠธ๊ฐ€ ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์–ด ์žฌ์‚ฌ์šฉ์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค
  2. ๋ฉ”์‹œ์ง€๊ฐ€ ๋‘ ๊ฐœ์˜ p ํƒœ๊ทธ๋กœ ๋‚˜๋‰˜์–ด ์žˆ์–ด ์Šคํฌ๋ฆฐ ๋ฆฌ๋” ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜ผ๋ž€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐœ์„ ํ•ด๋ณด์„ธ์š”:

-      <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

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
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>
);
}
// ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
if (!reviewDataList.length) {
return (
<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>
);
}


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);
Loading
Loading