-
Notifications
You must be signed in to change notification settings - Fork 3
[feature] 데스크탑 상세페이지 지도 클릭 시 전체화면 모달을 추가한다 #1440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
suhyun113
merged 21 commits into
develop-fe
from
feature/#1409-desktop-detail-map-modal-MOA-803
Apr 25, 2026
Merged
Changes from 12 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
0398b97
docs: CLAUDE.md 네이버 지도 환경변수 및 외부 서비스 추가
suhyun113 8dc6e12
refactor: ClubMapPage BottomCard를 MapClubInfoCard 공통 컴포넌트로 분리
suhyun113 7c299c3
feat: InteractiveMapView 공통 컴포넌트 추가 및 반응형 ClubMapModal 생성
suhyun113 5114f16
refactor: ClubMapPage 제거 및 반응형 모달로 통합
suhyun113 260d06f
style: 지도 UI 개선 (커서, 텍스트 선택 방지, 반응형 카드 스타일)
suhyun113 f40969d
feat: 데스크탑 지도 모달 줌 인/아웃 버튼 추가
suhyun113 1efcdee
refactor: 지도 관련 파일 구조 정리 (컴포넌트/훅/유틸 분리)
suhyun113 3ddda29
style: 줌 버튼 및 아이콘 두께 조정
suhyun113 615a26e
feat: 지도 정보 카드 클릭 시 초기 위치로 지도 복귀
suhyun113 240e29c
style: 지도 마커 반응형 크기 및 테마 색상 적용
suhyun113 2c02a5d
style: 지도 정보 카드 mini_mobile 반응형 너비 추가
suhyun113 fce9028
style: prettier 포맷 적용
suhyun113 56171be
fix: 모바일 모달 높이를 100dvh로 수정하여 주소바 영역 대응
suhyun113 fab2605
refactor: 지도 인스턴스 any 타입을 NaverMapInstance 인터페이스로 대체
suhyun113 1533a8a
refactor: NaverMap props에 Pick 제네릭 적용 (ClubProfileCard 패턴 일관성)
suhyun113 f1f4480
refactor: InteractiveMapView를 useNaverMap 훅으로 통합하여 중복 제거
suhyun113 228221b
refactor: 모바일에서 불필요한 줌 컨트롤 렌더 제거 및 InteractiveMapView ref 폴백 정리
suhyun113 643574f
fix: 지도 정보 카드 mobile 반응형 너비 범위 수정
suhyun113 fdfe0f3
refactor: MapModal 컨트롤 z-index를 로컬 상수로 분리
suhyun113 6ab0c7f
fix: loadNaverMapScript Race Condition 보강
suhyun113 4062689
Merge branch 'develop-fe' into feature/#1409-desktop-detail-map-modal…
suhyun113 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions
26
frontend/src/components/map/InteractiveMapView/InteractiveMapView.styles.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import styled from 'styled-components'; | ||
| import { media } from '@/styles/mediaQuery'; | ||
|
|
||
| export const Container = styled.div` | ||
| position: relative; | ||
| width: 100%; | ||
| height: 100%; | ||
| `; | ||
|
|
||
| export const MapArea = styled.div` | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: hidden; | ||
| `; | ||
|
|
||
| export const InfoCardWrapper = styled.div` | ||
| position: absolute; | ||
| bottom: 50px; | ||
| left: 50%; | ||
| transform: translateX(-50%); | ||
| z-index: 10; | ||
|
|
||
| ${media.tablet} { | ||
| bottom: 30px; | ||
| } | ||
| `; |
134 changes: 134 additions & 0 deletions
134
frontend/src/components/map/InteractiveMapView/InteractiveMapView.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| import { RefObject, useCallback, useEffect, useRef } from 'react'; | ||
| import markerIcon from '@/assets/images/icons/marker.svg'; | ||
| import MapClubInfoCard from '@/components/map/MapClubInfoCard/MapClubInfoCard'; | ||
| import { ClubLocation } from '@/constants/clubLocation'; | ||
| import { colors } from '@/styles/theme/colors'; | ||
| import { loadNaverMapScript } from '@/utils/loadNaverMapScript'; | ||
| import * as Styled from './InteractiveMapView.styles'; | ||
|
|
||
| interface InteractiveMapViewProps { | ||
| location: ClubLocation; | ||
| clubName: string; | ||
| clubLogo?: string; | ||
| active: boolean; | ||
| markerSize?: number; | ||
| bubbleFontSize?: number; | ||
| bubbleFontWeight?: number; | ||
| mapInstanceRef?: RefObject<any>; | ||
| } | ||
|
|
||
| const InteractiveMapView = ({ | ||
| location, | ||
| clubName, | ||
| clubLogo, | ||
| active, | ||
| markerSize = 40, | ||
| bubbleFontSize = 13, | ||
| bubbleFontWeight = 700, | ||
| mapInstanceRef: externalMapRef, | ||
| }: InteractiveMapViewProps) => { | ||
| const mapRef = useRef<HTMLDivElement | null>(null); | ||
| const internalMapRef = useRef<any>(null); | ||
| const mapInstanceRef = externalMapRef || internalMapRef; | ||
|
|
||
| useEffect(() => { | ||
| if (!active) return; | ||
|
|
||
| const timer = setTimeout(() => { | ||
| loadNaverMapScript().then(() => { | ||
| if (!mapRef.current || !window.naver) return; | ||
|
|
||
| const { naver } = window; | ||
| const position = new naver.maps.LatLng(location.lat, location.lng); | ||
|
|
||
| mapInstanceRef.current = new naver.maps.Map(mapRef.current, { | ||
| center: position, | ||
| zoom: 17, | ||
| logoControl: false, | ||
| mapDataControl: false, | ||
| scaleControl: false, | ||
| }); | ||
|
|
||
| const markerContent = ` | ||
| <div style="position: relative; display: inline-block;"> | ||
| <div style=" | ||
| position: absolute; | ||
| bottom: calc(${markerSize}px + 5px); | ||
| left: 50%; | ||
| transform: translateX(-50%); | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| "> | ||
| <div style=" | ||
| background: #fff; | ||
| border-radius: 50px; | ||
| padding: 10px 16px; | ||
| font-size: ${bubbleFontSize}px; | ||
| font-weight: ${bubbleFontWeight}; | ||
| color: ${colors.gray[900]}; | ||
| white-space: nowrap; | ||
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; | ||
| box-shadow: 0 2px 8px rgba(0,0,0,0.15); | ||
| ">동아리방</div> | ||
| <div style=" | ||
| width: 0; | ||
| height: 0; | ||
| border-left: 9px solid transparent; | ||
| border-right: 9px solid transparent; | ||
| border-top: 10px solid #fff; | ||
| margin-top: -2px; | ||
| "></div> | ||
| </div> | ||
| <img src="${markerIcon}" style="width: ${markerSize}px; height: ${markerSize}px; display: block;" /> | ||
| </div> | ||
| `; | ||
|
|
||
| new naver.maps.Marker({ | ||
| position, | ||
| map: mapInstanceRef.current, | ||
| icon: { | ||
| content: markerContent, | ||
| anchor: new naver.maps.Point(markerSize / 2, markerSize), | ||
| }, | ||
| }); | ||
| }); | ||
| }, 100); | ||
|
|
||
| return () => { | ||
| clearTimeout(timer); | ||
| mapInstanceRef.current?.destroy(); | ||
| mapInstanceRef.current = null; | ||
| }; | ||
| }, [ | ||
| active, | ||
| location.lat, | ||
| location.lng, | ||
| markerSize, | ||
| bubbleFontSize, | ||
| bubbleFontWeight, | ||
| ]); | ||
|
|
||
| const handleRecenter = useCallback(() => { | ||
| const map = mapInstanceRef.current; | ||
|
Comment on lines
+41
to
+42
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Recenter 중심으로 돌아간다는 의미인가요??
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네, 사용자가 지도를 드래그하여 이동한 뒤 하단 MapClubInfoCard를 클릭하면 원래 동아리 위치 기준으로 지도 중심을 되돌리는 기능입니다! |
||
| if (map && window.naver) { | ||
| map.setCenter(new window.naver.maps.LatLng(location.lat, location.lng)); | ||
| } | ||
| }, [mapInstanceRef, location.lat, location.lng]); | ||
|
|
||
| return ( | ||
| <Styled.Container> | ||
| <Styled.MapArea ref={mapRef} /> | ||
| <Styled.InfoCardWrapper onClick={handleRecenter}> | ||
| <MapClubInfoCard | ||
| logo={clubLogo} | ||
| name={clubName} | ||
| building={location.building} | ||
| detailLocation={location.detailLocation} | ||
| /> | ||
| </Styled.InfoCardWrapper> | ||
| </Styled.Container> | ||
| ); | ||
| }; | ||
|
|
||
| export default InteractiveMapView; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naver Map 초기화 위치 설명이 실제 구현과 다릅니다.
Line 61의 “모든 SDK는
src/utils/initSDK.ts에서 초기화”는 현재 지도 구현과 불일치합니다. Naver Map은src/utils/loadNaverMapScript.ts에서 동적 로드되므로 문구를 분리해 명시해 주세요.✍️ 문서 수정 예시
Also applies to: 74-74
🤖 Prompt for AI Agents