refactor: remove all any types, add strict GraphQL scalar typing
All checks were successful
Build Docker Image / build (push) Successful in 4m3s

- Add strictScalars: true to codegen.ts with proper scalar mappings
  (Date, Decimal, JSONString, JSON, UUID, BigInt → string/Record)
- Replace all ref<any[]> with proper GraphQL-derived types
- Add type guards for null filtering in arrays
- Fix bugs exposed by typing (locationLatitude vs latitude, etc.)
- Add interfaces for external components (MapboxSearchBox)

This enables end-to-end type safety from GraphQL schema to frontend.
This commit is contained in:
Ruslan Bakiev
2026-01-27 11:34:12 +07:00
parent ff34c564e1
commit 2dbe600d8a
42 changed files with 614 additions and 324 deletions

View File

@@ -22,7 +22,7 @@
:key="option.sourceUuid ?? index"
:location-name="getOfferData(option.sourceUuid)?.locationName"
:product-name="productName"
:price-per-unit="getOfferData(option.sourceUuid)?.pricePerUnit"
:price-per-unit="parseFloat(getOfferData(option.sourceUuid)?.pricePerUnit || '0') || null"
:currency="getOfferData(option.sourceUuid)?.currency"
:unit="getOfferData(option.sourceUuid)?.unit"
:stages="getRouteStages(option)"
@@ -81,7 +81,8 @@ interface RoutePathType {
totalTimeSeconds?: number | null
stages?: (RouteStage | null)[]
}
import { GetOfferDocument, GetSupplierProfileByTeamDocument } from '~/composables/graphql/public/exchange-generated'
import { GetOfferDocument, GetSupplierProfileByTeamDocument, type GetOfferQueryResult, type GetSupplierProfileByTeamQueryResult } from '~/composables/graphql/public/exchange-generated'
import type { OfferWithRouteType, RouteStageType } from '~/composables/graphql/public/geo-generated'
const route = useRoute()
const localePath = useLocalePath()
@@ -90,12 +91,14 @@ const { execute } = useGraphQL()
const productName = computed(() => searchStore.searchForm.product || (route.query.product as string) || 'Товар')
const locationName = computed(() => searchStore.searchForm.location || (route.query.location as string) || 'Назначение')
const quantity = computed(() => (route.query.quantity as string) || (searchStore.searchForm as any)?.quantity)
const quantity = computed(() => (route.query.quantity as string) || searchStore.searchForm.quantity)
// Offer data for prices
const offersData = ref<Map<string, any>>(new Map())
type OfferData = NonNullable<GetOfferQueryResult['getOffer']>
const offersData = ref<Map<string, OfferData>>(new Map())
// Supplier data for KYC profile UUID (by team_uuid)
const suppliersData = ref<Map<string, any>>(new Map())
type SupplierData = NonNullable<GetSupplierProfileByTeamQueryResult['getSupplierProfileByTeam']>
const suppliersData = ref<Map<string, SupplierData>>(new Map())
const summaryTitle = computed(() => `${productName.value}${locationName.value}`)
const summaryMeta = computed(() => {
@@ -149,14 +152,16 @@ const fetchOffersByHub = async () => {
const offers = offersResponse?.nearestOffers || []
// Offers already include routes from backend
const offersWithRoutes = offers.map((offer: any) => ({
sourceUuid: offer.uuid,
sourceName: offer.productName,
sourceLat: offer.latitude,
sourceLon: offer.longitude,
distanceKm: offer.distanceKm,
routes: offer.routes || []
}))
const offersWithRoutes = offers
.filter((offer): offer is NonNullable<OfferWithRouteType> => offer !== null)
.map((offer) => ({
sourceUuid: offer.uuid,
sourceName: offer.productName,
sourceLat: offer.latitude,
sourceLon: offer.longitude,
distanceKm: offer.distanceKm,
routes: offer.routes || []
}))
return { offersByHub: offersWithRoutes }
}
@@ -198,10 +203,12 @@ const mapRouteStages = (route: RoutePathType): RouteStageItem[] => {
const getRouteStages = (option: ProductRouteOption) => {
const route = option.routes?.[0]
if (!route?.stages) return []
return route.stages.filter(Boolean).map((stage: any) => ({
transportType: stage?.transportType,
distanceKm: stage?.distanceKm
}))
return route.stages
.filter((stage): stage is NonNullable<RouteStageType> => stage !== null)
.map((stage) => ({
transportType: stage.transportType,
distanceKm: stage.distanceKm
}))
}
// Get offer data for card
@@ -233,8 +240,8 @@ const loadOfferDetails = async (options: ProductRouteOption[]) => {
return
}
const newOffersData = new Map<string, any>()
const newSuppliersData = new Map<string, any>()
const newOffersData = new Map<string, OfferData>()
const newSuppliersData = new Map<string, SupplierData>()
const teamUuidsToLoad = new Set<string>()
// First, load all offers