-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/121/liked api #123
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/121/liked api #123
Changes from all commits
44d254e
77585af
0344be1
340752f
7a31287
c1fc0d7
1f75511
d3649f7
e075627
79d9191
ef72b00
84a8539
b243456
9e1b752
4317a4c
5bf99c2
e82ff4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { fetchApi } from '@/src/utils/api'; | ||
| import { GatheringResponseType } from '@/src/types/gathering-data'; | ||
|
|
||
| // ์ฐ ๋ชฉ๋ก ์กฐํ | ||
| export async function getLikedList(page: number): Promise<GatheringResponseType> { | ||
| const url = `/api/liked/memberLikes?page=${page}&size=6`; | ||
|
|
||
| const response = await fetchApi<{ data: GatheringResponseType }>(url, { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }); | ||
| return response.data; | ||
| } | ||
|
|
||
| // ์ฐ ์ถ๊ฐํ๊ธฐ | ||
| export async function addLike(gatheringId: number): Promise<void> { | ||
| const url = `/api/liked/${gatheringId}`; | ||
|
|
||
| await fetchApi<void>(url, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| // ์ฐ ํด์ ํ๊ธฐ | ||
| export async function removeLike(gatheringId: number): Promise<void> { | ||
| const url = `/api/liked/${gatheringId}`; | ||
|
|
||
| await fetchApi<void>(url, { | ||
| method: 'DELETE', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import { useQuery } from '@tanstack/react-query'; | ||
| import { getLikedList } from '@/src/_apis/liked/liked-apis'; | ||
|
|
||
| export function useGetLikedListQuery(page: number) { | ||
| return useQuery({ | ||
| queryKey: ['likedList', page], | ||
| queryFn: () => getLikedList(page), | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,12 @@ | ||
| 'use client'; | ||
|
|
||
| import { useState } from 'react'; | ||
| import { toast } from 'react-toastify'; | ||
| import { useRouter } from 'next/navigation'; | ||
| import { addLike, removeLike } from '@/src/_apis/liked/liked-apis'; | ||
| import { useGetGatheringListQuery } from '@/src/_queries/crew/gathering-list-queries'; | ||
| import { ApiError } from '@/src/utils/api'; | ||
| import ConfirmModal from '@/src/components/common/modal/confirm-modal'; | ||
| import GatheringCardCarousel from '@/src/components/gathering-list/gathering-card-carousel'; | ||
|
|
||
| interface GatheringListSectionProps { | ||
|
|
@@ -9,12 +15,57 @@ interface GatheringListSectionProps { | |
|
|
||
| export default function GatheringListSection({ id }: GatheringListSectionProps) { | ||
| const { data: gatheringList, isLoading, error } = useGetGatheringListQuery(id); | ||
| const [showLoginModal, setShowLoginModal] = useState(false); | ||
| const router = useRouter(); | ||
|
|
||
| if (isLoading) return <p>๋ก๋ฉ ์ค...</p>; | ||
| const handleLike = async (gatheringId: number) => { | ||
| try { | ||
| await addLike(gatheringId); | ||
| } catch (apiError) { | ||
| if (apiError instanceof ApiError) { | ||
| toast.error(`์ฐํ๊ธฐ์ ์คํจํ์ต๋๋ค: ${apiError.message}`); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| const handleUnlike = async (gatheringId: number) => { | ||
| try { | ||
| await removeLike(gatheringId); | ||
| } catch (apiError) { | ||
| if (apiError instanceof ApiError) { | ||
| toast.error(`์ฐํ๊ธฐ ํด์ ์ ์คํจํ์ต๋๋ค: ${apiError.message}`); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| if (error) return <p>๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค: {error.message}</p>; | ||
| const handleLoginRedirect = () => { | ||
| const currentPath = window.location.pathname || '/'; | ||
| router.push(`/login?redirect=${encodeURIComponent(currentPath)}`); | ||
| }; | ||
|
|
||
| // TODO: ์ถํ ์๋ฌ, ๋ก๋ฉ ์์ | ||
| if (isLoading) return <p>๋ก๋ฉ ์ค...</p>; | ||
| if (error) return <p>๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค</p>; | ||
|
Comment on lines
+46
to
+48
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 ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ ์ฌํญ์ ์ ์ํฉ๋๋ค:
if (isLoading) return <LoadingSpinner />;
if (error) return (
<ErrorState
message="๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค"
onRetry={() => refetch()}
/>
);
if (!gatheringList || gatheringList.length === 0) return (
<EmptyState message="์์ง ๋ฑ๋ก๋ ๋ชจ์์ด ์์ต๋๋ค" />
); |
||
| if (!gatheringList || gatheringList.length === 0) return <p>๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.</p>; | ||
|
|
||
| return <GatheringCardCarousel gatheringData={gatheringList} crewId={id} />; | ||
| return ( | ||
| <> | ||
| <GatheringCardCarousel | ||
| gatheringData={gatheringList} | ||
| crewId={id} | ||
| onLike={handleLike} | ||
| onUnlike={handleUnlike} | ||
| onShowLoginModal={() => setShowLoginModal(true)} | ||
| /> | ||
| {showLoginModal && ( | ||
| <ConfirmModal | ||
| opened={showLoginModal} | ||
| onClose={() => setShowLoginModal(false)} | ||
| onConfirm={handleLoginRedirect} | ||
| > | ||
| ๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค! | ||
| </ConfirmModal> | ||
| )} | ||
| </> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,5 @@ | ||||||||
| import { Bounce, ToastContainer } from 'react-toastify'; | ||||||||
|
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. ์คํ์ผ import ์์ ๊ฐ์ ์ด ํ์ํฉ๋๋ค
๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ฃผ์ธ์: import { Bounce, ToastContainer } from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
import '@mantine/core/styles.css';๐ Committable suggestion
Suggested change
|
||||||||
| import 'react-toastify/dist/ReactToastify.css'; | ||||||||
| import '@mantine/core/styles.css'; | ||||||||
| import Header from '@/src/components/common/header/container'; | ||||||||
| import '@/src/styles/globals.css'; | ||||||||
|
|
@@ -10,6 +12,19 @@ export default function RootLayout({ | |||||||
| return ( | ||||||||
| <> | ||||||||
| <Header /> | ||||||||
| <ToastContainer | ||||||||
| position="bottom-right" | ||||||||
| autoClose={3000} | ||||||||
| hideProgressBar={false} | ||||||||
| newestOnTop={false} | ||||||||
| closeOnClick | ||||||||
| rtl={false} | ||||||||
| pauseOnFocusLoss | ||||||||
| draggable | ||||||||
| pauseOnHover | ||||||||
| theme="light" | ||||||||
| transition={Bounce} | ||||||||
| /> | ||||||||
| <div className="flex min-h-screen flex-col items-center bg-gray-50"> | ||||||||
| <main className="container flex min-h-screen max-w-pc flex-1 flex-col md:shadow-bg"> | ||||||||
| {children} | ||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,9 @@ | ||
| import GatheringList from '@/src/components/gathering-list/gathering-list'; | ||
| import { gatheringData } from '@/src/mock/gathering-data'; | ||
| import LikedList from '@/src/components/gathering-list/liked-list-container'; | ||
|
|
||
| export default function FavoritePage() { | ||
| return ( | ||
| <div className="mt-4 md:mt-10"> | ||
| <GatheringList gatheringData={gatheringData} /> | ||
| <LikedList /> | ||
| </div> | ||
| ); | ||
| } |
This file was deleted.
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
์๋ฌ ์ฒ๋ฆฌ ๋ก์ง ๊ฐ์ ํ์
์๋ฌ ์ฒ๋ฆฌ ๋ก์ง์ด handleLike์ handleUnlike์์ ์ค๋ณต๋์ด ์์ต๋๋ค. ๋ํ ์ผ๋ฐ์ ์ธ ์๋ฌ ์ํฉ์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋์ด ์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํ๋ ๊ฒ์ ์ ์๋๋ฆฝ๋๋ค:
Also applies to: 31-39