Skip to content

[FEAT] 투두 생성 모달 및 홈 투두 카드 UI 구현#138

Merged
kimminna merged 20 commits into
developfrom
feat/web/137-create-todo-modal
Jul 12, 2026
Merged

[FEAT] 투두 생성 모달 및 홈 투두 카드 UI 구현#138
kimminna merged 20 commits into
developfrom
feat/web/137-create-todo-modal

Conversation

@kimminna

@kimminna kimminna commented Jul 10, 2026

Copy link
Copy Markdown
Member

ISSUE 🔗

close #137



What is this PR? 🔍

홈 화면에서 할 일을 생성·조회·정렬할 수 있는 투두 생성 모달과 투두 카드 UI를 구현했습니다.

배경

  • 기존 구조: 홈 화면에 할 일을 추가할 모달이나 관련 디자인시스템 컴포넌트(아이콘/날짜/태그 선택기 등)가 없었습니다.
  • 발생 문제: 사용자가 할 일을 등록·관리할 UI 자체가 없어 홈 화면의 핵심 기능이 비어 있었습니다.
  • 해결 방향: 오버레이 기반 모달 인프라와 투두 생성에 필요한 디자인시스템 컴포넌트를 새로 만들고, 이를 조합해 투두 생성 모달과 홈 투두 카드(드래그 정렬 포함)를 구현했습니다.

의존성

  • 변경 요약: overlay-kit, @dnd-kit/modifiers 의존성을 추가했습니다.
  • 이유: 모달을 prop drilling 없이 열고 닫기 위해 overlay-kit이, 드래그를 세로 축으로 제한하기 위해 @dnd-kit/modifiers가 필요했습니다.
  • 구현 방식: overlay.open()으로 모달의 isOpen/close/unmount를 관리하고, DndContextmodifiers prop에 restrictToVerticalAxis를 전달했습니다.

디자인시스템 컴포넌트

  • 변경 요약: IconSelector/IconGraphic/DateSelector/TagNameInput/TodoToolbar를 새로 추가하고, 기존 PriorityIcon/PrioritySelector/RepeatSelector/TagSelector/TimeSelector를 모달 요구사항에 맞게 수정했습니다.
  • 이유: 투두 생성 폼에서 아이콘/날짜/태그/시간/반복/우선순위를 선택하는 UI가 design-system에 없었습니다.
  • 구현 방식: 각 컴포넌트는 값과 변경 콜백만 받는 controlled 형태로 만들어 app 레이어의 폼 라이브러리와 독립적으로 재사용 가능하게 했습니다. 투두 카테고리 아이콘 8종(SVG)도 함께 추가했습니다.

API 스키마 및 오버레이 모달 인프라

  • 변경 요약: 투두 생성 요청 zod 스키마(createTodoRequestSchema)를 정의하고, 오버레이 기반 Modal 컴포넌트와 OverlayProvider를 루트 레이아웃에 연결했습니다.
  • 이유: 아직 백엔드 API가 없어 폼 유효성 검증 기준이 필요했고, 투두/태그 생성 모달이 공통으로 쓸 오버레이 컨테이너가 없었습니다.
  • 구현 방식: date/duration 포맷을 정규식으로 검증하고, repeatType에 따라 repeatWeekdays/repeatDayOfMonth 필수 여부를 superRefine으로 처리했습니다. OverlayProviderlayout.tsxQueryProvider 내부에 배치했습니다.
  • 디자인시스템 Modal과 다르게 만든 이유: @repo/timo-design-systemModal(Modal.Root+Trigger+Panel)은 TriggerPanel이 같은 트리에 선언되고 isOpen을 내부 state로만 관리하는 비제어(uncontrolled) 컴파운드 컴포넌트입니다. 반면 이번 요구사항은 overlay.open()으로 트리거와 무관한 위치(날짜 컬럼별 추가 버튼)에서 모달을 열고, 닫힘 애니메이션이 끝난 뒤에만 unmount()를 호출해야 해서 isOpen/onClose/onExited를 외부에서 제어할 수 있는 형태가 필요했습니다. 디자인시스템 Modal은 이 "외부 제어 + exit-aware unmount" 계약을 지원하지 않아 그대로 재사용할 수 없었고, 그래서 apps/timo-web/components/modal/Modal.tsx를 앱 레이어에 별도로 만들어 overlay-kit과 연결했습니다.

홈 투두 생성 모달 및 투두 카드

  • 변경 요약: 투두 생성 모달, 태그 생성 모달, 홈 투두 카드/데이 헤더 UI를 구현하고, 관련 폴더를 todo-card/todo-modal/tag-modal 기능 단위로 재구성했습니다.
  • 이유: 기존에는 _components/_containers/_hooks가 타입별로만 분리돼 있어 하나의 기능을 수정할 때 여러 폴더를 오가야 했고, 모달 폼도 watch/setValue를 필드마다 직접 호출해 필드 하나가 바뀌어도 폼 전체가 리렌더되는 구조였습니다.
  • 구현 방식: useIconField/useTagField/useTimeField/useRepeatField 각 훅이 control을 받아 내부에서 useController로 해당 폼 필드를 직접 구독하도록 바꿔, 컨테이너 컴포넌트는 훅이 반환한 값을 JSX에 배치하기만 하면 되도록 했습니다. 홈 투두 카드는 @dnd-kit/sortableuseSortable로 정렬 가능하게 만들었고, restrictToVerticalAxis로 드래그 축을 세로로 제한했습니다. 디자인에 없던 카드 그랩(드래그 핸들) 아이콘은 제거했습니다.
  • 경계 · 제약: 투두/태그 생성은 실제 백엔드 연동 전까지 로컬 mock 데이터로 즉시 반영되며, 서버 연동은 이번 PR 범위 밖입니다.



To Reviewers

CreateTodoModalContent의 필드 훅들이 watch/setValue 대신 useController를 직접 구독하는 구조로 바뀌었으니, 필드별 리렌더링 범위가 의도대로 좁혀졌는지 봐주세요.
투두/태그 API가 아직 없어 todoId/tagId 채번과 저장이 클라이언트 로컬 상태로만 처리됩니다. 의도된 범위이며 후속 API 연동 PR에서 대체될 예정입니다.
pnpm --filter timo-web check-types가 실패하는데, origin/develop에 이미 있는 온보딩 아이콘(export 누락) 문제로 이번 PR 변경사항과는 무관함을 확인했습니다.



Screenshot 📷

image image



Test Checklist ✔

  • pnpm --filter timo-web lint 통과
  • pnpm --filter @repo/timo-design-system check-types 통과
  • pnpm --filter @repo/timo-design-system lint 통과
  • pnpm --filter timo-web check-types — origin/develop에 이미 있는 온보딩 아이콘 export 누락 오류로 실패 (이번 PR과 무관함을 확인)
  • 브라우저에서 투두 생성 모달/드래그 정렬 동작 확인 — 미실행: 이번 세션에서 실제 브라우저 검증을 하지 않았습니다
  • pnpm build — 미실행

