develop

날짜 기능이 있는 게시판 만들기 with datepicker (4) - 이벤트 등록시

crab. 2023. 2. 25. 08:11

날짜를 읽어올때(with TZ)

  • 이렇게 서버로 보내준 날짜는 읽을 때 tz형식으로 들어온다.
  • tz는 timezone의 약자로
    • YYYY-MM-DDTHH:mm:ss.00Z
    • 2023-02-12T16:00:00.000Z
  • 이런 형태이다.
  • 이렇게 읽어온 데이터는
    • 이벤트 목록에서
    • 이벤트 수정에서
  • 두 번 쓰이게 된다.
  • 여기서의 문제는 한국의 시간은 GMT+09:00인데 서버에서 데이터베이스에 한국 표준시(GMT+09:00)를 insert해도 GMT로 insert 된다는 점이다.
  • 따라서 프론트에서 나라에 맞는 시간으로 변경하여 표시해야 한다.
    • 이 말뜻은 프론트에서 3시로 보내고 서버도 3시로 보내지만 막상 moment를 이용해 date객체로 만들면 서버로부터 받은 데이터는 (+9)되어 12시가 된다.

이벤트 목록의 경우

  • 처음의 이벤트 목록은 moment를 사용해서 형식을 바꿨다.
    • 단순히 목록에 날짜를 렌더링하기만 하면 되기에 문자열 형식이면 된다.
  • 2023-02-12T16:00:00.000Z 는
				<Items className="day">
          <p>
            {moment(Date.parse(event.open)).add(-9, "h").format("YYYY-MM-DD")}
            {/* {event.open.slice(0, 10)} */}
          </p>
          &nbsp;
          <p>
            {moment(Date.parse(event.open)).add(-9, "h").format("hh:mm A")}
            &nbsp;-&nbsp;
            {moment(Date.parse(event.close)).add(-9, "h").format("hh:mm A")}
          </p>
        </Items>
  • 를 통해 2023-02-12 04:00 PM - 06:00 PM 이 된다.
    • 저 위의 주석 slice도 가능하지만 그렇게 되면 아래의 시간 부분에서 매우 하드코딩이 될것이다..
  • 여기서 moment 라이브러리의 강력함을 알게 되었다.
    • moment.js는 JavaScript에서 사용되는 날짜관련 라이브러리 중 가장 많이 사용되었던 라이브러리로써
    • 현재는 더이상의 업데이트가 없을 것이라 하였지만, 2011년부터 가장 많이 사용된 날짜 관련 라이브러리이다.

이벤트 수정의 경우

  • 이벤트 수정의 경우는 기존의 datepicker에 서버로부터 받은 날짜가 나와야 하기 때문에 date객체로 바꿀 필요가 있다.
  • 따라서
	const [startDate, setStartDate] = useState(
    new Date(new Date(updateEvent.open).getTime() - 9 * 60 * 60 * 1000),
  );

  const [endDate, setEndDate] = useState(
    new Date(new Date(updateEvent.close).getTime() - 9 * 60 * 60 * 1000),
  );

  const [startTime, setStartTime] = useState(
    new Date(new Date(updateEvent.open).getTime() - 9 * 60 * 60 * 1000),
  );

  const [endTime, setEndTime] = useState(
    new Date(new Date(updateEvent.close).getTime() - 9 * 60 * 60 * 1000),
  );
  • 이렇게 처리해주었다.
  • 각 상태들은 날짜와 시간으로 나뉘는데 이 경우 모든 날짜와 시간들이 9시간을 빼고 그걸 날짜와 시간으로 나누면 되는 것이기에 통일성을 위해
  • 먼저 date객체로 만들고 getTime으로 ms단위의 숫자로 만든 다음 9시간(9 * 60 * 60 * 1000)을 빼준 이후 다시 date객체로 만들어준다.
  • 이렇게 하면 유저가 이벤트를 등록하고 그 이벤트를 수정하러 다시 들어왔을 때 datepicker에 정상적으로 그 날짜가 보이게 된다.

