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

174 lines
4.9 KiB
TypeScript

import { api as client } from "../auth/http";
import { unwrap } from "@/utils/endpoint";
import { URL_CONSTANTS } from "@/constants/URLS";
import type { BookingDetail } from "@/types/booking";
const B = URL_CONSTANTS.BOOKINGS;
export interface BookingListFilter {
status?: string;
// customerId?: string;
companyId?: string;
freightType?: string;
tradeDirection?: string;
paymentCurrency?: string;
page?: number;
pageSize?: number;
sortBy?: string;
sortOrder?: "ASC" | "DESC";
}
export interface PaginatedBookings {
items: BookingDetail[];
total: number;
}
export interface ApproveStepPayload {
id: string;
stepId: string;
requiredRole: string;
}
export interface RejectStepPayload {
id: string;
stepId: string;
reason: string;
}
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 SignContractPayload {
role: "CUSTOMER" | "STAFF";
signatureImageBase64: string;
signerDisplayName: string;
consentText?: string;
}
async function postBooking<T>(url: string, body?: unknown): Promise<T> {
const response = await client.post<T>(url, body ?? {});
return unwrap(response.data);
}
export const bookingsService = {
list: async (filter?: BookingListFilter): Promise<PaginatedBookings> => {
const response = await client.get<PaginatedBookings>(B.BASE, {
params: filter,
});
const data = unwrap(response.data);
return {
items: (data.items ?? []) as BookingDetail[],
total: data.total ?? 0,
};
},
getById: async (id: string): Promise<BookingDetail> => {
const response = await client.get<BookingDetail>(B.BY_ID(id));
return unwrap(response.data) as BookingDetail;
},
remove: async (id: string): Promise<void> => {
await client.delete(B.BY_ID(id));
},
staffAccept: (id: string) => postBooking<BookingDetail>(B.STAFF_ACCEPT(id)),
requestChanges: (id: string, note: string) =>
postBooking<BookingDetail>(B.STAFF_REQUEST_CHANGES(id), { note }),
staffReject: (id: string, reason: string) =>
postBooking<BookingDetail>(B.STAFF_REJECT(id), { reason }),
approveStep: ({ id, stepId, requiredRole }: ApproveStepPayload) =>
postBooking<BookingDetail>(B.APPROVE_STEP(id, stepId), { requiredRole }),
rejectStep: ({ id, stepId, reason }: RejectStepPayload) =>
postBooking<BookingDetail>(B.REJECT_STEP(id, stepId), { reason }),
generateContract: (id: string) =>
postBooking<BookingDetail>(B.CONTRACT_GENERATE(id)),
getContractView: async (id: string): Promise<ContractView> => {
const response = await client.get<ContractView>(B.CONTRACT_VIEW(id));
return unwrap(response.data) as ContractView;
},
downloadContract: async (id: string): Promise<Blob> => {
const response = await client.get(B.CONTRACT_DOWNLOAD(id), {
responseType: "blob",
});
return response.data as Blob;
},
downloadContractDocument: async (id: string): Promise<Blob> => {
const response = await client.get(B.CONTRACT_DOCUMENT(id), {
responseType: "blob",
});
return response.data as Blob;
},
signContract: (id: string, payload: SignContractPayload) =>
postBooking<BookingDetail>(B.CONTRACT_SIGN(id), payload),
getSummary: async (id: string): Promise<{ summary: string }> => {
const response = await client.get<{ summary: string }>(B.SUMMARY(id));
return unwrap(response.data);
},
customerSign: (id: string, payload: SignContractPayload) =>
postBooking<BookingDetail>(B.CUSTOMER_SIGN(id), {
...payload,
role: "CUSTOMER",
}),
marketingApprove: (id: string, payload: SignContractPayload) =>
postBooking<BookingDetail>(B.MARKETING_APPROVE(id), {
...payload,
role: "STAFF",
}),
generatePnr: (id: string) => postBooking<BookingDetail>(B.PAYMENT_PNR(id)),
submitPaymentProof: async (id: string, file: File): Promise<BookingDetail> => {
const form = new FormData();
form.append("file", file);
const response = await client.post<BookingDetail>(B.PAYMENT_PROOF(id), form, {
headers: { "Content-Type": "multipart/form-data" },
});
return unwrap(response.data) as BookingDetail;
},
verifyPayment: (id: string) =>
postBooking<BookingDetail>(B.PAYMENT_VERIFY(id)),
downloadPaymentRequestLetter: async (id: string): Promise<Blob> => {
const response = await client.get(B.PAYMENT_REQUEST_LETTER(id), {
responseType: "blob",
});
return response.data as Blob;
},
startTransit: (id: string) =>
postBooking<BookingDetail>(B.START_TRANSIT(id)),
complete: (id: string) => postBooking<BookingDetail>(B.COMPLETE(id)),
cancel: (id: string, reason: string) =>
postBooking<BookingDetail>(B.CANCEL(id), { reason }),
};