Mini프로젝트_병원예약프로그램_(DateTimePicker 라이브러리 사용)

이고운·2022년 10월 26일
0

기업협업

목록 보기
4/4

기업협업 과제 4번째부터는 개인 프로젝트로 변경되었다.
아무래도 개인과제이다 보니 부담이 커지긴 했지만, 과제 설명에 대한 해석에도 자율성을 두어 해석능력을 키우는 경험을 하게 된 것 같아 좋았다.

1. 프로젝트 개요

1) 프로젝트 기간

2022.10.17 ~ 2022.10.19 (3일간)

2) 기능 구현

  • 로그인 페이지
  • 예약 등록 페이지
  • 예약 조회 페이지

3) 코드 컨벤션

기존에 팀 프로젝트로 진행했을 때 사용했던 코드 컨벤션을 재 사용했다.

내가 구현한 기능 상세 설명 및 문제 발생

1) 로그인 페이지

일단 나는 로그인하여 이름 및 핸드폰 번호를 입력한 계정을 저장하여 그에 따라 예약자를 가져오려고 했다. 때문에 이때 입력한 계정을 저장해야하는데
보통 팀 프로젝트로 백엔드랑 같이 진행하게되면 서버에서 받아오지만
이번에는 프론트에서만 작업해야하는 것이기 때문에 어떤 식으로 해야할 지 고민이 많았다. 생각한 결과 기존에 팀 프로젝트 시에 로그인 여부를 확인할 때 localStorage를 썼던 것이 생각이 났다.
그래서 이번에는 localStorage를 사용하여 데이터를 저장하고 지우는 방식으로 프로젝트를 진행했다.

로그인 버튼을 클릭하면 로그인 모달창이 뜬다.
여기서 이전에 회원가입하던 것처럼 간단한 유효성 검사를 넣으려고 했다.
하기의 조건이 만족 시에만 로그인 버튼이 활성화되면서 색상이 변경된다.

이름은 한자 이상
핸드폰 번호는 10자 이상

<LoginModal.js>
  
import styled from "styled-components";
import { useRef, useState } from "react";
import { useNavigate } from "react-router-dom";

const LoginModal = ({ loginModal, setLoginModal }) => {
  const navigate = useNavigate();

  const [userName, setUserName] = useState("");
  const [userNumber, setUserNumber] = useState("");
  const [valid, setValid] = useState(false);

  const handleName = (e) => {
    const nameValue = e.target.value;
    setUserName(nameValue);
    nameValue.length >= 1 && userNumber.length >= 10
      ? setValid(true)
      : setValid(false);
  };

  const hadleNumber = (e) => {
    const numberValud = e.target.value;
    setUserNumber(numberValud);
    userName.length >= 1 && numberValud.length >= 10
      ? setValid(true)
      : setValid(false);
  };

  const handleLogin = (e) => {
    if (userName.length >= 1 && userNumber.length >= 10) {
      setValid(true);
      navigate("/reservation");
      setLoginModal(!loginModal);
    } else {
      setValid(false);
    }
  };

  function onClickLogin() {
    localStorage.setItem("USER_NAME", userName);
    localStorage.setItem("USER_PHONENUMBER", userNumber);
    handleLogin();
  }

그리고 로그인 버튼을 클릭하면 이름이랑 핸드폰 번호를 localStorage에 저장하기 위해 setItem을 이용했다.
하고 보니 핸드폰 번호는 저장할 필요가 없었지만, 원래는 이름이 아니라 핸드폰 번호가 더 고유한 것 같아서 이것도 예약자 데이터에 넣으려고 했다.
그리고 return 아래로 각각 이벤트 핸들러를 저장해줬다.

2) 예약 페이지

로그인버튼 누르면 예약 페이지로 넘어가게 되는데 예약페이지에는 병원 리스트, 달력, 진료 종류 들을 선택하여 예약할 수 있게 되어있다.
이 때 달력 라이브러리는 react-datetime-picker를 사용했다. 뭔가 이전에 사용했던 react-calendar말고 다른 라이브러리를 사용하고 싶었다.
사용하는 방식은 거의 동일했다.
여기서 병원 리스트는 별도의 파일에서 fetch함수를 이용해 가져왔고 진료종류는 3가지밖에 없어서 해당 파일에서 선언 후 이용했다.

