@@ -183,6 +183,7 @@ const props = defineProps<{
relatedSuppliers?: any[]
relatedOffers?: any[]
selectedProduct?: string | null
+ currentTab?: string
loading?: boolean
}>()
@@ -191,6 +192,7 @@ const emit = defineEmits<{
'add-to-filter': []
'open-info': [type: InfoEntityType, uuid: string]
'select-product': [uuid: string | null]
+ 'update:current-tab': [tab: string]
}>()
const { t } = useI18n()
@@ -202,9 +204,6 @@ const relatedHubs = computed(() => props.relatedHubs ?? [])
const relatedSuppliers = computed(() => props.relatedSuppliers ?? [])
const relatedOffers = computed(() => props.relatedOffers ?? [])
-// Current active tab
-const currentTab = ref('offers')
-
// Entity name
const entityName = computed(() => {
return props.entity?.name || props.entity?.productName || props.entityId.slice(0, 8) + '...'
@@ -278,17 +277,20 @@ const availableTabs = computed(() => {
return tabs
})
-// Set default active tab when entity type changes
-watch(
- () => props.entityType,
- () => {
- const firstTab = availableTabs.value[0]
- if (firstTab) {
- currentTab.value = firstTab.id
- }
- },
- { immediate: true }
-)
+// Active tab - use prop or default to first available
+const activeTab = computed(() => {
+ // If prop is set and is a valid tab, use it
+ if (props.currentTab && availableTabs.value.some(t => t.id === props.currentTab)) {
+ return props.currentTab
+ }
+ // Default to first tab
+ return availableTabs.value[0]?.id || 'offers'
+})
+
+// Handler for tab click
+const onTabClick = (tabId: string) => {
+ emit('update:current-tab', tabId)
+}
// Handlers for selecting related items
const onProductSelect = (product: any) => {
diff --git a/app/composables/useCatalogSearch.ts b/app/composables/useCatalogSearch.ts
index 60012a2..2394fa2 100644
--- a/app/composables/useCatalogSearch.ts
+++ b/app/composables/useCatalogSearch.ts
@@ -73,6 +73,12 @@ export function useCatalogSearch() {
return null
})
+ // Info panel tab (stored in URL for sharing)
+ const infoTab = computed(() => route.query.infoTab as string | undefined)
+
+ // Info panel selected product (stored in URL for sharing)
+ const infoProduct = computed(() => route.query.infoProduct as string | undefined)
+
const productId = computed(() => route.query.product as string | undefined)
const supplierId = computed(() => route.query.supplier as string | undefined)
const hubId = computed(() => route.query.hub as string | undefined)
@@ -232,11 +238,19 @@ export function useCatalogSearch() {
}
const openInfo = (type: InfoEntityType, uuid: string) => {
- updateQuery({ info: `${type}:${uuid}`, select: null })
+ updateQuery({ info: `${type}:${uuid}`, select: null, infoTab: null, infoProduct: null })
}
const closeInfo = () => {
- updateQuery({ info: null })
+ updateQuery({ info: null, infoTab: null, infoProduct: null })
+ }
+
+ const setInfoTab = (tab: string) => {
+ updateQuery({ infoTab: tab })
+ }
+
+ const setInfoProduct = (productUuid: string | null) => {
+ updateQuery({ infoProduct: productUuid })
}
const clearAll = () => {
@@ -326,6 +340,8 @@ export function useCatalogSearch() {
// State
selectMode,
infoId,
+ infoTab,
+ infoProduct,
displayMode,
catalogMode,
productId,
@@ -359,6 +375,8 @@ export function useCatalogSearch() {
setQuantity,
openInfo,
closeInfo,
+ setInfoTab,
+ setInfoProduct,
clearAll,
setLabel,
setMapViewMode,
diff --git a/app/pages/catalog/index.vue b/app/pages/catalog/index.vue
index 8f419dc..37c4a21 100644
--- a/app/pages/catalog/index.vue
+++ b/app/pages/catalog/index.vue
@@ -43,12 +43,14 @@
:related-hubs="relatedHubs"
:related-suppliers="relatedSuppliers"
:related-offers="relatedOffers"
- :selected-product="selectedProduct"
+ :selected-product="infoProduct ?? null"
+ :current-tab="infoTab"
:loading="infoLoading"
@close="onInfoClose"
@add-to-filter="onInfoAddToFilter"
@open-info="onInfoOpenRelated"
- @select-product="(uuid: string | null) => uuid && selectInfoProduct(uuid)"
+ @select-product="onInfoSelectProduct"
+ @update:current-tab="setInfoTab"
/>
@@ -105,6 +107,8 @@ const {
catalogMode,
selectMode,
infoId,
+ infoTab,
+ infoProduct,
productId,
supplierId,
hubId,
@@ -116,6 +120,8 @@ const {
cancelSelect,
openInfo,
closeInfo,
+ setInfoTab,
+ setInfoProduct,
setLabel
} = useCatalogSearch()
@@ -231,11 +237,22 @@ watch([filterByBounds, currentMapBounds], ([enabled, bounds]) => {
watch(infoId, async (info) => {
if (info) {
await loadInfo(info.type, info.uuid)
+ // If URL has infoProduct, load offers for it
+ if (infoProduct.value) {
+ await selectInfoProduct(infoProduct.value)
+ }
} else {
clearInfo()
}
}, { immediate: true })
+// Watch infoProduct URL param to load offers when it changes
+watch(infoProduct, async (productUuid) => {
+ if (productUuid && infoId.value) {
+ await selectInfoProduct(productUuid)
+ }
+})
+
// Related points for Info mode (shown on map)
const relatedPoints = computed(() => {
if (!infoId.value) return []
@@ -418,6 +435,11 @@ const onInfoOpenRelated = (type: 'hub' | 'supplier' | 'offer', uuid: string) =>
openInfo(type, uuid)
}
+// Handle product selection in InfoPanel - update URL which triggers loading
+const onInfoSelectProduct = (uuid: string | null) => {
+ setInfoProduct(uuid)
+}
+
// Search for offers
const onSearch = async () => {
if (!canSearch.value) return