기념일 계산 프로그램

LeeHyein·2024년 1월 23일

Side Project

목록 보기
1/1

어떤날 부터 오늘까지 지난 날짜를 계산하고
다른날 까지 남은 날짜를 계산하는 프로그램이다
그냥 갑자기 Date 활용하면 만들 수 있을 거 같아서 도전

Date 객체의 주요 함수를 이용하여 날짜와 시간정보를 가져와 작성할 예정이다
뼈대인 HTNL을 작성하였다 버튼은 사용자 입력값을 받을 예정이고 기념일이나
날짜부분은 아무 숫자나 임의로 값을 설정하였다 값이 바뀌어야 할 부분에 각각 id 를 붙여주었다

기능구현이 목적이라 css는 따로 설정해두지 않았다

Html ,js ,css 만으로 원하는걸 구현 할 수 있겠지만
리액트로 구현을 해보고 싶다는 생각을 하였다 (걍 나대지 말고 만들었으면 금방 끝났을텐데.....)

React에서 상태(state)를 관리하기 위해 useState를 이용해야 컴포넌트의 상태를 관리하고 동적으로 변경되는 데이터를 처리할 수 있기에 리액트로 작성한 코드는 다음과 같다

동일하게 동작하지만 의문점이 생겼다

반복하는 배열엔 map함수를 이용하여 각 배열의 정보를 동적으로 생성하게 하였고 결과는 동일 했다 useState를 통해 관리할 수 있게 되어서
리팩토링 안 했으면 기념일 추가고 뭐고 못 하지 않았을까

useState 배열에 600, 700 이렇게 수동으로 넣어 주는게 아니라
맨 아레 +버튼을 누르면 600일 700일 추가 되도록 만들어 문제를 해결하고자 한다


addNewAnniversaries이름의 함수를 만들어 아래 + 버튼에 onClick 함수를 엮어서 버튼이 누를 때 마다 이벤트가 발생하도록 하려고 한다

맨아래 붙은 초라한 +버튼

<button onClick={addNewAnniversaries}>+</button>
  // 새로운 기념일을 추가하는 함수
  const addNewAnniversaries = () => {
    // 현재 배열의 마지막 기념일을 가져온 뒤, 100씩 증가시켜 새로운 배열을 생성
    const lastAnniversary = parseInt(title[title.length - 1]); //마지막으로 추가된 기념일을 가져옵니다.
    const newAnniversaries = Array.from({ length: 1 }, (_, index) => `${lastAnniversary + (index + 1) * 100}일`);

    // 이전 기념일 배열과 새로운 배열을 합쳐 업데이트
    setTitle([...title, ...newAnniversaries]);
  }

parseInt함수를 이용하여 배열의 마지막 500일 에서 숫자 500을 추출 하여 100씩 더한값을 새로운 배열로 만들어 이전 기념일 배열과 합쳐주는 코드다 버튼 태그와 온클릭으로 엮어주니 버튼을 누를 때 마다 500이후의 배열이 추가된다

테스트영상
https://im7.ezgif.com/tmp/ezgif-7-259c2444a3.webp

기능구현 다 하지도 않았는데 힘들어죽겟다2시간반 걸린거 실화냐,,,,,,,,,,,,,,,,,,

