From 8a8a1b73165234977d9a8aecccea01cad417ac89 Mon Sep 17 00:00:00 2001 From: natib21 Date: Mon, 29 Jun 2026 09:11:48 +0000 Subject: [PATCH] fix --- .../src/pages/operations/FirstMilePage.tsx | 27 ++++++++++++-- .../backoffice/src/services/rates.service.ts | 35 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 apps/edr-freight-web/backoffice/src/services/rates.service.ts diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx index cd16b92ba..a9cab6247 100644 --- a/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/operations/FirstMilePage.tsx @@ -43,6 +43,7 @@ import { } from "@/services/first-mile.service"; import { bookingsService } from "@/services/bookings.service"; import { vehiclesService } from "@/services/vehicles.service"; +import { ratesService } from "@/services/rates.service"; import type { BookingDetail } from "@/types/booking"; const formatPrice = (amount: number) => @@ -348,6 +349,14 @@ const FirstMilePage = () => { }, }); + const { data: ratesData } = useQuery({ + queryKey: ["rates", "FIRST_MILE"], + queryFn: async () => { + const res = await ratesService.getByType("FIRST_MILE"); + return res.data; + }, + }); + const { data: paidBookingsData, isLoading: bookingsLoading } = useQuery({ queryKey: QUERY_KEYS.BOOKINGS.list({ status: "PAID" }), queryFn: () => bookingsService.list({ status: "PAID", pageSize: 100 }), @@ -385,8 +394,8 @@ const FirstMilePage = () => { }); const updateDistanceMutation = useMutation({ - mutationFn: ({ id, exactKm }: { id: string; exactKm: number }) => - firstMileService.update(id, { exactKm }), + mutationFn: ({ id, exactKm, remainingPayment }: { id: string; exactKm: number; remainingPayment?: number }) => + firstMileService.update(id, { exactKm, ...(remainingPayment != null && { remainingPayment }) }), onSuccess: () => { void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT }); if (activeRecord) { @@ -492,7 +501,19 @@ const FirstMilePage = () => { toast({ title: "Invalid distance", description: "Enter a valid distance value.", variant: "destructive" }); return; } - updateDistanceMutation.mutate({ id: activeId, exactKm: distance }); + + let remainingPayment: number | undefined; + if (ratesData?.data) { + const firstMileRate = ratesData.data.find( + (r) => r.rateType === "FIRST_MILE" && r.status === "LIVE" + ); + if (firstMileRate) { + const rateValue = parseFloat(firstMileRate.rateValue); + remainingPayment = distance * rateValue; + } + } + + updateDistanceMutation.mutate({ id: activeId, exactKm: distance, remainingPayment }); }; const matchesFilter = (r: FirstMileRecord) => { diff --git a/apps/edr-freight-web/backoffice/src/services/rates.service.ts b/apps/edr-freight-web/backoffice/src/services/rates.service.ts new file mode 100644 index 000000000..589f3ea13 --- /dev/null +++ b/apps/edr-freight-web/backoffice/src/services/rates.service.ts @@ -0,0 +1,35 @@ +import { api } from '../auth/http'; + +export interface Rate { + id: string; + rateType: string; + appliesTo: string; + trigger: string; + containerTypeId: string | null; + cargoTypeId: string | null; + tradeDirection: string | null; + currency: string; + rateValue: string; + rateUnit: string; + status: string; + proposedByStaffId: string; + approvedByCeoId: string | null; + approvedAt: string | null; + effectiveFrom: string; + effectiveTo: string | null; + createdAt: string; + updatedAt: string; + deletedAt: string | null; +} + +export interface RatesListResponse { + data: Rate[]; + meta: { total: number; page: number; pageSize: number; totalPages: number }; +} + +export const ratesService = { + list: (pageSize = 1000) => + api.get(`/rates?pageSize=${pageSize}`), + getByType: (rateType: string) => + api.get(`/rates?rateType=${rateType}&pageSize=1000`), +};