Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 25 additions & 27 deletions src/features/map/components/MapPinMarker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ export function MapPinMarker({
onPlay,
}: MapPinMarkerProps) {
return (
<div
className="relative cursor-pointer select-none transition-transform duration-150"
style={{
width: 51,
height: 57,
transform: isSelected ? 'scale(1.2)' : undefined,
}}
>
<div className="relative cursor-pointer select-none" style={{ width: 51, height: 57 }}>
{isSelected && nickname && introduction ? (
<div className="absolute bottom-full left-1/2 mb-2 -translate-x-1/2">
<MapPinMessageBox
Expand All @@ -38,27 +31,32 @@ export function MapPinMarker({
</div>
) : null}

<img
src={pinIconUrl}
alt="핀 아이콘"
draggable={false}
className="pointer-events-none block size-full object-contain"
/>

<div
className="pointer-events-none absolute overflow-hidden rounded-full"
style={{
left: '49.7%',
top: '36%',
width: 24,
height: 24,
transform: 'translate(-50%, -50%)',
background: coverUrl,
}}
className="relative size-full transition-transform duration-150"
style={{ transform: isSelected ? 'scale(1.2)' : undefined }}
>
{coverUrl ? (
<img src={coverUrl} alt="" draggable={false} className="size-full object-cover" />
) : null}
<img
src={pinIconUrl}
alt="핀 아이콘"
draggable={false}
className="pointer-events-none block size-full object-contain"
/>

<div
className="pointer-events-none absolute overflow-hidden rounded-full"
style={{
left: '49.7%',
top: '36%',
width: 24,
height: 24,
transform: 'translate(-50%, -50%)',
background: coverUrl,
}}
>
{coverUrl ? (
<img src={coverUrl} alt="" draggable={false} className="size-full object-cover" />
) : null}
</div>
</div>
</div>
);
Expand Down
43 changes: 43 additions & 0 deletions src/features/map/constants/devMockMapPins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { MapPin } from '@/features/map/types';

/**
* 개발 환경에서 실제 API 응답이 비어있을 때(근처에 등록된 PIN이 없을 때)
* 배선/렌더링을 확인할 수 있도록 서울시청 근처(공공장소)에 고정으로 띄우는 목데이터.
* 화면 중심 기준으로 계산하지 않는다 — 지도를 움직여도 따라오지 않고 실제
* 위치에 고정돼 있어야 하기 때문. 프로덕션 빌드(import.meta.env.DEV === false)
* 에서는 절대 사용하지 않는다.
*/
export const DEV_MOCK_MAP_PINS: MapPin[] = [
{
id: 'dev-mock:1',
lat: 37.5663,
lng: 126.9779,
coverUrl: undefined,
nickname: '냥코',
introduction: '도가니 살리기 위잉잉잉~',
},
{
id: 'dev-mock:2',
lat: 37.5658,
lng: 126.9784,
coverUrl: undefined,
nickname: '한강러버',
introduction: '야경 보면서 듣기 딱 좋아요',
},
{
id: 'dev-mock:3',
lat: 37.5669,
lng: 126.9773,
coverUrl: undefined,
nickname: '산책러',
introduction: '퇴근길 산책 플레이리스트',
},
{
id: 'dev-mock:4',
lat: 37.5661,
lng: 126.977,
coverUrl: undefined,
nickname: '댄스머신',
introduction: '기분 좋아지는 노래 추천',
},
];
17 changes: 14 additions & 3 deletions src/pages/MapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { useNavigate } from 'react-router-dom';
import { SearchLauncher } from '@/components/ui/SearchInput';
import { Toast, ToastProvider, ToastViewport } from '@/components/ui/Toast';
import { Button } from '@/components/ui/button';
import type { MapCoordinate, MapPlace } from '@/features/map/types';
import type { MapCoordinate, MapPlace, MapViewport } from '@/features/map/types';
import { loadGoogleMapsScript } from '@/features/map/utils';
import { MapViewer, type MapViewerHandle } from '@/features/map/components/MapViewer';
import { useMapPins } from '@/features/map/queries/useMapPins';
import { DEV_MOCK_MAP_PINS } from '@/features/map/constants/devMockMapPins';
import { PinListSheet } from '@/features/pin/components/PinListSheet';
import type { PinSearchPlace, PlaceInfo } from '@/features/pin/types';
import BookmarkIcon from '@/assets/icons/bookmark.svg?react';
Expand Down Expand Up @@ -54,6 +56,13 @@ const MapPage: React.FC<MapPageProps> = ({ selectedMapPlace, onClearMapPlace })
);
const [currentLocation, setCurrentLocation] = useState<MapCoordinate | null>(null);
const [registrationToast, setRegistrationToast] = useState<RegistrationToast | null>(null);
const [viewport, setViewport] = useState<MapViewport | null>(null);
const [selectedMapPinId, setSelectedMapPinId] = useState<string | null>(null);
const { data: mapPinsData } = useMapPins(viewport);
const mapPins =
import.meta.env.DEV && mapPinsData !== undefined && mapPinsData.pins.length === 0
? DEV_MOCK_MAP_PINS
: (mapPinsData?.pins ?? []);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
// develop 방식: selectedMapPlace prop으로 장소 결과 관리
const placeResults = useMemo<MapPlace[]>(
() => (selectedMapPlace ? [selectedMapPlace] : []),
Expand Down Expand Up @@ -225,10 +234,12 @@ const MapPage: React.FC<MapPageProps> = ({ selectedMapPlace, onClearMapPlace })
zoom={zoom}
placeResults={placeResults}
selectedPlaceId={selectedPlaceId}
mapPins={[]}
selectedMapPinId={null}
mapPins={mapPins}
selectedMapPinId={selectedMapPinId}
onZoomChanged={handleZoomChange}
onCurrentLocationChanged={setCurrentLocation}
onViewportChanged={setViewport}
onSelectMapPin={setSelectedMapPinId}
/>
</div>
);
Expand Down
Loading