Fix type safety in catalog composables + 3 InfoPanel bugs
All checks were successful
Build Docker Image / build (push) Successful in 3m42s

- Add proper codegen types to all catalog composables:
  - useCatalogHubs: HubItem, NearestHubItem
  - useCatalogSuppliers: SupplierItem, NearestSupplierItem
  - useCatalogProducts: ProductItem
  - useCatalogOffers: OfferItem
  - useCatalogInfo: InfoEntity, ProductItem, HubItem, OfferItem

- Fix InfoPanel bugs for offers:
  - Use locationLatitude/locationLongitude for offer coordinates
  - Enrich entity with supplierName after loading profile
  - Apply-to-filter now adds both product AND hub for offers

- Filter null values from GraphQL array responses
- Add type-safe coordinate helper (getEntityCoords)
- Fix urlBounds type inference in useCatalogSearch
This commit is contained in:
Ruslan Bakiev
2026-01-26 23:30:16 +07:00
parent 839ab4e830
commit 70c53da8eb
7 changed files with 190 additions and 84 deletions

View File

@@ -91,11 +91,27 @@ const onHoverItem = (uuid: string | null) => {
hoveredItemId.value = uuid
}
// Type for map items - must have required string uuid and number coordinates
type MapItemWithCoords = { uuid: string; name: string; latitude: number; longitude: number; country?: string }
// Helper to convert items to map-compatible format (filter null values)
const toMapItems = <T extends { uuid?: string | null; name?: string | null; latitude?: number | null; longitude?: number | null }>(
items: T[]
): MapItemWithCoords[] =>
items.filter((item): item is T & { uuid: string; latitude: number; longitude: number } =>
item.uuid != null && item.latitude != null && item.longitude != null
).map(item => ({
uuid: item.uuid,
name: item.name || '',
latitude: item.latitude,
longitude: item.longitude
}))
// Current selection items for hover highlighting on map
const currentSelectionItems = computed(() => {
if (selectMode.value === 'product') return filteredProducts.value
if (selectMode.value === 'hub') return filteredHubs.value
if (selectMode.value === 'supplier') return filteredSuppliers.value
const currentSelectionItems = computed((): MapItemWithCoords[] => {
if (selectMode.value === 'product') return [] // Products don't have coordinates
if (selectMode.value === 'hub') return toMapItems(filteredHubs.value)
if (selectMode.value === 'supplier') return toMapItems(filteredSuppliers.value)
return []
})
@@ -280,10 +296,10 @@ const relatedPoints = computed(() => {
// Add all hubs
relatedHubs.value.forEach(hub => {
if (hub.latitude && hub.longitude) {
if (hub.uuid && hub.latitude && hub.longitude) {
points.push({
uuid: hub.uuid,
name: hub.name,
name: hub.name || '',
latitude: hub.latitude,
longitude: hub.longitude,
type: 'hub'
@@ -293,10 +309,10 @@ const relatedPoints = computed(() => {
// Add all suppliers
relatedSuppliers.value.forEach(supplier => {
if (supplier.latitude && supplier.longitude) {
if (supplier.uuid && supplier.latitude && supplier.longitude) {
points.push({
uuid: supplier.uuid,
name: supplier.name,
name: supplier.name || '',
latitude: supplier.latitude,
longitude: supplier.longitude,
type: 'supplier'
@@ -416,10 +432,17 @@ const onInfoAddToFilter = () => {
if (!infoId.value || !entity.value) return
const { type, uuid } = infoId.value
// For offers, add the product to filter (not the offer itself)
if (type === 'offer' && entity.value.productUuid) {
const productName = entity.value.productName || entity.value.name || uuid.slice(0, 8) + '...'
selectItem('product', entity.value.productUuid, productName)
// 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) + '...'