From 6aee5bd8a4311a248c4e0021d2c3bd63d192096d Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 00:29:55 +0900 Subject: [PATCH 01/22] =?UTF-8?q?feat(ui):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=8B=9C=EA=B3=84=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source/statistics-clock-disabled.svg | 4 ++++ .../statistics-clock-empty-selected.svg | 21 +++++++++++++++++++ .../icons/source/statistics-clock-empty.svg | 9 ++++++++ .../statistics-clock-filled-selected.svg | 21 +++++++++++++++++++ .../icons/source/statistics-clock-filled.svg | 7 +++++++ .../statistics-clock-light-selected.svg | 21 +++++++++++++++++++ .../icons/source/statistics-clock-light.svg | 7 +++++++ .../statistics-clock-outline-selected.svg | 21 +++++++++++++++++++ .../icons/source/statistics-clock-outline.svg | 7 +++++++ 9 files changed, 118 insertions(+) create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-empty.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-filled.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-light.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg create mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-outline.svg diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg b/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg new file mode 100644 index 0000000..69e0fe5 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg new file mode 100644 index 0000000..9becce8 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-empty.svg b/packages/timo-design-system/src/icons/source/statistics-clock-empty.svg new file mode 100644 index 0000000..ac08c2a --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-empty.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg new file mode 100644 index 0000000..5ee7078 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-filled.svg b/packages/timo-design-system/src/icons/source/statistics-clock-filled.svg new file mode 100644 index 0000000..5875877 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-filled.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg new file mode 100644 index 0000000..d5be223 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-light.svg b/packages/timo-design-system/src/icons/source/statistics-clock-light.svg new file mode 100644 index 0000000..bb9ebaf --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-light.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg new file mode 100644 index 0000000..3db735a --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-outline.svg b/packages/timo-design-system/src/icons/source/statistics-clock-outline.svg new file mode 100644 index 0000000..6c74fc2 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/statistics-clock-outline.svg @@ -0,0 +1,7 @@ + + + + + + + From 95a0be231ca176760ea6678b1a024517a9b22ea4 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 04:27:07 +0900 Subject: [PATCH 02/22] =?UTF-8?q?feat(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=9B=94=20=EC=83=81=ED=83=9C=EB=A5=BC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=EC=84=9C=20=EA=B4=80=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_containers/StatisticsHeaderContainer.tsx | 18 +++++++++++++----- .../app/[locale]/(main)/statistics/page.tsx | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx index 8f978ff..524cf02 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx @@ -1,10 +1,16 @@ "use client"; -import { useState } from "react"; +import type { Dispatch, SetStateAction } from "react"; import { Header } from "@/components/layout/header/Header"; import { useNavigationSidebar } from "@/components/layout/sidebar/navigation/NavigationSidebarContext"; + +interface StatisticsHeaderContainerProps { + currentMonth: Date; + onChangeMonth: Dispatch>; +} + const MONTH_LABEL_FORMATTER = new Intl.DateTimeFormat("en-US", { month: "long", }); @@ -12,12 +18,14 @@ const MONTH_LABEL_FORMATTER = new Intl.DateTimeFormat("en-US", { const addMonths = (date: Date, amount: number) => new Date(date.getFullYear(), date.getMonth() + amount, 1); -export const StatisticsHeaderContainer = () => { - const [currentMonth, setCurrentMonth] = useState(() => new Date()); +export const StatisticsHeaderContainer = ({ + currentMonth, + onChangeMonth, +}: StatisticsHeaderContainerProps) => { const { isOpen, toggle } = useNavigationSidebar(); - const handlePrev = () => setCurrentMonth((prev) => addMonths(prev, -1)); - const handleNext = () => setCurrentMonth((prev) => addMonths(prev, 1)); + const handlePrev = () => onChangeMonth((prev) => addMonths(prev, -1)); + const handleNext = () => onChangeMonth((prev) => addMonths(prev, 1)); return (
; + const [currentMonth, setCurrentMonth] = useState(() => new Date()); + + return ( + <> + + + + ); } From da32fc8eddb3ea13d127dafb45e81c82547425ca Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 04:30:56 +0900 Subject: [PATCH 03/22] =?UTF-8?q?feat(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=9D=91=EB=8B=B5=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_types/statistics.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_types/statistics.ts b/apps/timo-web/app/[locale]/(main)/statistics/_types/statistics.ts index febf963..5a1e7f3 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_types/statistics.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_types/statistics.ts @@ -22,6 +22,17 @@ export const statisticsDayDetailSchema = z.object({ todos: z.array(statisticsTodoRecordSchema), }); +export const statisticsCalendarResponseSchema = z.object({ + yearMonth: z.string(), + today: z.string(), + days: z.array( + z.object({ + date: z.string(), + completionRate: z.number().nullable(), + }), + ), +}); + export type StatisticsMonthSummary = z.infer< typeof statisticsMonthSummarySchema >; @@ -29,3 +40,7 @@ export type StatisticsMonthSummary = z.infer< export type StatisticsDayDetail = z.infer; export type StatisticsTodoRecord = z.infer; + +export type StatisticsCalendarResponse = z.infer< + typeof statisticsCalendarResponseSchema +>; From 3a7009a8e4e0df56b8e58a9998b995c31c50a8c3 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 04:31:28 +0900 Subject: [PATCH 04/22] =?UTF-8?q?feat(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EB=82=A0=EC=A7=9C=20=ED=8F=AC=EB=A7=B7=20=EC=9C=A0=ED=8B=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_utils/formatStatisticsDate.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts new file mode 100644 index 0000000..516bc0a --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts @@ -0,0 +1,14 @@ +export const formatStatisticsDate = (date: Date, locale: string) => { + return new Intl.DateTimeFormat(locale, { + year: "numeric", + month: "long", + day: "numeric", + weekday: "long", + }).format(date); +}; + +export const formatStatisticsMonth = (date: Date, locale: string) => { + return new Intl.DateTimeFormat(locale, { + month: "long", + }).format(date); +}; From 59c7870f96a271058279d8762af021214741ad4c Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 15:19:18 +0900 Subject: [PATCH 05/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EB=82=A0=EC=A7=9C=20=ED=8F=AC=EB=A7=B7=20=EC=9C=A0=ED=8B=B8=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_utils/formatStatisticsDate.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts index 516bc0a..5a054eb 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts @@ -1,14 +1,14 @@ -export const formatStatisticsDate = (date: Date, locale: string) => { +export const formatStatisticsMonth = (date: Date, locale = "ko") => { return new Intl.DateTimeFormat(locale, { - year: "numeric", month: "long", - day: "numeric", - weekday: "long", }).format(date); }; -export const formatStatisticsMonth = (date: Date, locale: string) => { +export const formatStatisticsCalendarDate = (date: Date, locale = "ko") => { return new Intl.DateTimeFormat(locale, { + year: "numeric", month: "long", + day: "numeric", + weekday: "long", }).format(date); }; From a34e16d9188572ddbf20d70c6f0c2876343c0210 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 15:20:15 +0900 Subject: [PATCH 06/22] =?UTF-8?q?feat(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=82=A0=EC=A7=9C=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EC=9C=A0=ED=8B=B8=20=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_utils/statisticsCalendar.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts new file mode 100644 index 0000000..13b2eff --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts @@ -0,0 +1,37 @@ +export interface CalendarDate { + date: Date; + day: number; +} + +export const getLastDayOfMonth = (date: Date) => { + return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); +}; + +export const getCalendarDates = (month: Date): CalendarDate[] => { + const year = month.getFullYear(); + const monthIndex = month.getMonth(); + const lastDay = getLastDayOfMonth(month); + + return Array.from({ length: lastDay }, (_, index) => { + const day = index + 1; + + return { + date: new Date(year, monthIndex, day), + day, + }; + }); +}; + +export const getFirstDayOffset = (month: Date) => { + const firstDate = new Date(month.getFullYear(), month.getMonth(), 1); + + return (firstDate.getDay() + 6) % 7; +}; + +export const formatDateKey = (date: Date) => { + const year = date.getFullYear(); + const month = `${date.getMonth() + 1}`.padStart(2, "0"); + const day = `${date.getDate()}`.padStart(2, "0"); + + return `${year}-${month}-${day}`; +}; From 474d576e2384a3d6326a282234df222ddaddda80 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 15:20:39 +0900 Subject: [PATCH 07/22] =?UTF-8?q?chore(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=AA=A9=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_mocks/statisticsCalendar.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts new file mode 100644 index 0000000..9bc7768 --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts @@ -0,0 +1,13 @@ +import type { StatisticsCalendarResponse } from "@/app/[locale]/(main)/statistics/_types/statistics"; + +export const MOCK_STATISTICS_CALENDAR: StatisticsCalendarResponse = { + yearMonth: "2026-07", + today: "2026-07-10", + days: [ + { date: "2026-07-01", completionRate: 0 }, + { date: "2026-07-02", completionRate: 25 }, + { date: "2026-07-03", completionRate: 75 }, + { date: "2026-07-04", completionRate: 100 }, + { date: "2026-07-05", completionRate: null }, + ], +}; From b8ede7c7c04154bc36ddffe87608687c6ba999fb Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 15:20:52 +0900 Subject: [PATCH 08/22] =?UTF-8?q?feat(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/StatisticsCalendar.tsx | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx new file mode 100644 index 0000000..78b0463 --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -0,0 +1,115 @@ +import { + StatisticsClockDisabledIcon, + StatisticsClockEmptyIcon, + StatisticsClockFilledIcon, + StatisticsClockLightIcon, + StatisticsClockOutlineIcon, +} from "@repo/timo-design-system/icons"; +import { cn } from "@repo/timo-design-system/utils"; + +import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; +import { + formatStatisticsCalendarDate, + formatStatisticsMonth, +} from "@/app/[locale]/(main)/statistics/_utils/formatStatisticsDate"; +import { + formatDateKey, + getCalendarDates, + getFirstDayOffset, +} from "@/app/[locale]/(main)/statistics/_utils/statisticsCalendar"; + +type CalendarIconStatus = "empty" | "outline" | "light" | "filled" | "disabled"; + +const STATUS_ICON = { + empty: StatisticsClockEmptyIcon, + outline: StatisticsClockOutlineIcon, + light: StatisticsClockLightIcon, + filled: StatisticsClockFilledIcon, + disabled: StatisticsClockDisabledIcon, +}; + +const getIconStatus = ( + completionRate: number | null, + isCurrentMonth: boolean, +): CalendarIconStatus => { + if (!isCurrentMonth) return "disabled"; + if (completionRate === null) return "empty"; + if (completionRate === 0) return "empty"; + if (completionRate < 50) return "outline"; + if (completionRate < 100) return "light"; + return "filled"; +}; + +const WEEKDAYS = ["M", "T", "W", "T", "F", "S", "S"]; + +interface StatisticsCalendarProps { + currentMonth: Date; +} + +export const StatisticsCalendar = ({ + currentMonth, +}: StatisticsCalendarProps) => { + const today = new Date(MOCK_STATISTICS_CALENDAR.today); + const calendarDates = getCalendarDates(currentMonth); + const firstDayOffset = getFirstDayOffset(currentMonth); + const completionRateByDate = new Map( + MOCK_STATISTICS_CALENDAR.days.map(({ date, completionRate }) => [ + date, + completionRate, + ]), + ); + const todayLabel = formatStatisticsCalendarDate(today); + + return ( +
+
+
+

+ {formatStatisticsMonth(currentMonth)} +

+ +

+ {todayLabel} +

+
+ +
+ {WEEKDAYS.map((weekday, index) => ( +
= 5 ? "text-timo-red" : "text-timo-gray-900", + )} + > + {weekday} +
+ ))} + + {Array.from({ length: firstDayOffset }, (_, index) => ( +
+ ))} + + {calendarDates.map((calendarDate) => { + const dateKey = formatDateKey(calendarDate.date); + const completionRate = completionRateByDate.get(dateKey) ?? null; + const status = getIconStatus(completionRate, true); + const Icon = STATUS_ICON[status]; + + return ( +
+ + + {calendarDate.day} + +
+ ); + })} +
+
+
+ ); +}; From 0ad681f90d40aef747da7060852d51daad63e0c1 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 22:13:00 +0900 Subject: [PATCH 09/22] =?UTF-8?q?docs(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=9C=A0=ED=8B=B8=20JSDoc=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_utils/statisticsCalendar.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts index 13b2eff..dfac20c 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts @@ -7,6 +7,10 @@ export const getLastDayOfMonth = (date: Date) => { return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); }; +/** + * 주어진 월에 포함된 날짜 목록을 반환합니다. + * 이전/다음 달 날짜는 포함하지 않고 현재 월 날짜만 생성합니다. + */ export const getCalendarDates = (month: Date): CalendarDate[] => { const year = month.getFullYear(); const monthIndex = month.getMonth(); @@ -22,12 +26,20 @@ export const getCalendarDates = (month: Date): CalendarDate[] => { }); }; +/** + * 월요일 시작 캘린더에서 1일 앞에 필요한 빈 칸 개수를 반환합니다. + * JS Date.getDay()는 일요일을 0으로 반환하므로 월요일 기준 인덱스로 변환합니다. + */ export const getFirstDayOffset = (month: Date) => { const firstDate = new Date(month.getFullYear(), month.getMonth(), 1); return (firstDate.getDay() + 6) % 7; }; +/** + * Date 객체를 API 응답 날짜 형식인 yyyy-MM-dd 문자열로 변환합니다. + * 날짜별 completionRate를 매칭할 때 사용합니다. + */ export const formatDateKey = (date: Date) => { const year = date.getFullYear(); const month = `${date.getMonth() + 1}`.padStart(2, "0"); From 833f0f4e410f4271ebda812548d42634550ebc31 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 22:30:49 +0900 Subject: [PATCH 10/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=A3=BC=EC=9E=85=20=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_components/StatisticsCalendar.tsx | 12 ++++++------ .../timo-web/app/[locale]/(main)/statistics/page.tsx | 6 +++++- 2 files changed, 11 insertions(+), 7 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 78b0463..2f070c5 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -7,7 +7,8 @@ import { } from "@repo/timo-design-system/icons"; import { cn } from "@repo/timo-design-system/utils"; -import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; +import type { StatisticsCalendarResponse } from "@/app/[locale]/(main)/statistics/_types/statistics"; + import { formatStatisticsCalendarDate, formatStatisticsMonth, @@ -44,19 +45,18 @@ const WEEKDAYS = ["M", "T", "W", "T", "F", "S", "S"]; interface StatisticsCalendarProps { currentMonth: Date; + calendarData: StatisticsCalendarResponse; } export const StatisticsCalendar = ({ currentMonth, + calendarData, }: StatisticsCalendarProps) => { - const today = new Date(MOCK_STATISTICS_CALENDAR.today); + const today = new Date(calendarData.today); const calendarDates = getCalendarDates(currentMonth); const firstDayOffset = getFirstDayOffset(currentMonth); const completionRateByDate = new Map( - MOCK_STATISTICS_CALENDAR.days.map(({ date, completionRate }) => [ - date, - completionRate, - ]), + calendarData.days.map(({ date, completionRate }) => [date, completionRate]), ); const todayLabel = formatStatisticsCalendarDate(today); diff --git a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx index 9cdb76a..42a48f8 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; +import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; export default function StatisticsPage() { const [currentMonth, setCurrentMonth] = useState(() => new Date()); @@ -14,7 +15,10 @@ export default function StatisticsPage() { currentMonth={currentMonth} onChangeMonth={setCurrentMonth} /> - + ); } From 769ddad16ef7390f006b1c2c684135fb7898c58d Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 22:36:12 +0900 Subject: [PATCH 11/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=B9=84=ED=99=9C=EC=84=B1=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=A1=B0=EA=B1=B4=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_components/StatisticsCalendar.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 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 2f070c5..151b6a5 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -19,22 +19,18 @@ import { getFirstDayOffset, } from "@/app/[locale]/(main)/statistics/_utils/statisticsCalendar"; -type CalendarIconStatus = "empty" | "outline" | "light" | "filled" | "disabled"; +type CalendarIconStatus = "disabled" | "empty" | "outline" | "light" | "filled"; const STATUS_ICON = { + disabled: StatisticsClockDisabledIcon, empty: StatisticsClockEmptyIcon, outline: StatisticsClockOutlineIcon, light: StatisticsClockLightIcon, filled: StatisticsClockFilledIcon, - disabled: StatisticsClockDisabledIcon, }; -const getIconStatus = ( - completionRate: number | null, - isCurrentMonth: boolean, -): CalendarIconStatus => { - if (!isCurrentMonth) return "disabled"; - if (completionRate === null) return "empty"; +const getIconStatus = (completionRate: number | null): CalendarIconStatus => { + if (completionRate === null) return "disabled"; if (completionRate === 0) return "empty"; if (completionRate < 50) return "outline"; if (completionRate < 100) return "light"; @@ -93,7 +89,7 @@ export const StatisticsCalendar = ({ {calendarDates.map((calendarDate) => { const dateKey = formatDateKey(calendarDate.date); const completionRate = completionRateByDate.get(dateKey) ?? null; - const status = getIconStatus(completionRate, true); + const status = getIconStatus(completionRate); const Icon = STATUS_ICON[status]; return ( From 999c27c7da37e131df59a9d24746a60412add5b4 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Fri, 10 Jul 2026 22:38:23 +0900 Subject: [PATCH 12/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=83=81=ED=83=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_containers/StatisticsPageContainer.tsx | 24 +++++++++++++++++++ .../app/[locale]/(main)/statistics/page.tsx | 23 ++---------------- 2 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx new file mode 100644 index 0000000..1b1552d --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { useState } from "react"; + +import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; +import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; +import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; + +export const StatisticsPageContainer = () => { + const [currentMonth, setCurrentMonth] = useState(() => new Date()); + + return ( + <> + + + + ); +}; diff --git a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx index 42a48f8..a8e019c 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx @@ -1,24 +1,5 @@ -"use client"; - -import { useState } from "react"; - -import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; -import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; -import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; +import { StatisticsPageContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer"; export default function StatisticsPage() { - const [currentMonth, setCurrentMonth] = useState(() => new Date()); - - return ( - <> - - - - ); + return ; } From 4e357c368eab4b89ccdbcded323dcdfd9b860038 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 02:16:46 +0900 Subject: [PATCH 13/22] =?UTF-8?q?docs(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=9C=A0=ED=8B=B8=20JSDoc=20?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20=EB=B0=8F=20=EC=84=A4=EB=AA=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/_utils/formatStatisticsDate.ts | 20 +++++++++++++++++++ .../statistics/_utils/statisticsCalendar.ts | 12 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts index 5a054eb..4985b47 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts @@ -1,9 +1,29 @@ +/** + * 통계 캘린더 헤더에 표시할 월 이름을 반환합니다. + * + * @param date - 월 이름을 가져올 날짜 + * @param locale - 날짜 표기에 사용할 locale 값 + * @returns locale에 맞게 변환된 월 이름 + * + * @example + * formatStatisticsMonth(new Date(2026, 5, 1)); // "6월" + */ export const formatStatisticsMonth = (date: Date, locale = "ko") => { return new Intl.DateTimeFormat(locale, { month: "long", }).format(date); }; +/** + * 통계 캘린더 설명 영역에 표시할 날짜 문구를 반환합니다. + * + * @param date - 표시할 날짜 + * @param locale - 날짜 표기에 사용할 locale 값 + * @returns 년, 월, 일, 요일이 포함된 날짜 문구 + * + * @example + * formatStatisticsCalendarDate(new Date(2026, 5, 28)); // "2026년 6월 28일 일요일" + */ export const formatStatisticsCalendarDate = (date: Date, locale = "ko") => { return new Intl.DateTimeFormat(locale, { year: "numeric", diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts index dfac20c..e42f864 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts @@ -10,6 +10,9 @@ export const getLastDayOfMonth = (date: Date) => { /** * 주어진 월에 포함된 날짜 목록을 반환합니다. * 이전/다음 달 날짜는 포함하지 않고 현재 월 날짜만 생성합니다. + * + * @param month - 날짜 목록을 생성할 기준 월 + * @returns 해당 월의 날짜와 일자를 담은 배열 */ export const getCalendarDates = (month: Date): CalendarDate[] => { const year = month.getFullYear(); @@ -29,6 +32,9 @@ export const getCalendarDates = (month: Date): CalendarDate[] => { /** * 월요일 시작 캘린더에서 1일 앞에 필요한 빈 칸 개수를 반환합니다. * JS Date.getDay()는 일요일을 0으로 반환하므로 월요일 기준 인덱스로 변환합니다. + * + * @param month - 첫 주 offset을 계산할 기준 월 + * @returns 월요일 시작 캘린더에서 1일 앞에 필요한 빈 칸 개수 */ export const getFirstDayOffset = (month: Date) => { const firstDate = new Date(month.getFullYear(), month.getMonth(), 1); @@ -39,6 +45,12 @@ export const getFirstDayOffset = (month: Date) => { /** * Date 객체를 API 응답 날짜 형식인 yyyy-MM-dd 문자열로 변환합니다. * 날짜별 completionRate를 매칭할 때 사용합니다. + * + * @param date - 변환할 날짜 + * @returns yyyy-MM-dd 형식의 날짜 문자열 + * + * @example + * formatDateKey(new Date(2026, 5, 28)); // "2026-06-28" */ export const formatDateKey = (date: Date) => { const year = date.getFullYear(); From b0d8fcff66c8c68fcb6be0f54162d7d04bf835a7 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 03:09:18 +0900 Subject: [PATCH 14/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=B9=84=ED=99=9C=EC=84=B1=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=EC=9D=84=20CSS=EB=A1=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsCalendar.tsx | 9 ++++++--- .../src/icons/source/statistics-clock-disabled.svg | 4 ---- 2 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg 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 151b6a5..18834be 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -1,5 +1,4 @@ import { - StatisticsClockDisabledIcon, StatisticsClockEmptyIcon, StatisticsClockFilledIcon, StatisticsClockLightIcon, @@ -21,8 +20,12 @@ import { type CalendarIconStatus = "disabled" | "empty" | "outline" | "light" | "filled"; +const DisabledClockIcon = () => ( +
+); + const STATUS_ICON = { - disabled: StatisticsClockDisabledIcon, + disabled: DisabledClockIcon, empty: StatisticsClockEmptyIcon, outline: StatisticsClockOutlineIcon, light: StatisticsClockLightIcon, @@ -74,7 +77,7 @@ export const StatisticsCalendar = ({
= 5 ? "text-timo-red" : "text-timo-gray-900", )} > diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg b/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg deleted file mode 100644 index 69e0fe5..0000000 --- a/packages/timo-design-system/src/icons/source/statistics-clock-disabled.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - From 5f85d9c70251501f1d70b7f7d15ef9848f2b0850 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 03:14:12 +0900 Subject: [PATCH 15/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20selected=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=97=90=EC=85=8B=20=EC=A0=9C=EA=B1=B0=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics-clock-empty-selected.svg | 21 ------------------- .../statistics-clock-filled-selected.svg | 21 ------------------- .../statistics-clock-light-selected.svg | 21 ------------------- .../statistics-clock-outline-selected.svg | 21 ------------------- 4 files changed, 84 deletions(-) delete mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg delete mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg delete mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg delete mode 100644 packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg deleted file mode 100644 index 9becce8..0000000 --- a/packages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg deleted file mode 100644 index 5ee7078..0000000 --- a/packages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg deleted file mode 100644 index d5be223..0000000 --- a/packages/timo-design-system/src/icons/source/statistics-clock-light-selected.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg b/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg deleted file mode 100644 index 3db735a..0000000 --- a/packages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - From 8289b96e7f624713c31185ee04b993fd1b10cd8f Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 03:16:49 +0900 Subject: [PATCH 16/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20dateKey=EB=A5=BC=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20key=EB=A1=9C=20=EC=82=AC=EC=9A=A9=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsCalendar.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 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 18834be..7fda056 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -96,10 +96,7 @@ export const StatisticsCalendar = ({ const Icon = STATUS_ICON[status]; return ( -
+
{calendarDate.day} From 6f28e7a2c4cf2469fdf82fe44a18c951ad5fa9df Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 03:20:15 +0900 Subject: [PATCH 17/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EC=9A=94=EC=9D=BC=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=EC=84=B1=20=EB=9D=BC=EB=B2=A8=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/StatisticsCalendar.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 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 7fda056..2e9681c 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -40,7 +40,15 @@ const getIconStatus = (completionRate: number | null): CalendarIconStatus => { return "filled"; }; -const WEEKDAYS = ["M", "T", "W", "T", "F", "S", "S"]; +const WEEKDAYS = [ + { label: "M", ariaLabel: "Monday" }, + { label: "T", ariaLabel: "Tuesday" }, + { label: "W", ariaLabel: "Wednesday" }, + { label: "T", ariaLabel: "Thursday" }, + { label: "F", ariaLabel: "Friday" }, + { label: "S", ariaLabel: "Saturday" }, + { label: "S", ariaLabel: "Sunday" }, +]; interface StatisticsCalendarProps { currentMonth: Date; @@ -73,15 +81,16 @@ export const StatisticsCalendar = ({
- {WEEKDAYS.map((weekday, index) => ( + {WEEKDAYS.map(({ label, ariaLabel }, index) => (
= 5 ? "text-timo-red" : "text-timo-gray-900", )} > - {weekday} + {label}
))} From 8abdc438cd85e5a51a9f7b60163e00774aa2a13f Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 03:21:30 +0900 Subject: [PATCH 18/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=EB=82=B4=EB=B6=80=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=20export=20=EC=A0=9C=EA=B1=B0=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts index e42f864..ffe14db 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts +++ b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts @@ -3,7 +3,7 @@ export interface CalendarDate { day: number; } -export const getLastDayOfMonth = (date: Date) => { +const getLastDayOfMonth = (date: Date) => { return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); }; From cfd85203a758b2e2fb6f1adbe367f00767ad19dd Mon Sep 17 00:00:00 2001 From: "Novaris." Date: Sat, 11 Jul 2026 04:16:52 +0900 Subject: [PATCH 19/22] =?UTF-8?q?refactor(web):=20=EC=BB=A8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=84=88=EB=A1=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 김민아 --- .../(main)/statistics/_containers/StatisticsPageContainer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx index 1b1552d..2750c8b 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx @@ -6,7 +6,7 @@ import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; -export const StatisticsPageContainer = () => { +export const StatisticsContainer = () => { const [currentMonth, setCurrentMonth] = useState(() => new Date()); return ( From b86be66030e5226dd0c3335f5599bce7273164c2 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 04:12:58 +0900 Subject: [PATCH 20/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=EC=9D=84=20kebab-case=EB=A1=9C=20=EC=A0=95=EB=A6=AC=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(main)/statistics/_components/StatisticsCalendar.tsx | 4 ++-- .../{formatStatisticsDate.ts => format-statistics-date.ts} | 0 .../_utils/{statisticsCalendar.ts => statistics-calendar.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename apps/timo-web/app/[locale]/(main)/statistics/_utils/{formatStatisticsDate.ts => format-statistics-date.ts} (100%) rename apps/timo-web/app/[locale]/(main)/statistics/_utils/{statisticsCalendar.ts => statistics-calendar.ts} (100%) 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 2e9681c..3ed0fff 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx @@ -11,12 +11,12 @@ import type { StatisticsCalendarResponse } from "@/app/[locale]/(main)/statistic import { formatStatisticsCalendarDate, formatStatisticsMonth, -} from "@/app/[locale]/(main)/statistics/_utils/formatStatisticsDate"; +} from "@/app/[locale]/(main)/statistics/_utils/format-statistics-date"; import { formatDateKey, getCalendarDates, getFirstDayOffset, -} from "@/app/[locale]/(main)/statistics/_utils/statisticsCalendar"; +} from "@/app/[locale]/(main)/statistics/_utils/statistics-calendar"; type CalendarIconStatus = "disabled" | "empty" | "outline" | "light" | "filled"; diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/format-statistics-date.ts similarity index 100% rename from apps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.ts rename to apps/timo-web/app/[locale]/(main)/statistics/_utils/format-statistics-date.ts diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_utils/statistics-calendar.ts similarity index 100% rename from apps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts rename to apps/timo-web/app/[locale]/(main)/statistics/_utils/statistics-calendar.ts From a5e9c1c006a92c3f18a9a6abfa96d3625e3b2f00 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 04:15:47 +0900 Subject: [PATCH 21/22] =?UTF-8?q?refactor(web):=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_mocks/{statisticsCalendar.ts => statistics-calendar.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/timo-web/app/[locale]/(main)/statistics/_mocks/{statisticsCalendar.ts => statistics-calendar.ts} (100%) diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts b/apps/timo-web/app/[locale]/(main)/statistics/_mocks/statistics-calendar.ts similarity index 100% rename from apps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.ts rename to apps/timo-web/app/[locale]/(main)/statistics/_mocks/statistics-calendar.ts From f217bd930af08a06a19b30d00ab62aa7f63e23fd Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Sat, 11 Jul 2026 04:23:00 +0900 Subject: [PATCH 22/22] =?UTF-8?q?refactor(web):=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=EA=B3=BC=20zod=20=EC=A0=95=EC=9D=98=20(#129)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_containers/StatisticsContainer.tsx | 24 +++++++++++++++++++ .../_containers/StatisticsHeaderContainer.tsx | 1 - .../_containers/StatisticsPageContainer.tsx | 2 +- .../app/[locale]/(main)/statistics/page.tsx | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx new file mode 100644 index 0000000..e926fcf --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { useState } from "react"; + +import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; +import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; +import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statistics-calendar"; + +export const StatisticsContainer = () => { + const [currentMonth, setCurrentMonth] = useState(() => new Date()); + + return ( + <> + + + + ); +}; diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx index 524cf02..dd64590 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx @@ -5,7 +5,6 @@ import type { Dispatch, SetStateAction } from "react"; import { Header } from "@/components/layout/header/Header"; import { useNavigationSidebar } from "@/components/layout/sidebar/navigation/NavigationSidebarContext"; - interface StatisticsHeaderContainerProps { currentMonth: Date; onChangeMonth: Dispatch>; diff --git a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx index 2750c8b..e926fcf 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { StatisticsCalendar } from "@/app/[locale]/(main)/statistics/_components/StatisticsCalendar"; import { StatisticsHeaderContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer"; -import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statisticsCalendar"; +import { MOCK_STATISTICS_CALENDAR } from "@/app/[locale]/(main)/statistics/_mocks/statistics-calendar"; export const StatisticsContainer = () => { const [currentMonth, setCurrentMonth] = useState(() => new Date()); diff --git a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx index a8e019c..2ed50a4 100644 --- a/apps/timo-web/app/[locale]/(main)/statistics/page.tsx +++ b/apps/timo-web/app/[locale]/(main)/statistics/page.tsx @@ -1,5 +1,5 @@ -import { StatisticsPageContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer"; +import { StatisticsContainer } from "@/app/[locale]/(main)/statistics/_containers/StatisticsContainer"; export default function StatisticsPage() { - return ; + return ; }