390 lines
12 KiB
TypeScript
390 lines
12 KiB
TypeScript
"use client";
|
|
|
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
|
|
import Customer, { Document, DocumentType } from "le-coffre-resources/dist/Customer";
|
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
import { DocumentNotary, OfficeFolder as OfficeFolderNotary } from "le-coffre-resources/dist/Notary";
|
|
|
|
import classes from "./classes.module.scss";
|
|
import { useRouter } from "next/router";
|
|
import JwtService, { ICustomerJwtPayload } from "@Front/Services/JwtService/JwtService";
|
|
|
|
import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
|
|
import DefaultCustomerDashboard from "@Front/Components/LayoutTemplates/DefaultCustomerDashboard";
|
|
|
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
|
import DepositDocumentComponent from "./DepositDocumentComponent";
|
|
import Module from "@Front/Config/Module";
|
|
import Separator, { ESeperatorColor, ESeperatorDirection } from "@Front/Components/DesignSystem/Separator";
|
|
import NotificationBox from "@Front/Components/DesignSystem/NotificationBox";
|
|
import ContactBox from "./ContactBox";
|
|
import { EDocumentNotaryStatus } from "le-coffre-resources/dist/Notary/DocumentNotary";
|
|
import DepositOtherDocument from "@Front/Components/DesignSystem/DepositOtherDocument";
|
|
|
|
import Modal from "@Front/Components/DesignSystem/Modal";
|
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
|
|
|
import AuthModal from "src/sdk/AuthModal";
|
|
|
|
import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
|
|
import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService";
|
|
import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService";
|
|
import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
|
|
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
|
|
|
type IProps = {};
|
|
|
|
export default function ClientDashboard(props: IProps) {
|
|
const router = useRouter();
|
|
let { folderUid, profileUid } = router.query;
|
|
const [documents, setDocuments] = useState<Document[] | null>(null);
|
|
|
|
const [customer, setCustomer] = useState<Customer | null>(null);
|
|
const [folder, setFolder] = useState<OfficeFolderNotary | null>(null);
|
|
|
|
const [documentsNotary, setDocumentsNotary] = useState<DocumentNotary[]>([]);
|
|
const [isAddDocumentModalVisible, setIsAddDocumentModalVisible] = useState<boolean>(false);
|
|
|
|
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
|
|
const [isSmsModalOpen, setIsSmsModalOpen] = useState(false);
|
|
const [smsCode, setSmsCode] = useState("");
|
|
const [smsError, setSmsError] = useState("");
|
|
|
|
const verifySmsCode = useCallback(() => {
|
|
if (smsCode === "1234") {
|
|
setIsSmsModalOpen(false);
|
|
} else {
|
|
setSmsError("Code incorrect. Le code valide est 1234.");
|
|
}
|
|
}, [smsCode]);
|
|
|
|
useEffect(() => {
|
|
const handleKeyPress = (e: KeyboardEvent) => {
|
|
if (e.key === "Enter" && isSmsModalOpen) {
|
|
verifySmsCode();
|
|
}
|
|
};
|
|
|
|
window.addEventListener("keypress", handleKeyPress);
|
|
return () => {
|
|
window.removeEventListener("keypress", handleKeyPress);
|
|
};
|
|
}, [isSmsModalOpen, smsCode, verifySmsCode]);
|
|
|
|
const fetchFolderAndCustomer = useCallback(async () => {
|
|
let jwt: ICustomerJwtPayload | undefined;
|
|
if (typeof document !== "undefined") {
|
|
jwt = JwtService.getInstance().decodeCustomerJwt();
|
|
}
|
|
|
|
// TODO: review
|
|
LoaderService.getInstance().show();
|
|
const { folder, customer } = await new Promise<any>((resolve) => {
|
|
FolderService.getFolderByUid(folderUid as string).then((process: any) => {
|
|
if (process) {
|
|
const folder: any = process.processData;
|
|
|
|
const customers: any[] = folder.customers;
|
|
const customer: any = customers.find((customer: any) => customer.uid === profileUid as string);
|
|
if (customer) {
|
|
resolve({ folder: folder, customer });
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
setCustomer(customer);
|
|
setFolder(folder);
|
|
|
|
setIsAuthModalOpen(true);
|
|
LoaderService.getInstance().hide();
|
|
|
|
return { folder, customer };
|
|
|
|
/*
|
|
const folder = await Folders.getInstance().getByUid(folderUid as string, {
|
|
q: {
|
|
office: true,
|
|
customers: true,
|
|
notes: {
|
|
include: {
|
|
customer: true,
|
|
},
|
|
},
|
|
stakeholders: {
|
|
include: {
|
|
contact: true,
|
|
office_role: true,
|
|
},
|
|
},
|
|
deed: {
|
|
include: {
|
|
deed_type: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const customer = folder?.customers?.find((customer) => customer.contact?.email === jwt?.email);
|
|
if (!customer) throw new Error("Customer not found");
|
|
|
|
setFolder(folder);
|
|
setCustomer(customer);
|
|
|
|
return { folder, customer };
|
|
*/
|
|
}, [folderUid]);
|
|
|
|
const fetchDocuments = useCallback(
|
|
async (customerUid: string | undefined) => {
|
|
LoaderService.getInstance().show();
|
|
return new Promise<void>((resolve: () => void) => {
|
|
DocumentService.getDocuments().then(async (processes: any[]) => {
|
|
if (processes.length > 0) {
|
|
let documents: any[] = processes.map((process: any) => process.processData);
|
|
|
|
// FilterBy folder.uid & depositor.uid
|
|
documents = documents.filter((document: any) => document.folder.uid === folderUid && document.depositor && document.depositor.uid === customerUid);
|
|
|
|
for (const document of documents) {
|
|
if (document.document_type) {
|
|
document.document_type = (await DocumentTypeService.getDocumentTypeByUid(document.document_type.uid)).processData;
|
|
}
|
|
|
|
if (document.files && document.files.length > 0) {
|
|
const files: any[] = [];
|
|
for (const file of document.files) {
|
|
files.push((await FileService.getFileByUid(file.uid)).processData);
|
|
}
|
|
document.files = files;
|
|
}
|
|
}
|
|
|
|
setDocuments(documents);
|
|
}
|
|
LoaderService.getInstance().hide();
|
|
resolve();
|
|
});
|
|
});
|
|
},
|
|
[folderUid],
|
|
);
|
|
|
|
useEffect(() => {
|
|
fetchFolderAndCustomer().then(({ customer }) => fetchDocuments(customer.uid));
|
|
}, [fetchDocuments, fetchFolderAndCustomer]);
|
|
|
|
useEffect(() => {
|
|
const customerUid = customer?.uid;
|
|
if (!folderUid || !customerUid) return;
|
|
|
|
LoaderService.getInstance().show();
|
|
DocumentService.getDocuments().then(async (processes: any[]) => {
|
|
if (processes.length > 0) {
|
|
let documents: any[] = processes.map((process: any) => process.processData);
|
|
|
|
// FilterBy folder.uid & customer.uid
|
|
documents = documents.filter((document: any) => document.folder.uid === folderUid && document.customer && document.customer.uid === customerUid);
|
|
|
|
for (const document of documents) {
|
|
if (document.files && document.files.length > 0) {
|
|
const files: any[] = [];
|
|
for (const file of document.files) {
|
|
files.push((await FileService.getFileByUid(file.uid)).processData);
|
|
}
|
|
document.files = files;
|
|
}
|
|
}
|
|
|
|
setDocumentsNotary(documents);
|
|
LoaderService.getInstance().hide();
|
|
}
|
|
});
|
|
}, [folderUid, customer?.uid]);
|
|
|
|
const documentsNotaryNotRead = useMemo(
|
|
() => documentsNotary.filter((doc) => doc.document_status === EDocumentNotaryStatus.SENT),
|
|
[documentsNotary],
|
|
);
|
|
|
|
const onCloseModalAddDocument = useCallback(() => {
|
|
setIsAddDocumentModalVisible(false);
|
|
fetchFolderAndCustomer();
|
|
}, [fetchFolderAndCustomer]);
|
|
|
|
const onOpenModalAddDocument = useCallback(() => {
|
|
setIsAddDocumentModalVisible(true);
|
|
}, []);
|
|
|
|
const renderBox = useCallback(() => {
|
|
return (
|
|
<DepositOtherDocument
|
|
folder_uid={folderUid!}
|
|
customer_uid={customer!.uid!}
|
|
open={isAddDocumentModalVisible}
|
|
onClose={onCloseModalAddDocument}
|
|
document={Document.hydrate<Document>({
|
|
document_type: DocumentType.hydrate<DocumentType>({
|
|
name: "Autres documents",
|
|
office: folder!.office!,
|
|
}),
|
|
})}
|
|
/>
|
|
);
|
|
}, [customer, folderUid, isAddDocumentModalVisible, onCloseModalAddDocument, folder]);
|
|
|
|
return (
|
|
<DefaultCustomerDashboard>
|
|
<div className={classes["root"]}>
|
|
<div className={classes["top"]}>
|
|
<div className={classes["folder-info-container"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
|
Dossier {folder?.folder_number} - {folder?.name}
|
|
</Typography>
|
|
<Typography typo={ETypo.TITLE_H4} color={ETypoColor.TEXT_PRIMARY}>
|
|
Bonjour {customer?.contact?.first_name.concat(" ", customer?.contact?.last_name)}
|
|
</Typography>
|
|
<Tag color={ETagColor.INFO} label={folder?.deed?.deed_type?.name ?? ""} />
|
|
<div className={classes["office-container"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
|
Office
|
|
</Typography>
|
|
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_ACCENT}>
|
|
{folder?.office?.name}
|
|
</Typography>
|
|
</div>
|
|
</div>
|
|
<Separator
|
|
className={classes["desktop-separator"]}
|
|
direction={ESeperatorDirection.VERTICAL}
|
|
size={142}
|
|
color={ESeperatorColor.LIGHT}
|
|
/>
|
|
{(documentsNotaryNotRead?.length ?? 0) > 0 && (
|
|
<NotificationBox
|
|
text={`${documentsNotaryNotRead?.length} Nouveaux document(s) envoyé(s) par votre notaire`}
|
|
button={{
|
|
children: "Consulter les documents",
|
|
variant: EButtonVariant.SECONDARY,
|
|
styletype: EButtonstyletype.OUTLINED,
|
|
onClick: () =>
|
|
router.push(
|
|
Module.getInstance()
|
|
.get()
|
|
.modules.pages.ClientDashboard.pages.ReceiveDocuments.props.path.replace(
|
|
"[folderUid]",
|
|
folderUid as string,
|
|
),
|
|
),
|
|
}}
|
|
read={false}
|
|
/>
|
|
)}
|
|
{(documentsNotaryNotRead?.length ?? 0) === 0 && (documentsNotary?.length ?? 0) > 0 && (
|
|
<NotificationBox
|
|
text={`Consultez les documents envoyés par votre notaire`}
|
|
button={{
|
|
children: "Consulter les documents",
|
|
variant: EButtonVariant.SECONDARY,
|
|
styletype: EButtonstyletype.OUTLINED,
|
|
onClick: () =>
|
|
router.push(
|
|
Module.getInstance()
|
|
.get()
|
|
.modules.pages.ClientDashboard.pages.ReceiveDocuments.props.path.replace(
|
|
"[folderUid]",
|
|
folderUid as string,
|
|
),
|
|
),
|
|
}}
|
|
read={true}
|
|
/>
|
|
)}
|
|
</div>
|
|
|
|
{customer && folder && <ContactBox customer={customer} folder={folder} />}
|
|
|
|
<div className={classes["documents"]}>
|
|
<Typography typo={ETypo.TEXT_LG_BOLD} color={ETypoColor.TABLE_COLUMN_CONTRAST}>
|
|
Documents à envoyer
|
|
</Typography>
|
|
<div className={classes["content"]}>
|
|
{documents?.map((document) => (
|
|
<DepositDocumentComponent
|
|
key={document.uid}
|
|
document={document}
|
|
onChange={() => fetchDocuments(customer?.uid)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<Typography typo={ETypo.TITLE_H3}>Documents supplémentaires (facultatif)</Typography>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
|
|
Vous souhaitez envoyer d'autres documents à votre notaire ?
|
|
</Typography>
|
|
<Button
|
|
variant={EButtonVariant.PRIMARY}
|
|
styletype={EButtonstyletype.OUTLINED}
|
|
className={classes["button"]}
|
|
onClick={onOpenModalAddDocument}>
|
|
Ajouter d'autres documents
|
|
</Button>
|
|
{isAddDocumentModalVisible && renderBox()}
|
|
|
|
{isAuthModalOpen && <AuthModal
|
|
isOpen={isAuthModalOpen}
|
|
onClose={() => {
|
|
setIsAuthModalOpen(false);
|
|
setIsSmsModalOpen(true);
|
|
}}
|
|
/>}
|
|
|
|
{isSmsModalOpen && (
|
|
<Modal
|
|
isOpen={isSmsModalOpen}
|
|
onClose={() => setIsSmsModalOpen(false)}
|
|
title="Vérification SMS"
|
|
>
|
|
<div className={classes["sms-modal-content"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_PRIMARY}>
|
|
Veuillez saisir le code à 4 chiffres que vous avez reçu par SMS
|
|
</Typography>
|
|
|
|
<TextField
|
|
name="smsCode"
|
|
placeholder="Code SMS à 4 chiffres"
|
|
value={smsCode}
|
|
onChange={(e) => {
|
|
const value = e.target.value;
|
|
// Only allow digits
|
|
if (value === "" || /^\d+$/.test(value)) {
|
|
setSmsCode(value);
|
|
setSmsError("");
|
|
}
|
|
}}
|
|
/>
|
|
|
|
{smsError && (
|
|
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.TEXT_ACCENT}>
|
|
{smsError}
|
|
</Typography>
|
|
)}
|
|
|
|
<div style={{ marginTop: "20px" }}>
|
|
<Button
|
|
variant={EButtonVariant.PRIMARY}
|
|
onClick={verifySmsCode}
|
|
>
|
|
Vérifier
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Modal>
|
|
)}
|
|
</div>
|
|
</DefaultCustomerDashboard>
|
|
);
|
|
}
|