Files
edr-platform/apps/edr-freight-web/backoffice/src/shared/services/unifiedUploadService.ts
natib21 e6e44e773b fix ui
2026-07-10 11:25:59 +00:00

168 lines
4.1 KiB
TypeScript

import { AxiosInstance } from "axios";
import { presignedAxios } from "./presignedAxios";
import { withHeaders } from "@/record-management/services/api/withHeaders";
export interface UploadKeyResponse {
uploadKey: string;
presignedUrl?: string;
presigned?: string;
fileInfo: {
fileName: string;
originalname: string;
contentType: string;
fileType: string;
size: number;
};
}
export interface UploadAndCreateResourceParams {
type: "signature" | "stamp" | "header" | "footer";
file: File;
name: { am: string; en: string };
parentId: string;
locale?: "am" | "en" | null;
}
const config = {
signature: {
uploadKey: "/signatures/get-file-upload-key",
create: "/signatures",
parentField: "employeeId",
},
stamp: {
uploadKey: "/employee-stamps/get-file-upload-key",
create: "/employee-stamps",
parentField: "employeePositionId",
},
header: {
uploadKey: "/headers/get-file-upload-key",
create: "/headers",
parentField: "unitId",
},
footer: {
uploadKey: "/footers/get-file-upload-key",
create: "/footers",
parentField: "unitId",
},
} as const;
/**
* Get upload key and presigned URL for file upload
*/
export async function getUploadKey(
endpoint: string,
file: File,
axiosInstance: AxiosInstance,
positionId?: string[],
recordTypeKey?: string | null,
): Promise<UploadKeyResponse> {
const payload = {
fileName: file.name,
originalname: file.name,
contentType: file.type || "application/octet-stream",
size: file.size,
...(positionId?.length ? { positionId } : {}),
recordTypeKey: recordTypeKey,
};
const { data } = await axiosInstance.post<UploadKeyResponse>(
endpoint,
payload,
{
headers: withHeaders(),
},
);
return data;
}
/**
* Upload file to presigned URL
*/
export async function uploadToPresigned(
file: File,
presignedUrl: string,
): Promise<void> {
if (!presignedUrl) {
throw new Error("Presigned URL is required");
}
const uploadRes = await presignedAxios.put(presignedUrl, file, {
headers: {
"Content-Type": file.type,
},
});
if (uploadRes.status < 200 || uploadRes.status >= 300) {
throw new Error(
`Upload failed with status ${uploadRes.status}: ${uploadRes.statusText}`,
);
}
}
/**
* Unified upload and create resource function
*/
export async function uploadAndCreateResource(
params: UploadAndCreateResourceParams,
axiosInstance: AxiosInstance,
positionId?: string[],
recordTypeKey?: string | null,
) {
const { type, file, name, parentId, locale } = params;
const typeConfig = config[type];
// 1. Get upload key and presigned URL
const uploadKeyResponse = await getUploadKey(
typeConfig.uploadKey,
file,
axiosInstance,
positionId,
recordTypeKey,
);
const presignedUrl =
uploadKeyResponse.presignedUrl || uploadKeyResponse.presigned;
// 2. Upload file to presigned URL
await uploadToPresigned(file, presignedUrl || "");
// 3. For header/footer: done — no separate create POST needed
if (type === "header" || type === "footer") {
// 4. For signature/stamp: create resource
const createPayload = {
fileInfo: uploadKeyResponse.fileInfo,
name,
[typeConfig.parentField]: parentId,
positionIds: positionId,
isCurrent: true,
recordTypeKey: recordTypeKey,
};
const { data } = await axiosInstance.post(
typeConfig.create,
createPayload,
{
headers: withHeaders(),
},
);
return data;
}
// 4. For signature/stamp: create resource
const createPayload = {
fileInfo: uploadKeyResponse.fileInfo,
name,
[typeConfig.parentField]: parentId,
...(type === "signature" ? { isCurrent: true } : {}),
...(type === "stamp" && locale !== undefined ? { locale } : {}),
};
const { data } = await axiosInstance.post(typeConfig.create, createPayload, {
headers: withHeaders(),
});
return data;
}