Update catalog pages to use new geo queries
Some checks failed
Build Docker Image / build (push) Failing after 1m35s

- Replace FindProductRoutesDocument with GetOffersToHubDocument
- Replace FindSupplierProductHubsDocument with GetOffersBySupplierProductDocument + GetHubsNearOfferDocument
- Update all catalog pages to use new query naming convention
- Add new GraphQL operation files, remove deprecated ones
This commit is contained in:
Ruslan Bakiev
2026-01-16 15:40:06 +07:00
parent e869c2065f
commit 2253cd20b0
19 changed files with 232 additions and 188 deletions

View File

@@ -1,4 +1,4 @@
import { GetAvailableProductsDocument } from '~/composables/graphql/public/exchange-generated' import { GetProductsDocument } from '~/composables/graphql/public/geo-generated'
// Shared state // Shared state
const items = ref<any[]>([]) const items = ref<any[]>([])
@@ -13,12 +13,12 @@ export function useCatalogProducts() {
isLoading.value = true isLoading.value = true
try { try {
const data = await execute( const data = await execute(
GetAvailableProductsDocument, GetProductsDocument,
{}, {},
'public', 'public',
'exchange' 'geo'
) )
items.value = data?.getAvailableProducts || [] items.value = data?.products || []
isInitialized.value = true isInitialized.value = true
} finally { } finally {
isLoading.value = false isLoading.value = false

View File

@@ -94,7 +94,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetNodeConnectionsDocument, FindProductRoutesDocument } from '~/composables/graphql/public/geo-generated' import { GetNodeConnectionsDocument, GetOffersToHubDocument } from '~/composables/graphql/public/geo-generated'
import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated' import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated'
definePageMeta({ definePageMeta({
@@ -225,7 +225,7 @@ const loadOfferDetails = async () => {
offersData.value = newOffersData offersData.value = newOffersData
} }
// Load routes // Load offers with routes to this hub
const loadRoutes = async () => { const loadRoutes = async () => {
if (!productId.value || !hubId.value) { if (!productId.value || !hubId.value) {
rawSources.value = [] rawSources.value = []
@@ -238,20 +238,19 @@ const loadRoutes = async () => {
try { try {
const data = await execute( const data = await execute(
FindProductRoutesDocument, GetOffersToHubDocument,
{ {
hubUuid: hubId.value,
productUuid: productId.value, productUuid: productId.value,
toUuid: hubId.value, limit: 12
limitSources: 12,
limitRoutes: 1
}, },
'public', 'public',
'geo' 'geo'
) )
rawSources.value = (data?.findProductRoutes || []).filter(Boolean) rawSources.value = (data?.offersToHub || []).filter(Boolean)
await loadOfferDetails() await loadOfferDetails()
} catch (error) { } catch (error) {
console.error('Error loading routes:', error) console.error('Error loading offers:', error)
rawSources.value = [] rawSources.value = []
} finally { } finally {
isLoadingRoutes.value = false isLoadingRoutes.value = false

View File

@@ -62,8 +62,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetNodeConnectionsDocument, FindProductsForHubDocument } from '~/composables/graphql/public/geo-generated' import { GetNodeConnectionsDocument, GetProductsNearHubDocument } from '~/composables/graphql/public/geo-generated'
import { GetAvailableProductsDocument } from '~/composables/graphql/public/exchange-generated'
definePageMeta({ definePageMeta({
layout: 'topnav' layout: 'topnav'
@@ -119,19 +118,17 @@ const getMockPriceHistory = (uuid: string): number[] => {
// Initial load // Initial load
try { try {
const [{ data: connectionsData }, { data: productUuidsData }, { data: allProductsData }] = await Promise.all([ const [{ data: connectionsData }, { data: productsData }] = await Promise.all([
useServerQuery('hub-connections', GetNodeConnectionsDocument, { uuid: hubId.value }, 'public', 'geo'), useServerQuery('hub-connections', GetNodeConnectionsDocument, { uuid: hubId.value }, 'public', 'geo'),
useServerQuery('hub-product-uuids', FindProductsForHubDocument, { hubUuid: hubId.value }, 'public', 'geo'), useServerQuery('products-near-hub', GetProductsNearHubDocument, { hubUuid: hubId.value, radiusKm: 500 }, 'public', 'geo')
useServerQuery('available-products', GetAvailableProductsDocument, {}, 'public', 'exchange')
]) ])
hub.value = connectionsData.value?.nodeConnections?.hub || null hub.value = connectionsData.value?.nodeConnections?.hub || null
// Filter products by UUIDs that can be delivered to this hub // Get products near this hub (from geo)
const relevantUuids = new Set(productUuidsData.value?.findProductsForHub?.filter(Boolean) || []) products.value = (productsData.value?.productsNearHub || [])
products.value = (allProductsData.value?.getAvailableProducts || []) .filter((p): p is { uuid: string; name?: string | null } => p !== null && !!p.uuid)
.filter((p): p is { uuid: string; name: string } => p !== null && !!p.uuid && !!p.name && relevantUuids.has(p.uuid)) .map(p => ({ uuid: p.uuid!, name: p.name || '' }))
.map(p => ({ uuid: p.uuid!, name: p.name! }))
} catch (error) { } catch (error) {
console.error('Error loading hub:', error) console.error('Error loading hub:', error)
} finally { } finally {

View File

@@ -94,7 +94,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetNodeConnectionsDocument, FindProductRoutesDocument } from '~/composables/graphql/public/geo-generated' import { GetNodeConnectionsDocument, GetOffersToHubDocument } from '~/composables/graphql/public/geo-generated'
import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated' import { GetAvailableProductsDocument, GetOfferDocument } from '~/composables/graphql/public/exchange-generated'
definePageMeta({ definePageMeta({
@@ -225,7 +225,7 @@ const loadOfferDetails = async () => {
offersData.value = newOffersData offersData.value = newOffersData
} }
// Load routes // Load offers with routes to this hub
const loadRoutes = async () => { const loadRoutes = async () => {
if (!productId.value || !hubId.value) { if (!productId.value || !hubId.value) {
rawSources.value = [] rawSources.value = []
@@ -238,20 +238,19 @@ const loadRoutes = async () => {
try { try {
const data = await execute( const data = await execute(
FindProductRoutesDocument, GetOffersToHubDocument,
{ {
hubUuid: hubId.value,
productUuid: productId.value, productUuid: productId.value,
toUuid: hubId.value, limit: 12
limitSources: 12,
limitRoutes: 1
}, },
'public', 'public',
'geo' 'geo'
) )
rawSources.value = (data?.findProductRoutes || []).filter(Boolean) rawSources.value = (data?.offersToHub || []).filter(Boolean)
await loadOfferDetails() await loadOfferDetails()
} catch (error) { } catch (error) {
console.error('Error loading routes:', error) console.error('Error loading offers:', error)
rawSources.value = [] rawSources.value = []
} finally { } finally {
isLoadingRoutes.value = false isLoadingRoutes.value = false

View File

@@ -77,8 +77,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetAvailableProductsDocument } from '~/composables/graphql/public/exchange-generated' import { GetOffersByProductDocument, GetHubsNearOfferDocument } from '~/composables/graphql/public/geo-generated'
import { FindHubsForProductDocument } from '~/composables/graphql/public/geo-generated'
definePageMeta({ definePageMeta({
layout: 'topnav' layout: 'topnav'
@@ -155,20 +154,35 @@ const chartSeries = computed(() => [{
// Initial load // Initial load
try { try {
const [{ data: productsData }, { data: hubsData }] = await Promise.all([ // Get offers for this product from geo
useServerQuery('product-info', GetAvailableProductsDocument, {}, 'public', 'exchange'), const { data: offersData } = await useServerQuery(
useServerQuery('hubs-for-product', FindHubsForProductDocument, { productUuid: productId.value }, 'public', 'geo') 'offers-for-product',
]) GetOffersByProductDocument,
{ productUuid: productId.value },
'public',
'geo'
)
const foundProduct = (productsData.value?.getAvailableProducts || []) const offers = offersData.value?.offersByProduct || []
.find(p => p?.uuid === productId.value)
if (foundProduct) { if (offers.length > 0) {
product.value = { uuid: foundProduct.uuid!, name: foundProduct.name || '' } const firstOffer = offers[0]
product.value = {
uuid: productId.value,
name: firstOffer?.productName || ''
} }
// Get only hubs where this product can be delivered // Get hubs near the first offer's location
hubs.value = (hubsData.value?.findHubsForProduct || []) if (firstOffer?.uuid) {
const { data: hubsData } = await useServerQuery(
'hubs-near-offer',
GetHubsNearOfferDocument,
{ offerUuid: firstOffer.uuid, limit: 12 },
'public',
'geo'
)
hubs.value = (hubsData.value?.hubsNearOffer || [])
.filter((h): h is NonNullable<typeof h> => h !== null && !!h.uuid && !!h.name) .filter((h): h is NonNullable<typeof h> => h !== null && !!h.uuid && !!h.name)
.map(h => ({ .map(h => ({
uuid: h.uuid!, uuid: h.uuid!,
@@ -178,6 +192,8 @@ try {
country: h.country || undefined, country: h.country || undefined,
countryCode: h.countryCode || undefined countryCode: h.countryCode || undefined
})) }))
}
}
} catch (error) { } catch (error) {
console.error('Error loading product hubs:', error) console.error('Error loading product hubs:', error)
} finally { } finally {

View File

@@ -126,12 +126,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { GetNodeConnectionsDocument, FindRoutesDocument } from '~/composables/graphql/public/geo-generated' import { GetNodeConnectionsDocument, GetOffersBySupplierProductDocument, GetDeliveryToHubDocument } from '~/composables/graphql/public/geo-generated'
import { import {
GetSupplierProfileDocument, GetSupplierProfileDocument,
GetSupplierOffersDocument,
GetSupplierProfilesDocument, GetSupplierProfilesDocument,
GetOffersDocument,
} from '~/composables/graphql/public/exchange-generated' } from '~/composables/graphql/public/exchange-generated'
definePageMeta({ definePageMeta({
@@ -264,9 +262,9 @@ const chartSeries = computed(() => [{
data: priceHistory.value data: priceHistory.value
}]) }])
// Load route using FindRoutes (single source!) // Load route using delivery to hub
const loadRoute = async () => { const loadRoute = async (offerUuid: string) => {
if (!sourceLocation.value || !hubId.value) { if (!offerUuid || !hubId.value) {
routeData.value = null routeData.value = null
return return
} }
@@ -274,16 +272,15 @@ const loadRoute = async () => {
isLoadingRoute.value = true isLoadingRoute.value = true
try { try {
const data = await execute( const data = await execute(
FindRoutesDocument, GetDeliveryToHubDocument,
{ {
fromUuid: sourceLocation.value.uuid, offerUuid,
toUuid: hubId.value, hubUuid: hubId.value
limit: 1
}, },
'public', 'public',
'geo' 'geo'
) )
routeData.value = data?.findRoutes?.[0] || null routeData.value = data?.deliveryToHub?.routes?.[0] || null
} catch (error) { } catch (error) {
console.error('Error loading route:', error) console.error('Error loading route:', error)
routeData.value = null routeData.value = null
@@ -304,7 +301,7 @@ try {
) )
hub.value = hubData.value?.nodeConnections?.hub || null hub.value = hubData.value?.nodeConnections?.hub || null
// Get supplier // Get supplier profile from exchange
const { data: supplierData } = await useServerQuery( const { data: supplierData } = await useServerQuery(
'supplier-profile', 'supplier-profile',
GetSupplierProfileDocument, GetSupplierProfileDocument,
@@ -326,53 +323,40 @@ try {
.find((s: any) => s?.teamUuid === supplierId.value || s?.uuid === supplierId.value) || null .find((s: any) => s?.teamUuid === supplierId.value || s?.uuid === supplierId.value) || null
} }
// Get supplier's offers to find product and source location // Get offers for this supplier+product from geo
if (supplier.value) { if (supplier.value) {
const teamIds = [supplier.value?.teamUuid, supplier.value?.uuid, supplierId.value].filter(Boolean) const supplierUuidForGeo = supplier.value?.uuid || supplierId.value
const primaryId = teamIds[0] as string
const { data: offersData } = await useServerQuery( const { data: offersData } = await useServerQuery(
'supplier-offers', 'supplier-product-offers',
GetSupplierOffersDocument, GetOffersBySupplierProductDocument,
{ teamUuid: primaryId }, { supplierUuid: supplierUuidForGeo, productUuid: productId.value },
'public', 'public',
'exchange' 'geo'
) )
let offers = offersData.value?.getOffers || []
if (!offers.length) { const offers = offersData.value?.offersBySupplierProduct || []
const { data: allOffersData } = await useServerQuery(
'supplier-offers-fallback', // Use first offer for product info and source location
GetOffersDocument, if (offers.length > 0) {
{}, const firstOffer = offers[0]
'public', if (firstOffer?.productUuid && firstOffer?.productName) {
'exchange' product.value = { uuid: firstOffer.productUuid, name: firstOffer.productName }
)
const ids = new Set(teamIds)
offers = (allOffersData.value?.getOffers || []).filter((o: any) => o?.teamUuid && ids.has(o.teamUuid))
} }
if (firstOffer?.latitude && firstOffer?.longitude) {
// Find product and source location in offers
for (const offer of offers) {
const line = offer.lines?.find((l: any) => l?.productUuid === productId.value)
if (line) {
product.value = { uuid: line.productUuid, name: line.productName }
if (offer.locationUuid && offer.locationName) {
sourceLocation.value = { sourceLocation.value = {
uuid: offer.locationUuid, uuid: firstOffer.uuid || '',
name: offer.locationName, name: firstOffer.country || 'Origin',
latitude: offer.locationLat, latitude: firstOffer.latitude,
longitude: offer.locationLon longitude: firstOffer.longitude
}
}
break
}
} }
} }
// Load route after getting source location // Load route using the offer UUID
if (sourceLocation.value && hub.value) { if (firstOffer?.uuid && hub.value) {
await loadRoute() await loadRoute(firstOffer.uuid)
}
}
} }
} catch (error) { } catch (error) {
console.error('Error loading data:', error) console.error('Error loading data:', error)

View File

@@ -92,12 +92,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { FindSupplierProductHubsDocument } from '~/composables/graphql/public/geo-generated' import { GetOffersBySupplierProductDocument, GetHubsNearOfferDocument } from '~/composables/graphql/public/geo-generated'
import { import {
GetSupplierProfileDocument, GetSupplierProfileDocument,
GetSupplierOffersDocument,
GetSupplierProfilesDocument, GetSupplierProfilesDocument,
GetOffersDocument,
} from '~/composables/graphql/public/exchange-generated' } from '~/composables/graphql/public/exchange-generated'
definePageMeta({ definePageMeta({
@@ -178,7 +176,7 @@ const chartSeries = computed(() => [{
// Load data // Load data
try { try {
// Get supplier // Get supplier profile from exchange
const { data: supplierData } = await useServerQuery( const { data: supplierData } = await useServerQuery(
'supplier-profile', 'supplier-profile',
GetSupplierProfileDocument, GetSupplierProfileDocument,
@@ -200,57 +198,44 @@ try {
.find((s: any) => s?.teamUuid === supplierId.value || s?.uuid === supplierId.value) || null .find((s: any) => s?.teamUuid === supplierId.value || s?.uuid === supplierId.value) || null
} }
// Get supplier's offers to find product and location // Get offers for this supplier+product from geo
if (supplier.value) { if (supplier.value) {
const teamIds = [supplier.value?.teamUuid, supplier.value?.uuid, supplierId.value].filter(Boolean) const supplierUuidForGeo = supplier.value?.uuid || supplierId.value
const primaryId = teamIds[0] as string
const { data: offersData } = await useServerQuery( const { data: offersData } = await useServerQuery(
'supplier-offers', 'supplier-product-offers',
GetSupplierOffersDocument, GetOffersBySupplierProductDocument,
{ teamUuid: primaryId },
'public',
'exchange'
)
let offers = offersData.value?.getOffers || []
if (!offers.length) {
const { data: allOffersData } = await useServerQuery(
'supplier-offers-fallback',
GetOffersDocument,
{},
'public',
'exchange'
)
const ids = new Set(teamIds)
offers = (allOffersData.value?.getOffers || []).filter((o: any) => o?.teamUuid && ids.has(o.teamUuid))
}
// Find product in offers
for (const offer of offers) {
if (offer.productUuid === productId.value && offer.productName) {
product.value = { uuid: offer.productUuid, name: offer.productName }
if (offer.locationUuid && offer.locationName) {
sourceLocation.value = { uuid: offer.locationUuid, name: offer.locationName }
}
break
}
}
}
// Get hubs where this supplier can deliver this product
if (supplier.value && product.value) {
// Use supplier.uuid (public) for geo query, not teamUuid (internal)
const supplierUuidForGeo = supplier.value?.uuid || supplierId.value
const { data: hubsData } = await useServerQuery(
'supplier-product-hubs',
FindSupplierProductHubsDocument,
{ supplierUuid: supplierUuidForGeo, productUuid: productId.value }, { supplierUuid: supplierUuidForGeo, productUuid: productId.value },
'public', 'public',
'geo' 'geo'
) )
hubs.value = (hubsData.value?.findSupplierProductHubs || []) const offers = offersData.value?.offersBySupplierProduct || []
// Set product info from first offer
if (offers.length > 0) {
const firstOffer = offers[0]
if (firstOffer?.productUuid && firstOffer?.productName) {
product.value = { uuid: firstOffer.productUuid, name: firstOffer.productName }
}
// Source location is the offer's location (first offer)
if (firstOffer?.latitude && firstOffer?.longitude) {
sourceLocation.value = {
uuid: firstOffer.uuid || '',
name: firstOffer.country || 'Origin'
}
}
// Get hubs near the first offer
const { data: hubsData } = await useServerQuery(
'hubs-near-offer',
GetHubsNearOfferDocument,
{ offerUuid: firstOffer.uuid, limit: 20 },
'public',
'geo'
)
hubs.value = (hubsData.value?.hubsNearOffer || [])
.filter((h): h is NonNullable<typeof h> => h !== null && !!h.uuid && !!h.name) .filter((h): h is NonNullable<typeof h> => h !== null && !!h.uuid && !!h.name)
.map(h => ({ .map(h => ({
uuid: h.uuid!, uuid: h.uuid!,
@@ -261,6 +246,7 @@ try {
countryCode: h.countryCode || undefined countryCode: h.countryCode || undefined
})) }))
} }
}
} catch (error) { } catch (error) {
console.error('Error loading data:', error) console.error('Error loading data:', error)
} finally { } finally {

View File

@@ -1,11 +0,0 @@
query FindHubsForProduct($productUuid: String!) {
findHubsForProduct(productUuid: $productUuid) {
uuid
name
latitude
longitude
country
countryCode
transportTypes
}
}

View File

@@ -1,3 +0,0 @@
query FindProductsForHub($hubUuid: String!) {
findProductsForHub(hubUuid: $hubUuid)
}

View File

@@ -1,11 +0,0 @@
query FindSupplierProductHubs($supplierUuid: String!, $productUuid: String!) {
findSupplierProductHubs(supplierUuid: $supplierUuid, productUuid: $productUuid) {
uuid
name
latitude
longitude
country
countryCode
transportTypes
}
}

View File

@@ -1,9 +1,5 @@
query FindOffersForHubByProduct($hubUuid: String!, $productUuid: String!, $limitSources: Int) { query GetDeliveryToHub($offerUuid: String!, $hubUuid: String!) {
findOffersForHubByProduct( deliveryToHub(offerUuid: $offerUuid, hubUuid: $hubUuid) {
hubUuid: $hubUuid
productUuid: $productUuid
limitSources: $limitSources
) {
sourceUuid sourceUuid
sourceName sourceName
sourceLat sourceLat

View File

@@ -0,0 +1,11 @@
query GetHubsNearOffer($offerUuid: String!, $limit: Int) {
hubsNearOffer(offerUuid: $offerUuid, limit: $limit) {
uuid
name
latitude
longitude
country
countryCode
transportTypes
}
}

View File

@@ -0,0 +1,16 @@
query GetOffersByProduct($productUuid: String!) {
offersByProduct(productUuid: $productUuid) {
uuid
productUuid
productName
supplierUuid
latitude
longitude
country
countryCode
pricePerUnit
currency
quantity
unit
}
}

View File

@@ -0,0 +1,16 @@
query GetOffersBySupplierProduct($supplierUuid: String!, $productUuid: String!) {
offersBySupplierProduct(supplierUuid: $supplierUuid, productUuid: $productUuid) {
uuid
productUuid
productName
supplierUuid
latitude
longitude
country
countryCode
pricePerUnit
currency
quantity
unit
}
}

View File

@@ -0,0 +1,26 @@
query GetOffersToHub($hubUuid: String!, $productUuid: String!, $limit: Int) {
offersToHub(hubUuid: $hubUuid, productUuid: $productUuid, limit: $limit) {
sourceUuid
sourceName
sourceLat
sourceLon
distanceKm
routes {
totalDistanceKm
totalTimeSeconds
stages {
fromUuid
fromName
fromLat
fromLon
toUuid
toName
toLat
toLon
distanceKm
travelTimeSeconds
transportType
}
}
}
}

View File

@@ -0,0 +1,6 @@
query GetProducts {
products {
uuid
name
}
}

View File

@@ -0,0 +1,6 @@
query GetProductsBySupplier($supplierUuid: String!) {
productsBySupplier(supplierUuid: $supplierUuid) {
uuid
name
}
}

View File

@@ -0,0 +1,6 @@
query GetProductsNearHub($hubUuid: String!, $radiusKm: Float) {
productsNearHub(hubUuid: $hubUuid, radiusKm: $radiusKm) {
uuid
name
}
}

View File

@@ -0,0 +1,5 @@
query GetSuppliers {
suppliers {
uuid
}
}