2025-07-02 13:41:39 +02:00

402 lines
12 KiB
TypeScript

import DepositDocumentIcon from "@Assets/Icons/deposit-document.svg";
import CrossIcon from "@Assets/Icons/cross.svg";
import DocumentCheckIcon from "@Assets/Icons/document-check.svg";
import PlusIcon from "@Assets/Icons/plus.svg";
import Image from "next/image";
import React from "react";
import Typography, { ETypo, ETypoColor } from "../Typography";
import classes from "./classes.module.scss";
import { Document } from "le-coffre-resources/dist/Customer";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import classNames from "classnames";
import Button, { EButtonstyletype, EButtonVariant } from "../Button";
import Confirm from "../OldModal/Confirm";
import Alert from "../OldModal/Alert";
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
type IProps = {
onChange?: (files: File[]) => void;
open: boolean;
onClose?: () => void;
document: Document;
customer_uid: string;
folder_uid: string | string[];
};
type IFile = {
index: number;
file: File;
fileName: string;
};
type IState = {
files: IFile[];
isDragOver: boolean;
currentFiles?: IFile[];
refusedReason?: string;
isShowRefusedReasonModalVisible: boolean;
showFailedUploaded: string | null;
showFailedDocument: string | null;
isAddDocumentModalVisible: boolean;
isLoading: boolean;
};
export default class DepositOtherDocument extends React.Component<IProps, IState> {
private inputRef = React.createRef<HTMLInputElement>();
private index = 0;
public constructor(props: IProps) {
super(props);
this.state = {
isAddDocumentModalVisible: this.props.open,
files: [],
isDragOver: false,
refusedReason: "",
isShowRefusedReasonModalVisible: false,
showFailedUploaded: null,
isLoading: false,
showFailedDocument: null,
};
this.addDocument = this.addDocument.bind(this);
this.onFileChange = this.onFileChange.bind(this);
this.removeFile = this.removeFile.bind(this);
this.onDragOver = this.onDragOver.bind(this);
this.onDragDrop = this.onDragDrop.bind(this);
this.onDragLeave = this.onDragLeave.bind(this);
this.onAccept = this.onAccept.bind(this);
this.onCloseAlertUpload = this.onCloseAlertUpload.bind(this);
}
public override render(): JSX.Element {
return (
<div>
<Confirm
isOpen={this.state.isAddDocumentModalVisible}
onClose={this.props.onClose!}
onAccept={this.onAccept}
closeBtn
header={"Ajouter un document"}
cancelText={"Annuler"}
confirmText={this.state.isLoading ? "Chargement..." : "Déposer le document"}
canConfirm={!this.state.isLoading}>
<div className={classes["modal-content"]}>
<div className={classes["container"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
Vous souhaitez envoyer un autre document à votre notaire ?
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le
document correspondant.
</Typography>
<div
className={classNames(
classes["root"],
this.props.document.document_status === EDocumentStatus.VALIDATED && classes["validated"],
)}
onDragOver={this.onDragOver}
onDrop={this.onDragDrop}
onDragLeave={this.onDragLeave}
data-drag-over={this.state.isDragOver.toString()}>
<input type="file" ref={this.inputRef} hidden onChange={this.onFileChange} />
<div className={classes["top-container"]}>
<div className={classes["left"]}>
<Image src={DepositDocumentIcon} alt="Deposit document" />
</div>
<div className={classes["separator"]} />
<div className={classes["right"]}>
<Typography
typo={ETypo.TEXT_MD_SEMIBOLD}
color={ETypoColor.COLOR_GENERIC_BLACK}
className={classes["title"]}>
<div
className={
this.props.document.document_status === EDocumentStatus.VALIDATED
? classes["validated"]
: ""
}>
{this.props.document.document_type?.name}
</div>
</Typography>
<Typography color={ETypoColor.COLOR_NEUTRAL_500} typo={ETypo.TEXT_SM_REGULAR}>
Sélectionnez des documents .jpg, .pdf ou .png
</Typography>
</div>
</div>
{this.state.currentFiles && this.state.currentFiles.length > 0 && (
<div className={classes["documents-container"]}>
{this.state.currentFiles.map((file) => {
const fileObj = file.file;
return (
<div className={classes["file-container"]} key={fileObj.name}>
<div className={classes["left-part"]}>
<Image src={DocumentCheckIcon} alt="Document check" />
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
{this.shortName(fileObj.name)}
</Typography>
</div>
<Image
src={CrossIcon}
alt="Cross icon"
className={classes["cross"]}
onClick={this.removeFile}
data-file={file.index}
/>
</div>
);
})}
</div>
)}
<div className={classes["bottom-container"]}>
<Button
variant={EButtonVariant.PRIMARY}
styletype={EButtonstyletype.TEXT}
className={classes["add-button"]}
onClick={this.addDocument}>
<Typography
typo={ETypo.TEXT_MD_SEMIBOLD}
color={ETypoColor.COLOR_PRIMARY_500}
className={classes["add-document"]}>
Ajouter un document <Image src={PlusIcon} alt="Plus icon" />
</Typography>
</Button>
</div>
</div>
</div>
</div>
</Confirm>
{this.state.showFailedDocument && (
<Alert
onClose={this.onCloseAlertUpload}
header={"L'ajout de Document n'est plus autorisé"}
isOpen={!!this.state.showFailedDocument}>
<div className={classes["modal-content"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
{this.state.showFailedDocument}
</Typography>
</div>
</Alert>
)}
{this.state.showFailedUploaded && (
<Alert onClose={this.onCloseAlertUpload} header={"Fichier non autorisé"} isOpen={!!this.state.showFailedUploaded}>
<div className={classes["modal-content"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
{this.state.showFailedUploaded}
</Typography>
</div>
</Alert>
)}
</div>
);
}
public override componentDidMount(): void { }
private onCloseAlertUpload() {
this.setState({ showFailedUploaded: null });
}
private async onAccept() {
this.setState({
isLoading: true,
});
const filesArray = this.state.currentFiles;
if (!filesArray) return;
LoaderService.getInstance().show();
let documentCreated: any;
try {
documentCreated = await new Promise<any>((resolve: (document: any) => void) => {
const documentTypeData: any = {
folder: {
uid: this.props.folder_uid,
},
depositor: {
uid: this.props.customer_uid,
}
};
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
DocumentService.createDocument(documentTypeData, validatorId).then((processCreated: any) => {
if (processCreated) {
const document: any = processCreated.processData;
resolve(document);
}
});
});
} catch (e) {
this.setState({ showFailedDocument: "Le dossier est vérifié aucune modification n'est acceptée", isLoading: false });
return;
}
for (let i = 0; i < filesArray.length; i++) {
const file = filesArray[i]!.file;
await 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: any = {
type: file.type,
data: uint8Array
};
const fileData: any = {
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(documentCreated.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);
});
}
this.setState({
isLoading: false,
});
this.props.onClose!();
window.location.reload();
}
private shortName(name: string): string {
const maxLength = 20;
if (name.length > maxLength) {
return name.substring(0, maxLength / 2) + "..." + name.substring(name.length - maxLength / 2, name.length);
}
return name;
}
private onDragOver(event: React.DragEvent<HTMLDivElement>) {
if (!this.state.isDragOver) {
this.setState({
isDragOver: true,
});
}
event.preventDefault();
}
private onDragLeave(event: React.DragEvent<HTMLDivElement>) {
this.setState({
isDragOver: false,
});
event.preventDefault();
}
private async onDragDrop(event: React.DragEvent<HTMLDivElement>) {
event.preventDefault();
this.setState({
isDragOver: false,
});
const file = event.dataTransfer.files[0];
if (file) this.addFile(file);
}
private async addFile(file: File) {
const iFile: IFile = {
file: file,
fileName: file.name,
index: this.index++,
};
const tmpArray: IFile[] = this.state.currentFiles || [];
tmpArray.push(iFile);
this.setState({
currentFiles: tmpArray,
});
// const formData = new FormData();
// formData.append("file", file, file.name);
// const query = JSON.stringify({ document: { uid: this.props.document.uid } });
// formData.append("q", query);
// const newFile = await Files.getInstance().post(formData);
// const newFile: FileCustomer = {
// file_name: file.name,
// }
// const files = this.state.currentFiles ? [...this.state.currentFiles, newFile] : [newFile];
// this.setState({
// currentFiles: files,
// loading: false,
// files: [
// ...this.state.files,
// {
// index: this.index++,
// file: file,
// uid: newFile.uid!,
// archived: null,
// fileName: newFile?.file_name ?? "",
// },
// ],
// });
// if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file));
}
private async removeFile(e: any) {
const image = e.target as HTMLElement;
const indexToRemove = image.getAttribute("data-file");
if (!indexToRemove) return;
const file = this.state.currentFiles!.find((file) => file.index === parseInt(indexToRemove));
if (!file) return;
this.setState({
currentFiles: this.state.currentFiles!.filter((file) => file.index !== parseInt(indexToRemove)),
});
if (this.props.onChange) this.props.onChange(this.state.currentFiles!.map((file) => file.file));
}
private async onFileChange() {
if (!this.inputRef.current) return;
const files = this.inputRef.current.files;
if (!files) {
return;
}
const file = files[0];
if (file) this.addFile(file);
}
private addDocument() {
if (!this.inputRef.current) return;
this.inputRef.current.click();
}
// private formatDate(date: Date) {
// const dateToConvert = new Date(date);
// return dateToConvert.toLocaleDateString("fr-FR");
// }
}