[REFACTOR] 투두 생성/수정 모달 시간·태그·아이콘 UI 개선 및 버그 수정 - #189
Conversation
- Enter 키다운 이벤트가 한글 조합(IME composing) 중에 발생하면 무시하도록 처리했습니다
- 기본 태그 4종(일상/업무/운동/과제)을 tagId로 매핑해 next-intl로 번역하도록 했습니다 - 홈 목록, 설정 태그 목록, 생성 모달 태그 드롭다운에 동일하게 적용했습니다
- IconGraphic 아이콘 크기를 18px에서 24px로 키워 버튼 영역에 꽉 차게 했습니다
- duration 문자열을 분:초(mm:ss)로 일관되게 해석·변환하도록 수정했습니다 - 트리거에 보여주는 시:분 표기를 분·초 전체 길이 기준으로 계산하도록 했습니다 - 생성/상세 모달의 60분·90분 옵션 라벨을 "1 h"/"1.5 h"에서 "60 min"/"90 min"으로 통일했습니다
- 시간 선택기의 직접 입력을 분/초 두 칸으로 분리하고 초 값을 0~59로 제한했습니다 - Dropdown.Trigger가 열림 상태를 자식에게 전달하도록 render-prop을 지원하게 했습니다 - 툴바 트리거(날짜/시간/태그/반복)의 닫힘·설정됨·열림 상태에 따라 아이콘과 텍스트 색상을 구분했습니다 - 반복 선택기에서 매일을 선택하면 상세 설정 단계로 넘어가지 않고 바로 닫히도록 했습니다
- 날짜 라벨을 상세 모달과 동일한 yy.MM.dd 형식으로 표시하도록 했습니다 - 시간 트리거의 활성 상태를 실제 값 존재 여부가 아닌 사용자 입력 여부(dirtyFields)로 판단하도록 했습니다
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough투두 모달의 시간 입력·변환, 기본 태그 번역, 드롭다운 트리거 상태 표시, 날짜 포맷, IME 입력 처리를 변경했습니다. 디자인 시스템의 선택기 트리거 타입과 시간 입력 UI도 확장했습니다. Changes투두 모달 UI 및 공통 디자인 시스템
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant TimeSelector
participant UseTimeField
participant APIFormat
User->>TimeSelector: 분·초 입력 또는 시간 선택
TimeSelector->>UseTimeField: 변경된 시간 전달
UseTimeField->>APIFormat: 초 단위 duration 변환
APIFormat-->>UseTimeField: API duration 반환
UseTimeField-->>TimeSelector: h:mm 표시값 갱신
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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: 3
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)/today/_utils/todo-time.ts (1)
4-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win중복된 유틸리티 함수 제거 및 공용 패키지 사용
시간 변환 유틸리티를 공용 폴더로 잘 분리해 주셨네요! 👍
다만 한 가지 아쉬운 점은 이 파일이 도메인(today) 폴더에 여전히 남아 있어 코드 중복이 발생했다는 점입니다."공유 로직은 반드시
lib/또는packages/로 추출"해야 한다는 아키텍처 규칙에 따라, 도메인에 종속된 이 파일을 완전히 삭제하시고 필요한 곳에서는 이미 만들어두신apps/timo-web/utils/todo/todo-time.ts의 공용 유틸리티를 import 하여 사용하도록 정리해 주시는 것을 권장합니다.🤖 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)/today/_utils/todo-time.ts around lines 4 - 13, Remove the domain-local convertApiDurationToSeconds utility from the today time helper, and update its consumers to import and use the existing shared utility from apps/timo-web/utils/todo/todo-time.ts instead. Ensure no duplicate implementation or references to the deleted local helper remain.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/hooks/todo-modal/use-detail-todo-form.ts`:
- Line 69: Update the todo detail form’s `defaultValues.time` initialization to
use `convertSecondsToApiDuration(todo.durationSeconds)` instead of
`convertDurationToTimeText`, keeping the initial value in the API’s `mm:ss`
format and consistent with the save payload.
In
`@packages/timo-design-system/src/components/time/time-selector/TimeSelector.tsx`:
- Around line 28-38: Update the TimeSelector input flow around
sanitizeTimeSegment, sanitizeSecondsSegment, and onTimeChange to maintain local,
uncommitted minute/second text while the user edits. Do not propagate empty or
one-digit segments to duration; on blur or explicit confirmation, normalize both
segments to two digits, preserve seconds clamping, and then call onTimeChange
with the complete mm:ss value.
In
`@packages/timo-design-system/src/components/todo/todo-toolbar/TodoToolbar.tsx`:
- Around line 164-166: Update the TodoToolbar trigger’s TagIcon variant logic so
a selected tag is not rendered with the disabled variant when the menu is
closed: keep the open state blue, use the default variant when selectedTag is
configured, and reserve "disable" for the unconfigured state.
---
Outside diff comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_utils/todo-time.ts:
- Around line 4-13: Remove the domain-local convertApiDurationToSeconds utility
from the today time helper, and update its consumers to import and use the
existing shared utility from apps/timo-web/utils/todo/todo-time.ts instead.
Ensure no duplicate implementation or references to the deleted local helper
remain.
🪄 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: 902ec25c-7e9e-4b86-8db4-3b53a2229c16
📒 Files selected for processing (18)
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsxapps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_utils/todo-time.tsapps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.tsapps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsxapps/timo-web/hooks/todo-modal/use-detail-subtask-field.tsapps/timo-web/hooks/todo-modal/use-detail-todo-form.tsapps/timo-web/hooks/todo-modal/use-subtask-field.tsapps/timo-web/hooks/todo-modal/use-tag-field.tsxapps/timo-web/hooks/todo-modal/use-time-field.tsapps/timo-web/utils/todo/tag-label.tsapps/timo-web/utils/todo/todo-time.tspackages/timo-design-system/src/components/calendar/date-selector/DateSelector.tsxpackages/timo-design-system/src/components/icon/icon-graphic/IconGraphic.tsxpackages/timo-design-system/src/components/layout/dropdown/Dropdown.tsxpackages/timo-design-system/src/components/repeat/repeat-selector/RepeatSelector.tsxpackages/timo-design-system/src/components/tag/tag-selector/TagSelector.tsxpackages/timo-design-system/src/components/time/time-selector/TimeSelector.tsxpackages/timo-design-system/src/components/todo/todo-toolbar/TodoToolbar.tsx

