Skip to content

Commit 3bd43ed

Browse files
committed
chore:임시저장
1 parent 5440eff commit 3bd43ed

File tree

6 files changed

+73
-56
lines changed

6 files changed

+73
-56
lines changed

src/components/common/ErrorBoundary.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { Component, ErrorInfo, ReactNode } from 'react';
22

33
import { isAxiosError } from 'axios';
4+
import { NextRouter } from 'next/router';
45

56
import ErrorModal from './Modal/ErrorModal';
67

78
interface ErrorBoundaryProps {
89
children: ReactNode;
910
fallback?: ReactNode;
1011
onError?: (error: Error, errorInfo: ErrorInfo) => void;
11-
onRedirect: () => void;
12+
router: NextRouter;
1213
}
1314

1415
interface ErrorBoundaryState {
@@ -45,6 +46,13 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
4546
}
4647
break;
4748
}
49+
case 401: {
50+
const apiMessage = error.response?.data?.message;
51+
if (apiMessage === 'Unauthorized') {
52+
errorMessage = '로그인이 필요합니다.';
53+
}
54+
break;
55+
}
4856
default: {
4957
errorMessage = `${error.response?.status || ''} - ${error.response?.data?.message || error.message}`;
5058
break;
@@ -69,7 +77,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
6977
// 컴포넌트 렌더링 로직
7078
public render() {
7179
const { hasError, isOpen, errorMessageToDisplay } = this.state;
72-
const { children, onRedirect } = this.props;
80+
const { children, router } = this.props;
7381

7482
if (hasError) {
7583
return (
@@ -78,14 +86,10 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
7886
onOpenChange={() => {}}
7987
onConfirm={() => {
8088
this.setState({ isOpen: false, hasError: false });
81-
onRedirect();
89+
router.back();
8290
}}
8391
>
84-
<div className='text-center custom-text-lg-bold'>
85-
{errorMessageToDisplay}
86-
<br />
87-
{'메인화면으로 돌아갑니다.'}
88-
</div>
92+
<div className='text-center custom-text-lg-bold'>{errorMessageToDisplay}</div>
8993
</ErrorModal>
9094
);
9195
}

src/components/common/Gnb.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ function AuthMenu() {
4141
const { pathname } = useRouter();
4242
const { user } = useUser();
4343

44+
/**
45+
1)로그인 -> User스토어에 바로 저장이되나?(확인하고)
46+
2)바로 저장이 되는데 안보인다? -> user다시 조회하는 동작 추가 필요
47+
3)바로 저장이 되면 보인다? -> 그냥 넘어가기
48+
4) 로딩스피너 적용되는 거 보고 오버레이(뒤에 비치니까) 만약 새로고침 시 유저상태 변하는 게 보인다? -> ssr고려하기? 하
49+
50+
51+
*/
52+
4453
return user ? (
4554
<UserDropdown userImage={user.image} />
4655
) : (
@@ -79,8 +88,12 @@ function UserDropdown({ userImage }: Props) {
7988
]}
8089
onSelect={onSelect}
8190
trigger={
82-
<div className='relative w-[20px] md:w-[45px] h-[20px] md:h-[45px] cursor-pointer'>
83-
{userImage ? <Image fill src={userImage} alt='유저의 프로필 사진' /> : <UserDefaultImg />}
91+
<div className='relative w-[20px] md:w-[45px] h-[20px] md:h-[45px] cursor-pointer rounded-full overflow-hidden'>
92+
{userImage ? (
93+
<Image width={45} height={45} src={userImage} alt='유저의 프로필 사진' />
94+
) : (
95+
<UserDefaultImg />
96+
)}
8497
</div>
8598
}
8699
></MenuDropdown>

src/components/wineDetail/Kebab.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ function Kebab({ reviewId }: Props) {
3434
break;
3535
}
3636
case 'delete': {
37-
setOpenDeleteModal(true);
37+
if (user?.id !== reviewData.user.id) setOpenAlertModal(true);
38+
else {
39+
setOpenDeleteModal(true);
40+
}
3841
break;
3942
}
4043
}

src/components/wineDetail/LikeButton.tsx

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,63 @@
11
import { useState } from 'react';
22

3-
import { QueryClient, useMutation } from '@tanstack/react-query';
4-
53
import { postLike, deleteLike } from '@/api/handleLikeRequest';
64
import FullLikeIcon from '@/assets/icons/fullLike.svg';
75
import LikeIcon from '@/assets/icons/like.svg';
86
import { Button } from '@/components/ui/button';
7+
import { useUser } from '@/hooks/useUser';
98
import { cn } from '@/lib/utils';
9+
import useReviewCardStore from '@/stores/reviewCardStore';
10+
11+
import ErrorModal from '../common/Modal/ErrorModal';
1012

1113
interface Props {
1214
isLike?: boolean;
1315
reviewId: number;
1416
}
1517

16-
const queryClient = new QueryClient();
17-
18-
export function usePostLikeMutation() {
19-
return useMutation({
20-
mutationFn: (reviewId: number) => postLike(reviewId),
21-
onSuccess: () => {
22-
queryClient.invalidateQueries({ queryKey: ['wineDetail'] }); // 필요한 캐시 무효화
23-
},
24-
throwOnError: true,
25-
});
26-
}
27-
28-
export function useDeleteLikeMutation() {
29-
return useMutation({
30-
mutationFn: (reviewId: number) => deleteLike(reviewId),
31-
onSuccess: () => {
32-
queryClient.invalidateQueries({ queryKey: ['wineDetail'] });
33-
},
34-
throwOnError: true,
35-
});
36-
}
37-
3818
function LikeButton({ isLike, reviewId }: Props) {
3919
const [isClicked, setIsClicked] = useState(isLike);
40-
const postLikeMutation = usePostLikeMutation();
41-
const deleteLikeMutation = useDeleteLikeMutation();
20+
const [openAlertModal, setOpenAlertModal] = useState(false);
4221

43-
async function handleToggle() {
44-
setIsClicked((prev) => !prev); //미리 업데이트
22+
const { user } = useUser();
23+
const id = useReviewCardStore((state) => state.allReviews[reviewId]?.user.id);
4524

46-
try {
47-
isClicked
48-
? await deleteLikeMutation.mutateAsync(reviewId)
49-
: await postLikeMutation.mutateAsync(reviewId);
50-
} catch (err) {
51-
setIsClicked((prev) => !prev); //실패하면 업데이트 했던 거 취소
52-
}
25+
async function handleToggle() {
26+
if (user?.id !== id) {
27+
setIsClicked((prev) => !prev);
28+
try {
29+
isClicked ? await deleteLike(reviewId) : await postLike(reviewId);
30+
} catch (err) {
31+
setIsClicked((prev) => !prev); //실패하면 업데이트 했던 거 취소
32+
}
33+
} else {
34+
setOpenAlertModal(true);
35+
} //미리 업데이트
5336
}
5437
return (
55-
<Button
56-
onClick={handleToggle}
57-
variant='onlyCancel'
58-
className={cn(
59-
'border-0 hover:text-primary w-8 h-8 md:w-9.5 md:h-9.5 mr-4.5 md:mr-5 [&_svg]:w-8 [&_svg]:h-8',
60-
{ 'text-primary': isClicked },
38+
<>
39+
<Button
40+
onClick={handleToggle}
41+
variant='onlyCancel'
42+
className={cn(
43+
'border-0 hover:text-primary w-8 h-8 md:w-9.5 md:h-9.5 mr-4.5 md:mr-5 [&_svg]:w-8 [&_svg]:h-8',
44+
{ 'text-primary': isClicked },
45+
)}
46+
>
47+
{isClicked ? <FullLikeIcon /> : <LikeIcon />}
48+
</Button>
49+
{openAlertModal && (
50+
<ErrorModal
51+
open={openAlertModal}
52+
onOpenChange={() => {}}
53+
onConfirm={() => setOpenAlertModal(false)}
54+
>
55+
<div className='custom-text-lg-bold'>
56+
본인이 작성한 리뷰에는 좋아요를 할 수 없습니다.{' '}
57+
</div>
58+
</ErrorModal>
6159
)}
62-
>
63-
{isClicked ? <FullLikeIcon /> : <LikeIcon />}
64-
</Button>
60+
</>
6561
);
6662
}
6763

src/pages/_app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default function App({ Component, pageProps }: AppProps) {
3939
<QueryClientProvider client={queryClient}>
4040
<HydrationBoundary state={pageProps.dehydratedState}>
4141
{!hideHeader && <Gnb />}
42-
<ErrorBoundary fallback={<></>} onRedirect={() => router.replace('/')}>
42+
<ErrorBoundary fallback={<></>} router={router}>
4343
<div
4444
className={clsx({
4545
'pt-[70px] md:pt-[100px] xl:pt-[110px]': !hideHeader,

src/pages/wines/[wineid].tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default function WineInfoById(props: WinePageProps) {
3535
queryKey: ['wineDetail', parsedWineId],
3636
queryFn: () => getWineInfoForClient(parsedWineId),
3737
staleTime: 1000 * 60 * 5,
38+
throwOnError: true,
3839
});
3940

4041
useEffect(() => {

0 commit comments

Comments
 (0)