kimminna added 4 commits July 11, 2026 00:34
- overlay-kit, @dnd-kit/modifiers 의존성을 추가했습니다
- 아이콘 선택기, 날짜 선택기, 태그 입력, 투두 툴바 컴포넌트를 추가했습니다
- 우선순위/반복/태그/시간 선택기를 투두 모달 요구사항에 맞게 수정했습니다
- 투두 아이콘 SVG 8종을 추가했습니다
- 투두 생성 요청 스키마를 정의했습니다
- 오버레이 기반 모달 컴포넌트와 프로바이더를 추가하고 루트 레이아웃에 연결했습니다
- 투두 생성 모달과 태그 생성 모달을 구현했습니다
- 홈 투두 카드와 데이 헤더 UI를 구현하고 드래그 정렬을 연동했습니다
- 모달 폼 필드 바인딩을 useController 기반으로 구현했습니다
- 드래그 정렬을 세로 축으로 제한했습니다
- 관련 폴더를 기능 단위(todo-card/todo-modal/tag-modal)로 구성했습니다
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
timo Ready Ready Preview, Comment Jul 12, 2026 6:34am

Request Review

@github-actions github-actions Bot added ⏰ Timo-web Timo 웹 서비스 ⌚ Timo-Design-system Timo 디자인 시스템 labels Jul 10, 2026
@github-actions github-actions Bot added ✨ Feature 새로운 기능(기능성) 구현 ♦️ 민아 민아상 labels Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kimminna, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4174f79b-d73e-4f13-9806-055e78d2e151

📥 Commits

Reviewing files that changed from the base of the PR and between c60c9db and 683286c.

📒 Files selected for processing (6)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts
  • apps/timo-web/components/modal/OverlayModal.tsx
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json

Walkthrough

투두 생성 API 스키마와 입력 폼, 오버레이·태그 생성 모달, 디자인시스템 컴포넌트가 추가되었다. 생성된 Todo는 홈의 날짜별 목록에 반영되며, 날짜·우선순위·반복 값과 관련 유틸리티 및 공개 export가 갱신되었다.

Changes

투두 생성 기능

