From 1e6142c4bfe7fdf4994746ef0019bd6c3025d6c9 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 15 Jul 2026 18:51:47 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EB=A1=9C=EB=9D=A0=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EB=8B=A8=EC=88=9C=ED=99=94=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StatisticsCalendarContainer.tsx | 37 +------------------ .../components/lottie/LottiePlayer.tsx | 2 +- 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx index 2472c9a5..160ea7a5 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx @@ -14,28 +14,6 @@ interface StatisticsCalendarContainerProps { onSelectDate: (date: Date) => void; } -interface StatisticsCalendarStatusProps { - lottieSrc: string; - message: string; - role?: "status" | "alert"; -} - -const StatisticsCalendarStatus = ({ - lottieSrc, - message, - role = "status", -}: StatisticsCalendarStatusProps) => { - return ( -
- -

{message}

-
- ); -}; - export const StatisticsCalendarContainer = ({ currentMonth, displayDate, @@ -48,22 +26,11 @@ export const StatisticsCalendarContainer = ({ const calendarData = calendarQuery.data?.data; if (calendarQuery.isPending) { - return ( - - ); + return ; } if (calendarQuery.isError || !calendarData) { - return ( - - ); + return ; } return ( diff --git a/apps/timo-web/components/lottie/LottiePlayer.tsx b/apps/timo-web/components/lottie/LottiePlayer.tsx index d94d49fe..a52d4f2d 100644 --- a/apps/timo-web/components/lottie/LottiePlayer.tsx +++ b/apps/timo-web/components/lottie/LottiePlayer.tsx @@ -38,7 +38,7 @@ export const LottiePlayer = ({ }, [src]); return ( -
+
{animationData && ( Date: Wed, 15 Jul 2026 21:02:28 +0900 Subject: [PATCH 2/7] =?UTF-8?q?refactor(web):=20=EC=BA=98=EB=A6=B0?= =?UTF-8?q?=EB=8D=94=20=ED=97=A4=EB=8D=94=20=EA=B3=A0=EC=A0=95=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsCalendar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx index 69d2756f..9ac6028f 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -85,7 +85,7 @@ export const StatisticsCalendar = ({ return (
-
+

{formatStatisticsMonth(currentMonth, locale)} From fbe7f89d224f742249180278b2e5b0bcb6f4e799 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 15 Jul 2026 21:54:34 +0900 Subject: [PATCH 3/7] =?UTF-8?q?fix(web):=20=EC=98=A4=EB=A5=B8=EC=AA=BD=20?= =?UTF-8?q?=ED=8C=A8=EB=84=90=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_components/StatisticsSidePanel.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx index 4037f77d..c31ce42f 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx @@ -102,14 +102,18 @@ export const StatisticsSidePanel = (props: StatisticsSidePanelProps) => {

    - {detail.todos.map((todo) => { + {detail.todos.map((todo, index) => { const diffMinutes = todo.actualTimeMinutes - todo.estimatedTimeMinutes; + const isLastTodo = index === detail.todos.length - 1; return (
  • @@ -128,7 +132,9 @@ export const StatisticsSidePanel = (props: StatisticsSidePanelProps) => { {formatStatisticsClockText(todo.estimatedTimeMinutes)} - + {getDiffLabel(diffMinutes, t)}

    From e1b90fc467d686a6111b22836ee64a1c126466a0 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 15 Jul 2026 22:03:24 +0900 Subject: [PATCH 4/7] =?UTF-8?q?fix(web):=20=ED=86=B5=EA=B3=84=20=EC=BA=98?= =?UTF-8?q?=EB=A6=B0=EB=8D=94=EC=99=80=20=EC=82=AC=EC=9D=B4=EB=93=9C=20?= =?UTF-8?q?=ED=8C=A8=EB=84=90=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsSidePanel.tsx | 2 +- .../(main)/statistics/_containers/StatisticsContainer.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx index c31ce42f..35b72c2a 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsSidePanel.tsx @@ -28,7 +28,7 @@ export type StatisticsSidePanelProps = | StatisticsDaySidePanelProps; const SIDE_PANEL_CLASS_NAME = - "border-timo-gray-500 bg-white h-full w-[304px] shrink-0 border-l text-timo-black"; + "border-timo-gray-500 bg-white h-full w-[304px] shrink-0 overflow-y-auto border-l text-timo-black"; const getDiffLabel = ( diffMinutes: number, diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx index 73dd709f..361ba886 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx @@ -69,13 +69,13 @@ export const StatisticsContainer = () => { }; return ( -
    -
    +
    +
    -
    +
    Date: Wed, 15 Jul 2026 22:13:29 +0900 Subject: [PATCH 5/7] =?UTF-8?q?fix(web):=20=EB=B0=B0=EA=B2=BD=EC=83=89=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsCalendar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx index 9ac6028f..98b16dad 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -85,7 +85,7 @@ export const StatisticsCalendar = ({ return (
    -
    +

    {formatStatisticsMonth(currentMonth, locale)} @@ -112,7 +112,7 @@ export const StatisticsCalendar = ({

    -
    +
    {Array.from({ length: firstDayOffset }, (_, index) => (
    ))} From 353c878abcd520b68727b99851a57630bc2aa672 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 15 Jul 2026 22:43:39 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix(web):=20=ED=88=AC=EB=91=90=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=ED=9B=84=20=ED=86=B5=EA=B3=84=20=EC=BA=90=EC=8B=9C?= =?UTF-8?q?=20=EA=B0=B1=EC=8B=A0=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../home/_hooks/use-home-todos-by-date.ts | 11 +++++++-- .../use-statistics-query-invalidation.ts | 23 +++++++++++++++++++ .../timer/use-timer-query-invalidation.ts | 4 ++++ .../create/use-create-todo-submit.ts | 3 +++ .../detail/use-delete-todo-submit.ts | 3 +++ .../detail/use-update-todo-submit.ts | 3 +++ 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 apps/timo-web/hooks/statistics/use-statistics-query-invalidation.ts 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 fff1170b..b7c8340a 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 @@ -48,8 +48,12 @@ export const useHomeTodosByDate = ( const { mutate: changeSubtaskStatus } = useChangeSubtaskStatus(); const { mutate: reorderTodo } = useReorderTodo(); const { mutate: stopTimer } = useStopTimer(); - const { invalidateHomeView, invalidateTimerState, invalidateTimeBoxes } = - useTimerQueryInvalidation(); + const { + invalidateHomeView, + invalidateStatistics, + invalidateTimerState, + invalidateTimeBoxes, + } = useTimerQueryInvalidation(); const { mutate: startTimer } = useStartTimer({ mutation: { onSuccess: invalidateTimerState }, @@ -110,6 +114,7 @@ export const useHomeTodosByDate = ( invalidateHomeAndFocus(); invalidateTimeBoxes(); invalidateTodoDetail(dateKey, todoId); + invalidateStatistics(); }, onError: () => { setTodosByDate((prev) => ({ ...prev, [dateKey]: previous })); @@ -138,6 +143,7 @@ export const useHomeTodosByDate = ( onSuccess: () => { invalidateHomeAndFocus(); invalidateTodoDetail(dateKey, todoId); + invalidateStatistics(); }, }, ); @@ -206,6 +212,7 @@ export const useHomeTodosByDate = ( invalidateHomeAndFocus(); invalidateTimeBoxes(); invalidateTodoDetail(dateKey, todoId); + invalidateStatistics(); }, onError: () => { setTodosByDate((prev) => ({ ...prev, [dateKey]: previous })); diff --git a/apps/timo-web/hooks/statistics/use-statistics-query-invalidation.ts b/apps/timo-web/hooks/statistics/use-statistics-query-invalidation.ts new file mode 100644 index 00000000..b5acb0c2 --- /dev/null +++ b/apps/timo-web/hooks/statistics/use-statistics-query-invalidation.ts @@ -0,0 +1,23 @@ +"use client"; + +import { useQueryClient } from "@tanstack/react-query"; + +import { + getGetCalendarQueryKey, + getGetDailyQueryKey, + getGetSummaryQueryKey, +} from "@/api/generated/endpoints/statistics/statistics"; + +export const useStatisticsQueryInvalidation = () => { + const queryClient = useQueryClient(); + + const invalidateStatistics = () => { + queryClient.invalidateQueries({ queryKey: getGetSummaryQueryKey() }); + queryClient.invalidateQueries({ queryKey: getGetDailyQueryKey() }); + queryClient.invalidateQueries({ queryKey: getGetCalendarQueryKey() }); + }; + + return { + invalidateStatistics, + }; +}; diff --git a/apps/timo-web/hooks/timer/use-timer-query-invalidation.ts b/apps/timo-web/hooks/timer/use-timer-query-invalidation.ts index c9d009ea..e6ae32c8 100644 --- a/apps/timo-web/hooks/timer/use-timer-query-invalidation.ts +++ b/apps/timo-web/hooks/timer/use-timer-query-invalidation.ts @@ -5,9 +5,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { getGetHomeQueryKey } from "@/api/generated/endpoints/home/home"; import { getGetTimeBoxesQueryKey } from "@/api/generated/endpoints/time-box/time-box"; import { getGetActiveTimerQueryKey } from "@/api/generated/endpoints/timer/timer"; +import { useStatisticsQueryInvalidation } from "@/hooks/statistics/use-statistics-query-invalidation"; export const useTimerQueryInvalidation = () => { const queryClient = useQueryClient(); + const { invalidateStatistics } = useStatisticsQueryInvalidation(); const invalidateActiveTimer = () => queryClient.invalidateQueries({ queryKey: getGetActiveTimerQueryKey() }); @@ -19,11 +21,13 @@ export const useTimerQueryInvalidation = () => { invalidateActiveTimer(); invalidateHomeView(); invalidateTimeBoxes(); + invalidateStatistics(); }; return { invalidateActiveTimer, invalidateHomeView, + invalidateStatistics, invalidateTimeBoxes, invalidateTimerState, }; diff --git a/apps/timo-web/hooks/todo-modal/create/use-create-todo-submit.ts b/apps/timo-web/hooks/todo-modal/create/use-create-todo-submit.ts index d7074344..2db717c6 100644 --- a/apps/timo-web/hooks/todo-modal/create/use-create-todo-submit.ts +++ b/apps/timo-web/hooks/todo-modal/create/use-create-todo-submit.ts @@ -8,6 +8,7 @@ import type { CreateTodoRequest } from "@/schemas/todo/todo-schema"; import { getGetHomeQueryKey } from "@/api/generated/endpoints/home/home"; import { useCreateTodo } from "@/api/generated/endpoints/todo/todo"; +import { useStatisticsQueryInvalidation } from "@/hooks/statistics/use-statistics-query-invalidation"; import { todoCreateResponseSchema } from "@/schemas/todo/todo-schema"; const buildCreateTodoRequestBody = ( @@ -30,6 +31,7 @@ export const useCreateTodoSubmit = () => { const [isErrorToastOpen, setIsErrorToastOpen] = useState(false); const { mutate: createTodo } = useCreateTodo(); const queryClient = useQueryClient(); + const { invalidateStatistics } = useStatisticsQueryInvalidation(); const handleSubmit = (data: CreateTodoRequest) => { createTodo( @@ -44,6 +46,7 @@ export const useCreateTodoSubmit = () => { } queryClient.invalidateQueries({ queryKey: getGetHomeQueryKey() }); + invalidateStatistics(); }, onError: () => { setIsErrorToastOpen(true); diff --git a/apps/timo-web/hooks/todo-modal/detail/use-delete-todo-submit.ts b/apps/timo-web/hooks/todo-modal/detail/use-delete-todo-submit.ts index 0ad7d7da..1cd53a09 100644 --- a/apps/timo-web/hooks/todo-modal/detail/use-delete-todo-submit.ts +++ b/apps/timo-web/hooks/todo-modal/detail/use-delete-todo-submit.ts @@ -10,6 +10,7 @@ import { getGetTodayQueryKey, } from "@/api/generated/endpoints/home/home"; import { useDeleteTodo } from "@/api/generated/endpoints/todo/todo"; +import { useStatisticsQueryInvalidation } from "@/hooks/statistics/use-statistics-query-invalidation"; export interface DeleteTodoSubmitHandlers { onSuccess: () => void; @@ -19,6 +20,7 @@ export interface DeleteTodoSubmitHandlers { export const useDeleteTodoSubmit = () => { const { mutate: deleteTodo } = useDeleteTodo(); const queryClient = useQueryClient(); + const { invalidateStatistics } = useStatisticsQueryInvalidation(); const handleDelete = ( todoId: number, @@ -30,6 +32,7 @@ export const useDeleteTodoSubmit = () => { onSuccess: () => { queryClient.invalidateQueries({ queryKey: getGetHomeQueryKey() }); queryClient.invalidateQueries({ queryKey: getGetTodayQueryKey() }); + invalidateStatistics(); onSuccess(); }, onError, diff --git a/apps/timo-web/hooks/todo-modal/detail/use-update-todo-submit.ts b/apps/timo-web/hooks/todo-modal/detail/use-update-todo-submit.ts index b145e719..cd63a1de 100644 --- a/apps/timo-web/hooks/todo-modal/detail/use-update-todo-submit.ts +++ b/apps/timo-web/hooks/todo-modal/detail/use-update-todo-submit.ts @@ -13,6 +13,7 @@ import { getGetTodoDetailQueryKey, useUpdateTodo, } from "@/api/generated/endpoints/todo/todo"; +import { useStatisticsQueryInvalidation } from "@/hooks/statistics/use-statistics-query-invalidation"; export interface UpdateTodoSubmitParams { todoId: number; @@ -28,6 +29,7 @@ export interface UpdateTodoSubmitHandlers { export const useUpdateTodoSubmit = () => { const { mutate: updateTodo } = useUpdateTodo(); const queryClient = useQueryClient(); + const { invalidateStatistics } = useStatisticsQueryInvalidation(); const handleUpdate = ( { todoId, date, data }: UpdateTodoSubmitParams, @@ -42,6 +44,7 @@ export const useUpdateTodoSubmit = () => { queryClient.invalidateQueries({ queryKey: getGetTodoDetailQueryKey(todoId, { date }), }); + invalidateStatistics(); onSuccess?.(); }, onError, From b8be4b6b5ac14d63bdcc7e3a6cf0e2efc113dae7 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Thu, 16 Jul 2026 12:34:12 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix(web):=20=ED=86=B5=EA=B3=84=20=EC=BA=98?= =?UTF-8?q?=EB=A6=B0=EB=8D=94=20=EB=A1=9C=EB=94=A9=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=A0=9C=EA=B1=B0=20(#222)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_containers/StatisticsCalendarContainer.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx index 160ea7a5..10dfd4b9 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsCalendarContainer.tsx @@ -1,10 +1,7 @@ "use client"; -import { useTranslations } from "next-intl"; - import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; import { useStatisticsCalendarQuery } from "@/app/[locale]/(main)/statistics/_queries/use-statistics-query"; -import { LottiePlayer } from "@/components/lottie/LottiePlayer"; import { formatDateKey } from "@/utils/date/date"; interface StatisticsCalendarContainerProps { @@ -20,17 +17,12 @@ export const StatisticsCalendarContainer = ({ selectedDate, onSelectDate, }: StatisticsCalendarContainerProps) => { - const t = useTranslations("Statistics.calendar"); const yearMonth = formatDateKey(currentMonth).slice(0, 7); const calendarQuery = useStatisticsCalendarQuery(yearMonth); const calendarData = calendarQuery.data?.data; - if (calendarQuery.isPending) { - return ; - } - - if (calendarQuery.isError || !calendarData) { - return ; + if (calendarQuery.isPending || calendarQuery.isError || !calendarData) { + return null; } return (