mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
refactor(bookings): Streamline new booking process, integrate useAuth for customer data, and simplify API payloads
This commit is contained in:
@@ -13,7 +13,6 @@ import {
|
||||
Truck,
|
||||
} from "lucide-react";
|
||||
|
||||
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||
import DeleteBookingDialog from "./DeleteBookingDialog";
|
||||
import { getMyBookings } from "@/lib/currentCustomer";
|
||||
import { deleteBooking, type Booking, type BookingStatus } from "./bookings.mock";
|
||||
@@ -183,8 +182,6 @@ export default function MyBookings() {
|
||||
return (
|
||||
<div className="min-h-screen p-6">
|
||||
<div className="space-y-6">
|
||||
<Breadcrumbs items={[{ label: "My Bookings" }]} />
|
||||
|
||||
{/* Header Section Card */}
|
||||
<Card className="p-6 flex-row justify-between">
|
||||
<div>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { CheckCircle2, ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { Button } from "@edr/ui-common";
|
||||
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||
import { getCurrentCustomer } from "@/lib/currentCustomer";
|
||||
import { api } from "@/services/api";
|
||||
import type { CreateBookingPayload } from "@/services/bookings.service";
|
||||
import {
|
||||
@@ -30,6 +29,7 @@ import {
|
||||
Step7Documents,
|
||||
Step8Review,
|
||||
} from "./new-booking-form/steps";
|
||||
import useAuth from "@/hooks/useAuth";
|
||||
|
||||
export default function NewBookingPage() {
|
||||
const navigate = useNavigate();
|
||||
@@ -37,6 +37,7 @@ export default function NewBookingPage() {
|
||||
const [step, setStep] = useState(1);
|
||||
const [renewalValidating, setRenewalValidating] = useState(false);
|
||||
const [renewalValid, setRenewalValid] = useState<boolean | null>(null);
|
||||
const { customer } = useAuth();
|
||||
const createMutation = useMutation({
|
||||
mutationFn: (payload: CreateBookingPayload) =>
|
||||
api.bookings.create.call(payload),
|
||||
@@ -129,7 +130,6 @@ export default function NewBookingPage() {
|
||||
return;
|
||||
}
|
||||
|
||||
const me = getCurrentCustomer();
|
||||
const reference = data.previousContractRef;
|
||||
|
||||
const totalWeight =
|
||||
@@ -142,7 +142,7 @@ export default function NewBookingPage() {
|
||||
|
||||
const apiPayload = {
|
||||
reference,
|
||||
customerId: String(me.id),
|
||||
customerId: customer!.id,
|
||||
scheduledDate: new Date().toISOString().slice(0, 10),
|
||||
totalAmount: 0,
|
||||
contractType:
|
||||
@@ -194,7 +194,7 @@ export default function NewBookingPage() {
|
||||
createMutation.mutate(apiPayload);
|
||||
});
|
||||
|
||||
if (createMutation.isSuccess && createMutation.data) {
|
||||
if (createMutation.isSuccess) {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center p-6">
|
||||
<div className="w-full max-w-sm rounded-2xl border border-border bg-card p-10 text-center shadow-sm">
|
||||
@@ -207,7 +207,7 @@ export default function NewBookingPage() {
|
||||
notified once approved.
|
||||
</p>
|
||||
<p className="mt-4 font-mono text-sm font-semibold text-primary">
|
||||
{createMutation.data.reference}
|
||||
{createMutation.data?.reference}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -161,7 +161,7 @@ export const bookingFormSchema = z
|
||||
destinationYard: z.string(),
|
||||
cargoType: z.enum(["container", "bulk"], "Select a cargo type."),
|
||||
cargoWeight: z.string(),
|
||||
freightType: z.enum(["bulk", "break_bulk"]),
|
||||
freightType: z.enum(["bulk", "break_bulk"]).optional(),
|
||||
bulkCommodity: z.string(),
|
||||
bulkCommodityOther: z.string(),
|
||||
breakBulkType: z.string(),
|
||||
|
||||
@@ -2,7 +2,13 @@ import { Controller, type UseFormReturn } from "react-hook-form";
|
||||
import { Flame, MapPin, Snowflake } from "lucide-react";
|
||||
import { Field, SelectItem, Separator, Switch } from "@edr/ui-common";
|
||||
import { type BookingFormValues, getRouteDirection, STATIONS } from "./schema";
|
||||
import { SelectField, SelectOptions, StepHeader, StepLabel } from "./shared";
|
||||
import {
|
||||
AlertBox,
|
||||
SelectField,
|
||||
SelectOptions,
|
||||
StepHeader,
|
||||
StepLabel,
|
||||
} from "./shared";
|
||||
import { useDropdownSettingByCode } from "@/hooks/useDropdownSettings";
|
||||
import { DropdownOption } from "@/types/dropdownSettings";
|
||||
|
||||
@@ -145,12 +151,10 @@ export function Step4Route({ form }: { form: BookingForm }) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function getStationOptions(options?: DropdownOption[]): DropdownOption[] {
|
||||
return [...(options ?? [])].sort((a, b) => a.order - b.order);
|
||||
}
|
||||
|
||||
|
||||
function StationSelectOptions({
|
||||
options,
|
||||
excludeValue,
|
||||
@@ -193,4 +197,4 @@ function StationSelectOptions({
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,9 @@ export function Step5CargoDetails({
|
||||
selected={cargoType === "container"}
|
||||
onClick={() => {
|
||||
field.onChange("container");
|
||||
form.setValue("freightType", "", { shouldDirty: true });
|
||||
form.setValue("freightType", undefined, {
|
||||
shouldDirty: true,
|
||||
});
|
||||
form.setValue("cargoWeight", "", { shouldDirty: true });
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,31 +1,23 @@
|
||||
import type { Freight, PaginatedResponse } from "@edr/types";
|
||||
import { client as api } from "@/utils/api";
|
||||
|
||||
import { client } from "../utils/api";
|
||||
|
||||
export type CreateBookingPayload = Freight.CreateBookingDto;
|
||||
|
||||
export const bookingsService = {
|
||||
list: async (): Promise<PaginatedResponse<Freight.IBooking>> => {
|
||||
const { data } = await api.get("/bookings");
|
||||
const { data } = await client.get("/bookings");
|
||||
return data.data;
|
||||
},
|
||||
get: async (id: string): Promise<Freight.IBooking> => {
|
||||
const { data } = await api.get(`/bookings/${id}`);
|
||||
const { data } = await client.get(`/bookings/${id}`);
|
||||
return data.data;
|
||||
},
|
||||
create: async (payload: CreateBookingPayload): Promise<Freight.IBooking> => {
|
||||
const fd = new FormData();
|
||||
for (const [key, value] of Object.entries(payload)) {
|
||||
if (value === undefined || value === null) continue;
|
||||
if (Array.isArray(value) || typeof value === "object") {
|
||||
fd.append(key, JSON.stringify(value));
|
||||
} else {
|
||||
fd.append(key, String(value));
|
||||
}
|
||||
}
|
||||
const { data } = await api.post("/api/bookings", fd);
|
||||
const { data } = await client.post("/api/bookings", payload);
|
||||
return data.data;
|
||||
},
|
||||
remove: async (id: string): Promise<void> => {
|
||||
await api.delete(`/bookings/${id}`);
|
||||
await client.delete(`/bookings/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user