mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 16:28:12 +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 { useState } from "react";
|
||||||
import { FileSignature, Loader2 } from "lucide-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 { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -10,10 +13,6 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
import { useAuth } from "@/auth/useAuth";
|
import { useAuth } from "@/auth/useAuth";
|
||||||
import {
|
|
||||||
useMySignature,
|
|
||||||
useSaveSignature,
|
|
||||||
} from "@/hooks/useSavedSignature";
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -33,8 +32,10 @@ import {
|
|||||||
*/
|
*/
|
||||||
export function MySignatureCard() {
|
export function MySignatureCard() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { data: saved, isLoading } = useMySignature();
|
const { data: saved, isLoading } = useQuery(
|
||||||
const saveMutation = useSaveSignature();
|
api.signatures.mySignature.queryOptions({ staleTime: 60_000 }),
|
||||||
|
);
|
||||||
|
const saveMutation = useMutation(api.signatures.save.mutationOptions());
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [signerName, setSignerName] = useState("");
|
const [signerName, setSignerName] = useState("");
|
||||||
@@ -56,7 +57,13 @@ export function MySignatureCard() {
|
|||||||
signerDisplayName: signerName.trim(),
|
signerDisplayName: signerName.trim(),
|
||||||
signatureImageBase64: signatureData,
|
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,
|
Weight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
import {
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
useAvailableLocomotives,
|
import { api } from "@/services/api";
|
||||||
useEligibleBookings,
|
|
||||||
useScheduleList,
|
|
||||||
useScheduleMutations,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useRoutes } from "@/hooks/useRoutes";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { trainSchedulingService } from "@/services/trainScheduling.service";
|
import { trainSchedulingService } from "@/services/trainScheduling.service";
|
||||||
import type { BookingDetail } from "@/types/booking";
|
import type { BookingDetail } from "@/types/booking";
|
||||||
@@ -133,13 +128,27 @@ export function AllocateBookingWizard({
|
|||||||
[originId, destinationId],
|
[originId, destinationId],
|
||||||
);
|
);
|
||||||
|
|
||||||
const eligibleQuery = useEligibleBookings(eligibleFilters, opened);
|
const eligibleQuery = useQuery(
|
||||||
const schedulesQuery = useScheduleList();
|
api.trainScheduling.eligibleBookings.queryOptions({
|
||||||
const routesQuery = useRoutes();
|
input: { filters: eligibleFilters },
|
||||||
const locomotivesQuery = useAvailableLocomotives(
|
enabled: opened,
|
||||||
scheduleMode === "new" && routeId ? routeId : undefined,
|
}),
|
||||||
);
|
);
|
||||||
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(() => {
|
useEffect(() => {
|
||||||
if (scheduleMode === "new") {
|
if (scheduleMode === "new") {
|
||||||
|
|||||||
@@ -13,11 +13,10 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { CheckCircle2, Layers, Lock, LockOpen, PlayCircle, Repeat, XCircle } from "lucide-react";
|
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 { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
||||||
import {
|
import { api } from "@/services/api";
|
||||||
useBatchActions,
|
|
||||||
useBookableSchedules,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
||||||
|
|
||||||
@@ -33,16 +32,31 @@ const windowColor: Record<string, string> = {
|
|||||||
|
|
||||||
export function ScheduleBatchPanel({ schedule }: ScheduleBatchPanelProps) {
|
export function ScheduleBatchPanel({ schedule }: ScheduleBatchPanelProps) {
|
||||||
const { toast } = useToast();
|
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 windowStatus = (schedule as { bookingWindowStatus?: string }).bookingWindowStatus ?? "OPEN";
|
||||||
const locked = schedule.status === "DISPATCHED" || schedule.status === "ARRIVED";
|
const locked = schedule.status === "DISPATCHED" || schedule.status === "ARRIVED";
|
||||||
|
|
||||||
const [moveBookingId, setMoveBookingId] = useState<string | null>(null);
|
const [moveBookingId, setMoveBookingId] = useState<string | null>(null);
|
||||||
const [moveTarget, setMoveTarget] = useState<string | null>(null);
|
const [moveTarget, setMoveTarget] = useState<string | null>(null);
|
||||||
|
|
||||||
const { data: targets } = useBookableSchedules(
|
const { data: targets } = useQuery(
|
||||||
schedule.originStation?.id,
|
api.trainScheduling.bookableSchedules.queryOptions({
|
||||||
schedule.destinationStation?.id,
|
input: {
|
||||||
|
originYardId: schedule.originStation?.id,
|
||||||
|
destinationYardId: schedule.destinationStation?.id,
|
||||||
|
},
|
||||||
|
enabled: Boolean(
|
||||||
|
schedule.originStation?.id && schedule.destinationStation?.id,
|
||||||
|
),
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
const moveOptions = useMemo(
|
const moveOptions = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { Building2, Package, TrainFront, Weight, X } from "lucide-react";
|
|||||||
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
import type { TrainScheduleDetail } from "@/types/trainScheduling";
|
||||||
import type { BookingDetailData } from "./BookingDetailModal";
|
import type { BookingDetailData } from "./BookingDetailModal";
|
||||||
import { RemoveBookingConfirmModal, type RemovalTarget } from "./RemoveBookingConfirmModal";
|
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 { useToast } from "@/hooks/use-toast";
|
||||||
import { freightBrand } from "@/theme/freight-brand";
|
import { freightBrand } from "@/theme/freight-brand";
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ export const AssignedBookingsPanel = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
}: AssignedBookingsPanelProps) => {
|
}: AssignedBookingsPanelProps) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const unassign = useScheduleMutations(scheduleId).unassign;
|
const unassign = useMutation(api.trainScheduling.unassignBooking.mutationOptions());
|
||||||
const isDispatched = scheduleDetail.status === "DISPATCHED";
|
const isDispatched = scheduleDetail.status === "DISPATCHED";
|
||||||
const [removalTarget, setRemovalTarget] = useState<RemovalTarget | null>(null);
|
const [removalTarget, setRemovalTarget] = useState<RemovalTarget | null>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,8 @@ import { UnassignedBookingsPanel } from "./UnassignedBookingsPanel";
|
|||||||
import { RemovalLogPanel } from "./RemovalLogPanel";
|
import { RemovalLogPanel } from "./RemovalLogPanel";
|
||||||
import { BatchBookingList } from "./BatchBookingList";
|
import { BatchBookingList } from "./BatchBookingList";
|
||||||
import { BookingDetailModal, type BookingDetailData } from "./BookingDetailModal";
|
import { BookingDetailModal, type BookingDetailData } from "./BookingDetailModal";
|
||||||
import {
|
import { useQuery } from "@tanstack/react-query";
|
||||||
useCompositionRemovals,
|
import { api } from "@/services/api";
|
||||||
useUnassignedBookings,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { freightBrand } from "@/theme/freight-brand";
|
import { freightBrand } from "@/theme/freight-brand";
|
||||||
|
|
||||||
interface CompositionBookingTabsProps {
|
interface CompositionBookingTabsProps {
|
||||||
@@ -47,8 +45,18 @@ export const CompositionBookingTabs = ({
|
|||||||
const [detailBooking, setDetailBooking] = useState<BookingDetailData | null>(null);
|
const [detailBooking, setDetailBooking] = useState<BookingDetailData | null>(null);
|
||||||
const [tab, setTab] = useState<TabKey>("assigned");
|
const [tab, setTab] = useState<TabKey>("assigned");
|
||||||
|
|
||||||
const unassignedQuery = useUnassignedBookings(scheduleId);
|
const unassignedQuery = useQuery(
|
||||||
const removalsQuery = useCompositionRemovals(scheduleId);
|
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 { assignedCount } = useMemo(() => {
|
||||||
const wagons = scheduleDetail.trainSet?.wagons ?? [];
|
const wagons = scheduleDetail.trainSet?.wagons ?? [];
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Group, TextInput, Text } from "@mantine/core";
|
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 {
|
interface ContainerNumberInputProps {
|
||||||
value: string | null;
|
value: string | null;
|
||||||
@@ -19,13 +20,16 @@ export const ContainerNumberInput = ({
|
|||||||
const [inputValue, setInputValue] = useState(value ?? "");
|
const [inputValue, setInputValue] = useState(value ?? "");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
const updateMutation = useUpdateContainerItem(scheduleId);
|
const updateMutation = useMutation(
|
||||||
|
api.trainScheduling.updateContainerItem.mutationOptions(),
|
||||||
|
);
|
||||||
const isLoading = updateMutation.isPending;
|
const isLoading = updateMutation.isPending;
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
try {
|
try {
|
||||||
setError(null);
|
setError(null);
|
||||||
await updateMutation.mutateAsync({
|
await updateMutation.mutateAsync({
|
||||||
|
scheduleId,
|
||||||
itemId,
|
itemId,
|
||||||
containerNumber: inputValue || null,
|
containerNumber: inputValue || null,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { Box, Card, Group, Stack, Text, ThemeIcon } from "@mantine/core";
|
import { Box, Card, Group, Stack, Text, ThemeIcon } from "@mantine/core";
|
||||||
import { History, PackageX } from "lucide-react";
|
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 {
|
interface RemovalLogPanelProps {
|
||||||
scheduleId: string;
|
scheduleId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RemovalLogPanel = ({ scheduleId }: RemovalLogPanelProps) => {
|
export const RemovalLogPanel = ({ scheduleId }: RemovalLogPanelProps) => {
|
||||||
const removalQuery = useCompositionRemovals(scheduleId);
|
const removalQuery = useQuery(
|
||||||
|
api.trainScheduling.compositionRemovals.queryOptions({
|
||||||
|
input: { scheduleId },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (removalQuery.isLoading) {
|
if (removalQuery.isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { TrainStatsBar } from "./TrainStatsBar";
|
|||||||
import { WagonCard } from "./WagonCard";
|
import { WagonCard } from "./WagonCard";
|
||||||
import { InteractiveTrainConsist } from "./InteractiveTrainConsist";
|
import { InteractiveTrainConsist } from "./InteractiveTrainConsist";
|
||||||
import { RemoveBookingModal } from "./RemoveBookingModal";
|
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";
|
import { freightBrand } from "@/theme/freight-brand";
|
||||||
|
|
||||||
type Wagon = TrainScheduleDetail["trainSet"]["wagons"][number];
|
type Wagon = TrainScheduleDetail["trainSet"]["wagons"][number];
|
||||||
@@ -47,8 +48,12 @@ export const TrainConsistView = ({
|
|||||||
const [selectedWagonId, setSelectedWagonId] = useState<string | null>(null);
|
const [selectedWagonId, setSelectedWagonId] = useState<string | null>(null);
|
||||||
const [removeModalOpen, setRemoveModalOpen] = useState(false);
|
const [removeModalOpen, setRemoveModalOpen] = useState(false);
|
||||||
|
|
||||||
const unassignMutation = useScheduleMutations(scheduleId).unassign;
|
const unassignMutation = useMutation(
|
||||||
const removeWagonMutation = useRemoveWagonSlot(scheduleId);
|
api.trainScheduling.unassignBooking.mutationOptions(),
|
||||||
|
);
|
||||||
|
const removeWagonMutation = useMutation(
|
||||||
|
api.trainScheduling.removeWagonSlot.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
const trainSet = scheduleDetail.trainSet;
|
const trainSet = scheduleDetail.trainSet;
|
||||||
const wagons = trainSet?.wagons ?? [];
|
const wagons = trainSet?.wagons ?? [];
|
||||||
@@ -83,7 +88,7 @@ export const TrainConsistView = ({
|
|||||||
|
|
||||||
const handleRemoveWagon = async (wagonId: string) => {
|
const handleRemoveWagon = async (wagonId: string) => {
|
||||||
if (confirm("Are you sure you want to remove this wagon slot?")) {
|
if (confirm("Are you sure you want to remove this wagon slot?")) {
|
||||||
await removeWagonMutation.mutateAsync(wagonId);
|
await removeWagonMutation.mutateAsync({ scheduleId, wagonId });
|
||||||
setSelectedWagonId(null);
|
setSelectedWagonId(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { Badge, Box, Button, Card, Group, Stack, Text, ThemeIcon, Tooltip } from "@mantine/core";
|
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 { AlertTriangle, Container as ContainerIcon, MapPin, Plus, TrainFront } from "lucide-react";
|
||||||
import {
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
useUnassignedBookings,
|
import { api } from "@/services/api";
|
||||||
useScheduleMutations,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type { FleetAvailabilityRow } from "@/types/trainScheduling";
|
import type { FleetAvailabilityRow } from "@/types/trainScheduling";
|
||||||
import type { BookingDetailData } from "./BookingDetailModal";
|
import type { BookingDetailData } from "./BookingDetailModal";
|
||||||
@@ -73,8 +71,15 @@ export const UnassignedBookingsPanel = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
}: UnassignedBookingsPanelProps) => {
|
}: UnassignedBookingsPanelProps) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const unassignedQuery = useUnassignedBookings(scheduleId);
|
const unassignedQuery = useQuery(
|
||||||
const assignMutation = useScheduleMutations(scheduleId).assignUnassigned;
|
api.trainScheduling.unassignedBookings.queryOptions({
|
||||||
|
input: { scheduleId },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const assignMutation = useMutation(
|
||||||
|
api.trainScheduling.assignUnassignedBooking.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
const handleAssign = async (bookingId: string, reference: string | null) => {
|
const handleAssign = async (bookingId: string, reference: string | null) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,17 +4,18 @@ import { Button, Group, Modal, NumberInput, Select, Stack, Text } from "@mantine
|
|||||||
|
|
||||||
import { Freight } from "@edr/types";
|
import { Freight } from "@edr/types";
|
||||||
|
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import { api } from "@/services/api";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useRouteYards } from "@/hooks/useRoutes";
|
|
||||||
import { useAssignWagonToTrain, useWagons } from "@/hooks/useWagons";
|
|
||||||
|
|
||||||
export function AssignWagonDialog({ trainId }: { trainId: string }) {
|
export function AssignWagonDialog({ trainId }: { trainId: string }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [wagonId, setWagonId] = useState<string | null>(null);
|
const [wagonId, setWagonId] = useState<string | null>(null);
|
||||||
const [sequence, setSequence] = useState<number | "">("");
|
const [sequence, setSequence] = useState<number | "">("");
|
||||||
const { data: wagons } = useWagons();
|
const { data: wagons } = useQuery(api.wagons.list.queryOptions({ input: {} }));
|
||||||
const { data: yards = [] } = useRouteYards();
|
const { data: yards = [] } = useQuery(api.routes.yards.queryOptions());
|
||||||
const assign = useAssignWagonToTrain();
|
const assign = useMutation(api.wagons.assignToTrain.mutationOptions());
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const available = (wagons ?? []).filter(
|
const available = (wagons ?? []).filter(
|
||||||
|
|||||||
@@ -3,15 +3,22 @@ import { Trash2 } from "lucide-react";
|
|||||||
import type { ColumnDef } from "@edr/ui-common";
|
import type { ColumnDef } from "@edr/ui-common";
|
||||||
import { ActionIcon, Badge, Group, Text, Tooltip } from "@mantine/core";
|
import { ActionIcon, Badge, Group, Text, Tooltip } from "@mantine/core";
|
||||||
|
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||||
|
import { api } from "@/services/api";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useUnassignWagon, useWagonsByTrain } from "@/hooks/useWagons";
|
|
||||||
import type { Wagon } from "@/services/wagon.service";
|
import type { Wagon } from "@/services/wagon.service";
|
||||||
import { DataTable } from "@edr/ui-common";
|
import { DataTable } from "@edr/ui-common";
|
||||||
|
|
||||||
export function WagonsTable({ trainId }: { trainId: string }) {
|
export function WagonsTable({ trainId }: { trainId: string }) {
|
||||||
const { data: wagons = [], isLoading, refetch } = useWagonsByTrain(trainId);
|
const { data: wagons = [], isLoading, refetch } = useQuery(
|
||||||
const unassign = useUnassignWagon();
|
api.wagons.listByTrain.queryOptions({
|
||||||
|
input: { trainId },
|
||||||
|
enabled: !!trainId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const unassign = useMutation(api.wagons.unassign.mutationOptions());
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const columns = useMemo((): ColumnDef<Wagon>[] => {
|
const columns = useMemo((): ColumnDef<Wagon>[] => {
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
|
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '@/services/api';
|
import { api } from '@/services/api';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useStations } from '@/hooks/useStations';
|
|
||||||
import type { SaveWarehousePayload, Warehouse, WarehouseType } from '@/types/warehouse';
|
import type { SaveWarehousePayload, Warehouse, WarehouseType } from '@/types/warehouse';
|
||||||
import { extractErrorMessage, statusOptions, warehouseTypeOptions } from './options';
|
import { extractErrorMessage, statusOptions, warehouseTypeOptions } from './options';
|
||||||
|
|
||||||
@@ -52,7 +51,9 @@ export function CreateWarehouseModal({ opened, onClose, warehouse }: CreateWareh
|
|||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const createMutation = useMutation(api.warehouses.create.mutationOptions());
|
const createMutation = useMutation(api.warehouses.create.mutationOptions());
|
||||||
const updateMutation = useMutation(api.warehouses.update.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 [form, setForm] = useState<FormState>(emptyForm());
|
||||||
|
|
||||||
const stationOptions = (stations ?? []).map((s) => ({ value: s.id, label: `${s.name} (${s.code})` }));
|
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 { ActionIcon, Card, Group, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||||
import { Building2, Eye, MapPin, Pencil } from 'lucide-react';
|
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 type { Warehouse } from '@/types/warehouse';
|
||||||
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
||||||
import { formatCapacity } from './options';
|
import { formatCapacity } from './options';
|
||||||
@@ -14,7 +16,9 @@ interface WarehouseCardViewProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WarehouseCardView({ warehouses, onView, onEdit }: 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(
|
const stationNameById = useMemo(
|
||||||
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
||||||
[stations],
|
[stations],
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import { ActionIcon, Group, Text } from '@mantine/core';
|
|||||||
import { Eye, Pencil } from 'lucide-react';
|
import { Eye, Pencil } from 'lucide-react';
|
||||||
import { DataTable, type ColumnDef } from '@edr/ui-common';
|
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 type { Warehouse } from '@/types/warehouse';
|
||||||
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
import { WarehouseStatusBadge, WarehouseTypeBadge } from './badges';
|
||||||
import { formatCapacity } from './options';
|
import { formatCapacity } from './options';
|
||||||
@@ -15,7 +17,9 @@ interface WarehouseTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WarehouseTable({ warehouses, onView, onEdit }: 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(
|
const stationNameById = useMemo(
|
||||||
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
() => new Map((stations ?? []).map((s) => [s.id, s.name])),
|
||||||
[stations],
|
[stations],
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { BookingListFilter } from "@/services/bookings.service";
|
|
||||||
import type { CompanyListFilter } from "@/types/customer";
|
|
||||||
import type { RuleEngineListParams } from "@/services/ruleEngine/ruleEngine.service";
|
|
||||||
import type { TrainScheduleFilters } from "@/types/trainScheduling";
|
|
||||||
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
|
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
|
||||||
|
import type { BookingListFilter } from "@/services/bookings.service";
|
||||||
|
import type { RuleEngineListParams } from "@/services/ruleEngine/ruleEngine.service";
|
||||||
|
import type { CompanyListFilter } from "@/types/customer";
|
||||||
import type { RuleEngineResourceSlug } from "@/types/rule-engine";
|
import type { RuleEngineResourceSlug } from "@/types/rule-engine";
|
||||||
|
import type { TrainScheduleFilters } from "@/types/trainScheduling";
|
||||||
|
|
||||||
export const QUERY_KEYS = {
|
export const QUERY_KEYS = {
|
||||||
USERS: {
|
USERS: {
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
|
||||||
import type { FleetListFilters, FleetResourceSlug } from "@/services/fleet/fleet.service";
|
|
||||||
import { fleetService } from "@/services/fleet/fleet.service";
|
|
||||||
|
|
||||||
export function useFleetList(slug: FleetResourceSlug, filters?: FleetListFilters) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: [...QUERY_KEYS.FLEET.list(slug), filters ?? {}],
|
|
||||||
queryFn: () => fleetService.list(slug, filters),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useFleetMutations(slug: FleetResourceSlug) {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
const invalidate = () => qc.invalidateQueries({ queryKey: QUERY_KEYS.FLEET.list(slug) });
|
|
||||||
|
|
||||||
const create = useMutation({
|
|
||||||
mutationFn: (data: Record<string, unknown>) => fleetService.create(slug, data),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const update = useMutation({
|
|
||||||
mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
|
|
||||||
fleetService.update(slug, id, data),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const remove = useMutation({
|
|
||||||
mutationFn: (id: string) => fleetService.remove(slug, id),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
return { create, update, remove };
|
|
||||||
}
|
|
||||||
@@ -1,325 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
|
||||||
import { trainSchedulingService } from "@/services/trainScheduling.service";
|
|
||||||
import type {
|
|
||||||
AssignBookingsPayload,
|
|
||||||
CreateTrainSchedulePayload,
|
|
||||||
FreightType,
|
|
||||||
PinWagonsPayload,
|
|
||||||
RecordCheckpointPayload,
|
|
||||||
TrainScheduleFilters,
|
|
||||||
TrainSchedulePreviewPayload,
|
|
||||||
} from "@/types/trainScheduling";
|
|
||||||
|
|
||||||
export const useScheduleList = (freightType?: FreightType) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.schedules(),
|
|
||||||
queryFn: () => trainSchedulingService.listSchedules(freightType),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useBatchBoard = () =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(),
|
|
||||||
queryFn: () => trainSchedulingService.getBatchBoard(),
|
|
||||||
refetchInterval: 30_000,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useBatchBoardDetail = (scheduleId: string | undefined) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId ?? ""),
|
|
||||||
queryFn: () => trainSchedulingService.getBatchBoardDetail(scheduleId!),
|
|
||||||
enabled: Boolean(scheduleId),
|
|
||||||
refetchInterval: 30_000,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useRunAllocation = (scheduleId: string) => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: () => trainSchedulingService.runAllocation(scheduleId),
|
|
||||||
onSuccess: () => {
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard() });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useScheduleDetail = (id: string | undefined, freightType?: FreightType) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(id ?? ""),
|
|
||||||
queryFn: () => trainSchedulingService.getScheduleById(id!, freightType),
|
|
||||||
enabled: Boolean(id),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useEligibleBookings = (
|
|
||||||
filters?: TrainScheduleFilters,
|
|
||||||
enabled = true,
|
|
||||||
freightType?: FreightType,
|
|
||||||
) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.eligible(freightType, filters),
|
|
||||||
queryFn: () => trainSchedulingService.getEligibleBookings(filters, freightType),
|
|
||||||
enabled,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useAvailableLocomotives = (routeId?: string) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.locomotives(routeId),
|
|
||||||
queryFn: () => trainSchedulingService.getAvailableLocomotives(routeId),
|
|
||||||
enabled: routeId ? Boolean(routeId) : true,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useBatchActions = (scheduleId?: string) => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
const invalidate = () => {
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.ROOT });
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.BOOKINGS.ROOT });
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard() });
|
|
||||||
if (scheduleId) {
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const runBatch = useMutation({
|
|
||||||
mutationFn: (id: string) => trainSchedulingService.runBatch(id),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
const setWindow = useMutation({
|
|
||||||
mutationFn: ({ id, status }: { id: string; status: "OPEN" | "CLOSED" }) =>
|
|
||||||
trainSchedulingService.setBookingWindow(id, status),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
const markPaid = useMutation({
|
|
||||||
mutationFn: (bookingId: string) => trainSchedulingService.markBookingPaid(bookingId),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
const expire = useMutation({
|
|
||||||
mutationFn: (bookingId: string) => trainSchedulingService.expireBooking(bookingId),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
const moveSchedule = useMutation({
|
|
||||||
mutationFn: ({ bookingId, trainScheduleId }: { bookingId: string; trainScheduleId: string }) =>
|
|
||||||
trainSchedulingService.moveBookingSchedule(bookingId, trainScheduleId),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
return { runBatch, setWindow, markPaid, expire, moveSchedule, invalidate };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useBookableSchedules = (
|
|
||||||
originYardId?: string | null,
|
|
||||||
destinationYardId?: string | null,
|
|
||||||
) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: [
|
|
||||||
...QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
|
||||||
"bookable",
|
|
||||||
originYardId ?? "",
|
|
||||||
destinationYardId ?? "",
|
|
||||||
],
|
|
||||||
queryFn: () =>
|
|
||||||
trainSchedulingService.getBookableSchedules(
|
|
||||||
originYardId ?? undefined,
|
|
||||||
destinationYardId ?? undefined,
|
|
||||||
),
|
|
||||||
enabled: Boolean(originYardId && destinationYardId),
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Day-level pool: which days have an OPEN departure on the route. Staff pick a
|
|
||||||
* day (not a train) when creating a booking; the engine assigns the train.
|
|
||||||
*/
|
|
||||||
export const useAvailableDays = (
|
|
||||||
originYardId?: string | null,
|
|
||||||
destinationYardId?: string | null,
|
|
||||||
) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: [
|
|
||||||
...QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
|
||||||
"available-days",
|
|
||||||
originYardId ?? "",
|
|
||||||
destinationYardId ?? "",
|
|
||||||
],
|
|
||||||
queryFn: () =>
|
|
||||||
trainSchedulingService.getAvailableDays(
|
|
||||||
originYardId ?? undefined,
|
|
||||||
destinationYardId ?? undefined,
|
|
||||||
),
|
|
||||||
enabled: Boolean(originYardId && destinationYardId),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useTrainTrack = (id: string | undefined) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.track(id ?? ""),
|
|
||||||
queryFn: () => trainSchedulingService.getTrack(id!),
|
|
||||||
enabled: Boolean(id),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useScheduleMutations = (scheduleId?: string) => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
|
|
||||||
const invalidate = () => {
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.ROOT });
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.schedules() });
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.locomotives() });
|
|
||||||
if (scheduleId) {
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.track(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.unassignedBookings(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.BOOKINGS.ROOT });
|
|
||||||
};
|
|
||||||
|
|
||||||
const create = useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
freightType,
|
|
||||||
payload,
|
|
||||||
}: {
|
|
||||||
freightType?: FreightType;
|
|
||||||
payload: CreateTrainSchedulePayload;
|
|
||||||
}) => trainSchedulingService.createSchedule(payload, freightType),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const preview = useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
freightType,
|
|
||||||
payload,
|
|
||||||
}: {
|
|
||||||
freightType?: FreightType;
|
|
||||||
payload: TrainSchedulePreviewPayload;
|
|
||||||
}) => trainSchedulingService.preview(payload, freightType),
|
|
||||||
});
|
|
||||||
|
|
||||||
const assign = useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
id,
|
|
||||||
freightType,
|
|
||||||
payload,
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
freightType?: FreightType;
|
|
||||||
payload: AssignBookingsPayload;
|
|
||||||
}) => trainSchedulingService.assignBookings(id, payload, freightType),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const assignUnassigned = useMutation({
|
|
||||||
mutationFn: ({ id, bookingId }: { id: string; bookingId: string }) =>
|
|
||||||
trainSchedulingService.assignUnassignedBooking(id, bookingId),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const unassign = useMutation({
|
|
||||||
mutationFn: ({ id, bookingId }: { id: string; bookingId: string }) =>
|
|
||||||
trainSchedulingService.unassignBooking(id, bookingId),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const pin = useMutation({
|
|
||||||
mutationFn: ({ id, payload }: { id: string; payload: PinWagonsPayload }) =>
|
|
||||||
trainSchedulingService.pinWagons(id, payload),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const finalize = useMutation({
|
|
||||||
mutationFn: (id: string) => trainSchedulingService.finalizeSchedule(id),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const dispatch = useMutation({
|
|
||||||
mutationFn: (id: string) => trainSchedulingService.dispatchSchedule(id),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const cancel = useMutation({
|
|
||||||
mutationFn: ({ id, freightType }: { id: string; freightType?: FreightType }) =>
|
|
||||||
trainSchedulingService.cancelSchedule(id, freightType ?? "CONTAINER"),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const recordCheckpoint = useMutation({
|
|
||||||
mutationFn: ({ id, payload }: { id: string; payload: RecordCheckpointPayload }) =>
|
|
||||||
trainSchedulingService.recordCheckpoint(id, payload),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
const arrive = useMutation({
|
|
||||||
mutationFn: (id: string) => trainSchedulingService.arriveSchedule(id),
|
|
||||||
onSuccess: invalidate,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
create,
|
|
||||||
preview,
|
|
||||||
assign,
|
|
||||||
assignUnassigned,
|
|
||||||
unassign,
|
|
||||||
pin,
|
|
||||||
finalize,
|
|
||||||
dispatch,
|
|
||||||
cancel,
|
|
||||||
recordCheckpoint,
|
|
||||||
arrive,
|
|
||||||
invalidate,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUnassignedBookings = (scheduleId: string | undefined) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.unassignedBookings(scheduleId ?? ""),
|
|
||||||
queryFn: () => trainSchedulingService.getUnassignedBookings(scheduleId!),
|
|
||||||
enabled: Boolean(scheduleId),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useCompositionRemovals = (scheduleId: string | undefined) =>
|
|
||||||
useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId ?? ""),
|
|
||||||
queryFn: () => trainSchedulingService.getCompositionRemovals(scheduleId!),
|
|
||||||
enabled: Boolean(scheduleId),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useRemoveWagonSlot = (scheduleId: string) => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (wagonId: string) =>
|
|
||||||
trainSchedulingService.removeWagonSlot(scheduleId, wagonId),
|
|
||||||
onSuccess: () => {
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
|
||||||
});
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateContainerItem = (scheduleId: string) => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ itemId, containerNumber }: { itemId: string; containerNumber: string | null }) =>
|
|
||||||
trainSchedulingService.updateContainerItem(scheduleId, itemId, { containerNumber }),
|
|
||||||
onSuccess: () => {
|
|
||||||
void qc.invalidateQueries({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
|
||||||
import { cargoTypesService } from '@/services/cargo-types.service';
|
|
||||||
|
|
||||||
export const CARGO_TYPES_QUERY_KEY = ['cargo-types'];
|
|
||||||
|
|
||||||
export function useCargoTypes() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: CARGO_TYPES_QUERY_KEY,
|
|
||||||
queryFn: () => cargoTypesService.getCargoTypes(),
|
|
||||||
staleTime: Infinity,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
|
||||||
import { containerTypesService } from '@/services/container-types.service';
|
|
||||||
|
|
||||||
export const CONTAINER_TYPES_QUERY_KEY = ['container-types'];
|
|
||||||
|
|
||||||
export function useContainerTypes() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: CONTAINER_TYPES_QUERY_KEY,
|
|
||||||
queryFn: () => containerTypesService.getContainerTypes(),
|
|
||||||
staleTime: Infinity,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { wagonTypesService } from '@/services/wagon-types.service';
|
|
||||||
|
|
||||||
export const WAGON_TYPES_QUERY_KEY = ['wagon-types'];
|
|
||||||
|
|
||||||
export function useWagonTypes() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: WAGON_TYPES_QUERY_KEY,
|
|
||||||
queryFn: () => wagonTypesService.getWagonTypes(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCreateWagonType() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: wagonTypesService.create,
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: WAGON_TYPES_QUERY_KEY }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateWagonType() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
|
|
||||||
wagonTypesService.update(id, data),
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: WAGON_TYPES_QUERY_KEY }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDeleteWagonType() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: wagonTypesService.delete,
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: WAGON_TYPES_QUERY_KEY }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { containerService } from '@/services/containerService';
|
|
||||||
|
|
||||||
export const containerKeys = {
|
|
||||||
all: ['containers'] as const,
|
|
||||||
byWagon: (wagonId: string) => [...containerKeys.all, 'wagon', wagonId] as const,
|
|
||||||
details: () => [...containerKeys.all, 'detail'] as const,
|
|
||||||
detail: (id: string) => [...containerKeys.details(), id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useContainers() {
|
|
||||||
return useQuery({ queryKey: containerKeys.all, queryFn: () => containerService.getAll().then(res => res.data) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetContainers = useContainers;
|
|
||||||
|
|
||||||
export function useContainersByWagon(wagonId: string) {
|
|
||||||
return useQuery({ queryKey: containerKeys.byWagon(wagonId), queryFn: () => containerService.getByWagon(wagonId).then(res => res.data), enabled: !!wagonId });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useContainer(id: string) {
|
|
||||||
return useQuery({ queryKey: containerKeys.detail(id), queryFn: () => containerService.getById(id).then(res => res.data), enabled: !!id });
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetContainer = useContainer;
|
|
||||||
|
|
||||||
export function useCreateContainer() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: containerService.create, onSuccess: () => qc.invalidateQueries({ queryKey: containerKeys.all }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateContainer() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: ({ id, data }: any) => containerService.update(id, data), onSuccess: (_, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: containerKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: containerKeys.detail(id) });
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDeleteContainer() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: containerService.delete, onSuccess: () => qc.invalidateQueries({ queryKey: containerKeys.all }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useAssignContainerToWagon() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ containerId, wagonId, position }: any) => containerService.assignToWagon(containerId, wagonId, position),
|
|
||||||
onSuccess: (_, { wagonId }) => qc.invalidateQueries({ queryKey: containerKeys.byWagon(wagonId) })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUnassignContainer() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: containerService.unassign,
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: containerKeys.all })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import { api } from "@/services/api";
|
|
||||||
import type {
|
|
||||||
CreateDropdownOptionDto,
|
|
||||||
CreateDropdownSettingDto,
|
|
||||||
UpdateDropdownOptionDto,
|
|
||||||
UpdateDropdownSettingDto,
|
|
||||||
} from "@/types/dropdownSettings";
|
|
||||||
|
|
||||||
/* ----------------------------- Mutations ----------------------------- */
|
|
||||||
|
|
||||||
export const useCreateDropdownSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (dto: CreateDropdownSettingDto) =>
|
|
||||||
api.dropdownSettings.create.call(dto),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateDropdownSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
id,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
dto: UpdateDropdownSettingDto;
|
|
||||||
}) => api.dropdownSettings.update.call({ id, dto }),
|
|
||||||
onSuccess: (_data, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.dropdownSettings.getById.queryKey({ id }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDeleteDropdownSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (id: string) => api.dropdownSettings.remove.call({ id }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useReplaceDropdownOptions = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
settingId,
|
|
||||||
options,
|
|
||||||
}: {
|
|
||||||
settingId: string;
|
|
||||||
options: CreateDropdownOptionDto[];
|
|
||||||
}) => api.dropdownSettings.replaceOptions.call({ id: settingId, options }),
|
|
||||||
onSuccess: (_data, { settingId }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.dropdownSettings.getById.queryKey({ id: settingId }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useAddDropdownOption = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
settingId,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
settingId: string;
|
|
||||||
dto: CreateDropdownOptionDto;
|
|
||||||
}) => api.dropdownSettings.addOption.call({ id: settingId, dto }),
|
|
||||||
onSuccess: (_data, { settingId }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.dropdownSettings.getById.queryKey({ id: settingId }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateDropdownOption = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
optionId,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
optionId: string;
|
|
||||||
dto: UpdateDropdownOptionDto;
|
|
||||||
}) => api.dropdownSettings.updateOption.call({ optionId, dto }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useRemoveDropdownOption = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (optionId: string) =>
|
|
||||||
api.dropdownSettings.removeOption.call({ optionId }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { facilityService } from '@/services/facility.service';
|
|
||||||
|
|
||||||
export const facilityKeys = {
|
|
||||||
all: ['facilities'] as const,
|
|
||||||
list: () => ['facilities', 'list'] as const,
|
|
||||||
detail: (id: string) => ['facilities', 'detail', id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useFacilities() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: facilityKeys.list(),
|
|
||||||
queryFn: () => facilityService.list().then((r) => r.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import { api } from "@/services/api";
|
|
||||||
import type {
|
|
||||||
CreateFileUploadFieldDto,
|
|
||||||
CreateFileUploadSettingDto,
|
|
||||||
UpdateFileUploadFieldDto,
|
|
||||||
UpdateFileUploadSettingDto,
|
|
||||||
} from "@/types/fileUploadSettings";
|
|
||||||
|
|
||||||
/* ----------------------------- Mutations ----------------------------- */
|
|
||||||
|
|
||||||
export const useCreateFileUploadSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (dto: CreateFileUploadSettingDto) =>
|
|
||||||
api.fileUploadSettings.create.call(dto),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateFileUploadSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
id,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
dto: UpdateFileUploadSettingDto;
|
|
||||||
}) => api.fileUploadSettings.update.call({ id, dto }),
|
|
||||||
onSuccess: (_data, { id }) => {
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
});
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.getById.queryKey({ id }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDeleteFileUploadSetting = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (id: string) => api.fileUploadSettings.remove.call({ id }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useReplaceFileUploadFields = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
settingId,
|
|
||||||
fields,
|
|
||||||
}: {
|
|
||||||
settingId: string;
|
|
||||||
fields: CreateFileUploadFieldDto[];
|
|
||||||
}) => api.fileUploadSettings.replaceFields.call({ id: settingId, fields }),
|
|
||||||
onSuccess: (_data, { settingId }) => {
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
});
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.getById.queryKey({ id: settingId }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useAddFileUploadField = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
settingId,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
settingId: string;
|
|
||||||
dto: CreateFileUploadFieldDto;
|
|
||||||
}) => api.fileUploadSettings.addField.call({ settingId, dto }),
|
|
||||||
onSuccess: (_data, { settingId }) => {
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
});
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.getById.queryKey({ id: settingId }),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateFileUploadField = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
fieldId,
|
|
||||||
dto,
|
|
||||||
}: {
|
|
||||||
fieldId: string;
|
|
||||||
dto: UpdateFileUploadFieldDto;
|
|
||||||
}) => api.fileUploadSettings.updateField.call({ fieldId, dto }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useRemoveFileUploadField = () => {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (fieldId: string) =>
|
|
||||||
api.fileUploadSettings.removeField.call({ fieldId }),
|
|
||||||
onSuccess: () =>
|
|
||||||
qc.invalidateQueries({
|
|
||||||
queryKey: api.fileUploadSettings.list.queryKey(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { locomotivesService } from '@/services/locomotives.service';
|
|
||||||
|
|
||||||
export const locomotiveKeys = {
|
|
||||||
all: ['locomotives'] as const,
|
|
||||||
details: () => [...locomotiveKeys.all, 'detail'] as const,
|
|
||||||
detail: (id: string) => [...locomotiveKeys.details(), id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useLocomotives() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: locomotiveKeys.all,
|
|
||||||
queryFn: () => locomotivesService.getAll().then((response) => response.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCreateLocomotive() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: locomotivesService.create,
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: locomotiveKeys.all }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateLocomotive() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
|
|
||||||
locomotivesService.update(id, data),
|
|
||||||
onSuccess: (_, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: locomotiveKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: locomotiveKeys.detail(id) });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDecommissionLocomotive() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: locomotivesService.decommission,
|
|
||||||
onSuccess: (_, id) => {
|
|
||||||
qc.invalidateQueries({ queryKey: locomotiveKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: locomotiveKeys.detail(id) });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import {
|
|
||||||
paymentsService,
|
|
||||||
type PaymentListFilter,
|
|
||||||
} from "@/services/payments.service";
|
|
||||||
|
|
||||||
export function usePaymentList(filter?: PaymentListFilter, enabled = true) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ["payments", "list", filter ?? {}],
|
|
||||||
queryFn: () => paymentsService.list(filter),
|
|
||||||
enabled,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function usePaymentSummary(enabled = true) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ["payments", "summary"],
|
|
||||||
queryFn: () => paymentsService.getSummary(),
|
|
||||||
staleTime: 30_000,
|
|
||||||
enabled,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { routesService } from '@/services/routes.service';
|
|
||||||
|
|
||||||
export const routeKeys = {
|
|
||||||
all: ['routes'] as const,
|
|
||||||
yards: ['routes', 'yards'] as const,
|
|
||||||
details: () => [...routeKeys.all, 'detail'] as const,
|
|
||||||
detail: (id: string) => [...routeKeys.details(), id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useRoutes() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: routeKeys.all,
|
|
||||||
queryFn: () => routesService.getAll().then((response) => response.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useRouteYards() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: routeKeys.yards,
|
|
||||||
queryFn: () => routesService.getYards().then((response) => response.data.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCreateRoute() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: routesService.create,
|
|
||||||
onSuccess: () => qc.invalidateQueries({ queryKey: routeKeys.all }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateRoute() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
|
|
||||||
routesService.update(id, data),
|
|
||||||
onSuccess: (_, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: routeKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: routeKeys.detail(id) });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDeactivateRoute() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: routesService.deactivate,
|
|
||||||
onSuccess: (_, id) => {
|
|
||||||
qc.invalidateQueries({ queryKey: routeKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: routeKeys.detail(id) });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
|
|
||||||
import {
|
|
||||||
signaturesService,
|
|
||||||
type SaveSignaturePayload,
|
|
||||||
} from "@/services/signatures.service";
|
|
||||||
|
|
||||||
const SAVED_SIGNATURE_KEY = ["me", "signature"] as const;
|
|
||||||
|
|
||||||
export function useMySignature() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: SAVED_SIGNATURE_KEY,
|
|
||||||
queryFn: () => signaturesService.getMySignature(),
|
|
||||||
staleTime: 60_000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useSaveSignature() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (payload: SaveSignaturePayload) =>
|
|
||||||
signaturesService.saveMySignature(payload),
|
|
||||||
onSuccess: () => {
|
|
||||||
toast.success("Signature saved");
|
|
||||||
void qc.invalidateQueries({ queryKey: SAVED_SIGNATURE_KEY });
|
|
||||||
},
|
|
||||||
onError: () => toast.error("Failed to save signature"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { trainSchedulingService } from '@/services/trainScheduling.service';
|
|
||||||
import { QUERY_KEYS } from '@/constants/QUERY_KEYS';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The 21 network stations / yards, sourced from the existing booking
|
|
||||||
* reference-data API. Reused as the parent "Facility / Port" for warehouses.
|
|
||||||
*/
|
|
||||||
export function useStations() {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.stations(),
|
|
||||||
queryFn: () => trainSchedulingService.getStations(),
|
|
||||||
staleTime: 5 * 60 * 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { trainService } from '@/services/trains.service';
|
|
||||||
|
|
||||||
export const trainKeys = {
|
|
||||||
all: ['trains'] as const,
|
|
||||||
lists: () => [...trainKeys.all, 'list'] as const,
|
|
||||||
details: () => [...trainKeys.all, 'detail'] as const,
|
|
||||||
detail: (id: string) => [...trainKeys.details(), id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useTrains() {
|
|
||||||
return useQuery({ queryKey: trainKeys.lists(), queryFn: () => trainService.getAll().then(res => res.data) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetTrains = useTrains;
|
|
||||||
|
|
||||||
export function useTrain(id: string) {
|
|
||||||
return useQuery({ queryKey: trainKeys.detail(id), queryFn: () => trainService.getById(id).then(res => res.data), enabled: !!id });
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetTrain = useTrain;
|
|
||||||
|
|
||||||
export function useCreateTrain() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: trainService.create, onSuccess: () => qc.invalidateQueries({ queryKey: trainKeys.lists() }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateTrain() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: ({ id, data }: any) => trainService.update(id, data), onSuccess: (_, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: trainKeys.lists() });
|
|
||||||
qc.invalidateQueries({ queryKey: trainKeys.detail(id) });
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDeleteTrain() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: trainService.delete, onSuccess: () => qc.invalidateQueries({ queryKey: trainKeys.lists() }) });
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { wagonService } from '@/services/wagon.service';
|
|
||||||
|
|
||||||
export type WagonListFilters = import('@/services/wagon.service').WagonListFilters;
|
|
||||||
|
|
||||||
export const wagonKeys = {
|
|
||||||
all: ['wagons'] as const,
|
|
||||||
list: (filters?: WagonListFilters) => [...wagonKeys.all, 'list', filters ?? {}] as const,
|
|
||||||
byTrain: (trainId: string) => [...wagonKeys.all, 'train', trainId] as const,
|
|
||||||
details: () => [...wagonKeys.all, 'detail'] as const,
|
|
||||||
detail: (id: string) => [...wagonKeys.details(), id] as const,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useWagons(filters?: WagonListFilters) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: wagonKeys.list(filters),
|
|
||||||
queryFn: () => wagonService.getAll(filters ?? {}).then((res) => res.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetWagons = useWagons;
|
|
||||||
|
|
||||||
export function useWagonsByTrain(trainId: string) {
|
|
||||||
return useQuery({ queryKey: wagonKeys.byTrain(trainId), queryFn: () => wagonService.getByTrain(trainId).then(res => res.data), enabled: !!trainId });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useWagon(id: string) {
|
|
||||||
return useQuery({ queryKey: wagonKeys.detail(id), queryFn: () => wagonService.getById(id).then(res => res.data), enabled: !!id });
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGetWagon = useWagon;
|
|
||||||
|
|
||||||
export function useAssignWagonToTrain() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: ({ wagonId, trainId, sequenceNumber }: any) => wagonService.assignToTrain(wagonId, trainId, sequenceNumber), onSuccess: (_, { trainId }) => qc.invalidateQueries({ queryKey: wagonKeys.byTrain(trainId) }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUnassignWagon() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: wagonService.unassign, onSuccess: () => qc.invalidateQueries({ queryKey: wagonKeys.all }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useReorderWagons() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: ({ trainId, wagonIds }: any) => wagonService.reorder(trainId, wagonIds), onSuccess: (_, { trainId }) => qc.invalidateQueries({ queryKey: wagonKeys.byTrain(trainId) }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useCreateWagon() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: wagonService.create, onSuccess: () => qc.invalidateQueries({ queryKey: wagonKeys.all }) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUpdateWagon() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: ({ id, data }: any) => wagonService.update(id, data), onSuccess: (_, { id }) => {
|
|
||||||
qc.invalidateQueries({ queryKey: wagonKeys.all });
|
|
||||||
qc.invalidateQueries({ queryKey: wagonKeys.detail(id) });
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDeleteWagon() {
|
|
||||||
const qc = useQueryClient();
|
|
||||||
return useMutation({ mutationFn: wagonService.delete, onSuccess: () => qc.invalidateQueries({ queryKey: wagonKeys.all }) });
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { isAxiosError } from "axios";
|
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Badge,
|
Badge,
|
||||||
@@ -23,6 +19,8 @@ import {
|
|||||||
ThemeIcon,
|
ThemeIcon,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { isAxiosError } from "axios";
|
||||||
import {
|
import {
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
@@ -40,14 +38,16 @@ import {
|
|||||||
Trash2,
|
Trash2,
|
||||||
Weight,
|
Weight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import Breadcrumbs from "@/components/ui/Breadcrumbs";
|
|
||||||
import { bookingsService } from "@/services/bookings.service";
|
|
||||||
import { useAvailableDays } from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { api } from "@/auth/http";
|
import { api } from "@/auth/http";
|
||||||
import { unwrap } from "@/utils/endpoint";
|
import Breadcrumbs from "@/components/ui/Breadcrumbs";
|
||||||
import { URL_CONSTANTS } from "@/constants/URLS";
|
import { URL_CONSTANTS } from "@/constants/URLS";
|
||||||
|
import { api as appApi } from "@/services/api";
|
||||||
|
import { bookingsService } from "@/services/bookings.service";
|
||||||
|
import { unwrap } from "@/utils/endpoint";
|
||||||
|
|
||||||
interface CompanyOption {
|
interface CompanyOption {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -234,9 +234,11 @@ export default function NewBookingPage() {
|
|||||||
|
|
||||||
// Day-level pool: fetch only the days that have a departure on the route (no
|
// Day-level pool: fetch only the days that have a departure on the route (no
|
||||||
// train, no capacity). The batch engine assigns the train after booking.
|
// train, no capacity). The batch engine assigns the train after booking.
|
||||||
const { data: availableDays, isLoading: daysLoading } = useAvailableDays(
|
const { data: availableDays, isLoading: daysLoading } = useQuery(
|
||||||
originYardId,
|
appApi.trainScheduling.availableDays.queryOptions({
|
||||||
destinationYardId,
|
input: { originYardId, destinationYardId },
|
||||||
|
enabled: Boolean(originYardId && destinationYardId),
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
const dayOptions = (availableDays ?? []).map((day) => ({
|
const dayOptions = (availableDays ?? []).map((day) => ({
|
||||||
value: day,
|
value: day,
|
||||||
@@ -392,7 +394,7 @@ export default function NewBookingPage() {
|
|||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Grid gutter="lg" mt="lg">
|
<Grid gap="lg" mt="lg">
|
||||||
{/* LEFT — form */}
|
{/* LEFT — form */}
|
||||||
<Grid.Col span={{ base: 12, lg: 8 }}>
|
<Grid.Col span={{ base: 12, lg: 8 }}>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
@@ -453,7 +455,6 @@ export default function NewBookingPage() {
|
|||||||
value={originYardId}
|
value={originYardId}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setOriginYardId(v);
|
setOriginYardId(v);
|
||||||
setTrainScheduleId(null);
|
|
||||||
}}
|
}}
|
||||||
searchable
|
searchable
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { Label } from "@/components/ui/label";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { FileUploadEntity } from "@edr/types/freight";
|
import { FileUploadEntity } from "@edr/types/freight";
|
||||||
import { useCreateFileUploadSetting, useUpdateFileUploadSetting } from "@/hooks/useFileUploadSettings";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { api } from "@/services/api";
|
||||||
|
|
||||||
// import type {
|
// import type {
|
||||||
// FileUploadEntity,
|
// FileUploadEntity,
|
||||||
@@ -61,8 +62,8 @@ export default function EditFileUploadSettingDialog({
|
|||||||
const [description, setDescription] = useState(setting?.description ?? "");
|
const [description, setDescription] = useState(setting?.description ?? "");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
const createMutation = useCreateFileUploadSetting();
|
const createMutation = useMutation(api.fileUploadSettings.create.mutationOptions());
|
||||||
const updateMutation = useUpdateFileUploadSetting();
|
const updateMutation = useMutation(api.fileUploadSettings.update.mutationOptions());
|
||||||
const pending = createMutation.isPending || updateMutation.isPending;
|
const pending = createMutation.isPending || updateMutation.isPending;
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
|
|||||||
@@ -25,12 +25,11 @@ import {
|
|||||||
Trash2,
|
Trash2,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
||||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||||
import { api } from "@/services/api";
|
import { api } from "@/services/api";
|
||||||
import { useDeleteFileUploadSetting } from "@/hooks/useFileUploadSettings";
|
|
||||||
import { getMinFiles, type FileUploadSetting } from "@/types/fileUploadSettings";
|
import { getMinFiles, type FileUploadSetting } from "@/types/fileUploadSettings";
|
||||||
import { DataTable, type ColumnDef } from "@edr/ui-common";
|
import { DataTable, type ColumnDef } from "@edr/ui-common";
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ export default function FileUploadSettingsPage() {
|
|||||||
const { data, isLoading, isError, error, refetch } = useQuery(
|
const { data, isLoading, isError, error, refetch } = useQuery(
|
||||||
api.fileUploadSettings.list.queryOptions(),
|
api.fileUploadSettings.list.queryOptions(),
|
||||||
);
|
);
|
||||||
const deleteMutation = useDeleteFileUploadSetting();
|
const deleteMutation = useMutation(api.fileUploadSettings.remove.mutationOptions());
|
||||||
|
|
||||||
const fileUploadSettings = useMemo(
|
const fileUploadSettings = useMemo(
|
||||||
() => (Array.isArray(data) ? data : []),
|
() => (Array.isArray(data) ? data : []),
|
||||||
@@ -202,7 +201,7 @@ export default function FileUploadSettingsPage() {
|
|||||||
<DeleteFileUploadSettingDialog
|
<DeleteFileUploadSettingDialog
|
||||||
settingLabel={setting.label}
|
settingLabel={setting.label}
|
||||||
settingCode={setting.code}
|
settingCode={setting.code}
|
||||||
onConfirm={() => deleteMutation.mutate(setting.id)}
|
onConfirm={() => deleteMutation.mutate({ id: setting.id })}
|
||||||
>
|
>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
variant="default"
|
variant="default"
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import type {
|
|||||||
FileUploadSetting,
|
FileUploadSetting,
|
||||||
} from "@/types/fileUploadSettings";
|
} from "@/types/fileUploadSettings";
|
||||||
import { getMinFiles } from "@/types/fileUploadSettings";
|
import { getMinFiles } from "@/types/fileUploadSettings";
|
||||||
import { useReplaceFileUploadFields } from "@/hooks/useFileUploadSettings";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { api } from "@/services/api";
|
||||||
|
|
||||||
export interface ManageFileUploadFieldsDialogProps {
|
export interface ManageFileUploadFieldsDialogProps {
|
||||||
setting: FileUploadSetting;
|
setting: FileUploadSetting;
|
||||||
@@ -77,7 +78,9 @@ export default function ManageFileUploadFieldsDialog({
|
|||||||
|
|
||||||
const [fields, setFields] = useState<DraftField[]>(seed);
|
const [fields, setFields] = useState<DraftField[]>(seed);
|
||||||
|
|
||||||
const replaceMutation = useReplaceFileUploadFields();
|
const replaceMutation = useMutation(
|
||||||
|
api.fileUploadSettings.replaceFields.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
const update = (i: number, patch: Partial<DraftField>) =>
|
const update = (i: number, patch: Partial<DraftField>) =>
|
||||||
setFields((prev) =>
|
setFields((prev) =>
|
||||||
@@ -145,7 +148,7 @@ export default function ManageFileUploadFieldsDialog({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
replaceMutation.mutate(
|
replaceMutation.mutate(
|
||||||
{ settingId: setting.id, fields: payload },
|
{ id: setting.id, fields: payload },
|
||||||
{
|
{
|
||||||
onSuccess: () => setOpen(false),
|
onSuccess: () => setOpen(false),
|
||||||
onError: (err) =>
|
onError: (err) =>
|
||||||
|
|||||||
@@ -31,9 +31,8 @@ import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
|||||||
import EditDropdownSettingDialog from "./EditDropdownSettingDialog";
|
import EditDropdownSettingDialog from "./EditDropdownSettingDialog";
|
||||||
import ManageDropdownOptionsDialog from "./ManageDropdownOptionsDialog";
|
import ManageDropdownOptionsDialog from "./ManageDropdownOptionsDialog";
|
||||||
import DeleteDropdownSettingDialog from "./DeleteDropdownSettingDialog";
|
import DeleteDropdownSettingDialog from "./DeleteDropdownSettingDialog";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { api } from "@/services/api";
|
import { api } from "@/services/api";
|
||||||
import { useDeleteDropdownSetting } from "@/hooks/useDropdownSettings";
|
|
||||||
import type { DropdownSetting } from "@/types/dropdownSettings";
|
import type { DropdownSetting } from "@/types/dropdownSettings";
|
||||||
import {
|
import {
|
||||||
DataTable,
|
DataTable,
|
||||||
@@ -63,7 +62,7 @@ export default function DropdownSettingsPage() {
|
|||||||
const { data, isLoading, isError, error } = useQuery(
|
const { data, isLoading, isError, error } = useQuery(
|
||||||
api.dropdownSettings.list.queryOptions(),
|
api.dropdownSettings.list.queryOptions(),
|
||||||
);
|
);
|
||||||
const deleteMutation = useDeleteDropdownSetting();
|
const deleteMutation = useMutation(api.dropdownSettings.remove.mutationOptions());
|
||||||
|
|
||||||
const dropdownSettings = useMemo<DropdownSetting[]>(
|
const dropdownSettings = useMemo<DropdownSetting[]>(
|
||||||
() => (Array.isArray(data) ? data : []),
|
() => (Array.isArray(data) ? data : []),
|
||||||
@@ -353,7 +352,7 @@ export default function DropdownSettingsPage() {
|
|||||||
key={`delete-${activeSetting.id}`}
|
key={`delete-${activeSetting.id}`}
|
||||||
settingLabel={activeSetting.label}
|
settingLabel={activeSetting.label}
|
||||||
settingCode={activeSetting.code}
|
settingCode={activeSetting.code}
|
||||||
onConfirm={() => deleteMutation.mutate(activeSetting.id)}
|
onConfirm={() => deleteMutation.mutate({ id: activeSetting.id })}
|
||||||
open={activeDialog === "delete"}
|
open={activeDialog === "delete"}
|
||||||
onOpenChange={(next) => (next ? null : closeDialog())}
|
onOpenChange={(next) => (next ? null : closeDialog())}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ import type {
|
|||||||
DropdownSetting,
|
DropdownSetting,
|
||||||
UpdateDropdownSettingDto,
|
UpdateDropdownSettingDto,
|
||||||
} from "@/types/dropdownSettings";
|
} from "@/types/dropdownSettings";
|
||||||
import {
|
import { useMutation } from "@tanstack/react-query";
|
||||||
useCreateDropdownSetting,
|
|
||||||
useUpdateDropdownSetting,
|
import { api } from "@/services/api";
|
||||||
} from "@/hooks/useDropdownSettings";
|
|
||||||
|
|
||||||
export interface EditDropdownSettingDialogProps {
|
export interface EditDropdownSettingDialogProps {
|
||||||
mode?: "create" | "edit";
|
mode?: "create" | "edit";
|
||||||
@@ -76,8 +75,8 @@ export default function EditDropdownSettingDialog({
|
|||||||
);
|
);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
const createMutation = useCreateDropdownSetting();
|
const createMutation = useMutation(api.dropdownSettings.create.mutationOptions());
|
||||||
const updateMutation = useUpdateDropdownSetting();
|
const updateMutation = useMutation(api.dropdownSettings.update.mutationOptions());
|
||||||
const pending = createMutation.isPending || updateMutation.isPending;
|
const pending = createMutation.isPending || updateMutation.isPending;
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ import type {
|
|||||||
CreateDropdownOptionDto,
|
CreateDropdownOptionDto,
|
||||||
DropdownSetting,
|
DropdownSetting,
|
||||||
} from "@/types/dropdownSettings";
|
} from "@/types/dropdownSettings";
|
||||||
import { useReplaceDropdownOptions } from "@/hooks/useDropdownSettings";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { api } from "@/services/api";
|
||||||
|
|
||||||
export interface ManageDropdownOptionsDialogProps {
|
export interface ManageDropdownOptionsDialogProps {
|
||||||
setting: DropdownSetting;
|
setting: DropdownSetting;
|
||||||
@@ -84,7 +85,9 @@ export default function ManageDropdownOptionsDialog({
|
|||||||
|
|
||||||
const [options, setOptions] = useState<DraftOption[]>(seed);
|
const [options, setOptions] = useState<DraftOption[]>(seed);
|
||||||
|
|
||||||
const replaceMutation = useReplaceDropdownOptions();
|
const replaceMutation = useMutation(
|
||||||
|
api.dropdownSettings.replaceOptions.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
const update = (i: number, patch: Partial<DraftOption>) =>
|
const update = (i: number, patch: Partial<DraftOption>) =>
|
||||||
setOptions((prev) =>
|
setOptions((prev) =>
|
||||||
@@ -147,7 +150,7 @@ export default function ManageDropdownOptionsDialog({
|
|||||||
});
|
});
|
||||||
|
|
||||||
replaceMutation.mutate(
|
replaceMutation.mutate(
|
||||||
{ settingId: setting.id, options: payload },
|
{ id: setting.id, options: payload },
|
||||||
{
|
{
|
||||||
onSuccess: () => setOpen(false),
|
onSuccess: () => setOpen(false),
|
||||||
onError: (err) =>
|
onError: (err) =>
|
||||||
|
|||||||
@@ -36,30 +36,7 @@ import { Input } from '@/components/ui/input';
|
|||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@edr/ui-common';
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||||
import { useCargoTypes } from '@/hooks/use-cargo-types';
|
|
||||||
import { useContainerTypes } from '@/hooks/use-container-types';
|
|
||||||
import {
|
|
||||||
useCreateWagonType,
|
|
||||||
useDeleteWagonType,
|
|
||||||
useUpdateWagonType,
|
|
||||||
useWagonTypes,
|
|
||||||
} from '@/hooks/use-wagon-types';
|
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import {
|
|
||||||
useContainers,
|
|
||||||
useCreateContainer,
|
|
||||||
useDeleteContainer,
|
|
||||||
useUpdateContainer,
|
|
||||||
} from '@/hooks/useContainers';
|
|
||||||
import { useCreateTrain, useDeleteTrain, useTrains, useUpdateTrain } from '@/hooks/useTrains';
|
|
||||||
import { useRouteYards } from '@/hooks/useRoutes';
|
|
||||||
import { useCreateWagon, useDeleteWagon, useUpdateWagon, useWagons } from '@/hooks/useWagons';
|
|
||||||
import {
|
|
||||||
useCreateLocomotive,
|
|
||||||
useDecommissionLocomotive,
|
|
||||||
useLocomotives,
|
|
||||||
useUpdateLocomotive,
|
|
||||||
} from '@/hooks/useLocomotives';
|
|
||||||
import type { Cargo } from '@/services/cargoService';
|
import type { Cargo } from '@/services/cargoService';
|
||||||
import { DeliverCargoDialog } from '@/components/cargoes/DeliverCargoDialog';
|
import { DeliverCargoDialog } from '@/components/cargoes/DeliverCargoDialog';
|
||||||
import type { Container } from '@/services/containerService';
|
import type { Container } from '@/services/containerService';
|
||||||
@@ -513,7 +490,7 @@ const optionLabel = (options: { value: string; label: string }[], value?: string
|
|||||||
options.find((option) => option.value === value)?.label ?? value ?? '-';
|
options.find((option) => option.value === value)?.label ?? value ?? '-';
|
||||||
|
|
||||||
export function TrainMasterDataPage() {
|
export function TrainMasterDataPage() {
|
||||||
const query = useTrains();
|
const query = useQuery(api.trains.list.queryOptions());
|
||||||
return (
|
return (
|
||||||
<FleetCrudPage<Train>
|
<FleetCrudPage<Train>
|
||||||
title="Trains"
|
title="Trains"
|
||||||
@@ -521,9 +498,9 @@ export function TrainMasterDataPage() {
|
|||||||
addLabel="Add Train"
|
addLabel="Add Train"
|
||||||
data={query.data}
|
data={query.data}
|
||||||
isLoading={query.isLoading}
|
isLoading={query.isLoading}
|
||||||
create={useCreateTrain()}
|
create={useMutation(api.trains.create.mutationOptions())}
|
||||||
update={useUpdateTrain()}
|
update={useMutation(api.trains.update.mutationOptions())}
|
||||||
remove={useDeleteTrain()}
|
remove={useMutation(api.trains.remove.mutationOptions())}
|
||||||
searchText={(train) => [train.code, train.trainNumber, train.trainName, train.status].join(' ')}
|
searchText={(train) => [train.code, train.trainNumber, train.trainName, train.status].join(' ')}
|
||||||
columns={[
|
columns={[
|
||||||
{ key: 'code', label: 'Code' },
|
{ key: 'code', label: 'Code' },
|
||||||
@@ -548,10 +525,10 @@ export function TrainMasterDataPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WagonTypesCrudPage() {
|
export function WagonTypesCrudPage() {
|
||||||
const query = useWagonTypes();
|
const query = useQuery(api.wagonTypes.list.queryOptions());
|
||||||
const create = useCreateWagonType();
|
const create = useMutation(api.wagonTypes.create.mutationOptions());
|
||||||
const update = useUpdateWagonType();
|
const update = useMutation(api.wagonTypes.update.mutationOptions());
|
||||||
const remove = useDeleteWagonType();
|
const remove = useMutation(api.wagonTypes.remove.mutationOptions());
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
@@ -898,9 +875,9 @@ export function WagonTypesCrudPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WagonsCrudPage() {
|
export function WagonsCrudPage() {
|
||||||
const query = useWagons();
|
const query = useQuery(api.wagons.list.queryOptions({ input: {} }));
|
||||||
const { data: wagonTypes = [] } = useWagonTypes();
|
const { data: wagonTypes = [] } = useQuery(api.wagonTypes.list.queryOptions());
|
||||||
const { data: yards = [] } = useRouteYards();
|
const { data: yards = [] } = useQuery(api.routes.yards.queryOptions());
|
||||||
const wagonTypeOptions = wagonTypes.map((type: any) => ({
|
const wagonTypeOptions = wagonTypes.map((type: any) => ({
|
||||||
value: type.id,
|
value: type.id,
|
||||||
label: `${type.code} - ${type.name}`,
|
label: `${type.code} - ${type.name}`,
|
||||||
@@ -916,9 +893,9 @@ export function WagonsCrudPage() {
|
|||||||
addLabel="Add Wagon"
|
addLabel="Add Wagon"
|
||||||
data={query.data}
|
data={query.data}
|
||||||
isLoading={query.isLoading}
|
isLoading={query.isLoading}
|
||||||
create={useCreateWagon()}
|
create={useMutation(api.wagons.create.mutationOptions())}
|
||||||
update={useUpdateWagon()}
|
update={useMutation(api.wagons.update.mutationOptions())}
|
||||||
remove={useDeleteWagon()}
|
remove={useMutation(api.wagons.remove.mutationOptions())}
|
||||||
searchText={(wagon) => [
|
searchText={(wagon) => [
|
||||||
wagon.wagonNumber,
|
wagon.wagonNumber,
|
||||||
wagon.wagonTypeId,
|
wagon.wagonTypeId,
|
||||||
@@ -986,9 +963,11 @@ export function WagonsCrudPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ContainersCrudPage() {
|
export function ContainersCrudPage() {
|
||||||
const query = useContainers();
|
const query = useQuery(api.containers.list.queryOptions());
|
||||||
const { data: containerTypes = [] } = useContainerTypes();
|
const { data: containerTypes = [] } = useQuery(
|
||||||
const { data: wagons = [] } = useWagons();
|
api.containerTypes.list.queryOptions({ staleTime: Infinity }),
|
||||||
|
);
|
||||||
|
const { data: wagons = [] } = useQuery(api.wagons.list.queryOptions({ input: {} }));
|
||||||
const containerTypeOptions = containerTypes.map((type: any) => ({
|
const containerTypeOptions = containerTypes.map((type: any) => ({
|
||||||
value: type.id,
|
value: type.id,
|
||||||
label: type.label ?? type.name ?? type.code,
|
label: type.label ?? type.name ?? type.code,
|
||||||
@@ -1004,9 +983,9 @@ export function ContainersCrudPage() {
|
|||||||
addLabel="Add Container"
|
addLabel="Add Container"
|
||||||
data={query.data}
|
data={query.data}
|
||||||
isLoading={query.isLoading}
|
isLoading={query.isLoading}
|
||||||
create={useCreateContainer()}
|
create={useMutation(api.containers.create.mutationOptions())}
|
||||||
update={useUpdateContainer()}
|
update={useMutation(api.containers.update.mutationOptions())}
|
||||||
remove={useDeleteContainer()}
|
remove={useMutation(api.containers.remove.mutationOptions())}
|
||||||
searchText={(container) => [container.containerNumber, container.containerTypeId, container.wagonId, container.status].join(' ')}
|
searchText={(container) => [container.containerNumber, container.containerTypeId, container.wagonId, container.status].join(' ')}
|
||||||
columns={[
|
columns={[
|
||||||
{ key: 'containerNumber', label: 'Number' },
|
{ key: 'containerNumber', label: 'Number' },
|
||||||
@@ -1044,8 +1023,10 @@ export function ContainersCrudPage() {
|
|||||||
|
|
||||||
export function CargoesCrudPage() {
|
export function CargoesCrudPage() {
|
||||||
const query = useQuery(api.cargoes.list.queryOptions());
|
const query = useQuery(api.cargoes.list.queryOptions());
|
||||||
const { data: cargoTypes = [] } = useCargoTypes();
|
const { data: cargoTypes = [] } = useQuery(
|
||||||
const { data: containers = [] } = useContainers();
|
api.cargoTypes.list.queryOptions({ staleTime: Infinity }),
|
||||||
|
);
|
||||||
|
const { data: containers = [] } = useQuery(api.containers.list.queryOptions());
|
||||||
const cargoTypeOptions = cargoTypes.map((type: any) => ({
|
const cargoTypeOptions = cargoTypes.map((type: any) => ({
|
||||||
value: type.id,
|
value: type.id,
|
||||||
label: type.cargoTypeName ?? type.cargo_type_name ?? type.name ?? type.code,
|
label: type.cargoTypeName ?? type.cargo_type_name ?? type.name ?? type.code,
|
||||||
@@ -1112,7 +1093,7 @@ export function CargoesCrudPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function LocomotivesCrudPage() {
|
export function LocomotivesCrudPage() {
|
||||||
const query = useLocomotives();
|
const query = useQuery(api.locomotives.list.queryOptions());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FleetCrudPage<Locomotive>
|
<FleetCrudPage<Locomotive>
|
||||||
@@ -1122,9 +1103,9 @@ export function LocomotivesCrudPage() {
|
|||||||
addLabel="Add Locomotive"
|
addLabel="Add Locomotive"
|
||||||
data={query.data}
|
data={query.data}
|
||||||
isLoading={query.isLoading}
|
isLoading={query.isLoading}
|
||||||
create={useCreateLocomotive()}
|
create={useMutation(api.locomotives.create.mutationOptions())}
|
||||||
update={useUpdateLocomotive()}
|
update={useMutation(api.locomotives.update.mutationOptions())}
|
||||||
remove={useDecommissionLocomotive()}
|
remove={useMutation(api.locomotives.decommission.mutationOptions())}
|
||||||
removeActionLabel="Decommission"
|
removeActionLabel="Decommission"
|
||||||
removeConfirmMessage="Decommission this locomotive?"
|
removeConfirmMessage="Decommission this locomotive?"
|
||||||
removeSuccessMessage="Locomotive decommissioned"
|
removeSuccessMessage="Locomotive decommissioned"
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import type { ColumnDef } from "@edr/ui-common";
|
import type { ColumnDef } from "@edr/ui-common";
|
||||||
import { Box, Button, Card, Group, Modal, Select, Stack, Text } from "@mantine/core";
|
import { Box, Button, Card, Group, Modal, Select, Stack, Text } from "@mantine/core";
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import { api } from "@/services/api";
|
||||||
import {
|
import {
|
||||||
Archive,
|
Archive,
|
||||||
Circle,
|
Circle,
|
||||||
@@ -22,14 +25,7 @@ import { formatFleetCell, registerFleetOptionLabels } from "@/components/fleet/f
|
|||||||
import { useFleetViewMode } from "@/components/fleet/useFleetViewMode";
|
import { useFleetViewMode } from "@/components/fleet/useFleetViewMode";
|
||||||
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
||||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||||
import { useFleetList, useFleetMutations } from "@/hooks/fleet/useFleet";
|
|
||||||
import { useCargoTypes } from "@/hooks/use-cargo-types";
|
|
||||||
import { useContainerTypes } from "@/hooks/use-container-types";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useWagonTypes } from "@/hooks/use-wagon-types";
|
|
||||||
import { useContainers } from "@/hooks/useContainers";
|
|
||||||
import { useRouteYards } from "@/hooks/useRoutes";
|
|
||||||
import { useWagons } from "@/hooks/useWagons";
|
|
||||||
import {
|
import {
|
||||||
FLEET_SELECT_NONE,
|
FLEET_SELECT_NONE,
|
||||||
getFleetResource,
|
getFleetResource,
|
||||||
@@ -90,15 +86,31 @@ const FleetResourcePage = () => {
|
|||||||
return filters;
|
return filters;
|
||||||
}, [slug, listFilterValues, search]);
|
}, [slug, listFilterValues, search]);
|
||||||
|
|
||||||
const { data: allRows = [], isLoading, isError, error } = useFleetList(slug, serverListFilters);
|
const { data: allRows = [], isLoading, isError, error } = useQuery(
|
||||||
const { create, update, remove } = useFleetMutations(slug);
|
api.fleet.list.queryOptions({ input: { slug, filters: serverListFilters } }),
|
||||||
|
);
|
||||||
|
const create = useMutation(api.fleet.create.mutationOptions());
|
||||||
|
const update = useMutation(api.fleet.update.mutationOptions());
|
||||||
|
const remove = useMutation(api.fleet.remove.mutationOptions());
|
||||||
|
|
||||||
const { data: wagonTypes = [], isLoading: wagonTypesLoading } = useWagonTypes();
|
const { data: wagonTypes = [], isLoading: wagonTypesLoading } = useQuery(
|
||||||
const { data: containerTypes = [], isLoading: containerTypesLoading } = useContainerTypes();
|
api.wagonTypes.list.queryOptions(),
|
||||||
const { data: cargoTypes = [], isLoading: cargoTypesLoading } = useCargoTypes();
|
);
|
||||||
const { data: wagons = [], isLoading: wagonsLoading } = useWagons();
|
const { data: containerTypes = [], isLoading: containerTypesLoading } = useQuery(
|
||||||
const { data: containers = [], isLoading: containersLoading } = useContainers();
|
api.containerTypes.list.queryOptions({ staleTime: Infinity }),
|
||||||
const { data: yards = [], isLoading: yardsLoading } = useRouteYards();
|
);
|
||||||
|
const { data: cargoTypes = [], isLoading: cargoTypesLoading } = useQuery(
|
||||||
|
api.cargoTypes.list.queryOptions({ staleTime: Infinity }),
|
||||||
|
);
|
||||||
|
const { data: wagons = [], isLoading: wagonsLoading } = useQuery(
|
||||||
|
api.wagons.list.queryOptions({ input: {} }),
|
||||||
|
);
|
||||||
|
const { data: containers = [], isLoading: containersLoading } = useQuery(
|
||||||
|
api.containers.list.queryOptions(),
|
||||||
|
);
|
||||||
|
const { data: yards = [], isLoading: yardsLoading } = useQuery(
|
||||||
|
api.routes.yards.queryOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPagination((prev) => ({ pageIndex: 0, pageSize: prev.pageSize }));
|
setPagination((prev) => ({ pageIndex: 0, pageSize: prev.pageSize }));
|
||||||
@@ -316,10 +328,10 @@ const FleetResourcePage = () => {
|
|||||||
const handleFormSubmit = async (values: Record<string, unknown>) => {
|
const handleFormSubmit = async (values: Record<string, unknown>) => {
|
||||||
try {
|
try {
|
||||||
if (editing && "id" in editing) {
|
if (editing && "id" in editing) {
|
||||||
await update.mutateAsync({ id: String(editing.id), data: values });
|
await update.mutateAsync({ slug, id: String(editing.id), data: values });
|
||||||
toast({ title: `${config.entityLabel} updated` });
|
toast({ title: `${config.entityLabel} updated` });
|
||||||
} else {
|
} else {
|
||||||
await create.mutateAsync(values);
|
await create.mutateAsync({ slug, data: values });
|
||||||
toast({ title: `${config.entityLabel} created` });
|
toast({ title: `${config.entityLabel} created` });
|
||||||
}
|
}
|
||||||
setFormOpen(false);
|
setFormOpen(false);
|
||||||
@@ -335,7 +347,7 @@ const FleetResourcePage = () => {
|
|||||||
const handleRemove = async () => {
|
const handleRemove = async () => {
|
||||||
if (!removeTarget || !("id" in removeTarget)) return;
|
if (!removeTarget || !("id" in removeTarget)) return;
|
||||||
try {
|
try {
|
||||||
await remove.mutateAsync(String(removeTarget.id));
|
await remove.mutateAsync({ slug, id: String(removeTarget.id) });
|
||||||
toast({
|
toast({
|
||||||
title: config.removeSuccessMessage ?? `${config.entityLabel} removed`,
|
title: config.removeSuccessMessage ?? `${config.entityLabel} removed`,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,18 +17,14 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
||||||
import FleetToolbar from "@/components/fleet/FleetToolbar";
|
import FleetToolbar from "@/components/fleet/FleetToolbar";
|
||||||
import { useFleetViewMode } from "@/components/fleet/useFleetViewMode";
|
import { useFleetViewMode } from "@/components/fleet/useFleetViewMode";
|
||||||
import RuleEngineListFooter from "@/components/ruleEngine/RuleEngineListFooter";
|
import RuleEngineListFooter from "@/components/ruleEngine/RuleEngineListFooter";
|
||||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||||
import {
|
import { api } from "@/services/api";
|
||||||
useCreateRoute,
|
|
||||||
useDeactivateRoute,
|
|
||||||
useRouteYards,
|
|
||||||
useRoutes,
|
|
||||||
useUpdateRoute,
|
|
||||||
} from "@/hooks/useRoutes";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type { RouteRecord, YardRef } from "@/services/routes.service";
|
import type { RouteRecord, YardRef } from "@/services/routes.service";
|
||||||
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
|
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
|
||||||
@@ -71,11 +67,11 @@ export default function RoutesPage() {
|
|||||||
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const routesQuery = useRoutes();
|
const routesQuery = useQuery(api.routes.list.queryOptions());
|
||||||
const yardsQuery = useRouteYards();
|
const yardsQuery = useQuery(api.routes.yards.queryOptions());
|
||||||
const createMutation = useCreateRoute();
|
const createMutation = useMutation(api.routes.create.mutationOptions());
|
||||||
const updateMutation = useUpdateRoute();
|
const updateMutation = useMutation(api.routes.update.mutationOptions());
|
||||||
const deactivateMutation = useDeactivateRoute();
|
const deactivateMutation = useMutation(api.routes.deactivate.mutationOptions());
|
||||||
|
|
||||||
const filteredRoutes = useMemo(() => {
|
const filteredRoutes = useMemo(() => {
|
||||||
const query = search.trim().toLowerCase();
|
const query = search.trim().toLowerCase();
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
|
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
|
||||||
import { usePaymentList, usePaymentSummary } from "@/hooks/usePayments";
|
import { api } from "@/services/api";
|
||||||
import type { PaymentMethod, PaymentRow } from "@/services/payments.service";
|
import type { PaymentMethod, PaymentRow } from "@/services/payments.service";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
@@ -106,8 +108,12 @@ export default function PaymentsPage() {
|
|||||||
[query, statuses, method, pagination.pageIndex, pagination.pageSize],
|
[query, statuses, method, pagination.pageIndex, pagination.pageSize],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, isLoading, isError } = usePaymentList(filter);
|
const { data, isLoading, isError } = useQuery(
|
||||||
const { data: summary, isLoading: summaryLoading } = usePaymentSummary();
|
api.payments.list.queryOptions({ input: { filter } }),
|
||||||
|
);
|
||||||
|
const { data: summary, isLoading: summaryLoading } = useQuery(
|
||||||
|
api.payments.summary.queryOptions({ staleTime: 30_000 }),
|
||||||
|
);
|
||||||
|
|
||||||
const rows = data?.items ?? [];
|
const rows = data?.items ?? [];
|
||||||
const total = data?.total ?? 0;
|
const total = data?.total ?? 0;
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ import {
|
|||||||
import { RouteCorridor } from "@/components/trainScheduling/scheduleVisuals";
|
import { RouteCorridor } from "@/components/trainScheduling/scheduleVisuals";
|
||||||
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
|
||||||
import { FREIGHT_BRAND, FREIGHT_BRAND_DARK } from "@/theme/freight-brand";
|
import { FREIGHT_BRAND, FREIGHT_BRAND_DARK } from "@/theme/freight-brand";
|
||||||
import { useBatchBoard } from "@/hooks/trainScheduling/useTrainScheduling";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { api } from "@/services/api";
|
||||||
import type { BatchBoardSchedule } from "@/types/trainScheduling";
|
import type { BatchBoardSchedule } from "@/types/trainScheduling";
|
||||||
|
|
||||||
const fmtTons = (n: number) =>
|
const fmtTons = (n: number) =>
|
||||||
@@ -368,7 +369,9 @@ function CardSkeleton() {
|
|||||||
|
|
||||||
export default function BatchBoardPage() {
|
export default function BatchBoardPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data, isLoading, isError, isFetching, refetch } = useBatchBoard();
|
const { data, isLoading, isError, isFetching, refetch } = useQuery(
|
||||||
|
api.trainScheduling.batchBoard.queryOptions({ refetchInterval: 30_000 }),
|
||||||
|
);
|
||||||
const { viewMode, setViewMode } = useFleetViewMode("batch-board");
|
const { viewMode, setViewMode } = useFleetViewMode("batch-board");
|
||||||
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
const { pagination, setPagination } = usePagination({ pageSize: 10 });
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
|||||||
@@ -52,11 +52,8 @@ import {
|
|||||||
WindowStatusPill,
|
WindowStatusPill,
|
||||||
} from "@/components/trainScheduling/batchVisuals";
|
} from "@/components/trainScheduling/batchVisuals";
|
||||||
import { RouteCorridor } from "@/components/trainScheduling/scheduleVisuals";
|
import { RouteCorridor } from "@/components/trainScheduling/scheduleVisuals";
|
||||||
import {
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
useBatchBoardDetail,
|
import { api } from "@/services/api";
|
||||||
useRunAllocation,
|
|
||||||
useScheduleDetail,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type {
|
import type {
|
||||||
BatchBoardBookingDetail,
|
BatchBoardBookingDetail,
|
||||||
@@ -429,8 +426,16 @@ export default function BatchScheduleDetailPage() {
|
|||||||
const { scheduleId } = useParams<{ scheduleId: string }>();
|
const { scheduleId } = useParams<{ scheduleId: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { data, isLoading, isFetching, refetch } = useBatchBoardDetail(scheduleId);
|
const { data, isLoading, isFetching, refetch } = useQuery(
|
||||||
const runAllocation = useRunAllocation(scheduleId ?? "");
|
api.trainScheduling.batchBoardDetail.queryOptions({
|
||||||
|
input: { scheduleId: scheduleId ?? "" },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
refetchInterval: 30_000,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const runAllocation = useMutation(
|
||||||
|
api.trainScheduling.runAllocation.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
const hasAssignedWagons = useMemo(
|
const hasAssignedWagons = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -443,7 +448,12 @@ export default function BatchScheduleDetailPage() {
|
|||||||
[data],
|
[data],
|
||||||
);
|
);
|
||||||
|
|
||||||
const scheduleDetailQuery = useScheduleDetail(scheduleId, "CONTAINER");
|
const scheduleDetailQuery = useQuery(
|
||||||
|
api.trainScheduling.scheduleDetail.queryOptions({
|
||||||
|
input: { id: scheduleId ?? "", freightType: "CONTAINER" },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// Batch bookings by state for the composition side panel (payment / expired lists).
|
// Batch bookings by state for the composition side panel (payment / expired lists).
|
||||||
const batchBookings = useMemo(() => {
|
const batchBookings = useMemo(() => {
|
||||||
@@ -550,7 +560,7 @@ export default function BatchScheduleDetailPage() {
|
|||||||
|
|
||||||
const handleRunAllocation = () => {
|
const handleRunAllocation = () => {
|
||||||
runAllocation
|
runAllocation
|
||||||
.mutateAsync()
|
.mutateAsync({ scheduleId: scheduleId ?? "" })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
const failed = result.issues.filter((i) => i.status === "FAILED").length;
|
const failed = result.issues.filter((i) => i.status === "FAILED").length;
|
||||||
const deferred = result.deferred.length;
|
const deferred = result.deferred.length;
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ import { PageContainer } from "@/components/page";
|
|||||||
import { RouteCorridorTrack } from "@/components/trainScheduling/RouteCorridorTrack";
|
import { RouteCorridorTrack } from "@/components/trainScheduling/RouteCorridorTrack";
|
||||||
import { RouteCorridor, StatusPill } from "@/components/trainScheduling/scheduleVisuals";
|
import { RouteCorridor, StatusPill } from "@/components/trainScheduling/scheduleVisuals";
|
||||||
import { freightBrand } from "@/theme/freight-brand";
|
import { freightBrand } from "@/theme/freight-brand";
|
||||||
import { useTrainTrack, useScheduleMutations } from "@/hooks/trainScheduling/useTrainScheduling";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
import { api } from "@/services/api";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
|
|
||||||
const parseError = (error: unknown, fallback: string) => {
|
const parseError = (error: unknown, fallback: string) => {
|
||||||
@@ -81,8 +82,15 @@ function MetaStat({
|
|||||||
export default function TrainScheduleTrackPage() {
|
export default function TrainScheduleTrackPage() {
|
||||||
const { scheduleId } = useParams<{ scheduleId: string }>();
|
const { scheduleId } = useParams<{ scheduleId: string }>();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const trackQuery = useTrainTrack(scheduleId);
|
const trackQuery = useQuery(
|
||||||
const { recordCheckpoint } = useScheduleMutations(scheduleId);
|
api.trainScheduling.trainTrack.queryOptions({
|
||||||
|
input: { id: scheduleId ?? "" },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const recordCheckpoint = useMutation(
|
||||||
|
api.trainScheduling.recordCheckpoint.mutationOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
if (trackQuery.isLoading) {
|
if (trackQuery.isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -56,11 +56,8 @@ import { shouldShowContainerPlacementStep } from "@/components/trainScheduling/s
|
|||||||
import { TrainCompositionDiagram } from "@/components/trainScheduling/TrainCompositionDiagram";
|
import { TrainCompositionDiagram } from "@/components/trainScheduling/TrainCompositionDiagram";
|
||||||
import { WagonPlanGrid } from "@/components/trainScheduling/WagonPlanGrid";
|
import { WagonPlanGrid } from "@/components/trainScheduling/WagonPlanGrid";
|
||||||
import { WorkflowRail, WorkflowStep } from "@/components/trainScheduling/WorkflowStep";
|
import { WorkflowRail, WorkflowStep } from "@/components/trainScheduling/WorkflowStep";
|
||||||
import {
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
useEligibleBookings,
|
import { api } from "@/services/api";
|
||||||
useScheduleDetail,
|
|
||||||
useScheduleMutations,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type {
|
import type {
|
||||||
ContainerPlacement,
|
ContainerPlacement,
|
||||||
@@ -91,7 +88,12 @@ export default function TrainScheduleV2DetailPage() {
|
|||||||
const [maintenanceOpen, setMaintenanceOpen] = useState(false);
|
const [maintenanceOpen, setMaintenanceOpen] = useState(false);
|
||||||
const autoPreviewedRef = useRef(false);
|
const autoPreviewedRef = useRef(false);
|
||||||
|
|
||||||
const detailQuery = useScheduleDetail(scheduleId);
|
const detailQuery = useQuery(
|
||||||
|
api.trainScheduling.scheduleDetail.queryOptions({
|
||||||
|
input: { id: scheduleId ?? "" },
|
||||||
|
enabled: Boolean(scheduleId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
const schedule = detailQuery.data;
|
const schedule = detailQuery.data;
|
||||||
const freightType: FreightType | undefined = schedule?.freightType as FreightType | undefined;
|
const freightType: FreightType | undefined = schedule?.freightType as FreightType | undefined;
|
||||||
|
|
||||||
@@ -111,12 +113,17 @@ export default function TrainScheduleV2DetailPage() {
|
|||||||
const eligibleFreightType =
|
const eligibleFreightType =
|
||||||
freightType === "CONTAINER" || freightType === "BULK" ? freightType : undefined;
|
freightType === "CONTAINER" || freightType === "BULK" ? freightType : undefined;
|
||||||
|
|
||||||
const eligibleQuery = useEligibleBookings(
|
const eligibleQuery = useQuery(
|
||||||
eligibleFilters,
|
api.trainScheduling.eligibleBookings.queryOptions({
|
||||||
Boolean(schedule),
|
input: { filters: eligibleFilters, freightType: eligibleFreightType },
|
||||||
eligibleFreightType,
|
enabled: Boolean(schedule),
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
const { preview, assign, unassign, finalize, dispatch } = useScheduleMutations(scheduleId);
|
const preview = useMutation(api.trainScheduling.preview.mutationOptions());
|
||||||
|
const assign = useMutation(api.trainScheduling.assignBookings.mutationOptions());
|
||||||
|
const unassign = useMutation(api.trainScheduling.unassignBooking.mutationOptions());
|
||||||
|
const finalize = useMutation(api.trainScheduling.finalizeSchedule.mutationOptions());
|
||||||
|
const dispatch = useMutation(api.trainScheduling.dispatchSchedule.mutationOptions());
|
||||||
|
|
||||||
const assignedIds = useMemo(
|
const assignedIds = useMemo(
|
||||||
() => (schedule?.bookings ?? []).map((b) => b.id),
|
() => (schedule?.bookings ?? []).map((b) => b.id),
|
||||||
|
|||||||
@@ -39,13 +39,9 @@ import {
|
|||||||
RouteCorridor,
|
RouteCorridor,
|
||||||
StatusPill,
|
StatusPill,
|
||||||
} from "@/components/trainScheduling/scheduleVisuals";
|
} from "@/components/trainScheduling/scheduleVisuals";
|
||||||
import {
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
useAvailableLocomotives,
|
import { api } from "@/services/api";
|
||||||
useScheduleList,
|
|
||||||
useScheduleMutations,
|
|
||||||
} from "@/hooks/trainScheduling/useTrainScheduling";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useRoutes } from "@/hooks/useRoutes";
|
|
||||||
import type { TrainScheduleListItem } from "@/types/trainScheduling";
|
import type { TrainScheduleListItem } from "@/types/trainScheduling";
|
||||||
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
|
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
|
||||||
|
|
||||||
@@ -88,10 +84,17 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
const [scheduleDate, setScheduleDate] = useState("");
|
const [scheduleDate, setScheduleDate] = useState("");
|
||||||
const [locomotiveId, setLocomotiveId] = useState("");
|
const [locomotiveId, setLocomotiveId] = useState("");
|
||||||
|
|
||||||
const schedulesQuery = useScheduleList();
|
const schedulesQuery = useQuery(
|
||||||
const routesQuery = useRoutes();
|
api.trainScheduling.scheduleList.queryOptions({ input: {} }),
|
||||||
const locomotivesQuery = useAvailableLocomotives(routeId || undefined);
|
);
|
||||||
const { create, cancel } = useScheduleMutations();
|
const routesQuery = useQuery(api.routes.list.queryOptions());
|
||||||
|
const locomotivesQuery = useQuery(
|
||||||
|
api.trainScheduling.availableLocomotives.queryOptions({
|
||||||
|
input: { routeId: routeId || undefined },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const create = useMutation(api.trainScheduling.createSchedule.mutationOptions());
|
||||||
|
const cancel = useMutation(api.trainScheduling.cancelSchedule.mutationOptions());
|
||||||
|
|
||||||
const activeRoutes = useMemo(
|
const activeRoutes = useMemo(
|
||||||
() => (routesQuery.data ?? []).filter((r) => r.isActive),
|
() => (routesQuery.data ?? []).filter((r) => r.isActive),
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ import { useParams, Link } from "react-router-dom";
|
|||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import { Badge, Button, Card, Group, Loader, SimpleGrid, Stack, Text } from "@mantine/core";
|
import { Badge, Button, Card, Group, Loader, SimpleGrid, Stack, Text } from "@mantine/core";
|
||||||
|
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { AssignWagonDialog } from "@/components/wagons/AssignWagonDialog";
|
import { AssignWagonDialog } from "@/components/wagons/AssignWagonDialog";
|
||||||
import { WagonsTable } from "@/components/wagons/WagonsTable";
|
import { WagonsTable } from "@/components/wagons/WagonsTable";
|
||||||
import { useTrain } from "@/hooks/useTrains";
|
import { api } from "@/services/api";
|
||||||
|
|
||||||
export default function TrainDetailPage() {
|
export default function TrainDetailPage() {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const { data: train, isLoading } = useTrain(id!);
|
const { data: train, isLoading } = useQuery(
|
||||||
|
api.trains.getById.queryOptions({ input: { id: id ?? "" }, enabled: !!id }),
|
||||||
|
);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -42,7 +42,68 @@ import {
|
|||||||
type Cargo,
|
type Cargo,
|
||||||
type DeliverCargoPayload,
|
type DeliverCargoPayload,
|
||||||
} from "./cargoService";
|
} from "./cargoService";
|
||||||
|
import { containerService, type Container } from "./containerService";
|
||||||
|
import { containerTypesService } from "./container-types.service";
|
||||||
|
import {
|
||||||
|
wagonService,
|
||||||
|
type Wagon,
|
||||||
|
type WagonListFilters,
|
||||||
|
} from "./wagon.service";
|
||||||
|
import { wagonTypesService, type WagonType } from "./wagon-types.service";
|
||||||
|
import { trainService, type Train } from "./trains.service";
|
||||||
|
import {
|
||||||
|
locomotivesService,
|
||||||
|
type Locomotive,
|
||||||
|
type SaveLocomotivePayload,
|
||||||
|
} from "./locomotives.service";
|
||||||
|
import { cargoTypesService } from "./cargo-types.service";
|
||||||
|
import {
|
||||||
|
fleetService,
|
||||||
|
type FleetListFilters,
|
||||||
|
type FleetRecord,
|
||||||
|
} from "./fleet/fleet.service";
|
||||||
|
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
|
||||||
|
import {
|
||||||
|
paymentsService,
|
||||||
|
type PaginatedPayments,
|
||||||
|
type PaymentListFilter,
|
||||||
|
type PaymentSummary,
|
||||||
|
} from "./payments.service";
|
||||||
|
import {
|
||||||
|
signaturesService,
|
||||||
|
type SavedSignature,
|
||||||
|
type SaveSignaturePayload,
|
||||||
|
} from "./signatures.service";
|
||||||
import { warehouseService } from "./warehouse.service";
|
import { warehouseService } from "./warehouse.service";
|
||||||
|
import { trainSchedulingService } from "./trainScheduling.service";
|
||||||
|
import {
|
||||||
|
routesService,
|
||||||
|
type RouteRecord,
|
||||||
|
type SaveRoutePayload,
|
||||||
|
type YardRef,
|
||||||
|
} from "./routes.service";
|
||||||
|
import type {
|
||||||
|
AssignBookingsPayload,
|
||||||
|
BatchBoardSchedule,
|
||||||
|
BatchBoardScheduleDetail,
|
||||||
|
BookableSchedule,
|
||||||
|
CompositionRemovalEntry,
|
||||||
|
CreateTrainSchedulePayload,
|
||||||
|
EligibleContainerBookingsResponse,
|
||||||
|
FreightType,
|
||||||
|
LocomotiveRecord,
|
||||||
|
PinWagonsPayload,
|
||||||
|
RecordCheckpointPayload,
|
||||||
|
TrainScheduleDetail,
|
||||||
|
TrainScheduleFilters,
|
||||||
|
TrainScheduleListItem,
|
||||||
|
TrainSchedulePreviewPayload,
|
||||||
|
TrainSchedulePreviewResponse,
|
||||||
|
TrainTrackResponse,
|
||||||
|
UnassignedBookingsResponse,
|
||||||
|
WagonAllocationAttemptResult,
|
||||||
|
YardOption,
|
||||||
|
} from "@/types/trainScheduling";
|
||||||
import type {
|
import type {
|
||||||
AllocationCriteria,
|
AllocationCriteria,
|
||||||
AllocationPreviewResult,
|
AllocationPreviewResult,
|
||||||
@@ -104,7 +165,333 @@ const INVENTORY_INVALIDATIONS: ReadonlyArray<readonly unknown[]> = [
|
|||||||
["warehouses"],
|
["warehouses"],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Train-scheduling mutations broadly affect the schedule board and bookings.
|
||||||
|
* The grouped hooks invalidated TRAIN_SCHEDULING.ROOT + BOOKINGS.ROOT; since
|
||||||
|
* every train-scheduling key is prefixed with `"train-scheduling"`, the two
|
||||||
|
* roots below cover all of them via React Query's prefix matching.
|
||||||
|
*/
|
||||||
|
const TRAIN_SCHEDULING_INVALIDATIONS: ReadonlyArray<readonly unknown[]> = [
|
||||||
|
QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
||||||
|
QUERY_KEYS.BOOKINGS.ROOT,
|
||||||
|
];
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
|
trainScheduling: {
|
||||||
|
// ── Queries ────────────────────────────────────────────────────────────
|
||||||
|
scheduleList: endpoint<{ freightType?: FreightType }, TrainScheduleListItem[]>(
|
||||||
|
"train-scheduling",
|
||||||
|
"schedules",
|
||||||
|
({ freightType }) => trainSchedulingService.listSchedules(freightType),
|
||||||
|
() => QUERY_KEYS.TRAIN_SCHEDULING.schedules(),
|
||||||
|
),
|
||||||
|
|
||||||
|
batchBoard: endpoint<void, BatchBoardSchedule[]>(
|
||||||
|
"train-scheduling",
|
||||||
|
"batch-board",
|
||||||
|
() => trainSchedulingService.getBatchBoard(),
|
||||||
|
() => QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(),
|
||||||
|
),
|
||||||
|
|
||||||
|
batchBoardDetail: endpoint<{ scheduleId: string }, BatchBoardScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"batch-board-detail",
|
||||||
|
({ scheduleId }) => trainSchedulingService.getBatchBoardDetail(scheduleId),
|
||||||
|
({ scheduleId }) => QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||||
|
),
|
||||||
|
|
||||||
|
scheduleDetail: endpoint<
|
||||||
|
{ id: string; freightType?: FreightType },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"schedule-detail",
|
||||||
|
({ id, freightType }) =>
|
||||||
|
trainSchedulingService.getScheduleById(id, freightType),
|
||||||
|
({ id }) => QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(id),
|
||||||
|
),
|
||||||
|
|
||||||
|
eligibleBookings: endpoint<
|
||||||
|
{ filters?: TrainScheduleFilters; freightType?: FreightType },
|
||||||
|
EligibleContainerBookingsResponse
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"eligible-bookings",
|
||||||
|
({ filters, freightType }) =>
|
||||||
|
trainSchedulingService.getEligibleBookings(filters, freightType),
|
||||||
|
({ filters, freightType }) =>
|
||||||
|
QUERY_KEYS.TRAIN_SCHEDULING.eligible(freightType, filters),
|
||||||
|
),
|
||||||
|
|
||||||
|
availableLocomotives: endpoint<{ routeId?: string }, LocomotiveRecord[]>(
|
||||||
|
"train-scheduling",
|
||||||
|
"locomotives",
|
||||||
|
({ routeId }) => trainSchedulingService.getAvailableLocomotives(routeId),
|
||||||
|
({ routeId }) => QUERY_KEYS.TRAIN_SCHEDULING.locomotives(routeId),
|
||||||
|
),
|
||||||
|
|
||||||
|
bookableSchedules: endpoint<
|
||||||
|
{ originYardId?: string | null; destinationYardId?: string | null },
|
||||||
|
BookableSchedule[]
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"bookable",
|
||||||
|
({ originYardId, destinationYardId }) =>
|
||||||
|
trainSchedulingService.getBookableSchedules(
|
||||||
|
originYardId ?? undefined,
|
||||||
|
destinationYardId ?? undefined,
|
||||||
|
),
|
||||||
|
({ originYardId, destinationYardId }) => [
|
||||||
|
...QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
||||||
|
"bookable",
|
||||||
|
originYardId ?? "",
|
||||||
|
destinationYardId ?? "",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
availableDays: endpoint<
|
||||||
|
{ originYardId?: string | null; destinationYardId?: string | null },
|
||||||
|
string[]
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"available-days",
|
||||||
|
({ originYardId, destinationYardId }) =>
|
||||||
|
trainSchedulingService.getAvailableDays(
|
||||||
|
originYardId ?? undefined,
|
||||||
|
destinationYardId ?? undefined,
|
||||||
|
),
|
||||||
|
({ originYardId, destinationYardId }) => [
|
||||||
|
...QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
||||||
|
"available-days",
|
||||||
|
originYardId ?? "",
|
||||||
|
destinationYardId ?? "",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
trainTrack: endpoint<{ id: string }, TrainTrackResponse>(
|
||||||
|
"train-scheduling",
|
||||||
|
"track",
|
||||||
|
({ id }) => trainSchedulingService.getTrack(id),
|
||||||
|
({ id }) => QUERY_KEYS.TRAIN_SCHEDULING.track(id),
|
||||||
|
),
|
||||||
|
|
||||||
|
unassignedBookings: endpoint<
|
||||||
|
{ scheduleId: string },
|
||||||
|
UnassignedBookingsResponse
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"unassigned-bookings",
|
||||||
|
({ scheduleId }) =>
|
||||||
|
trainSchedulingService.getUnassignedBookings(scheduleId),
|
||||||
|
({ scheduleId }) =>
|
||||||
|
QUERY_KEYS.TRAIN_SCHEDULING.unassignedBookings(scheduleId),
|
||||||
|
),
|
||||||
|
|
||||||
|
compositionRemovals: endpoint<
|
||||||
|
{ scheduleId: string },
|
||||||
|
CompositionRemovalEntry[]
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"composition-removals",
|
||||||
|
({ scheduleId }) =>
|
||||||
|
trainSchedulingService.getCompositionRemovals(scheduleId),
|
||||||
|
({ scheduleId }) =>
|
||||||
|
QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId),
|
||||||
|
),
|
||||||
|
|
||||||
|
// ── Mutations ──────────────────────────────────────────────────────────
|
||||||
|
runAllocation: endpoint<{ scheduleId: string }, WagonAllocationAttemptResult>(
|
||||||
|
"train-scheduling",
|
||||||
|
"run-allocation",
|
||||||
|
({ scheduleId }) => trainSchedulingService.runAllocation(scheduleId),
|
||||||
|
undefined,
|
||||||
|
() => [QUERY_KEYS.TRAIN_SCHEDULING.ROOT],
|
||||||
|
),
|
||||||
|
|
||||||
|
runBatch: endpoint<string, BatchBoardScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"run-batch",
|
||||||
|
(id) => trainSchedulingService.runBatch(id),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
setBookingWindow: endpoint<
|
||||||
|
{ id: string; status: "OPEN" | "CLOSED" },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"set-booking-window",
|
||||||
|
({ id, status }) => trainSchedulingService.setBookingWindow(id, status),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
markBookingPaid: endpoint<string, void>(
|
||||||
|
"train-scheduling",
|
||||||
|
"mark-booking-paid",
|
||||||
|
(bookingId) => trainSchedulingService.markBookingPaid(bookingId),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
expireBooking: endpoint<string, void>(
|
||||||
|
"train-scheduling",
|
||||||
|
"expire-booking",
|
||||||
|
(bookingId) => trainSchedulingService.expireBooking(bookingId),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
moveBookingSchedule: endpoint<
|
||||||
|
{ bookingId: string; trainScheduleId: string },
|
||||||
|
void
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"move-booking-schedule",
|
||||||
|
({ bookingId, trainScheduleId }) =>
|
||||||
|
trainSchedulingService.moveBookingSchedule(bookingId, trainScheduleId),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
createSchedule: endpoint<
|
||||||
|
{ freightType?: FreightType; payload: CreateTrainSchedulePayload },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"create-schedule",
|
||||||
|
({ freightType, payload }) =>
|
||||||
|
trainSchedulingService.createSchedule(payload, freightType),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
preview: endpoint<
|
||||||
|
{ freightType?: FreightType; payload: TrainSchedulePreviewPayload },
|
||||||
|
TrainSchedulePreviewResponse
|
||||||
|
>("train-scheduling", "preview", ({ freightType, payload }) =>
|
||||||
|
trainSchedulingService.preview(payload, freightType),
|
||||||
|
),
|
||||||
|
|
||||||
|
assignBookings: endpoint<
|
||||||
|
{ id: string; freightType?: FreightType; payload: AssignBookingsPayload },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"assign-bookings",
|
||||||
|
({ id, freightType, payload }) =>
|
||||||
|
trainSchedulingService.assignBookings(id, payload, freightType),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
assignUnassignedBooking: endpoint<
|
||||||
|
{ id: string; bookingId: string },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"assign-unassigned-booking",
|
||||||
|
({ id, bookingId }) =>
|
||||||
|
trainSchedulingService.assignUnassignedBooking(id, bookingId),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
unassignBooking: endpoint<
|
||||||
|
{ id: string; bookingId: string },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"unassign-booking",
|
||||||
|
({ id, bookingId }) =>
|
||||||
|
trainSchedulingService.unassignBooking(id, bookingId),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
pinWagons: endpoint<{ id: string; payload: PinWagonsPayload }, TrainScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"pin-wagons",
|
||||||
|
({ id, payload }) => trainSchedulingService.pinWagons(id, payload),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
finalizeSchedule: endpoint<string, TrainScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"finalize-schedule",
|
||||||
|
(id) => trainSchedulingService.finalizeSchedule(id),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
dispatchSchedule: endpoint<string, TrainScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"dispatch-schedule",
|
||||||
|
(id) => trainSchedulingService.dispatchSchedule(id),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
cancelSchedule: endpoint<
|
||||||
|
{ id: string; freightType?: FreightType },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"cancel-schedule",
|
||||||
|
({ id, freightType }) =>
|
||||||
|
trainSchedulingService.cancelSchedule(id, freightType ?? "CONTAINER"),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
recordCheckpoint: endpoint<
|
||||||
|
{ id: string; payload: RecordCheckpointPayload },
|
||||||
|
TrainTrackResponse
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"record-checkpoint",
|
||||||
|
({ id, payload }) => trainSchedulingService.recordCheckpoint(id, payload),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
arriveSchedule: endpoint<string, TrainScheduleDetail>(
|
||||||
|
"train-scheduling",
|
||||||
|
"arrive-schedule",
|
||||||
|
(id) => trainSchedulingService.arriveSchedule(id),
|
||||||
|
undefined,
|
||||||
|
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||||
|
),
|
||||||
|
|
||||||
|
removeWagonSlot: endpoint<
|
||||||
|
{ scheduleId: string; wagonId: string },
|
||||||
|
TrainScheduleDetail
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"remove-wagon-slot",
|
||||||
|
({ scheduleId, wagonId }) =>
|
||||||
|
trainSchedulingService.removeWagonSlot(scheduleId, wagonId),
|
||||||
|
undefined,
|
||||||
|
() => [QUERY_KEYS.TRAIN_SCHEDULING.ROOT],
|
||||||
|
),
|
||||||
|
|
||||||
|
updateContainerItem: endpoint<
|
||||||
|
{ scheduleId: string; itemId: string; containerNumber: string | null },
|
||||||
|
{ id: string; containerNumber: string | null }
|
||||||
|
>(
|
||||||
|
"train-scheduling",
|
||||||
|
"update-container-item",
|
||||||
|
({ scheduleId, itemId, containerNumber }) =>
|
||||||
|
trainSchedulingService.updateContainerItem(scheduleId, itemId, {
|
||||||
|
containerNumber,
|
||||||
|
}),
|
||||||
|
undefined,
|
||||||
|
() => [QUERY_KEYS.TRAIN_SCHEDULING.ROOT],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
warehouses: {
|
warehouses: {
|
||||||
// ── Warehouses ─────────────────────────────────────────────────────────
|
// ── Warehouses ─────────────────────────────────────────────────────────
|
||||||
list: endpoint<{ filter?: WarehouseFilter }, Warehouse[]>(
|
list: endpoint<{ filter?: WarehouseFilter }, Warehouse[]>(
|
||||||
@@ -685,6 +1072,388 @@ export const api = {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
routes: {
|
||||||
|
list: endpoint<void, RouteRecord[]>("routes", "list", () =>
|
||||||
|
routesService.getAll().then((r) => r.data),
|
||||||
|
),
|
||||||
|
|
||||||
|
yards: endpoint<void, YardRef[]>(
|
||||||
|
"routes",
|
||||||
|
"yards",
|
||||||
|
() => routesService.getYards().then((r) => r.data.data),
|
||||||
|
() => ["routes", "yards"],
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<SaveRoutePayload, RouteRecord>(
|
||||||
|
"routes",
|
||||||
|
"create",
|
||||||
|
(payload) => routesService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["routes"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<{ id: string; data: Partial<SaveRoutePayload> }, RouteRecord>(
|
||||||
|
"routes",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => routesService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["routes"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
deactivate: endpoint<string, void>(
|
||||||
|
"routes",
|
||||||
|
"deactivate",
|
||||||
|
(id) => routesService.deactivate(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["routes"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
stations: {
|
||||||
|
list: endpoint<void, YardOption[]>(
|
||||||
|
"train-scheduling",
|
||||||
|
"stations",
|
||||||
|
() => trainSchedulingService.getStations(),
|
||||||
|
() => QUERY_KEYS.TRAIN_SCHEDULING.stations(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
containers: {
|
||||||
|
list: endpoint<void, Container[]>("containers", "list", () =>
|
||||||
|
containerService.getAll().then((r) => r.data),
|
||||||
|
),
|
||||||
|
|
||||||
|
listByWagon: endpoint<{ wagonId: string }, Container[]>(
|
||||||
|
"containers",
|
||||||
|
"listByWagon",
|
||||||
|
({ wagonId }) => containerService.getByWagon(wagonId).then((r) => r.data),
|
||||||
|
({ wagonId }) => ["containers", "wagon", wagonId],
|
||||||
|
),
|
||||||
|
|
||||||
|
getById: endpoint<{ id: string }, Container>(
|
||||||
|
"containers",
|
||||||
|
"getById",
|
||||||
|
({ id }) => containerService.getById(id).then((r) => r.data),
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<Partial<Container>, Container>(
|
||||||
|
"containers",
|
||||||
|
"create",
|
||||||
|
(payload) => containerService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["containers"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<{ id: string; data: Partial<Container> }, Container>(
|
||||||
|
"containers",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => containerService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["containers"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
remove: endpoint<string, void>(
|
||||||
|
"containers",
|
||||||
|
"remove",
|
||||||
|
(id) => containerService.delete(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["containers"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
assignToWagon: endpoint<
|
||||||
|
{ containerId: string; wagonId: string; position?: number },
|
||||||
|
Container
|
||||||
|
>(
|
||||||
|
"containers",
|
||||||
|
"assignToWagon",
|
||||||
|
({ containerId, wagonId, position }) =>
|
||||||
|
containerService
|
||||||
|
.assignToWagon(containerId, wagonId, position)
|
||||||
|
.then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["containers"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
unassign: endpoint<string, void>(
|
||||||
|
"containers",
|
||||||
|
"unassign",
|
||||||
|
(containerId) =>
|
||||||
|
containerService.unassign(containerId).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["containers"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
containerTypes: {
|
||||||
|
list: endpoint<void, unknown[]>("container-types", "list", () =>
|
||||||
|
containerTypesService.getContainerTypes(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
wagons: {
|
||||||
|
list: endpoint<{ filters?: WagonListFilters }, Wagon[]>(
|
||||||
|
"wagons",
|
||||||
|
"list",
|
||||||
|
({ filters }) => wagonService.getAll(filters ?? {}).then((r) => r.data),
|
||||||
|
({ filters }) => ["wagons", "list", filters ?? {}],
|
||||||
|
),
|
||||||
|
|
||||||
|
listByTrain: endpoint<{ trainId: string }, Wagon[]>(
|
||||||
|
"wagons",
|
||||||
|
"listByTrain",
|
||||||
|
({ trainId }) => wagonService.getByTrain(trainId).then((r) => r.data),
|
||||||
|
({ trainId }) => ["wagons", "train", trainId],
|
||||||
|
),
|
||||||
|
|
||||||
|
getById: endpoint<{ id: string }, Wagon>(
|
||||||
|
"wagons",
|
||||||
|
"getById",
|
||||||
|
({ id }) => wagonService.getById(id).then((r) => r.data),
|
||||||
|
),
|
||||||
|
|
||||||
|
assignToTrain: endpoint<
|
||||||
|
{ wagonId: string; trainId: string; sequenceNumber?: number },
|
||||||
|
Wagon
|
||||||
|
>(
|
||||||
|
"wagons",
|
||||||
|
"assignToTrain",
|
||||||
|
({ wagonId, trainId, sequenceNumber }) =>
|
||||||
|
wagonService
|
||||||
|
.assignToTrain(wagonId, trainId, sequenceNumber)
|
||||||
|
.then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
unassign: endpoint<string, void>(
|
||||||
|
"wagons",
|
||||||
|
"unassign",
|
||||||
|
(wagonId) => wagonService.unassign(wagonId).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
reorder: endpoint<{ trainId: string; wagonIds: string[] }, Wagon[]>(
|
||||||
|
"wagons",
|
||||||
|
"reorder",
|
||||||
|
({ trainId, wagonIds }) =>
|
||||||
|
wagonService.reorder(trainId, wagonIds).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<Partial<Wagon>, Wagon>(
|
||||||
|
"wagons",
|
||||||
|
"create",
|
||||||
|
(payload) => wagonService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<{ id: string; data: Partial<Wagon> }, Wagon>(
|
||||||
|
"wagons",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => wagonService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
remove: endpoint<string, void>(
|
||||||
|
"wagons",
|
||||||
|
"remove",
|
||||||
|
(id) => wagonService.delete(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["wagons"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
trains: {
|
||||||
|
list: endpoint<void, Train[]>(
|
||||||
|
"trains",
|
||||||
|
"list",
|
||||||
|
() => trainService.getAll().then((r) => r.data),
|
||||||
|
() => ["trains", "list"],
|
||||||
|
),
|
||||||
|
|
||||||
|
getById: endpoint<{ id: string }, Train>(
|
||||||
|
"trains",
|
||||||
|
"getById",
|
||||||
|
({ id }) => trainService.getById(id).then((r) => r.data),
|
||||||
|
({ id }) => ["trains", "detail", id],
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<Partial<Train>, Train>(
|
||||||
|
"trains",
|
||||||
|
"create",
|
||||||
|
(payload) => trainService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["trains"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<{ id: string; data: Partial<Train> }, Train>(
|
||||||
|
"trains",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => trainService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["trains"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
remove: endpoint<string, void>(
|
||||||
|
"trains",
|
||||||
|
"remove",
|
||||||
|
(id) => trainService.delete(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["trains"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
locomotives: {
|
||||||
|
list: endpoint<void, Locomotive[]>(
|
||||||
|
"locomotives",
|
||||||
|
"list",
|
||||||
|
() => locomotivesService.getAll().then((r) => r.data),
|
||||||
|
() => ["locomotives"],
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<Partial<SaveLocomotivePayload>, Locomotive>(
|
||||||
|
"locomotives",
|
||||||
|
"create",
|
||||||
|
(payload) => locomotivesService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["locomotives"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<
|
||||||
|
{ id: string; data: Partial<SaveLocomotivePayload> },
|
||||||
|
Locomotive
|
||||||
|
>(
|
||||||
|
"locomotives",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => locomotivesService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["locomotives"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
decommission: endpoint<string, void>(
|
||||||
|
"locomotives",
|
||||||
|
"decommission",
|
||||||
|
(id) => locomotivesService.decommission(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["locomotives"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
cargoTypes: {
|
||||||
|
list: endpoint<void, unknown[]>("cargo-types", "list", () =>
|
||||||
|
cargoTypesService.getCargoTypes(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
payments: {
|
||||||
|
list: endpoint<{ filter?: PaymentListFilter }, PaginatedPayments>(
|
||||||
|
"payments",
|
||||||
|
"list",
|
||||||
|
({ filter }) => paymentsService.list(filter),
|
||||||
|
({ filter }) => ["payments", "list", filter ?? {}],
|
||||||
|
),
|
||||||
|
|
||||||
|
summary: endpoint<void, PaymentSummary>(
|
||||||
|
"payments",
|
||||||
|
"summary",
|
||||||
|
() => paymentsService.getSummary(),
|
||||||
|
() => ["payments", "summary"],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
signatures: {
|
||||||
|
mySignature: endpoint<void, SavedSignature | null>(
|
||||||
|
"me",
|
||||||
|
"signature",
|
||||||
|
() => signaturesService.getMySignature(),
|
||||||
|
() => ["me", "signature"],
|
||||||
|
),
|
||||||
|
|
||||||
|
save: endpoint<SaveSignaturePayload, SavedSignature | null>(
|
||||||
|
"me",
|
||||||
|
"save-signature",
|
||||||
|
(payload) => signaturesService.saveMySignature(payload),
|
||||||
|
undefined,
|
||||||
|
() => [["me", "signature"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
fleet: {
|
||||||
|
list: endpoint<
|
||||||
|
{ slug: FleetResourceSlug; filters?: FleetListFilters },
|
||||||
|
FleetRecord[]
|
||||||
|
>(
|
||||||
|
"fleet",
|
||||||
|
"list",
|
||||||
|
({ slug, filters }) => fleetService.list(slug, filters),
|
||||||
|
({ slug, filters }) => [...QUERY_KEYS.FLEET.list(slug), filters ?? {}],
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<
|
||||||
|
{ slug: FleetResourceSlug; data: Record<string, unknown> },
|
||||||
|
unknown
|
||||||
|
>(
|
||||||
|
"fleet",
|
||||||
|
"create",
|
||||||
|
({ slug, data }) => fleetService.create(slug, data),
|
||||||
|
undefined,
|
||||||
|
({ slug }) => [QUERY_KEYS.FLEET.list(slug)],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<
|
||||||
|
{ slug: FleetResourceSlug; id: string; data: Record<string, unknown> },
|
||||||
|
unknown
|
||||||
|
>(
|
||||||
|
"fleet",
|
||||||
|
"update",
|
||||||
|
({ slug, id, data }) => fleetService.update(slug, id, data),
|
||||||
|
undefined,
|
||||||
|
({ slug }) => [QUERY_KEYS.FLEET.list(slug)],
|
||||||
|
),
|
||||||
|
|
||||||
|
remove: endpoint<{ slug: FleetResourceSlug; id: string }, unknown>(
|
||||||
|
"fleet",
|
||||||
|
"remove",
|
||||||
|
({ slug, id }) => fleetService.remove(slug, id),
|
||||||
|
undefined,
|
||||||
|
({ slug }) => [QUERY_KEYS.FLEET.list(slug)],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
wagonTypes: {
|
||||||
|
list: endpoint<void, WagonType[]>("wagon-types", "list", () =>
|
||||||
|
wagonTypesService.getWagonTypes(),
|
||||||
|
),
|
||||||
|
|
||||||
|
create: endpoint<Partial<WagonType>, WagonType>(
|
||||||
|
"wagon-types",
|
||||||
|
"create",
|
||||||
|
(payload) => wagonTypesService.create(payload).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagon-types"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
update: endpoint<{ id: string; data: Partial<WagonType> }, WagonType>(
|
||||||
|
"wagon-types",
|
||||||
|
"update",
|
||||||
|
({ id, data }) => wagonTypesService.update(id, data).then((r) => r.data),
|
||||||
|
undefined,
|
||||||
|
() => [["wagon-types"]],
|
||||||
|
),
|
||||||
|
|
||||||
|
remove: endpoint<string, void>(
|
||||||
|
"wagon-types",
|
||||||
|
"remove",
|
||||||
|
(id) => wagonTypesService.delete(id).then(() => undefined),
|
||||||
|
undefined,
|
||||||
|
() => [["wagon-types"]],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
cargoes: {
|
cargoes: {
|
||||||
list: endpoint<void, Cargo[]>("cargoes", "list", () =>
|
list: endpoint<void, Cargo[]>("cargoes", "list", () =>
|
||||||
cargoService.getAll().then((r) => r.data),
|
cargoService.getAll().then((r) => r.data),
|
||||||
@@ -778,46 +1547,68 @@ export const api = {
|
|||||||
"file-upload-settings",
|
"file-upload-settings",
|
||||||
"create",
|
"create",
|
||||||
(payload) => fileUploadSettingsService.create(payload),
|
(payload) => fileUploadSettingsService.create(payload),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
update: endpoint<
|
update: endpoint<
|
||||||
{ id: string; dto: UpdateFileUploadSettingDto },
|
{ id: string; dto: UpdateFileUploadSettingDto },
|
||||||
FileUploadSetting
|
FileUploadSetting
|
||||||
>("file-upload-settings", "update", ({ id, dto }) =>
|
>(
|
||||||
fileUploadSettingsService.update(id, dto),
|
"file-upload-settings",
|
||||||
|
"update",
|
||||||
|
({ id, dto }) => fileUploadSettingsService.update(id, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
remove: endpoint<{ id: string }, void>(
|
remove: endpoint<{ id: string }, void>(
|
||||||
"file-upload-settings",
|
"file-upload-settings",
|
||||||
"remove",
|
"remove",
|
||||||
({ id }) => fileUploadSettingsService.remove(id),
|
({ id }) => fileUploadSettingsService.remove(id),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
replaceFields: endpoint<
|
replaceFields: endpoint<
|
||||||
{ id: string; fields: CreateFileUploadFieldDto[] },
|
{ id: string; fields: CreateFileUploadFieldDto[] },
|
||||||
FileUploadField[]
|
FileUploadField[]
|
||||||
>("file-upload-settings", "replaceFields", ({ id, fields }) =>
|
>(
|
||||||
fileUploadSettingsService.replaceFields(id, fields),
|
"file-upload-settings",
|
||||||
|
"replaceFields",
|
||||||
|
({ id, fields }) => fileUploadSettingsService.replaceFields(id, fields),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
addField: endpoint<
|
addField: endpoint<
|
||||||
{ settingId: string; dto: CreateFileUploadFieldDto },
|
{ settingId: string; dto: CreateFileUploadFieldDto },
|
||||||
FileUploadField
|
FileUploadField
|
||||||
>("file-upload-settings", "addField", ({ settingId, dto }) =>
|
>(
|
||||||
fileUploadSettingsService.addField(settingId, dto),
|
"file-upload-settings",
|
||||||
|
"addField",
|
||||||
|
({ settingId, dto }) => fileUploadSettingsService.addField(settingId, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
updateField: endpoint<
|
updateField: endpoint<
|
||||||
{ fieldId: string; dto: UpdateFileUploadFieldDto },
|
{ fieldId: string; dto: UpdateFileUploadFieldDto },
|
||||||
FileUploadField
|
FileUploadField
|
||||||
>("file-upload-settings", "updateField", ({ fieldId, dto }) =>
|
>(
|
||||||
fileUploadSettingsService.updateField(fieldId, dto),
|
"file-upload-settings",
|
||||||
|
"updateField",
|
||||||
|
({ fieldId, dto }) => fileUploadSettingsService.updateField(fieldId, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
removeField: endpoint<{ fieldId: string }, void>(
|
removeField: endpoint<{ fieldId: string }, void>(
|
||||||
"file-upload-settings",
|
"file-upload-settings",
|
||||||
"removeField",
|
"removeField",
|
||||||
({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
|
({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
|
||||||
|
undefined,
|
||||||
|
() => [["file-upload-settings"]],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -844,46 +1635,68 @@ export const api = {
|
|||||||
"dropdown-settings",
|
"dropdown-settings",
|
||||||
"create",
|
"create",
|
||||||
(payload) => dropdownSettingsService.create(payload),
|
(payload) => dropdownSettingsService.create(payload),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
update: endpoint<
|
update: endpoint<
|
||||||
{ id: string; dto: UpdateDropdownSettingDto },
|
{ id: string; dto: UpdateDropdownSettingDto },
|
||||||
DropdownSetting
|
DropdownSetting
|
||||||
>("dropdown-settings", "update", ({ id, dto }) =>
|
>(
|
||||||
dropdownSettingsService.update(id, dto),
|
"dropdown-settings",
|
||||||
|
"update",
|
||||||
|
({ id, dto }) => dropdownSettingsService.update(id, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
remove: endpoint<{ id: string }, void>(
|
remove: endpoint<{ id: string }, void>(
|
||||||
"dropdown-settings",
|
"dropdown-settings",
|
||||||
"remove",
|
"remove",
|
||||||
({ id }) => dropdownSettingsService.remove(id),
|
({ id }) => dropdownSettingsService.remove(id),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
replaceOptions: endpoint<
|
replaceOptions: endpoint<
|
||||||
{ id: string; options: CreateDropdownOptionDto[] },
|
{ id: string; options: CreateDropdownOptionDto[] },
|
||||||
DropdownOption[]
|
DropdownOption[]
|
||||||
>("dropdown-settings", "replaceOptions", ({ id, options }) =>
|
>(
|
||||||
dropdownSettingsService.replaceOptions(id, options),
|
"dropdown-settings",
|
||||||
|
"replaceOptions",
|
||||||
|
({ id, options }) => dropdownSettingsService.replaceOptions(id, options),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
addOption: endpoint<
|
addOption: endpoint<
|
||||||
{ id: string; dto: CreateDropdownOptionDto },
|
{ id: string; dto: CreateDropdownOptionDto },
|
||||||
DropdownOption
|
DropdownOption
|
||||||
>("dropdown-settings", "addOption", ({ id, dto }) =>
|
>(
|
||||||
dropdownSettingsService.addOption(id, dto),
|
"dropdown-settings",
|
||||||
|
"addOption",
|
||||||
|
({ id, dto }) => dropdownSettingsService.addOption(id, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
updateOption: endpoint<
|
updateOption: endpoint<
|
||||||
{ optionId: string; dto: UpdateDropdownOptionDto },
|
{ optionId: string; dto: UpdateDropdownOptionDto },
|
||||||
DropdownOption
|
DropdownOption
|
||||||
>("dropdown-settings", "updateOption", ({ optionId, dto }) =>
|
>(
|
||||||
dropdownSettingsService.updateOption(optionId, dto),
|
"dropdown-settings",
|
||||||
|
"updateOption",
|
||||||
|
({ optionId, dto }) => dropdownSettingsService.updateOption(optionId, dto),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
|
|
||||||
removeOption: endpoint<{ optionId: string }, void>(
|
removeOption: endpoint<{ optionId: string }, void>(
|
||||||
"dropdown-settings",
|
"dropdown-settings",
|
||||||
"removeOption",
|
"removeOption",
|
||||||
({ optionId }) => dropdownSettingsService.removeOption(optionId),
|
({ optionId }) => dropdownSettingsService.removeOption(optionId),
|
||||||
|
undefined,
|
||||||
|
() => [["dropdown-settings"]],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
|
|||||||
Reference in New Issue
Block a user