[희락] Fullcalendar (Events DB)수정

jaeyeon_lee·2024년 4월 1일

희락

목록 보기
5/8


현재 데이터베이스에서 이벤트를 불러올때 전체 데이터를 불러오게 되어있음!! 전체적인 데이터를 가져오는건 비효율적이라고 생각해서 Fullcalendar에서 보여지는 달에서 앞뒤달을 포함한 데이터를 가져오도록 수정함! (캘린더에 그 달에 해당하는 데이터만 가져오면 전달~해당달에 해당하는 데이터들이 안보임! 그래서 앞뒤로 한달씩 총 세달치를 가져오기로 함!)

Backend

event.route.ts

eventRouter
  .route("/")
  // .get(eventCtrl.getAllEvents)
  .get( (req, res, next) => {
    // 클라이언트가 날짜를 제공한 경우에는 getDateEvents 호출
    if (req.query.date) {
      return eventCtrl.getDateEvents(req, res, next);
    } else {
      // 그 외의 경우에는 getMonthEvents 호출
      return eventCtrl.getMonthEvents(req,res,next);
    }
  })

event.ctrl.ts

export const getMonthEvents = asyncHandler(async (req, res) => {
  console.log("Event Moth req.query:",req.query)
  const {year , month} = req.query as { year: string, month: string} ;
  const result = await findMonthEvents(year,month);
  res.json(result.rows);
});

event.db.ts

export const findMonthEvents = async (year: string, month: string) => {
  const startDate = new Date(`${year}-${month}-01`);

  // 시작 날짜로부터 앞뒤 한 달씩 총 세 달치의 범위 계산
  const startPreviousMonth = new Date(startDate);
  startPreviousMonth.setMonth(startPreviousMonth.getMonth() - 1);

  const startNextMonth = new Date(startDate);
  startNextMonth.setMonth(startNextMonth.getMonth() + 1);

  // 각 범위의 마지막 날짜를 계산
  const lastDayOfPreviousMonth = new Date(startPreviousMonth.getFullYear(), startPreviousMonth.getMonth() + 1, 0);
  const lastDayOfCurrentMonth = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 0);
  const lastDayOfNextMonth = new Date(startNextMonth.getFullYear(), startNextMonth.getMonth() + 1, 0);

  const result = await db.query<Event>('SELECT * FROM events WHERE start_date >= $1 AND start_date <= $2 OR start_date >= $3 AND start_date <= $4 OR start_date >= $5 AND start_date <= $6 ORDER BY start_date ASC',
    [startPreviousMonth, lastDayOfPreviousMonth, startDate, lastDayOfCurrentMonth, startNextMonth, lastDayOfNextMonth]);

  console.log("find three months events result:", result);

  return result
};

Frontend

InfoEvents.tsx

const fetchEvents = async (viewMonth: string) => {
    try {
      console.log("fetchEvents:", viewMonth);
      const year = viewMonth.split("-")[0];
      const month = viewMonth.split("-")[1];
      const events = await getMonthEvents(year, month);
      // 날짜 객체로 변환
      events.forEach((event: WithId<ChurchEvent>) => {
        event.start_date = new Date(event.start_date);
        event.end_date = new Date(event.end_date);
      });
      // console.log("converted date fetch events", events);

      const filteredEvents = events.filter((event: WithId<ChurchEvent>) => {
        const eventMonth = event.start_date.getMonth();
        const eventYear = event.start_date.getFullYear();
        const eventEndMonth = event.end_date.getMonth();
        const eventEndYear = event.end_date.getFullYear();
        return (
          (eventMonth === parseInt(month) - 1 &&
            eventYear === parseInt(year)) ||
          (eventEndMonth === parseInt(month) - 1 &&
            eventEndYear === parseInt(year))
        );
      });

      setFilteredEvents(filteredEvents);
      setEvents(events);
    } catch (error) {
      console.log("error", error);
    }
  };

  useEffect(() => {
    const initialViewMonth = `${new Date().getFullYear()}-${(new Date().getMonth() + 1).toString()}`;
    fetchEvents(initialViewMonth);
  }, []);