Layer / File(s) Summary
투두 계약과 도메인 변환
apps/timo-web/api/todo/todo-schema.ts, apps/timo-web/utils/date.ts, apps/timo-web/app/.../todo-time.ts, packages/timo-design-system/src/components/icon/icon-graphic/*
생성 요청·응답 스키마, 반복 조건 검증, 날짜·기간 변환, Todo 아이콘 및 우선순위 타입이 정의되었다.
생성 UI 디자인시스템 구성
packages/timo-design-system/src/components/{calendar,icon,priority,repeat,tag,time,todo}/*
날짜·아이콘·태그·우선순위·반복·시간 선택기와 TodoToolbar가 추가되었고 Storybook 스토리와 공개 export가 갱신되었다.
모달 인프라와 입력 상태
apps/timo-web/providers/*, apps/timo-web/components/modal/*, apps/timo-web/.../todo-modal/*, apps/timo-web/package.json
OverlayProvider와 포털 모달이 연결되었으며, 생성 폼의 아이콘·반복·태그·시간·태스크·메모 입력 상태가 구현되었다.
투두·태그 생성 제출 흐름
apps/timo-web/.../CreateTodoModal*.tsx, CreateTagModalContainer.tsx, use-create-todo-submit.ts, messages/*.json
생성 모달과 태그 모달이 검증, 번역, 태그 생성, Todo 변환 및 제출 콜백으로 연결되었다.
홈 목록과 상호작용 연동
apps/timo-web/.../home/_containers/*, home/_hooks/*, home/_mocks/*, providers/dnd/*
날짜 헤더에서 생성 모달을 열고 생성된 Todo를 날짜별 목록에 추가하며, 홈 우선순위 표시와 드래그 동작이 갱신되었다.
날짜 유틸리티 공용화
apps/timo-web/utils/date.ts, home/_utils/date.ts, statistics/_utils/statistics-calendar.ts
날짜 키 포맷팅과 날짜 계산이 공용 유틸리티로 이동하고 기존 로컬 구현이 제거되었다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant HomeDayHeaderContainer
  participant CreateTodoModalContent
  participant TodoSchema
  participant useCreateTodoSubmit
  participant HomeTodoContainer

  User->>HomeDayHeaderContainer: 생성 버튼 클릭
  HomeDayHeaderContainer->>CreateTodoModalContent: 날짜와 모달 표시
  User->>CreateTodoModalContent: Todo 입력 및 제출
  CreateTodoModalContent->>TodoSchema: 요청 데이터 검증
  TodoSchema-->>CreateTodoModalContent: 검증 결과
  CreateTodoModalContent->>useCreateTodoSubmit: 검증된 데이터 전달
  useCreateTodoSubmit->>HomeTodoContainer: Todo 생성 콜백 호출
  HomeTodoContainer->>HomeTodoContainer: 날짜별 목록에 Todo 추가
Loading

Possibly related PRs

Suggested labels: ♥️ 혜원

Suggested reviewers: yumin-kim2, ehye1, jjangminii

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 투두 생성 모달과 홈 투두 카드 UI라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 설명이 투두 생성·조회·정렬 UI와 관련 컴포넌트/모달 인프라 변경을 잘 설명합니다.
Linked Issues check ✅ Passed #137의 투두 모달, 태그 모달, 디자인시스템, 오버레이, 드래그 정렬 요구사항이 전반적으로 구현되었습니다.
Out of Scope Changes check ✅ Passed 스토리북과 유틸 리팩터링도 모두 투두 생성·카드 UI 구현 범위에 맞아 보이는 별도 이슈는 없습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web/137-create-todo-modal

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Storybook Preview

항목 링크
Storybook 열기
Chromatic 빌드 확인

마지막 업데이트: 2026-07-12 06:33 UTC

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Timo Performance Report

Bundle Size — timo-web
라우트 크기 First Load JS
/[locale]/home 164.44 kB 🔴 370.25 kB
/[locale]/today 62.26 kB 🟡 268.08 kB
/[locale]/focus 58.84 kB 🟡 264.66 kB
/[locale]/settings/account 0 B 🟡 205.81 kB
/[locale]/settings 0 B 🟡 205.81 kB
/[locale]/settings/policy 0 B 🟡 205.81 kB
/[locale]/statistics 57.82 kB 🟡 263.63 kB
/[locale]/[...rest] 0 B 🟡 205.81 kB
/[locale]/onboarding 109.29 kB 🟡 315.10 kB
/[locale] 0 B 🟡 205.81 kB

공유 번들: 205.81 kB
🟢 < 200kB  |  🟡 < 350kB  |  🔴 ≥ 350kB (First Load JS · gzip)

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 64 🟢 96 🔴 14.4s 🟢 0.000 🟡 438ms
/en/today 🟡 70 🟡 93 🔴 13.7s 🟢 0.000 🟡 249ms
/en/focus 🟡 72 🟡 91 🔴 13.7s 🟢 0.000 🟢 190ms
/en/statistics 🔴 58 🟢 96 🔴 13.7s 🟢 0.000 🔴 691ms

Perf ≥ 70 / A11y ≥ 85 목표
LCP 🟢 < 2.5s 🟡 < 4s 🔴 ≥ 4s  |  CLS 🟢 < 0.1 🟡 < 0.25 🔴 ≥ 0.25  |  TBT 🟢 < 200ms 🟡 < 600ms 🔴 ≥ 600ms

Image Optimization — timo-web

public/ 디렉토리에 이미지가 없습니다.

측정 커밋: 35e10d6

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🤖 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/api/todo/todo-schema.ts`:
- Around line 43-76: createTodoRequestSchema의 superRefine에서 repeatType과 반복 필드의
불일치를 검증하도록 보강하세요. WEEKLY가 아닐 때 repeatWeekdays가 비어 있지 않으면 해당 값을 무효화하거나 검증 오류를
추가하고, MONTHLY가 아닐 때 repeatDayOfMonth가 null이 아니면 동일하게 처리하여 stale 데이터가 백엔드로 전송되지
않도록 하세요.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_components/todo-modal/CreateTodoMemoField.tsx:
- Around line 12-20: textarea in CreateTodoMemoField currently removes the focus
outline without a replacement. Replace the unconditional outline-none styling
with a focus-visible-based accessible focus indicator, using focus-visible:ring
or an equivalent visible border/outline style while preserving the default
non-focused appearance.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_components/todo-modal/CreateTodoTaskFields.tsx:
- Around line 22-39: title and subtask inputs in CreateTodoTaskFields use
outline-none without a visible keyboard focus indicator. Replace the
unconditional outline removal on both inputs with focus-visible styles that
provide a clear focus outline or equivalent ring while preserving the existing
appearance otherwise.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx:
- Around line 55-62: Update the close button in CreateTagModalContainer to use a
tag-modal-specific or shared close-label translation instead of
t("createModal.close"). Prefer adding and using the createTagModal.close key, or
use the existing Common.close key consistently with the translation structure.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx:
- Around line 115-119: subtasks 매핑에서 각 항목에 동일한 Date.now() 값이 할당되지 않도록 수정하세요.
CreateTodoModalContent의 subtaskId 생성 로직을 확인해 고유한 ID를 생성하도록 인덱스나 UUID 등 안정적인 식별자를
사용하고, 토글·삭제 로직과의 일관성도 유지하세요.
- Line 122: In the reset call within CreateTodoModalContent, pass the existing
defaultDate to createDefaultValues instead of calling it without arguments, so
the form retains the selected default date after submission.
- Around line 233-237: Expose validation failures from zodResolver in
CreateTodoModalContent instead of silently ignoring them: use formState.errors
to render an inline message or provide an onInvalid callback to handleSubmit,
especially for conditions such as missing WEEKLY days. Keep the existing
title-based disabled state while ensuring users receive a clear error when
validation blocks submission.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_hooks/useHomeTodosByDate.ts:
- Around line 35-42: handleAddTodo의 TODO API를 구현해 로컬 상태만 갱신하지 않도록 하세요. Todo 생성
API를 호출하고 성공 시 서버 응답으로 상태를 반영하며, 실패 시 낙관적으로 추가한 항목을 제거하는 rollback과 사용자에게 오류를 알리는
처리를 추가하세요.

In `@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_utils/date.ts:
- Around line 79-85: formatDateToIsoDate와 기존 formatDateKey가 동일한 날짜 포맷팅 로직을 중복
구현하고 있습니다. 두 함수의 의미가 동일하면 하나를 제거하고 기존 함수를 사용하며, 별도 공개 API가 필요하면
formatDateToIsoDate가 formatDateKey를 호출하도록 변경해 중복을 없애세요.

In `@apps/timo-web/components/modal/Modal.tsx`:
- Around line 11-17: ModalProps에 선택적 aria-label 프로퍼티를 추가하고, Modal 컴포넌트의
role="dialog" 요소에 해당 값을 전달하세요. 호출부에서 모달 목적을 설명하는 accessible name을 제공할 수 있도록 기본값
없이 구현하고, 기존 className 및 기타 속성 동작은 유지하세요.
- Around line 48-87: Modal의 포커스 관리가 없어 키보드 사용자가 대화상자 밖으로 이동할 수 있습니다. `Modal`
컴포넌트의 `useEffect`와 dialog 요소를 수정해 열리기 전 활성 요소를 저장하고 열린 직후 첫 번째 포커스 가능 요소(없으면
dialog 자체)로 포커스를 이동하세요. `keydown` 처리에서 Tab 이동을 dialog 내부의 포커스 가능 요소 사이로 순환시키고,
닫힐 때 저장한 이전 요소로 포커스를 복원하며 dialog에 필요한 `tabIndex={-1}`를 추가하세요.

In
`@packages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.tsx`:
- Around line 15-23: TodoIconValue와 todoIconSchema의 아이콘 값이 중복 정의되어 있으므로,
IconGraphic.tsx에서 ICON_1~ICON_8을 담은 공용 상수를 먼저 만들고 이를 기반으로 TodoIconValue 타입과
z.enum(...) 스키마를 파생시키세요. 두 정의가 동일한 소스를 참조하도록 관련 선언을 정리하세요.

In `@packages/timo-design-system/src/components/index.ts`:
- Around line 22-42: 기존 소비자가 Modal 관련 타입을 import할 수 있도록
`src/components/index.ts`의 barrel export에서 `ModalButtonVariantTypes`,
`ModalButtonProps` 및 `Modal.tsx`의 관련 props 타입을 다시 re-export하세요. 기존 `Modal` 컴포넌트
export는 유지하고, 필요하면 호환 가능한 별도 `modal` 진입점도 함께 유지하세요.

In
`@packages/timo-design-system/src/components/tag/tag-name-input/TagNameInput.tsx`:
- Around line 30-35: TagNameInput의 입력 접근성을 개선하세요. TagNameInput 컴포넌트에서 useId()로
인스턴스별 고유 ID를 생성하고 input의 id와 접근 가능한 이름(aria-label 또는 연결된 label)에 사용하세요. input의
className에서 outline-none을 제거하고 키보드 포커스가 명확히 보이는 기본 또는 대체 focus 스타일을 유지하세요.
🪄 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: cfbe899b-c4cd-41e8-8eb9-6edf98da2264

📥 Commits

Reviewing files that changed from the base of the PR and between c6e0879 and 87c8f56.

⛔ Files ignored due to path filters (9)
  • packages/timo-design-system/src/icons/source/todo-icon-daily.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-etc.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-plus.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-relationship.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-rest.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-study.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-task.svg is excluded by !**/*.svg
  • packages/timo-design-system/src/icons/source/todo-icon-work.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (46)
  • apps/timo-web/api/todo/todo-schema.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_components/todo-card/HomeDateInformation.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_components/todo-card/HomeTodoCard.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_components/todo-modal/CreateTodoIconField.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_components/todo-modal/CreateTodoMemoField.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_components/todo-modal/CreateTodoTaskFields.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-card/HomeDayHeaderContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-icon-field.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-repeat-field.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-tag-field.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-time-field.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/useHomeTodosByDate.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/useHomeViewMode.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_mocks/todo-mock.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_types/todo-type.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_utils/date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_utils/todo-time.ts
  • apps/timo-web/app/[locale]/layout.tsx
  • apps/timo-web/components/modal/Modal.tsx
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json
  • apps/timo-web/package.json
  • apps/timo-web/providers/OverlayProvider.tsx
  • apps/timo-web/providers/dnd/DndSortableListProvider.tsx
  • packages/timo-design-system/src/components/calendar/date-selector/DateSelector.stories.tsx
  • packages/timo-design-system/src/components/calendar/date-selector/DateSelector.tsx
  • packages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.stories.tsx
  • packages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.tsx
  • packages/timo-design-system/src/components/icon/icon-selector/IconSelector.stories.tsx
  • packages/timo-design-system/src/components/icon/icon-selector/IconSelector.tsx
  • packages/timo-design-system/src/components/index.ts
  • packages/timo-design-system/src/components/priority/priority-icon/PriorityIcon.stories.tsx
  • packages/timo-design-system/src/components/priority/priority-icon/PriorityIcon.tsx
  • packages/timo-design-system/src/components/priority/priority-selector/PrioritySelector.stories.tsx
  • packages/timo-design-system/src/components/priority/priority-selector/PrioritySelector.tsx
  • packages/timo-design-system/src/components/repeat/repeat-selector/RepeatSelector.stories.tsx
  • packages/timo-design-system/src/components/repeat/repeat-selector/RepeatSelector.tsx
  • packages/timo-design-system/src/components/tag/tag-name-input/TagNameInput.stories.tsx
  • packages/timo-design-system/src/components/tag/tag-name-input/TagNameInput.tsx
  • packages/timo-design-system/src/components/tag/tag-selector/TagSelector.tsx
  • packages/timo-design-system/src/components/time/time-selector/TimeSelector.tsx
  • packages/timo-design-system/src/components/todo/todo-toolbar/TodoToolbar.tsx

