diff --git a/src/app/(with-header)/myprofile/_components/MyProfile.tsx b/src/app/(with-header)/myprofile/_components/MyProfile.tsx index 232092a..001f780 100644 --- a/src/app/(with-header)/myprofile/_components/MyProfile.tsx +++ b/src/app/(with-header)/myprofile/_components/MyProfile.tsx @@ -121,7 +121,8 @@ export function MyProfile({ profileData, upLoadImgFile, upLoadUserData }: MuProf )} diff --git a/src/app/(with-header)/myprofile/_components/MyProfileContainer.tsx b/src/app/(with-header)/myprofile/_components/MyProfileContainer.tsx index 3316523..285bef5 100644 --- a/src/app/(with-header)/myprofile/_components/MyProfileContainer.tsx +++ b/src/app/(with-header)/myprofile/_components/MyProfileContainer.tsx @@ -3,12 +3,15 @@ import { useEffect, useState } from 'react'; import { fetchWithAuth } from '@/lib/auth'; import { MyProfile, MyProfileData } from './MyProfile'; +import LoadingSpinner from '@/components/LoadingSpinner'; export default function MyProfileContainer() { const [profileData, setProfileData] = useState(); + const [isLoading, setIsLoading] = useState(true); const getUserData = async () => { try { + setIsLoading(true); const response = await fetchWithAuth(`${process.env.NEXT_PUBLIC_BASE_URL}/users/me`); if (!response?.ok || response === null) { @@ -19,6 +22,8 @@ export default function MyProfileContainer() { setProfileData(data); } catch (error) { console.error('유저 정보를 불러오는 중 문제가 발생했습니다:', error); + } finally { + setIsLoading(false); } }; @@ -71,6 +76,8 @@ export default function MyProfileContainer() { getUserData(); }, []); + if (isLoading) return ; + if (!profileData) return ; return ; diff --git a/src/app/(with-header)/myprofile/_components/MyReviewItem.tsx b/src/app/(with-header)/myprofile/_components/MyReviewItem.tsx index 1488063..cb182d0 100644 --- a/src/app/(with-header)/myprofile/_components/MyReviewItem.tsx +++ b/src/app/(with-header)/myprofile/_components/MyReviewItem.tsx @@ -5,26 +5,27 @@ import like from '@/assets/icons/star_hover.svg'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; import MyReviewKebabDropDown from './MyReviewKebabDropDown'; +import { MyReview } from '@/types/review-data'; +import { EditReviewData } from './MyReviewListContainer'; -interface MyReviewProps { - wineId: number; - id: number; - rating: number; - createdAt: string; - wineName: string; - content: string; -} - -export function MyReviewItem({ wineId, id, rating, createdAt, wineName, content }: MyReviewProps) { +export function MyReviewItem({ + reviewInitialData, + editMyReview, + deleteMyReview, +}: { + reviewInitialData: MyReview; + editMyReview: (id: number, editReviewData: EditReviewData, updatedAt: string) => void; + deleteMyReview: (id: number) => void; +}) { const router = useRouter(); - const reviewElapsedTime = elapsedTime(createdAt); + const reviewElapsedTime = elapsedTime(reviewInitialData.updatedAt); const onClickReviewItem = (event: React.MouseEvent) => { if ((event.target as HTMLElement).closest('.ignore-click')) { event.stopPropagation(); return; } - router.push(`/wines/${wineId}`); + router.push(`/wines/${reviewInitialData.wine.id}`); }; return ( @@ -33,14 +34,14 @@ export function MyReviewItem({ wineId, id, rating, createdAt, wineName, content - {rating.toFixed(1)} + {reviewInitialData.rating.toFixed(1)} - + {reviewElapsedTime} - {wineName} - {content} + {reviewInitialData.wine.name} + {reviewInitialData.content} diff --git a/src/app/(with-header)/myprofile/_components/MyReviewKebabDropDown.tsx b/src/app/(with-header)/myprofile/_components/MyReviewKebabDropDown.tsx index 32ac2c4..00a0aa3 100644 --- a/src/app/(with-header)/myprofile/_components/MyReviewKebabDropDown.tsx +++ b/src/app/(with-header)/myprofile/_components/MyReviewKebabDropDown.tsx @@ -8,8 +8,20 @@ import Modal from '@/components/modal/Modal'; import DeleteWineForm from '@/components/modal/DeleteWineModal'; import { fetchWithAuth } from '@/lib/auth'; import PatchReviewForm from '@/components/modal/PatchReviewForm'; +import { MyReview } from '@/types/review-data'; +import { EditReviewData } from './MyReviewListContainer'; -export default function MyReviewKebabDropDown({ wineName, id }: { wineName: string; id: number }) { +export default function MyReviewKebabDropDown({ + reviewInitialData, + id, + editMyReview, + deleteMyReview, +}: { + reviewInitialData: MyReview; + id: number; + editMyReview: (id: number, editReviewData: EditReviewData, updatedAt: string) => void; + deleteMyReview: (id: number) => void; +}) { const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); @@ -38,9 +50,6 @@ export default function MyReviewKebabDropDown({ wineName, id }: { wineName: stri try { const response = await fetchWithAuth(`${process.env.NEXT_PUBLIC_BASE_URL}/reviews/${id}`, { method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, }); if (!response?.ok || response === null) { @@ -49,6 +58,9 @@ export default function MyReviewKebabDropDown({ wineName, id }: { wineName: stri const body = await response.json(); if (body) { + if (deleteMyReview) { + deleteMyReview(id); + } closeDeleteModal(); } } catch (error) { @@ -73,7 +85,7 @@ export default function MyReviewKebabDropDown({ wineName, id }: { wineName: stri isEditModalOpen ? 'mobile:translate-y-0 mobile:animate-slide-up' : 'mobile:animate-slide-down mobile:translate-y-full' }`} > - + diff --git a/src/app/(with-header)/myprofile/_components/MyReviewListContainer.tsx b/src/app/(with-header)/myprofile/_components/MyReviewListContainer.tsx index 640f6eb..2517711 100644 --- a/src/app/(with-header)/myprofile/_components/MyReviewListContainer.tsx +++ b/src/app/(with-header)/myprofile/_components/MyReviewListContainer.tsx @@ -6,6 +6,18 @@ import { fetchWithAuth } from '@/lib/auth'; import emptyData from '@/assets/icons/empty_review.svg'; import { MyReview, MyReviewResponse } from '@/types/review-data'; import { MyReviewItem } from './MyReviewItem'; +import LoadingSpinner from '@/components/LoadingSpinner'; + +export interface EditReviewData { + rating: number; + lightBold: number; + smoothTannic: number; + drySweet: number; + softAcidic: number; + aroma: string[]; + content: string; + wineId: number; +} export default function MyReviewListContainer({ setDataCount }: { setDataCount: (value: number) => void }) { const [myReviewData, setMyReviewData] = useState([]); @@ -30,11 +42,26 @@ export default function MyReviewListContainer({ setDataCount }: { setDataCount: } }, [setDataCount]); + const deleteMyReview = (id: number) => { + const updatedReviewList = myReviewData.filter((value) => value.id !== id); + setMyReviewData(updatedReviewList); + }; + + const editMyReview = (id: number, editReviewData: EditReviewData, updatedAt: string) => { + const updatedReviewList = myReviewData.map((value) => { + if (value.id === id) { + return { ...value, ...editReviewData, updatedAt: updatedAt }; + } + return value; + }); + setMyReviewData(updatedReviewList); + }; + useEffect(() => { getMyReview(); }, [getMyReview]); - if (isLoading) return ; + if (isLoading) return ; if (myReviewData.length === 0) return ( @@ -47,7 +74,7 @@ export default function MyReviewListContainer({ setDataCount }: { setDataCount: return ( {myReviewData.map((value) => ( - + ))} ); diff --git a/src/app/(with-header)/myprofile/_components/MyWineListContainer.tsx b/src/app/(with-header)/myprofile/_components/MyWineListContainer.tsx index 5696b2a..fd0dd41 100644 --- a/src/app/(with-header)/myprofile/_components/MyWineListContainer.tsx +++ b/src/app/(with-header)/myprofile/_components/MyWineListContainer.tsx @@ -7,6 +7,7 @@ import { MyWineListResponse, WineDetails } from '@/types/wine'; import emptyData from '@/assets/icons/empty_review.svg'; import WineCard from '@/components/WineCard'; import { WineDataProps } from './MyWIneKebabDropDown '; +import LoadingSpinner from '@/components/LoadingSpinner'; export default function MyWineListContainer({ setDataCount }: { setDataCount: (value: number) => void }) { const [myWineData, setMyWineData] = useState([]); @@ -32,8 +33,8 @@ export default function MyWineListContainer({ setDataCount }: { setDataCount: (v }, [setDataCount]); const deleteMyWine = (id: number) => { - const updatedReviewList = myWineData.filter((value) => value.id !== id); - setMyWineData(updatedReviewList); + const updatedWineList = myWineData.filter((value) => value.id !== id); + setMyWineData(updatedWineList); }; const editMyWine = (id: number, editWineData: WineDataProps) => { @@ -50,7 +51,7 @@ export default function MyWineListContainer({ setDataCount }: { setDataCount: (v getMyWine(); }, [getMyWine]); - if (isLoading) return ; + if (isLoading) return ; if (myWineData.length === 0) return ( diff --git a/src/app/(with-header)/myprofile/page.tsx b/src/app/(with-header)/myprofile/page.tsx index 80270ff..841c684 100644 --- a/src/app/(with-header)/myprofile/page.tsx +++ b/src/app/(with-header)/myprofile/page.tsx @@ -17,7 +17,7 @@ export default function Page() { else if (category === '내가 등록한 와인') return ; } - const selectClassName = 'cursor-pointer text-xl font-bold text-gray-800 transition-all duration-300 hover:text-purple-100'; + const selectClassName = 'cursor-pointer text-xl font-bold text-purple-100 transition-all duration-300 hover:text-purple-100'; const unSelectClassName = 'duration-300 cursor-pointer text-xl font-bold text-gray-500 transition-all hover:text-purple-100';
{content}
{reviewInitialData.content}