feat(catalog): add offers section to InfoPanel after product selection
All checks were successful
Build Docker Image / build (push) Successful in 4m33s
All checks were successful
Build Docker Image / build (push) Successful in 4m33s
- Hide products section when product is selected - Show offers section with OfferCard components - Add cancel button to return to product list - Wire up select-offer event to navigate to offer detail
This commit is contained in:
@@ -98,8 +98,8 @@
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<!-- Products Section (for hub/supplier) -->
|
||||
<section v-if="entityType === 'hub' || entityType === 'supplier'">
|
||||
<!-- Products Section (for hub/supplier) - hide when product selected -->
|
||||
<section v-if="(entityType === 'hub' || entityType === 'supplier') && !selectedProduct">
|
||||
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
|
||||
<Icon name="lucide:package" size="16" />
|
||||
{{ productsSectionTitle }}
|
||||
@@ -122,6 +122,36 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Offers Section (after product selected) -->
|
||||
<section v-if="(entityType === 'hub' || entityType === 'supplier') && selectedProduct">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h3 class="text-sm font-semibold text-white/80 flex items-center gap-2">
|
||||
<Icon name="lucide:shopping-bag" size="16" />
|
||||
{{ $t('catalog.headers.offers') }}
|
||||
<span v-if="loadingOffers" class="loading loading-spinner loading-xs" />
|
||||
<span v-else-if="relatedOffers.length > 0" class="text-white/50">({{ relatedOffers.length }})</span>
|
||||
</h3>
|
||||
<button class="btn btn-ghost btn-xs text-white/60" @click="emit('select-product', null)">
|
||||
<Icon name="lucide:x" size="14" />
|
||||
{{ $t('common.cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="!loadingOffers && relatedOffers.length === 0" class="text-white/50 text-sm py-2">
|
||||
{{ $t('catalog.empty.noOffers') }}
|
||||
</div>
|
||||
<div v-else-if="!loadingOffers" class="flex flex-col gap-2">
|
||||
<OfferCard
|
||||
v-for="(offer, index) in relatedOffers"
|
||||
:key="offer.uuid ?? index"
|
||||
:offer="offer"
|
||||
compact
|
||||
selectable
|
||||
@select="onOfferSelect(offer)"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Suppliers Section (for hub only) -->
|
||||
<section v-if="entityType === 'hub'">
|
||||
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
|
||||
@@ -210,6 +240,7 @@ const emit = defineEmits<{
|
||||
'add-to-filter': []
|
||||
'open-info': [type: InfoEntityType, uuid: string]
|
||||
'select-product': [uuid: string | null]
|
||||
'select-offer': [offer: { uuid: string; productUuid?: string | null }]
|
||||
'update:current-tab': [tab: string]
|
||||
'open-kyc': [uuid: string | undefined]
|
||||
}>()
|
||||
@@ -221,6 +252,7 @@ const { entityColors } = useCatalogSearch()
|
||||
const relatedProducts = computed(() => props.relatedProducts ?? [])
|
||||
const relatedHubs = computed(() => props.relatedHubs ?? [])
|
||||
const relatedSuppliers = computed(() => props.relatedSuppliers ?? [])
|
||||
const relatedOffers = computed(() => props.relatedOffers ?? [])
|
||||
|
||||
// Entity name
|
||||
const entityName = computed(() => {
|
||||
@@ -289,6 +321,12 @@ const onProductSelect = (product: InfoProductItem) => {
|
||||
emit('select-product', product.uuid)
|
||||
}
|
||||
|
||||
const onOfferSelect = (offer: InfoOfferItem) => {
|
||||
if (offer.uuid) {
|
||||
emit('select-offer', { uuid: offer.uuid, productUuid: offer.productUuid })
|
||||
}
|
||||
}
|
||||
|
||||
const onHubSelect = (hub: InfoHubItem) => {
|
||||
if (hub.uuid) {
|
||||
emit('open-info', 'hub', hub.uuid)
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
@add-to-filter="onInfoAddToFilter"
|
||||
@open-info="onInfoOpenRelated"
|
||||
@select-product="onInfoSelectProduct"
|
||||
@select-offer="onSelectOffer"
|
||||
@open-kyc="onOpenKyc"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user