All checks were successful
Build Docker Image / build (push) Successful in 3m23s
- Add useCatalogSearch composable for managing unified search state - Add UnifiedSearchBar component with token chips for filters - Add CatalogHero component for empty/landing state - Create grid components for each display mode: - CatalogGridProducts, CatalogGridSuppliers, CatalogGridHubs - CatalogGridHubsForProduct, CatalogGridProductsFromSupplier - CatalogGridProductsInHub, CatalogGridOffers - Add unified catalog page at /catalog with query params - Remove SubNavigation from catalog section (kept for other sections) - Update all links to use new unified catalog paths - Delete old nested catalog pages (offers/suppliers/hubs flows) - Add i18n translations for catalog section
146 lines
3.9 KiB
Vue
146 lines
3.9 KiB
Vue
<template>
|
|
<div class="flex flex-col h-full">
|
|
<!-- Unified Search Bar -->
|
|
<div class="sticky top-0 z-20 px-3 lg:px-6 py-3 bg-base-300">
|
|
<UnifiedSearchBar
|
|
:active-tokens="activeTokens"
|
|
:available-chips="availableChips"
|
|
:select-mode="selectMode"
|
|
:search-query="searchQuery"
|
|
@start-select="startSelect"
|
|
@cancel-select="cancelSelect"
|
|
@edit-token="editFilter"
|
|
@remove-token="removeFilter"
|
|
@update:search-query="searchQuery = $event"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Dynamic Content -->
|
|
<div class="flex-1 px-3 lg:px-6 py-4">
|
|
<!-- Hero (empty state) -->
|
|
<template v-if="displayMode === 'hero'">
|
|
<CatalogHero @start-select="startSelect" />
|
|
</template>
|
|
|
|
<!-- Products Grid -->
|
|
<template v-else-if="displayMode === 'grid-products'">
|
|
<CatalogGridProducts
|
|
:search-query="searchQuery"
|
|
@select="onSelectProduct"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Suppliers Grid -->
|
|
<template v-else-if="displayMode === 'grid-suppliers'">
|
|
<CatalogGridSuppliers
|
|
:search-query="searchQuery"
|
|
@select="onSelectSupplier"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Hubs Grid -->
|
|
<template v-else-if="displayMode === 'grid-hubs'">
|
|
<CatalogGridHubs
|
|
:search-query="searchQuery"
|
|
@select="onSelectHub"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Hubs for selected product -->
|
|
<template v-else-if="displayMode === 'grid-hubs-for-product'">
|
|
<CatalogGridHubsForProduct
|
|
:product-id="productId!"
|
|
:search-query="searchQuery"
|
|
@select="onSelectHub"
|
|
@product-loaded="setLabel('product', productId!, $event)"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Products from supplier -->
|
|
<template v-else-if="displayMode === 'grid-products-from-supplier'">
|
|
<CatalogGridProductsFromSupplier
|
|
:supplier-id="supplierId!"
|
|
:search-query="searchQuery"
|
|
@select="onSelectProduct"
|
|
@supplier-loaded="setLabel('supplier', supplierId!, $event)"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Products in hub -->
|
|
<template v-else-if="displayMode === 'grid-products-in-hub'">
|
|
<CatalogGridProductsInHub
|
|
:hub-id="hubId!"
|
|
:search-query="searchQuery"
|
|
@select="onSelectProduct"
|
|
@hub-loaded="setLabel('hub', hubId!, $event)"
|
|
/>
|
|
</template>
|
|
|
|
<!-- Offers -->
|
|
<template v-else-if="displayMode === 'grid-offers'">
|
|
<CatalogGridOffers
|
|
:product-id="productId"
|
|
:supplier-id="supplierId"
|
|
:hub-id="hubId"
|
|
:search-query="searchQuery"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: 'topnav'
|
|
})
|
|
|
|
const { t } = useI18n()
|
|
|
|
const {
|
|
selectMode,
|
|
displayMode,
|
|
productId,
|
|
supplierId,
|
|
hubId,
|
|
searchQuery,
|
|
activeTokens,
|
|
availableChips,
|
|
startSelect,
|
|
cancelSelect,
|
|
selectItem,
|
|
removeFilter,
|
|
editFilter,
|
|
setLabel
|
|
} = useCatalogSearch()
|
|
|
|
// Selection handlers
|
|
const onSelectProduct = (product: { uuid: string; name: string }) => {
|
|
selectItem('product', product.uuid, product.name)
|
|
}
|
|
|
|
const onSelectSupplier = (supplier: { uuid: string; name: string }) => {
|
|
selectItem('supplier', supplier.uuid, supplier.name)
|
|
}
|
|
|
|
const onSelectHub = (hub: { uuid: string; name: string }) => {
|
|
selectItem('hub', hub.uuid, hub.name)
|
|
}
|
|
|
|
// SEO
|
|
useHead(() => {
|
|
let title = t('catalog.hero.title')
|
|
|
|
if (displayMode.value === 'grid-products') {
|
|
title = t('catalog.headers.selectProduct')
|
|
} else if (displayMode.value === 'grid-suppliers') {
|
|
title = t('catalog.headers.selectSupplier')
|
|
} else if (displayMode.value === 'grid-hubs') {
|
|
title = t('catalog.headers.selectHub')
|
|
} else if (displayMode.value === 'grid-offers') {
|
|
title = t('catalog.headers.offers')
|
|
}
|
|
|
|
return { title }
|
|
})
|
|
</script>
|