diff --git a/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/classes.module.scss b/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/classes.module.scss new file mode 100644 index 00000000..cdba1ed0 --- /dev/null +++ b/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/classes.module.scss @@ -0,0 +1,39 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + max-width: 357px; + width: 100%; + gap: var(--spacing-sm, 8px); + justify-content: space-between; + align-items: center; + + .content { + display: flex; + gap: var(--spacing-sm, 8px); + align-items: center; + + .file-name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 277px; + } + } + + svg { + min-width: var(--spacing-3, 24px); + min-height: var(--spacing-3, 24px); + width: var(--spacing-3, 24px); + height: var(--spacing-3, 24px); + stroke: var(--color-primary-500); + } + + .error{ + min-width: var(--spacing-3, 24px); + min-height: var(--spacing-3, 24px); + width: var(--spacing-3, 24px); + height: var(--spacing-3, 24px); + stroke: var(--color-error-500); + } +} \ No newline at end of file diff --git a/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/index.tsx b/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/index.tsx new file mode 100644 index 00000000..efb8aa20 --- /dev/null +++ b/src/front/Components/DesignSystem/DragAndDrop/DocumentElement/index.tsx @@ -0,0 +1,37 @@ +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import { CheckCircleIcon, XCircleIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import React from "react"; + +import IconButton, { EIconButtonVariant } from "../../IconButton"; +import Loader from "../../Loader"; +import classes from "./classes.module.scss"; + +type IProps = { + isLoading: boolean; + file: File | null; + onRemove: () => void; + error?: string; +}; + +export default function DocumentElement(props: IProps) { + const { isLoading, onRemove, file, error } = props; + + return ( +
+
+ {isLoading ? : !error ? : } + {error && ( + + {error} + + )} + {file && !error && ( + + {file.name} + + )} +
+ } variant={error ? EIconButtonVariant.ERROR : EIconButtonVariant.NEUTRAL} /> +
+ ); +} diff --git a/src/front/Components/DesignSystem/DragAndDrop/classes.module.scss b/src/front/Components/DesignSystem/DragAndDrop/classes.module.scss index 30993fb9..0c3fae28 100644 --- a/src/front/Components/DesignSystem/DragAndDrop/classes.module.scss +++ b/src/front/Components/DesignSystem/DragAndDrop/classes.module.scss @@ -2,22 +2,57 @@ .root { display: inline-flex; + flex-direction: column; + gap: var(--spacing-3, 24px); + + width: fit-content; padding: var(--spacing-2, 16px) var(--Radius-2xl, 32px) var(--spacing-2, 16px) var(--spacing-xl, 32px); - align-items: center; - gap: var(--spacing-4, 32px); + + border-radius: var(--Radius-md, 8px); + border: 1px dashed var(--dropdown-input-border-hovered, #b4bec5); + + &:hover { + border-color: var(--dropdown-input-border-expanded); + background: var(--primary-weak-higlight, #e5eefa); + } .content { - display: flex; - flex-direction: column; - gap: var(--spacing-sm, 8px); + display: inline-flex; + align-items: center; + gap: var(--spacing-4, 32px); - .deposit-document { + .browse-document-container { display: flex; + flex-direction: column; gap: var(--spacing-sm, 8px); + + .browse-document { + display: flex; + gap: var(--spacing-sm, 8px); + + &.desktop { + @media screen and (max-width: $screen-s) { + display: none; + } + } + + &.mobile { + display: none; + @media screen and (max-width: $screen-s) { + display: flex; + } + } + } } } - svg{ + .documents { + display: flex; + flex-direction: column; + gap: var(--spacing-sm, 8px); + } + + svg { min-width: var(--spacing-3, 24px); min-height: var(--spacing-3, 24px); width: var(--spacing-3, 24px); diff --git a/src/front/Components/DesignSystem/DragAndDrop/index.tsx b/src/front/Components/DesignSystem/DragAndDrop/index.tsx index 1fe559a9..16ce9619 100644 --- a/src/front/Components/DesignSystem/DragAndDrop/index.tsx +++ b/src/front/Components/DesignSystem/DragAndDrop/index.tsx @@ -1,35 +1,161 @@ import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; -import React from "react"; import { DocumentPlusIcon } from "@heroicons/react/24/outline"; - -import classes from "./classes.module.scss"; import classNames from "classnames"; -import Separator, { ESeperatorColor, ESeperatorDirection } from "../Separator"; -import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "../Button"; +import React, { useCallback, useRef, useState } from "react"; -type IProps = {}; +import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "../Button"; +import Separator, { ESeperatorColor, ESeperatorDirection } from "../Separator"; +import classes from "./classes.module.scss"; +import DocumentElement from "./DocumentElement"; + +type IProps = { + name?: string; + title: string; + description: string; +}; + +type IMimeTypes = { + extension: string; + size: number; +}; + +const mimeTypesAccepted: { [key: string]: IMimeTypes } = { + "application/pdf": { + extension: "pdf", + size: 41943040, + }, + "image/jpeg": { + extension: "jpeg", + size: 41943040, + }, + "image/png": { + extension: "png", + size: 41943040, + }, + "image/jpg": { + extension: "jpg", + size: 41943040, + }, +}; + +type IDocument = { + id: string; + file: File | null; + isLoading: boolean; + error?: string; +}; export default function DragAndDrop(props: IProps) { - const {} = props; + const { name, title, description } = props; + const fileInputRef = useRef(null); + + const [documents, setDocuments] = useState([]); + + const handleFiles = useCallback((files: File[]) => { + files.forEach((file) => { + setDocuments((prevDocs) => [...prevDocs, { id: file.name, file: file, isLoading: true }]); + setTimeout(() => { + if (mimeTypesAccepted[file.type]) { + const newDoc: IDocument = { id: file.name, file, isLoading: false }; + setDocuments((prevDocs) => prevDocs.map((doc) => (doc.id === newDoc.id ? newDoc : doc))); + } else { + const errorDoc: IDocument = { id: file.name, file: null, isLoading: false, error: "Type de fichier non accepté" }; + setDocuments((prevDocs) => prevDocs.map((doc) => (doc.id === errorDoc.id ? errorDoc : doc))); + } + }, 1000); + }); + }, []); + + const handleDrop = useCallback( + (event: React.DragEvent) => { + event.preventDefault(); + const files = Array.from(event.dataTransfer.files); + handleFiles(files); + }, + [handleFiles], + ); + + const handleRemove = useCallback((id: string) => { + setDocuments((prevDocs) => prevDocs.filter((doc) => doc.id !== id)); + }, []); + + const handleBrowse = useCallback( + (event: React.ChangeEvent) => { + const files = Array.from(event.target.files || []); + handleFiles(files); + }, + [handleFiles], + ); + + const triggerFileInput = () => { + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; return ( -
- - +
e.preventDefault()}>
-
- - Drag and Drop ou - - -
+ + +
+
+ + {title} + + +
- - Description - +
+ +
+ + + {description} + +
+ {documents.length > 0 && ( +
+ {documents.map((doc) => ( + handleRemove(doc.id)} + error={doc.error} + /> + ))} +
+ )}
); + + function inputFile() { + return ( + + ); + } } diff --git a/src/front/Components/Layouts/DesignSystem/index.tsx b/src/front/Components/Layouts/DesignSystem/index.tsx index 619f47dd..187dc05f 100644 --- a/src/front/Components/Layouts/DesignSystem/index.tsx +++ b/src/front/Components/Layouts/DesignSystem/index.tsx @@ -90,7 +90,7 @@ export default function DesignSystem() { DesignSystem
Drag and Drop - + Separators