refactor(catalog): replace InfoPanel tabs with vertical sections
All checks were successful
Build Docker Image / build (push) Successful in 3m57s

- Remove all tabs from InfoPanel, use stacked sections instead
- Load suppliers (for hub) and hubs (for supplier) immediately
- Show entity header as text, not card
- Simplify relatedPoints to show all points on map
- Add translations for new section titles
This commit is contained in:
Ruslan Bakiev
2026-01-26 19:34:04 +07:00
parent 69bb978526
commit e905098cb5
5 changed files with 236 additions and 323 deletions

View File

@@ -29,7 +29,7 @@ export function useCatalogInfo() {
const isLoadingSuppliers = ref(false)
const isLoadingOffers = ref(false)
// Load hub info: hub details + products + suppliers
// Load hub info: hub details + products + suppliers (in parallel)
const loadHubInfo = async (uuid: string) => {
try {
// Load hub node details
@@ -44,23 +44,27 @@ export function useCatalogInfo() {
// Set default active tab to offers (first step shows products)
activeTab.value = 'offers'
// Load products (offers grouped by product)
// Load products AND suppliers in parallel
isLoadingProducts.value = true
try {
const offersData = await execute(
NearestOffersDocument,
{
lat: entity.value.latitude,
lon: entity.value.longitude,
radius: 500
},
'public',
'geo'
)
isLoadingSuppliers.value = true
// Load products (offers grouped by product) and extract suppliers
execute(
NearestOffersDocument,
{
lat: entity.value.latitude,
lon: entity.value.longitude,
radius: 500
},
'public',
'geo'
).then(offersData => {
// Group offers by product
const productsMap = new Map<string, any>()
const suppliersMap = new Map<string, any>()
offersData?.nearestOffers?.forEach((offer: any) => {
// Products
if (offer?.productUuid) {
if (!productsMap.has(offer.productUuid)) {
productsMap.set(offer.productUuid, {
@@ -71,19 +75,50 @@ export function useCatalogInfo() {
}
productsMap.get(offer.productUuid)!.offersCount++
}
})
relatedProducts.value = Array.from(productsMap.values())
} finally {
isLoadingProducts.value = false
}
// Note: Suppliers and Offers loaded after product selection via loadOffersForHub
// Suppliers (extract from offers)
if (offer?.supplierUuid) {
if (!suppliersMap.has(offer.supplierUuid)) {
suppliersMap.set(offer.supplierUuid, {
uuid: offer.supplierUuid,
name: offer.supplierName || 'Supplier',
latitude: offer.latitude,
longitude: offer.longitude
})
}
}
})
relatedProducts.value = Array.from(productsMap.values())
// Load supplier profiles for detailed info
const supplierUuids = Array.from(suppliersMap.keys()).slice(0, 12)
if (supplierUuids.length > 0) {
Promise.all(
supplierUuids.map(supplierId =>
execute(GetSupplierProfileDocument, { uuid: supplierId }, 'public', 'exchange')
.then(data => data?.getSupplierProfile)
.catch(() => suppliersMap.get(supplierId)) // Fallback to basic info
)
).then(profiles => {
relatedSuppliers.value = profiles.filter(Boolean)
isLoadingSuppliers.value = false
})
} else {
relatedSuppliers.value = []
isLoadingSuppliers.value = false
}
}).finally(() => {
isLoadingProducts.value = false
})
} catch (error) {
console.error('Error loading hub info:', error)
isLoadingProducts.value = false
isLoadingSuppliers.value = false
}
}
// Load supplier info: supplier details + products
// Load supplier info: supplier details + products + hubs (in parallel)
const loadSupplierInfo = async (uuid: string) => {
try {
// Load supplier node details (might be geo node)
@@ -113,20 +148,21 @@ export function useCatalogInfo() {
// Set default active tab to offers (first step shows products)
activeTab.value = 'offers'
// Load products (offers grouped by product)
// Load products AND hubs in parallel
isLoadingProducts.value = true
try {
const offersData = await execute(
NearestOffersDocument,
{
lat: entity.value.latitude,
lon: entity.value.longitude,
radius: 500
},
'public',
'geo'
)
isLoadingHubs.value = true
// Load products (offers grouped by product)
execute(
NearestOffersDocument,
{
lat: entity.value.latitude,
lon: entity.value.longitude,
radius: 500
},
'public',
'geo'
).then(offersData => {
// Group offers by product
const productsMap = new Map<string, any>()
offersData?.nearestOffers?.forEach((offer: any) => {
@@ -142,13 +178,30 @@ export function useCatalogInfo() {
}
})
relatedProducts.value = Array.from(productsMap.values())
} finally {
}).finally(() => {
isLoadingProducts.value = false
}
})
// Note: Hubs will be loaded after product selection
// Load hubs near supplier
execute(
NearestHubsDocument,
{
lat: entity.value.latitude,
lon: entity.value.longitude,
radius: 1000,
limit: 12
},
'public',
'geo'
).then(hubsData => {
relatedHubs.value = hubsData?.nearestHubs || []
}).finally(() => {
isLoadingHubs.value = false
})
} catch (error) {
console.error('Error loading supplier info:', error)
isLoadingProducts.value = false
isLoadingHubs.value = false
}
}