import ChevronIcon from "@Assets/Icons/chevron.svg"; import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; import OfficeFolderAnchors from "@Front/Api/LeCoffreApi/Notary/OfficeFolderAnchors/OfficeFolderAnchors"; import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import FolderBoxInformation, { EFolderBoxInformationType } from "@Front/Components/DesignSystem/FolderBoxInformation"; import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import QuantityProgressBar from "@Front/Components/DesignSystem/QuantityProgressBar"; import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; import Module from "@Front/Config/Module"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; import Link from "next/link"; import { NextRouter, useRouter } from "next/router"; import { ChangeEvent, useCallback, useEffect, useState } from "react"; import Image from "next/image"; import ValidateAnchoringGif from "@Front/Assets/images/validate_anchoring.gif"; import BasePage from "../../Base"; import classes from "./classes.module.scss"; import ClientSection from "./ClientSection"; import Loader from "@Front/Components/DesignSystem/Loader"; export enum AnchorStatus { "VERIFIED_ON_CHAIN" = "VERIFIED_ON_CHAIN", "ANCHORING" = "ANCHORING", "NOT_ANCHORED" = "NOT_ANCHORED", } type IProps = {}; type IPropsClass = IProps & { router: NextRouter; selectedFolderUid: string; isAnchored: AnchorStatus; isLoading: boolean; selectedFolder: OfficeFolder | null; getAnchoringStatus: () => Promise; getFolderCallback: () => Promise; }; type IState = { isArchivedModalOpen: boolean; inputArchivedDescripton: string; isValidateModalVisible: boolean; hasValidateAnchoring: boolean; isVerifDeleteModalVisible: boolean; isPreventArchiveModalOpen: boolean; }; class FolderInformationClass extends BasePage { public constructor(props: IPropsClass) { super(props); this.state = { isArchivedModalOpen: false, inputArchivedDescripton: "", isValidateModalVisible: false, hasValidateAnchoring: false, isVerifDeleteModalVisible: false, isPreventArchiveModalOpen: false, }; this.openArchivedModal = this.openArchivedModal.bind(this); this.closeArchivedModal = this.closeArchivedModal.bind(this); this.onArchivedModalAccepted = this.onArchivedModalAccepted.bind(this); this.getCompletionNumber = this.getCompletionNumber.bind(this); this.onArchivedDescriptionInputChange = this.onArchivedDescriptionInputChange.bind(this); this.deleteFolder = this.deleteFolder.bind(this); this.closeModal = this.closeModal.bind(this); this.validateAnchoring = this.validateAnchoring.bind(this); this.openValidateModal = this.openValidateModal.bind(this); this.openVerifDeleteFolder = this.openVerifDeleteFolder.bind(this); this.closeVerifDeleteFolder = this.closeVerifDeleteFolder.bind(this); this.closePreventArchiveModal = this.closePreventArchiveModal.bind(this); } // TODO: Message if the user has not created any folder yet // TODO: get the selected folder from the api in componentDidMount public override render(): JSX.Element { const redirectPathEditCollaborators = Module.getInstance() .get() .modules.pages.Folder.pages.EditCollaborators.props.path.replace("[folderUid]", this.props.selectedFolderUid); return ( {!this.props.isLoading && (
{this.props.selectedFolder ? (
Informations du dossier
{this.doesFolderHaveCustomer() && ( )}
{!this.doesFolderHaveCustomer() && ( )}
{this.everyDocumentValidated() && !this.props.isLoading && ( <> {this.props.isAnchored === AnchorStatus.NOT_ANCHORED && ( )} {this.props.isAnchored === AnchorStatus.ANCHORING && ( )} {this.props.isAnchored === AnchorStatus.VERIFIED_ON_CHAIN && ( )} )} {!this.doesFolderHaveCustomer() && ( )}
Souhaitez-vous vraiment archiver le dossier ?
Cette action sera irréversible.
) : (
Informations du dossier
Sélectionnez un dossier
)}
)} {this.props.isLoading && (
)}
Pour valider un dossier, toutes les pièces envoyées par vos clients doivent être validées (vert). Si certains documents sont en attente (orange), alors, veuillez les valider ou les refuser et veillez à ce qu'aucun document ne soit encore en demandé au client (gris)
{!this.state.hasValidateAnchoring && ( Les documents du dossier seront certifiés sur la blockchain. Pensez à bien télécharger l'ensemble des documents du dossier ainsi que le fichier de preuve d'ancrage pour les mettre dans la GED de votre logiciel de rédaction d'actes. )} {this.state.hasValidateAnchoring && (
Vous pouvez désormais télécharger les feuilles d'ancrage et les mettre dans la GED de votre logiciel de rédaction d'acte. Anchoring animation
)}
); } private closePreventArchiveModal() { this.setState({ isPreventArchiveModalOpen: false, }); } public openVerifDeleteFolder() { this.setState({ isVerifDeleteModalVisible: true, }); } public closeVerifDeleteFolder() { this.setState({ isVerifDeleteModalVisible: false, }); } private closeModal() { this.setState({ isValidateModalVisible: false, }); } private openValidateModal() { this.setState({ isValidateModalVisible: true, }); } private async validateAnchoring() { this.setState({ hasValidateAnchoring: true, }); try { const timeoutDelay = 9800; await this.anchorFolder(); setTimeout(() => { this.setState({ isValidateModalVisible: false, }); }, timeoutDelay); setTimeout(() => { this.setState({ hasValidateAnchoring: false, }); }, timeoutDelay + 1000); } catch (e) { this.setState({ isValidateModalVisible: false, hasValidateAnchoring: false, }); console.error(e); } } private async anchorFolder() { if (!this.props.selectedFolder?.uid) return; await OfficeFolderAnchors.getInstance().post(this.props.selectedFolder.uid); this.props.getAnchoringStatus(); } private async downloadAnchoringProof(uid?: string) { if (!uid) return; try { const file: Blob = await OfficeFolderAnchors.getInstance().download(uid); const url = window.URL.createObjectURL(file); const a = document.createElement("a"); a.style.display = "none"; a.href = url; // the filename you want a.download = `anchoring_proof_${this.props.selectedFolder?.folder_number}_${this.props.selectedFolder?.name}.pdf`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); } catch (e) { console.error(e); } } private everyDocumentValidated(): boolean { if (!this.props.selectedFolder?.documents) return false; return ( this.props.selectedFolder?.documents?.length >= 1 && this.props.selectedFolder?.documents.every((document) => document.document_status === EDocumentStatus.VALIDATED) ); } private async deleteFolder() { if (!this.props.selectedFolder?.uid) return; await Folders.getInstance().delete(this.props.selectedFolder.uid); this.props.router.push(Module.getInstance().get().modules.pages.Folder.props.path); } private getCompletionNumber() { const documents = this.props.selectedFolder?.documents; if (!documents) return 0; const totalDocuments = documents.length; const refusedDocuments = documents.filter((document) => document.document_status === EDocumentStatus.REFUSED).length ?? 0; const askedDocuments = documents.filter( (document) => document.document_status === EDocumentStatus.ASKED || document.document_status === EDocumentStatus.DEPOSITED, ).length ?? 0; const depositedDocuments = totalDocuments - askedDocuments - refusedDocuments; const percentage = (depositedDocuments / totalDocuments) * 100; return isNaN(percentage) ? 0 : percentage; } private doesFolderHaveCustomer(): boolean { if (!this.props.selectedFolder?.customers) return false; return this.props.selectedFolder?.customers!.length > 0; } private openArchivedModal(): void { if (this.everyDocumentValidated() && this.props.isAnchored === AnchorStatus.VERIFIED_ON_CHAIN) { this.setState({ isArchivedModalOpen: true }); } else { this.setState({ isPreventArchiveModalOpen: true }); } } private closeArchivedModal(): void { this.setState({ isArchivedModalOpen: false }); } private onArchivedDescriptionInputChange(e: ChangeEvent) { this.setState({ inputArchivedDescripton: e.target.value }); } private async onArchivedModalAccepted() { if (!this.props.selectedFolder) return; await Folders.getInstance().archive(this.props.selectedFolder.uid ?? "", this.state.inputArchivedDescripton); this.closeArchivedModal(); this.props.router.push(Module.getInstance().get().modules.pages.Folder.props.path); } } export default function FolderInformation(props: IProps) { const router = useRouter(); const [isAnchored, setIsAnchored] = useState(AnchorStatus.NOT_ANCHORED); const [isLoading, setIsLoading] = useState(true); const [selectedFolder, setSelectedFolder] = useState(null); let { folderUid } = router.query; folderUid = folderUid as string; const getAnchoringStatus = useCallback(async () => { if (!folderUid) return; try { const anchorStatus = await OfficeFolderAnchors.getInstance().getByUid(folderUid as string); setIsAnchored(anchorStatus.status === "VERIFIED_ON_CHAIN" ? AnchorStatus.VERIFIED_ON_CHAIN : AnchorStatus.ANCHORING); } catch (e) { setIsAnchored(AnchorStatus.NOT_ANCHORED); } }, [folderUid]); const getFolder = useCallback(async () => { if (!folderUid) return; setIsLoading(true); const query = { q: { deed: { include: { deed_type: true } }, office: true, customers: { include: { contact: true, documents: { include: { folder: true, document_type: true, files: true, }, }, }, }, documents: { include: { depositor: { include: { contact: true, }, }, }, }, folder_anchor: true, }, }; const folder = await Folders.getInstance().getByUid(folderUid as string, query); if (folder) { setSelectedFolder(folder); getAnchoringStatus(); } setIsLoading(false); }, [folderUid, getAnchoringStatus]); useEffect(() => { setIsLoading(true); getFolder(); }, [getFolder]); return ( ); }