ISSUE 🔗
close #188
What is this PR? 🔍
투두 생성/수정 모달의 시간 선택, 태그 다국어 처리, 아이콘 크기, 하위 할일 입력, 툴바 트리거 색상 상태를 정리했습니다.
배경
하위 할일 입력
keydown이 조합 완료 전에 발생해, 조합이 끝나며 커밋되는 글자가 이미 포커스가 이동한 다음 입력칸에 남았습니다.handleInputKeyDown의 Enter 분기 맨 앞에event.nativeEvent.isComposing체크를 추가해 조합 중이면 그대로 반환하도록 했습니다.태그 다국어 처리
tag.name문자열을 그대로 표시해 로케일을 바꿔도 번역되지 않았습니다. 홈 목록·설정 화면은 이미 tagId 기반 매핑을 쓰고 있었지만 생성 모달만 빠져 있었습니다.getDefaultTagLabelKey(tagId)가 tagId 1~4를 알려진 라벨 키로 매핑하면tCommon(\tag.${key}`)로 번역하고, 그 외(사용자 정의 태그)는 원본 이름을 그대로 씁니다. 생성 모달의use-tag-field.tsx`에도 동일 로직을 적용해 세 곳(홈/설정/생성)이 같은 매핑을 공유합니다.아이콘 셀렉터 크기
size-6)인데 내부 아이콘은 18px(size-4.5)로 렌더링되어 버튼 안에 여백이 남았습니다.IconGraphic의 className을size-4.5에서size-6으로 변경해 버튼 크기와 맞췄습니다.시간(duration) 필드 정합성
duration문자열의 단위를 분:초(mm:ss)로 통일하고, 관련 변환 함수를 정리했습니다.DURATION_PATTERN(\d{1,3}:[0-5]\d)은 분이 60을 넘을 수 있는 분:초 형식을 전제로 하는데, 일부 훅은 이를 시:분(hh:mm)으로 해석해 15분을 "15:00"(15시간)으로 보내거나 반대로 분:초를 시:분으로 잘못 역산하는 문제가 있었습니다. 분(minute) 입력값이 60 이상이어도 검증되지 않아 잘못된 duration이 만들어지면react-hook-form검증이 조용히 실패해 생성 버튼이 무반응으로 보이는 버그로도 이어졌습니다.convertSecondsToApiDuration/convertApiDurationToSeconds(분:초 기준)로 실제 제출 값을 계산하고, 트리거에 보여줄 시:분 표기는formatDurationAsClockLabel로 별도 파생해 실제 값과 분리했습니다. 초 입력값은 0~59로 클램프해 무효한 duration이 만들어지지 않도록 했습니다.시간 선택 UI 및 툴바 트리거 상태
Dropdown.Trigger가 열림 상태를 자식에게 넘기는 render-prop(trigger={(isOpen) => ...})을 지원하도록 확장했습니다. 툴바는 닫힘+미설정=gray-700, 닫힘+설정됨=gray-900, 열림=blue-300으로 아이콘·텍스트 색을 정리했습니다.RepeatSelector는 DAILY 선택 시에만closeOnSelect를 true로 주고 상세 단계 전환을 건너뜁니다.생성 모달 날짜 표시
formState.dirtyFields(사용자가 실제로 값을 바꿨는지)로 판단하도록 했습니다.M.d형식을 따로 쓰고 있어 상세 모달과 표시가 달랐습니다. 또한 AI 추천이 드롭다운을 열자마자 자동으로 duration을 채우기 때문에, 값 존재 여부만으로 활성 상태를 판단하면 사용자가 아무것도 하지 않아도 활성 색으로 보였습니다.formatShortDateLabel을 재사용했습니다. 시간은formState.dirtyFields.duration을isTimeActive로 넘겨, 실제 폼 값이 기본값에서 바뀐 경우에만 활성 색이 켜지도록 했습니다. 날짜는 생성 모달 특성상 기본값 자체가 항상 유효한 선택이라 값 존재 여부 기준을 그대로 유지했습니다.To Reviewers
use-time-field.ts의 AI 추천/퀵 선택/수동 입력 사이 상태 관리가 이번에 여러 번 조정되었습니다.recommendedDuration(AI 박스 표시용)과field.value(실제 제출 값)를 분리한 부분을 중점적으로 봐주세요.Dropdown.Trigger의 render-prop 지원은 하위 호환(기존처럼 일반ReactNode를 넘기는 방식)을 유지하도록 했습니다.isRepeatActive)는 열림 상태와 별개로 유지했는데, 이 조합이 의도에 맞는지 확인 부탁드립니다.Screenshot 📷
Test Checklist ✔
pnpm --filter timo-web check-types통과pnpm --filter @repo/timo-design-system check-types통과pnpm --filter timo-web lint통과pnpm --filter @repo/timo-design-system lint통과pnpm build— 미실행: CI에서 확인 예정