feat(catalog): filter map clusters by chips
All checks were successful
Build Docker Image / build (push) Successful in 5m1s
All checks were successful
Build Docker Image / build (push) Successful in 5m1s
This commit is contained in:
@@ -116,13 +116,6 @@
|
||||
:key="product.uuid ?? index"
|
||||
class="relative group"
|
||||
>
|
||||
<button
|
||||
v-if="product.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="emit('pin', 'product', product)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<ProductCard
|
||||
:product="product"
|
||||
compact
|
||||
@@ -191,13 +184,6 @@
|
||||
:key="supplier.uuid ?? index"
|
||||
class="relative group"
|
||||
>
|
||||
<button
|
||||
v-if="supplier.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="emit('pin', 'supplier', supplier)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<SupplierCard
|
||||
:supplier="supplier"
|
||||
selectable
|
||||
@@ -235,13 +221,6 @@
|
||||
:key="hub.uuid ?? index"
|
||||
class="relative group"
|
||||
>
|
||||
<button
|
||||
v-if="hub.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="emit('pin', 'hub', hub)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<HubCard
|
||||
:hub="hub"
|
||||
:origin="originCoords"
|
||||
@@ -267,13 +246,6 @@
|
||||
:key="hub.uuid ?? index"
|
||||
class="relative group"
|
||||
>
|
||||
<button
|
||||
v-if="hub.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="emit('pin', 'hub', hub)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<HubCard
|
||||
:hub="hub"
|
||||
:origin="originCoords"
|
||||
@@ -286,11 +258,6 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Add to filter button -->
|
||||
<button class="btn btn-primary btn-sm mt-2" @click="emit('add-to-filter')">
|
||||
<Icon name="lucide:filter-plus" size="16" />
|
||||
{{ $t('catalog.info.addToFilter') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,8 +293,6 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits<{
|
||||
'close': []
|
||||
'add-to-filter': []
|
||||
'pin': [type: 'product' | 'supplier' | 'hub', item: { uuid?: string | null; name?: string | null }]
|
||||
'open-info': [type: InfoEntityType, uuid: string]
|
||||
'select-product': [uuid: string | null]
|
||||
'select-offer': [offer: { uuid: string; productUuid?: string | null }]
|
||||
|
||||
@@ -31,13 +31,6 @@
|
||||
@mouseenter="emit('hover', item.uuid ?? null)"
|
||||
@mouseleave="emit('hover', null)"
|
||||
>
|
||||
<button
|
||||
v-if="item.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="onPin(item)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<ProductCard
|
||||
:product="item"
|
||||
selectable
|
||||
@@ -56,13 +49,6 @@
|
||||
@mouseenter="emit('hover', item.uuid ?? null)"
|
||||
@mouseleave="emit('hover', null)"
|
||||
>
|
||||
<button
|
||||
v-if="item.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="onPin(item)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<HubCard
|
||||
:hub="item"
|
||||
selectable
|
||||
@@ -80,13 +66,6 @@
|
||||
@mouseenter="emit('hover', item.uuid ?? null)"
|
||||
@mouseleave="emit('hover', null)"
|
||||
>
|
||||
<button
|
||||
v-if="item.uuid"
|
||||
class="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity bg-black/40 hover:bg-black/60 text-white rounded-full w-6 h-6 flex items-center justify-center"
|
||||
@click.stop="onPin(item)"
|
||||
>
|
||||
<Icon name="lucide:pin" size="12" />
|
||||
</button>
|
||||
<SupplierCard
|
||||
:supplier="item"
|
||||
selectable
|
||||
@@ -129,7 +108,6 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits<{
|
||||
'select': [type: string, item: Item]
|
||||
'pin': [type: string, item: Item]
|
||||
'close': []
|
||||
'load-more': []
|
||||
'hover': [uuid: string | null]
|
||||
@@ -191,10 +169,4 @@ const onSelect = (item: Item) => {
|
||||
emit('select', props.selectMode, item)
|
||||
}
|
||||
}
|
||||
|
||||
const onPin = (item: Item) => {
|
||||
if (props.selectMode && item.uuid) {
|
||||
emit('pin', props.selectMode, item)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -206,9 +206,12 @@ export type QueryAutoRouteArgs = {
|
||||
/** Root query. */
|
||||
export type QueryClusteredNodesArgs = {
|
||||
east: Scalars['Float']['input'];
|
||||
hubUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
nodeType?: InputMaybe<Scalars['String']['input']>;
|
||||
north: Scalars['Float']['input'];
|
||||
productUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
south: Scalars['Float']['input'];
|
||||
supplierUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
transportType?: InputMaybe<Scalars['String']['input']>;
|
||||
west: Scalars['Float']['input'];
|
||||
zoom: Scalars['Int']['input'];
|
||||
@@ -479,6 +482,9 @@ export type GetClusteredNodesQueryVariables = Exact<{
|
||||
zoom: Scalars['Int']['input'];
|
||||
transportType?: InputMaybe<Scalars['String']['input']>;
|
||||
nodeType?: InputMaybe<Scalars['String']['input']>;
|
||||
productUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
hubUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
supplierUuid?: InputMaybe<Scalars['String']['input']>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -594,7 +600,7 @@ export type SuppliersListQueryResult = { __typename?: 'Query', suppliersList?: A
|
||||
|
||||
|
||||
export const GetAutoRouteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAutoRoute"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fromLat"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fromLon"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toLat"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toLon"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"autoRoute"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"fromLat"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fromLat"}}},{"kind":"Argument","name":{"kind":"Name","value":"fromLon"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fromLon"}}},{"kind":"Argument","name":{"kind":"Name","value":"toLat"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toLat"}}},{"kind":"Argument","name":{"kind":"Name","value":"toLon"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toLon"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"distanceKm"}},{"kind":"Field","name":{"kind":"Name","value":"geometry"}}]}}]}}]} as unknown as DocumentNode<GetAutoRouteQueryResult, GetAutoRouteQueryVariables>;
|
||||
export const GetClusteredNodesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetClusteredNodes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"west"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"south"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"east"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"north"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"zoom"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"transportType"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"nodeType"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"clusteredNodes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"west"},"value":{"kind":"Variable","name":{"kind":"Name","value":"west"}}},{"kind":"Argument","name":{"kind":"Name","value":"south"},"value":{"kind":"Variable","name":{"kind":"Name","value":"south"}}},{"kind":"Argument","name":{"kind":"Name","value":"east"},"value":{"kind":"Variable","name":{"kind":"Name","value":"east"}}},{"kind":"Argument","name":{"kind":"Name","value":"north"},"value":{"kind":"Variable","name":{"kind":"Name","value":"north"}}},{"kind":"Argument","name":{"kind":"Name","value":"zoom"},"value":{"kind":"Variable","name":{"kind":"Name","value":"zoom"}}},{"kind":"Argument","name":{"kind":"Name","value":"transportType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"transportType"}}},{"kind":"Argument","name":{"kind":"Name","value":"nodeType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"nodeType"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"count"}},{"kind":"Field","name":{"kind":"Name","value":"expansionZoom"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<GetClusteredNodesQueryResult, GetClusteredNodesQueryVariables>;
|
||||
export const GetClusteredNodesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetClusteredNodes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"west"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"south"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"east"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"north"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"zoom"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"transportType"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"nodeType"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"productUuid"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"hubUuid"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"supplierUuid"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"clusteredNodes"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"west"},"value":{"kind":"Variable","name":{"kind":"Name","value":"west"}}},{"kind":"Argument","name":{"kind":"Name","value":"south"},"value":{"kind":"Variable","name":{"kind":"Name","value":"south"}}},{"kind":"Argument","name":{"kind":"Name","value":"east"},"value":{"kind":"Variable","name":{"kind":"Name","value":"east"}}},{"kind":"Argument","name":{"kind":"Name","value":"north"},"value":{"kind":"Variable","name":{"kind":"Name","value":"north"}}},{"kind":"Argument","name":{"kind":"Name","value":"zoom"},"value":{"kind":"Variable","name":{"kind":"Name","value":"zoom"}}},{"kind":"Argument","name":{"kind":"Name","value":"transportType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"transportType"}}},{"kind":"Argument","name":{"kind":"Name","value":"nodeType"},"value":{"kind":"Variable","name":{"kind":"Name","value":"nodeType"}}},{"kind":"Argument","name":{"kind":"Name","value":"productUuid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"productUuid"}}},{"kind":"Argument","name":{"kind":"Name","value":"hubUuid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"hubUuid"}}},{"kind":"Argument","name":{"kind":"Name","value":"supplierUuid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"supplierUuid"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"count"}},{"kind":"Field","name":{"kind":"Name","value":"expansionZoom"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<GetClusteredNodesQueryResult, GetClusteredNodesQueryVariables>;
|
||||
export const GetHubCountriesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetHubCountries"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hubCountries"}}]}}]} as unknown as DocumentNode<GetHubCountriesQueryResult, GetHubCountriesQueryVariables>;
|
||||
export const GetNodeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetNode"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"uuid"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"uuid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"uuid"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uuid"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"country"}},{"kind":"Field","name":{"kind":"Name","value":"countryCode"}},{"kind":"Field","name":{"kind":"Name","value":"transportTypes"}}]}}]}}]} as unknown as DocumentNode<GetNodeQueryResult, GetNodeQueryVariables>;
|
||||
export const GetRailRouteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetRailRoute"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fromLat"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fromLon"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toLat"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"toLon"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"railRoute"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"fromLat"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fromLat"}}},{"kind":"Argument","name":{"kind":"Name","value":"fromLon"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fromLon"}}},{"kind":"Argument","name":{"kind":"Name","value":"toLat"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toLat"}}},{"kind":"Argument","name":{"kind":"Name","value":"toLon"},"value":{"kind":"Variable","name":{"kind":"Name","value":"toLon"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"distanceKm"}},{"kind":"Field","name":{"kind":"Name","value":"geometry"}}]}}]}}]} as unknown as DocumentNode<GetRailRouteQueryResult, GetRailRouteQueryVariables>;
|
||||
|
||||
@@ -11,7 +11,10 @@ export interface MapBounds {
|
||||
|
||||
export function useClusteredNodes(
|
||||
transportType?: Ref<string | undefined>,
|
||||
nodeType?: Ref<string | undefined>
|
||||
nodeType?: Ref<string | undefined>,
|
||||
productUuid?: Ref<string | undefined>,
|
||||
hubUuid?: Ref<string | undefined>,
|
||||
supplierUuid?: Ref<string | undefined>
|
||||
) {
|
||||
const { client } = useApolloClient('publicGeo')
|
||||
|
||||
@@ -30,7 +33,10 @@ export function useClusteredNodes(
|
||||
north: bounds.north,
|
||||
zoom: Math.floor(bounds.zoom),
|
||||
transportType: transportType?.value,
|
||||
nodeType: nodeType?.value
|
||||
nodeType: nodeType?.value,
|
||||
productUuid: productUuid?.value,
|
||||
hubUuid: hubUuid?.value,
|
||||
supplierUuid: supplierUuid?.value
|
||||
},
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
:info-loading="mapInfoLoading"
|
||||
:force-info-mode="forceInfoMode"
|
||||
:hide-view-toggle="hideViewToggle"
|
||||
:show-offers-toggle="showOffersToggle"
|
||||
:show-hubs-toggle="showHubsToggle"
|
||||
:show-suppliers-toggle="showSuppliersToggle"
|
||||
:cluster-product-uuid="clusterProductUuid"
|
||||
:cluster-hub-uuid="clusterHubUuid"
|
||||
:cluster-supplier-uuid="clusterSupplierUuid"
|
||||
@select="onMapSelect"
|
||||
@bounds-change="onBoundsChange"
|
||||
@update:filter-by-bounds="$event ? setBoundsInUrl(currentMapBounds) : clearBoundsFromUrl()"
|
||||
@@ -34,7 +40,6 @@
|
||||
:loading-more="selectionLoadingMore"
|
||||
:has-more="selectionHasMore && !filterByBounds"
|
||||
@select="onSelectItem"
|
||||
@pin="onPinItem"
|
||||
@close="onClosePanel"
|
||||
@load-more="onLoadMore"
|
||||
@hover="onHoverItem"
|
||||
@@ -57,8 +62,6 @@
|
||||
:loading-suppliers="isLoadingSuppliers"
|
||||
:loading-offers="isLoadingOffers"
|
||||
@close="onInfoClose"
|
||||
@add-to-filter="onInfoAddToFilter"
|
||||
@pin="onPinItem"
|
||||
@open-info="onInfoOpenRelated"
|
||||
@select-product="onInfoSelectProduct"
|
||||
@select-offer="onSelectOffer"
|
||||
@@ -312,6 +315,16 @@ watch(productId, (newProductId) => {
|
||||
setSupplierProductFilter(newProductId || null)
|
||||
}, { immediate: true })
|
||||
|
||||
// If a filter locks a view type, switch away from that view
|
||||
watch([hubId, supplierId], ([newHubId, newSupplierId]) => {
|
||||
if (newHubId && mapViewMode.value === 'hubs') {
|
||||
setMapViewMode('offers')
|
||||
}
|
||||
if (newSupplierId && mapViewMode.value === 'suppliers') {
|
||||
setMapViewMode('offers')
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
// Apply bounds filter when "filter by map bounds" is enabled
|
||||
// Only watch URL bounds - currentMapBounds changes too often (every map move)
|
||||
watch([filterByBounds, urlBounds], ([enabled, urlB]) => {
|
||||
@@ -474,6 +487,14 @@ const mapInfoLoading = computed(() =>
|
||||
const forceInfoMode = computed(() => showQuoteResults.value)
|
||||
const hideViewToggle = computed(() => showQuoteResults.value)
|
||||
|
||||
const showOffersToggle = computed(() => true)
|
||||
const showHubsToggle = computed(() => !hubId.value)
|
||||
const showSuppliersToggle = computed(() => !supplierId.value)
|
||||
|
||||
const clusterProductUuid = computed(() => productId.value || undefined)
|
||||
const clusterHubUuid = computed(() => hubId.value || undefined)
|
||||
const clusterSupplierUuid = computed(() => supplierId.value || undefined)
|
||||
|
||||
// Show panel when selecting OR when showing info OR when showing quote results
|
||||
const showPanel = computed(() => {
|
||||
return selectMode.value !== null || infoId.value !== null || showQuoteResults.value
|
||||
@@ -564,12 +585,6 @@ const onSelectItem = (type: string, item: { uuid?: string | null; name?: string
|
||||
}
|
||||
}
|
||||
|
||||
const onPinItem = (type: string, item: { uuid?: string | null; name?: string | null }) => {
|
||||
if (item.uuid && item.name) {
|
||||
selectItem(type, item.uuid, item.name)
|
||||
}
|
||||
}
|
||||
|
||||
// Close panel (cancel select mode)
|
||||
const onClosePanel = () => {
|
||||
cancelSelect()
|
||||
@@ -581,30 +596,6 @@ const onInfoClose = () => {
|
||||
clearInfo()
|
||||
}
|
||||
|
||||
const onInfoAddToFilter = () => {
|
||||
if (!infoId.value || !entity.value) return
|
||||
const { type, uuid } = infoId.value
|
||||
|
||||
// For offers, add the product AND hub to filter
|
||||
if (type === 'offer') {
|
||||
if (entity.value.productUuid) {
|
||||
const productName = entity.value.productName || entity.value.name || uuid.slice(0, 8) + '...'
|
||||
selectItem('product', entity.value.productUuid, productName)
|
||||
}
|
||||
// Also add hub (location) to filter if available
|
||||
if (entity.value.locationUuid) {
|
||||
const hubName = entity.value.locationName || entity.value.locationUuid.slice(0, 8) + '...'
|
||||
selectItem('hub', entity.value.locationUuid, hubName)
|
||||
}
|
||||
} else {
|
||||
// For hubs and suppliers, add directly
|
||||
const name = entity.value.name || uuid.slice(0, 8) + '...'
|
||||
selectItem(type, uuid, name)
|
||||
}
|
||||
|
||||
closeInfo()
|
||||
clearInfo()
|
||||
}
|
||||
|
||||
const onInfoOpenRelated = (type: 'hub' | 'supplier' | 'offer', uuid: string) => {
|
||||
openInfo(type, uuid)
|
||||
|
||||
@@ -6,6 +6,9 @@ query GetClusteredNodes(
|
||||
$zoom: Int!
|
||||
$transportType: String
|
||||
$nodeType: String
|
||||
$productUuid: String
|
||||
$hubUuid: String
|
||||
$supplierUuid: String
|
||||
) {
|
||||
clusteredNodes(
|
||||
west: $west
|
||||
@@ -15,6 +18,9 @@ query GetClusteredNodes(
|
||||
zoom: $zoom
|
||||
transportType: $transportType
|
||||
nodeType: $nodeType
|
||||
productUuid: $productUuid
|
||||
hubUuid: $hubUuid
|
||||
supplierUuid: $supplierUuid
|
||||
) {
|
||||
id
|
||||
latitude
|
||||
|
||||
Reference in New Issue
Block a user