[FEAT] 통계 페이지 캘린더 구현#133
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Walkthrough통계 페이지에 현재 월을 공유하는 클라이언트 컨테이너와 이전·다음 월 이동 기능을 추가했습니다. 날짜별 완료율 응답 계약, 날짜 계산 유틸리티, 완료율 상태 아이콘이 포함된 월간 캘린더 UI를 구현하고 모의 데이터를 연결했습니다. Changes통계 캘린더 기능
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant StatisticsPage
participant StatisticsContainer
participant StatisticsHeaderContainer
participant StatisticsCalendar
StatisticsPage->>StatisticsContainer: 통계 화면 렌더링
StatisticsContainer->>StatisticsHeaderContainer: 현재 월과 변경 콜백 전달
StatisticsHeaderContainer->>StatisticsContainer: 이전 또는 다음 월 변경
StatisticsContainer->>StatisticsCalendar: 변경된 월과 캘린더 데이터 전달
StatisticsCalendar->>StatisticsCalendar: 날짜 그리드와 완료율 아이콘 렌더링
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Timo Performance ReportBundle Size — timo-web
Lighthouse — timo-web
Image Optimization — timo-web
측정 커밋: |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx:
- Around line 1-19: StatisticsCalendar의 MOCK_STATISTICS_CALENDAR 직접 의존성을 제거하세요.
MOCK_STATISTICS_CALENDAR import는 상위 컨테이너 또는 페이지로 이동하고, StatisticsCalendar이 필요한
캘린더 데이터를 props로 받도록 타입과 호출부를 수정해 순수 UI 컴포넌트로 유지하세요.
- Line 52: Replace the direct new Date(MOCK_STATISTICS_CALENDAR.today) call in
StatisticsCalendar with a local-date parser that splits the YYYY-MM-DD key into
numeric year, month, and day and constructs new Date(year, month - 1, day); add
and reuse a parseDateKey helper in _utils/statisticsCalendar.ts alongside
formatDateKey.
- Around line 31-41: Remove the unused isCurrentMonth parameter and disabled
branch from getIconStatus, then update all call sites to pass only
completionRate. Also remove the unused StatisticsClockDisabledIcon import and
STATUS_ICON.disabled mapping, along with any related dead types or logic.
In `@apps/timo-web/app/`[locale]/(main)/statistics/page.tsx:
- Around line 1-20: Keep StatisticsPage as a Server Component by removing the
"use client" directive and useState from page.tsx, and have it render only a new
StatisticsPageContainer. Move the currentMonth state and existing
StatisticsHeaderContainer/StatisticsCalendar composition into a "use client"
component named StatisticsPageContainer under _containers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8407106d-f434-4f4e-964f-2c3c03884f9d
⛔ Files ignored due to path filters (9)
packages/timo-design-system/src/icons/source/statistics-clock-disabled.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-empty-selected.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-empty.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-filled-selected.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-filled.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-light-selected.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-light.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-outline-selected.svgis excluded by!**/*.svgpackages/timo-design-system/src/icons/source/statistics-clock-outline.svgis excluded by!**/*.svg
📒 Files selected for processing (8)
apps/timo-web/app/[locale]/(main)/statistics/_components/.gitkeepapps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsxapps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsxapps/timo-web/app/[locale]/(main)/statistics/_mocks/statisticsCalendar.tsapps/timo-web/app/[locale]/(main)/statistics/_types/statistics.tsapps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.tsapps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.tsapps/timo-web/app/[locale]/(main)/statistics/page.tsx
| export const StatisticsCalendar = ({ | ||
| currentMonth, | ||
| }: StatisticsCalendarProps) => { | ||
| const today = new Date(MOCK_STATISTICS_CALENDAR.today); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
new Date("2026-07-10")은 UTC로 파싱되어 timezone에 따라 날짜가 shift될 수 있습니다.
ECMAScript 스펙에 따라 date-only ISO 문자열(YYYY-MM-DD)은 UTC 자정으로 파싱됩니다. formatStatisticsCalendarDate는 local timezone으로 포맷하므로, UTC-5 등의 timezone에서는 "7월 9일"로 표시됩니다. 한국(UTC+9)에서는 문제가 없지만, 안전한 파싱 방식을 사용하는 것이 좋습니다.
🛡️ 제안하는 안전한 날짜 파싱
-const today = new Date(MOCK_STATISTICS_CALENDAR.today);
+const [year, month, day] = MOCK_STATISTICS_CALENDAR.today.split("-").map(Number);
+const today = new Date(year, month - 1, day);또는 formatDateKey와 동일한 방식으로 local date를 생성하는 헬퍼를 _utils/statisticsCalendar.ts에 추가할 수 있습니다:
export const parseDateKey = (dateKey: string): Date => {
const [year, month, day] = dateKey.split("-").map(Number);
return new Date(year, month - 1, day);
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const today = new Date(MOCK_STATISTICS_CALENDAR.today); | |
| const [year, month, day] = MOCK_STATISTICS_CALENDAR.today.split("-").map(Number); | |
| const today = new Date(year, month - 1, day); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx
at line 52, Replace the direct new Date(MOCK_STATISTICS_CALENDAR.today) call in
StatisticsCalendar with a local-date parser that splits the YYYY-MM-DD key into
numeric year, month, and day and constructs new Date(year, month - 1, day); add
and reuse a parseDateKey helper in _utils/statisticsCalendar.ts alongside
formatDateKey.
jjangminii
left a comment
There was a problem hiding this comment.
고생하셨습니다~ 이제 패널하고 합치면 뷰 금방 만들 수 있을것 같아요
코멘트 확인해주세요-!
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx (2)
97-97: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
keyprop에toISOString()대신dateKey를 재사용하세요.이전 리뷰에서 지적된 내용이 아직 반영되지 않았습니다. Line 90에서 이미
dateKey를 계산하고 있으므로, Line 97에서toISOString()을 다시 호출하는 것은 중복 계산입니다. 더 중요한 것은toISOString()이 UTC 기준으로 변환되므로, UTC+9 timezone에서new Date(2026, 6, 1)(local July 1)의toISOString()은"2026-06-30T15:00:00.000Z"가 되어 의도치 않게 전날 키가 생성됩니다.♻️ 제안하는 수정
- key={calendarDate.date.toISOString()} + key={dateKey}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx at line 97, StatisticsCalendar의 calendarDate 렌더링에서 key로 다시 toISOString()을 호출하지 말고, 이미 계산된 dateKey 변수를 재사용하세요. dateKey가 로컬 날짜를 기준으로 안정적인 키를 생성하도록 유지하고, key={dateKey}로 변경해 UTC 변환으로 날짜가 하루 밀리는 문제와 중복 계산을 해결하세요.
73-82: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win요일 헤더에
aria-label을 추가해 접근성을 개선하세요.이전 리뷰에서 지적된 내용이 아직 반영되지 않았습니다.
WEEKDAYS가 단일 문자("M", "T", "W"...)로 렌더링되므로, 스크린리더 사용자는 두 개의 "T"와 두 개의 "S"를 구분할 수 없습니다. 경로 규칙에 따르면 시맨틱 태그 사용과 접근성이 권장됩니다.참고: WAI-ARIA aria-label documentation
♿ 제안하는 접근성 개선
{WEEKDAYS.map((weekday, index) => ( <div key={`${weekday}-${index}`} + aria-label={["월", "화", "수", "목", "금", "토", "일"][index]} className={cn( "typo-headline-m-14 flex h-6 items-center justify-center", index >= 5 ? "text-timo-red" : "text-timo-gray-900", )} > {weekday} </div> ))}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx around lines 73 - 82, 요일 헤더의 단일 문자 표기를 스크린리더가 구분할 수 있도록 접근성을 보완하세요. StatisticsCalendar의 WEEKDAYS.map 렌더링에서 각 헤더 div에 전체 요일명을 제공하는 aria-label을 추가하고, 기존 시각적 표기와 스타일은 유지하세요.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx:
- Line 51: StatisticsCalendar의 `calendarData.today`를 `new Date("YYYY-MM-DD")`로
직접 파싱하지 말고, 연·월·일을 분리해 local timezone 기준으로 Date를 생성하도록 수정하세요. 이후
`formatStatisticsCalendarDate`와 비교·포맷 로직이 동일한 local 날짜를 사용하도록 `today` 초기화 코드를
조정하세요.
---
Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx:
- Line 97: StatisticsCalendar의 calendarDate 렌더링에서 key로 다시 toISOString()을 호출하지
말고, 이미 계산된 dateKey 변수를 재사용하세요. dateKey가 로컬 날짜를 기준으로 안정적인 키를 생성하도록 유지하고,
key={dateKey}로 변경해 UTC 변환으로 날짜가 하루 밀리는 문제와 중복 계산을 해결하세요.
- Around line 73-82: 요일 헤더의 단일 문자 표기를 스크린리더가 구분할 수 있도록 접근성을 보완하세요.
StatisticsCalendar의 WEEKDAYS.map 렌더링에서 각 헤더 div에 전체 요일명을 제공하는 aria-label을 추가하고,
기존 시각적 표기와 스타일은 유지하세요.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0d9c1a1d-6658-40c3-818b-2673e7c258a9
📒 Files selected for processing (5)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsxapps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsxapps/timo-web/app/[locale]/(main)/statistics/_utils/formatStatisticsDate.tsapps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.tsapps/timo-web/app/[locale]/(main)/statistics/page.tsx
| currentMonth, | ||
| calendarData, | ||
| }: StatisticsCalendarProps) => { | ||
| const today = new Date(calendarData.today); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
new Date(calendarData.today) UTC 파싱 이슈가 여전히 남아 있습니다.
이전 리뷰에서 지적된 내용이 아직 반영되지 않았습니다. calendarData.today가 "YYYY-MM-DD" 형식의 문자열이므로, ECMAScript 스펙상 UTC 자정으로 파싱됩니다. formatStatisticsCalendarDate가 local timezone 기준으로 포맷하므로, UTC-5 등의 timezone에서는 날짜가 하루 앞당겨져 표시됩니다.
참고: ECMAScript Date Time String Format specification
🛡️ 제안하는 안전한 날짜 파싱
- const today = new Date(calendarData.today);
+ const [year, month, day] = calendarData.today.split("-").map(Number);
+ const today = new Date(year, month - 1, day);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx
at line 51, StatisticsCalendar의 `calendarData.today`를 `new Date("YYYY-MM-DD")`로
직접 파싱하지 말고, 연·월·일을 분리해 local timezone 기준으로 Date를 생성하도록 수정하세요. 이후
`formatStatisticsCalendarDate`와 비교·포맷 로직이 동일한 local 날짜를 사용하도록 `today` 초기화 코드를
조정하세요.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx (1)
62-62: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
new Date(calendarData.today)UTC 파싱 이슈가 여전히 해결되지 않았습니다.이전 리뷰에서 두 차례 지적된 내용이 아직 반영되지 않았습니다.
calendarData.today는"YYYY-MM-DD"형식 문자열이며, ECMAScript 스펙상 date-only ISO 문자열은 UTC 자정으로 파싱됩니다.formatStatisticsCalendarDate가 local timezone 기준으로 포맷하므로 UTC-5 등의 timezone에서 날짜가 하루 앞당겨져 표시됩니다.🛡️ 제안하는 안전한 날짜 파싱
- const today = new Date(calendarData.today); + const [year, month, day] = calendarData.today.split("-").map(Number); + const today = new Date(year, month - 1, day);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx at line 62, StatisticsCalendar의 today 생성에서 date-only 문자열을 new Date(string)으로 파싱하지 않도록 수정하세요. calendarData.today의 YYYY-MM-DD 값을 연·월·일로 분리해 로컬 시간 기준 Date를 생성하고, 이후 formatStatisticsCalendarDate 호출이 해당 로컬 날짜를 사용하도록 하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx:
- Line 62: StatisticsCalendar의 today 생성에서 date-only 문자열을 new Date(string)으로 파싱하지
않도록 수정하세요. calendarData.today의 YYYY-MM-DD 값을 연·월·일로 분리해 로컬 시간 기준 Date를 생성하고, 이후
formatStatisticsCalendarDate 호출이 해당 로컬 날짜를 사용하도록 하세요.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ca19f367-93f9-4247-b39f-da3add383df7
📒 Files selected for processing (2)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsxapps/timo-web/app/[locale]/(main)/statistics/_utils/statisticsCalendar.ts
Co-authored-by: 김민아 <kmina121777@naver.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx (1)
7-24: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value
StatisticsPageContainer.tsx는 정리 대상입니다. 같은 이름의 export가 두 파일에 있어도 모듈이 분리되어 있어서 충돌은 없습니다. 지금은page.tsx가StatisticsContainer.tsx만 사용하므로,StatisticsPageContainer.tsx는 삭제하거나 실제 사용처에 맞게 파일명/임포트를 하나로 맞춰 두는 편이 깔끔합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/timo-web/app/`[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx around lines 7 - 24, Remove the unused StatisticsPageContainer.tsx, or consolidate it with StatisticsContainer.tsx by aligning the filename, export, and imports so page.tsx references a single implementation; verify no remaining imports depend on the redundant file.
♻️ Duplicate comments (1)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx (1)
62-62: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
new Date(calendarData.today)UTC 파싱 이슈가 여전히 해결되지 않았습니다.이전 리뷰에서 두 차례 지적된 내용이 현재 코드에 반영되지 않았습니다.
calendarData.today가"2026-07-10"형식의 date-only ISO 문자열이므로, ECMAScript 스펙상 UTC 자정으로 파싱됩니다.formatStatisticsCalendarDate는 local timezone 기준으로 포맷하므로, UTC-5 등의 timezone에서는 날짜가 하루 앞당겨져 표시됩니다.참고: ECMAScript Date Time String Format
🛡️ 제안하는 안전한 날짜 파싱
- const today = new Date(calendarData.today); + const [year, month, day] = calendarData.today.split("-").map(Number); + const today = new Date(year, month - 1, day);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx at line 62, StatisticsCalendar의 `calendarData.today`를 `new Date()`로 직접 파싱하지 말고, date-only 문자열을 로컬 날짜로 해석하도록 수정하세요. `today` 생성 로직과 `formatStatisticsCalendarDate` 사용 지점을 확인해 연·월·일을 직접 분리해 로컬 `Date`를 생성하거나 동일한 안전한 날짜 파서 함수를 사용하도록 변경하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/timo-web/app/`[locale]/(main)/statistics/_types/statistics.ts:
- Around line 3-12: statisticsCalendarResponseSchema의 날짜 필드 검증을 강화하세요.
yearMonth와 today는 현재 형식에 맞는 ISO 날짜 스키마를 사용하고, days 내부 객체의 date 필드도 z.string() 대신
Zod 4의 z.iso.date()로 검증하도록 변경하세요.
---
Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsx:
- Around line 7-24: Remove the unused StatisticsPageContainer.tsx, or
consolidate it with StatisticsContainer.tsx by aligning the filename, export,
and imports so page.tsx references a single implementation; verify no remaining
imports depend on the redundant file.
---
Duplicate comments:
In
`@apps/timo-web/app/`[locale]/(main)/statistics/_components/StatisticsCalendar.tsx:
- Line 62: StatisticsCalendar의 `calendarData.today`를 `new Date()`로 직접 파싱하지 말고,
date-only 문자열을 로컬 날짜로 해석하도록 수정하세요. `today` 생성 로직과 `formatStatisticsCalendarDate`
사용 지점을 확인해 연·월·일을 직접 분리해 로컬 `Date`를 생성하거나 동일한 안전한 날짜 파서 함수를 사용하도록 변경하세요.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3d4c3e75-a26f-4cf5-8846-21fcd0031483
📒 Files selected for processing (9)
apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsxapps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsContainer.tsxapps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsxapps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsPageContainer.tsxapps/timo-web/app/[locale]/(main)/statistics/_mocks/statistics-calendar.tsapps/timo-web/app/[locale]/(main)/statistics/_types/statistics.tsapps/timo-web/app/[locale]/(main)/statistics/_utils/format-statistics-date.tsapps/timo-web/app/[locale]/(main)/statistics/_utils/statistics-calendar.tsapps/timo-web/app/[locale]/(main)/statistics/page.tsx
💤 Files with no reviewable changes (1)
- apps/timo-web/app/[locale]/(main)/statistics/_containers/StatisticsHeaderContainer.tsx
| export const statisticsCalendarResponseSchema = z.object({ | ||
| yearMonth: z.string(), | ||
| today: z.string(), | ||
| days: z.array( | ||
| z.object({ | ||
| date: z.string(), | ||
| completionRate: z.number().nullable(), | ||
| }), | ||
| ), | ||
| }); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Zod 4의 z.iso.date()로 날짜 문자열 검증을 강화하는 것을 제안합니다.
현재 z.string()은 모든 문자열을 허용하므로 날짜 형식 오류를 런타임에서 잡을 수 없습니다. Zod 4에서新增된 z.iso.date()를 사용하면 YYYY-MM-DD 형식 검증이 보장됩니다.
♻️ 제안하는 스키마 개선
export const statisticsCalendarResponseSchema = z.object({
- yearMonth: z.string(),
- today: z.string(),
+ yearMonth: z.string().regex(/^\d{4}-\d{2}$/),
+ today: z.iso.date(),
days: z.array(
z.object({
- date: z.string(),
+ date: z.iso.date(),
completionRate: z.number().nullable(),
}),
),
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const statisticsCalendarResponseSchema = z.object({ | |
| yearMonth: z.string(), | |
| today: z.string(), | |
| days: z.array( | |
| z.object({ | |
| date: z.string(), | |
| completionRate: z.number().nullable(), | |
| }), | |
| ), | |
| }); | |
| export const statisticsCalendarResponseSchema = z.object({ | |
| yearMonth: z.string().regex(/^\d{4}-\d{2}$/), | |
| today: z.iso.date(), | |
| days: z.array( | |
| z.object({ | |
| date: z.iso.date(), | |
| completionRate: z.number().nullable(), | |
| }), | |
| ), | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/timo-web/app/`[locale]/(main)/statistics/_types/statistics.ts around
lines 3 - 12, statisticsCalendarResponseSchema의 날짜 필드 검증을 강화하세요. yearMonth와
today는 현재 형식에 맞는 ISO 날짜 스키마를 사용하고, days 내부 객체의 date 필드도 z.string() 대신 Zod 4의
z.iso.date()로 검증하도록 변경하세요.
ISSUE 🔗
close #129
What is this PR? 🔍
통계 페이지의 월별 캘린더 UI를 구현했습니다.
월 상태를 어디에서 관리할지
처음에는 캘린더 내부에서
currentMonth를 관리할 수도 있다고 봤습니다.하지만 월 이동 버튼은 헤더에 있고, 캘린더는 그 월을 기준으로 날짜를 렌더링해야 합니다. 즉 헤더와 캘린더가 같은 월 상태를 공유해야 했습니다.
그래서
currentMonth는 페이지 레벨에서 관리하고, 헤더와 캘린더에 각각 props로 내려주는 구조를 선택했습니다.이 구조는 이후 API 연결 시에도 currentMonth를 기준으로 yearMonth 파라미터를 만들 수 있어 확장하기 쉽다고 판단했습니다.
page.tsx를 Server Component로 유지
초기에는 page.tsx에서 useState로 currentMonth를 관리했지만, 이 경우 page.tsx 전체가 Client Component가 됩니다.
App Router의 page.tsx는 라우트 진입점 역할에 집중하는 것이 좋다고 판단해, 상태 관리와 데이터 주입은 별도 컨테이너로 이동했습니다.
이를 통해 page.tsx는 Server Component로 유지하고, 클라이언트 상태가 필요한 부분만 컨테이너에서 관리하도록 분리했습니다.
캘린더는 현재 월 날짜만 렌더링
해당 월의 1일이 시작되는 요일에 맞춰 앞쪽에 빈 칸을 추가했습니다.
완료율 기반 아이콘 매핑
API 명세의 completionRate 값을 기준으로 캘린더 아이콘 상태를 결정하도록 했습니다.
아이콘 상태와 실제 SVG 컴포넌트는 매핑 객체로 관리했습니다.
날짜 계산 유틸 분리
_utils/statisticsCalendar.ts에 캘린더 계산 로직을 분리했습니다.
To Reviewers
이번 PR에서 하지 않은 것
이번 PR은 월별 캘린더 UI 구현에 집중했습니다.
아래 작업은 다음 단계에서 처리할 예정입니다.
날짜 클릭 상태는 오른쪽 패널 상태와 함께 움직여야 하므로, 캘린더 단독으로 처리하지 않고 이후 뷰 전환 작업에서 selectedDate 상태를 기준으로 함께 구현하는 것이 적절하다고 판단했습니다.
캘린더가 화면에 꽉 차 보이지 않는 문제
Figma의 gap, padding, grid width 값을 맞췄지만 브라우저에서는 캘린더가 덜 차 보이는 문제가 있었습니다.
이는 캘린더 내부 spacing 문제라기보다, 현재 PR에서 오른쪽 통계 패널과 전체 layout 전환이 아직 포함되지 않았기 때문이라고 판단했습니다.
캘린더 grid를 임의로 넓히면 Figma 기준의 아이콘 간격과 grid 비율이 깨질 수 있어, 이번 PR에서는 캘린더 자체 수치를 유지했습니다.
이후 오른쪽 패널과 selectedDate 기반 화면 전환이 붙는 시점에 전체 layout 기준으로 다시 확인할 예정입니다!
Screenshot 📷
Test Checklist ✔
completionRate값에 따라 통계 아이콘 상태를 다르게 표시