Files
edr-platform/apps/edr-freight-web/portal/src/services/bookings.service.ts

155 lines
4.3 KiB
TypeScript

import type { Freight, PaginatedResponse } from "@edr/types";
import { URL_CONSTANTS } from "@/constants/URLS";
import { client } from "../utils/api";
const B = URL_CONSTANTS.BOOKINGS;
export type CreateBookingPayload = Freight.CreateBookingDto;
export interface ContractView {
bookingId: string;
reference: string;
status: string;
templateKey: string;
title: string;
html: string;
canSignCustomer: boolean;
canSignStaff: boolean;
hasContractDocument: boolean;
signatures: Array<{
role: string;
signerDisplayName: string;
signedAt: string;
signatureImageUrl?: string | null;
}>;
}
export interface PriceLineItem {
code: string;
description: string;
amount: number;
currency: string;
}
export interface GeneratePriceResponse {
bookingId: string;
totalAmount: number;
currency: string;
lineItems: PriceLineItem[];
warnings: string[];
}
export interface SignContractPayload {
role: "CUSTOMER" | "STAFF";
signatureImageBase64: string;
signerDisplayName: string;
consentText?: string;
}
export interface BookingListFilter {
status?: string;
page?: number;
pageSize?: number;
sortBy?: string;
sortOrder?: "ASC" | "DESC";
}
export const bookingsService = {
list: async (
filter: BookingListFilter | void = {},
): Promise<PaginatedResponse<Freight.IBooking>> => {
const { data } = await client.get("/api/bookings", { params: filter });
return data.data;
},
get: async (id: string): Promise<Freight.IBooking> => {
const { data } = await client.get(`/api/bookings/${id}`);
return data.data;
},
create: async (payload: CreateBookingPayload): Promise<Freight.IBooking> => {
const { data } = await client.post("/api/bookings", payload);
return data.data.booking;
},
getReferenceData: async (): Promise<Freight.BookingReferenceData> => {
const { data } = await client.get("/api/bookings/reference-data");
return data.data;
},
update: async (
id: string,
payload: Partial<CreateBookingPayload>,
): Promise<{ booking: Freight.IBooking; warnings: string[] }> => {
const { data } = await client.patch(`/api/bookings/${id}`, payload);
return data.data;
},
remove: async (id: string): Promise<void> => {
await client.delete(`/api/bookings/${id}`);
},
cancel: async (id: string, reason: string): Promise<Freight.IBooking> => {
const { data } = await client.post(`/api/bookings/${id}/cancel`, { reason });
return data.data;
},
generatePrice: async (id: string): Promise<GeneratePriceResponse> => {
const { data } = await client.post(`/api/bookings/${id}/generate-price`);
return data.data;
},
submit: async (id: string): Promise<Freight.IBooking> => {
const { data } = await client.post(`/api/bookings/${id}/submit`);
return data.data;
},
uploadDocuments: async (
id: string,
files: Record<string, File | File[] | null>,
): Promise<Freight.IBooking> => {
const formData = new FormData();
for (const [key, fileOrFiles] of Object.entries(files)) {
if (!fileOrFiles) continue;
if (Array.isArray(fileOrFiles)) {
for (const f of fileOrFiles) formData.append(key, f);
} else {
formData.append(key, fileOrFiles);
}
}
const { data } = await client.post(
`/api/bookings/${id}/documents`,
formData,
{ headers: { "Content-Type": "multipart/form-data" } },
);
return data.data;
},
getContractView: async (id: string): Promise<ContractView> => {
const { data } = await client.get(B.CONTRACT_VIEW(id));
return data.data ?? data;
},
downloadContractDocument: async (id: string): Promise<Blob> => {
const { data } = await client.get(B.CONTRACT_DOCUMENT(id), {
responseType: "blob",
});
return data;
},
checkPayment: async (orderId: string): Promise<{ status: string }> => {
const { data } = await client.post(`/api/payments/bookings/check-payment/${orderId}`);
return data.data ?? data;
},
pay: async (id: string): Promise<{ redirectUrl: string }> => {
const { data } = await client.post(`/api/bookings/${id}/payment/pay`);
return data.data ?? data;
},
signContract: async (
id: string,
payload: SignContractPayload,
): Promise<Freight.IBooking> => {
const { data } = await client.post(B.CONTRACT_SIGN(id), payload);
return data.data ?? data;
},
};