실패를 격고 대폭 수정한 코드

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {
 const [anniversaries, setAnniversaries] = useState([]);
 const [remainingTime, setRemainingTime] = useState([]);
 const [inputTitle, setInputTitle] = useState('');
 const [inputDate, setInputDate] = useState('');
 const [todayDate, setTodayDate] = useState(formatDate(new Date()));
 const [firstMeetDate, setFirstMeetDate] = useState('');
 const [firstMeetDays, setFirstMeetDays] = useState(0);
 const [showModal, setShowModal] = useState(false);

 const addNewAnniversary = () => {
   if (inputTitle && inputDate) {
     const newAnniversaries = [...anniversaries];
     newAnniversaries.push({
       title: inputTitle,
       date: inputDate,
     });

     setAnniversaries(newAnniversaries);
     setRemainingTime([...remainingTime, null]);

     setInputTitle('');
     setInputDate('');
     handleModalClose();
   }
 };

 const setFirstMeet = (selectedDate) => {
   if (selectedDate) {
     setFirstMeetDate(selectedDate);
     const today = new Date(todayDate).getTime();
     const meetDay = new Date(selectedDate).getTime();
     const gap = today - meetDay;
     const days = Math.floor(gap / (1000 * 60 * 60 * 24));
     setFirstMeetDays(days);
   }
 };

 useEffect(() => {
   const intervalId = setInterval(() => {
     const now = new Date().getTime();

     const updatedRemainingTime = anniversaries.map((anniversary) => {
       const dday = new Date(anniversary.date).getTime();
       const gap = dday - now;

       const day = Math.floor(gap / (1000 * 60 * 60 * 24));
       const hour = Math.floor((gap % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
       const min = Math.floor((gap % (1000 * 60 * 60)) / (1000 * 60));
       const sec = Math.floor((gap % (1000 * 60)) / 1000);

       return {
         days: day,
         hours: hour,
         minutes: min,
         seconds: sec,
       };
     });

     setRemainingTime(updatedRemainingTime);
   }, 1000);

   return () => clearInterval(intervalId);
 }, [anniversaries]);

 useEffect(() => {
   setFirstMeet(firstMeetDate);
 }, [firstMeetDate, todayDate]);

 const handleModalClose = () => {
   setShowModal(false);
   setInputTitle('');
   setInputDate('');
 };

 return (
   <div className="app-container">
     <div className="day">
       <h3>오늘은 {todayDate}</h3>
       {firstMeetDate && <p>처음 만난 날로부터 {firstMeetDays}일이 지났어요!</p>}
       {anniversaries.map((anniversary, index) => (
         <div key={index} className="anniversary">
           <h3>{anniversary.title} _✏️{remainingTime[index]?.days}일</h3>
           {remainingTime[index] && (
             <p>남은 시간: {remainingTime[index].days}일 {remainingTime[index].hours}시간 {remainingTime[index].minutes}분 {remainingTime[index].seconds}초</p>
           )}
         </div>
       ))}
       <button onClick={() => setShowModal(true)}>새로운 기념일 추가</button>
       <input type="date" value={firstMeetDate} onChange={(e) => setFirstMeetDate(e.target.value)} />
       <button onClick={() => setFirstMeet(firstMeetDate)}>처음 만난 날 설정</button>
     </div>

     {showModal && (
       <div className="modal">
         <div className="modal-content">
           <span className="close" onClick={handleModalClose}>x</span>
           <h2>새로운 기념일 추가</h2>
           <input type="text" placeholder="기념일 제목" value={inputTitle} onChange={(e) => setInputTitle(e.target.value)} />
           <input type="date" value={inputDate} onChange={(e) => setInputDate(e.target.value)} />
           <button onClick={addNewAnniversary}>확인</button>
         </div>
       </div>
     )}
   </div>
 );
}

function formatDate(date) {
 const year = date.getFullYear();
 let month = date.getMonth() + 1;
 let day = date.getDate();

 month = month < 10 ? `0${month}` : month;
 day = day < 10 ? `0${day}` : day;

 return `${year}-${month}-${day}`;
}

export default App;

여기까지 해보고 깨닳은점

    리액트는 State 없으면 아무것도 못함
    원하는걸 만드려면 State 외에 다른 훅이 필요함
    컴포넌트 분리 해야함 계획없이 하고싶은거 할려 하니까 코드 갈아엎게됨
```jsx
   import React, { useState, useEffect } from "react";
  import "./App.css";

  function App() {
    const [anniversaries, setAnniversaries] = useState([]); //D-DAY목록
    const [inputValues, setInputValues] = useState({ title: '', date: '' }); //입력폼
    const [todayDate, setTodayDate] = useState(formatDate(new Date())); //현재날짜
    const [firstMeetDate, setFirstMeetDate] = useState('');  //처음만난 날
    const [firstMeetDays, setFirstMeetDays] = useState(0);  ///처음 만나 날로부터 경과하 일 수
    const [showModal, setShowModal] = useState(false); ///모달 표시여부
    const [showFirstMeetForm, setShowFirstMeetForm] = useState(false); //처음 만난 날 설정 폼 표시여부

    const addNewAnniversary = () => {
      if (inputValues.title && inputValues.date) {
        const selectedDate = new Date(inputValues.date).getTime();
        const today = new Date(todayDate).getTime();

        if (selectedDate >= today) {
          setAnniversaries((prevAnniversaries) => [
            ...prevAnniversaries,
            { title: inputValues.title, date: inputValues.date }
          ]);
          setInputValues({ title: '', date: '' });
          handleModalClose();
        } else {
          alert("날짜를 현재 날짜 이후로 선택해주세요.");
        }
      }
    };

    const setFirstMeet = (selectedDate) => {
      if (selectedDate) {
        const today = new Date(todayDate).getTime();
        const meetDay = new Date(selectedDate).getTime();
        const gap = today - meetDay;
        const daysDifference = Math.floor(gap / (1000 * 60 * 60 * 24));

        if (daysDifference >= 0) {
          setFirstMeetDate(selectedDate);
          setFirstMeetDays(daysDifference);
        } else {
          alert("날짜를 현재 날짜 이전으로 선택해주세요.");
        }
      }
    };

    useEffect(() => {
      const intervalId = setInterval(() => {
        const now = new Date().getTime();

        setAnniversaries((prevAnniversaries) => {
          return prevAnniversaries.map((anniversary) => {
            const dday = new Date(anniversary.date).getTime();
            const gap = dday - now;

            return {
              ...anniversary,
              remainingTime: {
                days: Math.floor(gap / (1000 * 60 * 60 * 24)),
              },
            };
          });
        });
      }, 1000);

      return () => clearInterval(intervalId);
    }, []);

    useEffect(() => {
      setFirstMeet(firstMeetDate);
    }, [firstMeetDate, todayDate]);

    const handleModalClose = () => {
      setShowModal(false);
      setInputValues({ title: '', date: '' });
      setShowFirstMeetForm(false);
    };

    return (
      <div className="app-container">

        <div className="day">
          <h3>오늘은 {todayDate}</h3>
          {firstMeetDate && <p>우리만난지 {firstMeetDays}일</p>}
          <button onClick={() => setShowFirstMeetForm(true)}>처음 만난 날 설정</button>


          {showFirstMeetForm && (
            <div>
              <input type="date" value={firstMeetDate} onChange={(e) => setFirstMeetDate(e.target.value)} />
              <button onClick={() => { setFirstMeet(firstMeetDate); setShowFirstMeetForm(false); }}>확인</button>
            </div>
          )}
        <button onClick={() => setShowModal(true)}>New D-day</button>

          {anniversaries.map((anniversary, index) => (
            <div key={index} className="anniversary">
              <h3>{anniversary.title} _✏️{Math.max(0, anniversary.remainingTime?.days)}일</h3>
            </div>
          ))}






          {showModal && (
            <div className="modal">
              <div className="modal-content">
                <span className="close" onClick={handleModalClose}>x</span>
                <h2>New D-day</h2>
                <input
                  type="text"
                  placeholder="기념일 제목"
                  value={inputValues.title}
                  onChange={(e) => setInputValues({ ...inputValues, title: e.target.value })}
                />
                <input
                  type="date"
                  value={inputValues.date}
                  onChange={(e) => setInputValues({ ...inputValues, date: e.target.value })}
                />
                <button onClick={addNewAnniversary}>확인</button>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }

  const formatDate = (date) => {
    const year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();

    month = month < 10 ? `0${month}` : month;
    day = day < 10 ? `0${day}` : day;

    return `${year}-${month}-${day}`;
  };


  export default App;
 
profile
응애개발자 입니다

0개의 댓글