refactor: remove all any types, add strict GraphQL scalar typing
All checks were successful
Build Docker Image / build (push) Successful in 4m3s
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:
@@ -46,9 +46,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { GetOrderDocument } from '~/composables/graphql/team/orders-generated'
|
||||
import { GetOrderDocument, type GetOrderQueryResult } from '~/composables/graphql/team/orders-generated'
|
||||
import type { RouteStageItem } from '~/components/RouteStagesList.vue'
|
||||
|
||||
// Types from GraphQL
|
||||
type OrderType = NonNullable<GetOrderQueryResult['getOrder']>
|
||||
type StageType = NonNullable<NonNullable<OrderType['stages']>[number]>
|
||||
type TripType = NonNullable<NonNullable<StageType['trips']>[number]>
|
||||
type CompanyType = NonNullable<StageType['selectedCompany']>
|
||||
|
||||
definePageMeta({
|
||||
layout: 'topnav',
|
||||
middleware: ['auth-oidc']
|
||||
@@ -57,7 +63,7 @@ definePageMeta({
|
||||
const route = useRoute()
|
||||
const { t } = useI18n()
|
||||
|
||||
const order = ref<any>(null)
|
||||
const order = ref<OrderType | null>(null)
|
||||
const isLoadingOrder = ref(true)
|
||||
const hasOrderError = ref(false)
|
||||
const orderError = ref('')
|
||||
@@ -96,8 +102,8 @@ const orderMeta = computed(() => {
|
||||
|
||||
const orderRoutesForMap = computed(() => {
|
||||
const stages = (order.value?.stages || [])
|
||||
.filter(Boolean)
|
||||
.map((stage: any) => {
|
||||
.filter((stage): stage is StageType => stage !== null)
|
||||
.map((stage) => {
|
||||
if (stage.stageType === 'transport') {
|
||||
if (!stage.sourceLatitude || !stage.sourceLongitude || !stage.destinationLatitude || !stage.destinationLongitude) return null
|
||||
return {
|
||||
@@ -118,33 +124,43 @@ const orderRoutesForMap = computed(() => {
|
||||
return [{ stages }]
|
||||
})
|
||||
|
||||
// Company summary type
|
||||
interface CompanySummary {
|
||||
name: string | null | undefined
|
||||
totalWeight: number
|
||||
tripsCount: number
|
||||
company: CompanyType | null | undefined
|
||||
}
|
||||
|
||||
const orderStageItems = computed<RouteStageItem[]>(() => {
|
||||
return (order.value?.stages || []).map((stage: any) => {
|
||||
const isTransport = stage.stageType === 'transport'
|
||||
const from = isTransport ? stage.sourceLocationName : stage.locationName
|
||||
const to = isTransport ? stage.destinationLocationName : stage.locationName
|
||||
return (order.value?.stages || [])
|
||||
.filter((stage): stage is StageType => stage !== null)
|
||||
.map((stage) => {
|
||||
const isTransport = stage.stageType === 'transport'
|
||||
const from = isTransport ? stage.sourceLocationName : stage.locationName
|
||||
const to = isTransport ? stage.destinationLocationName : stage.locationName
|
||||
|
||||
const meta: string[] = []
|
||||
const dateRange = getStageDateRange(stage)
|
||||
if (dateRange) {
|
||||
meta.push(dateRange)
|
||||
}
|
||||
const meta: string[] = []
|
||||
const dateRange = getStageDateRange(stage)
|
||||
if (dateRange) {
|
||||
meta.push(dateRange)
|
||||
}
|
||||
|
||||
const companies = getCompaniesSummary(stage)
|
||||
companies.forEach((company: any) => {
|
||||
meta.push(
|
||||
`${company.name} · ${company.totalWeight || 0}${t('ordersDetail.labels.weight_unit')} · ${company.tripsCount || 0} ${t('ordersDetail.labels.trips')}`
|
||||
)
|
||||
const companies = getCompaniesSummary(stage)
|
||||
companies.forEach((company: CompanySummary) => {
|
||||
meta.push(
|
||||
`${company.name} · ${company.totalWeight || 0}${t('ordersDetail.labels.weight_unit')} · ${company.tripsCount || 0} ${t('ordersDetail.labels.trips')}`
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
key: stage.uuid ?? undefined,
|
||||
from: from ?? undefined,
|
||||
to: to ?? undefined,
|
||||
label: stage.name ?? undefined,
|
||||
meta
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
key: stage.uuid,
|
||||
from,
|
||||
to,
|
||||
label: stage.name,
|
||||
meta
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const loadOrder = async () => {
|
||||
@@ -154,10 +170,10 @@ const loadOrder = async () => {
|
||||
const orderUuid = route.params.id as string
|
||||
const { data, error: orderErrorResp } = await useServerQuery('order-detail', GetOrderDocument, { orderUuid }, 'team', 'orders')
|
||||
if (orderErrorResp.value) throw orderErrorResp.value
|
||||
order.value = data.value?.getOrder
|
||||
} catch (err: any) {
|
||||
order.value = data.value?.getOrder ?? null
|
||||
} catch (err: unknown) {
|
||||
hasOrderError.value = true
|
||||
orderError.value = err.message || t('ordersDetail.errors.load_failed')
|
||||
orderError.value = err instanceof Error ? err.message : t('ordersDetail.errors.load_failed')
|
||||
} finally {
|
||||
isLoadingOrder.value = false
|
||||
}
|
||||
@@ -172,8 +188,8 @@ const formatPrice = (price: number, currency?: string | null) => {
|
||||
}).format(price)
|
||||
}
|
||||
|
||||
const getCompaniesSummary = (stage: any) => {
|
||||
const companies = []
|
||||
const getCompaniesSummary = (stage: StageType): CompanySummary[] => {
|
||||
const companies: CompanySummary[] = []
|
||||
if (stage.stageType === 'service' && stage.selectedCompany) {
|
||||
companies.push({
|
||||
name: stage.selectedCompany.name,
|
||||
@@ -185,12 +201,13 @@ const getCompaniesSummary = (stage: any) => {
|
||||
}
|
||||
|
||||
if (stage.stageType === 'transport' && stage.trips?.length) {
|
||||
const companiesMap = new Map()
|
||||
stage.trips.forEach((trip: any) => {
|
||||
const companiesMap = new Map<string, CompanySummary>()
|
||||
stage.trips.forEach((trip) => {
|
||||
if (!trip) return
|
||||
const companyName = trip.company?.name || t('ordersDetail.labels.company_unknown')
|
||||
const weight = trip.plannedWeight || 0
|
||||
if (companiesMap.has(companyName)) {
|
||||
const existing = companiesMap.get(companyName)
|
||||
const existing = companiesMap.get(companyName)!
|
||||
existing.totalWeight += weight
|
||||
existing.tripsCount += 1
|
||||
} else {
|
||||
@@ -211,10 +228,12 @@ const getOrderDuration = () => {
|
||||
if (!order.value?.stages?.length) return 0
|
||||
let minDate: Date | null = null
|
||||
let maxDate: Date | null = null
|
||||
order.value.stages.forEach((stage: any) => {
|
||||
stage.trips?.forEach((trip: any) => {
|
||||
const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate)
|
||||
const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate)
|
||||
order.value.stages.forEach((stage) => {
|
||||
if (!stage) return
|
||||
stage.trips?.forEach((trip) => {
|
||||
if (!trip) return
|
||||
const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate || '')
|
||||
const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate || '')
|
||||
if (!minDate || startDate < minDate) minDate = startDate
|
||||
if (!maxDate || endDate > maxDate) maxDate = endDate
|
||||
})
|
||||
@@ -224,13 +243,14 @@ const getOrderDuration = () => {
|
||||
return Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||
}
|
||||
|
||||
const getStageDateRange = (stage: any) => {
|
||||
const getStageDateRange = (stage: StageType) => {
|
||||
if (!stage.trips?.length) return t('ordersDetail.labels.dates_undefined')
|
||||
let minDate: Date | null = null
|
||||
let maxDate: Date | null = null
|
||||
stage.trips.forEach((trip: any) => {
|
||||
const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate)
|
||||
const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate)
|
||||
stage.trips.forEach((trip) => {
|
||||
if (!trip) return
|
||||
const startDate = new Date(trip.plannedLoadingDate || trip.actualLoadingDate || '')
|
||||
const endDate = new Date(trip.plannedUnloadingDate || trip.actualUnloadingDate || '')
|
||||
if (!minDate || startDate < minDate) minDate = startDate
|
||||
if (!maxDate || endDate > maxDate) maxDate = endDate
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user