Skip to content

Commit

Permalink
RoomCalendarModal api 연결/RoomGuestsModal 생성
Browse files Browse the repository at this point in the history
  • Loading branch information
ihnsy committed Jan 18, 2025
1 parent 32d3814 commit 0d09386
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 62 deletions.
8 changes: 7 additions & 1 deletion src/components/home/context/SearchContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import type { ReactNode } from 'react';
import { createContext, useContext, useState } from 'react';

type ModalType = 'location' | 'calendar' | 'guests' | null;
type ModalType =
| 'location'
| 'calendar'
| 'guests'
| 'roomCalendar'
| 'roomGuests'
| null;

type Location = {
sido: string;
Expand Down
5 changes: 1 addition & 4 deletions src/components/roomdetail/HeartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@ const ShareModal = ({ onClose }: HeartModalProps) => {
</div>
<div className="grid grid-cols-2 gap-2 px-2">
{mockHeart.map((list) => (
<div
className="flex flex-col items-start p-2"
key={list.name}
>
<div className="flex flex-col items-start p-2" key={list.name}>
<PhotoSizeSelectActualIcon className="text-white bg-gray-300 w-full h-[200px] rounded-md shadow-md" />
<p className="mt-2 text-base font-bold">{list.name}</p>
<p className="text-gray-500 text-sm">
Expand Down
25 changes: 5 additions & 20 deletions src/components/roomdetail/Info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,44 +93,29 @@ const Info = ({ data }: InfoProps) => {
)}
</div>
<div className="col-span-1 row-span-1 flex gap-2 items-center px-4">
<img
src={superhost}
className="h-6 w-6 opacity-60"
/>
<img src={superhost} className="h-6 w-6 opacity-60" />
<div className="opacity-60 text-sm">
{issuperhost ? '슈퍼호스트' : '훌륭한 호스트'}
</div>
</div>
<div className="col-span-1 row-span-1 flex gap-2 items-center px-4">
<img
src={LuggageIcon}
className="h-6 w-6 opacity-60"
/>
<img src={LuggageIcon} className="h-6 w-6 opacity-60" />
<div className="opacity-60 text-sm">
{isluggage ? '여행 가방 보관 가능' : '여행 가방 보관 풀가'}
</div>
</div>
<div className="col-span-1 row-span-1 flex gap-2 items-center px-4">
<img
src={CheckinIcon}
className="h-6 w-6 opacity-60"
/>
<img src={CheckinIcon} className="h-6 w-6 opacity-60" />
<div className="opacity-60 text-sm">
{ischeckin ? '셀프체크인' : '편의성이 뛰어난 체크인 절차'}
</div>
</div>
<div className="col-span-1 row-span-1 flex gap-2 items-center px-4">
<img
src={TvIcon}
className="h-6 w-6 opacity-60"
/>
<img src={TvIcon} className="h-6 w-6 opacity-60" />
<div className="opacity-60 text-sm">{istv ? 'TV' : 'TV 없음'}</div>
</div>
<div className="col-span-1 row-span-1 flex gap-2 items-center px-4">
<img
src={WifiIcon}
className="h-6 w-6 opacity-60"
/>
<img src={WifiIcon} className="h-6 w-6 opacity-60" />
<div className="opacity-60 text-sm">
{iswifi ? '와이파이' : '와이파이 없음'}
</div>
Expand Down
41 changes: 26 additions & 15 deletions src/components/roomdetail/Reservation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useState } from 'react';

import BaseModal from '@/components/common/Modal/BaseModal';
import { useSearch } from '@/components/home/context/SearchContext';
import CalendarModal from '@/components/home/Topbar/Search/modals/CalendarModal';
import GuestsModal from '@/components/home/Topbar/Search/modals/GuestsModal';
import RoomCalendarModal from './roomCalendarModal';
import RoomGuestsModal from '@/components/roomdetail/RoomGuestsModal';
import clock from '@/assets/icons/reservation/clock.svg';
import type { roomType } from '@/types/roomType';

Expand All @@ -13,8 +13,8 @@ interface InfoProps {
}

type roomReservationResponseType = {
reservationId: number
}
reservationId: number;
};

const Reservation = ({ data }: InfoProps) => {
const [isLoading, setIsLoading] = useState(false);
Expand All @@ -31,8 +31,13 @@ const Reservation = ({ data }: InfoProps) => {
if (token == null) {
throw new Error('로그인이 필요합니다.');
}
console.debug(data)
if (data.roomId === 0 || checkIn == null || checkOut == null || guests <= 0) {
console.debug(data);
if (
data.roomId === 0 ||
checkIn == null ||
checkOut == null ||
guests <= 0
) {
throw new Error('모든 필드를 입력해주세요.');
}

Expand All @@ -57,8 +62,11 @@ const Reservation = ({ data }: InfoProps) => {
if (!response.ok) {
throw new Error('숙소 예약에 실패했습니다.');
}
const responseData = (await response.json()) as roomReservationResponseType;
alert(`숙소가 성공적으로 예약되었습니다! ID: ${responseData.reservationId}`);
const responseData =
(await response.json()) as roomReservationResponseType;
alert(
`숙소가 성공적으로 예약되었습니다! ID: ${responseData.reservationId}`,
);
} catch (err) {
const errorMessage =
err instanceof Error ? err.message : '오류가 발생했습니다.';
Expand All @@ -77,7 +85,7 @@ const Reservation = ({ data }: InfoProps) => {
<div className="w-full">
<button
onClick={() => {
openModal('calendar');
openModal('roomCalendar');
}}
className="flex flex-col items-start mt-1 w-full border border-red-700 rounded-md py-2 px-3 text-gray-700 bg-white cursor-pointer"
>
Expand All @@ -92,7 +100,7 @@ const Reservation = ({ data }: InfoProps) => {
<div className="w-full">
<button
onClick={() => {
openModal('calendar');
openModal('roomCalendar');
}}
className="flex flex-col items-start mt-1 w-full border border-red-700 rounded-md py-2 px-3 text-gray-700 bg-white cursor-pointer"
>
Expand All @@ -110,7 +118,7 @@ const Reservation = ({ data }: InfoProps) => {
<div className="my-4 w-full">
<button
onClick={() => {
openModal('guests');
openModal('roomGuests');
}}
className="flex flex-col items-start mt-1 w-full border border-gray-300 rounded-md py-2 px-3 bg-white cursor-pointer text-gray-700"
>
Expand Down Expand Up @@ -165,18 +173,21 @@ const Reservation = ({ data }: InfoProps) => {
</button>
</div>
<BaseModal
isOpen={currentModal === 'calendar'}
isOpen={currentModal === 'roomCalendar'}
onClose={closeModal}
title="날짜 선택"
>
<CalendarModal onClose={closeModal} />
<RoomCalendarModal id={data.roomId} onClose={closeModal} />
</BaseModal>
<BaseModal
isOpen={currentModal === 'guests'}
isOpen={currentModal === 'roomGuests'}
onClose={closeModal}
title="인원 선택"
>
<GuestsModal onClose={closeModal} />
<RoomGuestsModal
maxOccupancy={data.maxOccupancy}
onClose={closeModal}
/>
</BaseModal>
</>
);
Expand Down
27 changes: 17 additions & 10 deletions src/components/roomdetail/ReviewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import { useEffect, useState } from 'react';

import { CheckinIcon } from '@/components/common/constants/icons';
import accuracy from '@/assets/icons/reviews/clean.svg';
import accuracy from '@/assets/icons/reviews/accuracy.svg';
import clean from '@/assets/icons/reviews/clean.svg';
import type { ReviewsResponse } from '@/types/reviewType';
import type { roomType } from '@/types/roomType';
Expand Down Expand Up @@ -161,7 +161,9 @@ const ReviewModal = ({ onClose, data }: ReviewProps) => {
<div className="flex justify-between items-start">
<div className="text-xl ml-8 w-fit h-fit">
후기{' '}
<span className="font-bold w-fit h-fit">{reviewData?.content.length}</span>
<span className="font-bold w-fit h-fit">
{reviewData?.content.length}
</span>
</div>
<button
Expand Down Expand Up @@ -208,7 +210,9 @@ const ReviewModal = ({ onClose, data }: ReviewProps) => {
)}
<div className="ml-3">
<h5 className="font-medium">{review.nickname}</h5>
<p className="text-xs text-gray-500">숙박 일시&nbsp;{review.startDate}~{review.endDate}</p>
<p className="text-xs text-gray-500">
숙박 일시&nbsp;{review.startDate}~{review.endDate}
</p>
</div>
</div>
<p className="mt-2 text-sm">{review.content}</p>
Expand All @@ -217,14 +221,17 @@ const ReviewModal = ({ onClose, data }: ReviewProps) => {
</div>
</div>
</div>
{error !== null &&
<div className="fixed inset-0 bg-black bg-opacity-50">에러: {error}</div>
}
{isLoading &&
<div className="fixed inset-0 bg-black bg-opacity-50">서버에서 데이터를 가져오는 중...</div>
}
{error !== null && (
<div className="fixed inset-0 bg-black bg-opacity-50">
에러: {error}
</div>
)}
{isLoading && (
<div className="fixed inset-0 bg-black bg-opacity-50">
서버에서 데이터를 가져오는 중...
</div>
)}
</div>

);
};

Expand Down
79 changes: 79 additions & 0 deletions src/components/roomdetail/RoomGuestsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useState } from 'react';

Check failure on line 1 in src/components/roomdetail/RoomGuestsModal.tsx

View workflow job for this annotation

GitHub Actions / ci

Run autofix to sort these imports!

import { useSearch } from '@/components/home/context/SearchContext';
import ErrorIcon from '@mui/icons-material/Error';

type GuestsModalProps = {
onClose: () => void;
maxOccupancy: number;
};

const GuestsModal = ({ onClose, maxOccupancy }: GuestsModalProps) => {
const { setGuests } = useSearch();
const [guestCount, setGuestCount] = useState(0);

const handleIncrement = () => {
setGuestCount((prev) => prev + 1);
};

const handleDecrement = () => {
if (guestCount > 0) {
setGuestCount((prev) => prev - 1);
}
};

const handleSave = () => {
setGuests(guestCount);
onClose();
};

return (
<div className="p-6">
<div className="flex items-center justify-between py-4">
<div>
<h3 className="text-base font-medium">게스트</h3>
<p className="text-sm text-gray-500">숙박 인원을 선택해주세요</p>
</div>
<div className="flex items-center gap-4">
<button
onClick={handleDecrement}
disabled={guestCount === 0}
className={`w-8 h-8 rounded-full border flex items-center justify-center
${guestCount === 0 ? 'border-gray-200 text-gray-200' : 'border-gray-400 text-gray-400 hover:border-gray-700 hover:text-gray-700'}`}
>
-
</button>
<span className="w-6 text-center">{guestCount}</span>
<button
onClick={handleIncrement}
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"
>
+
</button>
</div>
</div>

<div className="flex items-center mt-6 pt-4 border-t gap-8">
<button onClick={onClose} className="text-base underline font-medium">
취소
</button>
<button
onClick={handleSave}
className="px-6 py-3 bg-black text-white rounded-lg font-medium"
>
저장하기
</button>
{maxOccupancy < guestCount && (
<div className="flex items-center gap-2">
<ErrorIcon className="text-red-700 text-sm" />
<div className="text-sm text-red-700">
게스트 인원이 최대 인원을 초과했습니다
</div>
</div>
)}
</div>
</div>
);
};

export default GuestsModal;
Loading

0 comments on commit 0d09386

Please sign in to comment.