diff --git a/.vscode/settings.json b/.vscode/settings.json index 7fb4001b..2fec080c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,5 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, diff --git a/src/front/Assets/Icons/left-arrow.svg b/src/front/Assets/Icons/left-arrow.svg new file mode 100644 index 00000000..4ac63441 --- /dev/null +++ b/src/front/Assets/Icons/left-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/front/Assets/Icons/right-arrow.svg b/src/front/Assets/Icons/right-arrow.svg new file mode 100644 index 00000000..5704297c --- /dev/null +++ b/src/front/Assets/Icons/right-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/front/Assets/images/validate_anchoring.gif b/src/front/Assets/images/validate_anchoring.gif new file mode 100644 index 00000000..5a5beade Binary files /dev/null and b/src/front/Assets/images/validate_anchoring.gif differ diff --git a/src/front/Components/DesignSystem/Document/DocumentNotary/classes.module.scss b/src/front/Components/DesignSystem/Document/DocumentNotary/classes.module.scss index 768a59bb..c3627588 100644 --- a/src/front/Components/DesignSystem/Document/DocumentNotary/classes.module.scss +++ b/src/front/Components/DesignSystem/Document/DocumentNotary/classes.module.scss @@ -7,11 +7,22 @@ justify-content: space-between; align-items: center; &.PENDING { - border-color: $orange-soft; + cursor: pointer; + border: 1px solid $orange-soft; + &:hover { + border: 1px solid $orange-soft; + outline: 1px solid $orange-soft; + } } &.VALIDATED { - border-color: $green-soft; + cursor: pointer; + border: 1px solid $green-soft; + &:hover { + border: 1px solid $green-soft; + outline: 1px solid $green-soft; + } } + .valid-radius { background-color: $green-flash; padding: 6px; diff --git a/src/front/Components/DesignSystem/Document/DocumentNotary/index.tsx b/src/front/Components/DesignSystem/Document/DocumentNotary/index.tsx index 28264ae9..198c4ec7 100644 --- a/src/front/Components/DesignSystem/Document/DocumentNotary/index.tsx +++ b/src/front/Components/DesignSystem/Document/DocumentNotary/index.tsx @@ -1,12 +1,14 @@ -import React from "react"; -import classes from "./classes.module.scss"; -import { Document } from "le-coffre-resources/dist/Customer"; -import Typography, { ITypo } from "../../Typography"; -import Image from "next/image"; -import TrashIcon from "@Assets/Icons/trash.svg"; import ValidIcon from "@Assets/Icons/check-valid.svg"; +import TrashIcon from "@Assets/Icons/trash.svg"; import classNames from "classnames"; +import { Document } from "le-coffre-resources/dist/Customer"; +import Image from "next/image"; +import { NextRouter, useRouter } from "next/router"; +import React from "react"; + +import Typography, { ITypo } from "../../Typography"; import WarningBadge from "../../WarningBadge"; +import classes from "./classes.module.scss"; type IProps = { document: { @@ -16,16 +18,22 @@ type IProps = { }; openDeletionModal?: (uid: Document["uid"]) => void; }; + +type IPropsClass = IProps & { + router: NextRouter; +}; + type IState = {}; -export default class DocumentNotary extends React.Component { - public constructor(props: IProps) { +class DocumentNotaryClass extends React.Component { + public constructor(props: IPropsClass) { super(props); this.onOpenDeletionModal = this.onOpenDeletionModal.bind(this); + this.onClick = this.onClick.bind(this); } public override render(): JSX.Element { return ( -
+
{this.props.document?.document_type?.name} Aucun document déposé @@ -35,6 +43,11 @@ export default class DocumentNotary extends React.Component { ); } + private onClick() { + if (this.props.document.document_status !== "VALIDATED" && this.props.document.document_status !== "PENDING") return; + this.props.router.push(`/folder/${this.props.document.folder.uid}/document/${this.props.document.uid}`); + } + private renderIcon(): JSX.Element { switch (this.props.document.document_status) { case "VALIDATED": @@ -55,3 +68,8 @@ export default class DocumentNotary extends React.Component { this.props.openDeletionModal(this.props.document.uid); } } + +export default function DocumentNotary(props: IProps): JSX.Element { + const router = useRouter(); + return ; +} diff --git a/src/front/Components/DesignSystem/FilePreview/classes.module.scss b/src/front/Components/DesignSystem/FilePreview/classes.module.scss index 95b916b2..b359b71f 100644 --- a/src/front/Components/DesignSystem/FilePreview/classes.module.scss +++ b/src/front/Components/DesignSystem/FilePreview/classes.module.scss @@ -1,15 +1,19 @@ .root { height: inherit; + min-height: inherit; .file-container { height: inherit; + min-height: inherit; .image { width: 100%; height: inherit; + min-height: inherit; object-fit: contain; } .pdf { width: 100%; + min-height: inherit; height: inherit; } } diff --git a/src/front/Components/DesignSystem/Modal/Confirm/index.tsx b/src/front/Components/DesignSystem/Modal/Confirm/index.tsx index a873b69e..1466d972 100644 --- a/src/front/Components/DesignSystem/Modal/Confirm/index.tsx +++ b/src/front/Components/DesignSystem/Modal/Confirm/index.tsx @@ -11,6 +11,7 @@ type IProps = IPropsModal & { cancelPath?: string; confirmText: string | JSX.Element; showCancelButton: boolean; + showButtons: boolean; canConfirm: boolean; }; @@ -21,7 +22,8 @@ export default class Confirm extends React.Component { showCancelButton: true, cancelText: "Cancel", confirmText: "Confirm", - canConfirm: false, + canConfirm: true, + showButtons: true, ...Modal.defaultProps, }; @@ -29,17 +31,17 @@ export default class Confirm extends React.Component { return ( + animationDelay={this.props.animationDelay} + {...this.props}> {this.props.children} ); } - private footer(): JSX.Element { + private footer(): JSX.Element | null { + if (!this.props.showButtons) return null; return (
{this.props.showCancelButton && diff --git a/src/front/Components/DesignSystem/Modal/index.tsx b/src/front/Components/DesignSystem/Modal/index.tsx index 6726b19b..a1bca8ef 100644 --- a/src/front/Components/DesignSystem/Modal/index.tsx +++ b/src/front/Components/DesignSystem/Modal/index.tsx @@ -11,7 +11,7 @@ import Loader from "./Elements/Loader"; export type IProps = { closeBtn?: boolean; header?: string | JSX.Element; - footer?: JSX.Element; + footer?: JSX.Element | null; textLoader?: string | JSX.Element; isOpen: boolean; onClose: () => void; @@ -87,6 +87,7 @@ export default class Modal extends React.Component { } protected close() { + if (this.props.hasContainerClosable === false) return; if (this.state.willClose) return; this.props.onClose(); } diff --git a/src/front/Components/DesignSystem/UserFolder/index.tsx b/src/front/Components/DesignSystem/UserFolder/index.tsx index 90d39360..4d56f190 100644 --- a/src/front/Components/DesignSystem/UserFolder/index.tsx +++ b/src/front/Components/DesignSystem/UserFolder/index.tsx @@ -124,9 +124,10 @@ export default class UserFolder extends React.Component { private getDocumentsByStatus(status: string): Document[] | null { if (!this.props.customer.documents) return null; - return this.props.customer.documents.filter( + const filteredDocuments = this.props.customer.documents.filter( (document) => document.document_status === status && document.folder.uid === this.props.folder.uid, ); + return filteredDocuments; } // Get all documents Validated, pending diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss index b9457cb1..7bd278e7 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss @@ -36,8 +36,8 @@ overflow: hidden; @media (max-width: ($screen-m - 1px)) { - width: 83px; - min-width: 83px; + width: 56px; + min-width: 56px; transform: translateX(-389px); &.opened { @@ -46,6 +46,16 @@ min-width: 389px; } } + + @media (max-width: $screen-s) { + width: 0px; + min-width: 0px; + + &.opened { + width: 100vw; + min-width: 100vw; + } + } } .closable-left-side { @@ -54,8 +64,8 @@ z-index: 0; display: flex; justify-content: center; - min-width: 83px; - max-width: 83px; + min-width: 56px; + max-width: 56px; height: calc(100vh - 83px); border-right: 1px $grey-medium solid; @@ -68,6 +78,10 @@ transform: rotate(180deg); cursor: pointer; } + + @media (max-width: $screen-s) { + display: none; + } } .right-side { @@ -76,8 +90,26 @@ overflow-y: auto; @media (max-width: ($screen-m - 1px)) { - min-width: calc(100vw - 83px); + min-width: calc(100vw - 56px); + } + + @media(max-width: $screen-s){ + flex: 1; + min-width: unset; + } + + .back-arrow-mobile{ + display: none; + @media (max-width: $screen-s) { + display: block; + } + } + + .back-arrow-desktop{ + @media (max-width: $screen-s) { + display: none; + } } } } -} \ No newline at end of file +} diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx index f4bb44f9..3133c29a 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx @@ -1,8 +1,11 @@ import "reflect-metadata"; + import ChevronIcon from "@Assets/Icons/chevron.svg"; +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; import FolderListContainer from "@Front/Components/DesignSystem/FolderListContainer"; import Header from "@Front/Components/DesignSystem/Header"; import Version from "@Front/Components/DesignSystem/Version"; +import BackArrow from "@Front/Components/Elements/BackArrow"; import { folders } from "@Front/Components/Layouts/DesignSystem/dummyData"; import { foldersArchived } from "@Front/Components/Layouts/DesignSystem/dummyData"; import WindowStore from "@Front/Stores/WindowStore"; @@ -13,11 +16,15 @@ import React, { ReactNode } from "react"; import classes from "./classes.module.scss"; + type IProps = { title: string; children?: ReactNode; isArchived?: boolean; onSelectedFolder: (folder: IDashBoardFolder) => void; + hasBackArrow: boolean; + backArrowUrl?: string; + mobileBackText?: string; }; type IState = { folders: IDashBoardFolder[] | null; @@ -37,8 +44,8 @@ export type IDashBoardFolder = { }; export default class DefaultNotaryDashboard extends React.Component { private onWindowResize = () => {}; - public static defaultProps = { - scrollTop: 0, + public static defaultProps: Partial = { + hasBackArrow: false, isArchived: false, }; @@ -72,7 +79,27 @@ export default class DefaultNotaryDashboard extends React.Component open side menu
-
{this.props.children}
+ +
+ {this.props.hasBackArrow && ( + <> +
+ +
+
+ +
+ + )} + {this.props.children} +
diff --git a/src/front/Components/Layouts/DesignSystem/dummyData.ts b/src/front/Components/Layouts/DesignSystem/dummyData.ts index 22cbc98e..95da8113 100644 --- a/src/front/Components/Layouts/DesignSystem/dummyData.ts +++ b/src/front/Components/Layouts/DesignSystem/dummyData.ts @@ -1,17 +1,6 @@ -import { - Address, - Office, - DeedType, - Deed, - OfficeFolder, - Contact, - Customer, - DocumentType, - Document, - OfficeFolderHasCustomer, -} from "le-coffre-resources/dist/Notary"; import { ECustomerStatus } from "le-coffre-resources/dist/Customer/Customer"; import { EFolderStatus } from "le-coffre-resources/dist/Customer/OfficeFolder"; +import { Address, Contact, Customer, Deed, DeedType, Document, DocumentType, File, Office, OfficeFolder, OfficeFolderHasCustomer } from "le-coffre-resources/dist/Notary"; export const address: Address = { uid: "a&2azedzaa3", @@ -92,7 +81,7 @@ export const customer: Customer = { status: ECustomerStatus.VALIDATED, }; export const folder: OfficeFolder = { - uid: "zfaefergregrezterf", + uid: "mkovrijvrezviev", folder_number: "12331", name: "Mon dossier", status: EFolderStatus.ARCHIVED, @@ -104,6 +93,8 @@ export const folder: OfficeFolder = { archived_description: "Archived description", }; + + export const document: Document = { uid: "fzeafergreztyzgrf", depositor: customer, @@ -114,6 +105,24 @@ export const document: Document = { created_at: new Date(), }; +export const fileMock: File = { + uid: "super_file_uid_1", + created_at: new Date(), + updated_at: new Date(), + document: document, + file_path: + "https://minteed-stg-euwest3-s3.s3.eu-west-3.amazonaws.com/Qmf_Yb_Eh_X9st_F_Srq_Ve_Bj_Yb_Aj56xv_AV_Nj6_Wjypo_B4r5ubce_U_ae3303e7ab.pdf", +}; + +export const fileMock2: File = { + uid: "super_file_uid_2", + created_at: new Date(), + updated_at: new Date(), + document: document, + file_path: + "https://minteed-prod-euwest3-s3.s3.eu-west-3.amazonaws.com/Qm_Wq_En1_DCA_8yt_RX_Qx_QFA_9_Fm_ZKZH_Qqb_VH_1_Q_Mnv_G_Jtt1_FS_Xp_2a35a36e19", +}; + export const documentPending: Document = { uid: "fzefeazdagrtetrury", depositor: customer, @@ -122,6 +131,7 @@ export const documentPending: Document = { document_type: docType, updated_at: new Date(), created_at: new Date(), + files: [fileMock2], }; export const documentDeposited: Document = { @@ -132,6 +142,7 @@ export const documentDeposited: Document = { document_type: docType, updated_at: new Date(), created_at: new Date(), + files: [fileMock], }; export const customer2: Customer = { diff --git a/src/front/Components/Layouts/Folder/ViewDocuments/classes.module.scss b/src/front/Components/Layouts/Folder/ViewDocuments/classes.module.scss new file mode 100644 index 00000000..61d7d101 --- /dev/null +++ b/src/front/Components/Layouts/Folder/ViewDocuments/classes.module.scss @@ -0,0 +1,59 @@ +@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{ + min-height: 700px; + flex: 1; + } + } + + .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; + } + } + } +} diff --git a/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx b/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx new file mode 100644 index 00000000..9cb8ed2a --- /dev/null +++ b/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx @@ -0,0 +1,249 @@ +import "reflect-metadata"; +import LeftArrowIcon from "@Assets/Icons/left-arrow.svg"; +import RightArrowIcon from "@Assets/Icons/right-arrow.svg"; +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 { folders } from "@Front/Components/Layouts/DesignSystem/dummyData"; +import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; +import { Document } from "le-coffre-resources/dist/Customer"; +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"; + + +type IProps = {}; +type IPropsClass = { + documentsList: Document[]; + selectedDocument: Document | null; + router: NextRouter; + folderUid: string; +}; + +type IState = { + isRefuseModalVisible: boolean; + isValidateModalVisible: boolean; + refuseText: string; + hasValidateAnchoring: boolean; + selectedDocument: Document | null; + selectedDocumentIndex: number; +}; + +class ViewDocumentsClass extends BasePage { + public constructor(props: IPropsClass) { + super(props); + + this.state = { + isValidateModalVisible: false, + isRefuseModalVisible: false, + refuseText: "", + hasValidateAnchoring: false, + selectedDocument: null, + selectedDocumentIndex: -1, + }; + + 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); + } + + public override render(): JSX.Element | null { + return ( + + {this.state.selectedDocument && ( +
+ + App 23 rue Torus Toulon + + + {this.state.selectedDocument.document_type.name} + +
+ {this.props.documentsList.length > 1 && ( +
+ left arrow +
+ )} +
+ {this.state.selectedDocument.files?.map((file) => ( + + ))} +
+ {this.props.documentsList.length > 1 && ( +
+ right arrow +
+ )} +
+
+ + + +
+ +
+ {!this.state.hasValidateAnchoring && ( + + Êtes-vous sûr de vouloir ancrer ce document ? + + )} + {this.state.hasValidateAnchoring && ( +
+ + Le document s'ancre dans la blockchain. + + Anchoring animation +
+ +
+
+ )} +
+
+ +
+ + Veuillez indiquer au client le motif du refus de son document afin qu'il puisse vous renvoyer une bonne + version. + + +
+
+
+ )} + {!this.state.selectedDocument && ( +
+ + Document non trouvé + +
+ )} +
+ ); + } + + override componentDidMount(): void { + if (!this.props.selectedDocument) return; + this.setState({ + selectedDocument: this.props.selectedDocument, + selectedDocumentIndex: this.props.documentsList.findIndex((doc) => doc.uid === this.props.selectedDocument!.uid), + }); + } + + override componentDidUpdate(prevProps: Readonly, prevState: Readonly, snapshot?: any): void { + if (prevProps.selectedDocument !== this.props.selectedDocument) { + this.setState({ + selectedDocument: this.props.selectedDocument, + selectedDocumentIndex: this.props.documentsList.findIndex((doc) => doc.uid === this.props.selectedDocument!.uid), + }); + } + } + + private goToPrevious() { + if (this.hasPrevious()) { + this.props.router.push( + `/folder/${this.props.folderUid}/document/${this.props.documentsList[this.state.selectedDocumentIndex - 1]!.uid}`, + ); + } + } + + private goToNext() { + if (this.hasNext()) { + this.props.router.push( + `/folder/${this.props.folderUid}/document/${this.props.documentsList[this.state.selectedDocumentIndex + 1]!.uid}`, + ); + } + } + + private hasPrevious() { + const index = this.state.selectedDocumentIndex - 1; + return index >= 0; + } + + private hasNext() { + const index = this.state.selectedDocumentIndex + 1; + return index < this.props.documentsList.length; + } + + private validateAnchoring() { + this.setState({ + hasValidateAnchoring: true, + }); + } + + private onRefuseTextChange(e: React.ChangeEvent) { + 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; + + const folder = folders[0]!; + const documents = folder.documents!.filter((document) => document.document_status !== "ASKED"); + const selectedDocument = documents.find((document) => document.uid === documentUid) ?? null; + return ( + + ); +} diff --git a/src/front/Components/Layouts/Folder/index.tsx b/src/front/Components/Layouts/Folder/index.tsx index 4ba9ec97..bfd2968a 100644 --- a/src/front/Components/Layouts/Folder/index.tsx +++ b/src/front/Components/Layouts/Folder/index.tsx @@ -1,6 +1,7 @@ -import DefaultNotaryDashboard, { IDashBoardFolder } from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; -import BasePage from "../Base"; import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; +import DefaultNotaryDashboard, { IDashBoardFolder } from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; + +import BasePage from "../Base"; import classes from "./classes.module.scss"; type IProps = {}; diff --git a/src/pages/folder/[folderUid]/document/[documentUid]/index.tsx b/src/pages/folder/[folderUid]/document/[documentUid]/index.tsx new file mode 100644 index 00000000..634e89a1 --- /dev/null +++ b/src/pages/folder/[folderUid]/document/[documentUid]/index.tsx @@ -0,0 +1,5 @@ +import ViewDocuments from "@Front/Components/Layouts/Folder/ViewDocuments"; + +export default function Route() { + return ; +}