Comment thread apps/timo-web/api/todo/todo-schema.ts
Comment thread apps/timo-web/components/modal/Modal.tsx Outdated
Comment thread apps/timo-web/components/modal/Modal.tsx Outdated
Comment thread packages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.tsx Outdated
Comment thread packages/timo-design-system/src/components/index.ts Outdated
kimminna added 2 commits July 11, 2026 03:50
- _hooks/useHomeTodayScroll.ts를 use-home-today-scroll.ts로 변경했습니다
- _hooks/useHomeTodosByDate.ts를 use-home-todos-by-date.ts로 변경했습니다
- _hooks/useHomeViewMode.ts를 use-home-view-mode.ts로 변경했습니다
- 네이밍 컨벤션에 맞춰 참조하는 컨테이너의 import 경로를 갱신했습니다
- 투두 생성(mock) 조립 로직을 use-create-todo-submit 훅으로 분리했습니다
- CreateTodoModalContainer가 useCreateTodoSubmit을 통해 생성 사이드 이펙트를 소유하도록 했습니다
- CreateTodoModalContent는 onSubmit prop만 호출하도록 하여 폼 검증·렌더링만 담당하게 했습니다

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

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)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx (1)

94-94: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

선택한 날짜를 handleAddTodo까지 전달하세요.
HomeTodoContainer.tsx:94에서 dateKey만 쓰면 모달에서 바꾼 data.date가 반영되지 않습니다. use-create-todo-submit.ts:8-38에서 buildTodoFromRequestdata.date를 버리고 있어서, 날짜를 수정해도 원래 컬럼에 추가됩니다. data.date를 상위로 넘겨 dateKey를 다시 계산하거나, Tododate를 포함해 저장 경로를 유지하세요. React Hook Form handleSubmit처럼 제출값은 중간에서 잃지 않는 구조가 좋습니다: https://react-hook-form.com/docs/useform/handlesubmit

🤖 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)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
at line 94, 모달에서 변경한 날짜가 저장 경로에서 유실되고 있습니다. HomeTodoContainer의 onCreateTodo와
handleAddTodo 호출 흐름에서 제출된 data.date를 상위로 전달하고, use-create-todo-submit의
buildTodoFromRequest가 해당 날짜를 보존하도록 수정하세요. 필요하면 data.date로 dateKey를 재계산해 올바른 날짜
컬럼에 추가되게 하며, React Hook Form handleSubmit처럼 제출값을 중간에서 버리지 않도록 전체 호출 체인을 점검하세요.
🤖 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)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts:
- Line 12: use-create-todo-submit.ts의 서브태스크 생성 로직에서 .map() 내부의 Date.now() 기반
todoId가 모든 항목에 동일하게 생성되고 상위 todoId와 충돌할 수 있습니다. 고유 ID 생성 유틸리티 또는 충돌을 방지하는 안정적인
ID 생성 방식을 사용해 각 서브태스크의 todoId를 독립적으로 생성하고, 관련 23–24행의 ID 할당도 동일하게 수정하세요.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts:
- Around line 16-20: When apiDays changes, the useEffect currently replaces
todosByDate and discards todos added locally by handleAddTodo. Preserve pending
local additions by tracking them in a separate overlay state and merging it with
the API-derived entries, or by merging additions into the incoming apiDays
result; update handleAddTodo and the apiDays synchronization logic consistently
so filter/baseDate refreshes retain unsynced todos.

---

Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx:
- Line 94: 모달에서 변경한 날짜가 저장 경로에서 유실되고 있습니다. HomeTodoContainer의 onCreateTodo와
handleAddTodo 호출 흐름에서 제출된 data.date를 상위로 전달하고, use-create-todo-submit의
buildTodoFromRequest가 해당 날짜를 보존하도록 수정하세요. 필요하면 data.date로 dateKey를 재계산해 올바른 날짜
컬럼에 추가되게 하며, React Hook Form handleSubmit처럼 제출값을 중간에서 버리지 않도록 전체 호출 체인을 점검하세요.
🪄 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: efcb067f-3026-495d-8a71-204b9d87d5f0

