diff --git a/src/front/Assets/Icons/deposit-document.svg b/src/front/Assets/Icons/deposit-document.svg new file mode 100644 index 00000000..585626d1 --- /dev/null +++ b/src/front/Assets/Icons/deposit-document.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/front/Assets/Icons/document-check.svg b/src/front/Assets/Icons/document-check.svg new file mode 100644 index 00000000..09925cc3 --- /dev/null +++ b/src/front/Assets/Icons/document-check.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/front/Components/DesignSystem/DepositDocument/classes.module.scss b/src/front/Components/DesignSystem/DepositDocument/classes.module.scss new file mode 100644 index 00000000..3ef6b854 --- /dev/null +++ b/src/front/Components/DesignSystem/DepositDocument/classes.module.scss @@ -0,0 +1,69 @@ +.root { + padding: 24px; + background-color: white; + border: 1px dashed #e7e7e7; + + height: fit-content; + &[data-drag-over="true"] { + border: 1px dashed grey; + } + + .top-container { + display: flex; + align-items: center; + + .left { + margin-right: 28px; + } + + .separator { + background-color: #939393; + width: 1px; + align-self: stretch; + } + + .right { + margin-left: 18px; + + .title { + display: flex; + align-items: center; + gap: 8px; + } + } + } + + .documents-container { + display: flex; + flex-direction: column; + gap: 16px; + margin-top: 16px; + + .file-container { + display: flex; + align-items: center; + justify-content: space-between; + + .left-part { + display: flex; + align-items: center; + gap: 8px; + } + + .cross{ + cursor: pointer; + } + } + } + + .bottom-container { + margin-top: 16px; + .add-button { + .add-document { + display: flex; + align-items: center; + gap: 14px; + } + } + } +} diff --git a/src/front/Components/DesignSystem/DepositDocument/index.tsx b/src/front/Components/DesignSystem/DepositDocument/index.tsx new file mode 100644 index 00000000..d599d0e6 --- /dev/null +++ b/src/front/Components/DesignSystem/DepositDocument/index.tsx @@ -0,0 +1,196 @@ +import DepositDocumentIcon from "@Assets/Icons/deposit-document.svg"; +import PlusIcon from "@Assets/Icons/plus.svg"; +import CrossIcon from "@Assets/Icons/cross.svg"; +import DocumentCheckIcon from "@Assets/Icons/document-check.svg"; +import Image from "next/image"; +import React from "react"; + +import Button, { EButtonVariant } from "../Button"; +import Tooltip from "../ToolTip"; +import Typography, { ITypo, ITypoColor } from "../Typography"; +import classes from "./classes.module.scss"; +import { File as FileCustomer } from "le-coffre-resources/dist/Customer"; + +type IProps = { + title: string; + dateAsked: Date; + defaultFiles?: FileCustomer[]; + onChange?: (files: File[]) => void; +}; + +type IFile = { + index: number; + file: File; +}; + +type IState = { + files: IFile[]; + isDragOver: boolean; +}; + +export default class DepositDocument extends React.Component { + private inputRef = React.createRef(); + private index = 0; + + public constructor(props: IProps) { + super(props); + + this.state = { + files: [], + isDragOver: false, + }; + + this.addDocument = this.addDocument.bind(this); + this.onFileChange = this.onFileChange.bind(this); + this.removeFile = this.removeFile.bind(this); + this.onDragOver = this.onDragOver.bind(this); + this.onDragDrop = this.onDragDrop.bind(this); + this.onDragLeave = this.onDragLeave.bind(this); + } + + public override render(): JSX.Element { + return ( +
+ +
+
+ Deposit document +
+
+
+ + {this.props.title} + + + Demandé par le notaire le {this.formatDate(this.props.dateAsked)} + +
+
+ {this.state.files.length > 0 && ( +
+ {this.state.files.map((file) => { + const fileObj = file.file; + return ( +
+
+ Document check + + {this.shortName(fileObj.name)} + +
+ Cross icon +
+ ); + })} +
+ )} + +
+ +
+
+ ); + } + + public override componentDidMount(): void { + if (this.props.defaultFiles) { + this.setState({ + files: this.props.defaultFiles.map((file) => ({ + index: this.index++, + file: new File([""], file.file_path, {}), + })), + }); + } + } + + private shortName(name: string): string { + const maxLength = 20; + if (name.length > maxLength) { + return name.substring(0, maxLength / 2) + "..." + name.substring(name.length - maxLength / 2, name.length); + } + return name; + } + + private onDragOver(event: React.DragEvent) { + if (!this.state.isDragOver) { + this.setState({ + isDragOver: true, + }); + } + event.preventDefault(); + } + + private onDragLeave(event: React.DragEvent) { + this.setState({ + isDragOver: false, + }); + event.preventDefault(); + } + + private async onDragDrop(event: React.DragEvent) { + event.preventDefault(); + this.setState({ + isDragOver: false, + }); + const file = event.dataTransfer.files[0]; + if (file) this.addFile(file); + } + + private addFile(file: File) { + this.setState({ + files: [ + ...this.state.files, + { + index: this.index++, + file: file, + }, + ], + }); + + if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file)); + } + + private removeFile(e: any) { + const image = e.target as HTMLElement; + const indexToRemove = image.getAttribute("data-file"); + if (!indexToRemove) return; + this.setState({ + files: this.state.files.filter((file) => file.index !== parseInt(indexToRemove)), + }); + + if (this.props.onChange) this.props.onChange(this.state.files.map((file) => file.file)); + } + + private async onFileChange() { + if (!this.inputRef.current) return; + const files = this.inputRef.current.files; + if (!files) return; + const file = files[0]; + + if (file) this.addFile(file); + } + + private addDocument() { + if (!this.inputRef.current) return; + this.inputRef.current.click(); + } + + private formatDate(date: Date) { + return date.toLocaleDateString("fr-FR"); + } +} diff --git a/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss b/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss index b3731010..3bf27c20 100644 --- a/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss +++ b/src/front/Components/DesignSystem/Form/Elements/InputField/classes.module.scss @@ -27,12 +27,15 @@ &:disabled { cursor: not-allowed; + background: white; + opacity: 0.6; ~ .fake-placeholder { + color: rgba($grey, 0.6); /** TODO * 1. Add styles so the placeholder has the same color as the background when disabled */ - background: transparent; + // background: transparent; } } &:focus { diff --git a/src/front/Components/DesignSystem/Typography/classes.module.scss b/src/front/Components/DesignSystem/Typography/classes.module.scss index 31a68d43..186404af 100644 --- a/src/front/Components/DesignSystem/Typography/classes.module.scss +++ b/src/front/Components/DesignSystem/Typography/classes.module.scss @@ -130,6 +130,10 @@ color: var(--purple-flash); } + &.pink-flash { + color: var(--pink-flash); + } + &.green-flash { color: var(--green-flash); } diff --git a/src/front/Components/DesignSystem/Typography/index.tsx b/src/front/Components/DesignSystem/Typography/index.tsx index bd212c9b..a1e72a60 100644 --- a/src/front/Components/DesignSystem/Typography/index.tsx +++ b/src/front/Components/DesignSystem/Typography/index.tsx @@ -35,6 +35,7 @@ export enum ITypoColor { GREY = "grey", BLACK = "black", PURPLE_FLASH = "purple-flash", + PINK_FLASH = "pink-flash", GREEN_FLASH = "green-flash", ORANGE_FLASH = "orange-flash", RED_FLASH = "red-flash", diff --git a/src/front/Components/Layouts/ClientDashboard/index.tsx b/src/front/Components/Layouts/ClientDashboard/index.tsx index 86abc8c3..1f147b94 100644 --- a/src/front/Components/Layouts/ClientDashboard/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/index.tsx @@ -1,12 +1,13 @@ +import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import DepositDocument from "@Front/Components/DesignSystem/DepositDocument"; +import InputField from "@Front/Components/DesignSystem/Form/Elements/InputField"; +import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import Base from "@Front/Components/Layouts/Base"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import React from "react"; - +import { documentDeposited } from "../DesignSystem/dummyData"; import classes from "./classes.module.scss"; -import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Confirm from "@Front/Components/DesignSystem/Modal/Confirm"; -import InputField from "@Front/Components/DesignSystem/Form/Elements/InputField"; type IProps = {}; type IState = { @@ -30,19 +31,23 @@ export default class ClientDashboard extends Base { {this.renderHeader()}
-
-
-
-
-
-
+ + + + + +
Documents supplémentaires (facultatif) - Vous souhaitez envoyer d’autres documents à votre notaire ? + Vous souhaitez envoyer d'autres documents à votre notaire ?
{ Glissez / Déposez votre document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le document correspondant. -
+
@@ -84,7 +89,7 @@ export default class ClientDashboard extends Base { - Votre notaire est dans l'attente de documents pour valider votre dossier. Voici la liste des documents.
Veuillez + Votre notaire est dans l'attente de documents pour valider votre dossier. Voici la liste des documents.Veuillez glisser / déposez chaque document dans la zone prévue à cet effet ou cliquez sur la zone puis sélectionnez le document correspondant. Si un des documents demandés ne vous concernent pas, veuillez contacter votre notaire à l’aide du bouton ci-dessus.