Use geo offers for quote results
All checks were successful
Build Docker Image / build (push) Successful in 5m9s
All checks were successful
Build Docker Image / build (push) Successful in 5m9s
This commit is contained in:
@@ -34,7 +34,8 @@
|
||||
:quantity="offer.quantity"
|
||||
:currency="offer.currency"
|
||||
:unit="offer.unit"
|
||||
:stages="[]"
|
||||
:stages="getOfferStages(offer)"
|
||||
:total-time-seconds="offer.routes?.[0]?.totalTimeSeconds ?? null"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,6 +49,7 @@ interface Offer {
|
||||
productName?: string | null
|
||||
productUuid?: string | null
|
||||
supplierName?: string | null
|
||||
supplierUuid?: string | null
|
||||
quantity?: number | string | null
|
||||
unit?: string | null
|
||||
pricePerUnit?: number | string | null
|
||||
@@ -55,6 +57,15 @@ interface Offer {
|
||||
locationName?: string | null
|
||||
locationCountry?: string | null
|
||||
locationCountryCode?: string | null
|
||||
routes?: Array<{
|
||||
totalTimeSeconds?: number | null
|
||||
stages?: Array<{
|
||||
transportType?: string | null
|
||||
distanceKm?: number | null
|
||||
travelTimeSeconds?: number | null
|
||||
fromName?: string | null
|
||||
} | null> | null
|
||||
} | null> | null
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -69,4 +80,17 @@ const props = defineProps<{
|
||||
const offersWithPrice = computed(() =>
|
||||
(props.offers || []).filter(o => o?.pricePerUnit != null)
|
||||
)
|
||||
|
||||
const getOfferStages = (offer: Offer) => {
|
||||
const route = offer.routes?.[0]
|
||||
if (!route?.stages) return []
|
||||
return route.stages
|
||||
.filter((stage): stage is NonNullable<typeof stage> => stage !== null)
|
||||
.map((stage) => ({
|
||||
transportType: stage.transportType,
|
||||
distanceKm: stage.distanceKm,
|
||||
travelTimeSeconds: stage.travelTimeSeconds,
|
||||
fromName: stage.fromName
|
||||
}))
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -83,11 +83,33 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { GetOffersDocument, GetOfferDocument, type GetOffersQueryVariables, type GetOffersQueryResult } from '~/composables/graphql/public/exchange-generated'
|
||||
import { GetOffersDocument, GetOfferDocument, type GetOffersQueryVariables } from '~/composables/graphql/public/exchange-generated'
|
||||
import { GetNodeDocument, NearestOffersDocument } from '~/composables/graphql/public/geo-generated'
|
||||
import type { MapBounds } from '~/components/catalog/CatalogMap.vue'
|
||||
|
||||
// Offer type from search results
|
||||
type OfferResult = NonNullable<NonNullable<GetOffersQueryResult['getOffers']>[number]>
|
||||
type QuoteOffer = {
|
||||
uuid: string
|
||||
productUuid?: string | null
|
||||
productName?: string | null
|
||||
supplierUuid?: string | null
|
||||
supplierName?: string | null
|
||||
teamUuid?: string | null
|
||||
quantity?: number | string | null
|
||||
unit?: string | null
|
||||
pricePerUnit?: number | string | null
|
||||
currency?: string | null
|
||||
locationName?: string | null
|
||||
locationCountry?: string | null
|
||||
routes?: Array<{
|
||||
totalTimeSeconds?: number | null
|
||||
stages?: Array<{
|
||||
transportType?: string | null
|
||||
distanceKm?: number | null
|
||||
travelTimeSeconds?: number | null
|
||||
fromName?: string | null
|
||||
} | null> | null
|
||||
} | null> | null
|
||||
}
|
||||
|
||||
definePageMeta({
|
||||
layout: 'topnav'
|
||||
@@ -393,7 +415,7 @@ const relatedPoints = computed(() => {
|
||||
})
|
||||
|
||||
// Offers data for quote results
|
||||
const offers = ref<OfferResult[]>([])
|
||||
const offers = ref<QuoteOffer[]>([])
|
||||
const offersLoading = ref(false)
|
||||
const showQuoteResults = ref(false)
|
||||
|
||||
@@ -574,24 +596,69 @@ const onSearch = async () => {
|
||||
showQuoteResults.value = true
|
||||
|
||||
try {
|
||||
const vars: GetOffersQueryVariables = {}
|
||||
if (productId.value) vars.productUuid = productId.value
|
||||
if (supplierId.value) vars.teamUuid = supplierId.value
|
||||
if (hubId.value) vars.locationUuid = hubId.value
|
||||
// Prefer geo-based offers with routes when hub + product are selected
|
||||
if (hubId.value && productId.value) {
|
||||
const hubData = await execute(GetNodeDocument, { uuid: hubId.value }, 'public', 'geo')
|
||||
const hub = hubData?.node
|
||||
if (hub?.latitude != null && hub?.longitude != null) {
|
||||
const geoData = await execute(
|
||||
NearestOffersDocument,
|
||||
{
|
||||
lat: hub.latitude,
|
||||
lon: hub.longitude,
|
||||
productUuid: productId.value,
|
||||
hubUuid: hubId.value,
|
||||
radius: 500,
|
||||
limit: 12
|
||||
},
|
||||
'public',
|
||||
'geo'
|
||||
)
|
||||
|
||||
const data = await execute(GetOffersDocument, vars, 'public', 'exchange')
|
||||
offers.value = (data?.getOffers || []).filter((o): o is OfferResult => o !== null)
|
||||
let nearest = (geoData?.nearestOffers || []).filter((o): o is QuoteOffer => o !== null)
|
||||
if (supplierId.value) {
|
||||
nearest = nearest.filter(o => o?.supplierUuid === supplierId.value)
|
||||
}
|
||||
offers.value = nearest
|
||||
|
||||
// Update labels from response
|
||||
const first = offers.value[0]
|
||||
if (first) {
|
||||
if (productId.value && first.productName) {
|
||||
setLabel('product', productId.value, first.productName)
|
||||
const first = offers.value[0]
|
||||
if (first?.productName) {
|
||||
setLabel('product', productId.value, first.productName)
|
||||
}
|
||||
} else {
|
||||
offers.value = []
|
||||
}
|
||||
if (hubId.value && first.locationName) {
|
||||
setLabel('hub', hubId.value, first.locationName)
|
||||
} else {
|
||||
const vars: GetOffersQueryVariables = {}
|
||||
if (productId.value) vars.productUuid = productId.value
|
||||
if (supplierId.value) vars.teamUuid = supplierId.value
|
||||
if (hubId.value) vars.locationUuid = hubId.value
|
||||
|
||||
const data = await execute(GetOffersDocument, vars, 'public', 'exchange')
|
||||
const exchangeOffers = (data?.getOffers || []).filter((o): o is NonNullable<typeof o> => o !== null)
|
||||
offers.value = exchangeOffers.map((offer) => ({
|
||||
uuid: offer.uuid,
|
||||
productUuid: offer.productUuid,
|
||||
productName: offer.productName,
|
||||
teamUuid: offer.teamUuid,
|
||||
quantity: offer.quantity,
|
||||
unit: offer.unit,
|
||||
pricePerUnit: offer.pricePerUnit,
|
||||
currency: offer.currency,
|
||||
locationName: offer.locationName,
|
||||
locationCountry: offer.locationCountry
|
||||
}))
|
||||
|
||||
// Update labels from response
|
||||
const first = offers.value[0]
|
||||
if (first) {
|
||||
if (productId.value && first.productName) {
|
||||
setLabel('product', productId.value, first.productName)
|
||||
}
|
||||
if (hubId.value && first.locationName) {
|
||||
setLabel('hub', hubId.value, first.locationName)
|
||||
}
|
||||
}
|
||||
// Note: teamName not included in GetOffers query, supplier label cannot be updated from offer
|
||||
}
|
||||
} finally {
|
||||
offersLoading.value = false
|
||||
|
||||
Reference in New Issue
Block a user