기업협업 과제 4번째부터는 개인 프로젝트로 변경되었다.
아무래도 개인과제이다 보니 부담이 커지긴 했지만, 과제 설명에 대한 해석에도 자율성을 두어 해석능력을 키우는 경험을 하게 된 것 같아 좋았다.
2022.10.17 ~ 2022.10.19 (3일간)
기존에 팀 프로젝트로 진행했을 때 사용했던 코드 컨벤션을 재 사용했다.
일단 나는 로그인하여 이름 및 핸드폰 번호를 입력한 계정을 저장하여 그에 따라 예약자를 가져오려고 했다. 때문에 이때 입력한 계정을 저장해야하는데
보통 팀 프로젝트로 백엔드랑 같이 진행하게되면 서버에서 받아오지만
이번에는 프론트에서만 작업해야하는 것이기 때문에 어떤 식으로 해야할 지 고민이 많았다. 생각한 결과 기존에 팀 프로젝트 시에 로그인 여부를 확인할 때 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 아래로 각각 이벤트 핸들러를 저장해줬다.
로그인버튼 누르면 예약 페이지로 넘어가게 되는데 예약페이지에는 병원 리스트, 달력, 진료 종류 들을 선택하여 예약할 수 있게 되어있다.
이 때 달력 라이브러리는 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으로 또 저장
해줬다.
예약 조회페이지는 이전에 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라이브러리도 사용했다.
원래 과제는 예약이 완료된 날짜는 재 예약이 안되도록 에러핸들
이 구현되어야한다.
예를 들어 10월 29일에 해당 건으로 예약을 하면 해당 날짜에 더이상 예약이 안되어야 하는데 나는 그 에러 핸들 부분을 구현하지 못했다.
생각을 해도 해결이 안된 부분이라 일단 조건을 좀 생각하고 나중에 좀 더 다양하게 개발을 해보고 시야가 넓어지면 다시 구현해보고 싶다.
먼저 에러핸들이 가능하려면 아래와 같은 조건을 충족해야할 것 같다.
- 병원마다 예약을 저장하는 별도의 작업이 있어야한다.
- 로그인하여 나의 예약 내역을 조회할 것이 아니라 그냥 비회원 계정 확인 식으로 예약자 입력 후 전체 예약을 조회할 수 있는 방향이어야 할 것 같다.
(그 중에 핸드폰 번호를 입력해서 나의 예약 조회 기능)- 위에서 예약이 불가능 한 날짜를 가져와 달력에서 비활성화를 해야함.
사실 이번 과제는 너무 틀에 박힌채로 내 생각에 갇혀서 다양하게 시도를 안하지 않았나 싶다.
내가 지금 구현한 화면은 처음에 내가 가이드를 잡은 화면 그대로인데
이 상태에서 중간에 기능들을 추가하려고 하니 쉽지 않았다.
이미 머리 속에는 내가 구현하고자 하는 화면에 틀에 박혀있었기 때문이다.
좀 더 유연하게 사고할 수 있어야하는데 아직 이 부분이 미숙한 것 같다.
내 생각에는 이 점은 더 다양하게 프로젝트 해보면서 시야와 실력을 넓혀야 해결이 될 것 같다.
그리고 서버 없이 데이터 저장하는 방식에 대해서도 꽤 오래 고민했는데,
다행히 이전에 회원가입, 로그인했던 방식이 생각나서 이번에도 적용해서
이후로는 무난히 작업할 수 있었다. 그러나 완성도 측면에서 백엔드 서버에서 데이터를 주고 받아오는 것이 얼마나 중요한 것인지 다시 한 번 생각
하게 되었다.