diff --git a/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts b/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts index 7d2c5ad8..3bab7f1b 100644 --- a/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts +++ b/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts @@ -42,7 +42,8 @@ export const useHomeTodosByDate = ( const [todosByDate, setTodosByDate] = useState>({}); const openTimerPanel = useTimeSidebarStore((state) => state.openTimerPanel); const queryClient = useQueryClient(); - const { data: activeTimer } = useActiveTimer(); + const { data: activeTimer, isFetching: isActiveTimerFetching } = + useActiveTimer(); const { mutate: changeTodoStatus } = useChangeTodoStatus(); const { mutate: changeSubtaskStatus } = useChangeSubtaskStatus(); const { mutate: reorderTodo } = useReorderTodo(); @@ -54,22 +55,27 @@ export const useHomeTodosByDate = ( invalidateFocusTodo, } = useTimerQueryInvalidation(); - const { mutate: startTimer } = useStartTimer({ - mutation: { - onSuccess: () => { - invalidateTimerState(); - invalidateFocusTodo(); + const { mutate: startTimer, isPending: isStartTimerPending } = + useStartTimer({ + mutation: { + onSuccess: () => { + invalidateTimerState(); + invalidateFocusTodo(); + }, }, - }, - }); - const { mutate: changeStatus } = useChangeStatus({ - mutation: { - onSuccess: () => { - invalidateTimerState(); - invalidateFocusTodo(); + }); + const { mutate: changeStatus, isPending: isChangeStatusPending } = + useChangeStatus({ + mutation: { + onSuccess: () => { + invalidateTimerState(); + invalidateFocusTodo(); + }, }, - }, - }); + }); + + const isTimerActionPending = + isStartTimerPending || isChangeStatusPending || isActiveTimerFetching; useEffect(() => { setTodosByDate( @@ -157,6 +163,8 @@ export const useHomeTodosByDate = ( }; const handleTogglePlay = (dateKey: string, todoId: number) => { + if (isTimerActionPending) return; + const willRun = todosByDate[dateKey]?.find((todo) => todo.todoId === todoId) ?.timerStatus !== "RUNNING"; @@ -260,6 +268,7 @@ export const useHomeTodosByDate = ( return { todosByDate, activeTimer, + isTimerActionPending, handleToggleCompleted, handleTogglePlay, handleToggleSubtaskCompleted, diff --git a/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts b/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts index 5e087253..c3b013c6 100644 --- a/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts +++ b/apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts @@ -40,7 +40,8 @@ export const useTodayTodoList = ( const [todos, setTodos] = useState(initialTodos); const openTimerPanel = useTimeSidebarStore((state) => state.openTimerPanel); const queryClient = useQueryClient(); - const { data: activeTimer } = useActiveTimer(); + const { data: activeTimer, isFetching: isActiveTimerFetching } = + useActiveTimer(); const { mutate: changeTodoStatus } = useChangeTodoStatus(); const { mutate: changeSubtaskStatus } = useChangeSubtaskStatus(); const { mutate: stopTimer } = useStopTimer(); @@ -51,7 +52,7 @@ export const useTodayTodoList = ( invalidateFocusTodo, } = useTimerQueryInvalidation(); - const { mutate: startTimer } = useStartTimer({ + const { mutate: startTimer, isPending: isStartTimerPending } = useStartTimer({ mutation: { onSuccess: () => { invalidateTimerState(); @@ -59,14 +60,19 @@ export const useTodayTodoList = ( }, }, }); - const { mutate: changeStatus } = useChangeStatus({ - mutation: { - onSuccess: () => { - invalidateTimerState(); - invalidateFocusTodo(); + + const { mutate: changeStatus, isPending: isChangeStatusPending } = + useChangeStatus({ + mutation: { + onSuccess: () => { + invalidateTimerState(); + invalidateFocusTodo(); + }, }, - }, - }); + }); + + const isTimerActionPending = + isStartTimerPending || isChangeStatusPending || isActiveTimerFetching; useEffect(() => { setTodos(initialTodos); @@ -145,6 +151,8 @@ export const useTodayTodoList = ( }; const handlePlay = (todoId: number) => { + if (isTimerActionPending) return; + const dateKey = todos.find((todo) => todo.todoId === todoId)?.date; if (!dateKey) return; @@ -231,6 +239,7 @@ export const useTodayTodoList = ( return { todos, activeTimer, + isTimerActionPending, handlePlay, handleToggleCompleted, handleDelete, diff --git a/apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx b/apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx index c80dbb85..456de63c 100644 --- a/apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx +++ b/apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx @@ -3,7 +3,7 @@ import { keepPreviousData } from "@tanstack/react-query"; import { useTranslations } from "next-intl"; import { overlay } from "overlay-kit"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import type { ErrorType } from "@/api/client/custom-instance"; import type { ErrorDto, TodoUpdateRequest } from "@/api/generated/models"; @@ -153,6 +153,9 @@ export const DetailTodoModalContainer = ({ const [actionErrorMessage, setActionErrorMessage] = useState(""); const [isActionErrorToastOpen, setIsActionErrorToastOpen] = useState(false); + const onTogglePlayRef = useRef(onTogglePlay); + onTogglePlayRef.current = onTogglePlay; + const showActionErrorToast = useCallback( (error: ErrorType) => { setActionErrorMessage( @@ -171,7 +174,7 @@ export const DetailTodoModalContainer = ({ isOpen={isOpen} onClose={close} onExited={unmount} - onTogglePlay={onTogglePlay} + onTogglePlay={() => onTogglePlayRef.current()} onToggleCompleted={onToggleCompleted} onDelete={onDelete} onActionError={showActionErrorToast}