mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-01 10:53:11 +00:00
Dispatchers can flag Aveta on Service and Notes and filter those rows without a site-level attribute.
106 lines
3 KiB
TypeScript
106 lines
3 KiB
TypeScript
import type { WorkOrderAdditionalContact } from "@/domain/work-orders/types/work-order-additional-contact";
|
|
import type {
|
|
WorkOrderTablePatch,
|
|
WorkOrderTableRow,
|
|
} from "@/domain/work-orders/types/work-order-table-row";
|
|
|
|
/**
|
|
* Fields compared for dirty state and included in Save patch.
|
|
* Only keys that map to board PATCH (or required companions like dispatcherName).
|
|
* Primary POC scalars and tech phone are not board-editable — exclude so Save cannot no-op.
|
|
* additionalContacts is board-editable (SH-218 PATCH field).
|
|
*/
|
|
export const SLIDE_OVER_EDIT_KEYS = [
|
|
"woNumber",
|
|
"site",
|
|
"type",
|
|
"dispatcherId",
|
|
"dispatcherName",
|
|
"scheduledOn",
|
|
"targetWeek",
|
|
"scheduleWeekOnly",
|
|
"dueDate",
|
|
"completedDate",
|
|
"apptTime",
|
|
"pm",
|
|
"serviceNotes",
|
|
"extraServices",
|
|
"avetaRequired",
|
|
"additionalContacts",
|
|
"vendorId",
|
|
// company/tech are display companions; board persists vendor via vendorId only
|
|
"status",
|
|
] as const satisfies ReadonlyArray<keyof WorkOrderTableRow>;
|
|
|
|
type EditKey = (typeof SLIDE_OVER_EDIT_KEYS)[number];
|
|
|
|
function sameExtraServices(a: string[] | undefined, b: string[] | undefined): boolean {
|
|
const left = a ?? [];
|
|
const right = b ?? [];
|
|
if (left.length !== right.length) return false;
|
|
return left.every((value, index) => value === right[index]);
|
|
}
|
|
|
|
function sameAdditionalContacts(
|
|
a: WorkOrderAdditionalContact[] | undefined,
|
|
b: WorkOrderAdditionalContact[] | undefined,
|
|
): boolean {
|
|
const left = a ?? [];
|
|
const right = b ?? [];
|
|
if (left.length !== right.length) return false;
|
|
return left.every((contact, index) => {
|
|
const other = right[index];
|
|
return (
|
|
contact.name === other.name &&
|
|
contact.phone === other.phone &&
|
|
(contact.notes ?? "") === (other.notes ?? "")
|
|
);
|
|
});
|
|
}
|
|
|
|
export function isSlideOverDraftDirty(
|
|
draft: WorkOrderTableRow,
|
|
baseline: WorkOrderTableRow,
|
|
): boolean {
|
|
for (const key of SLIDE_OVER_EDIT_KEYS) {
|
|
if (key === "extraServices") {
|
|
if (!sameExtraServices(draft.extraServices, baseline.extraServices)) return true;
|
|
continue;
|
|
}
|
|
if (key === "additionalContacts") {
|
|
if (!sameAdditionalContacts(draft.additionalContacts, baseline.additionalContacts)) {
|
|
return true;
|
|
}
|
|
continue;
|
|
}
|
|
if (draft[key] !== baseline[key]) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function buildSlideOverPatch(
|
|
draft: WorkOrderTableRow,
|
|
baseline: WorkOrderTableRow,
|
|
): WorkOrderTablePatch {
|
|
const patch: WorkOrderTablePatch = {};
|
|
|
|
for (const key of SLIDE_OVER_EDIT_KEYS) {
|
|
if (key === "extraServices") {
|
|
if (!sameExtraServices(draft.extraServices, baseline.extraServices)) {
|
|
patch.extraServices = draft.extraServices;
|
|
}
|
|
continue;
|
|
}
|
|
if (key === "additionalContacts") {
|
|
if (!sameAdditionalContacts(draft.additionalContacts, baseline.additionalContacts)) {
|
|
patch.additionalContacts = draft.additionalContacts;
|
|
}
|
|
continue;
|
|
}
|
|
if (draft[key] !== baseline[key]) {
|
|
(patch as Record<EditKey, WorkOrderTableRow[EditKey]>)[key] = draft[key];
|
|
}
|
|
}
|
|
|
|
return patch;
|
|
}
|