Add map improvements: hover highlight, fitBounds, search checkbox
All checks were successful
Build Docker Image / build (push) Successful in 5m45s
All checks were successful
Build Docker Image / build (push) Successful in 5m45s
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
|
||||
<Stack gap="3">
|
||||
<div
|
||||
v-for="item in items"
|
||||
v-for="item in displayItems"
|
||||
:key="item.uuid"
|
||||
:class="{ 'ring-2 ring-primary rounded-lg': item.uuid === selectedId }"
|
||||
@click="onItemClick(item)"
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<slot name="pagination" />
|
||||
|
||||
<Stack v-if="items.length === 0" align="center" gap="2">
|
||||
<Stack v-if="displayItems.length === 0" align="center" gap="2">
|
||||
<slot name="empty">
|
||||
<Text tone="muted">{{ $t('common.values.not_available') }}</Text>
|
||||
</slot>
|
||||
@@ -48,6 +48,11 @@
|
||||
<!-- Right: Map (fixed position) -->
|
||||
<div class="w-3/5 relative">
|
||||
<div class="fixed right-6 w-[calc(60%-3rem)] rounded-lg overflow-hidden" :class="[mapTopClass, mapHeightClass]">
|
||||
<!-- Search with map checkbox -->
|
||||
<label class="absolute top-4 left-4 z-10 bg-white/90 backdrop-blur px-3 py-2 rounded-lg shadow flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="searchWithMap" class="checkbox checkbox-sm" />
|
||||
<span class="text-sm">{{ $t('catalogMap.searchWithMap') }}</span>
|
||||
</label>
|
||||
<ClientOnly>
|
||||
<CatalogMap
|
||||
ref="mapRef"
|
||||
@@ -57,6 +62,7 @@
|
||||
:use-server-clustering="useServerClustering"
|
||||
:point-color="pointColor"
|
||||
:hovered-item-id="hoveredId"
|
||||
:hovered-item="hoveredItem"
|
||||
@select-item="onMapSelect"
|
||||
@bounds-change="onBoundsChange"
|
||||
/>
|
||||
@@ -74,7 +80,7 @@
|
||||
|
||||
<Stack gap="3">
|
||||
<div
|
||||
v-for="item in items"
|
||||
v-for="item in displayItems"
|
||||
:key="item.uuid"
|
||||
:class="{ 'ring-2 ring-primary rounded-lg': item.uuid === selectedId }"
|
||||
@click="onItemClick(item)"
|
||||
@@ -87,7 +93,7 @@
|
||||
|
||||
<slot name="pagination" />
|
||||
|
||||
<Stack v-if="items.length === 0" align="center" gap="2">
|
||||
<Stack v-if="displayItems.length === 0" align="center" gap="2">
|
||||
<slot name="empty">
|
||||
<Text tone="muted">{{ $t('common.values.not_available') }}</Text>
|
||||
</slot>
|
||||
@@ -95,7 +101,12 @@
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<div class="flex-1" v-show="mobileView === 'map'">
|
||||
<div class="flex-1 relative" v-show="mobileView === 'map'">
|
||||
<!-- Search with map checkbox (mobile) -->
|
||||
<label class="absolute top-4 left-4 z-10 bg-white/90 backdrop-blur px-3 py-2 rounded-lg shadow flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="searchWithMap" class="checkbox checkbox-sm" />
|
||||
<span class="text-sm">{{ $t('catalogMap.searchWithMap') }}</span>
|
||||
</label>
|
||||
<ClientOnly>
|
||||
<CatalogMap
|
||||
ref="mobileMapRef"
|
||||
@@ -105,6 +116,7 @@
|
||||
:use-server-clustering="useServerClustering"
|
||||
:point-color="pointColor"
|
||||
:hovered-item-id="hoveredId"
|
||||
:hovered-item="hoveredItem"
|
||||
@select-item="onMapSelect"
|
||||
@bounds-change="onBoundsChange"
|
||||
/>
|
||||
@@ -207,12 +219,37 @@ const emit = defineEmits<{
|
||||
// Server-side clustering
|
||||
const { clusteredNodes, fetchClusters } = useClusteredNodes()
|
||||
|
||||
// Search with map checkbox
|
||||
const searchWithMap = ref(false)
|
||||
const currentBounds = ref<MapBounds | null>(null)
|
||||
|
||||
const onBoundsChange = (bounds: MapBounds) => {
|
||||
currentBounds.value = bounds
|
||||
if (props.useServerClustering) {
|
||||
fetchClusters(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
// Filtered items when searchWithMap is enabled
|
||||
const displayItems = computed(() => {
|
||||
if (!searchWithMap.value || !currentBounds.value) return props.items
|
||||
return props.items.filter(item => {
|
||||
if (item.latitude == null || item.longitude == null) return false
|
||||
const { west, east, north, south } = currentBounds.value!
|
||||
const lng = Number(item.longitude)
|
||||
const lat = Number(item.latitude)
|
||||
return lng >= west && lng <= east && lat >= south && lat <= north
|
||||
})
|
||||
})
|
||||
|
||||
// Hovered item with coordinates for map highlight
|
||||
const hoveredItem = computed(() => {
|
||||
if (!props.hoveredId) return null
|
||||
const item = props.items.find(i => i.uuid === props.hoveredId)
|
||||
if (!item?.latitude || !item?.longitude) return null
|
||||
return { latitude: Number(item.latitude), longitude: Number(item.longitude) }
|
||||
})
|
||||
|
||||
// Use mapItems if provided, otherwise fall back to items
|
||||
const itemsForMap = computed(() => props.mapItems || props.items)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user