Files
webapp/app/components/GoodsContent.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

65 lines
1.8 KiB
Vue

<template>
<Stack gap="6">
<PageHeader
:title="$t('goods.title')"
:description="$t('goods.description')"
/>
<div v-if="pending" class="flex items-center justify-center p-8">
<span class="loading loading-spinner loading-lg" />
</div>
<Alert v-else-if="error" variant="error">
<Stack gap="2">
<Heading :level="4" weight="semibold">{{ $t('goods.error.title') }}</Heading>
<Button @click="refresh()">{{ $t('goods.error.retry') }}</Button>
</Stack>
</Alert>
<EmptyState
v-else-if="!productsData?.length"
:title="$t('goods.empty.title')"
:description="$t('goods.empty.description')"
/>
<Grid v-else :cols="1" :md="2" :lg="3" :gap="4">
<ProductCard
v-for="product in productsData"
:key="product.uuid"
:product="product"
selectable
@select="selectProduct(product)"
/>
</Grid>
</Stack>
</template>
<script setup lang="ts">
import { GetProductsDocument } from '~/composables/graphql/public/exchange-generated'
const searchStore = useSearchStore()
const { data, pending, error, refresh } = await useServerQuery('products', GetProductsDocument, {}, 'public', 'exchange')
const productsData = computed(() => data.value?.getProducts || [])
const selectProduct = (product: any) => {
searchStore.setProduct(product.name)
searchStore.setProductUuid(product.uuid)
const locationUuid = searchStore.searchForm.locationUuid
const quantity = searchStore.searchForm.quantity
const query: Record<string, string> = {}
if (quantity) query.quantity = String(quantity)
if (locationUuid) {
// Both product and hub selected -> show offers
navigateTo({
path: `/catalog`,
query: { product: product.uuid, hub: locationUuid, ...query }
})
return
}
history.back()
}
</script>