Skip to content
5 changes: 5 additions & 0 deletions src/components/Modal/DeleteModal/DeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { toast } from 'sonner';

import { deleteReview, deleteWine, DeleteResponse } from '@/api/delete';
import BasicBottomSheet from '@/components/common/BottomSheet/BasicBottomSheet';
Expand Down Expand Up @@ -32,10 +33,12 @@ const DeleteModal = ({ type, id, showDeleteModal, setShowDeleteModal }: DeleteMo
deleteWineMutation.mutate(id, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['wines'] }); //삭제후 관련데이터 바로 갱신
toast.success('와인이 성공적으로 삭제되었습니다.');
console.log('와인 삭제 성공');
setShowDeleteModal(false);
},
onError: (error) => {
toast.error('와인 삭제가 실패하였습니다.');
console.error('와인 삭제 실패', error);
},
});
Expand All @@ -44,10 +47,12 @@ const DeleteModal = ({ type, id, showDeleteModal, setShowDeleteModal }: DeleteMo
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['reviews'] });
queryClient.invalidateQueries({ queryKey: ['wineDetail'] });
toast.success('리뷰가 성공적으로 삭제되었습니다.');
console.log('리뷰 삭제 성공');
setShowDeleteModal(false);
},
onError: (error) => {
toast.error('리뷰 삭제가 실패하였습니다.');
console.error('리뷰 삭제 실패', error);
},
});
Expand Down
13 changes: 8 additions & 5 deletions src/components/Modal/ReviewModal/AddReviewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import Image from 'next/image';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';

