feat(catalog): KYC bottom sheet instead of separate page
All checks were successful
Build Docker Image / build (push) Successful in 4m21s

- Add KycBottomSheet component with glass effect (70vh height)
- Animate sheet sliding up from bottom when opening KYC
- InfoPanel hides when KYC sheet is open
- Click outside or X button to close
- Contains all company info: реквизиты, руководство, учредители, контакты, финансы, арбитраж, ОКВЭД
This commit is contained in:
Ruslan Bakiev
2026-01-28 05:04:20 +07:00
parent 1f996d27e5
commit 45acef9b20
2 changed files with 389 additions and 68 deletions

View File

@@ -1,72 +1,81 @@
<template>
<CatalogPage
ref="catalogPageRef"
:loading="isLoading"
:use-server-clustering="true"
:cluster-node-type="clusterNodeType"
map-id="unified-catalog-map"
:point-color="mapPointColor"
:items="currentSelectionItems"
:hovered-id="hoveredItemId ?? undefined"
:show-panel="showPanel"
:filter-by-bounds="filterByBounds"
:related-points="relatedPoints"
:info-loading="isInfoLoading"
@select="onMapSelect"
@bounds-change="onBoundsChange"
@update:filter-by-bounds="$event ? setBoundsInUrl(currentMapBounds) : clearBoundsFromUrl()"
>
<!-- Panel slot - shows selection list OR info OR quote results -->
<template #panel>
<!-- Selection mode: show list for picking product/hub/supplier -->
<SelectionPanel
v-if="selectMode"
:select-mode="selectMode"
:products="filteredProducts"
:hubs="filteredHubs"
:suppliers="filteredSuppliers"
:loading="selectionLoading"
:loading-more="selectionLoadingMore"
:has-more="selectionHasMore && !filterByBounds"
@select="onSelectItem"
@close="onClosePanel"
@load-more="onLoadMore"
@hover="onHoverItem"
/>
<div>
<CatalogPage
ref="catalogPageRef"
:loading="isLoading"
:use-server-clustering="true"
:cluster-node-type="clusterNodeType"
map-id="unified-catalog-map"
:point-color="mapPointColor"
:items="currentSelectionItems"
:hovered-id="hoveredItemId ?? undefined"
:show-panel="showPanel && !kycSheetUuid"
:filter-by-bounds="filterByBounds"
:related-points="relatedPoints"
:info-loading="isInfoLoading"
@select="onMapSelect"
@bounds-change="onBoundsChange"
@update:filter-by-bounds="$event ? setBoundsInUrl(currentMapBounds) : clearBoundsFromUrl()"
>
<!-- Panel slot - shows selection list OR info OR quote results -->
<template #panel>
<!-- Selection mode: show list for picking product/hub/supplier -->
<SelectionPanel
v-if="selectMode"
:select-mode="selectMode"
:products="filteredProducts"
:hubs="filteredHubs"
:suppliers="filteredSuppliers"
:loading="selectionLoading"
:loading-more="selectionLoadingMore"
:has-more="selectionHasMore && !filterByBounds"
@select="onSelectItem"
@close="onClosePanel"
@load-more="onLoadMore"
@hover="onHoverItem"
/>
<!-- Info mode: show detailed info about selected entity -->
<InfoPanel
v-else-if="infoId"
:entity-type="infoId.type"
:entity-id="infoId.uuid"
:entity="entity"
:related-products="relatedProducts"
:related-hubs="relatedHubs"
:related-suppliers="relatedSuppliers"
:related-offers="relatedOffers"
:selected-product="infoProduct ?? null"
:loading="infoLoading"
:loading-products="isLoadingProducts"
:loading-hubs="isLoadingHubs"
:loading-suppliers="isLoadingSuppliers"
:loading-offers="isLoadingOffers"
@close="onInfoClose"
@add-to-filter="onInfoAddToFilter"
@open-info="onInfoOpenRelated"
@select-product="onInfoSelectProduct"
@select-offer="onSelectOffer"
@open-kyc="onOpenKyc"
/>
<!-- Info mode: show detailed info about selected entity -->
<InfoPanel
v-else-if="infoId"
:entity-type="infoId.type"
:entity-id="infoId.uuid"
:entity="entity"
:related-products="relatedProducts"
:related-hubs="relatedHubs"
:related-suppliers="relatedSuppliers"
:related-offers="relatedOffers"
:selected-product="infoProduct ?? null"
:loading="infoLoading"
:loading-products="isLoadingProducts"
:loading-hubs="isLoadingHubs"
:loading-suppliers="isLoadingSuppliers"
:loading-offers="isLoadingOffers"
@close="onInfoClose"
@add-to-filter="onInfoAddToFilter"
@open-info="onInfoOpenRelated"
@select-product="onInfoSelectProduct"
@select-offer="onSelectOffer"
@open-kyc="onOpenKyc"
/>
<!-- Quote results: show offers after search -->
<QuotePanel
v-else-if="showQuoteResults"
:loading="offersLoading"
:offers="offers"
@select-offer="onSelectOffer"
/>
</template>
</CatalogPage>
<!-- Quote results: show offers after search -->
<QuotePanel
v-else-if="showQuoteResults"
:loading="offersLoading"
:offers="offers"
@select-offer="onSelectOffer"
/>
</template>
</CatalogPage>
<!-- KYC Bottom Sheet (overlays everything) -->
<KycBottomSheet
:is-open="!!kycSheetUuid"
:uuid="kycSheetUuid"
@close="onCloseKycSheet"
/>
</div>
</template>
<script setup lang="ts">
@@ -495,10 +504,18 @@ const onInfoSelectProduct = (uuid: string | null) => {
setInfoProduct(uuid)
}
// Handle KYC profile open - navigate to KYC page
// KYC Bottom Sheet state
const kycSheetUuid = ref<string | null>(null)
// Handle KYC profile open - show bottom sheet instead of navigating
const onOpenKyc = (uuid: string | undefined) => {
if (!uuid) return
navigateTo(localePath(`/kyc/${uuid}`))
kycSheetUuid.value = uuid
}
// Close KYC bottom sheet
const onCloseKycSheet = () => {
kycSheetUuid.value = null
}
// Search for offers