From d2c7899c64ab9698e86a52d901da1917396b2393 Mon Sep 17 00:00:00 2001 From: Yeonjin Kim Date: Thu, 18 Jun 2026 14:03:22 +0900 Subject: [PATCH 1/4] style: align event detail card text (#120) --- .../Calendar/components/EventDetailCard/EventDetailCard.style.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/Calendar/components/EventDetailCard/EventDetailCard.style.ts b/src/features/Calendar/components/EventDetailCard/EventDetailCard.style.ts index 0112e53..80d45aa 100644 --- a/src/features/Calendar/components/EventDetailCard/EventDetailCard.style.ts +++ b/src/features/Calendar/components/EventDetailCard/EventDetailCard.style.ts @@ -43,6 +43,7 @@ export const Content = styled.div` export const TextWrapper = styled.div` display: flex; flex-direction: column; + align-items: flex-start; gap: 8px; ` From e5ae8dd56e80eda230265f125603af6086683ff9 Mon Sep 17 00:00:00 2001 From: Yeonjin Kim Date: Sun, 21 Jun 2026 11:33:49 +0900 Subject: [PATCH 2/4] =?UTF-8?q?style:=20=ED=98=B8=EB=B2=84=20=EC=8B=9C=20p?= =?UTF-8?q?ointer=EB=A1=9C=20=EB=A7=88=EC=9A=B0=EC=8A=A4=20=EC=BB=A4?= =?UTF-8?q?=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/Todo/components/TodoCard/TodoCard.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/Todo/components/TodoCard/TodoCard.tsx b/src/features/Todo/components/TodoCard/TodoCard.tsx index 832c1ae..aba18c7 100644 --- a/src/features/Todo/components/TodoCard/TodoCard.tsx +++ b/src/features/Todo/components/TodoCard/TodoCard.tsx @@ -92,6 +92,7 @@ const TodoCard = ({ event.stopPropagation() handleDelete() }} + style={{ cursor: 'pointer' }} /> {openDeleteModal && isRecurringTodo && ( From 50b87a87f4cae22ed98e387d2d0c9545eb18e930 Mon Sep 17 00:00:00 2001 From: Yeonjin Kim Date: Sun, 21 Jun 2026 11:44:32 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20=EC=9E=84=EC=8B=9C=20=EC=9D=BC?= =?UTF-8?q?=EC=A0=95=EA=B3=BC=20=ED=95=A0=20=EC=9D=BC=20=EB=A1=9C=EC=BB=AC?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/Calendar/hooks/useCalendarDraftEvent.ts | 11 ++++++++--- src/features/Calendar/hooks/useCalendarEvents.ts | 4 +++- .../Calendar/utils/helpers/calendarPageHelpers.ts | 1 + src/shared/hooks/addSchedule/useScheduleFooter.tsx | 9 ++++++++- src/shared/hooks/addSchedule/useSchedulePatch.ts | 2 +- src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts | 3 ++- src/shared/hooks/addTodo/useTodoDetailHydration.ts | 5 ++++- src/shared/hooks/addTodo/useTodoFooter.tsx | 7 ++++++- src/shared/hooks/form/useTodoEditorForm.ts | 2 +- src/shared/types/calendar/types.ts | 1 + src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx | 1 + 11 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/features/Calendar/hooks/useCalendarDraftEvent.ts b/src/features/Calendar/hooks/useCalendarDraftEvent.ts index f8d9d50..f794066 100644 --- a/src/features/Calendar/hooks/useCalendarDraftEvent.ts +++ b/src/features/Calendar/hooks/useCalendarDraftEvent.ts @@ -32,11 +32,16 @@ export const useCalendarDraftEvent = ({ updateEventTiming, }: UseCalendarDraftEventArgs) => { const handleCloseModalWithCleanup = useCallback(() => { - if (!isModalEditing && modal.eventId != null) { - removeEvent(modal.eventId) + if (modal.eventId != null) { + const shouldRemoveDraft = + !isModalEditing || + events.some((eventItem) => eventItem.id === modal.eventId && eventItem.isTemporary) + if (shouldRemoveDraft) { + removeEvent(modal.eventId) + } } handleCloseModal() - }, [handleCloseModal, isModalEditing, modal.eventId, removeEvent]) + }, [events, handleCloseModal, isModalEditing, modal.eventId, removeEvent]) const clearPendingDraftEvent = useCallback(() => { if (!modal.isOpen || isModalEditing || modal.eventId == null) return diff --git a/src/features/Calendar/hooks/useCalendarEvents.ts b/src/features/Calendar/hooks/useCalendarEvents.ts index c7653be..ff780a6 100644 --- a/src/features/Calendar/hooks/useCalendarEvents.ts +++ b/src/features/Calendar/hooks/useCalendarEvents.ts @@ -144,7 +144,9 @@ export const useCalendarEvents = (options: UseCalendarEventsOptions = {}) => { // 서버 응답 후 임시 이벤트 id를 실제 id로 교체 const updateEventId = useCallback((tempId: CalendarEvent['id'], nextId: CalendarEvent['id']) => { setEvents((prev) => - prev.map((event) => (event.id === tempId ? { ...event, id: nextId } : event)), + prev.map((event) => + event.id === tempId ? { ...event, id: nextId, isTemporary: false } : event, + ), ) }, []) diff --git a/src/features/Calendar/utils/helpers/calendarPageHelpers.ts b/src/features/Calendar/utils/helpers/calendarPageHelpers.ts index 7ca43ed..5dbfc6c 100644 --- a/src/features/Calendar/utils/helpers/calendarPageHelpers.ts +++ b/src/features/Calendar/utils/helpers/calendarPageHelpers.ts @@ -34,6 +34,7 @@ export const createEvent = (date: Date, index: number, allDay = false): Calendar recurrenceGroup: null, friendIds: [], type: 'schedule', + isTemporary: true, } } diff --git a/src/shared/hooks/addSchedule/useScheduleFooter.tsx b/src/shared/hooks/addSchedule/useScheduleFooter.tsx index a36964f..32a60b1 100644 --- a/src/shared/hooks/addSchedule/useScheduleFooter.tsx +++ b/src/shared/hooks/addSchedule/useScheduleFooter.tsx @@ -58,6 +58,7 @@ export const useScheduleFooter = ({ const occurrenceDateRef = useRef(occurrenceDate) const closeModalRef = useRef(closeModal) const deleteEventMutateRef = useRef(deleteEventMutate) + const isTemporaryEventRef = useRef(Boolean(initialEvent?.isTemporary)) const canEditRef = useRef(canEdit) const onReadOnlyAttemptRef = useRef(onReadOnlyAttempt) const eventColorRef = useRef(eventColor) @@ -72,6 +73,7 @@ export const useScheduleFooter = ({ occurrenceDateRef.current = occurrenceDate closeModalRef.current = closeModal deleteEventMutateRef.current = deleteEventMutate + isTemporaryEventRef.current = Boolean(initialEvent?.isTemporary) canEditRef.current = canEdit onReadOnlyAttemptRef.current = onReadOnlyAttempt eventColorRef.current = eventColor @@ -86,6 +88,11 @@ export const useScheduleFooter = ({ onReadOnlyAttemptRef.current?.() return } + if (eventIdRef.current == null || eventIdRef.current === 0 || isTemporaryEventRef.current) { + setDeleteWarningVisible(false) + closeModalRef.current() + return + } if (repeatConfigRef.current.repeatType !== 'none') { setDeleteWarningVisible(true) return @@ -130,7 +137,7 @@ export const useScheduleFooter = ({ if (currentEventId != null && currentEventId !== 0) { onEventColorChangeRef.current?.(currentEventId, value) } - if (!isEditingRef.current) { + if (!isEditingRef.current || isTemporaryEventRef.current) { return } const nextValues = { ...getValuesRef.current(), eventColor: value } diff --git a/src/shared/hooks/addSchedule/useSchedulePatch.ts b/src/shared/hooks/addSchedule/useSchedulePatch.ts index 4c66d92..7dee458 100644 --- a/src/shared/hooks/addSchedule/useSchedulePatch.ts +++ b/src/shared/hooks/addSchedule/useSchedulePatch.ts @@ -80,7 +80,7 @@ export const useSchedulePatch = ({ }: UseSchedulePatchArgs) => useCallback( (values: ScheduleEditorFormValues, scope?: RecurrenceEventScope, occurrenceDate?: string) => { - if (eventId == null || eventId === 0) return Promise.resolve() + if (eventId == null || eventId === 0 || initialEvent?.isTemporary) return Promise.resolve() const startDate = values.eventStartDate ?? new Date(date) const endDate = values.eventEndDate ?? startDate const [start, end] = values.isAllday diff --git a/src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts b/src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts index ad0771e..cd2de0b 100644 --- a/src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts +++ b/src/shared/hooks/addSchedule/useScheduleSubmitFlow.ts @@ -81,6 +81,7 @@ export const useScheduleSubmitFlow = ({ }, []) const showToast = useToastStore.getState().showToast + const isTemporaryEvent = Boolean(initialEvent?.isTemporary) const confirmTitle = useCallback( (values: ScheduleEditorFormValues) => { @@ -163,7 +164,7 @@ export const useScheduleSubmitFlow = ({ return } await submitScheduleValues(values, { - mode: isEditing ? 'patch' : 'create', + mode: isEditing && !isTemporaryEvent ? 'patch' : 'create', }) }, (errors) => { diff --git a/src/shared/hooks/addTodo/useTodoDetailHydration.ts b/src/shared/hooks/addTodo/useTodoDetailHydration.ts index 21fb664..3c8a119 100644 --- a/src/shared/hooks/addTodo/useTodoDetailHydration.ts +++ b/src/shared/hooks/addTodo/useTodoDetailHydration.ts @@ -12,6 +12,7 @@ type UseTodoDetailHydrationProps = { date: string eventId: CalendarEvent['id'] isEditing: boolean + initialEvent?: CalendarEvent | null todoDate: Date | null setValue: UseFormSetValue } @@ -20,11 +21,13 @@ export const useTodoDetailHydration = ({ date, eventId, isEditing, + initialEvent, todoDate, setValue, }: UseTodoDetailHydrationProps) => { const hydratedDetailKeyRef = useRef(null) - const isPersistedTodo = isEditing && eventId != null && eventId !== 0 + const isPersistedTodo = + isEditing && eventId != null && eventId !== 0 && !initialEvent?.isTemporary const shouldFetchDetail = isPersistedTodo const detailOccurrenceDate = moment(date).format('YYYY-MM-DD') const { data: detailData } = useGetDetailTodoQuery( diff --git a/src/shared/hooks/addTodo/useTodoFooter.tsx b/src/shared/hooks/addTodo/useTodoFooter.tsx index 6140ff0..2aa6e70 100644 --- a/src/shared/hooks/addTodo/useTodoFooter.tsx +++ b/src/shared/hooks/addTodo/useTodoFooter.tsx @@ -99,7 +99,12 @@ export const useTodoFooter = ({ if (eventIdRef.current != null && eventIdRef.current !== 0) { onEventColorChangeRef.current?.(eventIdRef.current, value) } - if (!isEditingRef.current || eventIdRef.current == null || eventIdRef.current === 0) { + if ( + !isEditingRef.current || + eventIdRef.current == null || + eventIdRef.current === 0 || + !isPersistedTodoRef.current + ) { return } patchTodoMutateRef.current( diff --git a/src/shared/hooks/form/useTodoEditorForm.ts b/src/shared/hooks/form/useTodoEditorForm.ts index 8c7150a..d74e459 100644 --- a/src/shared/hooks/form/useTodoEditorForm.ts +++ b/src/shared/hooks/form/useTodoEditorForm.ts @@ -127,7 +127,7 @@ export const useTodoEditorForm = ({ recurrenceGroup, } - const isPersistedTodoId = typeof id === 'number' && id > 0 + const isPersistedTodoId = typeof id === 'number' && id > 0 && !initialEvent?.isTemporary if (isEditing && isPersistedTodoId) { const occurrenceDate = options?.occurrenceDate ?? formatIsoDate(date) return patchTodoMutate({ diff --git a/src/shared/types/calendar/types.ts b/src/shared/types/calendar/types.ts index 3661414..413e456 100644 --- a/src/shared/types/calendar/types.ts +++ b/src/shared/types/calendar/types.ts @@ -31,6 +31,7 @@ export type CalendarEvent = Omit & { type?: 'todo' | 'schedule' isDone?: boolean isRecurring?: boolean + isTemporary?: boolean } export type GetEventsResponseDTO = { diff --git a/src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx b/src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx index 81f0c4f..4d7cacc 100644 --- a/src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx +++ b/src/shared/ui/Modals/TodoEditor/TodoEditorContent.tsx @@ -39,6 +39,7 @@ const TodoEditorContent = ({ date, eventId, isEditing, + initialEvent, todoDate: todo.todoDate, setValue, }) From ef26d213695a642d48743bb05c467312f187cbc9 Mon Sep 17 00:00:00 2001 From: Yeonjin Kim Date: Sun, 21 Jun 2026 13:08:30 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20button=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B0=90=EC=8B=B8=EA=B8=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Todo/components/TodoCard/TodoCard.style.ts | 9 +++++++++ src/features/Todo/components/TodoCard/TodoCard.tsx | 10 ++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/features/Todo/components/TodoCard/TodoCard.style.ts b/src/features/Todo/components/TodoCard/TodoCard.style.ts index a37edf2..40a3adb 100644 --- a/src/features/Todo/components/TodoCard/TodoCard.style.ts +++ b/src/features/Todo/components/TodoCard/TodoCard.style.ts @@ -45,6 +45,15 @@ export const ButtonWrapper = styled.div` } } ` +export const DeleteButton = styled.button` + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0; + border: 0; + background: transparent; + cursor: pointer; +` export const TodoLeftWrapper = styled.div` display: flex; gap: 16px; diff --git a/src/features/Todo/components/TodoCard/TodoCard.tsx b/src/features/Todo/components/TodoCard/TodoCard.tsx index aba18c7..5f19aa0 100644 --- a/src/features/Todo/components/TodoCard/TodoCard.tsx +++ b/src/features/Todo/components/TodoCard/TodoCard.tsx @@ -86,14 +86,16 @@ const TodoCard = ({ - { event.stopPropagation() handleDelete() }} - style={{ cursor: 'pointer' }} - /> + > + + {openDeleteModal && isRecurringTodo && (