📥 Commits

Reviewing files that changed from the base of the PR and between 87c8f56 and 97f30e1.

📒 Files selected for processing (8)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeHeaderContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-today-scroll.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-view-mode.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

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)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx (1)

94-94: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

선택한 날짜를 handleAddTodo까지 전달하세요.
HomeTodoContainer.tsx:94에서 dateKey만 쓰면 모달에서 바꾼 data.date가 반영되지 않습니다. use-create-todo-submit.ts:8-38에서 buildTodoFromRequestdata.date를 버리고 있어서, 날짜를 수정해도 원래 컬럼에 추가됩니다. data.date를 상위로 넘겨 dateKey를 다시 계산하거나, Tododate를 포함해 저장 경로를 유지하세요. React Hook Form handleSubmit처럼 제출값은 중간에서 잃지 않는 구조가 좋습니다: https://react-hook-form.com/docs/useform/handlesubmit

🤖 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)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
at line 94, 모달에서 변경한 날짜가 저장 경로에서 유실되고 있습니다. HomeTodoContainer의 onCreateTodo와
handleAddTodo 호출 흐름에서 제출된 data.date를 상위로 전달하고, use-create-todo-submit의
buildTodoFromRequest가 해당 날짜를 보존하도록 수정하세요. 필요하면 data.date로 dateKey를 재계산해 올바른 날짜
컬럼에 추가되게 하며, React Hook Form handleSubmit처럼 제출값을 중간에서 버리지 않도록 전체 호출 체인을 점검하세요.
🤖 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)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts:
- Line 12: use-create-todo-submit.ts의 서브태스크 생성 로직에서 .map() 내부의 Date.now() 기반
todoId가 모든 항목에 동일하게 생성되고 상위 todoId와 충돌할 수 있습니다. 고유 ID 생성 유틸리티 또는 충돌을 방지하는 안정적인
ID 생성 방식을 사용해 각 서브태스크의 todoId를 독립적으로 생성하고, 관련 23–24행의 ID 할당도 동일하게 수정하세요.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts:
- Around line 16-20: When apiDays changes, the useEffect currently replaces
todosByDate and discards todos added locally by handleAddTodo. Preserve pending
local additions by tracking them in a separate overlay state and merging it with
the API-derived entries, or by merging additions into the incoming apiDays
result; update handleAddTodo and the apiDays synchronization logic consistently
so filter/baseDate refreshes retain unsynced todos.

---

Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx:
- Line 94: 모달에서 변경한 날짜가 저장 경로에서 유실되고 있습니다. HomeTodoContainer의 onCreateTodo와
handleAddTodo 호출 흐름에서 제출된 data.date를 상위로 전달하고, use-create-todo-submit의
buildTodoFromRequest가 해당 날짜를 보존하도록 수정하세요. 필요하면 data.date로 dateKey를 재계산해 올바른 날짜
컬럼에 추가되게 하며, React Hook Form handleSubmit처럼 제출값을 중간에서 버리지 않도록 전체 호출 체인을 점검하세요.
🪄 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: efcb067f-3026-495d-8a71-204b9d87d5f0

📥 Commits

Reviewing files that changed from the base of the PR and between 87c8f56 and 97f30e1.

📒 Files selected for processing (8)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeHeaderContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-today-scroll.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-view-mode.ts
🛑 Comments failed to post (2)
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts (1)

12-12: 🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Date.now() 기반 ID 충돌 — 서브태스크가 모두 동일한 subtaskId를 갖습니다.

이전 리뷰에서 CreateTodoModalContent.tsx의 동일한 문제를 지적했고 수정되었으나, 리팩토링으로 로직이 이 파일로 이동하면서 수정이 유실되었습니다. .map()Date.now()가 동기 호출되어 모든 서브태스크가 같은 ID를 갖게 되고, todoId와도 충돌할 수 있습니다.

 ): Todo => ({
-  todoId: Date.now(),
+  todoId: Date.now(),
   icon: data.icon,
   title: data.title,
   completed: false,
   durationSeconds: convertApiDurationToSeconds(data.duration),
   priority: data.priority ?? "MEDIUM",
   tag: { tagId: tag.id, name: tag.name },
   hasMemo: Boolean(data.memo?.trim()),
   isRepeated: data.repeatType !== "NONE",
   timerStatus: "STOPPED",
   sortOrder: 0,
   subtasks: (data.subtasks ?? []).map((content, index) => ({
-    subtaskId: Date.now(),
+    subtaskId: Date.now() + index,
     content,
     completed: false,
   })),
 }),

참고: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now

Also applies to: 23-24

🤖 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)/(with-time-sidebar)/home/_hooks/todo-modal/use-create-todo-submit.ts
at line 12, use-create-todo-submit.ts의 서브태스크 생성 로직에서 .map() 내부의 Date.now() 기반
todoId가 모든 항목에 동일하게 생성되고 상위 todoId와 충돌할 수 있습니다. 고유 ID 생성 유틸리티 또는 충돌을 방지하는 안정적인
ID 생성 방식을 사용해 각 서브태스크의 todoId를 독립적으로 생성하고, 관련 23–24행의 ID 할당도 동일하게 수정하세요.
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts (1)

16-20: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts'

echo "== file exists =="
git ls-files "$FILE"

echo "== outline =="
ast-grep outline "$FILE" --view expanded || true

echo "== file contents =="
cat -n "$FILE"

Repository: Team-Timo/Timo-client

Length of output: 4349


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find related usages and the hook's consumers to understand state ownership.
rg -n "useHomeTodosByDate|handleAddTodo|todosByDate|apiDays" apps/timo-web/app/[locale]/\(main\)/\(with-time-sidebar\)/home -S

# Show nearby files if present.
fd -a "use-home-todos-by-date" apps/timo-web/app/[locale]/\(main\)/\(with-time-sidebar\)/home || true

Repository: Team-Timo/Timo-client

Length of output: 2864


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts'

# Show only the hook and its immediate neighborhood with line numbers.
sed -n '1,220p' "$FILE" | cat -n

echo
echo "== related search =="
rg -n "setTodosByDate|handleAddTodo|apiDays" "$FILE" -n -S

Repository: Team-Timo/Timo-client

Length of output: 4629


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx'
sed -n '1,180p' "$FILE" | cat -n

Repository: Team-Timo/Timo-client

Length of output: 6861


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether apiDays is stable/memoized and how todosByDate is consumed.
rg -n "useMemo|useHomeTodosByDate|todosByDate\[dateKey\]|day\.todos|isWeekView" \
  apps/timo-web/app/[locale]/\(main\)/\(with-time-sidebar\)/home/_containers/HomeTodoContainer.tsx -n -S