쿠폰 추가의 경우

  • 이벤트를 등록할 때 그 안에 쿠폰을 여러개 추가할 수 있다.
  • 단, 이때 이 쿠폰들에 대해서도 CRUD가 가능한데.
  • 이벤트를 작성한다. (단, 이때 이벤트 날짜를 지정했으면 쿠폰날짜도 기본적으로 그 값이 들어간다.)
    • (선택) 쿠폰들을 추가한다.
    • (선택) 위에서 추가한 쿠폰을 수정한다.
    • (선택) 위에서 추가하거나 수정한 쿠폰을 삭제한다.
    • 이벤트를 등록한다. (추가하거나, 추가하고 수정한 쿠폰들도 한 번에 다)
  • 지금까지 한 것은 이벤트를 작성하고 등록한 것이고 이제는 (선택)들을 해야 한다.
  • 이벤트 날짜를 지정 했을 경우 쿠폰날짜의 기본값을 정하는 것은
  • 쿠폰설정을 눌렀을 때 기존의 open 값과 close 값을 store에 dispatch하여 쿠폰추가 컴포넌트에서 이를 확인하면 된다.
    	 	<CouponBtn
                      className="btn"
                      onClick={() => {
                        setCouponState(true);
                        dispatch(_postAddFormStartExpDate(open));
                        dispatch(_postAddFormEndExpDate(close));
                      }}
                    >
                      쿠폰 설정
                    </CouponBtn>
    
    ////////////////////////////////////////////////////////////////////////////////////
    
    
      const [startDate, setStartDate] = useState(
        addFormStartExpDate === "" ? false : new Date(addFormStartExpDate),
      );
      const [endDate, setEndDate] = useState(
        addFormStartExpDate === "" ? false : new Date(addFormEndExpDate),
      );
      const [startTime, setStartTime] = useState(
        addFormStartExpDate === "" ? false : new Date(addFormStartExpDate),
      );
      const [endTime, setEndTime] = useState(
        addFormStartExpDate === "" ? false : new Date(addFormEndExpDate),
      );
  • 쿠폰을 추가할때는 이벤트를 등록할때와 마찬가지로 datepicker를 이용해 날짜를 등록하고 useEffect를 이용해 open값을 바꾼다.
  • 단, 여기서 쿠폰을 저장할 때 서버로 바로 보내는 것이 아닌 우선 store에 dispatch한다.
    • 그래야 이벤트 등록전에 store에 있는 쿠폰 목록을 수정하고 삭제할 수 있다.
    		_postCoupon: (state, action) => {
          console.log(action.payload);
          state.coupon.unshift(action.payload);
        },
    
  • 이제는 방금 추가했던 쿠폰을 수정하는 기능을 구현해야 한다.

쿠폰 수정의 경우

  • 위에서 추가했던 쿠폰을 수정하는 것이기에
    • 쿠폰 추가에서 store에 저장했던 YYYY-MM-DD HH:mm 형태의 데이터를 다시 datepicker에 기본적으로 나오게 하기 위해서
    	const [startDate, setStartDate] = useState(
        new Date(new Date(couponData.startExpDate).getTime()),
      );
      const [endDate, setEndDate] = useState(
        new Date(new Date(couponData.endExpDate).getTime()),
      );
      const [startTime, setStartTime] = useState(
        new Date(new Date(couponData.startExpDate).getTime()),
      );
      const [endTime, setEndTime] = useState(
        new Date(new Date(couponData.endExpDate).getTime()),
      );
    
    • 를 이용해 다시 date객체 형식으로 바꿔준다.
    • 이후는 쿠폰추가와 같다.
  • 다만 수정이기에
		_updateCoupon: (state, action) => {
      for (let i = 0; i < state.coupon.length; i++) {
        if (i === action.payload.idx) {
          state.coupon[i] = action.payload.coupon;
        }
      }
    },
  • 를 이용해서 관련 쿠폰만 수정을 한다.
    • 여기서 idx는 쿠폰목록을 가져올때의(useSelector 이용) 그 index이다.
    • 목록을 그릴때 보통 map 함수를 이용할텐데 이때의 index속성을 이용하는 것이다.
    • (처음에는 서버의 id를 이용했었는데 백엔드분께 DB의 id는 안쓰는 것을 추천한다고 말을 듣고 이 방법을 추천받아서 수정과 삭제 모두에 사용했다. 아주 좋다!)
    function Items({ currentItems, updateState, deleteState }) {
      return (
        <Fragment>
          {currentItems &&
            currentItems.map((v, idx) => (
              <CouponCard
                event={v}
                idx={idx}
                updateState={updateState}
                deleteState={deleteState}
              />
            ))}
        </Fragment>
      );
    }
    
  • 삭제의 경우는 수정과 비슷하되
_deleteCoupon: (state, action) => {
      const deleteCoupon_list = state.coupon.filter((v, index) => {
        return index === action.payload ? false : true;
      });
      state.coupon = deleteCoupon_list;
    },
  • 로 하면 된다.