feat(catalog): filter map clusters by chips
All checks were successful
Build Docker Image / build (push) Successful in 5m1s

This commit is contained in:
Ruslan Bakiev
2026-02-07 08:35:22 +07:00
parent aa7790f45e
commit 755a92d194
7 changed files with 89 additions and 103 deletions

View File

@@ -71,6 +71,7 @@
<!-- View mode toggle -->
<div class="flex gap-1 glass-bright rounded-full p-1">
<button
v-if="showOffersToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium transition-colors"
:class="mapViewMode === 'offers' ? 'bg-white/20 text-white' : 'text-white/70 hover:text-white hover:bg-white/10'"
@click="setMapViewMode('offers')"
@@ -81,6 +82,7 @@
{{ $t('catalog.views.offers') }}
</button>
<button
v-if="showHubsToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium transition-colors"
:class="mapViewMode === 'hubs' ? 'bg-white/20 text-white' : 'text-white/70 hover:text-white hover:bg-white/10'"
@click="setMapViewMode('hubs')"
@@ -91,6 +93,7 @@
{{ $t('catalog.views.hubs') }}
</button>
<button
v-if="showSuppliersToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium transition-colors"
:class="mapViewMode === 'suppliers' ? 'bg-white/20 text-white' : 'text-white/70 hover:text-white hover:bg-white/10'"
@click="setMapViewMode('suppliers')"
@@ -132,6 +135,7 @@
<!-- Mobile view toggle - hide in info mode or when hideViewToggle -->
<div v-if="!isInfoMode && !hideViewToggle" class="flex gap-1 glass-bright rounded-full p-1">
<button
v-if="showOffersToggle"
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors"
:class="mapViewMode === 'offers' ? 'bg-white/20' : 'hover:bg-white/10'"
@click="setMapViewMode('offers')"
@@ -141,6 +145,7 @@
</span>
</button>
<button
v-if="showHubsToggle"
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors"
:class="mapViewMode === 'hubs' ? 'bg-white/20' : 'hover:bg-white/10'"
@click="setMapViewMode('hubs')"
@@ -150,6 +155,7 @@
</span>
</button>
<button
v-if="showSuppliersToggle"
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors"
:class="mapViewMode === 'suppliers' ? 'bg-white/20' : 'hover:bg-white/10'"
@click="setMapViewMode('suppliers')"
@@ -258,6 +264,12 @@ const props = withDefaults(defineProps<{
forceInfoMode?: boolean
panelWidth?: string
hideViewToggle?: boolean
showOffersToggle?: boolean
showHubsToggle?: boolean
showSuppliersToggle?: boolean
clusterProductUuid?: string
clusterHubUuid?: string
clusterSupplierUuid?: string
relatedPoints?: Array<{
uuid: string
name: string
@@ -279,6 +291,12 @@ const props = withDefaults(defineProps<{
forceInfoMode: false,
panelWidth: 'w-96',
hideViewToggle: false,
showOffersToggle: true,
showHubsToggle: true,
showSuppliersToggle: true,
clusterProductUuid: undefined,
clusterHubUuid: undefined,
clusterSupplierUuid: undefined,
relatedPoints: () => []
})
@@ -291,13 +309,23 @@ const emit = defineEmits<{
const useTypedClusters = computed(() => props.useTypedClusters && props.useServerClustering)
const clusterProductUuid = computed(() => props.clusterProductUuid ?? undefined)
const clusterHubUuid = computed(() => props.clusterHubUuid ?? undefined)
const clusterSupplierUuid = computed(() => props.clusterSupplierUuid ?? undefined)
// Server-side clustering (single-type mode)
const { clusteredNodes, fetchClusters, loading: singleClusterLoading, clearNodes } = useClusteredNodes(undefined, activeClusterNodeType)
const { clusteredNodes, fetchClusters, loading: singleClusterLoading, clearNodes } = useClusteredNodes(
undefined,
activeClusterNodeType,
clusterProductUuid,
clusterHubUuid,
clusterSupplierUuid
)
// Server-side clustering (typed mode)
const offerClusters = useClusteredNodes(undefined, ref('offer'))
const hubClusters = useClusteredNodes(undefined, ref('logistics'))
const supplierClusters = useClusteredNodes(undefined, ref('supplier'))
const offerClusters = useClusteredNodes(undefined, ref('offer'), clusterProductUuid, clusterHubUuid, clusterSupplierUuid)
const hubClusters = useClusteredNodes(undefined, ref('logistics'), clusterProductUuid, clusterHubUuid, clusterSupplierUuid)
const supplierClusters = useClusteredNodes(undefined, ref('supplier'), clusterProductUuid, clusterHubUuid, clusterSupplierUuid)
const clusteredPointsByType = computed(() => ({
offer: offerClusters.clusteredNodes.value,
@@ -341,6 +369,7 @@ const fetchActiveClusters = async () => {
// Refetch clusters when view mode changes
watch(mapViewMode, async () => {
if (!props.useServerClustering) return
if (isInfoMode.value) return
if (useTypedClusters.value) {
clearInactiveClusters(activeClusterType.value)
if (currentBounds.value) {
@@ -356,6 +385,17 @@ watch(mapViewMode, async () => {
}
})
watch([clusterProductUuid, clusterHubUuid, clusterSupplierUuid], async () => {
if (!props.useServerClustering) return
if (isInfoMode.value) return
if (!currentBounds.value) return
if (useTypedClusters.value) {
await fetchActiveClusters()
return
}
await fetchClusters(currentBounds.value)
})
// Map refs
const mapRef = ref<{ flyTo: (lat: number, lng: number, zoom?: number) => void } | null>(null)