Repository: Team-Timo/Timo-client

Length of output: 850


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx'
echo "== file exists =="
git ls-files "$FILE"

echo "== outline =="
ast-grep outline "$FILE" --view expanded || true

echo "== contents =="
sed -n '1,220p' "$FILE" | cat -n

Repository: Team-Timo/Timo-client

Length of output: 7279


apiDays 갱신 시 로컬 추가 투두를 보존하세요. 구조는 깔끔합니다. 다만 handleAddTodo가 만든 항목은 로컬 상태에만 남아 있어서, filter/baseDate 변경으로 apiDays가 다시 들어오면 useEffecttodosByDate를 통째로 덮어씁니다. 아직 API에 반영되지 않은 추가분은 별도 오버레이 상태로 분리하거나 새 apiDays와 병합해 주세요. React의 derived state 안내도 참고할 만합니다: https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes

🤖 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)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
around lines 16 - 20, When apiDays changes, the useEffect currently replaces
todosByDate and discards todos added locally by handleAddTodo. Preserve pending
local additions by tracking them in a separate overlay state and merging it with
the API-derived entries, or by merging additions into the incoming apiDays
result; update handleAddTodo and the apiDays synchronization logic consistently
so filter/baseDate refreshes retain unsynced todos.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/messages/ko.json`:
- Around line 68-82: Update the Korean strings in the Error and GlobalError
entries to use “잠시 후” and “이동해 주세요” with proper spacing, and add a final period
to the NotFound description. Preserve the existing translations and structure.
🪄 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: c2696c17-ea4f-4e67-9ff2-ee234dd233e3

📥 Commits

Reviewing files that changed from the base of the PR and between 97f30e1 and 692ddbf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json
  • apps/timo-web/package.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 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/messages/ko.json`:
- Around line 68-82: Update the Korean strings in the Error and GlobalError
entries to use “잠시 후” and “이동해 주세요” with proper spacing, and add a final period
to the NotFound description. Preserve the existing translations and structure.
🪄 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: c2696c17-ea4f-4e67-9ff2-ee234dd233e3

📥 Commits

Reviewing files that changed from the base of the PR and between 97f30e1 and 692ddbf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json
  • apps/timo-web/package.json
🛑 Comments failed to post (1)
apps/timo-web/messages/ko.json (1)

68-82: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

한국어 문구의 띄어쓰기와 마침표를 다듬어 주세요.

잠시후잠시 후, 이동해주세요이동해 주세요로 띄어 쓰고, NotFound 설명 끝에 마침표를 추가하면 문구 일관성이 좋아집니다.

권장 수정
-    "description": "더 나은 경험을 위해 잠시 점검 중입니다. 잠시후 다시 이용해 주세요.",
+    "description": "더 나은 경험을 위해 잠시 점검 중입니다. 잠시 후 다시 이용해 주세요.",
...
-    "description": "존재하지 않는 주소를 입력하셨거나, 잘못된 경로를 이용하셨어요",
+    "description": "존재하지 않는 주소를 입력하셨거나, 잘못된 경로를 이용하셨어요.",
...
-    "description": "잠시 후 다시 시도하거나 홈으로 이동해주세요.",
+    "description": "잠시 후 다시 시도하거나 홈으로 이동해 주세요.",
📝 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.

  "Error": {
    "title": "잠시 문제가 발생했어요.",
    "description": "더 나은 경험을 위해 잠시 점검 중입니다. 잠시 후 다시 이용해 주세요.",
    "homeButton": "홈으로 돌아가기"
  },
  "NotFound": {
    "title": "페이지를 찾을 수 없어요.",
    "description": "존재하지 않는 주소를 입력하셨거나, 잘못된 경로를 이용하셨어요.",
    "homeButton": "홈으로 돌아가기"
  },
  "GlobalError": {
    "title": "문제가 발생했어요.",
    "description": "잠시 후 다시 시도하거나 홈으로 이동해 주세요.",
    "homeButton": "홈으로 돌아가기"
  },
🤖 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/messages/ko.json` around lines 68 - 82, Update the Korean
strings in the Error and GlobalError entries to use “잠시 후” and “이동해 주세요” with
proper spacing, and add a final period to the NotFound description. Preserve the
existing translations and structure.

kimminna added 4 commits July 11, 2026 18:22
- useId()로 input에 고유 id를 부여했습니다
- ariaLabel prop을 추가해 접근 가능한 이름을 제공하도록 했습니다
- outline-none만 있던 포커스 스타일을 focus-visible:ring으로 교체했습니다
- 신규 필수 prop ariaLabel에 기존 시각적 라벨 텍스트를 전달하도록 반영했습니다
- home/statistics/today 기능에 흩어져 있던 날짜 유틸을 apps/timo-web/utils/date.ts 하나로 모았습니다
- statistics/_utils/statistics-calendar.ts에 완전히 중복 구현돼 있던 formatDateKey를 제거했습니다
- 기존 apps/timo-web/utils/format-date.ts의 formatDate도 함께 통합했습니다
- PRIORITY_MAP이 PriorityIcon이 기대하는 VERY_HIGH/HIGH/MEDIUM/LOW 대신 소문자 값으로 잘못 매핑되어 있던 타입 에러를 수정했습니다
kimminna added 4 commits July 11, 2026 18:47
- ICON_1~ICON_8을 담은 TODO_ICON_VALUES 상수를 만들고 TodoIconValue 타입을 이로부터 파생시켰습니다
- TODO_ICON_OPTIONS도 같은 상수를 참조하도록 정리했습니다
- ICON_1~ICON_8을 하드코딩하던 z.enum 목록을 제거하고 TODO_ICON_VALUES에서 파생하도록 했습니다
- 모달 포커스 트랩 구현에 사용할 focus-trap-react를 추가했습니다
- 디자인시스템의 Modal 컴포넌트와 이름이 겹쳐 헷갈리지 않도록 OverlayModal로 이름을 바꿨습니다
- aria-label을 받아 대화상자에 접근 가능한 이름을 제공할 수 있도록 했습니다
- focus-trap-react로 Tab 포커스를 다이얼로그 내부로 트랩하고, 열릴 때 초기 포커스를, 닫힐 때 이전 포커스를 복원하도록 했습니다

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (3)
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx (1)

110-114: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

OverlayModalariaLabel prop이 누락되었습니다.

OverlayModal은 내부적으로 aria-label={ariaLabel}을 렌더링하지만, 현재 prop이 전달되지 않아 dialog 요소에 접근 가능한 이름(accessible name)이 없습니다. 스크린 리더 사용자가 모달의 목적을 파악하기 어렵습니다.

🛡️ 제안 수정
       <OverlayModal
         isOpen={isOpen}
         onClose={onClose}
         onExited={onExited}
+        ariaLabel={t("createModal.title")}
         className="w-[490px] items-center gap-2.5 px-6 py-4"
       >

As per coding guidelines, **/*.{ts,tsx} 파일에서 텍스트 없는 버튼에 aria-label이 필수이며, 시맨틱 태그와 접근성 규칙을 준수해야 합니다.

[accessibility]

🤖 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)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
around lines 110 - 114, Update the OverlayModal invocation in
CreateTodoModalContent to pass an ariaLabel describing the todo-creation modal,
ensuring the rendered dialog has an accessible name while preserving the
existing modal behavior.

Source: Path instructions

apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx (1)

45-49: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

OverlayModalariaLabel prop이 누락되었습니다.

CreateTodoModalContent와 동일한 문제입니다. OverlayModalaria-label={ariaLabel}을 렌더링하지만 prop이 전달되지 않아 dialog에 접근 가능한 이름이 없습니다.

🛡️ 제안 수정
     <OverlayModal
       isOpen={isOpen}
       onClose={onClose}
       onExited={onExited}
+      ariaLabel={t("createTagModal.title")}
       className="w-[490px] items-center gap-3 px-6 py-4"
     >

As per coding guidelines, **/*.{ts,tsx} 파일에서 접근성 규칙을 준수해야 하며, 시맨틱 태그와 aria-label 사용이 권장됩니다.

[accessibility]

🤖 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)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx
around lines 45 - 49, Update the OverlayModal usage in CreateTagModalContainer
to pass an appropriate ariaLabel value, using the modal’s existing title or
accessible-label source. Ensure the dialog receives a non-empty accessible name
while preserving the existing open, close, and exit behavior.

Source: Path instructions

apps/timo-web/components/modal/OverlayModal.tsx (1)

33-50: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

onClose/onExited를 ref로 고정하세요
apps/timo-web/components/modal/OverlayModal.tsx:33-67에서 콜백을 deps에 직접 넣으면 부모가 새 함수를 넘길 때 onExited 타이머가 리셋되어 닫힘 완료가 지연될 수 있고, keydown 리스너도 불필요하게 재등록됩니다. useRef로 최신 콜백만 읽고 effect deps는 isOpen/shouldRender만 유지하는 쪽이 더 단단합니다. React useEffect/useRef 참고: https://react.dev/reference/react/useEffect, https://react.dev/reference/react/useRef

🤖 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/components/modal/OverlayModal.tsx` around lines 33 - 50, Update
OverlayModal’s useEffect and keydown-listener logic to store the latest onClose
and onExited callbacks in useRef values, then read those refs when invoking
them. Remove callback identities from the effect dependencies so changing parent
callbacks does not restart the exit timer or re-register listeners; retain only
the necessary isOpen/shouldRender dependencies.
♻️ Duplicate comments (3)
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx (2)

