Merge branch 'dev' into staging

This commit is contained in:
Vins 2024-11-22 09:12:33 +01:00
commit 369be05592
10 changed files with 401 additions and 4 deletions

View File

@ -35,4 +35,16 @@ export default class DocumentsNotary extends BaseCustomer {
return Promise.reject(err); 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);
}
}
} }

View File

@ -90,4 +90,14 @@ export default class Files extends BaseCustomer {
return Promise.reject(err); 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);
}
}
} }

View File

@ -9,7 +9,7 @@ import BackArrow from "@Front/Components/Elements/BackArrow";
import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import JwtService from "@Front/Services/JwtService/JwtService"; 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 { saveAs } from "file-saver";
import JSZip from "jszip"; import JSZip from "jszip";
import DocumentNotary from "le-coffre-resources/dist/Notary/DocumentNotary"; 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 React, { useCallback, useEffect, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Link from "next/link";
const header: readonly IHead[] = [ const header: readonly IHead[] = [
{ {
@ -100,7 +101,7 @@ export default function ReceivedDocuments() {
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}> <Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}>
Un document vous a é envoyé Un document vous a é envoyé
</Typography> </Typography>
<Table className={classes["table"]} header={header} rows={buildRows(documentsNotary, onDownload)} /> <Table className={classes["table"]} header={header} rows={buildRows(documentsNotary, folderUid!, onDownload)} />
<Button <Button
variant={EButtonVariant.PRIMARY} variant={EButtonVariant.PRIMARY}
size={EButtonSize.LG} 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) => ({ return documentsNotary.map((documentNotary) => ({
key: documentNotary.uid ?? "", key: documentNotary.uid ?? "",
name: formatName(documentNotary.files?.[0]?.file_name?.split(".")?.[0] ?? "") || "_", name: formatName(documentNotary.files?.[0]?.file_name?.split(".")?.[0] ?? "") || "_",
sentAt: new Date(documentNotary.created_at!).toLocaleDateString(), 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>
),
},
})); }));
} }

View File

@ -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;
}
}
}
}

View File

@ -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} />;
}

View File

@ -38,6 +38,13 @@
"labelKey": "client-dashboard" "labelKey": "client-dashboard"
}, },
"pages": { "pages": {
"ViewDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
"labelKey": "view_documents"
}
},
"ReceiveDocuments": { "ReceiveDocuments": {
"enabled": true, "enabled": true,
"props": { "props": {

View File

@ -38,6 +38,13 @@
"labelKey": "client-dashboard" "labelKey": "client-dashboard"
}, },
"pages": { "pages": {
"ViewDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
"labelKey": "view_documents"
}
},
"ReceiveDocuments": { "ReceiveDocuments": {
"enabled": true, "enabled": true,
"props": { "props": {

View File

@ -38,6 +38,13 @@
"labelKey": "client-dashboard" "labelKey": "client-dashboard"
}, },
"pages": { "pages": {
"ViewDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
"labelKey": "view_documents"
}
},
"ReceiveDocuments": { "ReceiveDocuments": {
"enabled": true, "enabled": true,
"props": { "props": {

View File

@ -38,6 +38,13 @@
"labelKey": "client-dashboard" "labelKey": "client-dashboard"
}, },
"pages": { "pages": {
"ViewDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/documentNotary/[documentUid]",
"labelKey": "view_documents"
}
},
"ReceiveDocuments": { "ReceiveDocuments": {
"enabled": true, "enabled": true,
"props": { "props": {

View File

@ -0,0 +1,5 @@
import ViewDocumentsNotary from "@Front/Components/Layouts/ClientDashboard/ViewDocumentsNotary";
export default function Route() {
return <ViewDocumentsNotary />;
}