330 lines
10 KiB
TypeScript
330 lines
10 KiB
TypeScript
import "reflect-metadata";
|
|
|
|
import LeftArrowIcon from "@Assets/Icons/left-arrow.svg";
|
|
import RightArrowIcon from "@Assets/Icons/right-arrow.svg";
|
|
import Documents from "@Front/Api/LeCoffreApi/SuperAdmin/Documents/Documents";
|
|
import ValidateAnchoringGif from "@Front/Assets/images/validate_anchoring.gif";
|
|
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
|
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
|
|
import FilePreview from "@Front/Components/DesignSystem/FilePreview";
|
|
import InputField from "@Front/Components/DesignSystem/Form/Elements/InputField";
|
|
import Confirm from "@Front/Components/DesignSystem/Modal/Confirm";
|
|
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
|
|
import Module from "@Front/Config/Module";
|
|
import { Document, File } from "le-coffre-resources/dist/Customer";
|
|
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
|
|
import Image from "next/image";
|
|
import { NextRouter, useRouter } from "next/router";
|
|
import React from "react";
|
|
|
|
import BasePage from "../../Base";
|
|
import classes from "./classes.module.scss";
|
|
import OcrResult from "./OcrResult";
|
|
|
|
|
|
type IProps = {};
|
|
type IPropsClass = {
|
|
documentUid: string;
|
|
router: NextRouter;
|
|
folderUid: string;
|
|
};
|
|
|
|
type IState = {
|
|
isRefuseModalVisible: boolean;
|
|
isValidateModalVisible: boolean;
|
|
refuseText: string;
|
|
hasValidateAnchoring: boolean;
|
|
selectedFileIndex: number;
|
|
selectedFile: File | null;
|
|
validatedPercentage: number;
|
|
document: Document | null;
|
|
};
|
|
|
|
class ViewDocumentsClass extends BasePage<IPropsClass, IState> {
|
|
public constructor(props: IPropsClass) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
isValidateModalVisible: false,
|
|
isRefuseModalVisible: false,
|
|
refuseText: "",
|
|
hasValidateAnchoring: false,
|
|
selectedFileIndex: 0,
|
|
selectedFile: null,
|
|
validatedPercentage: this.getRandomPercentageForOcr(),
|
|
document: null,
|
|
};
|
|
|
|
this.closeModals = this.closeModals.bind(this);
|
|
this.openValidateModal = this.openValidateModal.bind(this);
|
|
this.openRefuseModal = this.openRefuseModal.bind(this);
|
|
this.onRefuseTextChange = this.onRefuseTextChange.bind(this);
|
|
this.validateAnchoring = this.validateAnchoring.bind(this);
|
|
this.goToNext = this.goToNext.bind(this);
|
|
this.goToPrevious = this.goToPrevious.bind(this);
|
|
|
|
this.hasPrevious = this.hasPrevious.bind(this);
|
|
this.hasNext = this.hasNext.bind(this);
|
|
this.refuseDocument = this.refuseDocument.bind(this);
|
|
}
|
|
|
|
public override render(): JSX.Element | null {
|
|
return (
|
|
<DefaultNotaryDashboard title={"Demander des documents"} hasBackArrow mobileBackText="Retour aux documents">
|
|
{this.state.document && this.state.document.files && this.state.selectedFile && (
|
|
<div className={classes["root"]}>
|
|
<Typography typo={ITypo.H1} color={ITypoColor.BLACK} className={classes["title"]}>
|
|
App 23 rue Torus Toulon
|
|
</Typography>
|
|
<Typography typo={ITypo.H3} color={ITypoColor.BLACK} className={classes["subtitle"]}>
|
|
{this.state.document.document_type?.name}
|
|
</Typography>
|
|
<div className={classes["document-container"]}>
|
|
{this.state.document.files.length > 1 && (
|
|
<div
|
|
className={classes["arrow-container"]}
|
|
onClick={this.goToPrevious}
|
|
data-disabled={(!this.hasPrevious()).toString()}>
|
|
<Image src={LeftArrowIcon} alt="left arrow" />
|
|
</div>
|
|
)}
|
|
<div className={classes["file-container"]}>
|
|
<FilePreview href={this.state.selectedFile.file_path as string} key={this.state.selectedFile.uid} />
|
|
</div>
|
|
{this.state.document.files.length > 1 && (
|
|
<div
|
|
className={classes["arrow-container"]}
|
|
onClick={this.goToNext}
|
|
data-disabled={(!this.hasNext()).toString()}>
|
|
<Image src={RightArrowIcon} alt="right arrow" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className={classes["footer"]}>
|
|
{this.state.document?.document_type?.name === "Carte d'identité" && (
|
|
<div className={classes["ocr-container"]}>
|
|
<OcrResult percentage={this.state.validatedPercentage} />
|
|
</div>
|
|
)}
|
|
|
|
<div className={classes["buttons-container"]}>
|
|
{this.state.document?.document_status === EDocumentStatus.DEPOSITED && (
|
|
<>
|
|
<Button variant={EButtonVariant.GHOST} onClick={this.openRefuseModal}>
|
|
Refuser
|
|
</Button>
|
|
<Button onClick={this.openValidateModal}>Valider et ancrer</Button>
|
|
<Button disabled>Télécharger</Button>
|
|
</>
|
|
)}
|
|
{this.state.document?.document_status === "VALIDATED" && (
|
|
<a href={this.state.selectedFile.file_path!} download target="_blank">
|
|
<Button>Télécharger</Button>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<Confirm
|
|
isOpen={this.state.isValidateModalVisible}
|
|
onClose={this.closeModals}
|
|
onAccept={this.validateAnchoring}
|
|
closeBtn={true}
|
|
hasContainerClosable={true}
|
|
header={this.state.hasValidateAnchoring ? "Document en cours de validation" : "Ancrer le document"}
|
|
cancelText={"Annuler"}
|
|
confirmText={"Confirmer"}
|
|
showButtons={!this.state.hasValidateAnchoring}>
|
|
<div className={classes["validate-document-container"]}>
|
|
{!this.state.hasValidateAnchoring && (
|
|
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
|
|
Êtes-vous sûr de vouloir ancrer ce document ?
|
|
</Typography>
|
|
)}
|
|
{this.state.hasValidateAnchoring && (
|
|
<div className={classes["document-validating-container"]}>
|
|
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["validate-text"]}>
|
|
Le document s'ancre dans la blockchain.
|
|
</Typography>
|
|
<Image src={ValidateAnchoringGif} alt="Anchoring animation" className={classes["validate-gif"]} />
|
|
<div className={classes["dont-show-again"]}>
|
|
<CheckBox option={{ label: "Ne plus afficher ce message", value: false }} toolTip={"Test"} />
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Confirm>
|
|
<Confirm
|
|
isOpen={this.state.isRefuseModalVisible}
|
|
onClose={this.closeModals}
|
|
onAccept={this.refuseDocument}
|
|
closeBtn
|
|
header={"Refuser le document ?"}
|
|
cancelText={"Annuler"}
|
|
confirmText={"Refuser"}>
|
|
<div className={classes["refuse-document-container"]}>
|
|
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["refuse-text"]}>
|
|
Veuillez indiquer au client le motif du refus de son document afin qu'il puisse vous renvoyer une bonne
|
|
version.
|
|
</Typography>
|
|
<InputField fakeplaceholder="Motif du refus" textarea onChange={this.onRefuseTextChange} />
|
|
</div>
|
|
</Confirm>
|
|
</div>
|
|
)}
|
|
{(!this.state.selectedFile || !this.state.document) && (
|
|
<div className={classes["root"]}>
|
|
<Typography typo={ITypo.P_16} color={ITypoColor.BLACK} className={classes["refuse-text"]}>
|
|
Document non trouvé
|
|
</Typography>
|
|
</div>
|
|
)}
|
|
</DefaultNotaryDashboard>
|
|
);
|
|
}
|
|
|
|
override async componentDidMount() {
|
|
try {
|
|
const document = await Documents.getInstance().getByUid(this.props.documentUid, {
|
|
files: true,
|
|
document_type: true,
|
|
});
|
|
this.setState({
|
|
document,
|
|
selectedFileIndex: 0,
|
|
selectedFile: document.files![0]!,
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
private getRandomPercentageForOcr() {
|
|
// find diff
|
|
let difference = 100 - 90;
|
|
|
|
// generate random number
|
|
let rand = Math.random();
|
|
|
|
// multiply with difference
|
|
rand = Math.floor(rand * difference);
|
|
|
|
// add with min value
|
|
rand = rand + 90;
|
|
|
|
return rand;
|
|
}
|
|
|
|
private goToPrevious() {
|
|
const index = this.state.selectedFileIndex - 1;
|
|
if (this.hasPrevious()) {
|
|
this.setState({
|
|
selectedFile: this.state.document!.files![index]!,
|
|
selectedFileIndex: index,
|
|
});
|
|
}
|
|
}
|
|
|
|
private goToNext() {
|
|
if (this.hasNext()) {
|
|
const index = this.state.selectedFileIndex + 1;
|
|
this.setState({
|
|
selectedFile: this.state.document!.files![index]!,
|
|
selectedFileIndex: index,
|
|
});
|
|
}
|
|
}
|
|
|
|
private hasPrevious() {
|
|
const index = this.state.selectedFileIndex - 1;
|
|
return index >= 0;
|
|
}
|
|
|
|
private hasNext() {
|
|
const index = this.state.selectedFileIndex + 1;
|
|
return index < this.state.document!.files!.length;
|
|
}
|
|
|
|
private async refuseDocument(){
|
|
try{
|
|
await Documents.getInstance().put(this.props.documentUid, {
|
|
document_status: EDocumentStatus.REFUSED,
|
|
refused_reason: this.state.refuseText
|
|
});
|
|
|
|
this.props.router.push(
|
|
Module.getInstance()
|
|
.get()
|
|
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid),
|
|
);
|
|
}catch(e){
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
private async validateAnchoring() {
|
|
this.setState({
|
|
hasValidateAnchoring: true,
|
|
});
|
|
|
|
try {
|
|
await Documents.getInstance().put(this.props.documentUid, {
|
|
document_status: EDocumentStatus.VALIDATED,
|
|
});
|
|
|
|
const timeoutDelay = 9800;
|
|
setTimeout(() => {
|
|
this.setState({
|
|
isValidateModalVisible: false,
|
|
});
|
|
this.props.router.push(
|
|
Module.getInstance()
|
|
.get()
|
|
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid),
|
|
);
|
|
}, timeoutDelay);
|
|
|
|
setTimeout(() => {
|
|
this.setState({
|
|
hasValidateAnchoring: false,
|
|
});
|
|
}, timeoutDelay + 1000);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
private onRefuseTextChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
this.setState({
|
|
refuseText: e.target.value,
|
|
});
|
|
}
|
|
|
|
private openValidateModal() {
|
|
this.setState({
|
|
isValidateModalVisible: true,
|
|
});
|
|
}
|
|
|
|
private openRefuseModal() {
|
|
this.setState({
|
|
isRefuseModalVisible: true,
|
|
});
|
|
}
|
|
|
|
private closeModals() {
|
|
this.setState({
|
|
isValidateModalVisible: false,
|
|
isRefuseModalVisible: false,
|
|
});
|
|
}
|
|
}
|
|
|
|
export default function ViewDocuments(props: IProps) {
|
|
const router = useRouter();
|
|
let { folderUid, documentUid } = router.query;
|
|
documentUid = documentUid as string;
|
|
folderUid = folderUid as string;
|
|
return <ViewDocumentsClass {...props} documentUid={documentUid} router={router} folderUid={folderUid as string} />;
|
|
}
|