<Reservation.js>
  const Reservation = () => {
  const navigate = useNavigate();
  const [value, onChange] = useState(new Date());
  const [selected, setSelected] = useState("");
  const [hospital, setHospital] = useState([]);
  const [hospitalSelected, setHospitalSelected] = useState("");
  const selectList = ["=== 선택 ===", "진료", "검진", "상담"];

  const currentUserName = localStorage.getItem("USER_NAME");
  console.log(currentUserName);
    
//진료 종류 selectbox 핸들러
  const handleSelect = (e) => {
    setSelected(e.target.value);
  };
//병원 선택 selectbox 핸들러
  const handleHospital = (e) => {
    setHospitalSelected(e.target.value);
  };
  console.log(hospitalSelected);

  const submitReservation = (e) => {
    // e.preventDefault();
    alert("예약이 완료되었습니다");
    navigate("/confirm");
    localStorage.setItem("hospital", hospitalSelected);
    localStorage.setItem("user_date", value);
    localStorage.setItem("user_data", selected);
  };
  useEffect(() => {
    fetch("/data/hospital.json")
      .then((res) => res.json())
      .then((data) => setHospital(data.category));
  }, []);

000님의 예약페이지로 출력하기 위해 저장해준 예약자 명을 getItem으로 가져왔다.

return (
    <RevervationWrapper>
      {localStorage.getItem("user_date") ? (
        <div className="alredyRes">
          <p> 이미 예약 내역이 있습니다. </p>
          <p>새로 예약하시려면 기존 예약 내역을 취소해주세요.</p>
          <button
            onClick={() => {
              navigate("/confirm");
            }}
          >
            예약취소하러 가기
          </button>
        </div>
      ) : (
        <MainBackground>
          <h1>{currentUserName}님의 예약페이지</h1>
          <h1>Reservation</h1>
          <h3 className="h3Title">병원 선택하기</h3>
          <select
            onChange={handleHospital}
            value={hospitalSelected}
            className="hospitalBox"
          >
            {hospital.map((item) => (
              <option value={item.hospitalName} key={item.id}>
                {item.hospitalName}
              </option>
            ))}
          </select>
          <h3 className="h3Title">날짜 및 시간 선택</h3>
          <DateTimePicker
            onChange={onChange}
            value={value}
            calendarAriaLabel="Toggle calendar"
            minDate={new Date()}
            timeIntervals={30}
            disableClock={true}
          />
          <h3 className="h3Title">진료 종류 선택</h3>
          <select
            onChange={handleSelect}
            value={selected}
            className="selectBox"
          >
            {selectList.map((list) => (
              <option value={list} key={list}>
                {list}
              </option>
            ))}
          </select>
          <form>
            <button onClick={submitReservation} className="reservationBtn">
              예약하기
            </button>
          </form>
        </MainBackground>
      )}
    </RevervationWrapper>
  );

해당 예약 페이지는 이미 예약 내역이 있으면 재 예약이 불가능하도록 조건부 렌더링을 사용해서 보여주는 화면을 달리했다.
그리고 value값을 예약 조회 화면에 보여주기 위해 useState로 e.target.value를 선언했고 예약버튼을 클릭하면 그 값을 localStorage.setItem으로 또 저장해줬다.

3) 예약 조회

예약 조회페이지는 이전에 localStorage로 저장했던 값들을 다 불러서 출력해줬다. 그리고 예약 취소 기능을 위해 해당 페이지에는 localStorage.remove 메소드도 사용했다. 저장되었던 데이터를 날리기 위함이다.

<Confirm.js>
  const Confirm = () => {
  const navigate = useNavigate();
  const currentUserName = localStorage.getItem("USER_NAME");
  const currentUserDate = localStorage.getItem("user_date");
  const currentUserData = localStorage.getItem("user_data");
  const currentHospital = localStorage.getItem("hospital");

  const reservationDate =
    moment(currentUserDate).format("YYYY년 MM월 DD일 HH시");

  const removeData = () => {
    localStorage.removeItem("user_date");
    localStorage.removeItem("user_data");
    localStorage.removeItem("hospital");
  };
  console.log(currentHospital);
  const clickDelete = () => {
    removeData();
    navigate("/");
  };
  const clickanother = () => {
    removeData();
    navigate("/reservation");
  };

추가로 달력에서 선택했던 날짜와 시간 형식을 변경해주기 위해 moment.js라이브러리도 사용했다.

4) ❌ 문제 발생 ❌

원래 과제는 예약이 완료된 날짜는 재 예약이 안되도록 에러핸들이 구현되어야한다.
예를 들어 10월 29일에 해당 건으로 예약을 하면 해당 날짜에 더이상 예약이 안되어야 하는데 나는 그 에러 핸들 부분을 구현하지 못했다.
생각을 해도 해결이 안된 부분이라 일단 조건을 좀 생각하고 나중에 좀 더 다양하게 개발을 해보고 시야가 넓어지면 다시 구현해보고 싶다.
먼저 에러핸들이 가능하려면 아래와 같은 조건을 충족해야할 것 같다.

  • 병원마다 예약을 저장하는 별도의 작업이 있어야한다.
  • 로그인하여 나의 예약 내역을 조회할 것이 아니라 그냥 비회원 계정 확인 식으로 예약자 입력 후 전체 예약을 조회할 수 있는 방향이어야 할 것 같다.
    (그 중에 핸드폰 번호를 입력해서 나의 예약 조회 기능)
  • 위에서 예약이 불가능 한 날짜를 가져와 달력에서 비활성화를 해야함.

5) 결과화면

3. 느낀 점

사실 이번 과제는 너무 틀에 박힌채로 내 생각에 갇혀서 다양하게 시도를 안하지 않았나 싶다.
내가 지금 구현한 화면은 처음에 내가 가이드를 잡은 화면 그대로인데
이 상태에서 중간에 기능들을 추가하려고 하니 쉽지 않았다.
이미 머리 속에는 내가 구현하고자 하는 화면에 틀에 박혀있었기 때문이다.
좀 더 유연하게 사고할 수 있어야하는데 아직 이 부분이 미숙한 것 같다.
내 생각에는 이 점은 더 다양하게 프로젝트 해보면서 시야와 실력을 넓혀야 해결이 될 것 같다.
그리고 서버 없이 데이터 저장하는 방식에 대해서도 꽤 오래 고민했는데,
다행히 이전에 회원가입, 로그인했던 방식이 생각나서 이번에도 적용해서
이후로는 무난히 작업할 수 있었다. 그러나 완성도 측면에서 백엔드 서버에서 데이터를 주고 받아오는 것이 얼마나 중요한 것인지 다시 한 번 생각하게 되었다.

profile
자 이제 시작이야~ 내 꿈을~ 내 꿈을 위한 여행~~🌈

0개의 댓글