import { postReview } from '@/api/addreview';
import BasicBottomSheet from '@/components/common/BottomSheet/BasicBottomSheet';
Expand Down Expand Up @@ -114,13 +115,15 @@ const AddReviewModal = ({ wineId, wineName }: { wineId: number; wineName: string
//mutation function
mutationFn: postReview, //실제 서버에 리뷰를 보내는 역할
onSuccess: (data) => {
toast.success('리뷰가 성공적으로 등록되었습니다.');
console.log('리뷰 등록 성공', data);
queryClient.invalidateQueries({ queryKey: ['reviews'] });
queryClient.invalidateQueries({ queryKey: ['wineDetail'] });
reset();
setShowRegisterModal(false);
},
onError: (error) => {
toast.error('리뷰 등록이 실패하였습니다.');
console.log('리뷰 등록 실패', error);
},
});
Expand Down Expand Up @@ -213,14 +216,14 @@ const AddReviewModal = ({ wineId, wineName }: { wineId: number; wineName: string
})}
placeholder='후기를 작성해 주세요'
className={cn(
'relative h-[100px] md:h-[120px] custom-text-md-regular md:custom-text-lg-regular w-full px-[20px] py-[14px] rounded-[16px] bg-white border border-gray-300 outline-none active:border-gray-500 focus:border-gray-500 font-sans resize-none',
'h-[100px] md:h-[120px] w-full px-[20px] py-[14px] rounded-[16px] bg-white border border-gray-300 outline-none font-sans resize-none',
errors.content && 'border-red-500',
)}
rows={5}
/>
{errors.content && (
<div role='alert' className='absolute text-red-500 mt-[4px]'>
<p>{errors.content.message}</p>
<div role='alert' className='relative'>
<p className='absolute text-red-500 mt-1'>{errors.content.message}</p>
</div>
)}
<p className='custom-text-2lg-bold md:custom-text-xl-bold mb-[24px] mt-[35px]'>
Expand Down Expand Up @@ -279,8 +282,8 @@ const AddReviewModal = ({ wineId, wineName }: { wineId: number; wineName: string
</div>
<p className='custom-text-2lg-bold md:custom-text-xl-bold'>기억에 남는 향이 있나요?</p>
{errors.aroma && (
<div role='alert' className='absolute text-red-500'>
{errors.aroma.message}
<div role='alert' className='relative'>
<p className='absolute text-red-500'>{errors.aroma.message}</p>
</div>
)}
<div className='relative flex flex-wrap gap-[10px] mt-6'>
Expand Down
13 changes: 8 additions & 5 deletions src/components/Modal/ReviewModal/EditReviewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import Image from 'next/image';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';

import { updateReview } from '@/api/editreview';
import BasicBottomSheet from '@/components/common/BottomSheet/BasicBottomSheet';
Expand Down Expand Up @@ -98,12 +99,14 @@ const EditReviewModal = ({
mutationFn: updateReview,
throwOnError: true,
onSuccess: () => {
toast.success('리뷰가 성공적으로 수정되었습니다.');
console.log('리뷰 수정 완료');
queryClient.invalidateQueries({ queryKey: ['reviews'] });
queryClient.invalidateQueries({ queryKey: ['wineDetail'] });
setShowEditModal(false);
},
onError: (error) => {
toast.error('리뷰 수정이 실패하였습니다.');
console.log('리뷰 수정 실패', error);
},
});
Expand Down Expand Up @@ -190,7 +193,7 @@ const EditReviewModal = ({
<form
onSubmit={handleSubmit(onSubmit)}
encType='multipart/form-data'
className='my-[32px] md:my-[40px]'
className='my-[32px] md:my-[40px] px-2'
>
<div className='w-[274px] md:w-[384px] h-[84px] md:h-[68px] mb-6 flex items-center'>
<Image
Expand Down Expand Up @@ -222,8 +225,8 @@ const EditReviewModal = ({
rows={5}
/>
{errors.content && (
<div role='alert' className='text-red-500 mt-1'>
{errors.content.message}
<div role='alert' className='relative'>
<p className='absolute text-red-500 mt-1'>{errors.content.message}</p>
</div>
)}

Expand Down Expand Up @@ -276,8 +279,8 @@ const EditReviewModal = ({

<p className='custom-text-2lg-bold md:custom-text-xl-bold'>기억에 남는 향이 있나요?</p>
{errors.aroma && (
<div role='alert' className='text-red-500 mt-1'>
{errors.aroma.message}
<div role='alert' className='relative'>
<p className='absolute text-red-500'>{errors.aroma.message}</p>
</div>
)}
<div className='relative flex flex-wrap gap-[10px] mt-6'>
Expand Down
14 changes: 12 additions & 2 deletions src/components/Modal/WineModal/AddWineModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import React, { useRef, useState } from 'react';

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';

import { uploadImage, postWine, PostWineRequest } from '@/api/addwine';
import CameraIcon from '@/assets/camera.svg';
import DropdownIcon from '@/assets/dropdowntriangle.svg';
import BasicBottomSheet from '@/components/common/BottomSheet/BasicBottomSheet';
import { useMediaQuery } from '@/hooks/useMediaQuery';
import { renameFileIfNeeded } from '@/lib/renameFile';

import SelectDropdown from '../../common/dropdown/SelectDropdown';
import Input from '../../common/Input';
Expand Down Expand Up @@ -41,7 +43,8 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
const imageUrl = URL.createObjectURL(file);
const renamedFile = renameFileIfNeeded(file); //이미지파일 이름 정규화
const imageUrl = URL.createObjectURL(renamedFile);
setPreviewImage(imageUrl);
} else {
setPreviewImage(null);
Expand Down Expand Up @@ -89,18 +92,25 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
const postWineMutation = useMutation({
mutationFn: handlePostWine,
onSuccess: () => {
toast.success('와인이 성공적으로 등록되었습니다.');
console.log('와인 등록 성공');
resetForm();
setShowRegisterModal(false);
queryClient.invalidateQueries({ queryKey: ['wines'] });
},
onError: (error) => {
toast.error('와인 등록이 실패하였습니다.');
console.log('와인 등록 실패', error);
},
});

const onSubmit = async (form: WineForm) => {
postWineMutation.mutate(form);
let file = form.wineImage[0];
file = renameFileIfNeeded(file); //이미지파일 이름 정규화
postWineMutation.mutate({
...form,
wineImage: [file] as unknown as FileList,
});
};

const categoryOptions = [
Expand Down
12 changes: 9 additions & 3 deletions src/components/Modal/WineModal/EditWineModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useRef, useState } from 'react';

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';

import { updateWine, uploadImage } from '@/api/editwine';
import BasicBottomSheet from '@/components/common/BottomSheet/BasicBottomSheet';
Expand All @@ -10,6 +11,7 @@ import Input from '@/components/common/Input';
import BasicModal from '@/components/common/Modal/BasicModal';
import { Button } from '@/components/ui/button';
import { useMediaQuery } from '@/hooks/useMediaQuery';
import { renameFileIfNeeded } from '@/lib/renameFile';

interface WineForm {
wineName: string;
Expand Down Expand Up @@ -77,13 +79,15 @@ const EditWineModal = ({ wine, showEditModal, setShowEditModal }: EditWineModalP
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
setPreviewImage(URL.createObjectURL(file));
const renamedFile = renameFileIfNeeded(file);
setPreviewImage(URL.createObjectURL(renamedFile));
}
};

const updateWineMutation = useMutation({
mutationFn: updateWine,
onSuccess: () => {
toast.success('와인이 성공적으로 수정되었습니다.');
console.log('와인수정완료');
queryClient.invalidateQueries({ queryKey: ['wines'] });
reset({
Expand All @@ -96,17 +100,19 @@ const EditWineModal = ({ wine, showEditModal, setShowEditModal }: EditWineModalP
setShowEditModal(false);
},
onError: (error) => {
toast.error('와인 수정이 실패하였습니다.');
console.log('와인수정실패', error);
},
});

const onSubmit = async (form: WineForm) => {
try {
const file = form.wineImage?.[0];
let imageUrl = file ? await uploadImage(file) : wine.image;
let imageUrl = wine.image;

if (file) {
const uploaded = await uploadImage(file);
const renamedFile = renameFileIfNeeded(file); //이미지파일 이름 정규화
const uploaded = await uploadImage(renamedFile);
imageUrl = uploaded + `?t=${Date.now()}`; // 캐시 방지
setPreviewImage(imageUrl); // 이미지 갱신
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/BottomSheet/BasicBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ const BasicBottomSheet = ({
</DrawerHeader>
)}

<div className='px-4 py-2'>{children}</div>
<div className='px-4 py-2 px-4 py-2 max-h-[60vh] overflow-y-auto'>{children}</div>

{buttons && (
<DrawerFooter className='flex flex-col gap-2 px-4 pb-4'>{buttons}</DrawerFooter>
<DrawerFooter className='flex flex-col gap-2 px-4 pb-4 '>{buttons}</DrawerFooter>
)}
</DrawerContent>
</Drawer>
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const Modal = ({ open, onOpenChange, showCloseButton = true, children, className
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
className={cn(
'flex flex-col rounded-xl max-h-[95vh] [&>button:last-child]:hidden focus:outline-none focus:border-none',
'flex flex-col rounded-xl max-h-[95vh] [&>button:last-child]:hidden',
className,
)}
>
Expand Down