102-102: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

reset() 호출 시 defaultDate가 여전히 누락되어 있습니다.

이전 리뷰에서 제안된 수정이 아직 적용되지 않은 것으로 보입니다. reset(createDefaultValues()) 대신 reset(createDefaultValues(defaultDate))를 사용해야 제출 후에도 선택했던 날짜가 유지됩니다.

💚 제안 수정
-    reset(createDefaultValues());
+    reset(createDefaultValues(defaultDate));
🤖 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)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
at line 102, Update the reset call in CreateTodoModalContent to pass defaultDate
into createDefaultValues, using reset(createDefaultValues(defaultDate)), so the
selected date remains preserved after submission.

213-217: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

검증 실패 시 에러가 여전히 사용자에게 보이지 않습니다.

이전 리뷰에서 지적된 내용이 아직 적용되지 않았습니다. zodResolver(createTodoRequestSchema)WEEKLY 요일 누락 등의 조건을 막을 때, handleSubmit이 조용히 종료되어 사용자가 제출이 안 되는 원인을 알 수 없습니다. formState.errors를 화면에 노출하거나 handleSubmit(onSubmit, onInvalid) 패턴으로 에러 피드백을 추가해 주세요.

참고: react-hook-form handleSubmit 문서

🤖 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)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
around lines 213 - 217, Update the CreateTodoModalContent submission flow around
handleSubmit(handleFormSubmit) so validation failures from zodResolver are
surfaced to the user instead of being silently ignored. Expose formState.errors
in the UI or add an onInvalid callback to handleSubmit that provides clear
validation feedback, while preserving the existing valid-submit behavior.
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx (1)

57-57: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

닫기 버튼 aria-label이 여전히 createModal 네임스페이스를 참조합니다.

이전 리뷰에서 지적된 내용이 아직 적용되지 않았습니다. 태그 모달의 닫기 버튼이 t("createModal.close")를 사용하고 있습니다. createTagModal.close 키를 추가하거나 공통 Common.close 키를 사용하는 것이 더 일관성 있습니다.

