✨ [FEAT] 관람객용 행사 상세 평면도 추가 및 핀 컴포넌트 공통화 - #46
Conversation
28px -> 20px로 줄이고 글자 크기도 함께 조정해 배치도가 좁을 때 핀이 과하게 커 보이던 문제를 개선했다.
- 상단에 실제 공개(PUBLISHED) 행사 목록을 드롭다운으로 표시하고 선택 가능하도록 변경 - 헤더(행사명·기간·장소)를 선택한 행사의 실제 데이터로 표시 - 행사장 배치도 탭을 목업 그리드 대신 실제 등록된 방문객용(VISITOR) 평면도 이미지와 부스 핀으로 교체, 핀 클릭 시 부스 정보 팝업 - 참가 부스/인기 부스/관심 부스/QR은 실시간 데이터 API가 아직 없어 기존 목업을 그대로 유지
- EventDetail(공개 행사 상세)에 VISITOR 타입 평면도 섹션 추가 - 배치도 핀에 부스코드 전체 표시 + 길이별 폰트 자동 축소 - 핀 렌더링(VenueMapPins)과 정보 팝업(BoothPinPopup)을 공용 컴포넌트로 추출해 EventDetail/EventOngoing/RecruitmentDetail 3곳의 중복 제거
|
Warning Review limit reached
Next review available in: 44 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Walkthrough공개 행사 평면도 API를 행사 화면에 연동했습니다. 좌표 기반 부스 핀과 부스 상세 팝업을 공통 컴포넌트로 추가했습니다. EventOngoing과 RecruitmentDetail의 기존 정적 또는 인라인 핀 렌더링을 공통 컴포넌트로 교체했습니다. Changes공개 행사장 평면도 흐름
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant EventOngoing
participant PublicEventAPI
participant PublicVenueMapAPI
participant VenueMapPins
participant BoothPinPopup
EventOngoing->>PublicEventAPI: 공개 행사 목록 조회
PublicEventAPI-->>EventOngoing: 행사 목록 응답
EventOngoing->>PublicVenueMapAPI: 행사 상세 및 VISITOR 평면도 조회
PublicVenueMapAPI-->>EventOngoing: 행사 상세와 평면도 응답
EventOngoing->>VenueMapPins: 평면도와 부스 위치 전달
VenueMapPins->>EventOngoing: 선택한 booth 전달
EventOngoing->>BoothPinPopup: 선택한 booth 전달
BoothPinPopup-->>EventOngoing: onClose 호출
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
FE/src/pages/RecruitmentDetail.jsx (1)
10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift
RecruitmentDetail의 부스 팝업도BoothPinPopup으로 교체해주세요.현재 이 파일은
VenueMapPins만 import하고,selectedBooth팝업을 356-445행에서 직접 렌더링합니다. 이 상태에서는EventDetail,EventOngoing,RecruitmentDetail의 팝업 구현이 다시 분기됩니다.BoothPinPopup을 사용해 공용 팝업 추출 목표를 완료해주세요.🤖 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 `@FE/src/pages/RecruitmentDetail.jsx` at line 10, Update RecruitmentDetail to import and render the shared BoothPinPopup for the selectedBooth popup instead of its inline popup implementation. Remove the duplicated popup markup and pass the existing selected booth data and required handlers/props so behavior remains consistent with EventDetail and EventOngoing.
🤖 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 `@FE/src/components/BoothPinPopup.jsx`:
- Around line 7-22: BoothPinPopup의 모달에 role="dialog", aria-modal="true", 제목 id와
aria-labelledby 연결을 추가하세요. 팝업이 열리면 닫기 버튼으로 포커스를 이동하고, 팝업 내부에서 포커스가 유지되도록 처리하세요.
Escape 키 입력 시 onClose를 호출하도록 키보드 이벤트를 구현하세요.
In `@FE/src/pages/EventDetail.jsx`:
- Around line 51-67: Update the venue-map loading useEffect in
FE/src/pages/EventDetail.jsx (lines 51-67) to call listPublicVenueMaps only when
event?.venueMapEnabled is true, while preserving the existing reset, loading,
cancellation, and error behavior. Apply the same venueMapEnabled guard in
FE/src/pages/EventOngoing.jsx (lines 109-133) using the event-detail data before
invoking listPublicVenueMaps.
In `@FE/src/pages/EventOngoing.jsx`:
- Around line 80-85: Use the URL query’s eventId as the single source of truth
for the selected event. Update the EventOngoing selection flow around
selectedEventId and the existing useEffect so browser history or external
navigation changes are reflected in the displayed event, either by deriving
selection directly from the query or synchronizing selectedEventId when the
query changes. Preserve URL updates for user selections without creating a
synchronization loop.
---
Nitpick comments:
In `@FE/src/pages/RecruitmentDetail.jsx`:
- Line 10: Update RecruitmentDetail to import and render the shared
BoothPinPopup for the selectedBooth popup instead of its inline popup
implementation. Remove the duplicated popup markup and pass the existing
selected booth data and required handlers/props so behavior remains consistent
with EventDetail and EventOngoing.
🪄 Autofix
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: CHILL
Plan: Pro Plus
Run ID: 74346640-7ed3-4049-83c9-56f64bb01bb2
📒 Files selected for processing (6)
FE/src/components/BoothPinPopup.jsxFE/src/components/VenueMapPins.jsxFE/src/pages/EventDetail.jsxFE/src/pages/EventOngoing.jsxFE/src/pages/RecruitmentDetail.jsxFE/src/utils/venueMapPin.js
단순 이름/코드만 보여주던 BoothPinPopup 대신, 참가 부스 목록과 동일한 바텀시트(혼잡도/실시간 대기/방문자/관심등록)를 재사용하도록 변경.
There was a problem hiding this comment.
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)
FE/src/pages/EventOngoing.jsx (1)
71-75: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win목록에 없는 URL
eventId를 기본 행사로 보정하세요.사용자가
?eventId=invalid를 열면selectedEventId가 비어 있지 않아서 기본 행사를 선택하지 않습니다. 이후 상세 행사와 평면도 요청이 존재하지 않는 ID로 실행되고,<select>도 목록에 없는 값을 갖습니다.행사 목록을 받은 뒤
selectedEventId가 목록에 있는지 확인하세요. 없으면 첫 번째 행사 ID로 변경하세요.수정 예시
const list = result?.data?.content || []; setEvents(list); - if (!selectedEventId && list.length > 0) { - setSelectedEventId(String(list[0].id)); + const selectedEvent = list.find((event) => String(event.id) === selectedEventId); + if (!selectedEvent && list.length > 0) { + setSelectedEventId(String(list[0].id)); }🤖 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 `@FE/src/pages/EventOngoing.jsx` around lines 71 - 75, Update the event-list handling around setEvents and selectedEventId so it validates the current selectedEventId against the returned list. When the ID is missing or not present in the list, replace it with the first event’s ID when available; preserve the existing selection when it remains valid and keep the empty-list behavior safe.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 `@FE/src/pages/EventOngoing.jsx`:
- Around line 44-45: Remove the mockCongestion-generated values from the bottom
sheet’s real-time metrics. Until a metrics API is connected, display “정보 없음” or
hide the metrics section, and only render actual API response data when
available; do not present deterministic booth ID values as live wait time or
visitor counts.
- Around line 152-167: Update openMapBoothSheet and toggleInterestFromSheet to
persist interest per booth using a stable identifier such as position.boothId,
rather than resetting interest to false. Store the state in dedicated component
state or the existing API, and read the saved value when reopening the same
booth pin so it survives closing and reopening the sheet.
---
Outside diff comments:
In `@FE/src/pages/EventOngoing.jsx`:
- Around line 71-75: Update the event-list handling around setEvents and
selectedEventId so it validates the current selectedEventId against the returned
list. When the ID is missing or not present in the list, replace it with the
first event’s ID when available; preserve the existing selection when it remains
valid and keep the empty-list behavior safe.
🪄 Autofix
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: CHILL
Plan: Pro Plus
Run ID: 118c3669-e5f7-4c55-8a11-5f3a1d55d14e
📒 Files selected for processing (1)
FE/src/pages/EventOngoing.jsx
- BoothPinPopup에 role/aria-modal/aria-labelledby, 포커스 트랩, Escape 닫기 추가 - venueMapEnabled가 false인 행사는 평면도 API를 호출하지 않도록 가드 - EventOngoing에서 뒤로가기 등 외부 내비게이션으로 바뀐 URL의 eventId를 선택 상태에 반영
- 배치도 핀 바텀시트의 혼잡도/대기시간/방문자 목업 값을 "정보 없음"으로 대체 (실제 지표 API 없이 가짜 숫자를 실시간 정보처럼 보여주지 않도록) - 관심 등록 상태를 boothId 기준으로 별도 보관해 시트를 닫았다 다시 열어도 유지되게 수정
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
FE/src/pages/EventOngoing.jsx (2)
120-144: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win행사 전환 시 이전 평면도 상태를 초기화하세요.
선택한 행사의
venueMapEnabled가false이면 Line 121에서 바로 반환합니다. 이전 행사에서 조회한venueMaps와loadingVenueMaps는 초기화되지 않습니다. 따라서 비활성 평면도 행사에서 이전 행사의 평면도가 표시되거나 로딩 문구가 계속 표시될 수 있습니다.조건을 만족하지 않을 때
venueMaps,venueMapError,loadingVenueMaps를 초기화하세요. 이전eventDetail로 새 행사의 평면도를 요청하지 않도록 평면도 조회 전에eventDetail.id와selectedEventId의 일치도 확인하세요.수정 방향
- if (!selectedEventId || !eventDetail?.venueMapEnabled) return; + if ( + !selectedEventId || + !eventDetail?.venueMapEnabled || + String(eventDetail.id) !== String(selectedEventId) + ) { + setVenueMaps([]); + setVenueMapError(""); + setLoadingVenueMaps(false); + return; + }🤖 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 `@FE/src/pages/EventOngoing.jsx` around lines 120 - 144, Update the venue-map useEffect keyed by selectedEventId and eventDetail?.venueMapEnabled to clear venueMaps, venueMapError, and loadingVenueMaps before returning when venue maps are disabled or unavailable. Before calling listPublicVenueMaps, also verify eventDetail.id matches selectedEventId so stale event details cannot trigger a request; preserve the existing cancellation handling for valid requests.
73-75: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win비동기 기본 선택이 URL의 행사 선택을 덮어쓸 수 있습니다.
행사 목록 요청이 시작될 때
selectedEventId가 비어 있으면, Line 73은 그 시점의 값을 클로저로 유지합니다. 요청이 끝나기 전에 뒤로가기나 외부 내비게이션으로 URL의eventId가 변경되면, Line 93이 새 값을 설정한 뒤에도 Line 74가 첫 행사를 다시 설정할 수 있습니다.URL의
eventId를 선택 상태의 기준으로 사용하세요. URL 값이 없을 때만 목록의 첫 행사를 기본값으로 계산하세요. 별도 effect에서 두 상태를 서로 갱신하지 마세요.Also applies to: 89-96
🤖 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 `@FE/src/pages/EventOngoing.jsx` around lines 73 - 75, Avoid letting the asynchronous list-loading callback overwrite a newer URL eventId. In the selection logic around setSelectedEventId and the URL synchronization at lines 89-96, use the current URL eventId as the source of truth and choose list[0].id only when that URL value is absent; consolidate the behavior without separate effects that update each state from the other.
🤖 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.
Outside diff comments:
In `@FE/src/pages/EventOngoing.jsx`:
- Around line 120-144: Update the venue-map useEffect keyed by selectedEventId
and eventDetail?.venueMapEnabled to clear venueMaps, venueMapError, and
loadingVenueMaps before returning when venue maps are disabled or unavailable.
Before calling listPublicVenueMaps, also verify eventDetail.id matches
selectedEventId so stale event details cannot trigger a request; preserve the
existing cancellation handling for valid requests.
- Around line 73-75: Avoid letting the asynchronous list-loading callback
overwrite a newer URL eventId. In the selection logic around setSelectedEventId
and the URL synchronization at lines 89-96, use the current URL eventId as the
source of truth and choose list[0].id only when that URL value is absent;
consolidate the behavior without separate effects that update each state from
the other.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 5d06a150-a640-4603-9ada-a9ece5cba2b5
📒 Files selected for processing (3)
FE/src/components/BoothPinPopup.jsxFE/src/pages/EventDetail.jsxFE/src/pages/EventOngoing.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- FE/src/pages/EventDetail.jsx
- venueMapEnabled가 false이거나 eventDetail이 아직 이전 행사 것일 때 venueMaps/loadingVenueMaps/venueMapError를 초기화하지 않던 문제 수정 (행사 전환 시 이전 평면도가 남아있거나 로딩 문구가 안 사라지는 버그) - 행사 목록 요청이 늦게 도착했을 때, 그 사이 URL로 바뀐 선택을 첫 행사로 덮어쓰던 경쟁 조건을 응답 시점의 실제 URL 기준으로 판단하도록 수정
📄 작업 내용
🔗 관련 이슈
Closes #
☑️ 체크리스트
📸 스크린샷 (UI 변경 시)
💬 리뷰어에게
FE에는 테스트 프레임워크가 아직 설정되어 있지 않아 이번 PR에도 테스트를 추가하지 않았습니다.
Summary by CodeRabbit
새로운 기능
개선 사항