From 557895af763833e29809572ec5c28a471df56e76 Mon Sep 17 00:00:00 2001 From: Kjiw0n Date: Fri, 19 Jul 2024 06:47:33 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20timeblock=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=82=AC=EC=9D=B4=EC=A6=88=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=88(=EC=8B=9C=EA=B0=84=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8)=20=EC=88=98=EC=A0=95=20api=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fullCalendar/FullCalendarBox.tsx | 93 +++++++++++-------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/src/components/common/fullCalendar/FullCalendarBox.tsx b/src/components/common/fullCalendar/FullCalendarBox.tsx index e9120cd9..2d911414 100644 --- a/src/components/common/fullCalendar/FullCalendarBox.tsx +++ b/src/components/common/fullCalendar/FullCalendarBox.tsx @@ -1,10 +1,10 @@ import styled from '@emotion/styled'; -import { ViewMountArg, DatesSetArg, EventClickArg } from '@fullcalendar/core'; +import { ViewMountArg, DatesSetArg, EventClickArg, EventDropArg } from '@fullcalendar/core'; import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; import FullCalendar from '@fullcalendar/react'; import timeGridPlugin from '@fullcalendar/timegrid'; -import { DateSelectArg } from 'fullcalendar/index.js'; +import { DateSelectArg, EventResizeDoneArg } from 'fullcalendar/index.js'; import { useState, useRef, useEffect } from 'react'; import Modal from '../modal/Modal'; @@ -13,6 +13,7 @@ import processEvents from './processEvents'; import useGetTimeBlock from '@/apis/timeBlocks/getTimeBlock/query'; import usePostTimeBlock from '@/apis/timeBlocks/postTimeBlock/query'; +import useUpdateTimeBlock from '@/apis/timeBlocks/updateTimeBlock/query'; import RefreshBtn from '@/components/common/button/RefreshBtn'; import DayHeaderContent from '@/components/common/fullCalendar/DayHeaderContent'; import FullCalendarLayout from '@/components/common/fullCalendar/FullCalendarStyle'; @@ -28,12 +29,28 @@ interface FullCalendarBoxProps { function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxProps) { const today = new Date().toDateString(); + const todayDate = new Date().toISOString().split('T')[0]; const [currentView, setCurrentView] = useState('timeGridWeek'); const [range, setRange] = useState(7); - const todayDate = new Date().toISOString().split('T')[0]; const [startDate, setStartDate] = useState(todayDate); - const [isModalOpen, setModalOpen] = useState(false); + const [top, setTop] = useState(0); + const [left, setLeft] = useState(0); + + const calendarRef = useRef(null); + + const { data: timeBlockData } = useGetTimeBlock({ startDate, range }); + const { mutate: createMutate } = usePostTimeBlock(); + const { mutate: updateMutate } = useUpdateTimeBlock(); + + const calendarEvents = timeBlockData ? processEvents(timeBlockData.data.data) : []; + + useEffect(() => { + if (selectDate && calendarRef.current) { + const calendarApi = calendarRef.current.getApi(); + calendarApi.gotoDate(selectDate); + } + }, [selectDate]); const handleViewChange = (view: ViewMountArg) => { setCurrentView(view.view.type); @@ -41,12 +58,12 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr }; const handleDatesSet = (dateInfo: DatesSetArg) => { - setCurrentView(dateInfo.view.type); const currentViewType = dateInfo.view.type; const newStartDate = new Date(dateInfo.start); newStartDate.setDate(newStartDate.getDate() + 1); const formattedStartDate = newStartDate.toISOString().split('T')[0]; + setCurrentView(dateInfo.view.type); setStartDate(formattedStartDate); updateRange(currentViewType); }; @@ -67,17 +84,6 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr } }; - const calendarRef = useRef(null); - useEffect(() => { - if (selectDate && calendarRef.current) { - const calendarApi = calendarRef.current.getApi(); - calendarApi.gotoDate(selectDate); - } - }, [selectDate]); - - const [top, setTop] = useState(0); - const [left, setLeft] = useState(0); - const handleEventClick = (info: EventClickArg) => { const rect = info.el.getBoundingClientRect(); const calculatedTop = rect.top; @@ -87,25 +93,14 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr setModalOpen(true); }; - /** 모달 닫기 */ const closeModal = () => { setModalOpen(false); }; - // Get timeblock - const { data: timeBlockData } = useGetTimeBlock({ startDate, range }); - console.log('timeBlockData.data.data', timeBlockData?.data.data); - - const { mutate } = usePostTimeBlock(); - - const calendarEvents = timeBlockData ? processEvents(timeBlockData.data.data) : []; - - /** 드래그해서 이벤트 추가하기 */ const addEventWhenDragged = (selectInfo: DateSelectArg) => { if (calendarRef.current && (selectedTarget?.id === 0 || selectedTarget)) { const calendarApi = calendarRef.current.getApi(); - // 기존에 같은 id 가진 이벤트가 캘린더에 있다면 삭제 const existingEvents = calendarApi.getEvents(); existingEvents.forEach((event) => { if (event.id === selectedTarget.id.toString()) { @@ -113,7 +108,6 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr } }); - // 이벤트 추가 calendarApi.addEvent({ id: selectedTarget.id.toString(), title: selectedTarget.name, @@ -121,22 +115,43 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr end: selectInfo.endStr, allDay: selectInfo.allDay, classNames: 'tasks', + extendedProps: { + taskId: selectedTarget.id, + timeBlockId: null, + }, }); - // console.log('selectedTarget.name,', selectedTarget.name); - const removeTimezone = (str: string) => str.replace(/:\d{2}[+-]\d{2}:\d{2}$/, ''); const startStr = removeTimezone(selectInfo.startStr); const endStr = removeTimezone(selectInfo.endStr); - // console.log('selectedTarget.id.toString(),', selectedTarget.id.toString()); - // console.log('startStr:', startStr); - // console.log('endStr:', endStr); + createMutate({ taskId: selectedTarget.id, startTime: startStr, endTime: endStr }); + } + }; + + const updateEvent = (info: EventDropArg | EventResizeDoneArg) => { + const { event } = info; + const { taskId, timeBlockId } = event.extendedProps; + const removeTimezone = (str: string) => str.replace(/:\d{2}[+-]\d{2}:\d{2}$/, ''); + + const startStr = removeTimezone(event.startStr); + const endStr = removeTimezone(event.endStr); - mutate({ taskId: selectedTarget.id, startTime: startStr, endTime: endStr }); + updateMutate({ taskId, timeBlockId, startTime: startStr, endTime: endStr }); + }; + + const handleSelect = (selectInfo: DateSelectArg) => { + if (calendarRef.current) { + const calendarApi = calendarRef.current.getApi(); + calendarApi.unselect(); + } + + if (selectedTarget) { + addEventWhenDragged(selectInfo); } }; + return ( @@ -168,7 +183,6 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr selectable nowIndicator dayMaxEvents - // netshell에서 할당한 이벤트 : tasks, 구글 캘린더에서 가져온 이벤트 : schedule events={calendarEvents} buttonText={{ today: '오늘', @@ -195,19 +209,20 @@ function FullCalendarBox({ size, selectDate, selectedTarget }: FullCalendarBoxPr minute: '2-digit', hour12: false, }} - droppable={true} + droppable eventClick={handleEventClick} - select={addEventWhenDragged} + select={handleSelect} // 선택된 날짜가 변경될 때마다 호출 + eventDrop={updateEvent} // 기존 이벤트 드래그 수정 핸들러 + eventResize={updateEvent} // 기존 이벤트 리사이즈 수정 핸들러 /> {isModalOpen && ( - // 🚨 임시 taskID ... 데이터 형식 확정 후 수정할 것 🚨 )}