Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough선택된 정류소 이름( Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant MapContainer
participant BusStopsPanel
participant BusStops
participant useMapOverlays
participant mapOverlays
participant Map
App->>MapContainer: selectedStopName
App->>BusStopsPanel: busCount, selectedStopName
BusStopsPanel->>BusStops: busCount
MapContainer->>useMapOverlays: map, busStops, buses, selectedStopName
useMapOverlays->>mapOverlays: createBusStopOverlays(map, busStops, selectedStopName)
mapOverlays->>mapOverlays: for each stop => isSelected = stop.name === selectedStopName
alt isSelected
mapOverlays->>mapOverlays: createIconSVG("mapPin", true) -- render red circle + red pin
else not selected
mapOverlays->>mapOverlays: createIconSVG("mapPin", false) -- render blue pin
end
mapOverlays->>Map: addOverlay(icon)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 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 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/BusStops.tsx (1)
10-11: selectedStopName prop이 사용되지 않습니다.
selectedStopNameprop이 정의되었지만 컴포넌트 내에서 사용되지 않습니다. 향후 사용 예정이거나 필요 없다면 제거를 고려하세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
src/App.tsx(4 hunks)src/components/BusStops.tsx(7 hunks)src/components/BusStopsPanel.tsx(2 hunks)src/components/MapContainer.tsx(1 hunks)src/data/busStops.ts(0 hunks)src/hooks/useBusSelection.ts(1 hunks)src/hooks/useMapOverlays.ts(2 hunks)src/lib/api.ts(1 hunks)src/utils/mapOverlays.ts(4 hunks)
💤 Files with no reviewable changes (1)
- src/data/busStops.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (4)
src/components/MapContainer.tsx (3)
src/api/bus.ts (1)
useBusLocations(6-16)src/hooks/useMapOverlays.ts (1)
useMapOverlays(10-34)src/data/busStops.ts (1)
busStops(7-12)
src/hooks/useMapOverlays.ts (1)
src/utils/mapOverlays.ts (2)
OverlayHandle(4-6)createBusStopOverlays(129-161)
src/utils/mapOverlays.ts (1)
src/data/busStops.ts (2)
busStops(7-12)BusStop(1-5)
src/App.tsx (1)
src/components/MapContainer.tsx (1)
MapContainer(15-32)
🔇 Additional comments (21)
src/lib/api.ts (1)
8-10: LGTM!조건부 헤더 스프레드를 여러 줄로 분리하여 가독성이 향상되었습니다. 로직 변경은 없으며 타입 안전합니다.
src/hooks/useBusSelection.ts (1)
18-26: LGTM!중첩된 삼항 연산자를 명확한 다중 조건문으로 리팩토링하여 가독성이 크게 향상되었습니다. 의미론적으로 동일하며 타입 안전합니다.
src/App.tsx (3)
76-78: LGTM!ReactQueryDevtools 조건부 렌더링이 명확하게 구성되었습니다.
91-95: LGTM!
setBubbleStop타입 주석이 명확하고 타입 안전합니다.
135-148: LGTM!
MapContainer와BusStopsPanel에 새로운 props(selectedStopName,busCount)가 올바르게 연결되었습니다.bubbleStop?.name과buses.length의 전파가 적절합니다.src/components/MapContainer.tsx (2)
12-12: LGTM!
selectedStopNameoptional prop이 올바르게 정의되었습니다.
15-24: LGTM!
selectedStopName이 컴포넌트 시그니처에 추가되고useMapOverlays로 올바르게 전달되었습니다.src/hooks/useMapOverlays.ts (2)
10-24: LGTM!
selectedStopName파라미터가 올바르게 추가되고createBusStopOverlays로 전달되었습니다. 타입 안전한 구현입니다.
33-33: LGTM!의존성 배열에
selectedStopName이 올바르게 추가되어 선택된 정류장이 변경될 때 effect가 재실행됩니다.src/components/BusStopsPanel.tsx (2)
9-17: LGTM!
busCount와selectedStopNameprops가 올바르게 추가되고 destructure되었습니다. 타입 정의가 명확합니다.
35-36: LGTM!새로운 props가
BusStops컴포넌트로 올바르게 전달되었습니다.src/utils/mapOverlays.ts (4)
9-19: LGTM!
createIconSVG에showCircle파라미터가 추가되어 선택된 정류장의 시각적 표현이 가능해졌습니다. SVG 크기와 viewBox가 원을 수용하도록 증가되었고, 선택 상태에 따라 색상이 조건부로 적용됩니다.
23-35: LGTM!선택된 정류장에 대한 반투명 빨간 배경 원이 올바르게 구현되었습니다.
showCircle이 true일 때만 렌더링됩니다.
37-57: LGTM!MapPin 아이콘의 fill 색상이 선택 상태에 따라 올바르게 조건부 처리되었습니다 (선택됨: 빨강, 기본: 파랑).
129-160: LGTM!
createBusStopOverlays가selectedStopName을 받아 각 정류장의 선택 상태를 계산하고 아이콘에 반영합니다. 문자열 비교가 명확하고 타입 안전합니다.src/components/BusStops.tsx (6)
19-19: LGTM!
busCount의 기본값 0이 안전하게 설정되었습니다.
79-97: LGTM!정류장 아이콘 SVG가 명시적인
strokeWidth로 업데이트되어 일관성이 향상되었습니다.
117-117: LGTM!그리드 레이아웃이 3열에서 2열로 변경되어 UI 디자인이 개선되었습니다.
171-174: LGTM!버스 아이콘에 명시적인
strokeWidth={2.5}가 설정되어 일관성이 향상되었습니다.
200-214: LGTM!버스 번호 버튼이
busCount기반으로 동적 렌더링되도록 올바르게 리팩토링되었습니다.Array.from사용이 적절합니다.
123-149: 데이터 일관성 검증 완료 - 모든 정류장 일치검증 결과, busStops 데이터와 BusStops.tsx의 하드코딩된 목록이 완전히 일치합니다:
- busStops 데이터: 평화의광장, 치과병원, 정문, 죽전역 (4개)
- 하드코딩된 목록: 죽전역, 치과병원, 정문, 평화의광장 (4개)
모든 정류장이 양쪽에 존재하며 누락되거나 초과된 항목이 없습니다. 코드가
busStops.find((s) => s.name === stop.name)을 사용하여 이름 기반으로 조회하므로 순서 차이는 문제가 되지 않습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/BusStops.tsx (1)
122-148: 하드코딩된 정류장 이름이 busStops 프롭과 불일치할 수 있습니다.정류장 이름을 하드코딩하고 있지만, 실제 데이터는
busStops프롭에서find로 찾고 있습니다(134-136줄). 만약busStops에 해당 이름의 정류장이 없으면 버튼 클릭 시 아무 동작도 하지 않습니다. 이는 데이터 불일치 시 조용히 실패하는 문제를 일으킬 수 있습니다.다음 중 하나의 방식으로 개선하는 것을 권장합니다:
방법 1: busStops 프롭을 직접 렌더링 (권장)
-{[ - { name: "죽전역" }, - { name: "치과병원" }, - { name: "정문" }, - { name: "평화의광장" }, -].map((stop) => ( +{busStops.map((stop) => ( <button key={stop.name} type="button" disabled={disabled} onClick={() => handleClick(() => { - const realStop = busStops.find( - (s) => s.name === stop.name - ); - if (realStop) { - onSelect(realStop); - if (onToggleBubble) - onToggleBubble(realStop); - } + onSelect(stop); + if (onToggleBubble) onToggleBubble(stop); }) } className="..." > {stop.name} </button> ))}방법 2: 하드코딩 유지가 필요하다면 찾지 못한 경우 처리
onClick={() => handleClick(() => { const realStop = busStops.find( (s) => s.name === stop.name ); if (realStop) { onSelect(realStop); if (onToggleBubble) onToggleBubble(realStop); + } else { + console.warn(`정류장 "${stop.name}"을 찾을 수 없습니다.`); } }) }
🧹 Nitpick comments (1)
src/components/BusStops.tsx (1)
78-96: 정류장 아이콘이 인라인 SVG로 교체되었습니다.접근성 속성들(
role,aria-label,title)이 잘 적용되어 있고, 아이콘 정상화 목적에 맞게 커스텀 SVG를 사용하고 있습니다.향후 재사용성과 유지보수를 위해 별도 컴포넌트로 추출하는 것을 고려해보세요:
// 별도 파일 또는 같은 파일 내 const BusStopIcon = () => ( <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#2563eb" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" role="img" aria-label="정류장 아이콘" > <title>정류장 아이콘</title> <path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0" fill="#2563eb" /> <circle cx="12" cy="10" r="3" fill="white" /> </svg> );그리고 사용처에서:
-<svg - width="32" - ... -</svg> +<BusStopIcon />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/App.tsx(4 hunks)src/components/BusStops.tsx(7 hunks)src/components/BusStopsPanel.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/BusStopsPanel.tsx
- src/App.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🔇 Additional comments (4)
src/components/BusStops.tsx (4)
10-10: busCount 프롭 추가가 타입 안전하게 구현되었습니다.타입이 명확하고 기본값 처리가 적절합니다. 다만
busCount가 0일 때 버스 번호 선택 영역이 비어있게 되는데, 이 경우 사용자에게 안내 메시지를 보여주는 것이 좋을지 확인해보세요.Also applies to: 18-18
116-116: 그리드 레이아웃이 3열에서 2열로 변경되었습니다.4개의 정류장을 2x2로 배치하는 것이 더 균형잡힌 레이아웃입니다. 다만 모바일 화면에서도 2열 레이아웃이 적절한지 확인해보세요.
170-173: Bus 아이콘에 명시적인 strokeWidth가 추가되었습니다.위의 정류장 SVG 아이콘과 동일한
strokeWidth={2.5}를 사용하여 시각적 일관성을 유지하고 있습니다.
199-213: 버스 번호 렌더링이 동적으로 개선되었습니다.하드코딩된
[1, 2, 3, 4, 5]대신busCount프롭을 기반으로 동적으로 버튼을 생성하도록 변경되어, 더 유연하고 확장 가능한 구조가 되었습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/BusStops.tsx (1)
78-96: 커스텀 SVG 아이콘 구현이 훌륭합니다!정류장 아이콘을 커스텀 인라인 SVG로 교체한 것은 좋은 선택입니다. 접근성 속성(
role,aria-label,title)이 적절하게 구현되어 있고, 시각적 일관성도 잘 유지되고 있습니다.참고: SVG의 색상(
#2563eb)이 하드코딩되어 있는데, 향후 다크모드를 지원하거나 테마를 변경할 경우 Tailwind의currentColor나 CSS 변수를 사용하는 것을 고려해볼 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/BusStops.tsx(6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (1)
src/components/BusStops.tsx (1)
src/data/busStops.ts (1)
busStops(7-12)
🔇 Additional comments (5)
src/components/BusStops.tsx (5)
116-116: LGTM!정류장이 4개인 경우
grid-cols-2로 변경하여 2x2의 균형잡힌 레이아웃을 만든 것은 좋은 개선입니다.
122-137: 동적 렌더링으로의 전환이 우수합니다!하드코딩된 정류장 목록을
busStops.map()을 사용한 동적 렌더링으로 변경한 것은 확장성과 유지보수성을 크게 향상시킵니다. 각 버튼에 올바른keyprop이 설정되어 있고, 이벤트 핸들러와 접근성 속성도 잘 유지되고 있습니다.
159-162: 시각적 일관성 개선!
Bus아이콘에strokeWidth={2.5}를 명시적으로 추가하여 커스텀 정류장 SVG 아이콘과 시각적 일관성을 맞춘 것은 좋은 디테일입니다.
188-202: 동적 버스 번호 렌더링 구현이 깔끔합니다!
Array.from({ length: busCount })을 사용한 동적 버튼 생성은 깔끔하고 유연한 접근 방식입니다. 코드가 타입 안전하고 React 모범 사례를 잘 따르고 있습니다.참고:
busCount가 0일 때의 UX는 Lines 10, 18에 대한 별도 코멘트를 참조해주세요.
10-10: 리뷰 코멘트가 부분적으로 부정확합니다.
busCount는App.tsx의buses.length로부터 항상BusStopsPanel을 통해 전달되므로, 기본값 0에 의한 빈 버스 선택 섹션 문제는 현재 코드에서 발생하지 않습니다.
BusStopsPanel에서busCount는 필수 prop이며 항상 값을 전달BusStops에서 기본값 0은 컴포넌트를 독립적으로 사용할 때를 위한 방어적 기본값으로 적절함- 현재 코드 구조에서는
busCount = 0이 실제로 적용되는 상황이 없음
Summary by CodeRabbit
새로운 기능
UI 변경
데이터 업데이트