feat: 네이버 지도 연동 (스팟 마커)
- 네이버 지도 JS SDK 동적 로더(싱글턴) + @types/navermaps 타입 - NaverMap 컴포넌트: 스팟 실좌표 마커, 클릭 시 스팟 선택/정보창, 선택 시 중심 이동 - HomePage 지도 자리를 네이버 지도로 교체, 마커 선택 → 해당 스팟 한줄평/메이트 로드 - 키(VITE_NAVER_MAP_CLIENT_ID) 미설정 시 폴백 처리 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+15
-17
@@ -1,13 +1,8 @@
|
||||
<template>
|
||||
<q-page class="q-pa-md">
|
||||
<!-- 지도 영역 (추후 네이버/카카오 지도 SDK 연동 자리) -->
|
||||
<q-card flat bordered class="map-placeholder flex flex-center q-mb-md">
|
||||
<div class="text-center text-grey-6">
|
||||
<q-icon name="map" size="48px" color="secondary" />
|
||||
<div class="q-mt-sm text-caption">
|
||||
{{ currentSpot ? currentSpot.name : '스팟 불러오는 중…' }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 네이버 지도: 스팟 마커 표시, 마커 클릭 시 해당 스팟 선택 -->
|
||||
<q-card flat bordered class="q-mb-md overflow-hidden">
|
||||
<NaverMap :spots="spots" :selected-id="currentSpot?.id ?? null" @select="onSelectSpot" />
|
||||
</q-card>
|
||||
|
||||
<!-- 로딩 / 에러 -->
|
||||
@@ -80,10 +75,12 @@ import { spotsApi, type Mate, type Review, type Spot } from '@/api/spots'
|
||||
import { matchesApi } from '@/api/matches'
|
||||
import { ApiError } from '@/api/http'
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import NaverMap from '@/components/NaverMap.vue'
|
||||
|
||||
const $q = useQuasar()
|
||||
const session = useSessionStore()
|
||||
|
||||
const spots = ref<Spot[]>([])
|
||||
const currentSpot = ref<Spot | null>(null)
|
||||
const reviews = ref<Review[]>([])
|
||||
const mates = ref<Mate[]>([])
|
||||
@@ -97,8 +94,8 @@ onMounted(load)
|
||||
async function load() {
|
||||
loadError.value = false
|
||||
try {
|
||||
const spots = await spotsApi.list()
|
||||
currentSpot.value = spots[0] ?? null
|
||||
spots.value = await spotsApi.list()
|
||||
currentSpot.value = spots.value[0] ?? null
|
||||
if (currentSpot.value) {
|
||||
await refreshSpot(currentSpot.value.id)
|
||||
}
|
||||
@@ -108,6 +105,14 @@ async function load() {
|
||||
}
|
||||
}
|
||||
|
||||
async function onSelectSpot(spotId: number) {
|
||||
const spot = spots.value.find((s) => s.id === spotId)
|
||||
if (!spot) return
|
||||
currentSpot.value = spot
|
||||
checkedIn.value = false
|
||||
await refreshSpot(spotId)
|
||||
}
|
||||
|
||||
async function refreshSpot(spotId: number) {
|
||||
const [r, m] = await Promise.all([spotsApi.reviews(spotId), spotsApi.mates(spotId)])
|
||||
reviews.value = r
|
||||
@@ -147,10 +152,3 @@ function notifyError(e: unknown) {
|
||||
$q.notify({ color: 'negative', message, icon: 'error', position: 'top' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.map-placeholder {
|
||||
height: 240px;
|
||||
background: linear-gradient(160deg, #eaf5fe 0%, #d7ecfb 100%);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user