Conversation
|
Warning Rate limit exceeded@skyblue1232 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 50 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
Walkthrough목적·숙박·이동 선택용 컴포넌트와 자유 입력 섹션, 선택 옵션 상수 및 상태 훅을 추가하고 페이지를 훅 기반으로 리팩터링해 모든 선택 완료 시 결과 페이지로 네비게이션하도록 흐름을 도입했습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User as 사용자
participant Page as CourseSettingPage
participant Hook as useCourseSelection
participant Select as CourseSelectSection
participant Input as CourseInputSection
participant Router as Router
User->>Page: 페이지 로드
Page->>Hook: 상태 획득 (purpose, stay, move)
User->>Select: 옵션 선택 (버튼 클릭)
Select->>Hook: setPurpose/setStay/setMove 호출
User->>Input: 텍스트 입력 후 Next 클릭
Input->>Page: onNext 호출
alt 모든 선택 완료
Page->>Router: push("/map/result")
else 선택 미완료
Page->>User: 완료 안내/비활성 상태 유지
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 분
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
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 |
|
🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message. |
|
🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (7)
src/shared/constants/course/courseOptions.ts (1)
1-17: 옵션 상수에 타입 안정성 부여(as const) + i18n 확장성 고려현재도 동작엔 문제 없지만, 리터럴 고정을 통해 교차 모듈에서 안전한 타입 추론이 가능합니다. 또한 label은 번역 키로 분리하면 i18n 확장에 유리합니다.
예시:
-export const purposes = [ +export const purposes = [ { id: 'date', label: '데이트' }, { id: 'family', label: '가족여행' }, { id: 'friends', label: '우정여행' }, -]; +] as const; -export const stays = [ +export const stays = [ { id: 'one', label: '당일치기' }, { id: 'two', label: '1박2일' }, { id: 'three', label: '2박3일' }, -]; +] as const; -export const moves = [ +export const moves = [ { id: 'walk', label: '도보' }, { id: 'transit', label: '대중교통' }, { id: 'car', label: '자가차' }, -]; +] as const; + +export type PurposeId = typeof purposes[number]['id']; +export type StayId = typeof stays[number]['id']; +export type MoveId = typeof moves[number]['id'];추가로, label을 나중에
t('course.purpose.date')같은 키로 교체할 여지를 남겨두면 좋습니다.src/shared/hooks/useCourseSelection.ts (1)
3-16: 옵션 ID를 유니온 타입으로 좁히기 + 파생 상태 제공 제안
string | null대신 옵션 상수에서 유추한 유니온 타입을 쓰면 오타를 컴파일 타임에 차단할 수 있습니다. 또한canProceed같은 파생 boolean을 훅에서 함께 반환하면 사용처 단순화에 도움이 됩니다.예시:
-import { useState } from 'react'; +import { useState } from 'react'; +import type { PurposeId, StayId, MoveId } from '@/shared/constants/course/courseOptions'; export function useCourseSelection() { - const [purpose, setPurpose] = useState<string | null>(null); - const [stay, setStay] = useState<string | null>(null); - const [move, setMove] = useState<string | null>(null); + const [purpose, setPurpose] = useState<PurposeId | null>(null); + const [stay, setStay] = useState<StayId | null>(null); + const [move, setMove] = useState<MoveId | null>(null); + const canProceed = Boolean(purpose && stay && move); return { purpose, setPurpose, stay, setStay, move, setMove, + canProceed, }; }src/pages/map/components/CourseSelectSection.tsx (1)
28-38: 수평 스크롤 + 중앙 정렬: 현재 로직 OK, 모멘텀 스크롤/스크롤바 CSS 범위만 보완
- 콘텐츠가 뷰포트보다 좁을 때
flex justify-center min-w-max로 버튼들이 중앙 정렬됩니다. 요구사항 충족합니다.- 다만 모멘텀 스크롤 속성(
WebkitOverflowScrolling: 'touch')은 스크롤되는 요소(overflow-x-auto)에게 적용해야 iOS에서 유효합니다.div::-webkit-scrollbar선택자는 컴포넌트 내 모든 div에 적용되어 과도합니다. 스크롤 컨테이너에만 한정하세요.아래처럼 class를 부여해 범위를 좁히고, 속성 위치를 옮기는 것을 권장합니다:
- <div - className="w-full overflow-x-auto" - style={{ - scrollbarWidth: 'none', - msOverflowStyle: 'none', - }} - > + <div + className="w-full overflow-x-auto no-scrollbar" + style={{ + scrollbarWidth: 'none', // Firefox + msOverflowStyle: 'none', // IE/Edge Legacy + WebkitOverflowScrolling: 'touch', // iOS momentum + }} + > <div - className="flex justify-center gap-[0.8rem] min-w-max" - style={{ WebkitOverflowScrolling: 'touch' }} + className="flex justify-center gap-[0.8rem] min-w-max" role="list" > @@ - <style jsx>{` - div::-webkit-scrollbar { - display: none; - } - `}</style> + <style jsx>{` + .no-scrollbar::-webkit-scrollbar { + display: none; + } + `}</style>Also applies to: 53-57
src/pages/map/components/CourseInputSection.tsx (2)
23-29: 입력 필드에 실제<label>연결로 접근성 강화 (aria-label 중복 제거)현재 섹션 제목
<p>+aria-label로 이름을 부여하고 있습니다. 입력 컨트롤에는 연결된<label htmlFor>이 가장 적합합니다.aria-label은 중복이므로 제거하세요.- <p - id={`${inputId}-label`} - className="text-body-lg text-gray-700" - > - {label} - </p> + <label + id={`${inputId}-label`} + htmlFor={inputId} + className="text-body-lg text-gray-700" + > + {label} + </label> @@ - <input + <input id={inputId} type="text" placeholder={placeholder} - aria-label={label} aria-describedby={`${inputId}-desc`} className=" w-full rounded-[2rem] py-[1.2rem] px-[1.7rem] text-body-md placeholder-gray-400 bg-gray-100 border-0 outline-none focus:ring-0 focus:outline-none " />Also applies to: 30-41
47-55: Enter 키로 진행 지원(선택 사항)텍스트 입력 후 Enter로도
onNext를 호출하면 조작성이 좋아집니다. (폼으로 감싸 submit 처리하는 방식이 최선)- <button + <button type="button" onClick={onNext} className="flex items-center justify-center" aria-label="다음 단계로 이동" >또는
<form onSubmit={...}>내부로 두고 버튼을type="submit"으로 전환하세요. (index.tsx 변경 필요)src/pages/map/index.tsx (2)
23-31: role="form" 대신 실제<form>사용 권장폼 영역에
role="form"을 부여하기보다 실제<form>으로 마크업하고onSubmit={handleNext}로 연결하면 키보드/스크린리더 흐름이 개선됩니다.예시(요약):
- <div + <form className={cn( 'relative px-[2.4rem] bg-white flex flex-col h-full pt-[1.3rem] pb-[12rem]' )} - role="form" + onSubmit={(e) => { e.preventDefault(); handleNext(); }} aria-labelledby="course-setting-title" aria-describedby="course-setting-desc" > @@ - </div> + </form>참고:
CourseInputSection의 진행 버튼은type="submit"으로 바꾸면 시맨틱이 맞춰집니다. (해당 컴포넌트 변경 필요)
39-42:aria-live="polite"적용 위치 조정
<main>전체를 라이브 영역으로 두면 예기치 않은 대규모 읽기가 발생할 수 있습니다. 상태 변화 메시지만 노출하는 작은 전용 라이브 영역을 두는 방식을 권합니다.- <main - className="w-full pt-[3.4rem] flex flex-col overflow-auto" - aria-live="polite" - > + <main className="w-full pt-[3.4rem] flex flex-col overflow-auto"> + <p id="live-status" className="sr-only" aria-live="polite" />선택지 미완료 시
alert대신 위 라이브 영역 텍스트를 갱신하는 것도 접근성 측면에서 더 나은 UX입니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
public/assets/bannerMap.svgis excluded by!**/*.svgsrc/shared/icons/source/NextButton.svgis excluded by!**/*.svgsrc/shared/icons/source/Stamp.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
src/pages/map/components/CourseInputSection.tsx(1 hunks)src/pages/map/components/CourseSelectSection.tsx(1 hunks)src/pages/map/index.tsx(1 hunks)src/shared/constants/course/courseOptions.ts(1 hunks)src/shared/hooks/useCourseSelection.ts(1 hunks)src/shared/icons/iconNames.ts(1 hunks)src/shared/icons/index.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/map/index.tsx (6)
src/shared/hooks/useCourseSelection.ts (1)
useCourseSelection(3-16)src/shared/lib/utils.ts (1)
cn(71-73)src/pages/map/components/CourseSelectSection.tsx (1)
CourseSelectSection(10-61)src/shared/constants/course/courseOptions.ts (3)
purposes(1-5)stays(7-11)moves(13-17)src/pages/map/components/CourseInputSection.tsx (1)
CourseInputSection(9-59)src/shared/components/tab/BottomNav.tsx (1)
BottomNav(21-54)
src/pages/map/components/CourseInputSection.tsx (1)
src/shared/icons/index.ts (1)
Icon(22-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
🔇 Additional comments (2)
src/shared/icons/index.ts (1)
16-16: 자동 생성 파일 변경 출처 확인 필요이 파일은 자동 생성 파일로 명시되어 있습니다. NextButton.svg 추가가 코드젠 결과인지 확인해 주세요. 수동 수정이면 이후 빌드/젠 과정에서 덮어씌워질 수 있습니다.
src/shared/icons/iconNames.ts (1)
16-16: 아이콘 이름 추가 방식 확인"NextButton" 추가가 아이콘 코드젠 파이프라인을 통해 반영된 것인지 확인해 주세요. 수동 변경은 재생성 시 소실 위험이 있습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/pages/map/index.tsx (1)
8-8: Pages Router에서next/router사용한 점 확인이전 피드백 반영됨. 런타임 이슈 소지 제거되었습니다. 굿.
🧹 Nitpick comments (8)
src/pages/map/components/CourseInputSection.tsx (4)
16-16: id 하드코딩 대신 ReactuseId사용다중 인스턴스/SSR에서 id 충돌을 막기 위해
useId로 대체를 권장합니다.-'use client'; + 'use client'; @@ -import { Icon } from '@/shared/icons'; +import { Icon } from '@/shared/icons'; +import { useId } from 'react'; @@ - const inputId = 'desired-place-input'; + const inputId = useId();Also applies to: 33-33
25-30: 시각 레이블은<label>로 연결하고aria-label중복 제거입력 필드는 연결된
<label>이 가장 확실합니다. 그룹 제목<p>대신<label htmlFor>사용 시aria-label은 불필요합니다.- <p - id={`${inputId}-label`} - className="text-body-lg text-gray-700" - > - {label} - </p> + <label + id={`${inputId}-label`} + htmlFor={inputId} + className="text-body-lg text-gray-700" + > + {label} + </label> @@ - aria-label={label}Also applies to: 36-36
20-24: role="group"는 선택 사항단일 입력만 포함되면 그룹 롤은 필수 아님. 유지해도 되지만 간소화 가능. Fieldset/legend로 실제 그룹핑할 때만 부여 추천.
49-57: 다음 버튼 비활성화/접근성 상태 반영진행 불가 시 비활성화 표시가 필요합니다.
disabled와aria-disabled를 지원하는 prop 추가를 권장합니다. 폼 전환 시type="submit"로도 동작하도록 확장하세요.interface CourseInputSectionProps { placeholder?: string; label?: string; onNext?: () => void; + disabled?: boolean; } @@ -export default function CourseInputSection({ +export default function CourseInputSection({ placeholder = '여기에 입력해 주세요...', label = '꼭 가고 싶은 곳을 적어 주세요 (선택)', onNext, + disabled = false, }: CourseInputSectionProps) { @@ - <button - type="button" - onClick={onNext} + <button + type="button" + onClick={disabled ? undefined : onNext} className="flex items-center justify-center" aria-label="다음 단계로 이동" + aria-disabled={disabled || undefined} + disabled={disabled} >폼으로 전환한다면 아래처럼
type="submit"을 사용하세요.- type="button" + type="submit"src/pages/map/index.tsx (4)
24-31: role="form" 대신 실제<form>사용폼 의미론이 필요하다면
<form onSubmit={...}>로 전환하는 것이 접근성/키보드 동작(Enter 제출) 모두에 이점이 있습니다.예시:
- <div - className={cn( - 'relative px-[2.4rem] bg-white flex flex-col h-full pt-[1.3rem] pb-[12rem]' - )} - role="form" - aria-labelledby="course-setting-title" - aria-describedby="course-setting-desc" - > + <form + className={cn( + 'relative px-[2.4rem] bg-white flex flex-col h-full pt-[1.3rem] pb-[12rem]' + )} + aria-labelledby="course-setting-title" + aria-describedby="course-setting-desc" + onSubmit={(e) => { + e.preventDefault(); + handleNext(); + }} + >그리고
</div>를</form>으로 변경.
39-42:aria-live="polite"는 불필요메인 영역이 동적으로 갱신되지 않으면 라이브 리전은 과잉입니다. 제거를 권장합니다. 오류 안내가 필요하면 별도 상태 메시지 영역에
role="status"/aria-live를 적용하세요.- <main - className="w-full pt-[3.4rem] flex flex-col overflow-auto" - aria-live="polite" - > + <main className="w-full pt-[3.4rem] flex flex-col overflow-auto">
16-21:alert대신 인라인 오류 메시지 + 라이브 리전
alert()는 접근성/UX 모두 거칩니다. 상태 메시지를 표시하고 라이브 리전으로 공지하세요. 버튼은 비활성화하는 편이 더 직관적입니다.간단 예시:
- const handleNext = () => { - if (!canProceed) return alert('모든 항목을 선택해주세요.'); + const handleNext = () => { + if (!canProceed) { + // TODO: 상태 메시지 setState로 표시하고 role="status" 영역에서 공지 + return; + } router.push('/map/result'); };그리고
CourseInputSection에disabled={!canProceed}전달을 권장합니다.- <CourseInputSection onNext={handleNext} /> + <CourseInputSection onNext={handleNext} disabled={!canProceed} />
65-85: 가로 스크롤 + 자동 센터링 로직 검토 결과: 개념은 적절함외부 컨테이너
overflow-x-auto, 내부 컨테이너min-w-max조합으로
- 내용 < 뷰포트: 가운데 정렬
- 내용 > 뷰포트: 수평 스크롤
의도를 대체로 충족합니다. 소소한 개선 제안 2가지:
- 더 직관적인 센터링
- 내부를
w-max mx-auto로 고정하면 내용 넓이만큼만 잡고 자동 가운데 정렬됩니다.- 현재
min-w-max는 부모 폭만큼 늘어날 수 있어 일부 환경에서 간헐적 좌우 여백 차이가 생길 수 있습니다.CourseSelectSection.tsx 예시(파일 외 보조 제안):
- <div - className="flex justify-center gap-[0.8rem] min-w-max" + <div + className="flex gap-[0.8rem] w-max mx-auto" style={{ WebkitOverflowScrolling: 'touch' }} role="list" >
- 스크롤 스냅으로 UX 보완(선택)
- <div className="w-full overflow-x-auto" ... + <div className="w-full overflow-x-auto snap-x snap-mandatory" ... @@ - <CommonButton + <CommonButton key={id} ... + className="snap-center"또한 CommonButton이 네이티브
<button>을 렌더링하는지 확인해 주세요. 네이티브가 아니라면role="button"+tabIndex=0+ Space/Enter 키 처리 필요합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/pages/map/components/CourseInputSection.tsx(1 hunks)src/pages/map/components/CourseSelectSection.tsx(1 hunks)src/pages/map/index.tsx(1 hunks)src/shared/components/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/pages/map/components/CourseSelectSection.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/map/index.tsx (6)
src/shared/hooks/useCourseSelection.ts (1)
useCourseSelection(3-16)src/shared/lib/utils.ts (1)
cn(71-73)src/pages/map/components/CourseSelectSection.tsx (1)
CourseSelectSection(12-64)src/shared/constants/course/courseOptions.ts (3)
purposes(1-5)stays(7-11)moves(13-17)src/pages/map/components/CourseInputSection.tsx (1)
CourseInputSection(11-61)src/shared/components/tab/BottomNav.tsx (1)
BottomNav(21-54)
src/pages/map/components/CourseInputSection.tsx (1)
src/shared/icons/index.ts (1)
Icon(22-22)
🔇 Additional comments (1)
src/shared/components/index.ts (1)
5-5: 배럴 익스포트 추가 LGTM공용 버튼을 barrel로 노출한 선택, 사용처 간 결합도 낮추는 데 도움 됩니다. 추가 액션 없습니다.
| className=" | ||
| w-full rounded-[2rem] py-[1.2rem] px-[1.7rem] | ||
| text-body-md placeholder-gray-400 bg-gray-100 | ||
| border-0 outline-none focus:ring-0 focus:outline-none | ||
| " | ||
| /> |
There was a problem hiding this comment.
포커스 스타일 제거 → WCAG Focus Visible 위반 가능
outline-none, focus:ring-0로 키보드 포커스가 보이지 않을 수 있습니다. 명시적 포커스 표시를 추가하세요.
아래처럼 교체 권장:
- className="
- w-full rounded-[2rem] py-[1.2rem] px-[1.7rem]
- text-body-md placeholder-gray-400 bg-gray-100
- border-0 outline-none focus:ring-0 focus:outline-none
- "
+ className="
+ w-full rounded-[2rem] py-[1.2rem] px-[1.7rem]
+ text-body-md placeholder-gray-400 bg-gray-100
+ border-0
+ focus-visible:ring-2 focus-visible:ring-mint-300
+ focus-visible:ring-offset-2 focus-visible:ring-offset-white
+ focus-visible:outline-none
+ "📝 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.
| className=" | |
| w-full rounded-[2rem] py-[1.2rem] px-[1.7rem] | |
| text-body-md placeholder-gray-400 bg-gray-100 | |
| border-0 outline-none focus:ring-0 focus:outline-none | |
| " | |
| /> | |
| className=" | |
| w-full rounded-[2rem] py-[1.2rem] px-[1.7rem] | |
| text-body-md placeholder-gray-400 bg-gray-100 | |
| border-0 | |
| focus-visible:ring-2 focus-visible:ring-mint-300 | |
| focus-visible:ring-offset-2 focus-visible:ring-offset-white | |
| focus-visible:outline-none | |
| " |
🤖 Prompt for AI Agents
In src/pages/map/components/CourseInputSection.tsx around lines 38 to 43, the
input currently removes all visible focus styling with "outline-none" and
"focus:ring-0" which can hide keyboard focus; replace those rules with an
explicit keyboard-visible focus style (e.g., remove global outline suppression
and add focus-visible utilities such as focus-visible:ring-2 and
focus-visible:ring-[color] or focus-visible:outline to provide a high-contrast
visible ring when focused via keyboard) and keep any mouse-focused visual
behavior intact (use focus-visible instead of focus to avoid changing click
focus), ensuring the new focus style meets WCAG contrast and size requirements.
KongMezu
left a comment
There was a problem hiding this comment.
중복으로 들어간 내용 한번 확인해주시면 될 거 같습니다! 그 외 리뷰는 제안 정도여서 :)
코스 선택 페이지 수고하셨습니다!
| <p | ||
| id={`${inputId}-label`} | ||
| className="text-body-lg text-gray-700" | ||
| > | ||
| {label} | ||
| </p> | ||
|
|
||
| <input | ||
| id={inputId} | ||
| type="text" | ||
| placeholder={placeholder} | ||
| aria-label={label} | ||
| aria-describedby={`${inputId}-desc`} | ||
| className=" |
There was a problem hiding this comment.
aria-labelledby={`${inputId}-label`}
aria-describedby={`${inputId}-desc`}
p태그로 이미 라벨이 있어서 스크린리더에서 aria-label은 중복 읽힐 수 있을거 같아요!
aria-labelledby로 하면 좋을 거 같습니다!
| label={label} | ||
| aria-pressed={selected === id} | ||
| aria-label={`${label} 선택`} | ||
| role="button" |
There was a problem hiding this comment.
이거 이미 button 컴포넌트 불러온건데
role 선언이 중복으로 선언되어있는거 같아요!
확인 부탁드립니다!
src/pages/map/index.tsx
Outdated
| const canProceed = Boolean(purpose && stay && move); | ||
|
|
||
| const handleNext = () => { | ||
| if (!canProceed) return alert('모든 항목을 선택해주세요.'); |
There was a problem hiding this comment.
여기 alret 경고문 보다는 다음으로 넘어가는 버튼 비활성화가 더 좋지 않을까 제안해봅니다!
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/pages/map/index.tsx (1)
79-79: CourseInputSection에disabledprop을 전달하여 UX 일관성을 개선하세요.
CourseInputSection은disabledprop을 지원하지만, 현재 전달되지 않아 필수 선택이 완료되지 않았을 때도 NextButton이 활성화된 것처럼 보입니다. 이는 사용자가 버튼을 클릭했을 때 아무 동작도 하지 않아 혼란을 줄 수 있습니다.- <CourseInputSection onNext={handleNext} /> + <CourseInputSection onNext={handleNext} disabled={!canProceed} />
🧹 Nitpick comments (2)
src/pages/map/index.tsx (2)
33-38: 향후 소셜 로그인 통합 시 ControlBar props 업데이트 필요.현재
isLoggedIn,onLogin,userName이 플레이스홀더 값으로 하드코딩되어 있습니다. PR 목표에 언급된 대로 향후 카카오/구글 로그인 구현 시 실제 인증 상태와 핸들러로 교체해야 합니다.TODO 주석을 추가하거나 이를 추적할 이슈를 생성하시겠습니까?
79-79: 입력값 상태 관리 추가를 권장합니다.
CourseInputSection의 입력 필드가 제어되지 않으며(uncontrolled), 사용자가 입력한 값이 캡처되지 않습니다. PR 목표에 언급된 대로 향후 서버 제출을 위해 입력값을 상태로 관리하는 것이 좋습니다.
useCourseSelection훅을 확장하여 입력값 상태를 추가하세요:src/shared/hooks/useCourseSelection.ts:
export function useCourseSelection() { const [purpose, setPurpose] = useState<string | null>(null); const [stay, setStay] = useState<string | null>(null); const [move, setMove] = useState<string | null>(null); const [desiredPlace, setDesiredPlace] = useState<string>(''); return { purpose, setPurpose, stay, setStay, move, setMove, desiredPlace, setDesiredPlace, }; }src/pages/map/index.tsx:
- const { purpose, setPurpose, stay, setStay, move, setMove } = + const { purpose, setPurpose, stay, setStay, move, setMove, desiredPlace, setDesiredPlace } = useCourseSelection(); @@ - <CourseInputSection onNext={handleNext} disabled={!canProceed} /> + <CourseInputSection + onNext={handleNext} + disabled={!canProceed} + value={desiredPlace} + onChange={setDesiredPlace} + />src/pages/map/components/CourseInputSection.tsx:
// interface에 추가 interface CourseInputSectionProps { // ... 기존 props value?: string; onChange?: (value: string) => void; } // 컴포넌트 내부에서 <input id={inputId} type="text" value={value} onChange={(e) => onChange?.(e.target.value)} // ... 기타 props />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/pages/map/components/CourseInputSection.tsx(1 hunks)src/pages/map/components/CourseSelectSection.tsx(1 hunks)src/pages/map/index.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/pages/map/components/CourseInputSection.tsx
- src/pages/map/components/CourseSelectSection.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/map/index.tsx (6)
src/shared/hooks/useCourseSelection.ts (1)
useCourseSelection(3-16)src/shared/lib/utils.ts (1)
cn(71-73)src/pages/map/components/CourseSelectSection.tsx (1)
CourseSelectSection(12-63)src/shared/constants/course/courseOptions.ts (3)
purposes(1-5)stays(7-11)moves(13-17)src/pages/map/components/CourseInputSection.tsx (1)
CourseInputSection(13-70)src/shared/components/tab/BottomNav.tsx (1)
BottomNav(21-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-and-deploy
🔇 Additional comments (3)
src/pages/map/index.tsx (3)
11-22: 이전 리뷰 피드백이 올바르게 반영되었습니다.
next/router에서useRouter를 정확히 import하고 있습니다.Boolean()캐스팅으로 의도가 명확해졌습니다.- alert 대신 조건부 라우팅 로직으로 개선되었습니다.
40-58: 접근성 구현이 우수합니다.
aria-live="polite"적용으로 동적 콘텐츠 업데이트가 스크린 리더에 전달됩니다.sr-only클래스와aria-labelledby/aria-describedby연결이 적절합니다.- 의미론적 HTML 구조와 ARIA 역할이 잘 조합되어 있습니다.
25-84: 레이아웃 구조가 잘 구성되어 있습니다.고정 위치의
ControlBar와BottomNav, 그리고 스크롤 가능한 메인 컨텐츠 영역이 적절히 조합되어 있습니다. 섹션 간격(3.6rem / 1.9rem)도 PR 설명과 일치합니다.다양한 화면 크기와 콘텐츠 길이에서 레이아웃이 올바르게 작동하는지 확인하세요. 특히 다음 사항을 테스트하세요:
- 작은 화면에서 ControlBar와 BottomNav가 컨텐츠를 가리지 않는지
- 스크롤 시 모든 컨텐츠가 접근 가능한지
- 가로 방향 및 다양한 기기에서의 표시
KongMezu
left a comment
There was a problem hiding this comment.
수고하셨습니다! 추후에 페이지 연결하면서 더 리팩토링 고려해보면 좋을 거 같습니다!
approve 하겠습니다!
|
🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🔥 작업 내용
🤔 추후 작업 사항
🔗 이슈
PR Point (To Reviewer)
📸 피그마 스크린샷 or 기능 GIF
(작업 내역 스크린샷)
-.Clipchamp.mp4
Summary by CodeRabbit
New Features
Refactor
Chores