💚 제안 수정
-        aria-label={t("createModal.close")}
+        aria-label={t("createTagModal.close")}
🤖 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)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx
at line 57, Update the close button’s translation reference in the tag modal
container from the createModal namespace to the tag modal’s createTagModal.close
key, or the shared Common.close key if that is the established convention;
ensure the rendered aria-label remains localized.
🤖 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/components/modal/OverlayModal.tsx`:
- Around line 12-19: Update OverlayModalProps and both OverlayModal consumers so
every role="dialog" instance has an accessible name. Prefer making ariaLabel
required and passing a meaningful label from each caller, or connect the
existing rendered title through aria-labelledby; do not leave either usage
without a dialog name.

---

Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx:
- Around line 45-49: Update the OverlayModal usage in CreateTagModalContainer to
pass an appropriate ariaLabel value, using the modal’s existing title or
accessible-label source. Ensure the dialog receives a non-empty accessible name
while preserving the existing open, close, and exit behavior.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx:
- Around line 110-114: Update the OverlayModal invocation in
CreateTodoModalContent to pass an ariaLabel describing the todo-creation modal,
ensuring the rendered dialog has an accessible name while preserving the
existing modal behavior.

In `@apps/timo-web/components/modal/OverlayModal.tsx`:
- Around line 33-50: Update OverlayModal’s useEffect and keydown-listener logic
to store the latest onClose and onExited callbacks in useRef values, then read
those refs when invoking them. Remove callback identities from the effect
dependencies so changing parent callbacks does not restart the exit timer or
re-register listeners; retain only the necessary isOpen/shouldRender
dependencies.

---

Duplicate comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx:
- Line 57: Update the close button’s translation reference in the tag modal
container from the createModal namespace to the tag modal’s createTagModal.close
key, or the shared Common.close key if that is the established convention;
ensure the rendered aria-label remains localized.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx:
- Line 102: Update the reset call in CreateTodoModalContent to pass defaultDate
into createDefaultValues, using reset(createDefaultValues(defaultDate)), so the
selected date remains preserved after submission.
- Around line 213-217: Update the CreateTodoModalContent submission flow around
handleSubmit(handleFormSubmit) so validation failures from zodResolver are
surfaced to the user instead of being silently ignored. Expose formState.errors
in the UI or add an onInvalid callback to handleSubmit that provides clear
validation feedback, while preserving the existing valid-submit behavior.
🪄 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: 97309454-285f-433f-a753-6ec18195f641

📥 Commits

Reviewing files that changed from the base of the PR and between 692ddbf and c60c9db.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • apps/timo-web/api/todo/todo-schema.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/tag-modal/CreateTagModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-card/HomeDayHeaderContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/todo-modal/CreateTodoModalContent.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-view-mode.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_mocks/home-view-mock.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_mocks/todo-mock.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_utils/date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/statistics/_components/StatisticsCalendar.tsx
  • apps/timo-web/app/[locale]/(main)/statistics/_utils/statistics-calendar.ts
  • apps/timo-web/components/modal/OverlayModal.tsx
  • apps/timo-web/package.json
  • apps/timo-web/utils/date.ts
  • apps/timo-web/utils/format-date.ts
  • packages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.tsx
  • packages/timo-design-system/src/components/index.ts
  • packages/timo-design-system/src/components/tag/tag-name-input/TagNameInput.stories.tsx
  • packages/timo-design-system/src/components/tag/tag-name-input/TagNameInput.tsx
💤 Files with no reviewable changes (2)
  • apps/timo-web/utils/format-date.ts
  • apps/timo-web/app/[locale]/(main)/statistics/_utils/statistics-calendar.ts

Comment thread apps/timo-web/components/modal/OverlayModal.tsx
- clickOutsideDeactivates: false가 트랩 바깥 클릭을 preventDefault/stopImmediatePropagation으로 완전히 삼켜 배경 클릭 onClose가 호출되지 않던 문제를 true로 바꿔 수정했습니다
- ariaLabel을 선택 prop에서 필수 prop으로 바꿔 모든 다이얼로그가 접근 가능한 이름을 갖도록 강제했습니다
- CreateTodoModalContent/CreateTagModalContainer 모두 이미 화면에 보이는 타이틀 텍스트를 ariaLabel로 전달하도록 했습니다

@jjangminii jjangminii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

복잡한 로직이라 구현하기 힘들었을텐데 고생하셨습니다-!
코멘트 간단하게 한번만 확인해주세요~

active={shouldRender}
focusTrapOptions={{
escapeDeactivates: false,
clickOutsideDeactivates: true,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clickOutsideDeactivates 대신 allowOutsideClick은 어떨까요?
clickOutsideDeactivates: true는 "바깥 클릭 시 트랩만 해제"라서, 백드롭이 아닌 바깥 요소를 클릭하면 모달은 열려 있는데 포커스 트랩만 풀리는 상태가 될 수 있을 것 같아요. 이 상태에서 Tab을 누르면 모달 뒤 요소로 포커스가 빠져나가서 aria-modal과 실제 동작이 어긋나게 돼요.

tsxfocusTrapOptions={{
  escapeDeactivates: false,
  clickOutsideDeactivates: false,
  allowOutsideClick: true, // 바깥 클릭 이벤트를 차단하지 않고 통과
  fallbackFocus: () => dialogRef.current ?? document.body,
}}

allowOutsideClick: true를 쓰면 백드롭 onClick -> onClose -> 언마운트 흐름으로 트랩이 함께 정리돼서, 트랩 해제 시점이 항상 모달 언마운트에 묶이게 되는데 어떻게 생각하시나요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋습니다! 해당 속성으로 변경해서 반영해 두었어요. 언마운트 흐름에서만 트랩이 해제되게 변경하는 게 좋을 것 같아요!


onSubmit(data, { id: data.tagId ?? tag.id, name: tag.name });

reset(createDefaultValues());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 제출 직후 모달이 닫혀서 티가 안 나지만, 인자가 없으면 날짜가 오늘로 리셋돼요. 예를 들어 7월 20일 컬럼에서 모달을 열었는데 리셋 후에는 오늘 날짜가 되는 거죠. 나중에 "연속 추가" 같은 UX가 들어오면 바로 버그로 드러날 수 있어서 미리 맞춰두면 좋을 것 같아요-!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇네요. defaultValues 로 변경해 두었어요!

</p>
<button
type="button"
aria-label={t("createModal.close")}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 문자열이 같아서 문제없지만, 태그 모달이 투두 모달 키에 의존하는 구조라 나중에 createModal.close를 수정/삭제할 때 태그 모달까지 확인할 생각을 못 하게 될 것 같아요. "닫기"는 앞으로 모든 모달에서 쓸 테니 Common.close로 빼두면 어떨까요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체 json 파일에 추가해서 반영해 두겠습니돵

Comment on lines +23 to +24
subtasks: (data.subtasks ?? []).map((content) => ({
subtaskId: Date.now(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
subtasks: (data.subtasks ?? []).map((content) => ({
subtaskId: Date.now(),
.map((content, index) => ({
subtaskId: Date.now() + index,

지금은 handleSubtaskInputChange가 배열에 최대 1개만 넣어서 잠재적 이슈지만, 코드 형태는 "여러 개를 처리하는 map"이라 나중에 subtask 다중 입력이 붙을 때 이 로직을 그대로 재사용하면 handleToggleSubtaskCompleted 같은 ID 기반 로직이 꼬일 수 있을 것 같아요-! Date.now() + index로만 바꿔도 방어가 될 수 있을 것 같은데 어떻게 생각하세요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미리 변경해 두는 게 좋을 것 같네요. 반영했습니댱!

@ehye1 ehye1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zod로 schema 하나에 타입이랑 검증을 같이 관리할 수 있어서 좋네요!!
동적으로 모달을 열 수 있게 하는 overlay-kit 라이브러리도 처음 알게됐어요
수고하셨습니다!!👍🏻👍🏻

kimminna added 3 commits July 12, 2026 15:29
- clickOutsideDeactivates를 false로, allowOutsideClick을 true로 변경해 트랩 해제가 onClose/언마운트 흐름에만 종속되도록 수정했습니다
- 제출 후 reset 시 defaultDate를 전달하지 않아 날짜가 오늘로 초기화되던 버그를 수정했습니다
- 닫기 버튼 aria-label을 Common.close 키로 통합하고 기존 Home.createModal.close는 제거했습니다
- subtaskId 생성에 index를 더해 다중 subtask 입력 시 Date.now() 충돌 가능성을 방지했습니다
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능(기능성) 구현 ⌚ Timo-Design-system Timo 디자인 시스템 ⏰ Timo-web Timo 웹 서비스 ♦️ 민아 민아상

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 투두 생성 모달 및 홈 투두 카드 UI 구현

3 participants