2025-07-03 18:09:01 +02:00

201 lines
6.8 KiB
TypeScript

import DragAndDrop, { IDocumentFileWithUid } from "@Front/Components/DesignSystem/DragAndDrop";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import { useCallback, useMemo, useState } from "react";
import classes from "./classes.module.scss";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import { ToasterService } from "@Front/Components/DesignSystem/Toaster";
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import { FileBlob, FileData } from "@Front/Api/Entities/types";
type IProps = {
document: any;
onChange: () => void;
};
export default function DepositDocumentComponent(props: IProps) {
const { document, onChange } = props;
const [isModalOpen, setIsModalOpen] = useState(false);
const [refused_reason, setRefusedReason] = useState<string | null>(null);
const defaultFiles: IDocumentFileWithUid[] = useMemo(() => {
const filesNotArchived = document.files?.filter((file: any) => !file.archived_at) ?? [];
return filesNotArchived.map((file: any) => ({
id: file.uid!,
file: new File([""], file.file_name!, { type: file.file_blob.type }),
uid: file.uid!,
}));
}, [document.files]);
const addFile = useCallback(
(file: File) => {
return new Promise<void>(
(resolve: () => void) => {
const reader = new FileReader();
reader.onload = (event) => {
if (event.target?.result) {
const arrayBuffer = event.target.result as ArrayBuffer;
const uint8Array = new Uint8Array(arrayBuffer);
const fileBlob: FileBlob = {
type: file.type,
data: uint8Array
};
const fileData: FileData = {
file_blob: fileBlob,
file_name: file.name
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
FileService.createFile(fileData, validatorId).then((processCreated: any) => {
const fileUid: string = processCreated.processData.uid;
DocumentService.getDocumentByUid(document.uid!).then((process: any) => {
if (process) {
const document: any = process.processData;
let files: any[] = document.files;
if (!files) {
files = [];
}
files.push({ uid: fileUid });
DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => resolve());
}
});
});
}
};
reader.readAsArrayBuffer(file);
})
.then(onChange)
.then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Fichier uploadé avec succès!" }))
.catch((error) => ToasterService.getInstance().error({ title: "Erreur !", description: error.message }));
},
[document.uid, onChange],
);
const deleteFile = useCallback(
(fileUid: string) => {
return new Promise<void>(
(resolve: () => void) => {
FileService.getFileByUid(fileUid).then((res: any) => {
if (res) {
FileService.updateFile(res.processId, { isDeleted: 'true' }).then(() => {
DocumentService.getDocumentByUid(document.uid!).then((process: any) => {
if (process) {
const document: any = process.processData;
let files: any[] = document.files;
if (!files) {
files = [];
}
files = files.filter((file: any) => file.uid !== fileUid);
DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.ASKED }).then(() => resolve());
}
});
});
}
});
})
.then(onChange)
.then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Fichier supprimé avec succès!" }))
.catch((error) => ToasterService.getInstance().error({ title: "Erreur !", description: error.message }));
},
[onChange],
);
const onOpenModal = useCallback(async () => {
if (document.document_status !== "REFUSED") return;
const refused_reason = document.refused_reason;
if (!refused_reason) return;
setRefusedReason(refused_reason);
setIsModalOpen(true);
}, [document.document_history]);
const closeModal = useCallback(() => {
setIsModalOpen(false);
}, []);
return (
<div className={classes["root"]}>
<div className={classes["title"]}>
<Typography typo={ETypo.TEXT_MD_SEMIBOLD} color={ETypoColor.TEXT_PRIMARY}>
{document.document_type?.name ?? "_"}
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Demandé le :{" "}
<a className={classes["date"]}>{document.created_at ? new Date(document.created_at).toLocaleDateString() : "_"}</a>
</Typography>
{document.document_status === "DEPOSITED" && (
<div>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Déposé le :{" "}
<a className={classes["date"]}>
{document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_"}
</a>
</Typography>
</div>
)}
{document.document_status === "REFUSED" && (
<div>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Refusé le :{" "}
<a className={classes["date"]}>
{document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_"}
</a>
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.ERROR_WEAK_CONTRAST} onClick={onOpenModal}>
Document non-conforme{" : "} <a className={classes["refused-link"]}>Voir le motif de refus</a>
</Typography>
</div>
)}
{document.document_status === "VALIDATED" && (
<div>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Validé le :{" "}
<a className={classes["date"]}>
{document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_"}
</a>
</Typography>
</div>
)}
</div>
<Confirm
isOpen={isModalOpen}
showCancelButton={false}
onAccept={closeModal}
onClose={closeModal}
closeBtn
header={"Motif de refus"}
confirmText={"J'ai compris"}>
<div className={classes["modal-content"]}>
<Typography typo={ETypo.TEXT_MD_SEMIBOLD} className={classes["text"]}>
Votre document a é refusé pour la raison suivante :
</Typography>
<br />
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
{refused_reason}
</Typography>
</div>
</Confirm>
{document.document_status !== "VALIDATED" && (
<DragAndDrop
title={"Glisser-déposer ou"}
description={document.document_type?.public_description ?? undefined}
defaultFiles={defaultFiles}
onAddFile={addFile}
onDelete={deleteFile}
/>
)}
</div>
);
}