Redirect search to catalog offers flow instead of /request
All checks were successful
Build Docker Image / build (push) Successful in 4m2s

- GlobalSearchBar now redirects to /catalog/offers/[productId]/[hubId]
- GoodsContent redirects to offers flow
- select-location pages redirect to offers flow
- Added quantity tag to offers page
- Added KYC profile loading and offer detail navigation on offers page
This commit is contained in:
Ruslan Bakiev
2026-01-21 14:59:50 +07:00
parent 16c0a8112e
commit 631effdde4
5 changed files with 86 additions and 42 deletions

View File

@@ -46,16 +46,16 @@ 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: '/request',
query: {
productUuid: product.uuid,
product: product.name,
locationUuid,
location: searchStore.searchForm.location,
quantity: searchStore.searchForm.quantity || undefined
}
path: `/catalog/offers/${product.uuid}/${locationUuid}`,
query
})
return
}

View File

@@ -99,30 +99,33 @@ const canSearch = computed(() => {
return !!productUuid.value
})
// Search handler - navigate to /request
// Search handler - navigate to catalog offers flow
const handleSearch = () => {
if (!canSearch.value) return
// Sync quantity to store
syncQuantityToStore()
const query: Record<string, string | undefined> = {
productUuid: productUuid.value || undefined,
product: productDisplay.value || undefined,
quantity: quantity.value ? String(quantity.value) : undefined,
locationUuid: locationUuid.value || undefined,
location: locationDisplay.value || undefined
// Build query params
const query: Record<string, string> = {}
if (quantity.value) {
query.quantity = String(quantity.value)
}
// Remove undefined/empty values
Object.keys(query).forEach(key => {
if (!query[key]) delete query[key]
})
// Navigate to offers flow
if (productUuid.value && locationUuid.value) {
// Both product and hub selected -> show offers
router.push({
path: localePath('/request'),
query: query as Record<string, string>
path: localePath(`/catalog/offers/${productUuid.value}/${locationUuid.value}`),
query
})
} else if (productUuid.value) {
// Only product selected -> select hub
router.push({
path: localePath(`/catalog/offers/${productUuid.value}`),
query
})
}
emit('search', {
productUuid: productUuid.value,

View File

@@ -73,6 +73,8 @@
:stages="item.stages"
:start-name="item.name"
:end-name="hub?.name"
:kyc-profile-uuid="getOfferData(item.uuid)?.kycProfileUuid"
@select="navigateTo(localePath(`/catalog/offers/${item.uuid}`))"
/>
</template>
@@ -89,7 +91,7 @@
<script setup lang="ts">
import { GetNodeConnectionsDocument, GetOffersByHubDocument } from '~/composables/graphql/public/geo-generated'
import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated'
import { GetAvailableProductsDocument, GetOfferDocument, GetSupplierProfileByTeamDocument } from '~/composables/graphql/public/exchange-generated'
definePageMeta({
layout: 'topnav'
@@ -108,9 +110,11 @@ const selectedSourceUuid = ref('')
const hoveredSourceUuid = ref<string>()
const rawSources = ref<any[]>([])
const offersData = ref<Map<string, any>>(new Map())
const suppliersData = ref<Map<string, any>>(new Map())
const productId = computed(() => route.params.productId as string)
const hubId = computed(() => route.params.hubId as string)
const quantity = computed(() => route.query.quantity as string | undefined)
// Navigation filters for search bar badges
const navigationFilters = computed(() => {
@@ -132,6 +136,14 @@ const navigationFilters = computed(() => {
})
}
if (quantity.value) {
filters.push({
id: 'quantity',
key: 'Кол-во',
label: `${quantity.value} т`
})
}
return filters
})
@@ -141,6 +153,9 @@ const handleRemoveFilter = (filterId: string) => {
navigateTo(localePath(`/catalog/offers/${productId.value}`))
} else if (filterId === 'product') {
navigateTo(localePath('/catalog/offers'))
} else if (filterId === 'quantity') {
// Remove quantity from query, stay on same page
navigateTo({ path: route.path, query: {} })
}
}
@@ -213,25 +228,57 @@ const getOfferData = (uuid: string) => {
return offersData.value.get(uuid)
}
// Load offer details for prices
// Load offer details for prices and supplier info
const loadOfferDetails = async () => {
if (rawSources.value.length === 0) {
offersData.value.clear()
suppliersData.value.clear()
return
}
const newOffersData = new Map<string, any>()
const newSuppliersData = new Map<string, any>()
const teamUuidsToLoad = new Set<string>()
// First, load all offers
await Promise.all(rawSources.value.map(async (source) => {
try {
const data = await execute(GetOfferDocument, { uuid: source.sourceUuid }, 'public', 'exchange')
if (data?.getOffer) {
newOffersData.set(source.sourceUuid, data.getOffer)
if (data.getOffer.teamUuid) {
teamUuidsToLoad.add(data.getOffer.teamUuid)
}
}
} catch (error) {
console.error('Error loading offer:', source.sourceUuid, error)
}
}))
// Then, load supplier profiles for KYC
await Promise.all([...teamUuidsToLoad].map(async (teamUuid) => {
try {
const data = await execute(GetSupplierProfileByTeamDocument, { teamUuid }, 'public', 'exchange')
if (data?.getSupplierProfileByTeam) {
newSuppliersData.set(teamUuid, data.getSupplierProfileByTeam)
}
} catch (error) {
console.error('Error loading supplier:', teamUuid, error)
}
}))
// Merge kycProfileUuid into offer data
newOffersData.forEach((offer, offerUuid) => {
if (offer.teamUuid) {
const supplier = newSuppliersData.get(offer.teamUuid)
if (supplier?.kycProfileUuid) {
offer.kycProfileUuid = supplier.kycProfileUuid
}
}
})
offersData.value = newOffersData
suppliersData.value = newSuppliersData
}
// Load offers with routes to this hub

View File

@@ -132,15 +132,12 @@ const isSelected = (type: 'address' | 'hub', uuid: string) => {
const goToRequestIfReady = () => {
if (route.query.after === 'request' && searchStore.searchForm.productUuid && searchStore.searchForm.locationUuid) {
const query: Record<string, string> = {}
if (searchStore.searchForm.quantity) query.quantity = String(searchStore.searchForm.quantity)
router.push({
path: '/request',
query: {
productUuid: searchStore.searchForm.productUuid,
product: searchStore.searchForm.product,
locationUuid: searchStore.searchForm.locationUuid,
location: searchStore.searchForm.location,
quantity: searchStore.searchForm.quantity || undefined
}
path: `/catalog/offers/${searchStore.searchForm.productUuid}/${searchStore.searchForm.locationUuid}`,
query
})
return true
}

View File

@@ -76,15 +76,12 @@ const selectItem = async (item: any) => {
searchStore.setLocation(item.name)
searchStore.setLocationUuid(item.uuid)
if (route.query.after === 'request' && searchStore.searchForm.productUuid && searchStore.searchForm.locationUuid) {
const query: Record<string, string> = {}
if (searchStore.searchForm.quantity) query.quantity = String(searchStore.searchForm.quantity)
router.push({
path: '/request',
query: {
productUuid: searchStore.searchForm.productUuid,
product: searchStore.searchForm.product,
locationUuid: searchStore.searchForm.locationUuid,
location: searchStore.searchForm.location,
quantity: searchStore.searchForm.quantity || undefined
}
path: `/catalog/offers/${searchStore.searchForm.productUuid}/${searchStore.searchForm.locationUuid}`,
query
})
return
}