mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 17:53:12 +00:00
Stage every selected file, wait for each scan, and download by document id. Refresh the work-order detail snapshot for the current tab strip.
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import type { UpliftEvidenceSnapshot } from "@/domain/work-orders/api/work-order-uplifts-api";
|
|
import type {
|
|
CreateWorkOrderUpliftInput,
|
|
WorkOrderUplift,
|
|
} from "@/domain/work-orders/types/work-order-uplift";
|
|
|
|
const POLL_INTERVAL_MS = 1000;
|
|
const MAX_POLL_ATTEMPTS = 30;
|
|
|
|
type CreateUpliftBody = {
|
|
amount: number;
|
|
notes: string;
|
|
evidenceDocumentId?: number;
|
|
evidenceDocumentIds?: number[];
|
|
};
|
|
|
|
export type SubmitWorkOrderUpliftDeps = {
|
|
uploadEvidence: (workOrderId: string | number, file: File) => Promise<UpliftEvidenceSnapshot>;
|
|
getEvidenceStatus: (
|
|
workOrderId: string | number,
|
|
documentId: number,
|
|
) => Promise<UpliftEvidenceSnapshot>;
|
|
create: (workOrderId: string | number, input: CreateUpliftBody) => Promise<WorkOrderUplift>;
|
|
sleep?: (ms: number) => Promise<void>;
|
|
};
|
|
|
|
function sleep(ms: number): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
setTimeout(resolve, ms);
|
|
});
|
|
}
|
|
|
|
function scanFailureMessage(scanStatus: "Rejected" | "Timeout"): string {
|
|
if (scanStatus === "Rejected") {
|
|
return "The evidence file was rejected by the security scan.";
|
|
}
|
|
return "The evidence file is still being scanned. Try again in a moment.";
|
|
}
|
|
|
|
async function waitForPassedScan(
|
|
workOrderId: string | number,
|
|
file: File,
|
|
deps: SubmitWorkOrderUpliftDeps,
|
|
): Promise<number> {
|
|
const pause = deps.sleep ?? sleep;
|
|
const uploaded = await deps.uploadEvidence(workOrderId, file);
|
|
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt += 1) {
|
|
const document =
|
|
attempt === 0 ? uploaded : await deps.getEvidenceStatus(workOrderId, uploaded.id);
|
|
if (document.scanStatus === "Passed") {
|
|
return uploaded.id;
|
|
}
|
|
if (document.scanStatus === "Rejected") {
|
|
throw new Error(scanFailureMessage("Rejected"));
|
|
}
|
|
await pause(POLL_INTERVAL_MS);
|
|
}
|
|
throw new Error(scanFailureMessage("Timeout"));
|
|
}
|
|
|
|
export async function submitWorkOrderUplift(
|
|
workOrderId: string | number,
|
|
input: CreateWorkOrderUpliftInput,
|
|
deps: SubmitWorkOrderUpliftDeps,
|
|
): Promise<WorkOrderUplift> {
|
|
const evidenceDocumentIds: number[] = [];
|
|
for (const file of input.files ?? []) {
|
|
evidenceDocumentIds.push(await waitForPassedScan(workOrderId, file, deps));
|
|
}
|
|
const [evidenceDocumentId] = evidenceDocumentIds;
|
|
return deps.create(workOrderId, {
|
|
amount: input.amount,
|
|
notes: input.notes,
|
|
evidenceDocumentId,
|
|
evidenceDocumentIds: evidenceDocumentIds.length > 0 ? evidenceDocumentIds : undefined,
|
|
});
|
|
}
|