탐나예 예약 현황 페이지 기능 및 코드 소개
1. 예약 현황 페이지 간단 기능 소개
2. 코드 소개
ReservationState
라는 페이지를 통해 유저 데이터를 받아, 관련 데이터를 구분하였고, props
를 활용해 할당해주었습니다.2-1-1) useState로 각 데이터 선언
//층수 API 정보 가져오기
const [floor, setfloor] = useState('');
const [bookingData, setBookingData] = useState([]);
const [roomData, setRoomData] = useState([]);
// 2층 정보
const [SecondMeetingRoominfo, setSecondMeetingRoominfo] = useState([]);
const [SecondNaboxinfo, setSecondNaboxinfo] = useState([]);
const [SinyangID, setSinYangID] = useState('');
const [SinyangName, setSinYangName] = useState('');
// 3층 정보
const [ThirdMeetingStudioinfo, setThirdMeetingStudioinfo] = useState([]);
const [ThirdNaboxinfo, setThirdNaboxinfo] = useState([]);
// 4층 정보
const [FourthFloorinfo, setFourthFloorinfo] = useState([]);
2-1-2) fetch, get을 통해 백에서 데이터를 층수에 맞게 구분 한 후, 필터로 세부 룸에 대한 정보로 나누기
const myUrl = useUrl();
const url = `http://${myUrl}/api/booking/details-booking`;
const navigate = useNavigate();
useEffect(() => {
fetchGet(url, navigate).then((data) => {
setfloor(data.floor);
setBookingData(data.BookingData);
setRoomData(data.RoomData);
// 2층 일 때 정보
if (data.floor === 2) {
setSecondMeetingRoominfo(
data.RoomData.filter(
(rooms) =>
rooms.roomType === 'meeting' && rooms.roomType !== 'official'
)
);
setSecondNaboxinfo(
data.RoomData.filter((rooms) => rooms.roomType === 'nabox')
);
setSinYangID(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomId
);
setSinYangName(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomName
);
}
// 3층 일 때 정보
else if (data.floor === 3) {
setThirdMeetingStudioinfo(
data.RoomData.filter(
(rooms) =>
rooms.roomType === 'meeting' || rooms.roomType === 'studio'
)
);
setThirdNaboxinfo(
data.RoomData.filter((rooms) => rooms.roomType === 'nabox')
);
}
// 0층일 때 즉 모두 보여줘야 할 때 정보
else {
// 2층 정보
setSecondMeetingRoominfo(
data.RoomData.filter(
(rooms) =>
rooms.floor === 2 &&
rooms.roomType === 'meeting' &&
rooms.roomType !== 'official'
)
);
setSecondNaboxinfo(
data.RoomData.filter(
(rooms) => rooms.floor === 2 && rooms.roomType === 'nabox'
)
);
setSinYangID(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomId
);
setSinYangName(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomName
);
// 3층 정보
setThirdMeetingStudioinfo(
data.RoomData.filter(
(rooms) =>
(rooms.floor === 3 && rooms.roomType === 'meeting') ||
rooms.roomType === 'studio'
)
);
setThirdNaboxinfo(
data.RoomData.filter(
(rooms) => rooms.floor === 3 && rooms.roomType === 'nabox'
)
);
// 4층 정보
setFourthFloorinfo(data.RoomData.filter((rooms) => rooms.floor === 4));
}
});
}, [url, myUrl]);
2-1-2) !!! 여기서 중요한 포인트 !!!
else {
// 2층 정보
setSecondMeetingRoominfo(
data.RoomData.filter(
(rooms) =>
rooms.floor === 2 &&
rooms.roomType === 'meeting' &&
rooms.roomType !== 'official'
)
);
setSecondNaboxinfo(
data.RoomData.filter(
(rooms) => rooms.floor === 2 && rooms.roomType === 'nabox'
)
);
setSinYangID(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomId
);
setSinYangName(
data.RoomData.filter((rooms) => rooms.roomType === 'official')[0]
.roomName
);
2-1-3) props를 통해 층수 별 component에 정보 할당하기
{floor === 0 && [
<AllFloorReservationState
className={styles.reservationTable}
key="0"
SecondMeetingRoominfo={SecondMeetingRoominfo}
SecondNaboxinfo={SecondNaboxinfo}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
ThirdNaboxinfo={ThirdNaboxinfo}
FourthFloorinfo={FourthFloorinfo}
bookingData={bookingData}
roomData={roomData}
SinyangID={SinyangID}
SinyangName={SinyangName}
floor={floor}
/>,
]}
{floor === 2 && [
<SecondFloorReservationState
key="2"
className={styles.reservationTable}
SecondMeetingRoominfo={SecondMeetingRoominfo}
SecondNaboxinfo={SecondNaboxinfo}
bookingData={bookingData}
roomData={roomData}
SinyangID={SinyangID}
SinyangName={SinyangName}
floor={floor}
/>,
]}
{floor === 3 && [
<ThirdFloorReservationState
key="3"
className={styles.reservationTable}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>,
]}
2-2-1) 3층 컴포넌트 예시 / state로 현재 보여주는 회의실 타입 구분
const [RoomType, setRoomType] = useState(true);
const MeetingRoom = true;
const NaBox = false;
2-2-2) 회의실 버튼, 나박스 버튼 클릭 함수 설정
const MeetingRoomOnClick = () => {
setRoomType(MeetingRoom);
};
const NaboxOnClick = () => {
setRoomType(NaBox);
};
return (
<div>
<div className={styles.ReservationStateContainer}>
{/* 3층 나박스와 회의실 버튼 */}
<div className={styles.buttonContainer}>
<button className={styles.button} onClick={MeetingRoomOnClick}>
회의실
</button>
<button className={styles.button} onClick={NaboxOnClick}>
Na Box
</button>
</div>
2-2-3) state 사용하여, 아래에 정보 뿌리기
{RoomType ? (
<ThirdFloorMeetingRoomState
className={styles.reservationTable}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
bookingData={bookingData}
roomData={roomData}
/>
) : (
<ThirdFloorNaRoomState
className={styles.reservationTable}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>
)}
2-3. 예약 관련 데이터, 표에 뿌리기
2-3-1) 해당 시간과 룸에 예약이 있는지 확인하는 함수 설정
1) 시간당 룸에 예약 데이터 불러오는 함수 설정
const TimeAndRoomFilter = (Time, Room) => {
let timedata = bookingData.filter(
(room) =>
room.roomId === Room && TimeToString(room.startTime) === onlyTime(Time)
);
return timedata;
};
2) 시간당 룸의 예약이 있는지 확인하는 함수 설정
const IsThisTimeRoombooked = (Time, Room) => {
const IsTrue = TimeAndRoomFilter(Time, Room).length !== 0;
return IsTrue;
};
3) 예약 시간 구하는 함수 설정
const bookingLength = (startTime, endTime) => {
let length =
Number(TimeToString(endTime)) - Number(TimeToString(startTime));
return length;
};
2-3-2) 룸의 값은 map으로 돌려, 행으로 뿌려주었고, Link
를 사용해 예약으로 관련 룸 예약으로 들어갈 수 있도록 제작하였습니다.
<thead className="table-light" id={styles.thead}>
<tr id={styles.theadTr}>
<th className="table-primary text-break" id={styles.time}></th>
{/* 룸 값 불러오기 */}
{ThirdNaboxinfo.map((room) => (
<th key={room.roomId} className="table-primary" id={styles.text}>
<Link to={`/booking/${room.roomId}`} id={styles.roomA}>
<ArrowRightCircleFill />
{room.roomName}
</Link>
</th>
))}
</tr>
</thead>
2-3-3) 시간 맵을 돌리고, 그 안에서 한번더 관련 룸의 값을 맵으로 돌려 테이블에 예약된 것이 알맞는 위치에 들어갈 수 있도록 하였습니다.
1) 시간 맵 돌리기
{timeList.map((time) => (
<tr key={time} id={styles.tbodyTr}>
<th className={styles.time}>{time}</th>
2) 그 내부에 시간에 맞는 회의실 예약 상황을 전달
- 함수를 통해 예약이 있는지 확인, 있으면 버튼과 팝업 창, 없으면 null
{ThirdNaboxinfo.map((room) => (
<th key={room.roomId} className={styles.roomstate}>
{IsThisTimeRoombooked(time, room.roomId) ? (
<OverlayTrigger>
</OverlayTrigger>
) : null}
</th>
))}
3) 팝오버 부트스트랩 사용, 관련 예약 내용 props
로 전달
<OverlayTrigger
trigger={['hover', 'focus']}
key={TimeAndRoomFilter(time, room.roomId)[0].bookingId}
placement="top"
overlay={
<Popover id="popover-positioned-top">
<Popover.Body>
<PoplayNabox
userName={
TimeAndRoomFilter(time, room.roomId)[0]
.applicant.userName
}
startTime={
TimeAndRoomFilter(time, room.roomId)[0]
.startTime
}
endTime={
TimeAndRoomFilter(time, room.roomId)[0].endTime
}
roomName={
TimeAndRoomFilter(time, room.roomId)[0].roomName
}
/>
</Popover.Body>
</Popover>
}
>
4) 버튼 스타일 높이는 bookingLength()
의 숫자에 표 높이를 곱한 수로 설정
5) 아이디는 official
이라면 매니저 스타일로 따로 적용
6) 버튼 내부에 userName
포함
<button
style={{
height: `${
bookingLength(
TimeAndRoomFilter(time, room.roomId)[0].startTime,
TimeAndRoomFilter(time, room.roomId)[0].endTime
) * 35.4
}px`,
}}
className={styles.bookingTime}
id={
TimeAndRoomFilter(time, room.roomId)[0].official
? [styles.Manager]
: null
}
variant="secondary"
>
<p>
<EmojiSmileFill />
{
TimeAndRoomFilter(time, room.roomId)[0].applicant
.userName
}
님 예약
</p>
</button>