Files
webapp/app/pages/catalog/index.vue
Ruslan Bakiev 08d7e0ade9
All checks were successful
Build Docker Image / build (push) Successful in 3m23s
Implement unified catalog search with token-based filtering
- 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
2026-01-22 10:57:30 +07:00

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>