[feat] 달력 UI 변경#167
Hidden character warning
Conversation
Walkthrough월간 모달 기반 UI를 제거하고 URL searchParams로 연/월 상태를 관리하도록 변경했습니다. 월별 선택을 숨긴 input + 버튼으로 대체하고, 월간 그리드에서 주간 그리드(CalendarWeekRow) 기반 렌더링으로 전환하며 하단 시트와 일정 상세 자동 스크롤, 날짜 파싱 유틸(parseDateDot)을 추가했습니다. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
src/components/layout/Header/components/ScheduleHeader.tsx (2)
37-43: Hidden input 접근성 고려
opacity-0과pointer-events-none으로 숨긴 input은 스크린 리더에서 여전히 접근 가능합니다. 의도적이라면 괜찮지만, 완전히 숨기려면aria-hidden="true"또는tabIndex={-1}추가를 고려해보세요.♻️ 접근성 개선 예시
<input ref={inputRef} type="month" value={`${year}-${String(month).padStart(2, '0')}`} onChange={handleMonthChange} - className="pointer-events-none absolute inset-0 opacity-0" + className="pointer-events-none absolute inset-0 opacity-0" + tabIndex={-1} + aria-hidden="true" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/Header/components/ScheduleHeader.tsx` around lines 37 - 43, The hidden month input in ScheduleHeader (the input using inputRef with value derived from year/month and onChange handler handleMonthChange) is visually hidden via CSS but remains reachable by screen readers; update the input to be truly hidden from assistive tech by adding either aria-hidden="true" or tabIndex={-1} (or both) depending on whether you still need it focusable, and document the intent in a short comment near the input so future readers know why it’s excluded from accessibility tree.
44-47: Typography token 사용 고려가이드라인에서 semantic typography utilities(
text-h1,text-body1등)를 우선 사용하도록 권장하고 있습니다.font-bold대신 적절한 typography token 사용을 검토해보세요.♻️ Typography token 적용 예시
- <button type="button" onClick={openMonthPicker} className="flex items-center gap-1 font-bold"> + <button type="button" onClick={openMonthPicker} className="flex items-center gap-1 text-h5">(실제 디자인 시스템에 맞는 token으로 대체)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/Header/components/ScheduleHeader.tsx` around lines 44 - 47, Replace the utility class "font-bold" on the button (the element that calls openMonthPicker and renders year/month with ChevronDownIcon) with the appropriate semantic typography token from our design system (e.g., text-body1 or text-h1 depending on intended prominence); locate the button in ScheduleHeader (the one with onClick={openMonthPicker}) and swap the raw font-weight utility for the correct semantic token so typography is consistent with the guideline.src/pages/Schedule/components/CalendarWeekRow.tsx (1)
4-4: 새 파일 import도@/*alias로 통일해주세요.이 경로가 계속 상대 경로로 남으면 동일 레이어 컴포넌트들에서 import 규칙이 쉽게 깨집니다.
As per coding guidelines, "Use path alias
@/*for imports instead of relative paths".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/CalendarWeekRow.tsx` at line 4, The import in CalendarWeekRow.tsx currently pulls DateBox via a relative path; replace that relative import with the project path-alias form using the `@/`* alias (i.e. import DateBox from '@/...') so imports are consistent across the layer and follow the coding guideline; update the import statement that references the DateBox symbol accordingly.src/pages/Schedule/index.tsx (1)
4-4: 새 import는@/*alias로 맞춰주세요.추가된
CalendarWeekRowimport만 상대 경로라서 이 파일의 import 규칙이 다시 섞입니다.As per coding guidelines, "Use path alias
@/*for imports instead of relative paths".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/index.tsx` at line 4, Replace the relative import of CalendarWeekRow with the project path-alias form using the `@/*` alias so imports remain consistent; locate the import statement for CalendarWeekRow in the Schedule page (symbol: CalendarWeekRow in index.tsx) and change it from a relative path to the equivalent `@/...` alias import that matches your project's alias convention.src/pages/Schedule/components/DateBox.tsx (1)
18-27: 조건부 스타일은cn()과 토큰으로 정리해주세요.
join(' '),text-[12px],bg-[#1B2B4B]가 같이 들어오면서 이 컴포넌트만 Tailwind 병합 규칙과 디자인 토큰 규칙에서 벗어났습니다.cn()으로 조합하고 날짜 텍스트/선택 상태는 semantic typography/color token으로 맞추는 편이 유지보수에 좋습니다.As per coding guidelines, "Use
cn()utility fromsrc/utils/ts/cn.tsto merge Tailwind CSS classes", "Prioritize color tokens fromsrc/styles/theme.css(indigo-, blue-, background, primary, etc.)", and "Use typography tokens (text-h1throughtext-h5,text-sub1throughtext-sub4,text-body1throughtext-body3,text-cap1throughtext-cap2) fromsrc/styles/theme.css".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/DateBox.tsx` around lines 18 - 27, Refactor the className assembly in the DateBox component to use the cn() utility instead of manual join(' '), replace raw utility tokens like text-[12px] and bg-[`#1B2B4B`] with the appropriate typography and color tokens from theme.css (e.g., a suitable text-cap or text-body token for the date text and a semantic background/primary token for selected state), and keep conditional logic using the existing props isCurrentMonth, isSelected, and isSunday so the expression reads like: cn(baseTypographyToken, conditionalTokensFor(!isCurrentMonth, isSelected, isSunday)). Ensure you import cn from src/utils/ts/cn.ts and use the theme token class names (typography and color) instead of inline values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/pages/Schedule/components/ScheduleDetail.tsx`:
- Around line 39-45: The auto-scroll useEffect only depends on day, so it won't
re-run when the async schedule data arrives and the first highlighted ref
becomes available; update the effect to also depend on the first-highlight
change (e.g., include the firstHighlightedIndex value returned from
useScheduleList or include firstHighlightedRef.current) and keep the existing
guard checks (if (!firstHighlightedRef.current || !containerRef.current) return)
so the effect runs again when the highlighted item is set; locate the useEffect
in ScheduleDetail, add the new dependency (firstHighlightedIndex or
firstHighlightedRef.current) to the dependency array, and ensure the scroll
logic remains unchanged.
In `@src/pages/Schedule/index.tsx`:
- Around line 87-130: The page root currently uses a hardcoded container and
100vh-based calc (the outer <div> with class "h-[calc(100vh-44px)]" and the
bottom sheet style using PEEK_HEIGHT and translateY) which bypasses app Layout
conventions; instead wrap this page's root content in the app Layout component
and pass the Layout props showBottomNav and contentClassName from this page,
remove hard 100vh math and use the CSS viewport/safe-area vars (e.g.
--viewport-height and safe-area insets) for height calculations for the main
container and the bottom sheet transform (keep references to isSheetExpanded and
PEEK_HEIGHT for sheet behavior), so the page respects the common Layout contract
and mobile/webview safe-area adjustments.
- Around line 134-139: Replace the non-interactive div used as the bottom-sheet
handle with a real button element (keeping the same className styling) so
keyboard and mouse users can toggle the sheet; wire the existing handlers
(handleSheetTouchStart, handleSheetTouchEnd) into the new button plus an onClick
handler that toggles the sheet open/closed and keyboard handlers (e.g.,
onKeyDown for Enter/Space) so the sheet can expand past PEEK_HEIGHT; add ARIA
attributes aria-expanded and aria-controls (pointing to the sheet content id)
and type="button" to prevent form submission, and ensure any visual styles
preserved (e.g., remove default outline only via focus-visible-friendly styles)
so accessibility and behavior work across touch, mouse, and keyboard.
---
Nitpick comments:
In `@src/components/layout/Header/components/ScheduleHeader.tsx`:
- Around line 37-43: The hidden month input in ScheduleHeader (the input using
inputRef with value derived from year/month and onChange handler
handleMonthChange) is visually hidden via CSS but remains reachable by screen
readers; update the input to be truly hidden from assistive tech by adding
either aria-hidden="true" or tabIndex={-1} (or both) depending on whether you
still need it focusable, and document the intent in a short comment near the
input so future readers know why it’s excluded from accessibility tree.
- Around line 44-47: Replace the utility class "font-bold" on the button (the
element that calls openMonthPicker and renders year/month with ChevronDownIcon)
with the appropriate semantic typography token from our design system (e.g.,
text-body1 or text-h1 depending on intended prominence); locate the button in
ScheduleHeader (the one with onClick={openMonthPicker}) and swap the raw
font-weight utility for the correct semantic token so typography is consistent
with the guideline.
In `@src/pages/Schedule/components/CalendarWeekRow.tsx`:
- Line 4: The import in CalendarWeekRow.tsx currently pulls DateBox via a
relative path; replace that relative import with the project path-alias form
using the `@/`* alias (i.e. import DateBox from '@/...') so imports are consistent
across the layer and follow the coding guideline; update the import statement
that references the DateBox symbol accordingly.
In `@src/pages/Schedule/components/DateBox.tsx`:
- Around line 18-27: Refactor the className assembly in the DateBox component to
use the cn() utility instead of manual join(' '), replace raw utility tokens
like text-[12px] and bg-[`#1B2B4B`] with the appropriate typography and color
tokens from theme.css (e.g., a suitable text-cap or text-body token for the date
text and a semantic background/primary token for selected state), and keep
conditional logic using the existing props isCurrentMonth, isSelected, and
isSunday so the expression reads like: cn(baseTypographyToken,
conditionalTokensFor(!isCurrentMonth, isSelected, isSunday)). Ensure you import
cn from src/utils/ts/cn.ts and use the theme token class names (typography and
color) instead of inline values.
In `@src/pages/Schedule/index.tsx`:
- Line 4: Replace the relative import of CalendarWeekRow with the project
path-alias form using the `@/*` alias so imports remain consistent; locate the
import statement for CalendarWeekRow in the Schedule page (symbol:
CalendarWeekRow in index.tsx) and change it from a relative path to the
equivalent `@/...` alias import that matches your project's alias convention.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 907c0b2b-583e-469b-8206-be6302fe5046
📒 Files selected for processing (7)
src/components/layout/Header/components/ScheduleHeader.tsxsrc/pages/Schedule/components/CalendarWeekRow.tsxsrc/pages/Schedule/components/DateBox.tsxsrc/pages/Schedule/components/ScheduleDetail.tsxsrc/pages/Schedule/index.tsxsrc/utils/hooks/useSchedule.tssrc/utils/ts/date.ts
| <div className="relative flex h-[calc(100vh-44px)] flex-col overflow-hidden bg-white"> | ||
| <main | ||
| className="flex w-full shrink-0 touch-pan-y flex-col gap-6 bg-white" | ||
| className="flex w-full shrink-0 touch-pan-y flex-col bg-white pt-[23px]" | ||
| onTouchStart={handleTouchStart} | ||
| onTouchEnd={handleTouchEnd} | ||
| > | ||
| <header className="flex items-center justify-center"> | ||
| <MonthPicker year={year} month={month} setDate={setDate} /> | ||
| </header> | ||
|
|
||
| <ul className="grid grid-cols-7 justify-items-center px-6 text-indigo-600"> | ||
| {DAYS.map((day) => ( | ||
| <li key={day}>{day}</li> | ||
| <li key={day} className="text-[13px] leading-5"> | ||
| {day} | ||
| </li> | ||
| ))} | ||
| </ul> | ||
|
|
||
| <ul className="grid grid-cols-7 gap-x-1.5 gap-y-3 px-6"> | ||
| {dateList.map((date) => ( | ||
| <DateBox | ||
| key={date.toISOString()} | ||
| date={date} | ||
| isCurrentMonth={isCurrentMonth(date)} | ||
| isToday={isSelectedDay(date)} | ||
| isSunday={isSunday(date)} | ||
| onClick={handleDateClick} | ||
| schedules={getSchedulesForDate(date)} | ||
| <div className="flex flex-col px-6"> | ||
| {weeks.map((weekDates) => ( | ||
| <CalendarWeekRow | ||
| key={weekDates[0].toISOString()} | ||
| dates={weekDates} | ||
| schedules={schedules} | ||
| isCurrentMonth={isCurrentMonth} | ||
| isSelectedDay={isSelectedDay} | ||
| isSunday={isSunday} | ||
| onDateClick={handleDateClick} | ||
| /> | ||
| ))} | ||
| </ul> | ||
| </div> | ||
| </main> | ||
|
|
||
| <section className="flex-1 overflow-y-auto"> | ||
| <ScheduleDetail year={year} month={month} day={day} /> | ||
| <ul className="text-cap2 flex shrink-0 gap-3 overflow-x-auto px-6 py-3 font-medium text-[#4B5563]"> | ||
| {COLOR_LEGENDS.map(({ name, color }) => ( | ||
| <li key={name} className="flex shrink-0 items-center gap-1"> | ||
| <span className="h-2.5 w-2.5 rounded-full" style={{ backgroundColor: color }} /> | ||
| {name} | ||
| </li> | ||
| ))} | ||
| </ul> | ||
|
|
||
| {/* 바텀시트 */} | ||
| <section | ||
| className="absolute inset-x-0 bottom-0 z-10 flex flex-col rounded-t-3xl bg-white shadow-[0_-4px_12px_rgba(0,0,0,0.06)] transition-transform duration-300 ease-out" | ||
| style={{ | ||
| height: `calc(100% - 200px)`, | ||
| transform: isSheetExpanded ? 'translateY(0)' : `translateY(calc(100% - ${PEEK_HEIGHT}px))`, |
There was a problem hiding this comment.
페이지 루트는 Layout/viewport 계약을 타는 게 안전합니다.
지금처럼 <div> + 100vh/고정 오프셋으로 높이를 직접 계산하면 공통 showBottomNav/contentClassName, safe-area, webview viewport 보정을 우회하게 됩니다. 바텀시트가 모바일 웹뷰에서 잘리거나 겹칠 가능성이 큽니다.
As per coding guidelines, "Pass showBottomNav (bottom tab display) and contentClassName (background color, etc.) props to Layout component" and "Maintain mobile webview responsive design with --viewport-height and safe area variables".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/pages/Schedule/index.tsx` around lines 87 - 130, The page root currently
uses a hardcoded container and 100vh-based calc (the outer <div> with class
"h-[calc(100vh-44px)]" and the bottom sheet style using PEEK_HEIGHT and
translateY) which bypasses app Layout conventions; instead wrap this page's root
content in the app Layout component and pass the Layout props showBottomNav and
contentClassName from this page, remove hard 100vh math and use the CSS
viewport/safe-area vars (e.g. --viewport-height and safe-area insets) for height
calculations for the main container and the bottom sheet transform (keep
references to isSheetExpanded and PEEK_HEIGHT for sheet behavior), so the page
respects the common Layout contract and mobile/webview safe-area adjustments.
| <div | ||
| className="flex shrink-0 justify-center pt-3 pb-2" | ||
| onTouchStart={handleSheetTouchStart} | ||
| onTouchEnd={handleSheetTouchEnd} | ||
| > | ||
| <div className="h-1 w-8 rounded-full bg-[#D1D5DB]" /> |
There was a problem hiding this comment.
바텀시트 핸들은 실제 버튼이어야 합니다.
지금은 터치 이벤트만 달린 div라서 마우스/키보드 환경에서는 확장/축소가 불가능합니다. 현재 구조상 상세 일정이 PEEK_HEIGHT 이상으로 열리지 않아 접근성이 막힙니다.
🔧 예시
- <div
- className="flex shrink-0 justify-center pt-3 pb-2"
- onTouchStart={handleSheetTouchStart}
- onTouchEnd={handleSheetTouchEnd}
- >
- <div className="h-1 w-8 rounded-full bg-[`#D1D5DB`]" />
- </div>
+ <button
+ type="button"
+ aria-expanded={isSheetExpanded}
+ className="flex shrink-0 justify-center pt-3 pb-2"
+ onClick={() => setIsSheetExpanded((prev) => !prev)}
+ onTouchStart={handleSheetTouchStart}
+ onTouchEnd={handleSheetTouchEnd}
+ >
+ <span className="h-1 w-8 rounded-full bg-[`#D1D5DB`]" />
+ </button>📝 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.
| <div | |
| className="flex shrink-0 justify-center pt-3 pb-2" | |
| onTouchStart={handleSheetTouchStart} | |
| onTouchEnd={handleSheetTouchEnd} | |
| > | |
| <div className="h-1 w-8 rounded-full bg-[#D1D5DB]" /> | |
| <button | |
| type="button" | |
| aria-expanded={isSheetExpanded} | |
| className="flex shrink-0 justify-center pt-3 pb-2" | |
| onClick={() => setIsSheetExpanded((prev) => !prev)} | |
| onTouchStart={handleSheetTouchStart} | |
| onTouchEnd={handleSheetTouchEnd} | |
| > | |
| <span className="h-1 w-8 rounded-full bg-[`#D1D5DB`]" /> | |
| </button> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/pages/Schedule/index.tsx` around lines 134 - 139, Replace the
non-interactive div used as the bottom-sheet handle with a real button element
(keeping the same className styling) so keyboard and mouse users can toggle the
sheet; wire the existing handlers (handleSheetTouchStart, handleSheetTouchEnd)
into the new button plus an onClick handler that toggles the sheet open/closed
and keyboard handlers (e.g., onKeyDown for Enter/Space) so the sheet can expand
past PEEK_HEIGHT; add ARIA attributes aria-expanded and aria-controls (pointing
to the sheet content id) and type="button" to prevent form submission, and
ensure any visual styles preserved (e.g., remove default outline only via
focus-visible-friendly styles) so accessibility and behavior work across touch,
mouse, and keyboard.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
src/pages/Schedule/components/ScheduleDetail.tsx (4)
7-7: 타입명 PascalCase 컨벤션TypeScript 타입명은 PascalCase를 사용하는 것이 관례입니다.
수정 제안
-type scheduleDetailProps = { +type ScheduleDetailProps = {Line 13도 함께 수정:
-function ScheduleDetail({ year, month, day }: scheduleDetailProps) { +function ScheduleDetail({ year, month, day }: ScheduleDetailProps) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/ScheduleDetail.tsx` at line 7, Rename the TypeScript type scheduleDetailProps to PascalCase (ScheduleDetailProps) and update every usage to the new name (including the props type annotation for the ScheduleDetail component and any other references in the file), ensuring exported/imported names are adjusted if this type is exported or used elsewhere; keep the same shape of the type while only changing its identifier to ScheduleDetailProps.
59-59: 조건부 클래스에cn()유틸리티 사용 권장코딩 가이드라인에 따라 Tailwind 클래스 병합 시
cn()유틸리티를 사용해야 합니다.수정 예시 (Line 59)
+import { cn } from '@/utils/ts/cn'; -className={`flex h-[70px] shrink-0 items-stretch self-stretch overflow-hidden rounded-lg border border-[`#F4F6F9`] bg-white transition-opacity ${!highlighted ? 'opacity-40' : ''}`} +className={cn( + 'flex h-[70px] shrink-0 items-stretch self-stretch overflow-hidden rounded-lg border border-[`#F4F6F9`] bg-white transition-opacity', + !highlighted && 'opacity-40' +)}Also applies to: 63-63, 66-66
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/ScheduleDetail.tsx` at line 59, Replace the inline template-string Tailwind class concatenations with the cn() utility in the ScheduleDetail component: for the element that currently uses className={`flex h-[70px] ... ${!highlighted ? 'opacity-40' : ''}`} switch to cn(...) and pass static classes plus a conditional object/array for the opacity class, and do the same for the other two occurrences in this component (the other className props around the same block). Ensure you import cn if not already and keep the exact class tokens but let cn handle merging/conditional inclusion.
49-49: 시맨틱 타이포그래피 토큰 사용 고려
text-[16px],text-[14px]등 커스텀 크기 대신theme.css의 타이포그래피 토큰(text-body1,text-body2등)을 우선 사용하면 일관성을 유지할 수 있습니다.Also applies to: 63-63, 66-66
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/ScheduleDetail.tsx` at line 49, In ScheduleDetail.tsx replace hard-coded utility classes like "text-[16px]" and "text-[14px]" on the span elements in the ScheduleDetail component with the semantic typography tokens defined in theme.css (e.g., "text-body1", "text-body2" or the project's equivalent) to ensure consistent typography; update each span that currently uses "text-[16px]" / "text-[14px]" (and nearby spans that use similar custom sizes) to the appropriate semantic class and remove the custom bracketed size classes.
26-34:isOnSelectedDay및firstHighlightedIndex메모이제이션 고려
isOnSelectedDay가 매 렌더마다 새로 생성되고,map내에서 반복 호출됩니다.firstHighlightedIndex와 함께useMemo로 감싸면 불필요한 재계산을 줄일 수 있습니다.예시
const { firstHighlightedIndex, isOnSelectedDay } = useMemo(() => { const isOnDay = (startedAt: string, endedAt: string) => { const start = parseDateDot(startedAt); const end = parseDateDot(endedAt); return start <= selectedDate && selectedDate <= end; }; const idx = sortedSchedules.findIndex(({ startedAt, endedAt }) => isOnDay(startedAt, endedAt)); return { firstHighlightedIndex: idx, isOnSelectedDay: isOnDay }; }, [sortedSchedules, selectedDate]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Schedule/components/ScheduleDetail.tsx` around lines 26 - 34, Wrap the creation of isOnSelectedDay and the computation of firstHighlightedIndex in a useMemo to avoid recreating the function and re-scanning sortedSchedules on every render: create an inner function (e.g., isOnDay) that uses parseDateDot and selectedDate, compute idx = sortedSchedules.findIndex(...) inside the same useMemo, and return both { firstHighlightedIndex: idx, isOnSelectedDay: isOnDay }; use dependencies [sortedSchedules, selectedDate] so callers of isOnSelectedDay and the firstHighlightedIndex value use the memoized versions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/pages/Schedule/components/ScheduleDetail.tsx`:
- Line 5: Replace the relative import in ScheduleDetail.tsx with the path-alias
version: change the import of useScheduleList from '../hooks/useGetSchedules' to
the project alias form (e.g. '@/pages/Schedule/hooks/useGetSchedules') so it
uses the `@/`* alias; update the import statement referencing the useScheduleList
symbol accordingly and ensure any ESLint/TS path mappings remain valid.
---
Nitpick comments:
In `@src/pages/Schedule/components/ScheduleDetail.tsx`:
- Line 7: Rename the TypeScript type scheduleDetailProps to PascalCase
(ScheduleDetailProps) and update every usage to the new name (including the
props type annotation for the ScheduleDetail component and any other references
in the file), ensuring exported/imported names are adjusted if this type is
exported or used elsewhere; keep the same shape of the type while only changing
its identifier to ScheduleDetailProps.
- Line 59: Replace the inline template-string Tailwind class concatenations with
the cn() utility in the ScheduleDetail component: for the element that currently
uses className={`flex h-[70px] ... ${!highlighted ? 'opacity-40' : ''}`} switch
to cn(...) and pass static classes plus a conditional object/array for the
opacity class, and do the same for the other two occurrences in this component
(the other className props around the same block). Ensure you import cn if not
already and keep the exact class tokens but let cn handle merging/conditional
inclusion.
- Line 49: In ScheduleDetail.tsx replace hard-coded utility classes like
"text-[16px]" and "text-[14px]" on the span elements in the ScheduleDetail
component with the semantic typography tokens defined in theme.css (e.g.,
"text-body1", "text-body2" or the project's equivalent) to ensure consistent
typography; update each span that currently uses "text-[16px]" / "text-[14px]"
(and nearby spans that use similar custom sizes) to the appropriate semantic
class and remove the custom bracketed size classes.
- Around line 26-34: Wrap the creation of isOnSelectedDay and the computation of
firstHighlightedIndex in a useMemo to avoid recreating the function and
re-scanning sortedSchedules on every render: create an inner function (e.g.,
isOnDay) that uses parseDateDot and selectedDate, compute idx =
sortedSchedules.findIndex(...) inside the same useMemo, and return both {
firstHighlightedIndex: idx, isOnSelectedDay: isOnDay }; use dependencies
[sortedSchedules, selectedDate] so callers of isOnSelectedDay and the
firstHighlightedIndex value use the memoized versions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: de39b110-bdf0-4bde-b978-95bdc3967ea0
📒 Files selected for processing (1)
src/pages/Schedule/components/ScheduleDetail.tsx
| import { SCHEDULE_COLOR } from '@/constants/schedule'; | ||
| import { formatScheduleTime } from '@/utils/hooks/useFormatTime'; | ||
| import { parseDateDot } from '@/utils/ts/date'; | ||
| import { useScheduleList } from '../hooks/useGetSchedules'; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
상대 경로 대신 @/* 별칭 사용 필요
코딩 가이드라인에 따라 상대 경로 대신 path alias를 사용해야 합니다.
수정 제안
-import { useScheduleList } from '../hooks/useGetSchedules';
+import { useScheduleList } from '@/pages/Schedule/hooks/useGetSchedules';📝 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.
| import { useScheduleList } from '../hooks/useGetSchedules'; | |
| import { useScheduleList } from '@/pages/Schedule/hooks/useGetSchedules'; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/pages/Schedule/components/ScheduleDetail.tsx` at line 5, Replace the
relative import in ScheduleDetail.tsx with the path-alias version: change the
import of useScheduleList from '../hooks/useGetSchedules' to the project alias
form (e.g. '@/pages/Schedule/hooks/useGetSchedules') so it uses the `@/`* alias;
update the import statement referencing the useScheduleList symbol accordingly
and ensure any ESLint/TS path mappings remain valid.
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항