Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
12 changes: 12 additions & 0 deletions src/components/common/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
if (isAxiosError(error)) {
switch (error.response?.status) {
case 404: {
//๋ผ์šฐํŒ… ๊ฒฝ๋กœ๋Š” ๋งž๋Š”๋ฐ ํŽ˜์ด์ง€ ๋ชป ์ฐพ์€ ๊ฒฝ์šฐ
errorMessage = 'ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.';
break;
}
case 403: {
//์ธ๊ฐ€๋ฐ›์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ
const apiMessage = error.response?.data?.message;
if (apiMessage === '๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์—๋Š” ์ข‹์•„์š”๋ฅผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.') {
errorMessage = '๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์—๋Š” ์ข‹์•„์š”๋ฅผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.';
Expand All @@ -47,18 +49,28 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
break;
}
case 401: {
//401
const apiMessage = error.response?.data?.message;
if (apiMessage === 'Unauthorized') {
errorMessage = '๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.';
}
break;
}
case 400: {
// wineid๊ฐ’์— ์˜์–ด๊ฐ€ ๋“ค์–ด๊ฐ„ ๊ฒฝ์šฐ
const apiMessage = error.response?.data?.message;
if (apiMessage === 'Validation Failed') {
errorMessage = '์ž˜๋ชป๋œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.';
}
break;
}
default: {
errorMessage = `${error.response?.status || ''} - ${error.response?.data?.message || error.message}`;
break;
}
}
} else {
//์—‘์‹œ์˜ค์Šค ์—๋Ÿฌ๊ฐ€ ์•„๋‹Œ ๊ฒƒ๋“ค
errorMessage = `${error.message}`;
}

Expand Down
9 changes: 0 additions & 9 deletions src/components/common/Gnb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,6 @@ function AuthMenu() {
const { pathname } = useRouter();
const { user } = useUser();

/**
1)๋กœ๊ทธ์ธ -> User์Šคํ† ์–ด์— ๋ฐ”๋กœ ์ €์žฅ์ด๋˜๋‚˜?(ํ™•์ธํ•˜๊ณ )
2)๋ฐ”๋กœ ์ €์žฅ์ด ๋˜๋Š”๋ฐ ์•ˆ๋ณด์ธ๋‹ค? -> user๋‹ค์‹œ ์กฐํšŒํ•˜๋Š” ๋™์ž‘ ์ถ”๊ฐ€ ํ•„์š”
3)๋ฐ”๋กœ ์ €์žฅ์ด ๋˜๋ฉด ๋ณด์ธ๋‹ค? -> ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐ€๊ธฐ
4) ๋กœ๋”ฉ์Šคํ”ผ๋„ˆ ์ ์šฉ๋˜๋Š” ๊ฑฐ ๋ณด๊ณ  ์˜ค๋ฒ„๋ ˆ์ด(๋’ค์— ๋น„์น˜๋‹ˆ๊นŒ) ๋งŒ์•ฝ ์ƒˆ๋กœ๊ณ ์นจ ์‹œ ์œ ์ €์ƒํƒœ ๋ณ€ํ•˜๋Š” ๊ฒŒ ๋ณด์ธ๋‹ค? -> ssr๊ณ ๋ คํ•˜๊ธฐ? ํ•˜


*/

return user ? (
<UserDropdown userImage={user.image} />
) : (
Expand Down
7 changes: 5 additions & 2 deletions src/components/common/card/ReviewCard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Image from 'next/image';

import ShowMoreBtn from '@/assets/icons/showMoreBtn.svg';
import Star from '@/assets/icons/star.svg';
import { Badge } from '@/components/ui/badge';
Expand Down Expand Up @@ -30,13 +32,14 @@ export function ReviewCard({ children }: ReviewCardProps) {

ReviewCard.UserHeader = function UserHeader({ userIcon, reviewId, children }: UserHeaderProps) {
const username = useReviewCardStore((state) => state.allReviews[reviewId]?.user.nickname);
const userImg = useReviewCardStore((state) => state.allReviews[reviewId]?.user.image);
const timeAgo = useReviewCardStore((state) => state.allReviews[reviewId]?.updatedAt);

return (
<div className='flex justify-between items-start'>
<div className='flex items-center gap-4'>
<div className='w-10 h-10 md:w-16 md:h-16 rounded-full bg-gray-200 overflow-hidden'>
{userIcon}
<div className='relative w-10 h-10 md:w-16 md:h-16 rounded-full bg-gray-200 overflow-hidden'>
{userImg ? <Image fill src={userImg} alt='์œ ์ € ํ”„๋กœํ•„' /> : userIcon}
</div>
<div className='flex flex-col'>
<span className='custom-text-lg-semibold text-gray-900'>{username}</span>
Expand Down
23 changes: 10 additions & 13 deletions src/components/wineDetail/Kebab.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useState } from 'react';

import { toast } from 'sonner';

import KebabIcon from '@/assets/icons/kebab.svg';
import { Button } from '@/components/ui/button';
import { useUser } from '@/hooks/useUser';
import useReviewCardStore from '@/stores/reviewCardStore';
import useWineStore from '@/stores/wineStore';

import MenuDropdown from '../common/dropdown/MenuDropdown';
import ErrorModal from '../common/Modal/ErrorModal';
import DeleteModal from '../Modal/DeleteModal/DeleteModal';
import EditReviewModal from '../Modal/ReviewModal/EditReviewModal';

Expand All @@ -20,21 +21,26 @@ function Kebab({ reviewId }: Props) {
const reviewData = useReviewCardStore((state) => state.allReviews[reviewId]);
const [openEditModal, setOepnEditModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [openAlertModal, setOpenAlertModal] = useState(false);

const { user } = useUser();

function onSelect(value: string) {
switch (value) {
case 'update': {
if (user?.id !== reviewData.user.id) setOpenAlertModal(true);
if (user?.id !== reviewData.user.id)
toast.error('', {
description: '๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.',
});
else {
setOepnEditModal(true);
}
break;
}
case 'delete': {
if (user?.id !== reviewData.user.id) setOpenAlertModal(true);
if (user?.id !== reviewData.user.id)
toast.error('', {
description: '๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.',
});
Comment on lines +31 to +43
Copy link
Collaborator

Choose a reason for hiding this comment

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

ํ† ์ŠคํŠธ ์—ฐ๊ฒฐํ•˜์‹  ๋ถ€๋ถ„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค!

else {
setOpenDeleteModal(true);
}
Expand Down Expand Up @@ -76,15 +82,6 @@ function Kebab({ reviewId }: Props) {
setShowDeleteModal={setOpenDeleteModal}
/>
)}
{openAlertModal && (
<ErrorModal
open={openAlertModal}
onOpenChange={() => {}}
onConfirm={() => setOpenAlertModal(false)}
>
<div className='custom-text-lg-bold'>๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.</div>
</ErrorModal>
)}
</>
);
}
Expand Down
20 changes: 5 additions & 15 deletions src/components/wineDetail/LikeButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useState } from 'react';

import { toast } from 'sonner';

import { postLike, deleteLike } from '@/api/handleLikeRequest';
import FullLikeIcon from '@/assets/icons/fullLike.svg';
import LikeIcon from '@/assets/icons/like.svg';
Expand All @@ -8,16 +10,13 @@ import { useUser } from '@/hooks/useUser';
import { cn } from '@/lib/utils';
import useReviewCardStore from '@/stores/reviewCardStore';

import ErrorModal from '../common/Modal/ErrorModal';

interface Props {
isLike?: boolean;
reviewId: number;
}

function LikeButton({ isLike, reviewId }: Props) {
const [isClicked, setIsClicked] = useState(isLike);
const [openAlertModal, setOpenAlertModal] = useState(false);

const { user } = useUser();
const id = useReviewCardStore((state) => state.allReviews[reviewId]?.user.id);
Expand All @@ -31,7 +30,9 @@ function LikeButton({ isLike, reviewId }: Props) {
setIsClicked((prev) => !prev); //์‹คํŒจํ•˜๋ฉด ์—…๋ฐ์ดํŠธ ํ–ˆ๋˜ ๊ฑฐ ์ทจ์†Œ
}
} else {
setOpenAlertModal(true);
toast.error('', {
description: '๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์—๋Š” ์ข‹์•„์š”๋ฅผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.',
});
} //๋ฏธ๋ฆฌ ์—…๋ฐ์ดํŠธ
}
return (
Expand All @@ -46,17 +47,6 @@ function LikeButton({ isLike, reviewId }: Props) {
>
{isClicked ? <FullLikeIcon /> : <LikeIcon />}
</Button>
{openAlertModal && (
<ErrorModal
open={openAlertModal}
onOpenChange={() => {}}
onConfirm={() => setOpenAlertModal(false)}
>
<div className='custom-text-lg-bold'>
๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์—๋Š” ์ข‹์•„์š”๋ฅผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.{' '}
</div>
</ErrorModal>
)}
</>
);
}
Expand Down
10 changes: 3 additions & 7 deletions src/pages/wines/[wineid].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { GetWineInfoResponse } from '@/types/WineTypes';
interface WinePageProps {
wineData?: GetWineInfoResponse; // getWineInfo๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” WineInfo ํƒ€์ž…์„ ์‚ฌ์šฉ
error?: string;
dehydratedState: any;
dehydratedState?: any;
parsedWineId: number;
}

Expand All @@ -31,7 +31,7 @@ export default function WineInfoById(props: WinePageProps) {
const setNowWine = useWineStore((state) => state.setNowWine);

//์„œ๋ฒ„๋“  ๋ชฉ๋ก(ํด๋ผ์ด์–ธํŠธ๋“ ) ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ
const { data, isLoading } = useQuery({
const { data } = useQuery({
queryKey: ['wineDetail', parsedWineId],
queryFn: () => getWineInfoForClient(parsedWineId),
staleTime: 1000 * 60 * 5,
Expand All @@ -42,10 +42,8 @@ export default function WineInfoById(props: WinePageProps) {
if (data) setNowWine(data);
}, [data]);

if (isLoading) return <div className='w-300 bg-red-400 h-20'>123</div>; //ํ…Œ์ŠคํŠธ์šฉ

if (!data) {
throw new Error('์กด์žฌํ•˜์ง€ ์•Š๋Š” ์™€์ธ์ž…๋‹ˆ๋‹ค.');
return;
}

return (
Expand Down Expand Up @@ -90,7 +88,6 @@ export const getServerSideProps: GetServerSideProps<WinePageProps> = async (cont
await queryClient.prefetchQuery({
queryKey: ['wineDetail', parsedWineId],
queryFn: async () => {
//์ถ”ํ›„ ๋ฐฐํฌ์šฉ ์ฃผ์†Œ๋กœ ๋ณ€๊ฒฝ
const res = await axios.get(
`${process.env.NEXT_PUBLIC_API_URL}/api/wines/${parsedWineId}`,
{
Expand All @@ -109,7 +106,6 @@ export const getServerSideProps: GetServerSideProps<WinePageProps> = async (cont
console.error(`[SSR] ์™€์ธ ์ƒ์„ธ ์ •๋ณด ๋กœ๋”ฉ ์ค‘ ์ตœ์ข… ์—๋Ÿฌ:`, error.message || error);
}

// prefetchํ•œ queryClient์˜ ์บ์‹œ๋ฅผ ์ง๋ ฌํ™”, ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌ.
return {
props: {
dehydratedState: dehydrate(queryClient),
Expand Down