All checks were successful
Build Docker Image / build (push) Successful in 3m42s
Animation on map only needed on final pages (routes/sources). Intermediate pages now navigate directly on card click. Files changed: - hubs/index.vue - removed hover/select - suppliers/index.vue - removed hover/select - suppliers/[]/[]/index.vue - removed hover - offers/index.vue - removed hover - offers/[]/index.vue - removed hover
80 lines
2.0 KiB
Vue
80 lines
2.0 KiB
Vue
<template>
|
|
<CatalogPage
|
|
:items="filteredProducts"
|
|
:loading="isLoading"
|
|
:total-count="products.length"
|
|
with-map
|
|
use-server-clustering
|
|
cluster-node-type="offer"
|
|
map-id="offers-products-map"
|
|
point-color="#22c55e"
|
|
>
|
|
<template #searchBar>
|
|
<CatalogSearchBar
|
|
v-model:search-query="searchQuery"
|
|
:show-counter="false"
|
|
/>
|
|
</template>
|
|
|
|
<template #header>
|
|
<Text v-if="!isLoading" tone="muted">Выберите товар</Text>
|
|
</template>
|
|
|
|
<template #card="{ item }">
|
|
<HubProductCard
|
|
:name="item.name || ''"
|
|
:price-history="getMockPriceHistory(item.uuid)"
|
|
@select="goToProduct(item.uuid)"
|
|
/>
|
|
</template>
|
|
|
|
<template #empty>
|
|
<Text tone="muted">{{ t('catalogProducts.empty.subtitle') }}</Text>
|
|
</template>
|
|
</CatalogPage>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: 'topnav'
|
|
})
|
|
|
|
const localePath = useLocalePath()
|
|
const { t } = useI18n()
|
|
|
|
const { items: products, isLoading, init } = useCatalogProducts()
|
|
|
|
// Search
|
|
const searchQuery = ref('')
|
|
|
|
const filteredProducts = computed(() => {
|
|
if (!searchQuery.value.trim()) return products.value
|
|
const q = searchQuery.value.toLowerCase()
|
|
return products.value.filter(item =>
|
|
item.name?.toLowerCase().includes(q)
|
|
)
|
|
})
|
|
|
|
// Navigate to product detail
|
|
const goToProduct = (productId: string) => {
|
|
navigateTo(localePath(`/catalog/offers/${productId}`))
|
|
}
|
|
|
|
// Mock price history generator (seeded by uuid for consistent results)
|
|
const getMockPriceHistory = (uuid: string): number[] => {
|
|
const seed = uuid.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)
|
|
const basePrice = 100 + (seed % 200)
|
|
return Array.from({ length: 7 }, (_, i) => {
|
|
const variation = Math.sin(seed + i * 0.5) * 20 + Math.cos(seed * 0.3 + i) * 10
|
|
return Math.round(basePrice + variation)
|
|
})
|
|
}
|
|
|
|
// Initialize
|
|
await init()
|
|
|
|
useHead(() => ({
|
|
title: t('catalogProducts.header.title')
|
|
}))
|
|
</script>
|