-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/116/reviewable gathering list api #154
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
Changes from 7 commits
174771f
559051f
0bf3acf
4b91e93
31611ba
f9de51a
b1c19b7
3354710
5a89e85
c523eab
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,14 @@ | ||||||
| import { fetchApi } from '@/src/utils/api'; | ||||||
| import { PageableTypes } from '@/src/types/crew-card'; | ||||||
| import { ReviewableGatheringCardInformResponse } from '@/src/types/reviewable-gathering-card'; | ||||||
|
|
||||||
| export async function getReviewableGatherings(pageable: PageableTypes) { | ||||||
| const { page, size, sort = ['string'] } = pageable; | ||||||
|
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 sort ๋งค๊ฐ๋ณ์์ ๊ธฐ๋ณธ๊ฐ ์ค์ ๊ฐ์ ํ์
๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ ๊ฒ์ ์ ์๋๋ฆฝ๋๋ค: - const { page, size, sort = ['string'] } = pageable;
+ const { page, size, sort = ['createdAt,desc'] } = pageable;๐ Committable suggestion
Suggested change
|
||||||
| const response: { data: ReviewableGatheringCardInformResponse } = await fetchApi( | ||||||
| `/api/gatherings/reviewable?page=${page}&size=${size}&sort=${sort}`, | ||||||
|
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. URL ๋งค๊ฐ๋ณ์ ์ธ์ฝ๋ฉ ์ฒ๋ฆฌ ํ์ URL ๋งค๊ฐ๋ณ์๊ฐ ์ธ์ฝ๋ฉ๋์ง ์์ ํน์ ๋ฌธ์๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ด - `/api/gatherings/reviewable?page=${page}&size=${size}&sort=${sort}`,
+ `/api/gatherings/reviewable?page=${encodeURIComponent(page)}&size=${encodeURIComponent(size)}&sort=${encodeURIComponent(sort)}`,๐ Committable suggestion
Suggested change
|
||||||
| ); | ||||||
| if (!response.data) { | ||||||
| throw new Error('Failed to get reviewable gatherings'); | ||||||
| } | ||||||
| return response.data; | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import { getReviewableGatherings } from '@/src/_apis/gathering/reviewable-gathering'; | ||||||||||||||||||||||
| import { PageableTypes } from '@/src/types/crew-card'; | ||||||||||||||||||||||
| import { ReviewableGatheringCardInformResponse } from '@/src/types/reviewable-gathering-card'; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export function useGetReviewableQuery({ pageable }: { pageable: PageableTypes }) { | ||||||||||||||||||||||
| const { size, sort = ['string'] } = pageable; | ||||||||||||||||||||||
|
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. ๊ธฐ๋ณธ ์ ๋ ฌ ๊ฐ์ ์์ ํด ์ฃผ์ธ์
- const { size, sort = ['string'] } = pageable;
+ const { size, sort = ['createdAt', 'desc'] } = pageable;๐ Committable suggestion
Suggested change
|
||||||||||||||||||||||
| return { | ||||||||||||||||||||||
| queryKey: ['reviewableGathering'], | ||||||||||||||||||||||
| queryFn: ({ pageParam = 0 }) => | ||||||||||||||||||||||
| getReviewableGatherings({ page: pageParam, size, sort }).then((response) => { | ||||||||||||||||||||||
| if (response === undefined || response === null) { | ||||||||||||||||||||||
| throw new Error('์ฝ์ ๋ชฉ๋ก์ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.'); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return response; | ||||||||||||||||||||||
| }), | ||||||||||||||||||||||
| getNextPageParam: ( | ||||||||||||||||||||||
| lastPage: ReviewableGatheringCardInformResponse, | ||||||||||||||||||||||
| allPages: ReviewableGatheringCardInformResponse[], | ||||||||||||||||||||||
| ) => (lastPage.hasNext ? allPages.length : undefined), | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
Comment on lines
+18
to
+22
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 ํ์ด์ง๋ค์ด์ ๋ก์ง์ ๋ณด์ํด ์ฃผ์ธ์ ํ์ฌ ๊ตฌํ๋ getNextPageParam: (
lastPage: ReviewableGatheringCardInformResponse,
- allPages: ReviewableGatheringCardInformResponse[],
+ _pages: ReviewableGatheringCardInformResponse[],
- ) => (lastPage.hasNext ? allPages.length : undefined),
+ ) => (lastPage.hasNext ? lastPage.currentPage + 1 : undefined),๐ Committable suggestion
Suggested change
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| export default function ReviewableGatheringsPage() { | ||
| return <div>reviewable gathering list component</div>; | ||
| 'use client'; | ||
|
|
||
| import ReviewableGatheringCardList from '@/src/components/my-page/reviewable-gatherings/reviewable-gathering-card-list'; | ||
|
|
||
| export default function ReviewableTab() { | ||
| return <ReviewableGatheringCardList />; | ||
| } | ||
|
Comment on lines
+5
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 ์๋ฌ ์ฒ๋ฆฌ์ ๋ก๋ฉ ์ํ ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ํ์ฌ ๊ตฌํ์ ๋งค์ฐ ๋จ์ํ์ฌ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ ์ฌํญ์ ๊ณ ๋ คํด๋ณด์๊ธฐ ๋ฐ๋๋๋ค:
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํ ์ ์์ต๋๋ค: +import { Suspense, ErrorBoundary } from 'react';
+import LoadingSpinner from '@/src/components/common/loading-spinner';
+import ErrorFallback from '@/src/components/common/error-fallback';
export default function ReviewableTab() {
- return <ReviewableGatheringCardList />;
+ return (
+ <ErrorBoundary fallback={<ErrorFallback />}>
+ <Suspense fallback={<LoadingSpinner />}>
+ <ReviewableGatheringCardList />
+ </Suspense>
+ </ErrorBoundary>
+ );
}
|
||
|
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,172 @@ | ||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import Image from 'next/image'; | ||||||||||||||||||||||||
| import { Menu } from '@mantine/core'; | ||||||||||||||||||||||||
| import { useDisclosure } from '@mantine/hooks'; | ||||||||||||||||||||||||
| import Profiles from '@/src/components/common/crew-list/profiles'; | ||||||||||||||||||||||||
| import ConfirmCancelModal from '@/src/components/common/modal/confirm-cancel-modal'; | ||||||||||||||||||||||||
| import ProgressBar from '@/src/components/common/progress-bar/index'; | ||||||||||||||||||||||||
| import { CrewMember } from '@/src/types/crew-card'; | ||||||||||||||||||||||||
| import Check from '@/public/assets/icons/ic-check.svg'; | ||||||||||||||||||||||||
| import KebabIcon from '@/public/assets/icons/kebab-btn.svg'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| interface DetailCrewCardProps { | ||||||||||||||||||||||||
| data: { | ||||||||||||||||||||||||
| id: number; | ||||||||||||||||||||||||
| title: string; | ||||||||||||||||||||||||
| mainLocation: string; | ||||||||||||||||||||||||
| subLocation: string; | ||||||||||||||||||||||||
| participantCount: number; | ||||||||||||||||||||||||
| totalCount: number; | ||||||||||||||||||||||||
| confirmed: boolean; | ||||||||||||||||||||||||
| imageUrl: string; | ||||||||||||||||||||||||
| totalGatheringCount: number; | ||||||||||||||||||||||||
| crewMembers: CrewMember[]; | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export default function DetailCrewCard({ data }: DetailCrewCardProps) { | ||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||
| id, | ||||||||||||||||||||||||
| title, | ||||||||||||||||||||||||
| mainLocation, | ||||||||||||||||||||||||
| subLocation, | ||||||||||||||||||||||||
| participantCount, | ||||||||||||||||||||||||
| totalCount, | ||||||||||||||||||||||||
| confirmed, | ||||||||||||||||||||||||
| imageUrl, | ||||||||||||||||||||||||
| totalGatheringCount, | ||||||||||||||||||||||||
| crewMembers, | ||||||||||||||||||||||||
| } = data; | ||||||||||||||||||||||||
| const [confirmCancelOpened, { open: openConfirmCancel, close: closeConfirmCancel }] = | ||||||||||||||||||||||||
| useDisclosure(); | ||||||||||||||||||||||||
| const [leaveCrewModalOpened, { open: openLeaveCrewModal, close: closeLeaveCrewModal }] = | ||||||||||||||||||||||||
| useDisclosure(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const handleDelete = () => { | ||||||||||||||||||||||||
| openConfirmCancel(); | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const handleLeaveCrew = () => { | ||||||||||||||||||||||||
| openLeaveCrewModal(); | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const handleConfirmDelete = () => { | ||||||||||||||||||||||||
| // TODO : ์ญ์ ๋ก์ง | ||||||||||||||||||||||||
| closeConfirmCancel(); | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const handleConfirmLeaveCrew = () => { | ||||||||||||||||||||||||
| // TODO : ํํด ๋ก์ง | ||||||||||||||||||||||||
| closeLeaveCrewModal(); | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||
| <div className="relative flex h-[508px] max-w-full flex-col overflow-hidden rounded-[14px] bg-white shadow-bg md:h-[270px] md:flex-row lg:h-[270px] lg:w-[1180px]"> | ||||||||||||||||||||||||
| {/* eslint-disable-next-line no-nested-ternary */} | ||||||||||||||||||||||||
| {/* //TODO: captin, crew์ธ ๊ฒฝ์ฐ ๋ก์ง ์์ */} | ||||||||||||||||||||||||
| {/* {isCaptain ? ( | ||||||||||||||||||||||||
| <Menu trigger="click" position="bottom-end" openDelay={100} closeDelay={400}> | ||||||||||||||||||||||||
| <Menu.Target> | ||||||||||||||||||||||||
| <div className="top-68 absolute right-6 top-[286px] cursor-pointer md:top-6 lg:top-6"> | ||||||||||||||||||||||||
| <Image src={KebabIcon} alt="๋๋ณด๊ธฐ" width={20} height={20} /> | ||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||
| </Menu.Target> | ||||||||||||||||||||||||
| <Menu.Dropdown> | ||||||||||||||||||||||||
| <Menu.Item component="a" href={`/crew/detail/${id}/edit`} className="font-pretendard"> | ||||||||||||||||||||||||
| ํฌ๋ฃจ ์์ ํ๊ธฐ | ||||||||||||||||||||||||
| </Menu.Item> | ||||||||||||||||||||||||
| <Menu.Item | ||||||||||||||||||||||||
| type="button" | ||||||||||||||||||||||||
| onClick={handleDelete} | ||||||||||||||||||||||||
| className="font-pretendard text-red-600" | ||||||||||||||||||||||||
| > | ||||||||||||||||||||||||
| ํฌ๋ฃจ ์ญ์ ํ๊ธฐ | ||||||||||||||||||||||||
| </Menu.Item> | ||||||||||||||||||||||||
| </Menu.Dropdown> | ||||||||||||||||||||||||
| </Menu> | ||||||||||||||||||||||||
| ) : isCrew ? ( | ||||||||||||||||||||||||
| <Menu trigger="click" position="bottom-end" openDelay={100} closeDelay={400}> | ||||||||||||||||||||||||
| <Menu.Target> | ||||||||||||||||||||||||
| <div className="top-68 absolute right-6 top-[286px] md:top-6 lg:top-6"> | ||||||||||||||||||||||||
| <Image src={KebabIcon} alt="๋๋ณด๊ธฐ" width={20} height={20} /> | ||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||
| </Menu.Target> | ||||||||||||||||||||||||
| <Menu.Dropdown> | ||||||||||||||||||||||||
| <Menu.Item type="button" onClick={handleLeaveCrew} className="font-pretendard"> | ||||||||||||||||||||||||
| ํฌ๋ฃจ ํํดํ๊ธฐ | ||||||||||||||||||||||||
| </Menu.Item> | ||||||||||||||||||||||||
| </Menu.Dropdown> | ||||||||||||||||||||||||
| </Menu> | ||||||||||||||||||||||||
| ) : null} */} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| {/* ์ธ๋ค์ผ */} | ||||||||||||||||||||||||
| <div className="relative h-[270px] w-full md:w-[385px] lg:w-[540px]"> | ||||||||||||||||||||||||
| <Image fill style={{ objectFit: 'cover' }} alt={title} src={imageUrl} /> | ||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| <div className="relative h-[270px] w-full md:w-[385px] lg:w-[540px]"> | |
| <Image fill style={{ objectFit: 'cover' }} alt={title} src={imageUrl} /> | |
| </div> | |
| <div className="relative h-[270px] w-full md:w-[385px] lg:w-[540px]"> | |
| <Image | |
| fill | |
| style={{ objectFit: 'cover' }} | |
| alt={`${title} ํฌ๋ฃจ์ ๋ํ ์ด๋ฏธ์ง`} | |
| src={imageUrl} | |
| /> | |
| </div> |
Outdated
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
ํ๋์ฝ๋ฉ๋ ๊ฐ๋ค์ ์์ํ ํ์
์ต์ ์ธ์์๊ฐ ํ๋์ฝ๋ฉ๋์ด ์์ต๋๋ค. ์ด๋ฐ ๊ฐ๋ค์ ์์๋ก ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์์๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์:
const CREW_CONSTANTS = {
MIN_MEMBERS: 2,
// ๋ค๋ฅธ ์์๋ค๋ ์ถ๊ฐ
} as const;
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.
๐ก Codebase verification
์์กด์ฑ ๋ฒ์ ๋ถ์ผ์น ๋ฐ ํธํ์ฑ ๋ฌธ์ ๋ฐ๊ฒฌ
Next.js์ React ๋ฒ์ ๊ฐ์ ํธํ์ฑ ๋ฌธ์ ๊ฐ ํ์ธ๋์์ต๋๋ค:
๋ค์๊ณผ ๊ฐ์ด ์์ ์ ๊ถ์ฅ๋๋ฆฝ๋๋ค:
๐ Analysis chain
์์กด์ฑ ๋ฒ์ ๊ด๋ฆฌ ์ ๋ต ๊ฒํ ํ์
๋ค์ ๋ณ๊ฒฝ ์ฌํญ๋ค์ ๋ํ ๊ฒํ ๊ฐ ํ์ํฉ๋๋ค:
์ด๋ฌํ ๋ณ๊ฒฝ์ ์๊ธฐ์น ์์ ํธํ์ฑ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ผ๋ฏ๋ก, ํ์ ๋ฒ์ ๊ด๋ฆฌ ์ ์ฑ ๊ณผ ์ผ์นํ๋์ง ํ์ธํด์ฃผ์ธ์.
๐ Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 301
Script:
Length of output: 2272