탐나예 메인페이지 기능 및 코드 소개
1. 메인 페이지 간단 기능 소개
2. 코드 소개
MainTemplate
이라는 페이지를 통해 유저 데이터를 받아, 유저에 따라 필요한 데이터 층수를 구분하여, 층수별 컴포넌트로 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/main`;
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.roomName !== '신양'
)
);
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-3) props를 통해 층수 별 component에 정보 할당하기
{/* classes 활용 */}
{floor === 0 && [
<SecondFloor
key="2"
className={styles.secondFloor}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
SecondMeetingRoominfo={SecondMeetingRoominfo}
SecondNaboxinfo={SecondNaboxinfo}
bookingData={bookingData}
roomData={roomData}
SinyangID={SinyangID}
SinyangName={SinyangName}
floor={floor}
/>,
<ThirdFloor
key="3"
className={styles.thirdFloor}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>,
<FourthFloor
key="4"
className={styles.fourthFloor}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
bookingData={bookingData}
roomData={roomData}
FourthFloorinfo={FourthFloorinfo}
/>,
]}
{floor === 2 && (
<SecondFloor
key="2"
className={styles.secondFloor}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
SecondMeetingRoominfo={SecondMeetingRoominfo}
SecondNaboxinfo={SecondNaboxinfo}
bookingData={bookingData}
roomData={roomData}
SinyangID={SinyangID}
SinyangName={SinyangName}
floor={floor}
/>
)}
{floor === 3 && (
<ThirdFloor
key="3"
className={styles.thirdFloor}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>
)}
2-2-1) 3층 컴포넌트 예시
ThirdFloorMeetingRoom.js';
import ThirdFloorNaRoom from './ThirdFloorNaRoom.js';
import styles from './ThirdFloor.module.css';
const ThirdFloor = ({
ablebtn,
BookingConfirm,
ThirdMeetingStudioinfo,
ThirdNaboxinfo,
bookingData,
roomData,
}) => {
return (
<div className={styles.MainThirdFloor}>
<div className={styles.ThirdFloor}>
<h2>3 Floor</h2>
<div className={styles.ThirdFloorcontainer}>
<ThirdFloorMap
className={styles.ThirdFloorMap}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>
<div className={styles.RoomContainer}>
<ThirdFloorMeetingRoom
className={styles.meetingRoom}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
ThirdMeetingStudioinfo={ThirdMeetingStudioinfo}
bookingData={bookingData}
roomData={roomData}
/>
<ThirdFloorNaRoom
className={styles.naRoom}
ablebtn={ablebtn}
BookingConfirm={BookingConfirm}
ThirdNaboxinfo={ThirdNaboxinfo}
bookingData={bookingData}
roomData={roomData}
/>
</div>
</div>
</div>
</div>
);
};
export default ThirdFloor;
<div>태그
를 사용하여, 버튼으로 작동하도록 구현하였습니다.2-3-1) roomFull 함수 설정
const Now = new Date();
const NowHour = Now.getHours();
const RemainTime = 21 - NowHour;
3) 현재 시간이 껴있지 않은 지금보다 뒤의 예약 시간 계산하는 알고리즘
const middleRoomState = bookingData.filter(
(room) =>
room.roomId === roomid &&
Number(TimeToString(room.startTime)) < Number(NowHour) &&
Number(TimeToString(room.endTime)) > Number(NowHour)
);
const roomBookingState = roomState.map(
(room) =>
TimeToString(room.endTime) - Number(TimeToString(room.startTime))
);
const sum = roomBookingState.reduce(function add(sum, currValue) {
return sum + currValue;
}, 0);
4) 현재 시간이 껴있는 예약 현황 시간 추출 (처음에는 고려하지 못한 부분)
const middleRoomState = bookingData.filter(
(room) =>
room.roomId === roomid &&
Number(TimeToString(room.startTime)) < Number(NowHour) &&
Number(TimeToString(room.endTime)) > Number(NowHour)
);
const middleBookingState = middleRoomState.map(
(room) => Number(TimeToString(room.endTime)) - Number(NowHour)
);
const middleSum = middleBookingState.reduce(function add(sum, currValue) {
return sum + currValue;
}, 0);
5) 전체 추출 시간들의 합과 남은 시간 불린으로 결과값 제출
return sum + middleSum < RemainTime;
2-3-2) 상황 별 회의실 기능 분리
{ThirdMeetingStudioinfo.map((rooms) => (
<Link
to={`/booking/${rooms.roomId}`}
key={rooms.roomId}
className={styles[rooms.roomName]}
id={
notroomFull(rooms.roomId) && ablebtn
? [styles.MeetingRoom]
: [styles.full]
}
onClick={BookingConfirm}
>
<div>
{notroomFull(rooms.roomId) && ablebtn
? rooms.roomName
: `${rooms.roomName}\n마감`}
</div>
</Link>
))}
2-3-3) useTimeAlert 훅 제작, 시간에 따라 예약 가능여부 맵에 표현
예약 시간을 전체적으로 한번에 관리할 수 있도록 커스텀 훅을 제작하여 사용하였습니다.
버튼 활성화 관련 상태값 useState로 지정
const [ablebtn, setAblebtn] = useState(true)
const Now = new Date()
const NowHour = Now.getHours()
const NowMins = Now.getMinutes()
function pluszero(times) {
let time = times.toString() //시간을 숫자에서 문자로 변환
if (time.length < 2) {
time = '0' + time //숫자 앞에 0을 붙여줌
return time
} else {
return time
}
}
const nowHour = pluszero(NowHour)
const nowMins = pluszero(NowMins)
const nowTime = nowHour + nowMins
const startTime = '0830'
const endTime = '2100'
useEffect(() => {
if (startTime > nowTime || endTime < nowTime) {
setAblebtn(false)
} else {
setAblebtn(true)
}
}, [])
const BookingConfirm = () => {
if (startTime > nowTime || endTime < nowTime) {
alert(
'예약할 수 없는 시간입니다!\n오전08:30부터 오후21:00까지 예약이 가능합니다.'
)
}
}
ablebtn
과 BookingConfirm
리스트로 내보내기 return [ablebtn, BookingConfirm]
{ThirdMeetingStudioinfo.map((room) => (
<Link to={`/booking/${room.roomId}`} key={room.roomId}>
<button
className={
notroomFull(room.roomId) && ablebtn
? [styles.notfull]
: [styles.full]
}
onClick={BookingConfirm}
>
{room.roomName}
</button>
</Link>
))}