Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
12 commits
Select commit Hold shift + click to select a range
6ad4859
๐Ÿ’„[Design] ์ฐœ UI ํ‘œ์‹œ #339
wynter24 Feb 27, 2025
a8494d5
โ™ป๏ธ[Refactor] bookclub ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ axios๋กœ fetching ๋ฐฉ์‹ ๋ณ€๊ฒฝ #339
wynter24 Mar 9, 2025
722a8b7
๐Ÿ›[Fix] ๋‚™๊ด€์  ์—…๋ฐ์ดํŠธ ๋ฐ์ดํ„ฐ ํƒ€์ž… ํ†ต์ผ #339
wynter24 Mar 9, 2025
83f84ab
๐Ÿ›[Fix] useEffect๋กœ hydration error ํ•ด๊ฒฐ #339
wynter24 Mar 11, 2025
aa53c13
๐Ÿ”ฅ[Remove] ๋ถˆํ•„์š”ํ•œ ์ฐœ๊ด€๋ จ context ํŒŒ์ผ ์‚ญ์ œ #339
wynter24 Mar 11, 2025
e3dceda
๐Ÿ›[Fix] ์ฐœ context ๊ด€๋ จ ์ฝ”๋“œ ์ œ๊ฑฐ #339
wynter24 Mar 11, 2025
52c48d1
๐ŸŽจ[Style] ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์ฝ”๋“œ ์ œ๊ฑฐ #339
wynter24 Mar 11, 2025
95c2633
โœจ[Feat] ๋ชจ์ž„ ์ฐพ๊ธฐ ํŽ˜์ด์ง€ errorboudary ์ฒ˜๋ฆฌ #339
wynter24 Mar 11, 2025
b366c7a
โœจ[Feat] ํ•„ํ„ฐ ๋ณ€๊ฒฝ ์š”์ฒญ์— ํ† ํฐ ์ถ”๊ฐ€ #339
wynter24 Mar 11, 2025
f570d69
โœจ[Feat] ๋ชจ์ž„ ๋ฉ”์ธ ํŽ˜์ด์ง€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ #339
wynter24 Mar 11, 2025
0f69c79
โœ…[Test] fetchBookClub ํ…Œ์ŠคํŠธ ์ฝ”๋“œ fetch์—์„œ axios๋กœ ๋ณ€๊ฒฝ #339
wynter24 Mar 11, 2025
a98a640
๐ŸŽจ[Style] ๋ชจ์ž„ ๋ชฉ๋ก ์กฐํšŒ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ suspense ์ œ๊ฑฐ #339
wynter24 Mar 13, 2025
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
8 changes: 3 additions & 5 deletions src/api/book-club/react-query/likeOptimisticUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ export const likeOnMutate = async (
await queryClient.cancelQueries({ queryKey: detailQueryKey });

// ๊ธฐ์กด ์บ์‹œ ๋ฐ์ดํ„ฐ ์ €์žฅ
const previousBookClubs = queryClient.getQueryData<{ bookClubs: BookClub[] }>(
listQueryKey,
);
const previousBookClubs = queryClient.getQueryData<BookClub[]>(listQueryKey);
const previousDetail = queryClient.getQueryData<BookClub>(detailQueryKey);

// ์บ์‹œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ
if (previousBookClubs) {
queryClient.setQueryData(listQueryKey, (old: any) =>
queryClient.setQueryData(listQueryKey, (old: BookClub[] | undefined) =>
old?.map((club: BookClub) =>
club.id === id ? { ...club, isLiked } : club,
),
Expand All @@ -42,7 +40,7 @@ export const likeOnError = (
queryClient: QueryClient,
id: number,
context: {
previousBookClubs?: { bookClubs: BookClub[] };
previousBookClubs?: BookClub[];
previousDetail?: BookClub;
},
) => {
Expand Down
20 changes: 20 additions & 0 deletions src/app/bookclub/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import ErrorTemplate from '@/components/error/ErrorTemplate';

export default function BookClubError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<ErrorTemplate
error={error}
reset={reset}
title="๋ถํด๋Ÿฝ ๋ชฉ๋ก ์กฐํšŒ ์˜ค๋ฅ˜"
message="๋ถํด๋Ÿฝ ๋ชฉ๋ก ์กฐํšŒ ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋˜ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."
/>
);
}
13 changes: 5 additions & 8 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Toast } from '@/components/toast/toast';

import { MSWComponent } from '@/components/MSWComponent';
import '@/styles/globals.css';
import { LikeProvider } from '@/lib/contexts/LikeContext';

export const metadata: Metadata = {
title: 'Bookco',
Expand All @@ -26,13 +25,11 @@ export default function RootLayout({
strategy="beforeInteractive"
/>
<ReactQueryProviders>
<LikeProvider>
<HeaderBar />
<main className="mx-auto flex w-full max-w-[1200px] flex-1 flex-col bg-white">
<Toast />
<MSWComponent>{children}</MSWComponent>
</main>
</LikeProvider>
<HeaderBar />
<main className="mx-auto flex w-full max-w-[1200px] flex-1 flex-col bg-white">
<Toast />
<MSWComponent>{children}</MSWComponent>
</main>
</ReactQueryProviders>
</body>
</html>
Expand Down
11 changes: 5 additions & 6 deletions src/components/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Avatar from '../avatar/Avatar';
import {
LocationIcon,
HostIcon,
// HeartIcon,
HeartIcon,
RatingIcon,
OnlineIcon,
} from '../../../public/icons';
Expand Down Expand Up @@ -52,11 +52,10 @@ function CardBox({ children, className = '', ...props }: CardBoxProps) {
function CardImage({
url,
alt = '๋ชจ์ž„ ์ด๋ฏธ์ง€',
// isLiked,
// onLikeClick,
isLiked,
onLikeClick,
className,
isPast,
// isHost,
...props
}: CardImageProps) {
return (
Expand All @@ -74,11 +73,11 @@ function CardImage({
fill
className={twMerge('object-cover', isPast && 'grayscale')}
/>
{/* {isLiked !== undefined && !isHost && (
{isLiked !== undefined && (
<div className="absolute right-5 top-[15px] z-10">
<HeartIcon isLiked={isLiked} onClick={onLikeClick} />
</div>
)} */}
)}
</div>
);
}
Expand Down
34 changes: 25 additions & 9 deletions src/features/bookclub/components/BookClubMainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ import { useRouter } from 'next/navigation';
import Loading from '@/components/loading/Loading';
import { useQuery } from '@tanstack/react-query';
import { fetchBookClubs } from '@/lib/utils/fetchBookClubs';
import { useEffect, useState } from 'react';
import ErrorHandlingWrapper from '@/components/error/ErrorHandlingWrapper';
import ErrorFallback from '@/components/error/ErrorFallback';
import { getCookie } from '@/features/auth/utils/cookies';

function BookClubMainPage() {
const { filters, updateFilters } = useBookClubList();
const { data, isLoading, isFetching } = useQuery({
const { data, isLoading } = useQuery({
queryKey: ['bookClubs', 'list', filters],
queryFn: () => fetchBookClubs(filters),
// enabled: false, // โœ… ์„œ๋ฒ„์—์„œ ์ด๋ฏธ ๊ฐ€์ ธ์™”๊ธฐ ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ์—์„œ ๋‹ค์‹œ ์š”์ฒญํ•˜์ง€ ์•Š์Œ
// refetchOnMount: false, // โœ… ๋งˆ์šดํŠธ ์‹œ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ง€ ์•Š์Œ
staleTime: 1000 * 60,
queryFn: () => {
const token = getCookie('auth_token');
return fetchBookClubs(filters, token || undefined);
},
});
// console.log('ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ:', data); // ํด๋ผ์ด์–ธํŠธ์˜ ๋ฐ์ดํ„ฐ ํ™•์ธ

const [isHydrated, setIsHydrated] = useState(false);
const router = useRouter();
const user = useAuthStore((state) => state.user);
const userName = user?.nickname || '๋ถ์ฝ”';

useEffect(() => {
setIsHydrated(true);
}, []);

const handleFilterChange = (newFilter: Partial<typeof filters>) => {
updateFilters(newFilter);
};
Expand All @@ -50,14 +60,20 @@ function BookClubMainPage() {
}
/>
<FilterBar filters={filters} handleFilterChange={handleFilterChange} />
{isLoading || isFetching ? (

{isLoading || !isHydrated ? (
<div className="flex h-[400px] justify-center">
<Loading />
</div>
) : (
<div className="pb-12">
<ClubListSection bookClubs={data} filter={filters} />
</div>
<ErrorHandlingWrapper
fallbackComponent={ErrorFallback}
suspenseFallback={<Loading />}
>
<div className="pb-12">
<ClubListSection bookClubs={data} filter={filters} />
</div>
</ErrorHandlingWrapper>
)}
</>
);
Expand Down
11 changes: 1 addition & 10 deletions src/features/bookclub/components/ClubListSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { BookClub, BookClubParams } from '@/types/bookclubs';
import { useLikeClub, useLikeWithAuthCheck, useUnLikeClub } from '@/lib/hooks';
import { useAuthStore } from '@/store/authStore';
import PopUp from '@/components/pop-up/PopUp';
import { queryClient } from '@/lib/utils/reactQueryProvider';

interface ClubListSectionProps {
bookClubs: BookClub[];
Expand All @@ -19,6 +18,7 @@ interface ClubListSectionProps {

function ClubListSection({ bookClubs = [], filter }: ClubListSectionProps) {
const router = useRouter();

const {
isLikePopUpOpen,
likePopUpLabel,
Expand All @@ -31,13 +31,10 @@ function ClubListSection({ bookClubs = [], filter }: ClubListSectionProps) {

useEffect(() => {
checkLoginStatus();
console.log('๋ฉ”์ธ ํŽ˜์ด์ง€: ', bookClubs);
}, [checkLoginStatus]);

const today = useMemo(() => new Date(), []);

// console.log('๐Ÿ” ClubListSection ๋ฐ์ดํ„ฐ:', bookClubs);

const handleLikeClub = (isLiked: boolean, id: number) => {
if (!isLoggedIn) {
onShowAuthPopUp();
Expand All @@ -49,12 +46,6 @@ function ClubListSection({ bookClubs = [], filter }: ClubListSectionProps) {
} else {
onConfirmLike(id);
}

queryClient.setQueryData(['bookClubs', 'list', filter], (oldData: any) =>
oldData.map((club: BookClub) =>
club.id === id ? { ...club, isLiked: !isLiked } : club,
),
);
};

const handleLikePopUpConfirm = () => {
Expand Down
9 changes: 2 additions & 7 deletions src/features/club-details/components/HeaderSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
useLikeWithAuthCheck,
useUnLikeClub,
} from '@/lib/hooks/index';
import { useLikeContext } from '@/lib/contexts/LikeContext';

interface HeaderSectionProps {
clubInfo: BookClub;
Expand Down Expand Up @@ -46,8 +45,6 @@ function HeaderSection({ clubInfo, idAsNumber }: HeaderSectionProps) {
} = useLikeWithAuthCheck();
const { onConfirmLike } = useLikeClub();
const { onConfirmUnLike } = useUnLikeClub();
const { likedClubs, toggleLike } = useLikeContext();
const isLiked = likedClubs?.has(clubInfo.id) ?? clubInfo.isLiked;

const { isLoggedIn, checkLoginStatus, user } = useAuthStore();

Expand All @@ -68,14 +65,12 @@ function HeaderSection({ clubInfo, idAsNumber }: HeaderSectionProps) {
!isLoggedIn ? router.push('/login') : handleJoin(clubInfo.id);
};

const handleLikeClub = () => {
const handleLikeClub = (isLiked: boolean) => {
if (!isLoggedIn) {
onShowAuthPopUp();
return;
}

toggleLike(clubInfo.id, !isLiked); // โœ… ์ „์—ญ ์ƒํƒœ ์—…๋ฐ์ดํŠธ

if (isLiked) {
onConfirmUnLike(clubInfo.id);
} else {
Expand Down Expand Up @@ -107,7 +102,7 @@ function HeaderSection({ clubInfo, idAsNumber }: HeaderSectionProps) {
clubInfo.endDate,
new Date(), // TODO: new Date() ์ตœ์ ํ™” ํ›„ ์ˆ˜์ •
),
onLikeClick: handleLikeClub,
onLikeClick: () => handleLikeClub(clubInfo.isLiked),
host: {
id: clubInfo.hostId,
name: clubInfo.hostNickname,
Expand Down
99 changes: 0 additions & 99 deletions src/lib/contexts/LikeContext.tsx

This file was deleted.

Loading