Fix InfoPanel map: hide toggle, show current entity, auto-center
All checks were successful
Build Docker Image / build (push) Successful in 4m18s
All checks were successful
Build Docker Image / build (push) Successful in 4m18s
- Hide view mode toggle (offers/hubs/suppliers) when in InfoPanel mode - Add current entity to relatedPoints so it's visible on the map - Auto-fit map bounds to show all points (current + related) in InfoPanel mode
This commit is contained in:
@@ -693,13 +693,26 @@ watch(() => props.hoveredItem, () => {
|
|||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
// Update related points layer when relatedPoints changes
|
// Update related points layer when relatedPoints changes + fit bounds
|
||||||
watch(() => props.relatedPoints, () => {
|
watch(() => props.relatedPoints, (points) => {
|
||||||
if (!mapRef.value || !mapInitialized.value) return
|
if (!mapRef.value || !mapInitialized.value) return
|
||||||
|
|
||||||
|
// Update the source data
|
||||||
const source = mapRef.value.getSource(relatedSourceId.value) as mapboxgl.GeoJSONSource | undefined
|
const source = mapRef.value.getSource(relatedSourceId.value) as mapboxgl.GeoJSONSource | undefined
|
||||||
if (source) {
|
if (source) {
|
||||||
source.setData(relatedPointsGeoJson.value)
|
source.setData(relatedPointsGeoJson.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fit bounds to show all related points (Info mode)
|
||||||
|
if (points && points.length > 0) {
|
||||||
|
const bounds = new LngLatBounds()
|
||||||
|
points.forEach(p => {
|
||||||
|
bounds.extend([p.longitude, p.latitude])
|
||||||
|
})
|
||||||
|
if (!bounds.isEmpty()) {
|
||||||
|
mapRef.value.fitBounds(bounds, { padding: 80, maxZoom: 12 })
|
||||||
|
}
|
||||||
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
// Watch for pointColor or entityType changes - update colors and icons
|
// Watch for pointColor or entityType changes - update colors and icons
|
||||||
|
|||||||
@@ -64,8 +64,8 @@
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|
||||||
<!-- View toggle (top RIGHT overlay, below header) -->
|
<!-- View toggle (top RIGHT overlay, below header) - hide in info mode -->
|
||||||
<div class="absolute top-[116px] right-4 z-20 hidden lg:flex items-center gap-2">
|
<div v-if="!isInfoMode" class="absolute top-[116px] right-4 z-20 hidden lg:flex items-center gap-2">
|
||||||
<!-- View mode toggle -->
|
<!-- View mode toggle -->
|
||||||
<div class="flex gap-1 bg-black/30 backdrop-blur-md rounded-lg p-1 border border-white/10">
|
<div class="flex gap-1 bg-black/30 backdrop-blur-md rounded-lg p-1 border border-white/10">
|
||||||
<button
|
<button
|
||||||
@@ -126,8 +126,8 @@
|
|||||||
<span>{{ $t('catalog.list') }}</span>
|
<span>{{ $t('catalog.list') }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Mobile view toggle -->
|
<!-- Mobile view toggle - hide in info mode -->
|
||||||
<div class="flex gap-1 bg-black/30 backdrop-blur-md rounded-lg p-1 border border-white/10">
|
<div v-if="!isInfoMode" class="flex gap-1 bg-black/30 backdrop-blur-md rounded-lg p-1 border border-white/10">
|
||||||
<button
|
<button
|
||||||
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors"
|
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors"
|
||||||
:class="mapViewMode === 'offers' ? 'bg-white/20' : 'hover:bg-white/10'"
|
:class="mapViewMode === 'offers' ? 'bg-white/20' : 'hover:bg-white/10'"
|
||||||
|
|||||||
@@ -67,9 +67,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { GetOffersDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated'
|
import { GetOffersDocument, GetOfferDocument, type GetOffersQueryVariables, type GetOffersQueryResult } from '~/composables/graphql/public/exchange-generated'
|
||||||
import type { MapBounds } from '~/components/catalog/CatalogMap.vue'
|
import type { MapBounds } from '~/components/catalog/CatalogMap.vue'
|
||||||
|
|
||||||
|
// Offer type from search results
|
||||||
|
type OfferResult = NonNullable<NonNullable<GetOffersQueryResult['getOffers']>[number]>
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'topnav'
|
layout: 'topnav'
|
||||||
})
|
})
|
||||||
@@ -282,7 +285,7 @@ watch(infoProduct, async (productUuid) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Related points for Info mode (shown on map) - show all related entities
|
// Related points for Info mode (shown on map) - show current entity + all related entities
|
||||||
const relatedPoints = computed(() => {
|
const relatedPoints = computed(() => {
|
||||||
if (!infoId.value) return []
|
if (!infoId.value) return []
|
||||||
|
|
||||||
@@ -294,7 +297,18 @@ const relatedPoints = computed(() => {
|
|||||||
type: 'hub' | 'supplier' | 'offer'
|
type: 'hub' | 'supplier' | 'offer'
|
||||||
}> = []
|
}> = []
|
||||||
|
|
||||||
// Add all hubs
|
// Add current entity first (the one we're viewing in InfoPanel)
|
||||||
|
if (entity.value?.latitude && entity.value?.longitude) {
|
||||||
|
points.push({
|
||||||
|
uuid: infoId.value.uuid,
|
||||||
|
name: entity.value.name || '',
|
||||||
|
latitude: Number(entity.value.latitude),
|
||||||
|
longitude: Number(entity.value.longitude),
|
||||||
|
type: infoId.value.type
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all related hubs
|
||||||
relatedHubs.value.forEach(hub => {
|
relatedHubs.value.forEach(hub => {
|
||||||
if (hub.uuid && hub.latitude && hub.longitude) {
|
if (hub.uuid && hub.latitude && hub.longitude) {
|
||||||
points.push({
|
points.push({
|
||||||
@@ -307,7 +321,7 @@ const relatedPoints = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add all suppliers
|
// Add all related suppliers
|
||||||
relatedSuppliers.value.forEach(supplier => {
|
relatedSuppliers.value.forEach(supplier => {
|
||||||
if (supplier.uuid && supplier.latitude && supplier.longitude) {
|
if (supplier.uuid && supplier.latitude && supplier.longitude) {
|
||||||
points.push({
|
points.push({
|
||||||
@@ -324,7 +338,7 @@ const relatedPoints = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Offers data for quote results
|
// Offers data for quote results
|
||||||
const offers = ref<any[]>([])
|
const offers = ref<OfferResult[]>([])
|
||||||
const offersLoading = ref(false)
|
const offersLoading = ref(false)
|
||||||
const showQuoteResults = ref(false)
|
const showQuoteResults = ref(false)
|
||||||
|
|
||||||
@@ -360,8 +374,15 @@ const mapPointColor = computed(() => {
|
|||||||
return entityColors.offer
|
return entityColors.offer
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Map item type from CatalogMap
|
||||||
|
interface MapSelectItem {
|
||||||
|
uuid?: string | null
|
||||||
|
id?: string
|
||||||
|
name?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
// Handle map item selection
|
// Handle map item selection
|
||||||
const onMapSelect = async (item: any) => {
|
const onMapSelect = async (item: MapSelectItem) => {
|
||||||
// Get uuid from item - clusters use 'id', regular items use 'uuid'
|
// Get uuid from item - clusters use 'id', regular items use 'uuid'
|
||||||
const itemId = item.uuid || item.id
|
const itemId = item.uuid || item.id
|
||||||
if (!itemId || itemId.startsWith('cluster-')) return
|
if (!itemId || itemId.startsWith('cluster-')) return
|
||||||
@@ -411,7 +432,7 @@ const onMapSelect = async (item: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle selection from SelectionPanel - add to filter (show badge in search)
|
// Handle selection from SelectionPanel - add to filter (show badge in search)
|
||||||
const onSelectItem = (type: string, item: any) => {
|
const onSelectItem = (type: string, item: { uuid?: string | null; name?: string | null }) => {
|
||||||
if (item.uuid && item.name) {
|
if (item.uuid && item.name) {
|
||||||
selectItem(type, item.uuid, item.name)
|
selectItem(type, item.uuid, item.name)
|
||||||
}
|
}
|
||||||
@@ -470,26 +491,24 @@ const onSearch = async () => {
|
|||||||
showQuoteResults.value = true
|
showQuoteResults.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const vars: any = {}
|
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
|
||||||
if (hubId.value) vars.locationUuid = hubId.value
|
if (hubId.value) vars.locationUuid = hubId.value
|
||||||
|
|
||||||
const data = await execute(GetOffersDocument, vars, 'public', 'exchange')
|
const data = await execute(GetOffersDocument, vars, 'public', 'exchange')
|
||||||
offers.value = data?.getOffers || []
|
offers.value = (data?.getOffers || []).filter((o): o is OfferResult => o !== null)
|
||||||
|
|
||||||
// Update labels from response
|
// Update labels from response
|
||||||
if (offers.value.length > 0) {
|
const first = offers.value[0]
|
||||||
const first = offers.value[0]
|
if (first) {
|
||||||
if (productId.value && first.productName) {
|
if (productId.value && first.productName) {
|
||||||
setLabel('product', productId.value, first.productName)
|
setLabel('product', productId.value, first.productName)
|
||||||
}
|
}
|
||||||
if (hubId.value && first.locationName) {
|
if (hubId.value && first.locationName) {
|
||||||
setLabel('hub', hubId.value, first.locationName)
|
setLabel('hub', hubId.value, first.locationName)
|
||||||
}
|
}
|
||||||
if (supplierId.value && first.teamName) {
|
// Note: teamName not included in GetOffers query, supplier label cannot be updated from offer
|
||||||
setLabel('supplier', supplierId.value, first.teamName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
offersLoading.value = false
|
offersLoading.value = false
|
||||||
@@ -497,7 +516,7 @@ const onSearch = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Select offer - navigate to detail page
|
// Select offer - navigate to detail page
|
||||||
const onSelectOffer = (offer: any) => {
|
const onSelectOffer = (offer: { uuid: string; productUuid?: string | null }) => {
|
||||||
if (offer.uuid && offer.productUuid) {
|
if (offer.uuid && offer.productUuid) {
|
||||||
router.push(localePath(`/catalog/offers/${offer.productUuid}?offer=${offer.uuid}`))
|
router.push(localePath(`/catalog/offers/${offer.productUuid}?offer=${offer.uuid}`))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user