캘린더 밑에 해당 달에 있는 이벤트들이 드롭다운으로 나오게 되어있는데, 그 데이터를 넘겨줄때는 해당달에 있는 것(filteredevents)만 넘겨줌!

<Calendar events={events} onDataChange={handleDataChange} initialDate = {initialDate}/>
<div className="divide-y divide-slate-200">
            {filteredEvents.map((event) => (
              <div key={event.id}>
                <ChurchEventView
                  event={event}
                  selectEvent={handleSelectEvent}
                  onDelete={handleDelete}
                />
              </div>
            ))}
</div>

수정하거나 새로운 이벤트를 추가했을때 수정하거나 추가한 달을 캘린더에 보여지게 하고자함! 수정하거나 추가할때의 날짜를 Calendar 컴포넌트에 initialDate props로 전달해주고 fullcalendar에 initailDate옵션을 사용함!

infoEvents.tsx

const handleAddOrUpdateEvent = async (
    event: WithId<ChurchEvent> | ChurchEvent
  ) => {
    let addOrUpdatedMonth=""
    if ("id" in event) {
      // Update Church Event
      console.log("update event:", event);
      const result = await updateEvent(event);
      // console.log("updated event result:", result);
      addOrUpdatedMonth = getDateString(new Date(event.start_date));
      console.log("업데이트 달",addOrUpdatedMonth)
      setInitialDate(addOrUpdatedMonth);
    } else {
      // Add Church Event
      console.log("add new event", event);
      const result = await createEvent(event);
      console.log("created event result:", result.start_date);
      addOrUpdatedMonth = getDateString(new Date(result.start_date));
      setInitialDate(addOrUpdatedMonth);
    }
    await fetchEvents(addOrUpdatedMonth);
  };

Calendar.tsx

export const Calendar = ({ events , onDataChange, initialDate }: CalendarProps ) => {

  return (
    <div className="p-3">
      <FullCalendar
        plugins={[dayGridPlugin]}
        initialView="dayGridMonth"
        initialDate={initialDate}
        height={"500px"}
        locale={"ko"}
        titleFormat={{ month: "short" }}
        headerToolbar={{
          start: "title",
          end: "prev,today,next",
        }}
        buttonText={{
          // prev: "이전", // 부트스트랩 아이콘으로 변경 가능
          // next: "다음",
          // prevYear: "이전 년도",
          // nextYear: "다음 년도",
          today: "오늘",
          month: "월별",
          week: "주별",
          day: "일별",
          list: "리스트",
        }}
        events={events.map((event) => ({
          title: event.title,
          start: event.start_date,
          end: new Date(new Date(event.end_date).getTime() + 86400000), // 현재 날짜에 24시간(하루)을 더함
          allDay: true,
        }))}
        datesSet={(dateInfo) => {
          const viewMonth = dateInfo.view;
          const month = viewMonth.title.slice(0,1);
          const year = viewMonth.currentStart.getFullYear().toString(); // 현재 보고 있는 달력 뷰의 년도를 추출
          const newData = `${year}-${month}`
          console.log("nonth",month,"year",year,"newData",newData)
          onDataChange(newData)
        }}
      />
    </div>
  );
};

현재 fullcalendar로 보고 있는 달을 onDataChange로 infoevents로 전달하고, 전달한 값으로 데이터를 가져오고 필터링한 데이터는ChurchEventView 컴포넌트로 전달해줌! 가져온 3달치 데이터는 Calendar 컴포넌트로 전달! 그리고 수정 및 추가할때 해당하는 데이터의 날짜를 가져와 fullcalendar의 initialdate로 설정해 해당하는 달이 보여지게 수정함..!

profile
🙋🏻‍♀️

0개의 댓글