diff --git a/src/components/roomdetail/ReviewModal.tsx b/src/components/roomdetail/ReviewModal.tsx index e2e3af2..cec4a56 100644 --- a/src/components/roomdetail/ReviewModal.tsx +++ b/src/components/roomdetail/ReviewModal.tsx @@ -54,7 +54,9 @@ const ReviewModal = ({ onClose, data }: ReviewProps) => { alt="왼쪽 월계수" className="w-16 h-24" /> -

4.92

+

+ {data.averageRating} +

오른쪽 월계수 { setIsLoading(true); setError(null); - const url = `/api/v1/reservations/availability/${id}?year=${currentYear}&month=${currentMonth.month() + 1}`; - - const response = await fetch(url, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { + const currentMonthRequest = `/api/v1/reservations/availability/${id}?year=${currentYear}&month=${currentMonth.month() + 1}`; + const nextMonthRequest = `/api/v1/reservations/availability/${id}?year=${currentYear}&month=${currentMonth.add(1, 'month').month() + 1}`; + + const [currentMonthResponse, nextMonthResponse] = await Promise.all([ + fetch(currentMonthRequest, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }), + fetch(nextMonthRequest, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + }), + ]); + + if (!currentMonthResponse.ok || !nextMonthResponse.ok) { throw new Error('숙소 예약 가능 날짜 로딩에 실패했습니다.'); } - const responseData = (await response.json()) as AvailabilityResponse; - console.debug(responseData); - setAvailableDates(responseData.availableDates); + const currentMonthData = + (await currentMonthResponse.json()) as AvailabilityResponse; + const nextMonthData = + (await nextMonthResponse.json()) as AvailabilityResponse; + + setAvailableDates([ + ...currentMonthData.availableDates, + ...nextMonthData.availableDates, + ]); } catch (err) { const errorMessage = err instanceof Error ? err.message : '오류가 발생했습니다.'; diff --git a/src/components/user/MyReviewItems.tsx b/src/components/user/MyReviewItems.tsx index c8fe846..5e6b5c1 100644 --- a/src/components/user/MyReviewItems.tsx +++ b/src/components/user/MyReviewItems.tsx @@ -98,7 +98,6 @@ const MyReviewItems = () => { const handleDeleteReview = async (reviewId: number) => { try { await axiosInstance.delete(`/api/v1/reviews/${reviewId}`); - // 삭제된 리뷰를 상태에서 제거 setReviews((prevReviews) => prevReviews.filter((review) => review.reviewId !== reviewId), ); diff --git a/src/components/user/ReservationUpdateModal.tsx b/src/components/user/ReservationUpdateModal.tsx index 08c15cd..6efab95 100644 --- a/src/components/user/ReservationUpdateModal.tsx +++ b/src/components/user/ReservationUpdateModal.tsx @@ -6,9 +6,11 @@ import { useNavigate } from 'react-router-dom'; import BaseModal from '@/components/common/Modal/BaseModal'; import { useSearch } from '@/components/home/context/SearchContext'; -import CalendarModal from '@/components/home/Topbar/SearchBar/modals/CalendarModal'; + +import RoomCalendarModal from '../roomdetail/roomCalendarModal'; type ReservationUpdateModalProps = { + roomId: number; reservationId: string; onClose: () => void; startDate: string; @@ -17,6 +19,7 @@ type ReservationUpdateModalProps = { }; const ReservationUpdateModal: React.FC = ({ + roomId, reservationId, onClose, startDate, @@ -34,17 +37,37 @@ const ReservationUpdateModal: React.FC = ({ } = useSearch(); const [error, setError] = useState(null); const [guests, setGuests] = useState(numberOfGuests); + const [maxOccupancy, setMaxOccupancy] = useState(null); useEffect(() => { setCheckIn(new Date(startDate)); setCheckOut(new Date(endDate)); setGuests(numberOfGuests); - }, [startDate, endDate, numberOfGuests, setCheckIn, setCheckOut]); + + const fetchMaxOccupancy = async () => { + try { + const response = await axios.get<{ maxOccupancy: number }>( + `/api/v1/rooms/main/${roomId}`, + ); + setMaxOccupancy(response.data.maxOccupancy); + } catch (err) { + console.error('최대 숙박 인원 정보를 불러오는 데 실패했습니다.', err); + setError('최대 숙박 인원 정보를 불러오는 데 실패했습니다.'); + } + }; + + void fetchMaxOccupancy(); + }, [roomId, startDate, endDate, numberOfGuests, setCheckIn, setCheckOut]); const navigate = useNavigate(); const handleGuestChange = (delta: number) => { - setGuests((prev) => Math.max(1, prev + delta)); + setGuests((prev) => { + if (delta > 0 && maxOccupancy !== null && prev >= maxOccupancy) { + return prev; + } + return Math.max(1, prev + delta); + }); }; const handleUpdateReservation = async () => { @@ -166,7 +189,10 @@ const ReservationUpdateModal: React.FC = ({ onClick={() => { handleGuestChange(1); }} - className="w-8 h-8 rounded-full border border-gray-400 text-gray-400 hover:border-gray-700 hover:text-gray-700 flex items-center justify-center" + disabled={maxOccupancy !== null && guests >= maxOccupancy} + className={`w-8 h-8 rounded-full border flex items-center justify-center + ${maxOccupancy !== null && guests >= maxOccupancy ? 'border-gray-300 text-gray-300 cursor-not-allowed' : 'border-gray-400 text-gray-400 hover:border-gray-700 hover:text-gray-700'} + `} > + @@ -191,7 +217,7 @@ const ReservationUpdateModal: React.FC = ({ onClose={closeModal} title="날짜 선택" > - + diff --git a/src/components/user/profile/OtherUserProfile.tsx b/src/components/user/profile/OtherUserProfile.tsx index ded764b..8a98bde 100644 --- a/src/components/user/profile/OtherUserProfile.tsx +++ b/src/components/user/profile/OtherUserProfile.tsx @@ -2,6 +2,7 @@ import axios from 'axios'; import { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; +import PastReservations from './PastReservations'; import ProfileHeader from './ProfileHeader'; type ProfileInfo = { @@ -70,6 +71,15 @@ const OtherUserProfile = () => {

{profile.bio}


+ + {/* 방문한 여행지 */} +
+

+ {profile.nickname} 님이 지금까지 가 본 여행지 +

+ +
+
); }; diff --git a/src/components/user/profile/PastReservations.tsx b/src/components/user/profile/PastReservations.tsx index 0d68478..4a8ca86 100644 --- a/src/components/user/profile/PastReservations.tsx +++ b/src/components/user/profile/PastReservations.tsx @@ -14,10 +14,9 @@ type Reservation = { type PastReservationsProps = { userId: number; - navigate: (path: string) => void; }; -const PastReservations = ({ userId, navigate }: PastReservationsProps) => { +const PastReservations = ({ userId }: PastReservationsProps) => { const [reservations, setReservations] = useState([]); const [error, setError] = useState(''); @@ -59,9 +58,6 @@ const PastReservations = ({ userId, navigate }: PastReservationsProps) => {
{ - navigate(`/reservations/${reservation.reservationId}`); - }} >

{reservation.place} diff --git a/src/components/user/profile/Profile.tsx b/src/components/user/profile/Profile.tsx index 239beb2..c9b0c11 100644 --- a/src/components/user/profile/Profile.tsx +++ b/src/components/user/profile/Profile.tsx @@ -123,10 +123,7 @@ const UserProfile = () => {

{profile.nickname} 님이 지금까지 가 본 여행지

- void navigate(path)} - /> +
{/* 리뷰 */} diff --git a/src/routes/ReservationDetails.tsx b/src/routes/ReservationDetails.tsx index c630d85..bc0615b 100644 --- a/src/routes/ReservationDetails.tsx +++ b/src/routes/ReservationDetails.tsx @@ -152,6 +152,7 @@ const ReservationDetails = () => { {isUpdateModalOpen && reservation !== null && (