Add Explore/Quote dual mode to catalog page
All checks were successful
Build Docker Image / build (push) Successful in 3m52s

- Add CatalogMode type (explore/quote) to useCatalogSearch
- Create ExplorePanel component with view toggle (offers/hubs/suppliers)
- Create QuoteForm and QuotePanel components for search form
- Refactor CatalogPage to fullscreen map with overlay panel
- Simplify catalog/index.vue to use new components
- Add translations for modes and quote form (ru/en)

The catalog now has two modes:
- Explore: Browse map with offers/hubs/suppliers toggle
- Quote: Search form with product/hub/qty filters to find offers
This commit is contained in:
Ruslan Bakiev
2026-01-22 19:13:45 +07:00
parent 749f15131b
commit 850ab3f252
10 changed files with 694 additions and 665 deletions

View File

@@ -0,0 +1,81 @@
<template>
<div class="flex flex-col gap-4 h-full">
<!-- Quote form -->
<QuoteForm
:product-id="productId"
:product-label="productLabel"
:hub-id="hubId"
:hub-label="hubLabel"
:supplier-id="supplierId"
:supplier-label="supplierLabel"
:quantity="quantity"
:can-search="canSearch"
@edit-filter="emit('edit-filter', $event)"
@remove-filter="emit('remove-filter', $event)"
@update-quantity="emit('update-quantity', $event)"
@search="emit('search')"
@clear-all="emit('clear-all')"
/>
<!-- Divider -->
<div v-if="showResults" class="divider my-0" />
<!-- Results section -->
<div v-if="showResults" class="flex-1 overflow-y-auto">
<div v-if="loading" class="flex items-center justify-center py-8">
<span class="loading loading-spinner loading-md" />
</div>
<div v-else-if="offers.length === 0" class="text-center py-8 text-base-content/60">
<Icon name="lucide:search-x" size="32" class="mb-2" />
<p>{{ $t('catalog.empty.noOffers') }}</p>
</div>
<div v-else class="flex flex-col gap-3">
<Text tone="muted" class="text-sm">
{{ $t('catalog.headers.offers') }}: {{ offers.length }}
</Text>
<div
v-for="offer in offers"
:key="offer.uuid"
class="cursor-pointer"
@click="emit('select-offer', offer)"
>
<slot name="offer-card" :offer="offer">
<OfferCard :offer="offer" linkable />
</slot>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
interface Offer {
uuid: string
[key: string]: any
}
defineProps<{
productId?: string
productLabel?: string
hubId?: string
hubLabel?: string
supplierId?: string
supplierLabel?: string
quantity?: string
canSearch: boolean
showResults: boolean
loading: boolean
offers: Offer[]
}>()
const emit = defineEmits<{
'edit-filter': [type: string]
'remove-filter': [type: string]
'update-quantity': [value: string]
'search': []
'clear-all': []
'select-offer': [offer: Offer]
}>()
</script>