Preprod (#193)
This commit is contained in:
commit
1640876eff
@ -35,4 +35,16 @@ export default class DocumentsNotary extends BaseCustomer {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public async getByUid(uid: string, q?: any): Promise<DocumentNotary> {
|
||||
const url = new URL(this.baseURl.concat(`/${uid}`));
|
||||
const query = { q };
|
||||
Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
|
||||
try {
|
||||
return await this.getRequest<DocumentNotary>(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,4 +90,14 @@ export default class Files extends BaseCustomer {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public async download(uid: string): Promise<any> {
|
||||
const url = new URL(this.baseURl.concat(`/download/${uid}`));
|
||||
try {
|
||||
return await this.getRequest<any>(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,12 @@ export interface IGetDocumentRemindersparams {
|
||||
where?: {};
|
||||
include?: {};
|
||||
orderBy?: {};
|
||||
skip?: number;
|
||||
take?: number;
|
||||
}
|
||||
|
||||
export interface IGetDocumentRemindersCountresponse {
|
||||
count: number;
|
||||
}
|
||||
|
||||
// TODO Type getbyuid query params
|
||||
@ -38,4 +44,14 @@ export default class DocumentReminders extends BaseNotary {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public count = async (): Promise<IGetDocumentRemindersCountresponse> => {
|
||||
const url = new URL(this.baseURl.concat("/count"));
|
||||
try {
|
||||
return await this.getRequest<IGetDocumentRemindersCountresponse>(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
|
||||
onClick={this.addDocument}>
|
||||
<Typography
|
||||
typo={ETypo.TEXT_MD_SEMIBOLD}
|
||||
color={ETypoColor.COLOR_SECONDARY_500}
|
||||
color={ETypoColor.COLOR_PRIMARY_500}
|
||||
className={classes["add-document"]}>
|
||||
Ajouter un document <Image src={PlusIcon} alt="Plus icon" />
|
||||
</Typography>
|
||||
@ -242,6 +242,7 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
|
||||
});
|
||||
|
||||
this.props.onClose!();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
private shortName(name: string): string {
|
||||
|
@ -46,6 +46,10 @@
|
||||
min-width: 85vw;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.fullheight {
|
||||
min-height: 75vh;
|
||||
}
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
|
@ -17,10 +17,11 @@ type IProps = {
|
||||
secondButton?: IButtonProps;
|
||||
fullwidth?: boolean;
|
||||
fullscreen?: boolean;
|
||||
fullheight?: boolean;
|
||||
};
|
||||
|
||||
export default function Modal(props: IProps) {
|
||||
const { isOpen, onClose, children, className, title, firstButton, secondButton, fullwidth, fullscreen } = props;
|
||||
const { isOpen, onClose, children, className, title, firstButton, secondButton, fullwidth, fullscreen, fullheight } = props;
|
||||
|
||||
if (!isOpen) return null;
|
||||
return (
|
||||
@ -33,6 +34,7 @@ export default function Modal(props: IProps) {
|
||||
className,
|
||||
fullwidth && classes["fullwidth"],
|
||||
fullscreen && classes["fullscreen"],
|
||||
fullheight && classes["fullheight"],
|
||||
)}>
|
||||
<div className={classes["header"]}>
|
||||
{title && <Typography typo={ETypo.TITLE_H4}> {title}</Typography>}
|
||||
|
@ -53,7 +53,7 @@ export default function MuiTable(props: IProps) {
|
||||
<InfiniteScroll orientation="vertical" onNext={props.onNext} offset={0}>
|
||||
<TableContainer
|
||||
className={classes["root"]}
|
||||
sx={{ maxHeight: "80vh", overflowY: "auto", overflowX: "hidden", backgroundColor: "var(--table-background-default)" }}>
|
||||
sx={{ height: "45vh", overflowY: "auto", overflowX: "hidden", backgroundColor: "var(--table-background-default)" }}>
|
||||
<Table aria-label="simple table" sx={{ border: "0" }}>
|
||||
<TableHead
|
||||
sx={{
|
||||
@ -93,8 +93,7 @@ export default function MuiTable(props: IProps) {
|
||||
<Typography
|
||||
className={classes["content"]}
|
||||
typo={ETypo.TEXT_MD_REGULAR}
|
||||
color={ETypoColor.COLOR_NEUTRAL_900}
|
||||
>
|
||||
color={ETypoColor.COLOR_NEUTRAL_900}>
|
||||
{cell.value && typeof cell.value === "object" && "content" in cell.value
|
||||
? cell.value.content
|
||||
: cell.value}
|
||||
|
@ -17,6 +17,10 @@
|
||||
text-decoration: underline !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: var(--color-primary-500);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $screen-s) {
|
||||
|
@ -72,18 +72,42 @@ export default function DepositDocumentComponent(props: IProps) {
|
||||
{document.document_type?.name ?? "_"}
|
||||
</Typography>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
|
||||
Demandé le: {document.created_at ? new Date(document.created_at).toLocaleDateString() : "_"}
|
||||
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 : {document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_"}
|
||||
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
|
||||
@ -105,13 +129,15 @@ export default function DepositDocumentComponent(props: IProps) {
|
||||
</div>
|
||||
</Confirm>
|
||||
|
||||
<DragAndDrop
|
||||
title={"Glisser-déposer ou"}
|
||||
description={document.document_type?.public_description ?? undefined}
|
||||
defaultFiles={defaultFiles}
|
||||
onAddFile={addFile}
|
||||
onDelete={deleteFile}
|
||||
/>
|
||||
{document.document_status !== "VALIDATED" && (
|
||||
<DragAndDrop
|
||||
title={"Glisser-déposer ou"}
|
||||
description={document.document_type?.public_description ?? undefined}
|
||||
defaultFiles={defaultFiles}
|
||||
onAddFile={addFile}
|
||||
onDelete={deleteFile}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||
import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
|
||||
import Module from "@Front/Config/Module";
|
||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
||||
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
|
||||
import { ArrowDownTrayIcon, EyeIcon } from "@heroicons/react/24/outline";
|
||||
import { saveAs } from "file-saver";
|
||||
import JSZip from "jszip";
|
||||
import DocumentNotary from "le-coffre-resources/dist/Notary/DocumentNotary";
|
||||
@ -17,6 +17,7 @@ import { useRouter } from "next/router";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import Link from "next/link";
|
||||
|
||||
const header: readonly IHead[] = [
|
||||
{
|
||||
@ -100,7 +101,7 @@ export default function ReceivedDocuments() {
|
||||
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}>
|
||||
Un document vous a été envoyé
|
||||
</Typography>
|
||||
<Table className={classes["table"]} header={header} rows={buildRows(documentsNotary, onDownload)} />
|
||||
<Table className={classes["table"]} header={header} rows={buildRows(documentsNotary, folderUid!, onDownload)} />
|
||||
<Button
|
||||
variant={EButtonVariant.PRIMARY}
|
||||
size={EButtonSize.LG}
|
||||
@ -114,12 +115,34 @@ export default function ReceivedDocuments() {
|
||||
);
|
||||
}
|
||||
|
||||
function buildRows(documentsNotary: DocumentNotary[], onDownloadFileNotary: (doc: DocumentNotary) => void): IRowProps[] {
|
||||
function buildRows(
|
||||
documentsNotary: DocumentNotary[],
|
||||
folderUid: string | string[],
|
||||
onDownloadFileNotary: (doc: DocumentNotary) => void,
|
||||
): IRowProps[] {
|
||||
console.log(documentsNotary);
|
||||
console.log(folderUid);
|
||||
|
||||
return documentsNotary.map((documentNotary) => ({
|
||||
key: documentNotary.uid ?? "",
|
||||
name: formatName(documentNotary.files?.[0]?.file_name?.split(".")?.[0] ?? "") || "_",
|
||||
sentAt: new Date(documentNotary.created_at!).toLocaleDateString(),
|
||||
actions: <IconButton onClick={() => onDownloadFileNotary(documentNotary)} icon={<ArrowDownTrayIcon />} />,
|
||||
// actions: <IconButton onClick={() => onDownloadFileNotary(documentNotary)} icon={<ArrowDownTrayIcon />} />,
|
||||
actions: {
|
||||
sx: { width: 76 },
|
||||
content: (
|
||||
<div className={classes["actions"]}>
|
||||
<Link
|
||||
href={Module.getInstance()
|
||||
.get()
|
||||
.modules.pages.ClientDashboard.pages.ViewDocuments.props.path.replace("[folderUid]", folderUid as string)
|
||||
.replace("[documentUid]", documentNotary.uid ?? "")}>
|
||||
<IconButton icon={<EyeIcon />} />
|
||||
</Link>
|
||||
<IconButton onClick={() => onDownloadFileNotary(documentNotary)} icon={<ArrowDownTrayIcon />} />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,77 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
.title {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.document-container {
|
||||
margin-top: 32px;
|
||||
gap: 64px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.arrow-container {
|
||||
cursor: pointer;
|
||||
|
||||
&[data-disabled="true"] {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.file-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
min-height: 600px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.unsuported-format {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin: auto;
|
||||
.ocr-container {
|
||||
margin-top: 42px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-top: 24px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
justify-content: center;
|
||||
margin-top: 32px;
|
||||
@media (max-width: $screen-s) {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.refuse-document-container {
|
||||
.refuse-text {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.validate-document-container {
|
||||
.document-validating-container {
|
||||
.validate-gif {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
import LeftArrowIcon from "@Assets/Icons/left-arrow.svg";
|
||||
import RightArrowIcon from "@Assets/Icons/right-arrow.svg";
|
||||
import Button from "@Front/Components/DesignSystem/Button";
|
||||
import FilePreview from "@Front/Components/DesignSystem/FilePreview";
|
||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
import { DocumentNotary, File } from "le-coffre-resources/dist/Notary";
|
||||
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 DocumentsNotary from "@Front/Api/LeCoffreApi/Customer/DocumentsNotary/DocumentsNotary";
|
||||
import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
|
||||
import FilesNotary from "@Front/Api/LeCoffreApi/Customer/FilesNotary/Files";
|
||||
|
||||
type IProps = {};
|
||||
type IPropsClass = {
|
||||
documentUid: string;
|
||||
router: NextRouter;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
isRefuseModalVisible: boolean;
|
||||
isValidateModalVisible: boolean;
|
||||
refuseText: string;
|
||||
selectedFileIndex: number;
|
||||
selectedFile: File | null;
|
||||
documentNotary: DocumentNotary | null;
|
||||
fileBlob: Blob | null;
|
||||
isLoading: boolean;
|
||||
};
|
||||
|
||||
class ViewDocumentsNotaryClass extends BasePage<IPropsClass, IState> {
|
||||
public constructor(props: IPropsClass) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isValidateModalVisible: false,
|
||||
isRefuseModalVisible: false,
|
||||
refuseText: "",
|
||||
selectedFileIndex: 0,
|
||||
selectedFile: null,
|
||||
documentNotary: null,
|
||||
fileBlob: null,
|
||||
isLoading: true,
|
||||
};
|
||||
|
||||
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.downloadFile = this.downloadFile.bind(this);
|
||||
}
|
||||
|
||||
public override render(): JSX.Element | null {
|
||||
return (
|
||||
<DefaultTemplate title={"Visualiser le document"} hasBackArrow>
|
||||
{this.state.documentNotary && this.state.documentNotary.files && this.state.selectedFile && !this.state.isLoading && (
|
||||
<div className={classes["root"]}>
|
||||
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.COLOR_GENERIC_BLACK} className={classes["subtitle"]}>
|
||||
{this.state.documentNotary.name}
|
||||
</Typography>
|
||||
<div className={classes["document-container"]}>
|
||||
{this.state.documentNotary.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"]}>
|
||||
{this.state.selectedFile.mimetype !== "text/csv" &&
|
||||
this.state.selectedFile.mimetype !==
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" &&
|
||||
this.state.selectedFile.mimetype !== "application/vnd.ms-excel" && (
|
||||
<FilePreview
|
||||
href={this.state.fileBlob ? URL.createObjectURL(this.state.fileBlob) : ""}
|
||||
fileName={this.state.selectedFile.file_name}
|
||||
key={this.state.selectedFile.uid}
|
||||
/>
|
||||
)}
|
||||
{this.state.selectedFile.mimetype === "text/csv" && (
|
||||
<div className={classes["unsuported-format"]}>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_GENERIC_BLACK}>
|
||||
L'affichage de ce format de fichier n'est pas supporté.
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
{this.state.selectedFile.mimetype ===
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" && (
|
||||
<div className={classes["unsuported-format"]}>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_GENERIC_BLACK}>
|
||||
L'affichage de ce format de fichier n'est pas supporté.
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
{this.state.selectedFile.mimetype === "application/vnd.ms-excel" && (
|
||||
<div className={classes["unsuported-format"]}>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_GENERIC_BLACK}>
|
||||
L'affichage de ce format de fichier n'est pas supporté.
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{this.state.documentNotary.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 === "Document d'identité" && (
|
||||
<div className={classes["ocr-container"]}>
|
||||
<OcrResult percentage={this.state.validatedPercentage} />
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
<div className={classes["buttons-container"]}>
|
||||
<Button onClick={this.downloadFile}>Télécharger</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{(!this.state.selectedFile || !this.state.documentNotary) && !this.state.isLoading && (
|
||||
<div className={classes["root"]}>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_GENERIC_BLACK} className={classes["refuse-text"]}>
|
||||
Document non trouvé
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
</DefaultTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
override async componentDidMount() {
|
||||
try {
|
||||
const documentNotary = await DocumentsNotary.getInstance().getByUid(this.props.documentUid, {
|
||||
files: true,
|
||||
folder: true,
|
||||
depositor: true,
|
||||
});
|
||||
console.log(documentNotary);
|
||||
|
||||
this.setState(
|
||||
{
|
||||
documentNotary,
|
||||
selectedFileIndex: 0,
|
||||
selectedFile: documentNotary.files![0]!,
|
||||
isLoading: false,
|
||||
},
|
||||
() => {
|
||||
this.getFilePreview();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async getFilePreview(): Promise<void> {
|
||||
try {
|
||||
const fileBlob: Blob = await FilesNotary.getInstance().download(this.state.selectedFile?.uid as string, this.props.documentUid);
|
||||
|
||||
this.setState({
|
||||
fileBlob,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private downloadFile() {
|
||||
if (!this.state.fileBlob) return;
|
||||
const url = window.URL.createObjectURL(this.state.fileBlob);
|
||||
const a = document.createElement("a");
|
||||
a.style.display = "none";
|
||||
a.href = url;
|
||||
// the filename you want
|
||||
a.download = this.state.selectedFile?.file_name as string;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
private goToPrevious() {
|
||||
const index = this.state.selectedFileIndex - 1;
|
||||
if (this.hasPrevious()) {
|
||||
this.setState(
|
||||
{
|
||||
selectedFile: this.state.documentNotary!.files![index]!,
|
||||
selectedFileIndex: index,
|
||||
fileBlob: null,
|
||||
},
|
||||
() => {
|
||||
this.getFilePreview();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private goToNext() {
|
||||
if (this.hasNext()) {
|
||||
const index = this.state.selectedFileIndex + 1;
|
||||
this.setState(
|
||||
{
|
||||
selectedFile: this.state.documentNotary!.files![index]!,
|
||||
selectedFileIndex: index,
|
||||
fileBlob: null,
|
||||
},
|
||||
() => {
|
||||
this.getFilePreview();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private hasPrevious() {
|
||||
const index = this.state.selectedFileIndex - 1;
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
private hasNext() {
|
||||
const index = this.state.selectedFileIndex + 1;
|
||||
return index < this.state.documentNotary!.files!.length;
|
||||
}
|
||||
}
|
||||
|
||||
export default function ViewDocumentsNotary(props: IProps) {
|
||||
const router = useRouter();
|
||||
let { folderUid, documentUid } = router.query;
|
||||
documentUid = documentUid as string;
|
||||
folderUid = folderUid as string;
|
||||
return <ViewDocumentsNotaryClass {...props} documentUid={documentUid} router={router} />;
|
||||
}
|
@ -3,7 +3,7 @@ import Documents, { IGetDocumentsparams } from "@Front/Api/LeCoffreApi/Customer/
|
||||
|
||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
|
||||
import Customer, { Document } from "le-coffre-resources/dist/Customer";
|
||||
import Customer, { Document, DocumentType } from "le-coffre-resources/dist/Customer";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { DocumentNotary, type OfficeFolder as OfficeFolderNotary } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@ -12,20 +12,18 @@ import { useRouter } from "next/router";
|
||||
import JwtService, { ICustomerJwtPayload } from "@Front/Services/JwtService/JwtService";
|
||||
import Folders from "@Front/Api/LeCoffreApi/Customer/Folders/Folders";
|
||||
|
||||
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 DocumentsNotary from "@Front/Api/LeCoffreApi/Customer/DocumentsNotary/DocumentsNotary";
|
||||
import { EDocumentNotaryStatus } from "le-coffre-resources/dist/Notary/DocumentNotary";
|
||||
// import DepositOtherDocument from "@Front/Components/DesignSystem/DepositOtherDocument";
|
||||
|
||||
import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
|
||||
import DefaultCustomerDashboard from "@Front/Components/LayoutTemplates/DefaultCustomerDashboard";
|
||||
|
||||
import { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
|
||||
import DepositDocumentComponent from "./DepositDocumentComponent";
|
||||
import DepositOtherDocument from "@Front/Components/DesignSystem/DepositOtherDocument";
|
||||
|
||||
type IProps = {};
|
||||
|
||||
@ -37,7 +35,7 @@ export default function ClientDashboard(props: IProps) {
|
||||
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 [isAddDocumentModalVisible, setIsAddDocumentModalVisible] = useState<boolean>(false);
|
||||
|
||||
const fetchFolderAndCustomer = useCallback(async () => {
|
||||
let jwt: ICustomerJwtPayload | undefined;
|
||||
@ -122,33 +120,31 @@ export default function ClientDashboard(props: IProps) {
|
||||
[documentsNotary],
|
||||
);
|
||||
|
||||
// const onCloseModalAddDocument = useCallback(() => {
|
||||
// setIsAddDocumentModalVisible(false);
|
||||
// fetchFolderAndCustomer();
|
||||
// }, [fetchFolderAndCustomer]);
|
||||
const onCloseModalAddDocument = useCallback(() => {
|
||||
setIsAddDocumentModalVisible(false);
|
||||
fetchFolderAndCustomer();
|
||||
}, [fetchFolderAndCustomer]);
|
||||
|
||||
// const onOpenModalAddDocument = useCallback(() => {
|
||||
// setIsAddDocumentModalVisible(true);
|
||||
// }, []);
|
||||
const onOpenModalAddDocument = useCallback(() => {
|
||||
setIsAddDocumentModalVisible(true);
|
||||
}, []);
|
||||
|
||||
// const renderBox = useCallback(() => {
|
||||
// console.log(folder!.office!.uid);
|
||||
|
||||
// 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]);
|
||||
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]);
|
||||
|
||||
return (
|
||||
<DefaultCustomerDashboard>
|
||||
@ -236,18 +232,18 @@ export default function ClientDashboard(props: IProps) {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/*<Typography typo={ETypo.TITLE_H3}>Documents supplémentaires (facultatif)</Typography>*/}
|
||||
{/*<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
|
||||
<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
|
||||
</Typography>
|
||||
<Button
|
||||
variant={EButtonVariant.PRIMARY}
|
||||
styletype={EButtonstyletype.OUTLINED}
|
||||
className={classes["button"]}
|
||||
onClick={onOpenModalAddDocument}>
|
||||
Ajouter d'autres documents
|
||||
</Button>
|
||||
{isAddDocumentModalVisible && renderBox()} */}
|
||||
{isAddDocumentModalVisible && renderBox()}
|
||||
</div>
|
||||
</DefaultCustomerDashboard>
|
||||
);
|
||||
|
@ -56,7 +56,6 @@ export default function ParameterDocuments(props: IProps) {
|
||||
}, []);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setFormattedOptions([]);
|
||||
setSelectedDocuments([]);
|
||||
setAddOrEditDocument("edit");
|
||||
setVisibleDescription("");
|
||||
@ -83,6 +82,7 @@ export default function ParameterDocuments(props: IProps) {
|
||||
|
||||
//await this.loadData();
|
||||
handleClose();
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -98,6 +98,7 @@ export default function ParameterDocuments(props: IProps) {
|
||||
|
||||
//await this.loadData();
|
||||
handleClose();
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -122,7 +123,8 @@ export default function ParameterDocuments(props: IProps) {
|
||||
onClose={handleClose}
|
||||
firstButton={{ children: "Annuler", onClick: handleClose }}
|
||||
secondButton={{ children: "Ajouter", onClick: addDocument }}
|
||||
title={"Ajouter un document"}>
|
||||
title={"Ajouter un document"}
|
||||
fullheight>
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["radiobox-container"]}>
|
||||
<RadioBox
|
||||
|
@ -8,11 +8,11 @@
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-xl, 32px);
|
||||
|
||||
.table{
|
||||
.table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.customer-filter{
|
||||
.customer-filter {
|
||||
width: 472px;
|
||||
}
|
||||
|
||||
@ -23,4 +23,74 @@
|
||||
@media screen and (max-width: $screen-s) {
|
||||
padding: var(--spacing-2);
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px; /* Adds gap between each button */
|
||||
|
||||
.active {
|
||||
background-color: var(--color-primary-800); /* Dark blue for active button */
|
||||
border-color: var(--color-primary-800); /* Dark blue border for active button */
|
||||
color: white; /* White text for active button */
|
||||
}
|
||||
|
||||
button {
|
||||
width: 50px; /* Fixed width */
|
||||
height: 50px; /* Fixed height */
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
// .pagination button {
|
||||
// width: 40px;
|
||||
// height: 40px;
|
||||
// background-color: var(--color-primary-500); /* Light blue background for inactive buttons */
|
||||
// border: 1px solid var(--color-primary-500); /* Light blue border */
|
||||
// color: #ffffff; /* Text color for inactive buttons */
|
||||
// padding: 8px 16px;
|
||||
// font-size: 14px;
|
||||
// cursor: pointer;
|
||||
// transition: background-color 0.3s;
|
||||
|
||||
// &:hover {
|
||||
// background-color: #b2ebf2; /* Lighter blue on hover */
|
||||
// }
|
||||
|
||||
// &.active {
|
||||
// background-color: var(--color-primary-800); /* Dark blue for active button */
|
||||
// border-color: var(--color-primary-800); /* Dark blue border for active button */
|
||||
// color: white; /* White text for active button */
|
||||
// }
|
||||
|
||||
// &.disabled {
|
||||
// background-color: #f1f1f1; /* Light gray background for disabled buttons */
|
||||
// color: #9e9e9e; /* Gray text for disabled buttons */
|
||||
// cursor: not-allowed;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .pagination button.prev,
|
||||
// .pagination button.next {
|
||||
// background-color: var(--color-primary-50); /* Dark teal background for Prev/Next buttons */
|
||||
// color: var(--color-primary-500); /* White text for Prev/Next buttons */
|
||||
// padding: 5px 10px;
|
||||
// border-radius: 8px; /* Make the Prev/Next buttons circular */
|
||||
// font-size: 14px;
|
||||
// border: none; /* Remove the border for a cleaner look */
|
||||
// }
|
||||
|
||||
// .pagination button.prev:hover,
|
||||
// .pagination button.next:hover {
|
||||
// border-color: var(--button-contained-neutral-hovered-border);
|
||||
// background: var(--button-contained-neutral-hovered-background);
|
||||
// }
|
||||
|
||||
// .pagination span {
|
||||
// color: #00796b; /* Color for ellipsis */
|
||||
// font-size: 14px;
|
||||
// }
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import { useRouter } from "next/router";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
|
||||
type IProps = {};
|
||||
|
||||
@ -50,8 +51,21 @@ export default function DocumentsReminderHistory(props: IProps) {
|
||||
const [customers, setCustomers] = useState<Customer[] | null>(null);
|
||||
const [customerOption, setCustomerOption] = useState<IOption | null>(null);
|
||||
const router = useRouter();
|
||||
const [page, setPage] = useState(1); // Current page number
|
||||
const [pageSize, setPageSize] = useState(10); // Number of items per page
|
||||
const [totalPages, setTotalPages] = useState(1); // Total number of pages
|
||||
let { folderUid } = router.query;
|
||||
|
||||
const fetchTotalPages = useCallback(() => {
|
||||
DocumentReminders.getInstance()
|
||||
.count()
|
||||
.then((response) => {
|
||||
const totalPages = Math.ceil(response.count / pageSize);
|
||||
setTotalPages(totalPages);
|
||||
})
|
||||
.catch((e) => console.warn(e));
|
||||
}, [pageSize]);
|
||||
|
||||
const fetchReminders = useCallback(() => {
|
||||
DocumentReminders.getInstance()
|
||||
.get({
|
||||
@ -69,10 +83,14 @@ export default function DocumentsReminderHistory(props: IProps) {
|
||||
},
|
||||
},
|
||||
orderBy: { reminder_date: "desc" },
|
||||
skip: (page - 1) * pageSize, // Skip based on the page number
|
||||
take: pageSize, // Take the number of items for the page
|
||||
})
|
||||
.then((response) => {
|
||||
setReminders(response); // Set the reminders
|
||||
})
|
||||
.then((reminders) => setReminders(reminders))
|
||||
.catch((e) => console.warn(e));
|
||||
}, [customerOption]);
|
||||
}, [customerOption, page, pageSize]); // Update on page change
|
||||
|
||||
const fetchCustomers = useCallback(async () => {
|
||||
if (!folderUid) return;
|
||||
@ -108,13 +126,64 @@ export default function DocumentsReminderHistory(props: IProps) {
|
||||
}, [customers]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchTotalPages();
|
||||
fetchReminders();
|
||||
fetchCustomers();
|
||||
}, [fetchCustomers, fetchReminders]);
|
||||
}, [fetchTotalPages, fetchCustomers, fetchReminders]);
|
||||
|
||||
const onSelectionChange = useCallback((option: IOption | null) => {
|
||||
setCustomerOption(option ?? null);
|
||||
}, []);
|
||||
const generatePageNumbers = (currentPage: number, totalPages: number) => {
|
||||
const pageNumbers = [];
|
||||
const maxPagesToShow = 7; // Maximum number of page buttons, including ellipsis
|
||||
|
||||
// Case 1: If total pages are <= 5, show all pages
|
||||
if (totalPages <= 5) {
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pageNumbers.push(i);
|
||||
}
|
||||
}
|
||||
// Case 2: If current page is <= 3, and totalPages > 5, show the first 4 pages + ellipsis
|
||||
else if (currentPage <= 3) {
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
pageNumbers.push(i);
|
||||
}
|
||||
pageNumbers.push("...");
|
||||
}
|
||||
// Case 3: If current page is in the middle, show ellipses and surrounding pages
|
||||
else if (currentPage > 3 && currentPage < totalPages - 2) {
|
||||
pageNumbers.push("...");
|
||||
pageNumbers.push(currentPage - 1);
|
||||
pageNumbers.push(currentPage);
|
||||
pageNumbers.push(currentPage + 1);
|
||||
pageNumbers.push("...");
|
||||
}
|
||||
// Case 4: If current page is near the end, show ellipsis and last 4 pages
|
||||
else if (currentPage >= totalPages - 2) {
|
||||
pageNumbers.push("...");
|
||||
for (let i = totalPages - 3; i <= totalPages; i++) {
|
||||
pageNumbers.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the pagination length is exactly maxPagesToShow (counting ellipses as one)
|
||||
if (pageNumbers.length > maxPagesToShow) {
|
||||
// Remove ellipsis at the start or end if pagination exceeds max length
|
||||
if (pageNumbers[0] === "...") {
|
||||
pageNumbers.shift(); // Remove first ellipsis if it's the first item
|
||||
}
|
||||
if (pageNumbers.length > maxPagesToShow && pageNumbers[pageNumbers.length - 1] === "...") {
|
||||
pageNumbers.pop(); // Remove last ellipsis if it's the last item
|
||||
}
|
||||
}
|
||||
|
||||
return pageNumbers;
|
||||
};
|
||||
|
||||
// Handle page change
|
||||
const handlePageChange = (newPage: number) => {
|
||||
if (newPage >= 1 && newPage <= totalPages) {
|
||||
setPage(newPage);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DefaultTemplate title={"Historique des relances de documents"} isPadding={false}>
|
||||
@ -131,11 +200,81 @@ export default function DocumentsReminderHistory(props: IProps) {
|
||||
<Dropdown
|
||||
className={classes["customer-filter"]}
|
||||
options={customersOptions}
|
||||
onSelectionChange={onSelectionChange}
|
||||
onSelectionChange={(option) => setCustomerOption(option ?? null)}
|
||||
selectedOption={customerOption ?? customersOptions?.[0]}
|
||||
label="Client"
|
||||
/>
|
||||
{/* Page Size Selector */}
|
||||
<Dropdown
|
||||
className={classes["page-size-selector"]}
|
||||
options={[
|
||||
{ id: "10", label: "10 par page" },
|
||||
{ id: "20", label: "20 par page" },
|
||||
{ id: "50", label: "50 par page" },
|
||||
]}
|
||||
selectedOption={{ id: `${pageSize}`, label: `${pageSize} par page` }}
|
||||
onSelectionChange={(option) => {
|
||||
setPageSize(parseInt(option.id, 10)); // Update the page size
|
||||
setPage(1); // Reset the page to 1
|
||||
}}
|
||||
label="Items par page"
|
||||
/>
|
||||
|
||||
<Table className={classes["table"]} header={header} rows={buildRows(reminders)} />
|
||||
|
||||
<div className={classes["pagination"]}>
|
||||
{/* Left Arrow (Prev) */}
|
||||
<Button
|
||||
variant={EButtonVariant.PRIMARY}
|
||||
styletype={EButtonstyletype.OUTLINED}
|
||||
className={`${page === 1 ? classes["disabled"] : ""} ${classes["prev"]}`}
|
||||
onClick={() => handlePageChange(page - 1)}>
|
||||
<
|
||||
</Button>
|
||||
{/* <button
|
||||
className={`${page === 1 ? classes["disabled"] : ""} ${classes["prev"]}`}
|
||||
onClick={() => handlePageChange(page - 1)}
|
||||
aria-label="Previous Page">
|
||||
<
|
||||
</button> */}
|
||||
|
||||
{/* Page numbers */}
|
||||
{generatePageNumbers(page, totalPages).map((pageNum, index) => (
|
||||
<React.Fragment key={index}>
|
||||
{pageNum === "..." ? (
|
||||
<Button variant={EButtonVariant.PRIMARY}>...</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant={EButtonVariant.PRIMARY}
|
||||
className={page === pageNum ? classes["active"] : ""}
|
||||
onClick={() => handlePageChange(pageNum as number)}>
|
||||
{pageNum}
|
||||
</Button>
|
||||
// <button
|
||||
// className={page === pageNum ? classes["active"] : ""}
|
||||
// onClick={() => handlePageChange(pageNum as number)}
|
||||
// aria-label={`Go to page ${pageNum}`}>
|
||||
// {pageNum}
|
||||
// </button>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
{/* Right Arrow (Next) */}
|
||||
<Button
|
||||
variant={EButtonVariant.PRIMARY}
|
||||
styletype={EButtonstyletype.OUTLINED}
|
||||
className={`${page === totalPages ? classes["disabled"] : ""} ${classes["next"]}`}
|
||||
onClick={() => handlePageChange(page + 1)}>
|
||||
>
|
||||
</Button>
|
||||
{/* <button
|
||||
className={`${page === totalPages ? classes["disabled"] : ""} ${classes["next"]}`}
|
||||
onClick={() => handlePageChange(page + 1)}
|
||||
aria-label="Next Page">
|
||||
>
|
||||
</button> */}
|
||||
</div>
|
||||
</div>
|
||||
</DefaultTemplate>
|
||||
);
|
||||
|
@ -4,4 +4,5 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-xl, 32px);
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import classes from "./classes.module.scss";
|
||||
import ClientBox from "./ClientBox";
|
||||
import DocumentTables from "./DocumentTables";
|
||||
import EmailReminder from "./EmailReminder";
|
||||
import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
|
||||
|
||||
type IProps = {
|
||||
folder: OfficeFolder;
|
||||
@ -57,8 +58,19 @@ export default function ClientView(props: IProps) {
|
||||
);
|
||||
|
||||
const handleClientDelete = useCallback(
|
||||
(customerUid: string) => {
|
||||
async (customerUid: string) => {
|
||||
if (!folder.uid) return;
|
||||
const documentsNotary = await DocumentsNotary.getInstance().get({
|
||||
where: { customer: { uid: customerUid }, folder: { uid: folder.uid } },
|
||||
});
|
||||
console.log(documentsNotary);
|
||||
|
||||
if (documentsNotary.length > 0) {
|
||||
documentsNotary.forEach(async (doc) => {
|
||||
await DocumentsNotary.getInstance().delete(doc.uid!);
|
||||
});
|
||||
}
|
||||
|
||||
Folders.getInstance().put(
|
||||
folder.uid,
|
||||
OfficeFolder.hydrate<OfficeFolder>({
|
||||
|
@ -148,9 +148,13 @@ export default function InformationSection(props: IProps) {
|
||||
<IconButton icon={<PaperAirplaneIcon />} variant={EIconButtonVariant.NEUTRAL} />
|
||||
</Link>
|
||||
|
||||
<Menu items={menuItemsDekstop}>
|
||||
<IconButton icon={<EllipsisHorizontalIcon />} variant={EIconButtonVariant.NEUTRAL} />
|
||||
</Menu>
|
||||
{/* If the folder is not archived, we can display the archive button */}
|
||||
{anchorStatus !== "VERIFIED_ON_CHAIN" && (
|
||||
<Menu items={menuItemsDekstop}>
|
||||
<IconButton icon={<EllipsisHorizontalIcon />} variant={EIconButtonVariant.NEUTRAL} />
|
||||
</Menu>
|
||||
)}
|
||||
|
||||
{!isArchived && <IconButton onClick={onArchive} icon={<ArchiveBoxIcon />} variant={EIconButtonVariant.ERROR} />}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -38,6 +38,13 @@
|
||||
"labelKey": "client-dashboard"
|
||||
},
|
||||
"pages": {
|
||||
"ViewDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
|
||||
"labelKey": "view_documents"
|
||||
}
|
||||
},
|
||||
"ReceiveDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
|
@ -38,6 +38,13 @@
|
||||
"labelKey": "client-dashboard"
|
||||
},
|
||||
"pages": {
|
||||
"ViewDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
|
||||
"labelKey": "view_documents"
|
||||
}
|
||||
},
|
||||
"ReceiveDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
|
@ -38,6 +38,13 @@
|
||||
"labelKey": "client-dashboard"
|
||||
},
|
||||
"pages": {
|
||||
"ViewDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
|
||||
"labelKey": "view_documents"
|
||||
}
|
||||
},
|
||||
"ReceiveDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
|
@ -38,6 +38,13 @@
|
||||
"labelKey": "client-dashboard"
|
||||
},
|
||||
"pages": {
|
||||
"ViewDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
|
||||
"labelKey": "view_documents"
|
||||
}
|
||||
},
|
||||
"ReceiveDocuments": {
|
||||
"enabled": true,
|
||||
"props": {
|
||||
|
@ -0,0 +1,5 @@
|
||||
import ViewDocumentsNotary from "@Front/Components/Layouts/ClientDashboard/ViewDocumentsNotary";
|
||||
|
||||
export default function Route() {
|
||||
return <ViewDocumentsNotary />;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user