feat(catalog): focus map during quote search
All checks were successful
Build Docker Image / build (push) Successful in 4m47s

This commit is contained in:
Ruslan Bakiev
2026-02-06 20:07:43 +07:00
parent 2d85e7187e
commit aa7790f45e
2 changed files with 68 additions and 4 deletions

View File

@@ -18,7 +18,7 @@
:map-id="mapId" :map-id="mapId"
:items="isInfoMode ? [] : (useServerClustering ? [] : itemsWithCoords)" :items="isInfoMode ? [] : (useServerClustering ? [] : itemsWithCoords)"
:clustered-points="isInfoMode ? [] : (useServerClustering && !useTypedClusters ? clusteredNodes : [])" :clustered-points="isInfoMode ? [] : (useServerClustering && !useTypedClusters ? clusteredNodes : [])"
:clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)" :clustered-points-by-type="isInfoMode ? undefined : (useServerClustering && useTypedClusters ? clusteredPointsByType : undefined)"
:use-server-clustering="useServerClustering && !isInfoMode" :use-server-clustering="useServerClustering && !isInfoMode"
:point-color="activePointColor" :point-color="activePointColor"
:entity-type="activeEntityType" :entity-type="activeEntityType"
@@ -255,6 +255,7 @@ const props = withDefaults(defineProps<{
showPanel?: boolean showPanel?: boolean
filterByBounds?: boolean filterByBounds?: boolean
infoLoading?: boolean infoLoading?: boolean
forceInfoMode?: boolean
panelWidth?: string panelWidth?: string
hideViewToggle?: boolean hideViewToggle?: boolean
relatedPoints?: Array<{ relatedPoints?: Array<{
@@ -275,6 +276,7 @@ const props = withDefaults(defineProps<{
showPanel: false, showPanel: false,
filterByBounds: false, filterByBounds: false,
infoLoading: false, infoLoading: false,
forceInfoMode: false,
panelWidth: 'w-96', panelWidth: 'w-96',
hideViewToggle: false, hideViewToggle: false,
relatedPoints: () => [] relatedPoints: () => []
@@ -364,7 +366,7 @@ const selectedMapItem = ref<MapItem | null>(null)
const mobilePanelExpanded = ref(false) const mobilePanelExpanded = ref(false)
// Info mode - when relatedPoints are present, hide clusters and show only related points // Info mode - when relatedPoints are present, hide clusters and show only related points
const isInfoMode = computed(() => props.relatedPoints && props.relatedPoints.length > 0) const isInfoMode = computed(() => props.forceInfoMode || (props.relatedPoints && props.relatedPoints.length > 0))
// Hovered item with coordinates for map highlight // Hovered item with coordinates for map highlight
const hoveredItem = computed(() => { const hoveredItem = computed(() => {

View File

@@ -14,7 +14,9 @@
:show-panel="showPanel && !kycSheetUuid" :show-panel="showPanel && !kycSheetUuid"
:filter-by-bounds="filterByBounds" :filter-by-bounds="filterByBounds"
:related-points="relatedPoints" :related-points="relatedPoints"
:info-loading="isInfoLoading" :info-loading="mapInfoLoading"
:force-info-mode="forceInfoMode"
:hide-view-toggle="hideViewToggle"
@select="onMapSelect" @select="onMapSelect"
@bounds-change="onBoundsChange" @bounds-change="onBoundsChange"
@update:filter-by-bounds="$event ? setBoundsInUrl(currentMapBounds) : clearBoundsFromUrl()" @update:filter-by-bounds="$event ? setBoundsInUrl(currentMapBounds) : clearBoundsFromUrl()"
@@ -131,6 +133,7 @@ const toMapItems = <T extends { uuid?: string | null; name?: string | null; lati
// Current selection items for hover highlighting on map // Current selection items for hover highlighting on map
const currentSelectionItems = computed((): MapItemWithCoords[] => { const currentSelectionItems = computed((): MapItemWithCoords[] => {
if (showQuoteResults.value) return []
if (selectMode.value === 'product') return [] // Products don't have coordinates if (selectMode.value === 'product') return [] // Products don't have coordinates
if (selectMode.value === 'hub') return toMapItems(filteredHubs.value) if (selectMode.value === 'hub') return toMapItems(filteredHubs.value)
if (selectMode.value === 'supplier') return toMapItems(filteredSuppliers.value) if (selectMode.value === 'supplier') return toMapItems(filteredSuppliers.value)
@@ -340,7 +343,7 @@ watch(infoProduct, async (productUuid) => {
}) })
// Related points for Info mode (shown on map) - show current entity + all related entities // Related points for Info mode (shown on map) - show current entity + all related entities
const relatedPoints = computed(() => { const infoRelatedPoints = computed(() => {
if (!infoId.value) return [] if (!infoId.value) return []
const points: Array<{ const points: Array<{
@@ -394,6 +397,50 @@ const relatedPoints = computed(() => {
return points return points
}) })
// Related points for Quote mode (shown on map)
const searchHubPoint = ref<MapItemWithCoords | null>(null)
const searchOfferPoints = computed(() =>
offers.value
.filter((offer) => offer.latitude != null && offer.longitude != null)
.map((offer) => ({
uuid: offer.uuid,
name: offer.productName || '',
latitude: Number(offer.latitude),
longitude: Number(offer.longitude),
type: 'offer' as const
}))
)
const searchRelatedPoints = computed(() => {
const points: Array<{
uuid: string
name: string
latitude: number
longitude: number
type: 'hub' | 'supplier' | 'offer'
}> = []
if (searchHubPoint.value) {
points.push({
uuid: searchHubPoint.value.uuid,
name: searchHubPoint.value.name,
latitude: searchHubPoint.value.latitude,
longitude: searchHubPoint.value.longitude,
type: 'hub'
})
}
searchOfferPoints.value.forEach((point) => points.push(point))
return points
})
const relatedPoints = computed(() => {
if (infoId.value) return infoRelatedPoints.value
if (showQuoteResults.value) return searchRelatedPoints.value
return []
})
// Offers data for quote results // Offers data for quote results
const offers = ref<QuoteOffer[]>([]) const offers = ref<QuoteOffer[]>([])
const quoteCalculations = ref<QuoteCalculation[]>([]) const quoteCalculations = ref<QuoteCalculation[]>([])
@@ -420,6 +467,13 @@ const isInfoLoading = computed(() =>
infoLoading.value || isLoadingProducts.value || isLoadingHubs.value || isLoadingSuppliers.value || isLoadingOffers.value infoLoading.value || isLoadingProducts.value || isLoadingHubs.value || isLoadingSuppliers.value || isLoadingOffers.value
) )
const mapInfoLoading = computed(() =>
isInfoLoading.value || (showQuoteResults.value && offersLoading.value)
)
const forceInfoMode = computed(() => showQuoteResults.value)
const hideViewToggle = computed(() => showQuoteResults.value)
// Show panel when selecting OR when showing info OR when showing quote results // Show panel when selecting OR when showing info OR when showing quote results
const showPanel = computed(() => { const showPanel = computed(() => {
return selectMode.value !== null || infoId.value !== null || showQuoteResults.value return selectMode.value !== null || infoId.value !== null || showQuoteResults.value
@@ -581,6 +635,7 @@ const onSearch = async () => {
offersLoading.value = true offersLoading.value = true
showQuoteResults.value = true showQuoteResults.value = true
searchHubPoint.value = null
try { try {
// Prefer geo-based offers with routes when hub + product are selected // Prefer geo-based offers with routes when hub + product are selected
@@ -588,6 +643,12 @@ const onSearch = async () => {
const hubData = await execute(GetNodeDocument, { uuid: hubId.value }, 'public', 'geo') const hubData = await execute(GetNodeDocument, { uuid: hubId.value }, 'public', 'geo')
const hub = hubData?.node const hub = hubData?.node
if (hub?.latitude != null && hub?.longitude != null) { if (hub?.latitude != null && hub?.longitude != null) {
searchHubPoint.value = {
uuid: hub.uuid,
name: hub.name || hub.uuid,
latitude: Number(hub.latitude),
longitude: Number(hub.longitude)
}
try { try {
const calcData = await execute( const calcData = await execute(
QuoteCalculationsDocument, QuoteCalculationsDocument,
@@ -647,6 +708,7 @@ const onSearch = async () => {
quoteCalculations.value = [] quoteCalculations.value = []
} }
} else { } else {
searchHubPoint.value = null
const vars: GetOffersQueryVariables = {} const vars: GetOffersQueryVariables = {}
if (productId.value) vars.productUuid = productId.value if (productId.value) vars.productUuid = productId.value
if (supplierId.value) vars.teamUuid = supplierId.value if (supplierId.value) vars.teamUuid = supplierId.value