mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-01 19:03:12 +00:00
177 lines
5.8 KiB
TypeScript
177 lines
5.8 KiB
TypeScript
import { ASSIGNEE_FILTER_UNASSIGNED } from "@/domain/work-orders/types/work-order-list";
|
|
import type { WorkOrderAdvancedFilters } from "@/domain/work-orders/types/work-order-advanced-filters";
|
|
import type { WorkOrderBarFilters } from "@/domain/work-orders/types/work-order-list-filters";
|
|
import {
|
|
BOARD_DISPATCHER_UNASSIGNED,
|
|
DATE_RANGE_TO_PRESET,
|
|
DOC_STATUS_API,
|
|
LIFECYCLE_STATUS_API,
|
|
type WorkOrderBoardQueryParams,
|
|
type WorkOrderBoardSearchQueryParams,
|
|
} from "@/domain/work-orders/types/work-order-board";
|
|
import { mapWizardTypeToApi } from "@/domain/work-orders/mappers/work-order-board-mapper";
|
|
import { weekRange } from "@/domain/work-orders/utils/list-week-utils";
|
|
import type { CompletionDocFilter } from "@/domain/work-orders/types/work-order-advanced-filters";
|
|
import type { WizardWOStatus, WOType } from "@/domain/work-orders/types/work-order-wizard";
|
|
|
|
export const BOARD_SEARCH_MAX_PAGE_SIZE = 100;
|
|
|
|
function toBoardDispatcherId(id: string): string {
|
|
if (id === ASSIGNEE_FILTER_UNASSIGNED || id === BOARD_DISPATCHER_UNASSIGNED) {
|
|
return BOARD_DISPATCHER_UNASSIGNED;
|
|
}
|
|
return id;
|
|
}
|
|
|
|
function mapDispatchers(ids: Iterable<string>): string[] | undefined {
|
|
const list = [...ids].map(toBoardDispatcherId);
|
|
return list.length > 0 ? list : undefined;
|
|
}
|
|
|
|
/** Maps UI type filters to API `types` + separate `overdue` flag. Overdue is never sent as types=99. */
|
|
function mapWoTypeFilters(types: Iterable<WOType | string>): {
|
|
types?: number[];
|
|
overdue?: boolean;
|
|
} {
|
|
const list: number[] = [];
|
|
let overdue = false;
|
|
for (const type of types) {
|
|
if (type === "All") {
|
|
continue;
|
|
}
|
|
if (type === "Overdue") {
|
|
overdue = true;
|
|
continue;
|
|
}
|
|
const api = mapWizardTypeToApi(type as WOType);
|
|
if (api != null) {
|
|
list.push(api);
|
|
}
|
|
}
|
|
return {
|
|
types: list.length > 0 ? list : undefined,
|
|
overdue: overdue || undefined,
|
|
};
|
|
}
|
|
|
|
function mapStatuses(statuses: Iterable<WizardWOStatus | string>): number[] | undefined {
|
|
const list: number[] = [];
|
|
for (const status of statuses) {
|
|
const value = LIFECYCLE_STATUS_API[status as WizardWOStatus];
|
|
if (typeof value === "number") {
|
|
list.push(value);
|
|
} else if (status === "Canceled" || status === "Cancelled") {
|
|
list.push(LIFECYCLE_STATUS_API.Canceled);
|
|
}
|
|
}
|
|
return list.length > 0 ? list : undefined;
|
|
}
|
|
|
|
function mapDocStatuses(docs: Iterable<CompletionDocFilter>): number[] | undefined {
|
|
const list: number[] = [];
|
|
for (const doc of docs) {
|
|
if (doc === "Yes") list.push(DOC_STATUS_API.Yes);
|
|
else if (doc === "No") list.push(DOC_STATUS_API.No);
|
|
else if (doc === "NN") list.push(DOC_STATUS_API.NotNeeded);
|
|
}
|
|
return list.length > 0 ? list : undefined;
|
|
}
|
|
|
|
/** Build GET /board query from weekly filter bar. */
|
|
export function toBoardQueryParams(
|
|
bar: WorkOrderBarFilters,
|
|
search: string,
|
|
): WorkOrderBoardQueryParams {
|
|
const [, weekTo] = weekRange(bar.weekMonday);
|
|
const typeFilters = bar.type !== "All" ? mapWoTypeFilters([bar.type]) : {};
|
|
|
|
return {
|
|
weekStart: bar.weekMonday,
|
|
weekEnd: weekTo,
|
|
dispatchers: mapDispatchers(bar.dispatcherIds),
|
|
types: typeFilters.types,
|
|
overdue: typeFilters.overdue,
|
|
search: search.trim().length >= 2 ? search.trim() : undefined,
|
|
};
|
|
}
|
|
|
|
/** Build GET /board/search query from advanced filters (+ optional bar/search). */
|
|
export function toBoardSearchQueryParams(input: {
|
|
filters: WorkOrderAdvancedFilters;
|
|
search?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
sortBy?: string;
|
|
sortDir?: string;
|
|
/** Optional company-name → vendorId resolution. */
|
|
vendorIdsByCompanyName?: Map<string, number>;
|
|
}): WorkOrderBoardSearchQueryParams {
|
|
const { filters } = input;
|
|
const datePreset = DATE_RANGE_TO_PRESET[filters.dateRange];
|
|
const pageSize = Math.min(
|
|
input.pageSize ?? BOARD_SEARCH_MAX_PAGE_SIZE,
|
|
BOARD_SEARCH_MAX_PAGE_SIZE,
|
|
);
|
|
|
|
const vendorIds: number[] = [];
|
|
if (input.vendorIdsByCompanyName && filters.vendorTechs.size > 0) {
|
|
for (const name of filters.vendorTechs) {
|
|
const id = input.vendorIdsByCompanyName.get(name);
|
|
if (typeof id === "number") {
|
|
vendorIds.push(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
const typeFilters = mapWoTypeFilters(filters.types);
|
|
|
|
const params: WorkOrderBoardSearchQueryParams = {
|
|
page: input.page ?? 0,
|
|
pageSize,
|
|
search:
|
|
input.search?.trim() && input.search.trim().length >= 2 ? input.search.trim() : undefined,
|
|
datePreset,
|
|
sites: filters.sites.size > 0 ? [...filters.sites] : undefined,
|
|
types: typeFilters.types,
|
|
overdue: typeFilters.overdue,
|
|
dispatchers: mapDispatchers(filters.dispatchers),
|
|
statuses: mapStatuses(filters.statuses),
|
|
pmTypes: filters.pmTypes.size > 0 ? [...filters.pmTypes] : undefined,
|
|
vendorIds: vendorIds.length > 0 ? vendorIds : undefined,
|
|
docStatuses: mapDocStatuses(filters.docs),
|
|
sortBy: input.sortBy || "scheduledDate",
|
|
sortDir: input.sortDir === "desc" ? "desc" : "asc",
|
|
};
|
|
|
|
if (datePreset === "Custom") {
|
|
params.dateFrom = filters.customFrom || undefined;
|
|
params.dateTo = filters.customTo || undefined;
|
|
}
|
|
|
|
return params;
|
|
}
|
|
|
|
/** ky/URLSearchParams-friendly object; arrays become repeated keys. */
|
|
export function buildBoardSearchParamsRecord(
|
|
params: WorkOrderBoardQueryParams | WorkOrderBoardSearchQueryParams,
|
|
): Record<string, string | number | boolean | (string | number)[]> {
|
|
const out: Record<string, string | number | boolean | (string | number)[]> = {};
|
|
|
|
for (const [key, value] of Object.entries(params)) {
|
|
if (value === undefined || value === null || value === "") {
|
|
continue;
|
|
}
|
|
if (Array.isArray(value)) {
|
|
if (value.length === 0) continue;
|
|
out[key] = value;
|
|
continue;
|
|
}
|
|
out[key] = value as string | number | boolean;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
export function woTypeFilterIsOverdue(type: string): boolean {
|
|
return type === "Overdue";
|
|
}
|