import { API_PATHS } from "@/api/api-paths"; import { apiDelete, apiGet, apiPost, apiPut } from "@/api/api"; import { handleApiResponse, handlePaginatedResponse } from "@/api/handle-api-response"; import { isWoTableMockEnabled, shouldUseMockWorkOrderDetail, } from "@/domain/work-orders/mocks/is-wo-table-mock-enabled"; import { buildMockWorkOrderDetailFromTableRow, getMockWorkOrderLocations, getMockWorkOrderTableRow, getMockWorkOrderVendors, getMockWorkOrdersList, MOCK_WO_TABLE_USERS, } from "@/domain/work-orders/mocks/wo-table-mock-data"; import { mapDispatchComment, mapDispatchDetail, mapDispatchSignoff, mapDispatchToVendorPayload, mapEmployeeOptions, mapLocationOptions, mapTaskListTemplates, mapUpdateDispatchPayload, mapVendorDropdownItems, mapWorkOrderComment, mapWorkOrderDetail, mapWorkOrderFormToCreatePayload, mapWorkOrderFormToUpdatePayload, mapWorkOrderTableRows, } from "@/domain/work-orders/mappers/work-order-mapper"; import type { WorkOrderFormSchemaValues } from "@/domain/work-orders/schemas/work-order-schema"; import type { DispatchDetail, DispatchToVendorPayload, EmployeeOption, LocationOption, TaskListTemplate, UpdateDispatchPayload, WorkOrderVendorUpdatePayload, VendorDropdownItem, WorkOrderComment, WorkOrderDetail, WorkOrderFormValues, WorkOrderUser, } from "@/domain/work-orders/types/work-order"; import { DISPATCH_LOCATION_WO_PAGE_SIZE, type WorkOrdersListParams, type WorkOrdersListResult, } from "@/domain/work-orders/types/work-order-list"; function buildSearchParams(params: WorkOrdersListParams): Record { const searchParams: Record = { search: params.search ?? "", page: params.page ?? 1, pageSize: params.pageSize ?? 12, }; if (params.sortBy) { searchParams.sortBy = params.sortBy; } if (params.sortDir) { searchParams.sortDir = params.sortDir; } if (params.status) { searchParams.status = params.status; } if (params.assignee) { searchParams.assignee = params.assignee; } if (params.locationId) { searchParams.locationId = params.locationId; } if (params.dateFrom) { searchParams.dateFrom = params.dateFrom; } if (params.dateTo) { searchParams.dateTo = params.dateTo; } if (params.type) { searchParams.type = params.type; } if (params.assigneeIds) { searchParams.assigneeIds = params.assigneeIds; } return searchParams; } function mapUser(raw: unknown): WorkOrderUser { const item = (typeof raw === "object" && raw !== null ? raw : {}) as Record; const id = item.id ?? item.Id; const name = (typeof item.name === "string" ? item.name : undefined) ?? (typeof item.Name === "string" ? item.Name : undefined) ?? (typeof item.userName === "string" ? item.userName : "") ?? ""; return { id: typeof id === "string" || typeof id === "number" ? id : "", name, }; } async function mockNetworkDelay(): Promise { await new Promise((resolve) => setTimeout(resolve, 250)); } export const workOrdersApi = { getList: async (params: WorkOrdersListParams = {}): Promise => { if (isWoTableMockEnabled()) { await mockNetworkDelay(); return getMockWorkOrdersList(params); } const searchParams = buildSearchParams(params); const data = await apiGet(API_PATHS.workOrder.getList, { searchParams }); const paginated = handlePaginatedResponse(data, { page: params.page, pageSize: params.pageSize, }); return { items: mapWorkOrderTableRows(paginated.items), totalCount: paginated.totalCount, page: paginated.page, pageSize: paginated.pageSize, }; }, getListByLocation: async ( locationId: string | number, search = "", ): Promise => { return workOrdersApi.getList({ locationId, search, page: 1, pageSize: DISPATCH_LOCATION_WO_PAGE_SIZE, sortBy: "number", sortDir: "asc", }); }, fetchUsers: async (): Promise => { if (isWoTableMockEnabled()) { return MOCK_WO_TABLE_USERS; } const data = await apiGet(API_PATHS.user.list); const users = handleApiResponse(data); return Array.isArray(users) ? users.map(mapUser) : []; }, getById: async (id: string | number): Promise => { if (shouldUseMockWorkOrderDetail(id)) { await mockNetworkDelay(); const row = getMockWorkOrderTableRow(id); if (!row) { throw new Error("Mock work order not found"); } return buildMockWorkOrderDetailFromTableRow(row); } const data = await apiGet(API_PATHS.workOrder.getById, { searchParams: { id }, }); return mapWorkOrderDetail(handleApiResponse(data)); }, create: async ( values: WorkOrderFormSchemaValues | WorkOrderFormValues, ): Promise => { const payload = mapWorkOrderFormToCreatePayload(values); const data = await apiPost(API_PATHS.workOrder.addWorkorder, payload); return mapWorkOrderDetail(handleApiResponse(data)); }, update: async ( id: string | number, values: WorkOrderFormSchemaValues | WorkOrderFormValues, ): Promise => { if (shouldUseMockWorkOrderDetail(id)) { await mockNetworkDelay(); const row = getMockWorkOrderTableRow(id); if (!row) { throw new Error("Mock work order not found"); } return buildMockWorkOrderDetailFromTableRow({ ...row, woNumber: values.workOrderNumber || row.woNumber, dueDate: values.dueDate || row.dueDate, scheduledOn: values.scheduledDate || row.scheduledOn, dispatcherName: values.assignedTo || row.dispatcherName, pm: values.problem || row.pm, type: (values.source || row.type) as typeof row.type, }); } const payload = mapWorkOrderFormToUpdatePayload(id, values); const data = await apiPost(API_PATHS.workOrder.editWorkorder, payload); return mapWorkOrderDetail(handleApiResponse(data)); }, delete: async (id: string | number): Promise => { await apiDelete(API_PATHS.workOrder.deleteWorkorder, { json: { Id: Number(id) }, }); }, addComment: async ( workOrderId: string | number, text: string, commentType: string, ): Promise => { const data = await apiPost(API_PATHS.workOrder.addCommentJson, { WorkorderId: workOrderId, Text: text, CommentType: commentType, }); return mapWorkOrderComment(handleApiResponse(data)); }, changeStatus: async (id: string | number, status: string): Promise => { if (shouldUseMockWorkOrderDetail(id)) { await mockNetworkDelay(); return; } await apiPost(API_PATHS.workOrder.changeStatus, undefined, { searchParams: { id, status }, }); }, changeAssignment: async (id: string | number, assignTo: string | number): Promise => { if (shouldUseMockWorkOrderDetail(id)) { await mockNetworkDelay(); return; } await apiPost(API_PATHS.workOrder.changeAssignment, undefined, { searchParams: { id, assignTo: assignTo || "" }, }); }, fetchLocations: async (): Promise => { if (isWoTableMockEnabled()) { return getMockWorkOrderLocations(); } const data = await apiGet(API_PATHS.contact.getLocations); const items = handleApiResponse(data); return Array.isArray(items) ? mapLocationOptions(items) : []; }, fetchEmployeesDropdown: async (): Promise => { const data = await apiGet(API_PATHS.employee.dropdown); const items = handleApiResponse(data); return Array.isArray(items) ? mapEmployeeOptions(items) : []; }, fetchVendorsDropdown: async (trade?: string, siteZip?: string): Promise => { if (isWoTableMockEnabled()) { return getMockWorkOrderVendors(); } const searchParams: Record = {}; if (trade) { searchParams.trade = trade; } if (siteZip) { searchParams.siteZip = siteZip; } const data = await apiGet(API_PATHS.vendor.dropdown, { searchParams: Object.keys(searchParams).length > 0 ? searchParams : undefined, }); const items = handleApiResponse(data); return Array.isArray(items) ? mapVendorDropdownItems(items) : []; }, fetchTaskTemplates: async (): Promise => { const data = await apiGet(API_PATHS.taskListTemplate.list); const items = handleApiResponse(data); return Array.isArray(items) ? mapTaskListTemplates(items) : []; }, dispatchToVendor: async (payload: DispatchToVendorPayload): Promise => { await apiPost( API_PATHS.workOrder.dispatchToVendor, mapDispatchToVendorPayload(payload), ); }, getDispatchById: async (id: string | number): Promise => { const data = await apiGet(`${API_PATHS.workOrder.getDispatch}/${id}`); return mapDispatchDetail(handleApiResponse(data)); }, updateDispatch: async (payload: UpdateDispatchPayload): Promise => { await apiPost(API_PATHS.workOrder.updateDispatch, mapUpdateDispatchPayload(payload)); }, updateVendorFromWorkOrder: async ( vendorId: string | number, payload: WorkOrderVendorUpdatePayload, ): Promise => { await apiPut(`${API_PATHS.rest.vendors}/${vendorId}/work-order-update`, payload); }, addDispatchComment: async ( dispatchId: string | number, text: string, sendEmail = true, ): Promise => { const data = await apiPost(API_PATHS.workOrder.addDispatchComment, { DispatchId: dispatchId, Text: text, SendEmail: sendEmail, }); return mapDispatchComment(handleApiResponse(data)); }, updateChecklistItem: async ( id: string | number, isCompleted: boolean, completedBy: string, ): Promise => { await apiPost(API_PATHS.workOrder.updateChecklistItem, { Id: id, IsCompleted: isCompleted, CompletedBy: completedBy, }); }, addChecklistItem: async (dispatchId: string | number, itemText: string): Promise => { await apiPost(API_PATHS.workOrder.addChecklistItem, { DispatchId: dispatchId, ItemText: itemText, }); }, addDispatchSignoff: async ( dispatchId: string | number, signoffType: string, name: string, signature: string, signatureMethod: string, ): Promise => { const data = await apiPost(API_PATHS.workOrder.addDispatchSignoff, { DispatchId: dispatchId, SignoffType: signoffType, Name: name, Signature: signature, SignatureMethod: signatureMethod, }); return mapDispatchSignoff(handleApiResponse(data)); }, verifyDispatch: async (dispatchId: string | number): Promise => { await apiPost(API_PATHS.workOrder.verifyDispatch, undefined, { searchParams: { dispatchId }, }); }, };