mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 19:30:57 +00:00
refactor: migrate from most of the custom hooks into the api.ts
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { FileSignature, Loader2 } from "lucide-react";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { api } from "@/services/api";
|
||||
import { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
|
||||
import {
|
||||
Card,
|
||||
@@ -10,10 +13,6 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { useAuth } from "@/auth/useAuth";
|
||||
import {
|
||||
useMySignature,
|
||||
useSaveSignature,
|
||||
} from "@/hooks/useSavedSignature";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -33,8 +32,10 @@ import {
|
||||
*/
|
||||
export function MySignatureCard() {
|
||||
const { user } = useAuth();
|
||||
const { data: saved, isLoading } = useMySignature();
|
||||
const saveMutation = useSaveSignature();
|
||||
const { data: saved, isLoading } = useQuery(
|
||||
api.signatures.mySignature.queryOptions({ staleTime: 60_000 }),
|
||||
);
|
||||
const saveMutation = useMutation(api.signatures.save.mutationOptions());
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [signerName, setSignerName] = useState("");
|
||||
@@ -56,7 +57,13 @@ export function MySignatureCard() {
|
||||
signerDisplayName: signerName.trim(),
|
||||
signatureImageBase64: signatureData,
|
||||
},
|
||||
{ onSuccess: () => setOpen(false) },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success("Signature saved");
|
||||
setOpen(false);
|
||||
},
|
||||
onError: () => toast.error("Failed to save signature"),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,13 +31,8 @@ import {
|
||||
Weight,
|
||||
} from "lucide-react";
|
||||
|
||||
import {
|
||||
useAvailableLocomotives,
|
||||
useEligibleBookings,
|
||||
useScheduleList,
|
||||
useScheduleMutations,
|
||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useRoutes } from "@/hooks/useRoutes";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { trainSchedulingService } from "@/services/trainScheduling.service";
|
||||
import type { BookingDetail } from "@/types/booking";
|
||||
@@ -133,13 +128,27 @@ export function AllocateBookingWizard({
|
||||
[originId, destinationId],
|
||||
);
|
||||
|
||||
const eligibleQuery = useEligibleBookings(eligibleFilters, opened);
|
||||
const schedulesQuery = useScheduleList();
|
||||
const routesQuery = useRoutes();
|
||||
const locomotivesQuery = useAvailableLocomotives(
|
||||
scheduleMode === "new" && routeId ? routeId : undefined,
|
||||
const eligibleQuery = useQuery(
|
||||
api.trainScheduling.eligibleBookings.queryOptions({
|
||||
input: { filters: eligibleFilters },
|
||||
enabled: opened,
|
||||
}),
|
||||
);
|
||||
const { create, preview, assign, finalize } = useScheduleMutations(selectedScheduleId ?? undefined);
|
||||
const schedulesQuery = useQuery(
|
||||
api.trainScheduling.scheduleList.queryOptions({ input: {} }),
|
||||
);
|
||||
const routesQuery = useQuery(api.routes.list.queryOptions());
|
||||
const locomotivesQuery = useQuery(
|
||||
api.trainScheduling.availableLocomotives.queryOptions({
|
||||
input: {
|
||||
routeId: scheduleMode === "new" && routeId ? routeId : undefined,
|
||||
},
|
||||
}),
|
||||
);
|
||||
const create = useMutation(api.trainScheduling.createSchedule.mutationOptions());
|
||||
const preview = useMutation(api.trainScheduling.preview.mutationOptions());
|
||||
const assign = useMutation(api.trainScheduling.assignBookings.mutationOptions());
|
||||
const finalize = useMutation(api.trainScheduling.finalizeSchedule.mutationOptions());
|
||||
|
||||
useEffect(() => {
|
||||
if (scheduleMode === "new") {
|
||||
|
||||
@@ -13,11 +13,10 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { CheckCircle2, Layers, Lock, LockOpen, PlayCircle, Repeat, XCircle } from "lucide-react";
|
||||
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
||||
import {
|
||||
useBatchActions,
|
||||
useBookableSchedules,
|
||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
||||
|
||||
@@ -33,16 +32,31 @@ const windowColor: Record<string, string> = {
|
||||
|
||||
export function ScheduleBatchPanel({ schedule }: ScheduleBatchPanelProps) {
|
||||
const { toast } = useToast();
|
||||
const actions = useBatchActions(schedule.id);
|
||||
const actions = {
|
||||
runBatch: useMutation(api.trainScheduling.runBatch.mutationOptions()),
|
||||
setWindow: useMutation(api.trainScheduling.setBookingWindow.mutationOptions()),
|
||||
markPaid: useMutation(api.trainScheduling.markBookingPaid.mutationOptions()),
|
||||
expire: useMutation(api.trainScheduling.expireBooking.mutationOptions()),
|
||||
moveSchedule: useMutation(
|
||||
api.trainScheduling.moveBookingSchedule.mutationOptions(),
|
||||
),
|
||||
};
|
||||
const windowStatus = (schedule as { bookingWindowStatus?: string }).bookingWindowStatus ?? "OPEN";
|
||||
const locked = schedule.status === "DISPATCHED" || schedule.status === "ARRIVED";
|
||||
|
||||
const [moveBookingId, setMoveBookingId] = useState<string | null>(null);
|
||||
const [moveTarget, setMoveTarget] = useState<string | null>(null);
|
||||
|
||||
const { data: targets } = useBookableSchedules(
|
||||
schedule.originStation?.id,
|
||||
schedule.destinationStation?.id,
|
||||
const { data: targets } = useQuery(
|
||||
api.trainScheduling.bookableSchedules.queryOptions({
|
||||
input: {
|
||||
originYardId: schedule.originStation?.id,
|
||||
destinationYardId: schedule.destinationStation?.id,
|
||||
},
|
||||
enabled: Boolean(
|
||||
schedule.originStation?.id && schedule.destinationStation?.id,
|
||||
),
|
||||
}),
|
||||
);
|
||||
const moveOptions = useMemo(
|
||||
() =>
|
||||
|
||||
@@ -4,7 +4,8 @@ import { Building2, Package, TrainFront, Weight, X } from "lucide-react";
|
||||
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
||||
import type { BookingDetailData } from "./BookingDetailModal";
|
||||
import { RemoveBookingConfirmModal, type RemovalTarget } from "./RemoveBookingConfirmModal";
|
||||
import { useScheduleMutations } from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { freightBrand } from "@/theme/freight-brand";
|
||||
|
||||
@@ -22,7 +23,7 @@ export const AssignedBookingsPanel = ({
|
||||
onSelect,
|
||||
}: AssignedBookingsPanelProps) => {
|
||||
const { toast } = useToast();
|
||||
const unassign = useScheduleMutations(scheduleId).unassign;
|
||||
const unassign = useMutation(api.trainScheduling.unassignBooking.mutationOptions());
|
||||
const isDispatched = scheduleDetail.status === "DISPATCHED";
|
||||
const [removalTarget, setRemovalTarget] = useState<RemovalTarget | null>(null);
|
||||
|
||||
|
||||
@@ -8,10 +8,8 @@ import { UnassignedBookingsPanel } from "./UnassignedBookingsPanel";
|
||||
import { RemovalLogPanel } from "./RemovalLogPanel";
|
||||
import { BatchBookingList } from "./BatchBookingList";
|
||||
import { BookingDetailModal, type BookingDetailData } from "./BookingDetailModal";
|
||||
import {
|
||||
useCompositionRemovals,
|
||||
useUnassignedBookings,
|
||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
import { freightBrand } from "@/theme/freight-brand";
|
||||
|
||||
interface CompositionBookingTabsProps {
|
||||
@@ -47,8 +45,18 @@ export const CompositionBookingTabs = ({
|
||||
const [detailBooking, setDetailBooking] = useState<BookingDetailData | null>(null);
|
||||
const [tab, setTab] = useState<TabKey>("assigned");
|
||||
|
||||
const unassignedQuery = useUnassignedBookings(scheduleId);
|
||||
const removalsQuery = useCompositionRemovals(scheduleId);
|
||||
const unassignedQuery = useQuery(
|
||||
api.trainScheduling.unassignedBookings.queryOptions({
|
||||
input: { scheduleId },
|
||||
enabled: Boolean(scheduleId),
|
||||
}),
|
||||
);
|
||||
const removalsQuery = useQuery(
|
||||
api.trainScheduling.compositionRemovals.queryOptions({
|
||||
input: { scheduleId },
|
||||
enabled: Boolean(scheduleId),
|
||||
}),
|
||||
);
|
||||
|
||||
const { assignedCount } = useMemo(() => {
|
||||
const wagons = scheduleDetail.trainSet?.wagons ?? [];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { Group, TextInput, Text } from "@mantine/core";
|
||||
import { useUpdateContainerItem } from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
|
||||
interface ContainerNumberInputProps {
|
||||
value: string | null;
|
||||
@@ -19,13 +20,16 @@ export const ContainerNumberInput = ({
|
||||
const [inputValue, setInputValue] = useState(value ?? "");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const updateMutation = useUpdateContainerItem(scheduleId);
|
||||
const updateMutation = useMutation(
|
||||
api.trainScheduling.updateContainerItem.mutationOptions(),
|
||||
);
|
||||
const isLoading = updateMutation.isPending;
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setError(null);
|
||||
await updateMutation.mutateAsync({
|
||||
scheduleId,
|
||||
itemId,
|
||||
containerNumber: inputValue || null,
|
||||
});
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { Box, Card, Group, Stack, Text, ThemeIcon } from "@mantine/core";
|
||||
import { History, PackageX } from "lucide-react";
|
||||
import { useCompositionRemovals } from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
|
||||
interface RemovalLogPanelProps {
|
||||
scheduleId: string;
|
||||
}
|
||||
|
||||
export const RemovalLogPanel = ({ scheduleId }: RemovalLogPanelProps) => {
|
||||
const removalQuery = useCompositionRemovals(scheduleId);
|
||||
const removalQuery = useQuery(
|
||||
api.trainScheduling.compositionRemovals.queryOptions({
|
||||
input: { scheduleId },
|
||||
enabled: Boolean(scheduleId),
|
||||
}),
|
||||
);
|
||||
|
||||
if (removalQuery.isLoading) {
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,8 @@ import { TrainStatsBar } from "./TrainStatsBar";
|
||||
import { WagonCard } from "./WagonCard";
|
||||
import { InteractiveTrainConsist } from "./InteractiveTrainConsist";
|
||||
import { RemoveBookingModal } from "./RemoveBookingModal";
|
||||
import { useScheduleMutations, useRemoveWagonSlot } from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
import { freightBrand } from "@/theme/freight-brand";
|
||||
|
||||
type Wagon = TrainScheduleDetail["trainSet"]["wagons"][number];
|
||||
@@ -47,8 +48,12 @@ export const TrainConsistView = ({
|
||||
const [selectedWagonId, setSelectedWagonId] = useState<string | null>(null);
|
||||
const [removeModalOpen, setRemoveModalOpen] = useState(false);
|
||||
|
||||
const unassignMutation = useScheduleMutations(scheduleId).unassign;
|
||||
const removeWagonMutation = useRemoveWagonSlot(scheduleId);
|
||||
const unassignMutation = useMutation(
|
||||
api.trainScheduling.unassignBooking.mutationOptions(),
|
||||
);
|
||||
const removeWagonMutation = useMutation(
|
||||
api.trainScheduling.removeWagonSlot.mutationOptions(),
|
||||
);
|
||||
|
||||
const trainSet = scheduleDetail.trainSet;
|
||||
const wagons = trainSet?.wagons ?? [];
|
||||
@@ -83,7 +88,7 @@ export const TrainConsistView = ({
|
||||
|
||||
const handleRemoveWagon = async (wagonId: string) => {
|
||||
if (confirm("Are you sure you want to remove this wagon slot?")) {
|
||||
await removeWagonMutation.mutateAsync(wagonId);
|
||||
await removeWagonMutation.mutateAsync({ scheduleId, wagonId });
|
||||
setSelectedWagonId(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { Badge, Box, Button, Card, Group, Stack, Text, ThemeIcon, Tooltip } from "@mantine/core";
|
||||
import { AlertTriangle, Container as ContainerIcon, MapPin, Plus, TrainFront } from "lucide-react";
|
||||
import {
|
||||
useUnassignedBookings,
|
||||
useScheduleMutations,
|
||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import type { FleetAvailabilityRow } from "@/types/trainScheduling";
|
||||
import type { BookingDetailData } from "./BookingDetailModal";
|
||||
@@ -73,8 +71,15 @@ export const UnassignedBookingsPanel = ({
|
||||
onSelect,
|
||||
}: UnassignedBookingsPanelProps) => {
|
||||
const { toast } = useToast();
|
||||
const unassignedQuery = useUnassignedBookings(scheduleId);
|
||||
const assignMutation = useScheduleMutations(scheduleId).assignUnassigned;
|
||||
const unassignedQuery = useQuery(
|
||||
api.trainScheduling.unassignedBookings.queryOptions({
|
||||
input: { scheduleId },
|
||||
enabled: Boolean(scheduleId),
|
||||
}),
|
||||
);
|
||||
const assignMutation = useMutation(
|
||||
api.trainScheduling.assignUnassignedBooking.mutationOptions(),
|
||||
);
|
||||
|
||||
const handleAssign = async (bookingId: string, reference: string | null) => {
|
||||
try {
|
||||
|
||||
@@ -4,17 +4,18 @@ import { Button, Group, Modal, NumberInput, Select, Stack, Text } from "@mantine
|
||||
|
||||
import { Freight } from "@edr/types";
|
||||
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useRouteYards } from "@/hooks/useRoutes";
|
||||
import { useAssignWagonToTrain, useWagons } from "@/hooks/useWagons";
|
||||
|
||||
export function AssignWagonDialog({ trainId }: { trainId: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [wagonId, setWagonId] = useState<string | null>(null);
|
||||
const [sequence, setSequence] = useState<number | "">("");
|
||||
const { data: wagons } = useWagons();
|
||||
const { data: yards = [] } = useRouteYards();
|
||||
const assign = useAssignWagonToTrain();
|
||||
const { data: wagons } = useQuery(api.wagons.list.queryOptions({ input: {} }));
|
||||
const { data: yards = [] } = useQuery(api.routes.yards.queryOptions());
|
||||
const assign = useMutation(api.wagons.assignToTrain.mutationOptions());
|
||||
const { toast } = useToast();
|
||||
|
||||
const available = (wagons ?? []).filter(
|
||||
|
||||
@@ -3,15 +3,22 @@ import { Trash2 } from "lucide-react";
|
||||
import type { ColumnDef } from "@edr/ui-common";
|
||||
import { ActionIcon, Badge, Group, Text, Tooltip } from "@mantine/core";
|
||||
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||
import { api } from "@/services/api";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useUnassignWagon, useWagonsByTrain } from "@/hooks/useWagons";
|
||||
import type { Wagon } from "@/services/wagon.service";
|
||||
import { DataTable } from "@edr/ui-common";
|
||||
|
||||
export function WagonsTable({ trainId }: { trainId: string }) {
|
||||
const { data: wagons = [], isLoading, refetch } = useWagonsByTrain(trainId);
|
||||
const unassign = useUnassignWagon();
|
||||
const { data: wagons = [], isLoading, refetch } = useQuery(
|
||||
api.wagons.listByTrain.queryOptions({
|
||||
input: { trainId },
|
||||
enabled: !!trainId,
|
||||
}),
|
||||
);
|
||||
const unassign = useMutation(api.wagons.unassign.mutationOptions());
|
||||
const { toast } = useToast();
|
||||
|
||||
const columns = useMemo((): ColumnDef<Wagon>[] => {
|
||||
|
||||
@@ -9,11 +9,10 @@ import {
|
||||
TextInput,
|
||||
} from '@mantine/core';
|
||||
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { api } from '@/services/api';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useStations } from '@/hooks/useStations';
|
||||
import type { SaveWarehousePayload, Warehouse, WarehouseType } from '@/types/warehouse';
|
||||
import { extractErrorMessage, statusOptions, warehouseTypeOptions } from './options';
|
||||
|
||||
@@ -52,7 +51,9 @@ export function CreateWarehouseModal({ opened, onClose, warehouse }: CreateWareh
|
||||
const { toast } = useToast();
|
||||
const createMutation = useMutation(api.warehouses.create.mutationOptions());
|
||||
const updateMutation = useMutation(api.warehouses.update.mutationOptions());
|
||||
const { data: stations } = useStations();
|
||||
const { data: stations } = useQuery(
|
||||
api.stations.list.queryOptions({ staleTime: 5 * 60 * 1000 }),
|
||||
);
|
||||
const [form, setForm] = useState<FormState>(emptyForm());
|
||||
|
||||
const stationOptions = (stations ?? []).map((s) => ({ value: s.id, label: `${s.name} (${s.code})` }));
|
||||
|
||||
@@ -2,7 +2,9 @@ import { useMemo } from 'react';
|
||||
import { ActionIcon, Card, Group, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||
import { Building2, Eye, MapPin, Pencil } from 'lucide-react';
|
||||
|
||||
import { useStations } from '@/hooks/useStations';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { api } from '@/services/api';
|
||||
import type { Warehouse } from '@/types/warehouse';
|
||||
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
||||
import { formatCapacity } from './options';
|
||||
@@ -14,7 +16,9 @@ interface WarehouseCardViewProps {
|
||||
}
|
||||
|
||||
export function WarehouseCardView({ warehouses, onView, onEdit }: WarehouseCardViewProps) {
|
||||
const { data: stations } = useStations();
|
||||
const { data: stations } = useQuery(
|
||||
api.stations.list.queryOptions({ staleTime: 5 * 60 * 1000 }),
|
||||
);
|
||||
const stationNameById = useMemo(
|
||||
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
||||
[stations],
|
||||
|
||||
@@ -3,7 +3,9 @@ import { ActionIcon, Group, Text } from '@mantine/core';
|
||||
import { Eye, Pencil } from 'lucide-react';
|
||||
import { DataTable, type ColumnDef } from '@edr/ui-common';
|
||||
|
||||
import { useStations } from '@/hooks/useStations';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { api } from '@/services/api';
|
||||
import type { Warehouse } from '@/types/warehouse';
|
||||
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
||||
import { formatCapacity } from './options';
|
||||
@@ -15,7 +17,9 @@ interface WarehouseTableProps {
|
||||
}
|
||||
|
||||
export function WarehouseTable({ warehouses, onView, onEdit }: WarehouseTableProps) {
|
||||
const { data: stations } = useStations();
|
||||
const { data: stations } = useQuery(
|
||||
api.stations.list.queryOptions({ staleTime: 5 * 60 * 1000 }),
|
||||
);
|
||||
const stationNameById = useMemo(
|
||||
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
||||
[stations],
|
||||
|
||||
Reference in New Issue
Block a user