Merge branch 'dev' into freight/feat/fixes-v1

This commit is contained in:
Nathnael
2026-07-10 08:54:34 +00:00
139 changed files with 8644 additions and 1557 deletions

View File

@@ -44,7 +44,8 @@ import {
} from "@/types/rule-engine";
import type {
AssignBookingsPayload,
BatchBoardSchedule,
BatchBoardFilters,
BatchBoardListResponse,
BatchBoardScheduleDetail,
BookableSchedule,
BookingWindow,
@@ -223,11 +224,14 @@ export const api = {
() => QUERY_KEYS.TRAIN_SCHEDULING.schedules(),
),
batchBoard: endpoint<void, BatchBoardSchedule[]>(
batchBoard: endpoint<
{ filters?: BatchBoardFilters },
BatchBoardListResponse
>(
"train-scheduling",
"batch-board",
() => trainSchedulingService.getBatchBoard(),
() => QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(),
({ filters }) => trainSchedulingService.getBatchBoard(filters),
({ filters }) => QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(filters),
),
allBookingWindows: endpoint<void, StaffBookingWindow[]>(

View File

@@ -21,6 +21,19 @@ export interface BookingListFilter {
bookingType?: string;
tradeDirection?: string;
paymentCurrency?: string;
paymentStatus?: string;
/** ISO date-time — bookings created on/after. */
createdFrom?: string;
/** ISO date-time — bookings created on/before (pass end-of-day for inclusive). */
createdTo?: string;
/** ISO date-time — bookings scheduled on/after. */
scheduledFrom?: string;
/** ISO date-time — bookings scheduled on/before (pass end-of-day for inclusive). */
scheduledTo?: string;
originYardId?: string;
destinationYardId?: string;
/** "true" = government bookings only, "false" = private only. */
isGovernment?: "true" | "false";
page?: number;
pageSize?: number;
sortBy?: string;
@@ -130,6 +143,14 @@ export const bookingsService = {
if (filter.bookingType) params.bookingType = filter.bookingType;
if (filter.tradeDirection) params.tradeDirection = filter.tradeDirection;
if (filter.paymentCurrency) params.paymentCurrency = filter.paymentCurrency;
if (filter.paymentStatus) params.paymentStatus = filter.paymentStatus;
if (filter.createdFrom) params.createdFrom = filter.createdFrom;
if (filter.createdTo) params.createdTo = filter.createdTo;
if (filter.scheduledFrom) params.scheduledFrom = filter.scheduledFrom;
if (filter.scheduledTo) params.scheduledTo = filter.scheduledTo;
if (filter.originYardId) params.originYardId = filter.originYardId;
if (filter.destinationYardId) params.destinationYardId = filter.destinationYardId;
if (filter.isGovernment) params.isGovernment = filter.isGovernment;
}
const response = await client.get<BookingListSummary>(B.LIST_SUMMARY, {
params,
@@ -154,6 +175,14 @@ export const bookingsService = {
if (filter.bookingType) params.bookingType = filter.bookingType;
if (filter.tradeDirection) params.tradeDirection = filter.tradeDirection;
if (filter.paymentCurrency) params.paymentCurrency = filter.paymentCurrency;
if (filter.paymentStatus) params.paymentStatus = filter.paymentStatus;
if (filter.createdFrom) params.createdFrom = filter.createdFrom;
if (filter.createdTo) params.createdTo = filter.createdTo;
if (filter.scheduledFrom) params.scheduledFrom = filter.scheduledFrom;
if (filter.scheduledTo) params.scheduledTo = filter.scheduledTo;
if (filter.originYardId) params.originYardId = filter.originYardId;
if (filter.destinationYardId) params.destinationYardId = filter.destinationYardId;
if (filter.isGovernment) params.isGovernment = filter.isGovernment;
}
const response = await client.get<PaginatedBookings>(B.BASE, {
params,

View File

@@ -0,0 +1,112 @@
import { api as client } from "../auth/http";
const BASE = "/contract-templates";
export interface ContractTemplateArticle {
id: string;
title: string;
body: string;
order: number;
}
export interface ContractTemplate {
id: string;
code:
| "IMPORT_BULK"
| "EXPORT_BULK"
| "INTERCITY_BULK"
| "IMPORT_CONTAINER"
| "EXPORT_CONTAINER"
| "INTERCITY_CONTAINER";
name: string;
description?: string | null;
documentTitle: string;
whereasClauses: string[];
articles: ContractTemplateArticle[];
isActive: boolean;
createdAt: string;
updatedAt: string;
}
export interface UpdateContractTemplatePayload {
name?: string;
description?: string;
documentTitle?: string;
whereasClauses?: string[];
isActive?: boolean;
}
export interface ArticlePayload {
title: string;
body: string;
position?: number;
}
export const contractTemplatesService = {
async list(): Promise<ContractTemplate[]> {
const { data } = await client.get<ContractTemplate[]>(BASE);
return data;
},
async getByCode(code: string): Promise<ContractTemplate> {
const { data } = await client.get<ContractTemplate>(`${BASE}/${code}`);
return data;
},
async update(
code: string,
payload: UpdateContractTemplatePayload,
): Promise<ContractTemplate> {
const { data } = await client.patch<ContractTemplate>(
`${BASE}/${code}`,
payload,
);
return data;
},
async preview(code: string): Promise<{ html: string }> {
const { data } = await client.post<{ html: string }>(
`${BASE}/${code}/preview`,
{},
);
return data;
},
async addArticle(code: string, payload: ArticlePayload): Promise<ContractTemplate> {
const { data } = await client.post<ContractTemplate>(
`${BASE}/${code}/articles`,
payload,
);
return data;
},
async updateArticle(
code: string,
articleId: string,
payload: Partial<ArticlePayload>,
): Promise<ContractTemplate> {
const { data } = await client.patch<ContractTemplate>(
`${BASE}/${code}/articles/${articleId}`,
payload,
);
return data;
},
async removeArticle(code: string, articleId: string): Promise<ContractTemplate> {
const { data } = await client.delete<ContractTemplate>(
`${BASE}/${code}/articles/${articleId}`,
);
return data;
},
async replaceArticles(
code: string,
articles: Array<{ id?: string; title: string; body: string }>,
): Promise<ContractTemplate> {
const { data } = await client.put<ContractTemplate>(
`${BASE}/${code}/articles`,
{ articles },
);
return data;
},
};

View File

@@ -3,7 +3,8 @@ import { api as client } from "../auth/http";
import { unwrap } from "@/utils/endpoint";
import { URL_CONSTANTS } from "@/constants/URLS";
import type {
BatchBoardSchedule,
BatchBoardFilters,
BatchBoardListResponse,
BatchBoardScheduleDetail,
BookableSchedule,
BookingWindow,
@@ -100,9 +101,25 @@ export const trainSchedulingService = {
return unwrap(response.data);
},
getBatchBoard: async (): Promise<BatchBoardSchedule[]> => {
const response = await client.get<BatchBoardSchedule[]>(
getBatchBoard: async (
filters: BatchBoardFilters = {},
): Promise<BatchBoardListResponse> => {
const params: Record<string, string | number> = {};
if (filters.page) params.page = filters.page;
if (filters.pageSize) params.pageSize = filters.pageSize;
if (filters.statuses?.length) params.statuses = filters.statuses.join(",");
if (filters.bookingWindowStatus)
params.bookingWindowStatus = filters.bookingWindowStatus;
if (filters.search?.trim()) params.search = filters.search.trim();
if (filters.departureFrom) params.departureFrom = filters.departureFrom;
if (filters.departureTo) params.departureTo = filters.departureTo;
if (filters.createdFrom) params.createdFrom = filters.createdFrom;
if (filters.createdTo) params.createdTo = filters.createdTo;
if (filters.sortBy) params.sortBy = filters.sortBy;
if (filters.sortOrder) params.sortOrder = filters.sortOrder;
const response = await client.get<BatchBoardListResponse>(
URL_CONSTANTS.TRAIN_SCHEDULING.BATCH_BOARD,
{ params },
);
return unwrap(response.data);
},