[CATSPOT]층별 학교 강의실 구조 설정 & 시간표 연동 BA2 페이지 구현기

2025. 3. 27. 15:48프론트엔드/REACT

728x90

상태 관리 & API 데이터 패칭

const BA2 = () => {
  const [selectedRoom, setSelectedRoom] = useState(null);
  const [highlightedRooms, setHighlightedRooms] = useState([]);

  useEffect(() => {
    const fetchHighlightedRooms = async () => {
      const { day, hour } = getKoreanDayAndHour();
      try {
        const response = await axiosInstance.post("/api/classroom", {
          buildingName: 'BA',
          floor: 2,
          day,
          hour,
        });
        setHighlightedRooms(response.data.classrooms);
      } catch (error) {
        console.error("Error fetching highlighted rooms:", error);
      }
    };
    fetchHighlightedRooms();
  }, []);

설명:

  • 선택된 강의실 및 강조 대상 강의실 상태 관리
  • API 호출을 통해 현재 시간 기준 데이터 수신
  • 데이터 반영 – 연동

강의실 클릭 이벤트 & 시간표 요청

  const handleRoomClick = async (room) => {
    if (room !== "상담실") {
      const { day, hour } = getKoreanDayAndHour();
      try {
        const response = await axiosInstance.post("/api/roomSchedule", {
          buildingName: 'BA',
          classroomNumber: room.substring(2),
          day,
          hour,
        });
        setSelectedRoom(response.data);
      } catch (error) {
        console.error("Error fetching room schedule:", error);
      }
    }
  };

  const closeModal = () => {
    setSelectedRoom(null);
  };

설명:

  • 강의실 클릭 시 해당 시간표 요청 및 모달 표시
  • 선택한 강의실 데이터 업데이트 – 요청

화면 구성 & JSX 렌더링

  return (
    <>
      <Navbar title="빈강의실" />

      <div className="ba2_container">
        <div className="border-marker marker-blue marker-bottom-right"></div>

        <div
          className={`room-box-max_ba2 ${highlightedRooms.includes(parseInt("203")) ? "room-box-highlight" : ""}`}
          onClick={() => handleRoomClick("BA203")}
        >
          <div className="room-box-content">BA203</div>
        </div>

        <div style={{ marginBottom: "50px" }}></div>

        <div className="flex-container">
          <div className={`room-box-max-left ${highlightedRooms.includes(parseInt("202")) ? "room-box-highlight" : ""}`}
            onClick={() => handleRoomClick("BA202")}>
            <div className="room-box-content" style={{ transform: "rotate(-90deg)" }}>
              BA202
            </div>
          </div>

          <div className="centered3-text">
            <span>밤</span>
            <span>비</span>
            <span>노</span>
            <span>2</span>
            <span>층</span>
          </div>

          <div className={`room-box-max-right ${highlightedRooms.includes(parseInt("204")) ? "room-box-highlight" : ""}`}
            onClick={() => handleRoomClick("BA204")}>
            <div className="room-box-content" style={{ transform: "rotate(90deg)" }}>
              BA204
            </div>
          </div>
        </div>
      </div>
      <p className="helper-text">강의실을 클릭하여 시간표를 확인하세요!</p>
      
      <div className="label-container">
        <div className="label label-use "></div>
        <span className="label-text label-margin">사용중</span>
        <div className="label label-exit"></div>
        <span className="label-text">입출구</span>
        <div className="label label-stairs" style={{ marginLeft: "20px" }}></div>
        <span className="label-text">계단</span>
      </div>
      
      {selectedRoom && <ScheduleModal schedule={selectedRoom} onClose={closeModal} />}
    </>
  );
};

export default BA2;

설명:

  • Navbar, 강의실 박스, 중앙 텍스트, 라벨 및 모달을 통한 전체 레이아웃 구성
  • 조건부 렌더링으로 강조 및 모달 제어 – 구성

CSS로 완성한 강의실 디자인

.ba2_container {
  position: relative;
  width: calc(100% - 40px);
  height: 643px;
  margin: 143px auto 0 auto;
  border: 3px solid #dfdfdf;
  border-radius: 5px;
  background-color: #ffffff;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  padding: 20px 40px;
}

.room-box-max_ba2 {
  position: relative;
  width: 100%;
  height: 80px;
  background-color: #b9bfe3;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  font-weight: bold;
  color: black;
  margin-top: 20px;
}

.room-box-max-left,
.room-box-max-right {
  position: relative;
  width: 80px;
  height: 300px;
  background-color: #b9bfe3;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  font-weight: bold;
  color: black;
  margin-top: 20px;
}

.room-box-max_ba2::before,
.room-box-max_ba2::after,
.room-box-max-left::before,
.room-box-max-left::after,
.room-box-max-right::before,
.room-box-max-right::after {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 0 15px 15px 15px;
  border-color: transparent transparent #b9bfe3 transparent;
  border-radius: 15px 15px 0 0;
}

.room-box-max-left::before {
  transform: rotate(-90deg);
  top: 240px;
  left: -20px;
}
.room-box-max-left::after {
  transform: rotate(-90deg);
  top: 50px;
  left: -20px;
}
.room-box-max-right::before {
  transform: rotate(90deg);
  top: 240px;
  left: 70px;
}
.room-box-max-right::after {
  transform: rotate(90deg);
  top: 50px;
  left: 70px;
}

.room-box-highlight {
  background-color: #ffd700 !important;
}
.room-box-highlight::before,
.room-box-highlight::after {
  border-color: transparent transparent #ffd700 transparent !important;
}

설명:

  • 전체 컨테이너, 강의실 박스, 삼각형 장식 및 강조 스타일을 CSS로 구현
  • 시각적 입체감 및 하이라이트 처리 – 디자인

 

728x90