From 791aeacfc45c1fa2e9f0e2247d89211df56ed566 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 10:53:52 +0200 Subject: [PATCH 01/18] :sparkles: Dropdown responsive working --- .../Dropdown/DropdownMenu/classes.module.scss | 1 + .../DropdownNavigation/index.tsx | 81 ++++--------------- 2 files changed, 18 insertions(+), 64 deletions(-) diff --git a/src/front/Components/DesignSystem/Dropdown/DropdownMenu/classes.module.scss b/src/front/Components/DesignSystem/Dropdown/DropdownMenu/classes.module.scss index d8742a45..a56ca26e 100644 --- a/src/front/Components/DesignSystem/Dropdown/DropdownMenu/classes.module.scss +++ b/src/front/Components/DesignSystem/Dropdown/DropdownMenu/classes.module.scss @@ -30,6 +30,7 @@ overflow: visible; .content { max-height: 500px; + overflow: auto; opacity: 1; } } diff --git a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx index 50c7ef77..990f292d 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx +++ b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx @@ -1,8 +1,8 @@ -import React, { useCallback, useEffect } from "react"; +import React, { useEffect } from "react"; import { IBlock } from "../BlockList/Block"; import classes from "./classes.module.scss"; -import Typography, { ETypo, ETypoColor } from "../../Typography"; -import { ChevronDownIcon } from "@heroicons/react/24/outline"; +import Dropdown from "../../Dropdown"; +import { IOption } from "../../Dropdown/DropdownMenu/DropdownOption"; type IProps = { blocks: IBlock[]; onSelectedBlock: (block: IBlock) => void; @@ -11,72 +11,25 @@ type IProps = { export default function DropdownNavigation({ blocks, onSelectedBlock, defaultSelectedBlock = blocks[0] }: IProps) { const [selectedBlock, setSelectedBlock] = React.useState(defaultSelectedBlock ?? null); - const [isDropdownOpened, setIsDropdownOpened] = React.useState(false); - const rootRef = React.useRef(null); - - const selectBlock = useCallback( - (id: string) => { - setIsDropdownOpened(false); - setSelectedBlock(blocks.find((folder) => folder.id === id)!); - onSelectedBlock && onSelectedBlock(blocks.find((folder) => folder.id === id)!); - }, - [blocks, onSelectedBlock], - ); - - const handleOnClick = () => setIsDropdownOpened((prev) => !prev); - - useEffect(() => { - // on click outside of root, close dropdown - const handleClickOutside = (event: MouseEvent) => { - if (rootRef.current && !rootRef.current.contains(event.target as Node)) { - setIsDropdownOpened(false); - } - }; - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); useEffect(() => { if (defaultSelectedBlock) setSelectedBlock(defaultSelectedBlock); }, [defaultSelectedBlock]); - return ( -
- {selectedBlock && ( - <> -
-
- {selectedBlock.secondaryText && ( - - {selectedBlock.secondaryText} - - )} - - {selectedBlock.primaryText} - -
- -
- {isDropdownOpened && ( -
- {blocks - .filter((block) => block.id !== selectedBlock.id) - .map((block) => ( -
selectBlock(block.id)}> - {block.secondaryText && ( - - {block.secondaryText} - - )} - - {block.primaryText} - -
- ))} -
- )} - - )} + return ( +
+ { + return { + id: block.id, + label: { + subtext: block.primaryText, + text: block.secondaryText, + }, + } as IOption; + })} + selectedOption={selectedBlock ? { id: selectedBlock.id, label: selectedBlock.primaryText } : undefined} + />
); } From 6870ffd47cfe8bdb3a49c1428af9fe3197149e7d Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 11:09:56 +0200 Subject: [PATCH 02/18] :sparkles: Refacto users super admin --- .../DropdownNavigation/index.tsx | 11 ++ .../SearchBlockList/classes.module.scss | 1 + .../DefaultUserDashboard/classes.module.scss | 109 +------------- .../DefaultUserDashboard/index.tsx | 140 ++++++------------ src/front/Components/Layouts/Users/index.tsx | 2 +- 5 files changed, 67 insertions(+), 196 deletions(-) diff --git a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx index 990f292d..458f6d67 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx +++ b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx @@ -16,6 +16,16 @@ export default function DropdownNavigation({ blocks, onSelectedBlock, defaultSel if (defaultSelectedBlock) setSelectedBlock(defaultSelectedBlock); }, [defaultSelectedBlock]); + const handleDropDownSelect = (option: IOption) => { + const block = blocks.find((block) => block.id === option.id); + if (block) { + setSelectedBlock(block); + onSelectedBlock + ? onSelectedBlock(block) + : console.error("DropdownNavigation: onSelectedBlock prop is required to handle block selection"); + } + }; + return (
diff --git a/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss b/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss index d7a8ef40..4354b29d 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss +++ b/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss @@ -11,6 +11,7 @@ justify-content: flex-start; @media (max-width: $screen-m) { + height: auto; gap: 16px; padding: var(--spacing-lg, 24px); width: auto; diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss index 059853fe..882a9394 100644 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss +++ b/src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss @@ -1,115 +1,22 @@ @import "@Themes/constants.scss"; -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - .root { + position: relative; .content { display: flex; - overflow: hidden; + justify-content: flex-start; height: calc(100vh - var(--header-height)); - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; + @media (max-width: $screen-m) { + flex-direction: column; } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200 solid); - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; + min-width: calc(100% - 336px); overflow-y: auto; + padding: var(--spacing-lg, 24px); - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } + @media (max-width: $screen-m) { + width: 100%; } } } diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx index 27a6d89b..c3d6a1f6 100644 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx @@ -1,115 +1,67 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; -import { ChevronLeftIcon } from "@heroicons/react/20/solid"; import Users, { IGetUsersparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Header from "@Front/Components/DesignSystem/Header"; import Version from "@Front/Components/DesignSystem/Version"; import BackArrow from "@Front/Components/Elements/BackArrow"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; import User from "le-coffre-resources/dist/SuperAdmin"; -import Image from "next/image"; -import React, { ReactNode } from "react"; +import React, { ReactNode, useEffect } from "react"; import classes from "./classes.module.scss"; -import UserListContainer from "./UserListContainer"; +import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; type IProps = { title: string; children?: ReactNode; - onSelectedUser: (user: User) => void; - hasBackArrow: boolean; + hasBackArrow?: boolean; backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - users: User[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; }; -export default class DefaultUserDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, - }; - - public constructor(props: IProps) { - super(props); - this.state = { - users: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.users && } -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); +export default function DefaultUserDashboard(props: IProps) { + const { hasBackArrow, children, backArrowUrl } = props; + const [users, setUsers] = React.useState(null); + const router = useRouter(); + useEffect(() => { const query: IGetUsersparams = { include: { contact: true }, }; - const users = await Users.getInstance().get(query); - this.setState({ users }); - } - public override componentWillUnmount() { - this.onWindowResize(); - } + Users.getInstance() + .get(query) + .then((users) => setUsers(users)); + }, []); - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } + const onSelectedBlock = (block: IBlock) => { + router.push(Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path.replace("[uid]", block.id)); + }; - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( +
+
+
+ {users && ( + { + return { + id: user.uid, + primaryText: user.contact?.first_name + " " + user.contact?.last_name, + secondaryText: user.contact?.email, + } as IBlock; + })} + onSelectedBlock={onSelectedBlock} + /> + )} +
+ {hasBackArrow && ( +
+ +
+ )} + {children} +
+
+ +
+ ); } diff --git a/src/front/Components/Layouts/Users/index.tsx b/src/front/Components/Layouts/Users/index.tsx index 60f48873..b9da00ca 100644 --- a/src/front/Components/Layouts/Users/index.tsx +++ b/src/front/Components/Layouts/Users/index.tsx @@ -9,7 +9,7 @@ type IState = {}; export default class Users extends BasePage { public override render(): JSX.Element { return ( - +
Informations des utilisateurs From f6130e00b826b500d1baabcb15f2ec14c30f89e0 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 11:31:09 +0200 Subject: [PATCH 03/18] :sparkles: Fixing build and creating default dashboard --- .../FolderList/classes.module.scss | 14 -- .../DesignSystem/FolderList/index.tsx | 76 ---------- .../FolderListContainer/index.tsx | 4 - .../classes.module.scss | 0 .../DefaultDashboardWithList/index.tsx | 42 ++++++ .../DefaultNotaryDashboard/index.tsx | 5 +- .../OfficeListContainer/classes.module.scss | 23 --- .../OfficeListContainer/index.tsx | 44 ------ .../classes.module.scss | 116 --------------- .../DefaultOfficeDashboard/index.tsx | 140 +++++------------- .../UserListContainer/classes.module.scss | 23 --- .../UserListContainer/index.tsx | 44 ------ .../DefaultUserDashboard/index.tsx | 57 +++---- .../Layouts/Folder/AskDocuments/index.tsx | 2 +- .../Layouts/Folder/UpdateClient/index.tsx | 2 +- src/front/Components/Layouts/Folder/index.tsx | 10 +- .../UpdateFolderMetadata/index.tsx | 2 +- .../Layouts/FolderArchived/index.tsx | 6 +- .../Offices/OfficeInformations/index.tsx | 2 +- .../Components/Layouts/Offices/index.tsx | 2 +- .../Layouts/Users/UserInformations/index.tsx | 2 +- 21 files changed, 107 insertions(+), 509 deletions(-) delete mode 100644 src/front/Components/DesignSystem/FolderList/classes.module.scss delete mode 100644 src/front/Components/DesignSystem/FolderList/index.tsx rename src/front/Components/LayoutTemplates/{DefaultUserDashboard => DefaultDashboardWithList}/classes.module.scss (100%) create mode 100644 src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultOfficeDashboard/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/index.tsx diff --git a/src/front/Components/DesignSystem/FolderList/classes.module.scss b/src/front/Components/DesignSystem/FolderList/classes.module.scss deleted file mode 100644 index b1bf1c69..00000000 --- a/src/front/Components/DesignSystem/FolderList/classes.module.scss +++ /dev/null @@ -1,14 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - height: calc(100vh - 290px); - overflow-y: scroll; - - &.archived { - height: calc(100vh - 220px); - } - - .active { - background-color: var(--color-neutral-200); - } -} diff --git a/src/front/Components/DesignSystem/FolderList/index.tsx b/src/front/Components/DesignSystem/FolderList/index.tsx deleted file mode 100644 index c319582a..00000000 --- a/src/front/Components/DesignSystem/FolderList/index.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import Module from "@Front/Config/Module"; -import classNames from "classnames"; -import { OfficeFolder } from "le-coffre-resources/dist/Notary"; -import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import React from "react"; - -import FolderContainer from "../FolderContainer"; -import classes from "./classes.module.scss"; - -type IProps = { - folders: OfficeFolder[]; - isArchived: boolean; - onSelectedFolder?: (folder: OfficeFolder) => void; - onCloseLeftSide?: () => void; -}; - -type IPropsClass = IProps & { - selectedFolder: string; -}; - -type IState = {}; - -class FolderListClass extends React.Component { - private redirectPath: string = this.props.isArchived - ? Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.pages.FolderInformation.props.path - : Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path; - public override render(): JSX.Element { - return
{this.renderFolders()}
; - } - - private renderFolders(): JSX.Element[] { - const pendingFolders = this.props.folders - .filter((folder) => { - const pendingDocuments = (folder.documents ?? []).filter( - (document) => document.document_status === EDocumentStatus.DEPOSITED, - ); - return pendingDocuments.length >= 1; - }) - .sort((folder1, folder2) => { - return folder1.created_at! > folder2.created_at! ? -1 : 1; - }); - - const otherFolders = this.props.folders - .filter((folder) => { - const pendingDocuments = (folder.documents ?? []).filter( - (document) => document.document_status === EDocumentStatus.DEPOSITED, - ); - return pendingDocuments.length === 0; - }) - .sort((folder1, folder2) => { - return folder1.created_at! > folder2.created_at! ? -1 : 1; - }); - - return [...pendingFolders, ...otherFolders].map((folder) => { - return ( -
- - ; - -
- ); - }); - } -} - -export default function FolderList(props: IProps) { - const router = useRouter(); - let { folderUid } = router.query; - folderUid = folderUid as string; - return ; -} diff --git a/src/front/Components/DesignSystem/FolderListContainer/index.tsx b/src/front/Components/DesignSystem/FolderListContainer/index.tsx index 53df5b74..188bcfd6 100644 --- a/src/front/Components/DesignSystem/FolderListContainer/index.tsx +++ b/src/front/Components/DesignSystem/FolderListContainer/index.tsx @@ -11,8 +11,6 @@ import SearchBlockList from "../SearchBlockList"; type IProps = { folders: OfficeFolder[]; isArchived: boolean; - onSelectedFolder?: (folder: OfficeFolder) => void; - onCloseLeftSide?: () => void; }; export default function FolderListContainer(props: IProps) { @@ -64,10 +62,8 @@ export default function FolderListContainer(props: IProps) { const [blocks, setBlocks] = React.useState(getBlocks(folders)); const onSelectedFolder = (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); const folder = folders.find((folder) => folder.uid === block.id); if (!folder) return; - props.onSelectedFolder && props.onSelectedFolder(folder); const path = redirectPath.replace("[folderUid]", folder.uid ?? ""); router.push(path); }; diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss similarity index 100% rename from src/front/Components/LayoutTemplates/DefaultUserDashboard/classes.module.scss rename to src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx new file mode 100644 index 00000000..26d30539 --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -0,0 +1,42 @@ +import Header from "@Front/Components/DesignSystem/Header"; +import Version from "@Front/Components/DesignSystem/Version"; +import BackArrow from "@Front/Components/Elements/BackArrow"; +import React, { ReactNode } from "react"; + +import classes from "./classes.module.scss"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; + +export type IPropsDashboardWithList = { + title?: string; + children?: ReactNode; + isArchived?: boolean; + hasBackArrow?: boolean; + backArrowUrl?: string; + mobileBackText?: string; + blocksList: IBlock[]; + onSelectedBlock: (block: IBlock) => void; + headerConnected?: boolean; +}; + +export default function DefaultDashboardWithList(props: IPropsDashboardWithList) { + const { hasBackArrow, backArrowUrl, children, blocksList, onSelectedBlock, headerConnected = true } = props; + + return ( +
+
+
+ +
+ {hasBackArrow && ( +
+ +
+ )} + {children} +
+
+ +
+ ); +} diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx index 2a5e00a7..3b3a383b 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx @@ -13,14 +13,13 @@ type IProps = { title: string; children?: ReactNode; isArchived?: boolean; - onSelectedFolder?: (folder: OfficeFolder) => void; hasBackArrow?: boolean; backArrowUrl?: string; mobileBackText?: string; }; export default function DefaultNotaryDashboard(props: IProps) { - const { hasBackArrow, onSelectedFolder, backArrowUrl, children, isArchived } = props; + const { hasBackArrow, backArrowUrl, children, isArchived } = props; const [folders, setFolders] = React.useState([]); @@ -67,7 +66,7 @@ export default function DefaultNotaryDashboard(props: IProps) {
- +
{hasBackArrow && (
diff --git a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/classes.module.scss deleted file mode 100644 index a34b9618..00000000 --- a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/classes.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - width: calc(100vh - 83px); - display: flex; - flex-direction: column; - justify-content: space-between; - - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: 100vh; - height: 100vh; - overflow: auto; - border-right: 1px solid var(--color-neutral-200); - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/index.tsx deleted file mode 100644 index b3c92662..00000000 --- a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/OfficeListContainer/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import Module from "@Front/Config/Module"; -import { Office } from "le-coffre-resources/dist/SuperAdmin"; -import { useRouter } from "next/router"; -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - offices: Office[]; - onSelectedOffice?: (office: Office) => void; - onCloseLeftSide?: () => void; -}; - -export default function OfficeListContainer(props: IProps) { - const router = useRouter(); - - const { officeUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - return { - primaryText: office.crpcen + " - " + office.name, - id: office.uid!, - isActive: office.uid === officeUid, - }; - })} - onSelectedBlock={onSelectedBlock} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/classes.module.scss deleted file mode 100644 index f54563dd..00000000 --- a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/classes.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@import "@Themes/constants.scss"; - -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - -.root { - .content { - display: flex; - overflow: hidden; - height: calc(100vh - var(--header-height)); - - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; - } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200) solid; - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; - overflow-y: auto; - - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx index bbb729f3..0cdeaf38 100644 --- a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx @@ -1,112 +1,42 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; +import { Office } from "le-coffre-resources/dist/SuperAdmin"; +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; import Offices from "@Front/Api/LeCoffreApi/SuperAdmin/Offices/Offices"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; -import { Office } from "le-coffre-resources/dist/Notary"; -import Image from "next/image"; -import React, { ReactNode } from "react"; -import classes from "./classes.module.scss"; -import OfficeListContainer from "./OfficeListContainer"; -import { ChevronLeftIcon } from "@heroicons/react/24/outline"; +type IProps = IPropsDashboardWithList; -type IProps = { - title: string; - children?: ReactNode; - onSelectedOffice: (office: Office) => void; - hasBackArrow: boolean; - backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - offices: Office[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; -}; +export default function DefaultOfficeDashboard(props: IProps) { + const [offices, setOffices] = React.useState(null); + const router = useRouter(); + const { officeUid } = router.query; + useEffect(() => { + Offices.getInstance() + .get() + .then((offices) => setOffices(offices)); + }, []); -export default class DefaultOfficeDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, + const onSelectedBlock = (block: IBlock) => { + router.push(Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path.replace("[uid]", block.id)); }; - public constructor(props: IProps) { - super(props); - this.state = { - offices: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.offices && } -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); - const offices = await Offices.getInstance().get(); - this.setState({ offices }); - } - - public override componentWillUnmount() { - this.onWindowResize(); - } - - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } - - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( + ({ + id: office.uid!, + primaryText: office.name, + isActive: office.uid === officeUid, + secondaryText: office.crpcen, + })) + : [] + } + /> + ); } diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/classes.module.scss deleted file mode 100644 index a34b9618..00000000 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/classes.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - width: calc(100vh - 83px); - display: flex; - flex-direction: column; - justify-content: space-between; - - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: 100vh; - height: 100vh; - overflow: auto; - border-right: 1px solid var(--color-neutral-200); - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/index.tsx deleted file mode 100644 index 0842539d..00000000 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/UserListContainer/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import Module from "@Front/Config/Module"; -import User from "le-coffre-resources/dist/Notary"; -import { useRouter } from "next/router"; -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - users: User[]; - onSelectedUser?: (user: User) => void; - onCloseLeftSide?: () => void; -}; - -export default function UserListContainer(props: IProps) { - const router = useRouter(); - - const { userUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - return { - primaryText: user.contact?.first_name + " " + user.contact?.last_name, - id: user.uid!, - isActive: user.uid === userUid, - }; - })} - onSelectedBlock={onSelectedBlock} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx index c3d6a1f6..e3b97389 100644 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx @@ -1,27 +1,18 @@ import Users, { IGetUsersparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; import User from "le-coffre-resources/dist/SuperAdmin"; -import React, { ReactNode, useEffect } from "react"; +import React, { useEffect } from "react"; -import classes from "./classes.module.scss"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; import { useRouter } from "next/router"; import Module from "@Front/Config/Module"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; -type IProps = { - title: string; - children?: ReactNode; - hasBackArrow?: boolean; - backArrowUrl?: string; -}; +type IProps = IPropsDashboardWithList; export default function DefaultUserDashboard(props: IProps) { - const { hasBackArrow, children, backArrowUrl } = props; const [users, setUsers] = React.useState(null); const router = useRouter(); + const { userUid } = router.query; useEffect(() => { const query: IGetUsersparams = { include: { contact: true }, @@ -37,31 +28,19 @@ export default function DefaultUserDashboard(props: IProps) { }; return ( -
-
-
- {users && ( - { - return { - id: user.uid, - primaryText: user.contact?.first_name + " " + user.contact?.last_name, - secondaryText: user.contact?.email, - } as IBlock; - })} - onSelectedBlock={onSelectedBlock} - /> - )} -
- {hasBackArrow && ( -
- -
- )} - {children} -
-
- -
+ ({ + id: user.uid!, + primaryText: user.contact?.first_name + " " + user.contact?.last_name, + isActive: user.uid === userUid, + secondaryText: user.contact?.email, + })) + : [] + } + /> ); } diff --git a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx index a0af3c56..fc6f4ce3 100644 --- a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx @@ -50,7 +50,7 @@ class AskDocumentsClass extends BasePage { .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid); return ( - {}}> +
diff --git a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx index 75d08e65..92095538 100644 --- a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx @@ -74,7 +74,7 @@ class UpdateClientClass extends BasePage { public override render(): JSX.Element { return ( - +
diff --git a/src/front/Components/Layouts/Folder/index.tsx b/src/front/Components/Layouts/Folder/index.tsx index a9aeaa84..fdcda8f0 100644 --- a/src/front/Components/Layouts/Folder/index.tsx +++ b/src/front/Components/Layouts/Folder/index.tsx @@ -6,10 +6,10 @@ import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNot import Module from "@Front/Config/Module"; import JwtService from "@Front/Services/JwtService/JwtService"; import { DocumentIcon } from "@heroicons/react/24/outline"; -import User, { OfficeFolder } from "le-coffre-resources/dist/Notary"; +import User from "le-coffre-resources/dist/Notary"; import Image from "next/image"; import Link from "next/link"; -import { useCallback, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import classes from "./classes.module.scss"; import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; @@ -17,14 +17,10 @@ import EFolderStatus from "le-coffre-resources/dist/Customer/EFolderStatus"; import { useRouter } from "next/router"; export default function Folder() { - const [_folder, setFolder] = useState(null); const [_isArchivedModalOpen, _setIsArchivedModalOpen] = useState(true); const router = useRouter(); const [activeUser, setActiveUser] = useState(); - const onSelectedFolder = useCallback((folder: OfficeFolder): void => { - setFolder(folder); - }, []); useEffect(() => { const decodedJwt = JwtService.getInstance().decodeJwt(); @@ -59,7 +55,7 @@ export default function Folder() { }, [router]); return ( - +
diff --git a/src/front/Components/Layouts/FolderArchived/UpdateFolderMetadata/index.tsx b/src/front/Components/Layouts/FolderArchived/UpdateFolderMetadata/index.tsx index a74522b7..fc3708bb 100644 --- a/src/front/Components/Layouts/FolderArchived/UpdateFolderMetadata/index.tsx +++ b/src/front/Components/Layouts/FolderArchived/UpdateFolderMetadata/index.tsx @@ -39,7 +39,7 @@ class UpdateFolderMetadataClass extends BasePage { .get() .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.selectedFolderUid); return ( - +
diff --git a/src/front/Components/Layouts/FolderArchived/index.tsx b/src/front/Components/Layouts/FolderArchived/index.tsx index 748e2001..2ee150f2 100644 --- a/src/front/Components/Layouts/FolderArchived/index.tsx +++ b/src/front/Components/Layouts/FolderArchived/index.tsx @@ -23,11 +23,7 @@ export default class FolderArchived extends BasePage { // TODO: Message if the user has not created any folder yet public override render(): JSX.Element { return ( - +
Informations du dossier diff --git a/src/front/Components/Layouts/Offices/OfficeInformations/index.tsx b/src/front/Components/Layouts/Offices/OfficeInformations/index.tsx index f6e8b91e..2a761172 100644 --- a/src/front/Components/Layouts/Offices/OfficeInformations/index.tsx +++ b/src/front/Components/Layouts/Offices/OfficeInformations/index.tsx @@ -117,7 +117,7 @@ export default function OfficeInformations(props: IProps) { ); return ( - +
Office {officeSelected?.crpcen + " - " + officeSelected?.name} diff --git a/src/front/Components/Layouts/Offices/index.tsx b/src/front/Components/Layouts/Offices/index.tsx index bded3736..5c060f27 100644 --- a/src/front/Components/Layouts/Offices/index.tsx +++ b/src/front/Components/Layouts/Offices/index.tsx @@ -9,7 +9,7 @@ type IState = {}; export default class Offices extends BasePage { public override render(): JSX.Element { return ( - +
Informations des offices diff --git a/src/front/Components/Layouts/Users/UserInformations/index.tsx b/src/front/Components/Layouts/Users/UserInformations/index.tsx index 2ffc406f..2a723553 100644 --- a/src/front/Components/Layouts/Users/UserInformations/index.tsx +++ b/src/front/Components/Layouts/Users/UserInformations/index.tsx @@ -210,7 +210,7 @@ export default function UserInformations(props: IProps) { }, [currentAppointment, getUser]); return ( - + {!isLoading && (
From 354d6576a4359345d0ba53bb12e9561a04edc7e4 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 11:37:12 +0200 Subject: [PATCH 04/18] :sparkles: Fixing build --- .../LayoutTemplates/DefaultDashboardWithList/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx index 26d30539..67fce823 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -14,12 +14,15 @@ export type IPropsDashboardWithList = { hasBackArrow?: boolean; backArrowUrl?: string; mobileBackText?: string; +}; + +type IProps = IPropsDashboardWithList & { blocksList: IBlock[]; onSelectedBlock: (block: IBlock) => void; headerConnected?: boolean; }; -export default function DefaultDashboardWithList(props: IPropsDashboardWithList) { +export default function DefaultDashboardWithList(props: IProps) { const { hasBackArrow, backArrowUrl, children, blocksList, onSelectedBlock, headerConnected = true } = props; return ( From 5f1da86813da2596ecb6483c673fe4e3e1011207 Mon Sep 17 00:00:00 2001 From: Max S Date: Mon, 29 Jul 2024 11:48:55 +0200 Subject: [PATCH 05/18] Autocomplete Multi Select (chip input) --- .../DesignSystem/Autocomplete/index.tsx | 31 ++++--- .../Chip/classes.module.scss | 20 +++++ .../AutocompleteMultiSelect/Chip/index.tsx | 26 ++++++ .../ChipContainer/classes.module.scss | 73 +++++++++++++++ .../ChipContainer/index.tsx | 90 +++++++++++++++++++ .../classes.module.scss | 7 ++ .../AutocompleteMultiSelect/index.tsx | 88 ++++++++++++++++++ .../Dropdown/DropdownMenu/index.tsx | 35 ++++++-- .../DesignSystem/Dropdown/index.tsx | 12 ++- .../IconButton/classes.module.scss | 4 + .../DesignSystem/SearchBar/index.tsx | 32 +++++-- .../DesignSystem/Typography/index.tsx | 2 + .../Components/Layouts/DesignSystem/index.tsx | 37 +++++--- 13 files changed, 415 insertions(+), 42 deletions(-) create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/classes.module.scss create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/index.tsx create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/classes.module.scss create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/index.tsx create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/classes.module.scss create mode 100644 src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx diff --git a/src/front/Components/DesignSystem/Autocomplete/index.tsx b/src/front/Components/DesignSystem/Autocomplete/index.tsx index 8ecfc3db..7b081c11 100644 --- a/src/front/Components/DesignSystem/Autocomplete/index.tsx +++ b/src/front/Components/DesignSystem/Autocomplete/index.tsx @@ -6,6 +6,7 @@ import { IOption } from "../Dropdown/DropdownMenu/DropdownOption"; import SearchBar from "../SearchBar"; import Typography, { ETypo, ETypoColor } from "../Typography"; import classes from "./classes.module.scss"; +import { getLabel } from "../Dropdown"; type IProps = { options: IOption[]; @@ -51,24 +52,21 @@ export default function Autocomplete(props: IProps) { }, [selectedOptionProps]); const handleSelectOption = useCallback( - (option: IOption) => { - setSelectedOption(option); - setSearchValue(getLabel(option) || ""); + (newOption: IOption, _options: IOption[]) => { + setSelectedOption(newOption); + setSearchValue(getLabel(newOption) || ""); openable.close(); }, [openable], ); - function getLabel(option: IOption | null): string | null { - if (!option) return null; - if (typeof option.label === "string") { - return option.label; - } - return `${option.label.text} ${option.label.subtext}`; - } - return ( - +
{label && ( @@ -76,7 +74,14 @@ export default function Autocomplete(props: IProps) { )}
- + setSelectedOption(null)} + onFocus={openable.open} + />
); } diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/classes.module.scss b/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/classes.module.scss new file mode 100644 index 00000000..9ebc273e --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/classes.module.scss @@ -0,0 +1,20 @@ +@import "@Themes/constants.scss"; + +.root { + width: fit-content; + height: 32px; + + display: inline-flex; + padding: 4px 12px; + align-items: center; + gap: 8px; + + border-radius: var(--input-chip-radius, 360px); + border: 1px solid var(--input-chip-default-border, #b7d1f1); + background: var(--input-chip-default-background, #e5eefa); + + &:hover { + background-color: var(--input-chip-hovered-background); + border-color: var(--input-chip-hovered-border); + } +} diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/index.tsx b/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/index.tsx new file mode 100644 index 00000000..2bcfa230 --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/Chip/index.tsx @@ -0,0 +1,26 @@ +import { XMarkIcon } from "@heroicons/react/24/outline"; +import classNames from "classnames"; +import React from "react"; + +import IconButton from "../../IconButton"; +import Typography, { ETypo, ETypoColor } from "../../Typography"; +import classes from "./classes.module.scss"; + +type IProps = { + text: string; + className?: string; + onDelete?: () => void; +}; + +export default function Chip(props: IProps) { + const { className, text, onDelete } = props; + + return ( +
+ + {text} + + } onClick={onDelete} /> +
+ ); +} diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/classes.module.scss b/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/classes.module.scss new file mode 100644 index 00000000..fa4937cd --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/classes.module.scss @@ -0,0 +1,73 @@ +@import "@Themes/constants.scss"; + +.root { + border-radius: var(--input-radius, 0px); + border: 1px solid var(--input-main-border-filled, #6d7e8a); + background: var(--input-background, #fff); + + svg { + stroke: var(--button-icon-button-default-default); + } + + &:hover { + border-radius: var(--input-radius, 0px); + border: 1px solid var(--input-main-border-hovered, #b4bec5); + background: var(--input-background, #fff); + } + + &[data-has-value="true"] { + border-radius: var(--input-radius, 0px); + border: 1px solid var(--input-main-border-filled, #6d7e8a); + background: var(--input-background, #fff); + } + + &[data-is-focused="true"] { + border-radius: var(--input-radius, 0px); + border: 1px solid var(--input-main-border-focused, #005bcb); + background: var(--input-background, #fff); + } + + &[data-is-disabled="true"] { + opacity: var(--opacity-disabled, 0.3); + pointer-events: none; + } + + .content { + display: flex; + align-items: center; + align-content: center; + gap: 16px var(--spacing-2, 16px); + flex-wrap: wrap; + + min-height: 56px; + + padding: var(--spacing-1-5, 12px) var(--spacing-sm, 8px); + + .input { + flex: 1; + border: none; + + color: var(--input-placeholder-filled, #24282e); + + /* text/md/semibold */ + font-family: var(--font-text-family, Poppins); + font-size: 16px; + font-style: normal; + font-weight: var(--font-text-weight-semibold, 600); + line-height: normal; + letter-spacing: 0.08px; + width: 100%; + + &::placeholder { + color: var(--input-placeholder-empty, #6d7e8a); + /* text/md/regular */ + font-family: var(--font-text-family, Poppins); + font-size: 16px; + font-style: normal; + font-weight: var(--font-text-weight-regular, 400); + line-height: normal; + letter-spacing: 0.08px; + } + } + } +} diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/index.tsx b/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/index.tsx new file mode 100644 index 00000000..5e926fdc --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/ChipContainer/index.tsx @@ -0,0 +1,90 @@ +import React, { useCallback, useEffect } from "react"; + +import { getLabel } from "../../Dropdown"; +import { IOption } from "../../Dropdown/DropdownMenu/DropdownOption"; +import Chip from "../Chip"; +import classes from "./classes.module.scss"; + +type IProps = { + selectedOptions: IOption[]; + onSelectedOptionsChange: (options: IOption[]) => void; + onChange?: (input: string) => void; + value?: string; + placeholder?: string; + disabled?: boolean; + onClear?: () => void; + onFocus?: () => void; + onBlur?: () => void; +}; + +export default function ChipContainer(props: IProps) { + const { + selectedOptions, + onChange, + value: propValue, + placeholder = "Rechercher", + disabled = false, + onFocus, + onBlur, + onSelectedOptionsChange, + } = props; + + const [isFocused, setIsFocused] = React.useState(false); + const [value, setValue] = React.useState(propValue || ""); + + const changeValue = useCallback( + (value: string) => { + setValue(value); + onChange && onChange(value); + }, + [onChange], + ); + + const handleOnChange = useCallback((event: React.ChangeEvent) => changeValue(event.target.value), [changeValue]); + + const handleFocus = useCallback(() => { + setIsFocused(true); + onFocus?.(); + }, [onFocus]); + + const handleBlur = useCallback( + (e: React.FocusEvent) => { + setIsFocused(false); + onBlur?.(); + }, + [onBlur], + ); + + const onChipDelete = useCallback( + (option: IOption) => { + const newSelectedOptions = selectedOptions.filter((selectedOption) => selectedOption.id !== option.id); + onSelectedOptionsChange && onSelectedOptionsChange(newSelectedOptions); + }, + [selectedOptions, onSelectedOptionsChange], + ); + + useEffect(() => { + if (propValue !== undefined) { + setValue(propValue); + } + }, [propValue]); + + return ( +
+
+ {selectedOptions.map((option) => ( + onChipDelete(option)} /> + ))} + +
+
+ ); +} diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/classes.module.scss b/src/front/Components/DesignSystem/AutocompleteMultiSelect/classes.module.scss new file mode 100644 index 00000000..0a331a1d --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/classes.module.scss @@ -0,0 +1,7 @@ +@import "@Themes/constants.scss"; + +.root { + .label { + padding: 0px var(--spacing-2, 16px); + } +} diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx new file mode 100644 index 00000000..36182827 --- /dev/null +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx @@ -0,0 +1,88 @@ +import useOpenable from "@Front/Hooks/useOpenable"; +import { useCallback, useEffect, useState } from "react"; + +import DropdownMenu from "../Dropdown/DropdownMenu"; +import { IOption } from "../Dropdown/DropdownMenu/DropdownOption"; +import Typography, { ETypo, ETypoColor } from "../Typography"; +import classes from "./classes.module.scss"; +import ChipContainer from "./ChipContainer"; +import { getLabel } from "../Dropdown"; + +type IProps = { + options: IOption[]; + placeholder?: string; + disabled?: boolean; + label?: string; + onSelect?: (option: IOption) => void; + selectedOptions?: IOption[] | null; +}; + +export default function Autocomplete(props: IProps) { + const { options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props; + const [selectedOptions, setSelectedOptions] = useState(selectedOptionsProps ?? null); + const [searchValue, setSearchValue] = useState(""); + const [filteredOptions, setFilteredOptions] = useState(options); + const openable = useOpenable({ defaultOpen: false }); + + useEffect(() => { + if (searchValue) { + const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase())); + console.log(filteredOptions); + if (filteredOptions.length === 0) + return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]); + return setFilteredOptions(filteredOptions); + } + return setFilteredOptions(options); + }, [searchValue, options]); + + const handleSearchChange = useCallback( + (value: string) => { + setSearchValue(value); + if (value) { + openable.open(); + } else { + openable.close(); + } + }, + [openable], + ); + + useEffect(() => { + setSelectedOptions(selectedOptionsProps ?? null); + }, [selectedOptionsProps]); + + const handleSelectOption = useCallback( + (_newOption: IOption, options: IOption[]) => { + setSelectedOptions(options); + setSearchValue(""); + openable.close(); + }, + [openable], + ); + + return ( + +
+ {label && ( + + {label} + + )} +
+ setSelectedOptions(null)} + onFocus={openable.open} + selectedOptions={selectedOptions ?? []} + onSelectedOptionsChange={setSelectedOptions} + /> +
+ ); +} diff --git a/src/front/Components/DesignSystem/Dropdown/DropdownMenu/index.tsx b/src/front/Components/DesignSystem/Dropdown/DropdownMenu/index.tsx index c19f6982..5ad68d7b 100644 --- a/src/front/Components/DesignSystem/Dropdown/DropdownMenu/index.tsx +++ b/src/front/Components/DesignSystem/Dropdown/DropdownMenu/index.tsx @@ -1,12 +1,12 @@ import classNames from "classnames"; -import React, { useCallback } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import classes from "./classes.module.scss"; import DropdownOption, { IOption } from "./DropdownOption"; type IProps = { options: IOption[]; - selectedOption: IOption | null; + selectedOptions: IOption[]; children: React.ReactNode; openable: { isOpen: boolean; @@ -14,21 +14,40 @@ type IProps = { close: () => void; toggle: () => void; }; - onSelect?: (option: IOption) => void; + onSelect?: (newOption: IOption, options: IOption[]) => void; }; export default function DropdownMenu(props: IProps) { - const { children, options, onSelect, openable, selectedOption } = props; + const { children, options, onSelect, openable, selectedOptions } = props; + const ref = useRef(null); const handleSelect = useCallback( (option: IOption) => { - onSelect?.(option); + const newOptions = selectedOptions.some((selectedOption) => selectedOption.id === option.id) + ? selectedOptions + : [...selectedOptions, option]; + + onSelect?.(option, newOptions); openable.close(); }, - [onSelect, openable], + [onSelect, openable, selectedOptions], ); + const handleClickOutside = useCallback( + (event: MouseEvent) => { + if (ref.current && !ref.current.contains(event.target as Node)) { + openable.close(); + } + }, + [openable], + ); + + useEffect(() => { + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, [handleClickOutside]); + return ( -
+
{children}
{options.map((option) => { @@ -39,6 +58,6 @@ export default function DropdownMenu(props: IProps) { ); function isActive(option: IOption): boolean { - return selectedOption?.id === option.id; + return selectedOptions.some((selectedOption) => selectedOption.id === option.id); } } diff --git a/src/front/Components/DesignSystem/Dropdown/index.tsx b/src/front/Components/DesignSystem/Dropdown/index.tsx index a3875994..b00cacea 100644 --- a/src/front/Components/DesignSystem/Dropdown/index.tsx +++ b/src/front/Components/DesignSystem/Dropdown/index.tsx @@ -27,15 +27,19 @@ export default function Dropdown(props: IProps) { }, [selectedOptionProps]); const handleOnSelect = useCallback( - (option: IOption) => { - setSelectedOption(option); - onSelect?.(option); + (newOption: IOption, _options: IOption[]) => { + setSelectedOption(newOption); + onSelect?.(newOption); }, [onSelect], ); return ( - +
{label && ( diff --git a/src/front/Components/DesignSystem/IconButton/classes.module.scss b/src/front/Components/DesignSystem/IconButton/classes.module.scss index 920f424e..cc78b949 100644 --- a/src/front/Components/DesignSystem/IconButton/classes.module.scss +++ b/src/front/Components/DesignSystem/IconButton/classes.module.scss @@ -94,6 +94,10 @@ } } + &.default { + padding: 0; + } + &.disabled { cursor: default; opacity: var(--opacity-disabled, 0.3); diff --git a/src/front/Components/DesignSystem/SearchBar/index.tsx b/src/front/Components/DesignSystem/SearchBar/index.tsx index 113305ce..ebcce2fe 100644 --- a/src/front/Components/DesignSystem/SearchBar/index.tsx +++ b/src/front/Components/DesignSystem/SearchBar/index.tsx @@ -1,16 +1,21 @@ +import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; import React, { useCallback, useEffect } from "react"; import classes from "./classes.module.scss"; -import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; type IProps = { onChange?: (input: string) => void; value?: string; placeholder?: string; disabled?: boolean; + onClear?: () => void; + onFocus?: () => void; + onBlur?: () => void; }; -export default function SearchBar({ onChange, value: propValue, placeholder = "Rechercher", disabled = false }: IProps) { +export default function SearchBar(props: IProps) { + const { onChange, value: propValue, placeholder = "Rechercher", disabled = false, onClear, onFocus, onBlur } = props; + const [isFocused, setIsFocused] = React.useState(false); const [value, setValue] = React.useState(propValue || ""); @@ -22,10 +27,25 @@ export default function SearchBar({ onChange, value: propValue, placeholder = "R [onChange], ); - const handleOnChange = (event: React.ChangeEvent) => changeValue(event.target.value); - const handleFocus = () => setIsFocused(true); - const handleBlur = () => setIsFocused(false); - const clearValue = () => changeValue(""); + const handleOnChange = useCallback((event: React.ChangeEvent) => changeValue(event.target.value), [changeValue]); + + const handleFocus = useCallback(() => { + setIsFocused(true); + onFocus?.(); + }, [onFocus]); + + const handleBlur = useCallback( + (e: React.FocusEvent) => { + setIsFocused(false); + onBlur?.(); + }, + [onBlur], + ); + + const clearValue = useCallback(() => { + changeValue(""); + onClear?.(); + }, [changeValue, onClear]); useEffect(() => { if (propValue !== undefined) { diff --git a/src/front/Components/DesignSystem/Typography/index.tsx b/src/front/Components/DesignSystem/Typography/index.tsx index 9f63599c..584397a6 100644 --- a/src/front/Components/DesignSystem/Typography/index.tsx +++ b/src/front/Components/DesignSystem/Typography/index.tsx @@ -159,6 +159,8 @@ export enum ETypoColor { DROPDOWN_CONTRAST_DEFAULT = "--dropdown-contrast-default", DROPDOWN_CONTRAST_ACTIVE = "--dropdown-contrast-active", + + INPUT_CHIP_CONTRAST = "--input-chip-contrast", } export default function Typography(props: IProps) { diff --git a/src/front/Components/Layouts/DesignSystem/index.tsx b/src/front/Components/Layouts/DesignSystem/index.tsx index 1ca60d3e..d8121590 100644 --- a/src/front/Components/Layouts/DesignSystem/index.tsx +++ b/src/front/Components/Layouts/DesignSystem/index.tsx @@ -1,4 +1,6 @@ import Alert, { EAlertVariant } from "@Front/Components/DesignSystem/Alert"; +import Autocomplete from "@Front/Components/DesignSystem/Autocomplete"; +import AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect"; import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import CircleProgress from "@Front/Components/DesignSystem/CircleProgress"; import Dropdown from "@Front/Components/DesignSystem/Dropdown"; @@ -19,19 +21,10 @@ import NumberPicker from "@Front/Components/Elements/NumberPicker"; import Tabs from "@Front/Components/Elements/Tabs"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import useOpenable from "@Front/Hooks/useOpenable"; -import { - ArchiveBoxIcon, - ArrowLongLeftIcon, - ArrowLongRightIcon, - EllipsisHorizontalIcon, - PencilSquareIcon, - UsersIcon, - XMarkIcon, -} from "@heroicons/react/24/outline"; +import { ArchiveBoxIcon, ArrowLongLeftIcon, ArrowLongRightIcon, EllipsisHorizontalIcon, PencilSquareIcon, UsersIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { useCallback, useMemo, useState } from "react"; import classes from "./classes.module.scss"; -import Autocomplete from "@Front/Components/DesignSystem/Autocomplete"; export default function DesignSystem() { const { isOpen, open, close } = useOpenable(); @@ -84,6 +77,29 @@ export default function DesignSystem() {
+ Autocomplete Multi Select + + Autocomplete Dropdown From b33037d8df16443202d1d9d3ccb1c483248d957b Mon Sep 17 00:00:00 2001 From: Max S Date: Mon, 29 Jul 2024 11:49:45 +0200 Subject: [PATCH 06/18] rename --- .../Components/DesignSystem/AutocompleteMultiSelect/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx index 36182827..4274bf89 100644 --- a/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx @@ -17,7 +17,7 @@ type IProps = { selectedOptions?: IOption[] | null; }; -export default function Autocomplete(props: IProps) { +export default function AutocompleteMultiSelect(props: IProps) { const { options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props; const [selectedOptions, setSelectedOptions] = useState(selectedOptionsProps ?? null); const [searchValue, setSearchValue] = useState(""); From 5186b1bd45591bc3c8f1db37a385e86fd34d036a Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 11:54:38 +0200 Subject: [PATCH 07/18] :sparkles: Every dashboard working --- .../SearchBlockList/classes.module.scss | 1 + .../DesignSystem/SearchBlockList/index.tsx | 4 +- .../classes.module.scss | 23 --- .../CollaboratorListContainer/index.tsx | 44 ----- .../classes.module.scss | 116 ------------- .../DefaultCollaboratorDashboard/index.tsx | 147 +++++----------- .../DefaultDashboardWithList/index.tsx | 14 +- .../DeedTypeListContainer/classes.module.scss | 32 ---- .../DeedTypeListContainer/index.tsx | 48 ------ .../classes.module.scss | 116 ------------- .../DefaultDeedTypeDashboard/index.tsx | 147 +++++----------- .../classes.module.scss | 30 ---- .../DocumentTypeListContainer/index.tsx | 48 ------ .../classes.module.scss | 116 ------------- .../DefaultDocumentTypesDashboard/index.tsx | 163 ++++++------------ .../DefaultOfficeDashboard/index.tsx | 2 +- .../RoleListContainer/classes.module.scss | 32 ---- .../RoleListContainer/index.tsx | 53 ------ .../DefaultRoleDashboard/classes.module.scss | 116 ------------- .../DefaultRoleDashboard/index.tsx | 146 +++++----------- .../DefaultUserDashboard/index.tsx | 2 +- 21 files changed, 175 insertions(+), 1225 deletions(-) delete mode 100644 src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/classes.module.scss delete mode 100644 src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultRoleDashboard/classes.module.scss diff --git a/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss b/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss index 4354b29d..cc668f67 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss +++ b/src/front/Components/DesignSystem/SearchBlockList/classes.module.scss @@ -1,6 +1,7 @@ @import "@Themes/constants.scss"; .root { width: 336px; + min-width: 336px; height: 100%; max-height: 100%; diff --git a/src/front/Components/DesignSystem/SearchBlockList/index.tsx b/src/front/Components/DesignSystem/SearchBlockList/index.tsx index 0ed80f61..0ca8fd77 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/index.tsx +++ b/src/front/Components/DesignSystem/SearchBlockList/index.tsx @@ -7,7 +7,7 @@ import Button from "../Button"; import { useRouter } from "next/router"; import DropdownNavigation from "./DropdownNavigation"; -type IProps = { +export type ISearchBlockListProps = { blocks: IBlock[]; onSelectedBlock: (block: IBlock) => void; bottomButton?: { @@ -15,7 +15,7 @@ type IProps = { link: string; }; }; -export default function SearchBlockList(props: IProps) { +export default function SearchBlockList(props: ISearchBlockListProps) { const { blocks, onSelectedBlock, bottomButton } = props; const [selectedBlock, setSelectedBlock] = useState(null); diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss deleted file mode 100644 index abe261a4..00000000 --- a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - width: calc(100vh - 83px); - display: flex; - flex-direction: column; - justify-content: space-between; - - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: calc(100vh - 215px); - height: 100%; - border-right: 1px solid var(--color-neutral-200); - overflow: auto; - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx deleted file mode 100644 index eee22e10..00000000 --- a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import User from "le-coffre-resources/dist/Notary"; -import { useRouter } from "next/router"; -import Module from "@Front/Config/Module"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - collaborators: User[]; - onSelectedCollaborator?: (user: User) => void; - onCloseLeftSide?: () => void; -}; - -export default function CollaboratorListContainer(props: IProps) { - const router = useRouter(); - - const { collaboratorUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.Collaborators.pages.CollaboratorInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - return { - primaryText: user.contact?.first_name + " " + user.contact?.last_name, - id: user.uid!, - isActive: user.uid === collaboratorUid, - }; - })} - onSelectedBlock={onSelectedBlock} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss deleted file mode 100644 index f54563dd..00000000 --- a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@import "@Themes/constants.scss"; - -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - -.root { - .content { - display: flex; - overflow: hidden; - height: calc(100vh - var(--header-height)); - - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; - } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200) solid; - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; - overflow-y: auto; - - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/index.tsx index afa164f5..f4c86d3c 100644 --- a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/index.tsx @@ -1,93 +1,20 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; -import Users, { IGetUsersparams } from "@Front/Api/LeCoffreApi/Admin/Users/Users"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; +import User from "le-coffre-resources/dist/Notary"; import JwtService from "@Front/Services/JwtService/JwtService"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; -import User from "le-coffre-resources/dist/Admin"; -import Image from "next/image"; -import React, { ReactNode } from "react"; +import Users, { IGetUsersparams } from "@Front/Api/LeCoffreApi/Admin/Users/Users"; -import classes from "./classes.module.scss"; -import CollaboratorListContainer from "./CollaboratorListContainer"; -import { ChevronLeftIcon } from "@heroicons/react/24/solid"; +type IProps = IPropsDashboardWithList; -type IProps = { - title: string; - children?: ReactNode; - onSelectedUser: (user: User) => void; - hasBackArrow: boolean; - backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - collaborators: User[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; -}; - -export default class DefaultCollaboratorDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, - }; - - public constructor(props: IProps) { - super(props); - this.state = { - collaborators: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.collaborators && ( - - )} -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); +export default function DefaultCollaboratorDashboard(props: IProps) { + const [collaborators, setCollaborators] = React.useState(null); + const router = useRouter(); + const { collaboratorUid } = router.query; + useEffect(() => { const jwt = JwtService.getInstance().decodeJwt(); if (!jwt) return; const query: IGetUsersparams = { @@ -102,27 +29,31 @@ export default class DefaultCollaboratorDashboard extends React.Component setCollaborators(users)); + }, []); - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } + const onSelectedBlock = (block: IBlock) => { + router.push( + Module.getInstance().get().modules.pages.Collaborators.pages.CollaboratorInformations.props.path.replace("[uid]", block.id), + ); + }; - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( + ({ + id: collaborator.uid!, + primaryText: collaborator.contact?.first_name + " " + collaborator.contact?.last_name, + isActive: collaborator.uid === collaboratorUid, + secondaryText: collaborator.contact?.email, + })) + : [] + } + /> + ); } diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx index 67fce823..3f3bd44a 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -4,8 +4,7 @@ import BackArrow from "@Front/Components/Elements/BackArrow"; import React, { ReactNode } from "react"; import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; +import SearchBlockList, { ISearchBlockListProps } from "@Front/Components/DesignSystem/SearchBlockList"; export type IPropsDashboardWithList = { title?: string; @@ -14,22 +13,19 @@ export type IPropsDashboardWithList = { hasBackArrow?: boolean; backArrowUrl?: string; mobileBackText?: string; -}; - -type IProps = IPropsDashboardWithList & { - blocksList: IBlock[]; - onSelectedBlock: (block: IBlock) => void; headerConnected?: boolean; }; +type IProps = IPropsDashboardWithList & ISearchBlockListProps; + export default function DefaultDashboardWithList(props: IProps) { - const { hasBackArrow, backArrowUrl, children, blocksList, onSelectedBlock, headerConnected = true } = props; + const { hasBackArrow, backArrowUrl, children, blocks, onSelectedBlock, headerConnected = true, bottomButton } = props; return (
- +
{hasBackArrow && (
diff --git a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/classes.module.scss deleted file mode 100644 index a1a8a9b9..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/classes.module.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - width: calc(100vh - 83px); - display: flex; - flex-direction: column; - justify-content: space-between; - - position: relative; - - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: calc(100vh - 290px); - height: calc(100vh - 290px); - overflow: auto; - border-right: 1px solid var(--color-neutral-200); - } - - .create-container { - position: absolute; - bottom: 0; - left: 0; - right: 0; - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/index.tsx deleted file mode 100644 index fd94a36d..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/DeedTypeListContainer/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes"; -import Module from "@Front/Config/Module"; -import { DeedType } from "le-coffre-resources/dist/Admin"; -import { useRouter } from "next/router"; -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - deedTypes: DeedType[]; - onSelectedDeed?: (deed: DeedTypes) => void; - onCloseLeftSide?: () => void; -}; - -export default function DeedListContainer(props: IProps) { - const router = useRouter(); - const { deedTypeUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.DeedTypes.pages.DeedTypesInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - return { - primaryText: deed.name, - id: deed.uid!, - isActive: deedTypeUid === deed.uid, - }; - })} - onSelectedBlock={onSelectedBlock} - bottomButton={{ - link: Module.getInstance().get().modules.pages.DeedTypes.pages.Create.props.path, - text: "Créer un type d'acte", - }} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/classes.module.scss deleted file mode 100644 index f54563dd..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/classes.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@import "@Themes/constants.scss"; - -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - -.root { - .content { - display: flex; - overflow: hidden; - height: calc(100vh - var(--header-height)); - - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; - } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200) solid; - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; - overflow-y: auto; - - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/index.tsx index 6db68829..f62d1e5d 100644 --- a/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDeedTypeDashboard/index.tsx @@ -1,92 +1,19 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; +import { DeedType } from "le-coffre-resources/dist/Notary"; import DeedTypes, { IGetDeedTypesParams } from "@Front/Api/LeCoffreApi/Notary/DeedTypes/DeedTypes"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; -import { Deed, DeedType } from "le-coffre-resources/dist/Notary"; -import Image from "next/image"; -import React, { ReactNode } from "react"; -import classes from "./classes.module.scss"; -import DeedListContainer from "./DeedTypeListContainer"; -import { ChevronLeftIcon } from "@heroicons/react/24/solid"; +type IProps = IPropsDashboardWithList; -type IProps = { - title: string; - children?: ReactNode; - onSelectedDeed: (deed: Deed) => void; - hasBackArrow: boolean; - backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - deedTypes: DeedType[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; -}; - -export default class DefaultDeedTypesDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, - }; - - public constructor(props: IProps) { - super(props); - this.state = { - deedTypes: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.deedTypes && ( - - )} -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); +export default function DefaultDeedTypeDashboard(props: IProps) { + const [deedTypes, setDeedTypes] = React.useState(null); + const router = useRouter(); + const { deedTypeUid } = router.query; + useEffect(() => { const query: IGetDeedTypesParams = { where: { archived_at: null, @@ -96,28 +23,32 @@ export default class DefaultDeedTypesDashboard extends React.Component setDeedTypes(deedTypes)); + }, []); - public override componentWillUnmount() { - this.onWindowResize(); - } + const onSelectedBlock = (block: IBlock) => { + router.push(Module.getInstance().get().modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", block.id)); + }; - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } - - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( + ({ + id: deedTypes.uid!, + primaryText: deedTypes.name, + isActive: deedTypes.uid === deedTypeUid, + })) + : [] + } + bottomButton={{ + link: Module.getInstance().get().modules.pages.DeedTypes.pages.Create.props.path, + text: "Créer une liste de pièces", + }} + /> + ); } diff --git a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/classes.module.scss deleted file mode 100644 index f6b183e8..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/classes.module.scss +++ /dev/null @@ -1,30 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - display: flex; - flex-direction: column; - justify-content: space-between; - - position: relative; - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: calc(100vh - 290px); - height: calc(100vh - 290px); - overflow: auto; - border-right: 1px solid var(--color-neutral-200); - } - - .create-container { - position: absolute; - bottom: 0; - left: 0; - right: 0; - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/index.tsx deleted file mode 100644 index da7fb26f..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/DocumentTypeListContainer/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import Module from "@Front/Config/Module"; -import { DocumentType } from "le-coffre-resources/dist/SuperAdmin"; -import { useRouter } from "next/router"; -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - documentTypes: DocumentType[]; - onSelectedDocumentType?: (documentType: DocumentType) => void; - onCloseLeftSide?: () => void; -}; - -export default function DocumentTypeListContainer(props: IProps) { - const router = useRouter(); - - const { documentTypeUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - return { - primaryText: documentType.name, - id: documentType.uid!, - isActive: documentType.uid === documentTypeUid, - }; - })} - onSelectedBlock={onSelectedBlock} - bottomButton={{ - link: Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path, - text: "Créer un type de document", - }} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/classes.module.scss deleted file mode 100644 index f54563dd..00000000 --- a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/classes.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@import "@Themes/constants.scss"; - -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - -.root { - .content { - display: flex; - overflow: hidden; - height: calc(100vh - var(--header-height)); - - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; - } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200) solid; - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; - overflow-y: auto; - - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/index.tsx index 584f0b58..451c1985 100644 --- a/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDocumentTypesDashboard/index.tsx @@ -1,124 +1,57 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; -import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; import JwtService from "@Front/Services/JwtService/JwtService"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; +import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes"; import { DocumentType } from "le-coffre-resources/dist/Notary"; -import Image from "next/image"; -import React, { ReactNode } from "react"; -import classes from "./classes.module.scss"; -import DocumentTypeListContainer from "./DocumentTypeListContainer"; -import { ChevronLeftIcon } from "@heroicons/react/24/solid"; +type IProps = IPropsDashboardWithList; -type IProps = { - title: string; - children?: ReactNode; - onSelectedDocumentType: (documentType: DocumentType) => void; - hasBackArrow: boolean; - backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - documentTypes: DocumentType[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; -}; - -export default class DefaultDocumentTypesDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, - }; - - public constructor(props: IProps) { - super(props); - this.state = { - documentTypes: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.documentTypes && ( - - )} -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); +export default function DefaultDocumentTypeDashboard(props: IProps) { + const [documentTypes, setDocumentTypes] = React.useState(null); + const router = useRouter(); + const { documentTypeUid } = router.query; + useEffect(() => { const jwt = JwtService.getInstance().decodeJwt(); if (!jwt) return; - const documentTypes = await DocumentTypes.getInstance().get({ - where: { - office_uid: jwt.office_Id, - }, - orderBy: { - name: "asc", - }, - }); - this.setState({ documentTypes }); - } + DocumentTypes.getInstance() + .get({ + where: { + office_uid: jwt.office_Id, + }, + orderBy: { + name: "asc", + }, + }) + .then((documentTypes) => setDocumentTypes(documentTypes)); + }, []); - public override componentWillUnmount() { - this.onWindowResize(); - } + const onSelectedBlock = (block: IBlock) => { + router.push( + Module.getInstance().get().modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace("[uid]", block.id), + ); + }; - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } - - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( + ({ + id: documentType.uid!, + primaryText: documentType.name, + isActive: documentType.uid === documentTypeUid, + })) + : [] + } + bottomButton={{ + link: Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path, + text: "Créer un type de document", + }} + /> + ); } diff --git a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx index 0cdeaf38..f3a5a2f6 100644 --- a/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultOfficeDashboard/index.tsx @@ -27,7 +27,7 @@ export default function DefaultOfficeDashboard(props: IProps) { ({ id: office.uid!, diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/classes.module.scss deleted file mode 100644 index 3cc8b688..00000000 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/classes.module.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - width: calc(100vh - 83px); - display: flex; - flex-direction: column; - justify-content: space-between; - - position: relative; - - .header { - flex: 1; - } - - .searchbar { - padding: 40px 24px 24px 24px; - } - - .folderlist-container { - max-height: calc(100vh - 215px); - height: calc(100vh - 215px); - overflow: auto; - border-right: 1px solid var(--color-neutral-200); - } - - .create-container { - position: absolute; - bottom: 0; - left: 0; - right: 0; - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/index.tsx deleted file mode 100644 index b02309c9..00000000 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/RoleListContainer/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import Module from "@Front/Config/Module"; -import { OfficeRole } from "le-coffre-resources/dist/Admin"; -import { useRouter } from "next/router"; -import React, { useCallback } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; -import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList"; - -type IProps = { - roles: OfficeRole[]; - onSelectedRole?: (role: OfficeRole) => void; - onCloseLeftSide?: () => void; -}; - -export default function RoleListContainer(props: IProps) { - const router = useRouter(); - - const { roleUid } = router.query; - - const onSelectedBlock = useCallback( - (block: IBlock) => { - props.onCloseLeftSide && props.onCloseLeftSide(); - const redirectPath = Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path; - router.push(redirectPath.replace("[uid]", block.id)); - }, - [props, router], - ); - - return ( -
- { - if (role.name === "admin") return false; - return true; - }) - .map((role) => { - return { - primaryText: role.name, - id: role.uid!, - isActive: role.uid === roleUid, - }; - })} - onSelectedBlock={onSelectedBlock} - bottomButton={{ - link: Module.getInstance().get().modules.pages.Roles.pages.Create.props.path, - text: "Créer un rôle", - }} - /> -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/classes.module.scss deleted file mode 100644 index f54563dd..00000000 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/classes.module.scss +++ /dev/null @@ -1,116 +0,0 @@ -@import "@Themes/constants.scss"; - -@keyframes growWidth { - 0% { - width: 100%; - } - - 100% { - width: 200%; - } -} - -.root { - .content { - display: flex; - overflow: hidden; - height: calc(100vh - var(--header-height)); - - .overlay { - position: absolute; - width: 100%; - height: 100%; - background-color: var(--color-generic-white); - opacity: 0.5; - z-index: 2; - transition: all 0.3s $custom-easing; - } - - .left-side { - background-color: var(--color-generic-white); - z-index: 3; - display: flex; - width: 336px; - min-width: 336px; - transition: all 0.3s $custom-easing; - overflow: hidden; - - @media (max-width: ($screen-m - 1px)) { - width: 56px; - min-width: 56px; - transform: translateX(-389px); - - &.opened { - transform: translateX(0px); - width: 336px; - min-width: 336px; - } - } - - @media (max-width: $screen-s) { - width: 0px; - min-width: 0px; - - &.opened { - width: 100vw; - min-width: 100vw; - } - } - } - - .closable-left-side { - position: absolute; - background-color: var(--color-generic-white); - z-index: 0; - display: flex; - justify-content: center; - min-width: 56px; - max-width: 56px; - height: calc(100vh - var(--header-height)); - border-right: 1px var(--color-neutral-200) solid; - - @media (min-width: $screen-m) { - display: none; - } - - .chevron-icon { - margin-top: 21px; - transform: rotate(180deg); - cursor: pointer; - } - - @media (max-width: $screen-s) { - display: none; - } - } - - .right-side { - min-width: calc(100vw - 389px); - padding: 24px; - overflow-y: auto; - - @media (max-width: ($screen-m - 1px)) { - 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; - margin-bottom: 24px; - } - } - - .back-arrow-desktop { - @media (max-width: $screen-s) { - display: none; - } - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx index 86a971ce..cadc71a3 100644 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx @@ -1,117 +1,49 @@ -import ChevronIcon from "@Assets/Icons/chevron.svg"; +import React, { useEffect } from "react"; + +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; +import { OfficeRole } from "le-coffre-resources/dist/Notary"; import OfficeRoles, { IGetRolesParams } from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles"; -import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; -import Header from "@Front/Components/DesignSystem/Header"; -import Version from "@Front/Components/DesignSystem/Version"; -import BackArrow from "@Front/Components/Elements/BackArrow"; -import WindowStore from "@Front/Stores/WindowStore"; -import classNames from "classnames"; -import { OfficeRole } from "le-coffre-resources/dist/Admin"; -import Image from "next/image"; -import React, { ReactNode } from "react"; -import classes from "./classes.module.scss"; -import RoleListContainer from "./RoleListContainer"; -import { ChevronLeftIcon } from "@heroicons/react/24/outline"; +type IProps = IPropsDashboardWithList; -type IProps = { - title: string; - children?: ReactNode; - onSelectedRole: (role: OfficeRole) => void; - hasBackArrow: boolean; - backArrowUrl?: string; - mobileBackText?: string; -}; -type IState = { - roles: OfficeRole[] | null; - isLeftSideOpen: boolean; - leftSideCanBeClosed: boolean; -}; - -export default class DefaultRoleDashboard extends React.Component { - private onWindowResize = () => {}; - public static defaultProps: Partial = { - hasBackArrow: false, - }; - - public constructor(props: IProps) { - super(props); - this.state = { - roles: null, - isLeftSideOpen: false, - leftSideCanBeClosed: typeof window !== "undefined" ? window.innerWidth < 1024 : false, - }; - this.onOpenLeftSide = this.onOpenLeftSide.bind(this); - this.onCloseLeftSide = this.onCloseLeftSide.bind(this); - } - - public override render(): JSX.Element { - return ( -
-
-
- {this.state.isLeftSideOpen &&
} -
- {this.state.roles && } -
-
- open side menu -
- -
- {this.props.hasBackArrow && ( -
- -
- )} - {this.props.mobileBackText && ( -
- -
- )} - {this.props.children} -
-
- -
- ); - } - - public override async componentDidMount() { - this.onWindowResize = WindowStore.getInstance().onResize((window) => this.onResize(window)); +export default function DefaultRoleDashboard(props: IProps) { + const [roles, setRoles] = React.useState(null); + const router = useRouter(); + const { roleUid } = router.query; + useEffect(() => { const query: IGetRolesParams = { include: { rules: true }, }; - const roles = await OfficeRoles.getInstance().get(query); + OfficeRoles.getInstance() + .get(query) + .then((roles) => setRoles(roles)); + }, []); - this.setState({ roles }); - } + const onSelectedBlock = (block: IBlock) => { + router.push(Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path.replace("[uid]", block.id)); + }; - public override componentWillUnmount() { - this.onWindowResize(); - } - - private onOpenLeftSide() { - this.setState({ isLeftSideOpen: true }); - } - - private onCloseLeftSide() { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ isLeftSideOpen: false }); - } - - private onResize(window: Window) { - if (window.innerWidth > 1023) { - if (!this.state.leftSideCanBeClosed) return; - this.setState({ leftSideCanBeClosed: false }); - } - this.setState({ leftSideCanBeClosed: true }); - } + return ( + ({ + id: role.uid!, + primaryText: role.name, + isActive: role.uid === roleUid, + })) + : [] + } + bottomButton={{ + link: Module.getInstance().get().modules.pages.Roles.pages.Create.props.path, + text: "Créer un rôle", + }} + /> + ); } diff --git a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx index e3b97389..d5643677 100644 --- a/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultUserDashboard/index.tsx @@ -31,7 +31,7 @@ export default function DefaultUserDashboard(props: IProps) { ({ id: user.uid!, From c707910f8dc97c0f3582487e8ebad5181e74f80d Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 12:05:02 +0200 Subject: [PATCH 08/18] :sparkles: Notary dashboard in conformity --- .../FolderListContainer/classes.module.scss | 7 -- .../FolderListContainer/index.tsx | 87 ----------------- .../DefaultDashboardWithList/index.tsx | 1 - .../classes.module.scss | 23 ----- .../DefaultNotaryDashboard/index.tsx | 95 ++++++++++++++----- 5 files changed, 72 insertions(+), 141 deletions(-) delete mode 100644 src/front/Components/DesignSystem/FolderListContainer/classes.module.scss delete mode 100644 src/front/Components/DesignSystem/FolderListContainer/index.tsx delete mode 100644 src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss diff --git a/src/front/Components/DesignSystem/FolderListContainer/classes.module.scss b/src/front/Components/DesignSystem/FolderListContainer/classes.module.scss deleted file mode 100644 index 560b12a5..00000000 --- a/src/front/Components/DesignSystem/FolderListContainer/classes.module.scss +++ /dev/null @@ -1,7 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - display: flex; - flex-direction: column; - justify-content: space-between; -} diff --git a/src/front/Components/DesignSystem/FolderListContainer/index.tsx b/src/front/Components/DesignSystem/FolderListContainer/index.tsx deleted file mode 100644 index 188bcfd6..00000000 --- a/src/front/Components/DesignSystem/FolderListContainer/index.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import Module from "@Front/Config/Module"; -import { OfficeFolder } from "le-coffre-resources/dist/Notary"; -import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; -import { useRouter } from "next/router"; -import React, { useCallback, useEffect } from "react"; - -import classes from "./classes.module.scss"; -import { IBlock } from "../SearchBlockList/BlockList/Block"; -import SearchBlockList from "../SearchBlockList"; - -type IProps = { - folders: OfficeFolder[]; - isArchived: boolean; -}; - -export default function FolderListContainer(props: IProps) { - const router = useRouter(); - const { folderUid } = router.query; - const { folders, isArchived } = props; - - const redirectPath: string = isArchived - ? Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.pages.FolderInformation.props.path - : Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path; - - const getBlocks = useCallback( - (folders: OfficeFolder[]): IBlock[] => { - const pendingFolders = folders - .filter((folder) => { - const pendingDocuments = (folder.documents ?? []).filter( - (document) => document.document_status === EDocumentStatus.DEPOSITED, - ); - return pendingDocuments.length >= 1; - }) - .sort((folder1, folder2) => { - return folder1.created_at! > folder2.created_at! ? -1 : 1; - }); - - const otherFolders = folders - .filter((folder) => { - const pendingDocuments = (folder.documents ?? []).filter( - (document) => document.document_status === EDocumentStatus.DEPOSITED, - ); - return pendingDocuments.length === 0; - }) - .sort((folder1, folder2) => { - return folder1.created_at! > folder2.created_at! ? -1 : 1; - }); - - return [...pendingFolders, ...otherFolders].map((folder) => { - return { - id: folder.uid!, - primaryText: folder.name, - secondaryText: folder.folder_number, - isActive: folderUid === folder.uid, - showAlert: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED), - }; - }); - }, - [folderUid], - ); - - const [blocks, setBlocks] = React.useState(getBlocks(folders)); - - const onSelectedFolder = (block: IBlock) => { - const folder = folders.find((folder) => folder.uid === block.id); - if (!folder) return; - const path = redirectPath.replace("[folderUid]", folder.uid ?? ""); - router.push(path); - }; - - useEffect(() => { - setBlocks(getBlocks(folders)); - }, [folders, getBlocks]); - - return ( -
- -
- ); -} diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx index 3f3bd44a..91919c77 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -9,7 +9,6 @@ import SearchBlockList, { ISearchBlockListProps } from "@Front/Components/Design export type IPropsDashboardWithList = { title?: string; children?: ReactNode; - isArchived?: boolean; hasBackArrow?: boolean; backArrowUrl?: string; mobileBackText?: string; diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss deleted file mode 100644 index 882a9394..00000000 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/classes.module.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - position: relative; - .content { - display: flex; - justify-content: flex-start; - height: calc(100vh - var(--header-height)); - - @media (max-width: $screen-m) { - flex-direction: column; - } - .right-side { - min-width: calc(100% - 336px); - overflow-y: auto; - padding: var(--spacing-lg, 24px); - - @media (max-width: $screen-m) { - width: 100%; - } - } - } -} diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx index 3b3a383b..a65da789 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx @@ -1,13 +1,13 @@ import Folders, { IGetFoldersParams } from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; -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 EFolderStatus from "le-coffre-resources/dist/Customer/EFolderStatus"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; -import React, { ReactNode, useEffect } from "react"; +import React, { ReactNode, useCallback, useEffect } from "react"; +import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; -import classes from "./classes.module.scss"; +import Module from "@Front/Config/Module"; +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import { useRouter } from "next/router"; +import DefaultDashboardWithList from "../DefaultDashboardWithList"; type IProps = { title: string; @@ -19,9 +19,64 @@ type IProps = { }; export default function DefaultNotaryDashboard(props: IProps) { - const { hasBackArrow, backArrowUrl, children, isArchived } = props; - + const { isArchived } = props; + const router = useRouter(); const [folders, setFolders] = React.useState([]); + const { folderUid } = router.query; + + const redirectPath: string = isArchived + ? Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.pages.FolderInformation.props.path + : Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path; + + const getBlocks = useCallback( + (folders: OfficeFolder[]): IBlock[] => { + const pendingFolders = folders + .filter((folder) => { + const pendingDocuments = (folder.documents ?? []).filter( + (document) => document.document_status === EDocumentStatus.DEPOSITED, + ); + return pendingDocuments.length >= 1; + }) + .sort((folder1, folder2) => { + return folder1.created_at! > folder2.created_at! ? -1 : 1; + }); + + const otherFolders = folders + .filter((folder) => { + const pendingDocuments = (folder.documents ?? []).filter( + (document) => document.document_status === EDocumentStatus.DEPOSITED, + ); + return pendingDocuments.length === 0; + }) + .sort((folder1, folder2) => { + return folder1.created_at! > folder2.created_at! ? -1 : 1; + }); + + return [...pendingFolders, ...otherFolders].map((folder) => { + return { + id: folder.uid!, + primaryText: folder.name, + secondaryText: folder.folder_number, + isActive: folderUid === folder.uid, + showAlert: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED), + }; + }); + }, + [folderUid], + ); + + const [blocks, setBlocks] = React.useState(getBlocks(folders)); + + const onSelectedBlock = (block: IBlock) => { + const folder = folders.find((folder) => folder.uid === block.id); + if (!folder) return; + const path = redirectPath.replace("[folderUid]", folder.uid ?? ""); + router.push(path); + }; + + useEffect(() => { + setBlocks(getBlocks(folders)); + }, [folders, getBlocks]); useEffect(() => { let targetedStatus: EFolderStatus = EFolderStatus["LIVE" as keyof typeof EFolderStatus]; @@ -63,20 +118,14 @@ export default function DefaultNotaryDashboard(props: IProps) { }, [isArchived]); return ( -
-
-
- -
- {hasBackArrow && ( -
- -
- )} - {children} -
-
- -
+ ); } From 4ec6e40fa2c1b3c7febc8cc6bc409478ee8d7616 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 12:26:04 +0200 Subject: [PATCH 09/18] :sparkles: Legal pages working --- .../classes.module.scss | 4 ++ .../DefaultDashboardWithList/index.tsx | 14 +++- .../DefaultLegalDashboard/index.tsx | 64 +++++++++++++++++++ .../DefaultNotaryDashboard/index.tsx | 13 ++-- .../LegalInformations/classes.module.scss | 31 +++++++++ .../Layouts/Legal/LegalInformations/index.tsx | 23 +++++++ .../Layouts/Legal/classes.module.scss | 17 +++++ src/front/Components/Layouts/Legal/index.tsx | 26 ++++++++ src/front/Config/Module/development.json | 16 +++++ src/front/Config/Module/preprod.json | 16 +++++ src/front/Config/Module/production.json | 16 +++++ src/front/Config/Module/staging.json | 16 +++++ src/pages/legal/[legalUid]/index.tsx | 5 ++ src/pages/legal/index.tsx | 5 ++ 14 files changed, 255 insertions(+), 11 deletions(-) create mode 100644 src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx create mode 100644 src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss create mode 100644 src/front/Components/Layouts/Legal/LegalInformations/index.tsx create mode 100644 src/front/Components/Layouts/Legal/classes.module.scss create mode 100644 src/front/Components/Layouts/Legal/index.tsx create mode 100644 src/pages/legal/[legalUid]/index.tsx create mode 100644 src/pages/legal/index.tsx diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss index 882a9394..1f508b61 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss @@ -15,6 +15,10 @@ overflow-y: auto; padding: var(--spacing-lg, 24px); + &[data-no-padding] { + padding: 0; + } + @media (max-width: $screen-m) { width: 100%; } diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx index 91919c77..84d8e187 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -13,19 +13,29 @@ export type IPropsDashboardWithList = { backArrowUrl?: string; mobileBackText?: string; headerConnected?: boolean; + noPadding?: boolean; }; type IProps = IPropsDashboardWithList & ISearchBlockListProps; export default function DefaultDashboardWithList(props: IProps) { - const { hasBackArrow, backArrowUrl, children, blocks, onSelectedBlock, headerConnected = true, bottomButton } = props; + const { + hasBackArrow, + backArrowUrl, + children, + blocks, + onSelectedBlock, + headerConnected = true, + bottomButton, + noPadding = false, + } = props; return (
-
+
{hasBackArrow && (
diff --git a/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx new file mode 100644 index 00000000..080ea25f --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx @@ -0,0 +1,64 @@ +import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; +import { useRouter } from "next/router"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; +import { useMemo } from "react"; +import Module from "@Front/Config/Module"; + +type IProps = IPropsDashboardWithList; + +export enum ELegalOptions { + LEGAL_MENTIONS = "mentions-legales", + CGU = "cgu", + CGS = "cgs", + POLITIQUE_DE_CONFIDENTIALITE = "politique-de-confidentialite", + POLITIQUE_DE_GESTION_DES_COOKIES = "politique-de-gestion-des-cookies", +} + +export default function DefaultLegalDashboard(props: IProps) { + const router = useRouter(); + const { legalUid } = router.query; + + const onSelectedBlock = (block: IBlock) => { + router.push(Module.getInstance().get().modules.pages.Legal.pages.LegalInformations.props.path.replace("[legalUid]", block.id)); + }; + + const blocks: IBlock[] = useMemo( + () => [ + { + id: ELegalOptions.LEGAL_MENTIONS, + primaryText: "Mentions légales", + isActive: legalUid === ELegalOptions.LEGAL_MENTIONS, + }, + { + id: ELegalOptions.CGU, + primaryText: "CGU", + isActive: legalUid === ELegalOptions.CGU, + }, + { + id: ELegalOptions.CGS, + primaryText: "CGS", + isActive: legalUid === ELegalOptions.CGS, + }, + { + id: ELegalOptions.POLITIQUE_DE_CONFIDENTIALITE, + primaryText: "Politique de confidentialité", + isActive: legalUid === ELegalOptions.POLITIQUE_DE_CONFIDENTIALITE, + }, + { + id: ELegalOptions.POLITIQUE_DE_GESTION_DES_COOKIES, + primaryText: "Politique de gestion des cookies", + isActive: legalUid === ELegalOptions.POLITIQUE_DE_GESTION_DES_COOKIES, + }, + ], + [legalUid], + ); + + if (!legalUid) { + router.push( + Module.getInstance() + .get() + .modules.pages.Legal.pages.LegalInformations.props.path.replace("[legalUid]", ELegalOptions.LEGAL_MENTIONS), + ); + } + return ; +} diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx index a65da789..190dc803 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx @@ -1,21 +1,16 @@ import Folders, { IGetFoldersParams } from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; import EFolderStatus from "le-coffre-resources/dist/Customer/EFolderStatus"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; -import React, { ReactNode, useCallback, useEffect } from "react"; +import React, { useCallback, useEffect } from "react"; import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; import Module from "@Front/Config/Module"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { useRouter } from "next/router"; -import DefaultDashboardWithList from "../DefaultDashboardWithList"; +import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; -type IProps = { - title: string; - children?: ReactNode; - isArchived?: boolean; - hasBackArrow?: boolean; - backArrowUrl?: string; - mobileBackText?: string; +type IProps = IPropsDashboardWithList & { + isArchived: boolean; }; export default function DefaultNotaryDashboard(props: IProps) { diff --git a/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss b/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss new file mode 100644 index 00000000..2eb0753b --- /dev/null +++ b/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss @@ -0,0 +1,31 @@ +@import "@Themes/constants.scss"; + +.root { + .subtitle { + margin-top: 32px; + } + + .rights-container { + margin-top: 32px; + padding: 32px 16px; + border: 1px solid gray; + .select-all-container { + margin-top: 32px; + } + + .rights { + margin-top: 32px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 32px; + + @media (max-width: $screen-m) { + grid-template-columns: 1fr; + } + } + + .save-container { + margin-top: 32px; + } + } +} diff --git a/src/front/Components/Layouts/Legal/LegalInformations/index.tsx b/src/front/Components/Layouts/Legal/LegalInformations/index.tsx new file mode 100644 index 00000000..42d7f7ef --- /dev/null +++ b/src/front/Components/Layouts/Legal/LegalInformations/index.tsx @@ -0,0 +1,23 @@ +import { useRouter } from "next/router"; +import React from "react"; + +import DefaultLegalDashboard, { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; + +const pdfLinks: Record = { + "mentions-legales": "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/mentions_legales.pdf", + "politique-de-confidentialite": "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/politique_confidentialite.pdf", + "politique-de-gestion-des-cookies": "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/politique_cookies.pdf", + cgs: "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/cgs.pdf", + cgu: "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/cgu.pdf", +}; + +export default function LegalInformations() { + const router = useRouter(); + let { legalUid } = router.query; + const legalUidTyped = legalUid as ELegalOptions; + return ( + + + + ); +} diff --git a/src/front/Components/Layouts/Legal/classes.module.scss b/src/front/Components/Layouts/Legal/classes.module.scss new file mode 100644 index 00000000..4eca97a6 --- /dev/null +++ b/src/front/Components/Layouts/Legal/classes.module.scss @@ -0,0 +1,17 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + align-items: center; + flex-direction: column; + min-height: 100%; + + .no-role-selected { + width: 100%; + + .choose-a-role { + margin-top: 96px; + text-align: center; + } + } +} diff --git a/src/front/Components/Layouts/Legal/index.tsx b/src/front/Components/Layouts/Legal/index.tsx new file mode 100644 index 00000000..1eb64384 --- /dev/null +++ b/src/front/Components/Layouts/Legal/index.tsx @@ -0,0 +1,26 @@ +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; + +import BasePage from "../Base"; +import classes from "./classes.module.scss"; +import DefaultLegalDashboard from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; + +type IProps = {}; +type IState = {}; +export default class Collaborators extends BasePage { + public override render(): JSX.Element { + return ( + +
+
+ Gestion des pages légales +
+ + Sélectionnez un rôle + +
+
+
+
+ ); + } +} diff --git a/src/front/Config/Module/development.json b/src/front/Config/Module/development.json index 20bc04c8..253742bf 100644 --- a/src/front/Config/Module/development.json +++ b/src/front/Config/Module/development.json @@ -390,6 +390,22 @@ } } } + }, + "Legal": { + "enabled": true, + "props": { + "path": "/legal", + "labelKey": "legal" + }, + "pages": { + "LegalInformations": { + "enabled": true, + "props": { + "path": "/legal/[legalUid]", + "labelKey": "legal_informations" + } + } + } } } } diff --git a/src/front/Config/Module/preprod.json b/src/front/Config/Module/preprod.json index 20bc04c8..253742bf 100644 --- a/src/front/Config/Module/preprod.json +++ b/src/front/Config/Module/preprod.json @@ -390,6 +390,22 @@ } } } + }, + "Legal": { + "enabled": true, + "props": { + "path": "/legal", + "labelKey": "legal" + }, + "pages": { + "LegalInformations": { + "enabled": true, + "props": { + "path": "/legal/[legalUid]", + "labelKey": "legal_informations" + } + } + } } } } diff --git a/src/front/Config/Module/production.json b/src/front/Config/Module/production.json index 20bc04c8..253742bf 100644 --- a/src/front/Config/Module/production.json +++ b/src/front/Config/Module/production.json @@ -390,6 +390,22 @@ } } } + }, + "Legal": { + "enabled": true, + "props": { + "path": "/legal", + "labelKey": "legal" + }, + "pages": { + "LegalInformations": { + "enabled": true, + "props": { + "path": "/legal/[legalUid]", + "labelKey": "legal_informations" + } + } + } } } } diff --git a/src/front/Config/Module/staging.json b/src/front/Config/Module/staging.json index 20bc04c8..253742bf 100644 --- a/src/front/Config/Module/staging.json +++ b/src/front/Config/Module/staging.json @@ -390,6 +390,22 @@ } } } + }, + "Legal": { + "enabled": true, + "props": { + "path": "/legal", + "labelKey": "legal" + }, + "pages": { + "LegalInformations": { + "enabled": true, + "props": { + "path": "/legal/[legalUid]", + "labelKey": "legal_informations" + } + } + } } } } diff --git a/src/pages/legal/[legalUid]/index.tsx b/src/pages/legal/[legalUid]/index.tsx new file mode 100644 index 00000000..58da8f23 --- /dev/null +++ b/src/pages/legal/[legalUid]/index.tsx @@ -0,0 +1,5 @@ +import LegalInformations from "@Front/Components/Layouts/Legal/LegalInformations"; + +export default function Route() { + return ; +} diff --git a/src/pages/legal/index.tsx b/src/pages/legal/index.tsx new file mode 100644 index 00000000..fb7e17c9 --- /dev/null +++ b/src/pages/legal/index.tsx @@ -0,0 +1,5 @@ +import Legal from "@Front/Components/Layouts/Legal"; + +export default function Route() { + return ; +} From d01984dd4863337a5b9b50fc2bed9fdb061e204a Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 12:39:46 +0200 Subject: [PATCH 10/18] :sparkles: Legal pages working --- .../DefaultLegalDashboard/index.tsx | 7 --- .../LegalInformations/classes.module.scss | 36 ++++------------ .../Layouts/Legal/LegalInformations/index.tsx | 15 ++++++- .../Layouts/Legal/classes.module.scss | 17 -------- src/front/Components/Layouts/Legal/index.tsx | 43 +++++++++---------- 5 files changed, 41 insertions(+), 77 deletions(-) delete mode 100644 src/front/Components/Layouts/Legal/classes.module.scss diff --git a/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx index 080ea25f..10a0acd0 100644 --- a/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultLegalDashboard/index.tsx @@ -53,12 +53,5 @@ export default function DefaultLegalDashboard(props: IProps) { [legalUid], ); - if (!legalUid) { - router.push( - Module.getInstance() - .get() - .modules.pages.Legal.pages.LegalInformations.props.path.replace("[legalUid]", ELegalOptions.LEGAL_MENTIONS), - ); - } return ; } diff --git a/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss b/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss index 2eb0753b..351451a0 100644 --- a/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss +++ b/src/front/Components/Layouts/Legal/LegalInformations/classes.module.scss @@ -1,31 +1,11 @@ -@import "@Themes/constants.scss"; +.pdf-viewer { + width: 100%; + height: 100%; + min-height: 100%; + min-width: 100%; -.root { - .subtitle { - margin-top: 32px; - } - - .rights-container { - margin-top: 32px; - padding: 32px 16px; - border: 1px solid gray; - .select-all-container { - margin-top: 32px; - } - - .rights { - margin-top: 32px; - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 32px; - - @media (max-width: $screen-m) { - grid-template-columns: 1fr; - } - } - - .save-container { - margin-top: 32px; - } + .no-pdf-text { + padding: 16px; + text-align: center; } } diff --git a/src/front/Components/Layouts/Legal/LegalInformations/index.tsx b/src/front/Components/Layouts/Legal/LegalInformations/index.tsx index 42d7f7ef..b7a6d200 100644 --- a/src/front/Components/Layouts/Legal/LegalInformations/index.tsx +++ b/src/front/Components/Layouts/Legal/LegalInformations/index.tsx @@ -1,7 +1,9 @@ import { useRouter } from "next/router"; import React from "react"; - +import classes from "./classes.module.scss"; import DefaultLegalDashboard, { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import Link from "next/link"; const pdfLinks: Record = { "mentions-legales": "https://s3.fr-par.scw.cloud/lecoffre.io-bucket/footer/mentions_legales.pdf", @@ -17,7 +19,16 @@ export default function LegalInformations() { const legalUidTyped = legalUid as ELegalOptions; return ( - + + + Votre navigateur ne prend pas en charge l'affichage des pdf  + + + cliquez ici pour télécharger le pdf. + + + + ); } diff --git a/src/front/Components/Layouts/Legal/classes.module.scss b/src/front/Components/Layouts/Legal/classes.module.scss deleted file mode 100644 index 4eca97a6..00000000 --- a/src/front/Components/Layouts/Legal/classes.module.scss +++ /dev/null @@ -1,17 +0,0 @@ -@import "@Themes/constants.scss"; - -.root { - display: flex; - align-items: center; - flex-direction: column; - min-height: 100%; - - .no-role-selected { - width: 100%; - - .choose-a-role { - margin-top: 96px; - text-align: center; - } - } -} diff --git a/src/front/Components/Layouts/Legal/index.tsx b/src/front/Components/Layouts/Legal/index.tsx index 1eb64384..f2b9961b 100644 --- a/src/front/Components/Layouts/Legal/index.tsx +++ b/src/front/Components/Layouts/Legal/index.tsx @@ -1,26 +1,23 @@ -import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; - -import BasePage from "../Base"; -import classes from "./classes.module.scss"; -import DefaultLegalDashboard from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; +import DefaultLegalDashboard, { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; +import { useRouter } from "next/router"; +import Module from "@Front/Config/Module"; +import { useEffect } from "react"; type IProps = {}; -type IState = {}; -export default class Collaborators extends BasePage { - public override render(): JSX.Element { - return ( - -
-
- Gestion des pages légales -
- - Sélectionnez un rôle - -
-
-
-
- ); - } + +export default function Legal(props: IProps) { + const router = useRouter(); + const { legalUid } = router.query; + + useEffect(() => { + if (!legalUid && router.isReady) { + router.push( + Module.getInstance() + .get() + .modules.pages.Legal.pages.LegalInformations.props.path.replace("[legalUid]", ELegalOptions.LEGAL_MENTIONS), + ); + } + }, [legalUid, router]); + + return ; } From 6eae754bc821b2435a40910caf6ddd8980ec8180 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 12:44:12 +0200 Subject: [PATCH 11/18] :sparkles: Fixing build --- .../LayoutTemplates/DefaultNotaryDashboard/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx index 190dc803..5d734e18 100644 --- a/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultNotaryDashboard/index.tsx @@ -10,11 +10,11 @@ import { useRouter } from "next/router"; import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDashboardWithList"; type IProps = IPropsDashboardWithList & { - isArchived: boolean; + isArchived?: boolean; }; export default function DefaultNotaryDashboard(props: IProps) { - const { isArchived } = props; + const { isArchived = false } = props; const router = useRouter(); const [folders, setFolders] = React.useState([]); const { folderUid } = router.query; From 447babc38658498784a39b6cdded59ae7433725a Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 13:02:47 +0200 Subject: [PATCH 12/18] :sparkles: Adding footer --- .../Components/DesignSystem/Footer/index.tsx | 5 +++- .../classes.module.scss | 23 +++++++++++-------- .../DefaultDashboardWithList/index.tsx | 16 ++++++++----- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/front/Components/DesignSystem/Footer/index.tsx b/src/front/Components/DesignSystem/Footer/index.tsx index 8867ec7f..9a23212f 100644 --- a/src/front/Components/DesignSystem/Footer/index.tsx +++ b/src/front/Components/DesignSystem/Footer/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import classes from "./classes.module.scss"; import Mobile from "./mobile"; import Desktop from "./desktop"; @@ -9,6 +9,9 @@ type IProps = { }; export default function Footer({ className }: IProps) { + useEffect(() => { + document.documentElement.style.setProperty("--footer-height", `43px`); + }); return (
diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss index 1f508b61..44981eea 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss @@ -7,21 +7,24 @@ justify-content: flex-start; height: calc(100vh - var(--header-height)); - @media (max-width: $screen-m) { - flex-direction: column; - } .right-side { min-width: calc(100% - 336px); - overflow-y: auto; - padding: var(--spacing-lg, 24px); - - &[data-no-padding] { - padding: 0; + .right-side-content { + overflow-y: auto; + padding: var(--spacing-lg, 24px); + height: calc(100% - var(--footer-height)); } - @media (max-width: $screen-m) { - width: 100%; + &[data-no-padding="true"] { + .right-side-content { + padding: 0; + } } } + + @media (max-width: $screen-m) { + width: 100%; + flex-direction: column; + } } } diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx index 84d8e187..5261e700 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/index.tsx @@ -5,6 +5,7 @@ import React, { ReactNode } from "react"; import classes from "./classes.module.scss"; import SearchBlockList, { ISearchBlockListProps } from "@Front/Components/DesignSystem/SearchBlockList"; +import Footer from "@Front/Components/DesignSystem/Footer"; export type IPropsDashboardWithList = { title?: string; @@ -36,12 +37,15 @@ export default function DefaultDashboardWithList(props: IProps) {
- {hasBackArrow && ( -
- -
- )} - {children} +
+ {hasBackArrow && ( +
+ +
+ )} + {children} +
+
From 8e2f666a6848bad54f3872d9267a4468f98fe603 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 13:17:09 +0200 Subject: [PATCH 13/18] :sparkles: Footer working --- .../DesignSystem/Footer/classes.module.scss | 3 +-- src/front/Components/DesignSystem/Footer/desktop.tsx | 11 ++++++++--- src/front/Components/DesignSystem/Footer/mobile.tsx | 9 +++++++-- src/front/Components/DesignSystem/Footer/tablet.tsx | 10 +++++++--- .../DefaultDashboardWithList/classes.module.scss | 10 +++++++++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/front/Components/DesignSystem/Footer/classes.module.scss b/src/front/Components/DesignSystem/Footer/classes.module.scss index f9a12433..16d6a0fb 100644 --- a/src/front/Components/DesignSystem/Footer/classes.module.scss +++ b/src/front/Components/DesignSystem/Footer/classes.module.scss @@ -8,13 +8,12 @@ font-size: 12px; font-weight: var(--font-text-weight-regular, 400); letter-spacing: 0.06px; - .sub-root { display: flex; align-items: center; gap: var(--Radius-lg, 16px); white-space: nowrap; - padding: 0 360px; + padding: var(--spacing-1-5, 12px) var(--Radius-xl, 24px); //make it sticky @media (max-width: 1023px) { diff --git a/src/front/Components/DesignSystem/Footer/desktop.tsx b/src/front/Components/DesignSystem/Footer/desktop.tsx index d0eb1772..023fb75e 100644 --- a/src/front/Components/DesignSystem/Footer/desktop.tsx +++ b/src/front/Components/DesignSystem/Footer/desktop.tsx @@ -1,20 +1,25 @@ import React from "react"; import classes from "./classes.module.scss"; +import Link from "next/link"; +import Module from "@Front/Config/Module"; +import { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; type IProps = { className?: string; }; +const legalPages = Module.getInstance().get().modules.pages.Legal.pages.LegalInformations.props.path; + export default function Desktop({ className }: IProps) { return (
© Copyright lecoffre 2024 - Conditions d'utilisation + Conditions d'utilisation - Politique de confidentialité + Politique de confidentialité - Politique des cookies + Politique des cookies
); } diff --git a/src/front/Components/DesignSystem/Footer/mobile.tsx b/src/front/Components/DesignSystem/Footer/mobile.tsx index 12f962bd..33ccef6c 100644 --- a/src/front/Components/DesignSystem/Footer/mobile.tsx +++ b/src/front/Components/DesignSystem/Footer/mobile.tsx @@ -1,18 +1,23 @@ import React from "react"; import classes from "./classes.module.scss"; +import Link from "next/link"; +import Module from "@Front/Config/Module"; +import { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; type IProps = { className?: string; }; +const legalPages = Module.getInstance().get().modules.pages.Legal.pages.LegalInformations.props.path; + export default function Mobile({ className }: IProps) { return (
© Lecoffre 2024 - Juridiques + Juridiques - Cookies + Cookies
); } diff --git a/src/front/Components/DesignSystem/Footer/tablet.tsx b/src/front/Components/DesignSystem/Footer/tablet.tsx index adec78f9..bf22abe0 100644 --- a/src/front/Components/DesignSystem/Footer/tablet.tsx +++ b/src/front/Components/DesignSystem/Footer/tablet.tsx @@ -1,20 +1,24 @@ import React from "react"; import classes from "./classes.module.scss"; +import Module from "@Front/Config/Module"; +import { ELegalOptions } from "@Front/Components/LayoutTemplates/DefaultLegalDashboard"; +import Link from "next/link"; type IProps = { className?: string; }; +const legalPages = Module.getInstance().get().modules.pages.Legal.pages.LegalInformations.props.path; export default function Tablet({ className }: IProps) { return (
© Lecoffre 2024 - Conditions d'utilisation + Conditions d'utilisation - Politique de confidentialité + Politique de confidentialité - Politique des cookies + Politique des cookies
); } diff --git a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss index 44981eea..da2293c5 100644 --- a/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss +++ b/src/front/Components/LayoutTemplates/DefaultDashboardWithList/classes.module.scss @@ -5,10 +5,14 @@ .content { display: flex; justify-content: flex-start; + min-height: calc(100vh - var(--header-height)); height: calc(100vh - var(--header-height)); - .right-side { min-width: calc(100% - 336px); + flex: 1; + display: flex; + justify-content: space-between; + flex-direction: column; .right-side-content { overflow-y: auto; padding: var(--spacing-lg, 24px); @@ -25,6 +29,10 @@ @media (max-width: $screen-m) { width: 100%; flex-direction: column; + + .right-side { + min-width: 100%; + } } } } From 67ffca67f896bb19b08d15a7480aa9a63e282ab3 Mon Sep 17 00:00:00 2001 From: Max S Date: Mon, 29 Jul 2024 13:23:39 +0200 Subject: [PATCH 14/18] :sparkles: change old multiselect with new autocomplete multi select --- .../DesignSystem/Autocomplete/index.tsx | 21 ++- .../AutocompleteMultiSelect/index.tsx | 25 ++- .../DesignSystem/Dropdown/classes.module.scss | 1 + .../DesignSystem/Dropdown/index.tsx | 56 +++++-- .../Form/AutocompleteField/index.tsx | 9 +- .../classes.module.scss | 11 ++ .../AutocompleteMultiSelectField/index.tsx | 66 ++++++++ .../DesignSystem/Form/SelectField/index.tsx | 7 +- .../MultiSelect/classes.module.scss | 79 --------- .../DesignSystem/MultiSelect/index.tsx | 158 ------------------ .../DesignSystem/MultiSelect/styles.tsx | 100 ----------- .../DropdownNavigation/index.tsx | 8 +- .../CollaboratorInformations/index.tsx | 2 +- .../DeedTypes/DeedTypesInformations/index.tsx | 29 ++-- .../Folder/AddClientToFolder/index.tsx | 43 ++--- .../AskDocuments/ParameterDocuments/index.tsx | 27 ++- .../Layouts/Folder/CreateFolder/index.tsx | 42 +++-- .../UpdateFolderCollaborators/index.tsx | 31 ++-- 18 files changed, 252 insertions(+), 463 deletions(-) create mode 100644 src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/classes.module.scss create mode 100644 src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/index.tsx delete mode 100644 src/front/Components/DesignSystem/MultiSelect/classes.module.scss delete mode 100644 src/front/Components/DesignSystem/MultiSelect/index.tsx delete mode 100644 src/front/Components/DesignSystem/MultiSelect/styles.tsx diff --git a/src/front/Components/DesignSystem/Autocomplete/index.tsx b/src/front/Components/DesignSystem/Autocomplete/index.tsx index 7b081c11..a5169574 100644 --- a/src/front/Components/DesignSystem/Autocomplete/index.tsx +++ b/src/front/Components/DesignSystem/Autocomplete/index.tsx @@ -13,12 +13,12 @@ type IProps = { placeholder?: string; disabled?: boolean; label?: string; - onSelect?: (option: IOption) => void; + onSelectionChange?: (option: IOption | null) => void; selectedOption?: IOption | null; }; export default function Autocomplete(props: IProps) { - const { options, placeholder, disabled, label, selectedOption: selectedOptionProps } = props; + const { onSelectionChange, options, placeholder, disabled, label, selectedOption: selectedOptionProps } = props; const [selectedOption, setSelectedOption] = useState(selectedOptionProps ?? null); const [searchValue, setSearchValue] = useState(""); const [filteredOptions, setFilteredOptions] = useState(options); @@ -47,17 +47,25 @@ export default function Autocomplete(props: IProps) { [openable], ); + const handleChange = useCallback( + (option: IOption | null) => { + setSelectedOption(option); + onSelectionChange?.(option); + }, + [onSelectionChange], + ); + useEffect(() => { setSelectedOption(selectedOptionProps ?? null); }, [selectedOptionProps]); const handleSelectOption = useCallback( (newOption: IOption, _options: IOption[]) => { - setSelectedOption(newOption); + handleChange(newOption); setSearchValue(getLabel(newOption) || ""); openable.close(); }, - [openable], + [handleChange, openable], ); return ( @@ -65,8 +73,7 @@ export default function Autocomplete(props: IProps) { options={filteredOptions} openable={openable} onSelect={handleSelectOption} - selectedOptions={selectedOption ? [selectedOption] : []} - > + selectedOptions={selectedOption ? [selectedOption] : []}>
{label && ( @@ -79,7 +86,7 @@ export default function Autocomplete(props: IProps) { disabled={disabled} onChange={handleSearchChange} value={searchValue} - onClear={() => setSelectedOption(null)} + onClear={() => handleChange(null)} onFocus={openable.open} /> diff --git a/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx index 4274bf89..700040db 100644 --- a/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx +++ b/src/front/Components/DesignSystem/AutocompleteMultiSelect/index.tsx @@ -1,24 +1,24 @@ import useOpenable from "@Front/Hooks/useOpenable"; import { useCallback, useEffect, useState } from "react"; +import { getLabel } from "../Dropdown"; import DropdownMenu from "../Dropdown/DropdownMenu"; import { IOption } from "../Dropdown/DropdownMenu/DropdownOption"; import Typography, { ETypo, ETypoColor } from "../Typography"; -import classes from "./classes.module.scss"; import ChipContainer from "./ChipContainer"; -import { getLabel } from "../Dropdown"; +import classes from "./classes.module.scss"; type IProps = { options: IOption[]; placeholder?: string; disabled?: boolean; label?: string; - onSelect?: (option: IOption) => void; + onSelectionChange?: (options: IOption[] | null) => void; selectedOptions?: IOption[] | null; }; export default function AutocompleteMultiSelect(props: IProps) { - const { options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props; + const { onSelectionChange, options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props; const [selectedOptions, setSelectedOptions] = useState(selectedOptionsProps ?? null); const [searchValue, setSearchValue] = useState(""); const [filteredOptions, setFilteredOptions] = useState(options); @@ -27,7 +27,6 @@ export default function AutocompleteMultiSelect(props: IProps) { useEffect(() => { if (searchValue) { const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase())); - console.log(filteredOptions); if (filteredOptions.length === 0) return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]); return setFilteredOptions(filteredOptions); @@ -47,17 +46,25 @@ export default function AutocompleteMultiSelect(props: IProps) { [openable], ); + const handleChange = useCallback( + (options: IOption[] | null) => { + setSelectedOptions(options); + onSelectionChange?.(options); + }, + [onSelectionChange], + ); + useEffect(() => { setSelectedOptions(selectedOptionsProps ?? null); }, [selectedOptionsProps]); const handleSelectOption = useCallback( (_newOption: IOption, options: IOption[]) => { - setSelectedOptions(options); + handleChange(options); setSearchValue(""); openable.close(); }, - [openable], + [handleChange, openable], ); return ( @@ -78,10 +85,10 @@ export default function AutocompleteMultiSelect(props: IProps) { disabled={disabled} onChange={handleSearchChange} value={searchValue} - onClear={() => setSelectedOptions(null)} + onClear={() => handleChange(null)} onFocus={openable.open} selectedOptions={selectedOptions ?? []} - onSelectedOptionsChange={setSelectedOptions} + onSelectedOptionsChange={handleChange} /> ); diff --git a/src/front/Components/DesignSystem/Dropdown/classes.module.scss b/src/front/Components/DesignSystem/Dropdown/classes.module.scss index ccb9c08a..d2b3d7b3 100644 --- a/src/front/Components/DesignSystem/Dropdown/classes.module.scss +++ b/src/front/Components/DesignSystem/Dropdown/classes.module.scss @@ -30,6 +30,7 @@ padding: 0px var(--spacing-2, 16px); align-items: center; flex: 1 0 0; + gap: 4px; } svg { diff --git a/src/front/Components/DesignSystem/Dropdown/index.tsx b/src/front/Components/DesignSystem/Dropdown/index.tsx index b00cacea..f325a0e5 100644 --- a/src/front/Components/DesignSystem/Dropdown/index.tsx +++ b/src/front/Components/DesignSystem/Dropdown/index.tsx @@ -13,12 +13,12 @@ type IProps = { label?: string; placeholder?: string; disabled?: boolean; - onSelect?: (option: IOption) => void; + onSelectionChange?: (option: IOption) => void; selectedOption?: IOption | null; }; export default function Dropdown(props: IProps) { - const { options, placeholder, disabled, onSelect, selectedOption: selectedOptionProps, label } = props; + const { options, placeholder, disabled, onSelectionChange, selectedOption: selectedOptionProps, label } = props; const [selectedOption, setSelectedOption] = useState(selectedOptionProps ?? null); const openable = useOpenable({ defaultOpen: false }); @@ -29,9 +29,9 @@ export default function Dropdown(props: IProps) { const handleOnSelect = useCallback( (newOption: IOption, _options: IOption[]) => { setSelectedOption(newOption); - onSelect?.(newOption); + onSelectionChange?.(newOption); }, - [onSelect], + [onSelectionChange], ); return ( @@ -55,12 +55,7 @@ export default function Dropdown(props: IProps) { ])} onClick={openable.toggle}>
- - {getLabel(selectedOption) ?? placeholder} - + {getLabelContent(selectedOption, placeholder)}
@@ -74,5 +69,44 @@ export function getLabel(option: IOption | null): string | null { if (typeof option.label === "string") { return option.label; } - return `${option.label.text} ${option.label.subtext}`; + return `${option.label.text}, ${option.label.subtext}`; +} + +function getLabelContent(option: IOption | null, placeholder?: string) { + if (!option) + return ( + + {placeholder} + + ); + + if (typeof option.label === "string") { + return ( + + {option.label} + + ); + } + + return ( + + + {`${option.label.text} , `} + + + {option.label.subtext} + + + ); } diff --git a/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx b/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx index ce36524a..d774c9ac 100644 --- a/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx +++ b/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx @@ -7,7 +7,7 @@ import BaseField, { IProps as IBaseFieldProps, IState as IBaseFieldState } from import classes from "./classes.module.scss"; export type IProps = IBaseFieldProps & { - onSelect?: (option: IOption) => void; + onSelectionChange?: (option: IOption | null) => void; options: IOption[]; selectedOption?: IOption | null; label?: string; @@ -28,9 +28,9 @@ export default class AutocompleteField extends BaseField { this.handleOnChange = this.handleOnChange.bind(this); } - private handleOnChange = (option: IOption) => { + private handleOnChange = (option: IOption | null) => { this.setState({ selectedOption: option }); - this.props.onSelect?.(option); + this.props.onSelectionChange?.(option); }; public override componentDidUpdate(prevProps: IProps): void { @@ -45,9 +45,10 @@ export default class AutocompleteField extends BaseField { {this.state.selectedOption && ( void; + options: IOption[]; + selectedOptions?: IOption[] | null; + label?: string; +}; + +type IState = IBaseFieldState & { + selectedOptions: IOption[] | null; +}; + +export default class AutocompleteMultiSelectField extends BaseField { + constructor(props: IProps) { + super(props); + this.state = { + selectedOptions: this.props.selectedOptions ?? null, + ...this.getDefaultState(), + }; + + this.handleOnChange = this.handleOnChange.bind(this); + } + + private handleOnChange = (options: IOption[] | null) => { + this.setState({ selectedOptions: options }); + this.props.onSelectionChange?.(options); + }; + + public override componentDidUpdate(prevProps: IProps): void { + if (prevProps.selectedOptions !== this.props.selectedOptions) { + this.setState({ selectedOptions: this.props.selectedOptions ?? null }); + } + } + + public override render(): ReactNode { + return ( +
+ + {this.state.selectedOptions && ( + + )} + {this.hasError() &&
{this.renderErrors()}
} +
+ ); + } +} diff --git a/src/front/Components/DesignSystem/Form/SelectField/index.tsx b/src/front/Components/DesignSystem/Form/SelectField/index.tsx index 3a79d80c..d36b5486 100644 --- a/src/front/Components/DesignSystem/Form/SelectField/index.tsx +++ b/src/front/Components/DesignSystem/Form/SelectField/index.tsx @@ -7,7 +7,7 @@ import classes from "./classes.module.scss"; import Dropdown from "../../Dropdown"; export type IProps = IBaseFieldProps & { - onSelect?: (option: IOption) => void; + onSelectionChange?: (option: IOption) => void; options: IOption[]; selectedOption?: IOption | null; label?: string; @@ -30,7 +30,7 @@ export default class SelectField extends BaseField { private handleOnChange = (option: IOption) => { this.setState({ selectedOption: option }); - this.props.onSelect?.(option); + this.props.onSelectionChange?.(option); }; public override componentDidUpdate(prevProps: IProps): void { @@ -45,9 +45,10 @@ export default class SelectField extends BaseField { {this.state.selectedOption && ( div { - width: 100%; - > div:first-of-type > div:first-of-type { - padding: 24px; - } - } - } - - &.active { - .input-container { - > div > div > div { - padding: 24px 16px 16px 16px !important; - } - } - } - - .is-active-placeholder { - position: absolute; - top: -11px; - left: 8px; - background-color: #ffffff; - z-index: 1; - padding: 0 16px; - } - - &[data-is-errored="true"] { - .input { - border: 1px solid var(--color-error-600); - ~ .fake-placeholder { - color: var(--color-error-600); - } - } - } - } -} diff --git a/src/front/Components/DesignSystem/MultiSelect/index.tsx b/src/front/Components/DesignSystem/MultiSelect/index.tsx deleted file mode 100644 index d505f4f6..00000000 --- a/src/front/Components/DesignSystem/MultiSelect/index.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { ValidationError } from "class-validator"; -import classNames from "classnames"; -import React from "react"; -import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select"; - -import { IOptionOld } from "../Form/SelectFieldOld"; -import Typography, { ETypo, ETypoColor } from "../Typography"; -import classes from "./classes.module.scss"; -import { styles } from "./styles"; - -type IProps = { - options: IOptionOld[]; - label?: string | JSX.Element; - placeholder?: string; - onChange?: (newValue: MultiValue, actionMeta: ActionMeta) => void; - defaultValue?: PropsValue; - value?: PropsValue; - isMulti?: boolean; - shouldCloseMenuOnSelect: boolean; - isOptionDisabled?: (option: IOptionOld, selectValue: Options) => boolean; - validationError?: ValidationError; -}; -type IState = { - isFocused: boolean; - selectedOptions: MultiValue; - validationError: ValidationError | null; -}; - -export default class MultiSelect extends React.Component { - public static defaultProps: Partial = { - placeholder: "Sélectionner une option...", - shouldCloseMenuOnSelect: false, - }; - - constructor(props: IProps) { - super(props); - this.state = { - isFocused: false, - selectedOptions: [], - validationError: this.props.validationError ?? null, - }; - this.hasError = this.hasError.bind(this); - this.onChange = this.onChange.bind(this); - this.onEmptyResearch = this.onEmptyResearch.bind(this); - this.onFocus = this.onFocus.bind(this); - this.onBlur = this.onBlur.bind(this); - this.renderErrors = this.renderErrors.bind(this); - } - public override render(): JSX.Element { - return ( -
-
= 1 && classes["active"])}> - {this.props.label &&
{this.props.label}
} - {this.props.placeholder && ( -
= 1).toString()}> - - {this.props.placeholder} - -
- )} -
- -
-
- {this.hasError() &&
{this.renderErrors()}
} -
- ); - } - - public override componentDidMount(): void { - if (this.props.defaultValue) { - // If default value contains multiple IOptions - if (Array.isArray(this.props.defaultValue)) { - this.setState({ selectedOptions: this.props.defaultValue }); - } - - // If default value is a single IOption - if ("label" in this.props.defaultValue) { - this.setState({ selectedOptions: [this.props.defaultValue] }); - } - } - } - - public override componentDidUpdate(prevProps: IProps): void { - if (this.props.validationError !== prevProps.validationError) { - this.setState({ - validationError: this.props.validationError ?? null, - }); - } - if (this.props.defaultValue && this.props.defaultValue !== prevProps.defaultValue) { - // If default value contains multiple IOptions - if (Array.isArray(this.props.defaultValue)) { - this.setState({ selectedOptions: this.props.defaultValue }); - } - - // If default value is a single IOption - if ("label" in this.props.defaultValue) { - this.setState({ selectedOptions: [this.props.defaultValue] }); - } - } - } - - private onFocus() { - this.setState({ isFocused: true }); - } - - private onBlur() { - this.setState({ isFocused: false }); - } - - private onChange(newValue: MultiValue, actionMeta: ActionMeta) { - this.props.onChange && this.props.onChange(newValue, actionMeta); - this.setState({ - selectedOptions: newValue, - validationError: null, - }); - } - - private onEmptyResearch() { - if (this.state.selectedOptions.length === this.props.options.length) { - return null; - } - return "Aucune option trouvée"; - } - - protected hasError(): boolean { - return this.state.validationError !== null; - } - - protected renderErrors(): JSX.Element[] | null { - if (!this.state.validationError || !this.state.validationError.constraints) return null; - let errors: JSX.Element[] = []; - Object.entries(this.state.validationError.constraints).forEach(([key, value]) => { - errors.push( - - {value} - , - ); - }); - return errors; - } -} diff --git a/src/front/Components/DesignSystem/MultiSelect/styles.tsx b/src/front/Components/DesignSystem/MultiSelect/styles.tsx deleted file mode 100644 index cc0ca791..00000000 --- a/src/front/Components/DesignSystem/MultiSelect/styles.tsx +++ /dev/null @@ -1,100 +0,0 @@ -export const styles = { - option: (provided: any, props: { isSelected: boolean; isFocused: boolean }) => ({ - ...provided, - cursor: "pointer", - padding: "8px 24px", - fontFamily: "var(--font-text-family)", - fontStyle: "normal", - fontWeight: "400", - fontSize: "18px", - lineHeight: "21.78px", - color: "#939393", - backgroundColor: props.isSelected ? "var(--color-primary-3)" : props.isFocused ? "var(--color-primary-3)" : undefined, - - ":active": { - ...provided[":active"], - backgroundColor: props.isSelected ? "var(--color-primary-3)" : undefined, - }, - }), - control: () => ({ - width: "100%", - display: "flex", - background: "transparent", - }), - valueContainer: (provided: any) => ({ - ...provided, - padding: 0, - minWidth: "100px", - fontFamily: "var(--font-text-family)", - fontStyle: "normal", - fontWeight: "600", - fontSize: "16px", - lineHeight: "22px", - color: "#939393", - letter: "0.5 px", - }), - multiValue: (provided: any) => ({ - ...provided, - margin: "4px", - padding: "8px 16px", - fontStyle: "normal", - fontWeight: "400", - fontSize: "16px", - lineHeight: "22px", - background: "transparent", - border: "1px solid black", - borderRadius: "100px", - }), - multiValueLabel: (provided: any) => ({ - ...provided, - fontSize: "16px", - color: "#939393", - fontWeight: "400", - }), - input: (provided: any) => ({ - ...provided, - margin: 0, - padding: 0, - }), - placeholder: (provided: any) => ({ - ...provided, - fontSize: "16px", - lineHeight: "22px", - fontWeight: "400", - color: "#939393", - }), - indicatorSeparator: () => ({ - display: "none", - }), - menu: (provided: any) => ({ - ...provided, - position: "static", - border: "0", - boxShadow: "none", - }), - menuList: (provided: any) => ({ - ...provided, - }), - multiValueRemove: (provided: any) => ({ - ...provided, - backgroundColor: "transparent", - color: "black", - "&:hover": { - color: "grey", - backgroundColor: "transparent", - }, - ">svg": { - width: "20px", - height: "20px", - }, - }), - indicatorsContainer: (provided: any) => ({ - ...provided, - display: "none", - }), - listBox: (provided: any) => ({ - ...provided, - color: "red", - fontSize: "16px", - }), -}; diff --git a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx index 458f6d67..b834da21 100644 --- a/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx +++ b/src/front/Components/DesignSystem/SearchBlockList/DropdownNavigation/index.tsx @@ -38,8 +38,12 @@ export default function DropdownNavigation({ blocks, onSelectedBlock, defaultSel }, } as IOption; })} - onSelect={handleDropDownSelect} - selectedOption={selectedBlock ? { id: selectedBlock.id, label: selectedBlock.primaryText } : undefined} + onSelectionChange={handleDropDownSelect} + selectedOption={ + selectedBlock + ? { id: selectedBlock.id, label: { text: selectedBlock.secondaryText ?? "", subtext: selectedBlock.primaryText } } + : undefined + } />
); diff --git a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx index bedf9614..9e6553b0 100644 --- a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx +++ b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx @@ -208,7 +208,7 @@ export default function CollaboratorInformations(props: IProps) { options={availableRoles.filter((role) => { return role.label !== "admin"; })} - onSelect={handleRoleChange} + onSelectionChange={handleRoleChange} selectedOption={selectedOption} />
diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx index 2b21f6c1..b547d980 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx @@ -3,9 +3,9 @@ import PenICon from "@Assets/Icons/pen.svg"; import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes"; import DocumentTypes from "@Front/Api/LeCoffreApi/Admin/DocumentTypes/DocumentTypes"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption"; import Form from "@Front/Components/DesignSystem/Form"; -import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld"; -import MultiSelect from "@Front/Components/DesignSystem/MultiSelect"; +import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Tooltip from "@Front/Components/DesignSystem/ToolTip"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; @@ -17,7 +17,6 @@ import Image from "next/image"; import Link from "next/link"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; -import { MultiValue } from "react-select"; import classes from "./classes.module.scss"; @@ -28,7 +27,7 @@ export default function DeedTypesInformations(props: IProps) { const [deedTypeSelected, setDeedTypeSelected] = useState(null); const [availableDocuments, setAvailableDocuments] = useState([]); - const [selectedDocuments, setSelectedDocuments] = useState([]); + const [selectedDocuments, setSelectedDocuments] = useState([]); const [isDeleteModalOpened, setIsDeleteModalOpened] = useState(false); const [isSaveModalOpened, setIsSaveModalOpened] = useState(false); @@ -71,11 +70,11 @@ export default function DeedTypesInformations(props: IProps) { setDeedTypeSelected(deedType); if (!deedType.document_types) return; - const documentsOptions: IOptionOld[] = deedType.document_types + const documentsOptions: IOption[] = deedType.document_types ?.map((documentType) => { return { label: documentType.name, - value: documentType.uid, + id: documentType.uid ?? "", }; }) .sort((a, b) => a.label.localeCompare(b.label)); @@ -101,19 +100,19 @@ export default function DeedTypesInformations(props: IProps) { const saveDocumentTypes = useCallback(async () => { await DeedTypes.getInstance().put(deedTypeUid as string, { uid: deedTypeUid as string, - document_types: selectedDocuments.map((document) => DocumentType.hydrate({ uid: document.value as string })), + document_types: selectedDocuments.map((document) => DocumentType.hydrate({ uid: document.id as string })), }); closeSaveModal(); }, [closeSaveModal, deedTypeUid, selectedDocuments]); - const onDocumentChangeHandler = useCallback((values: MultiValue) => { - setSelectedDocuments(values as IOptionOld[]); + const onDocumentChangeHandler = useCallback((options: IOption[] | null) => { + options && setSelectedDocuments(options); }, []); - const formattedOptions: IOptionOld[] = availableDocuments + const formattedOptions: IOption[] = availableDocuments .map((document) => ({ label: document.name, - value: document.uid, + id: document.uid ?? "", })) .sort((a, b) => a.label.localeCompare(b.label)); @@ -161,11 +160,11 @@ export default function DeedTypesInformations(props: IProps) {
-
diff --git a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx index 0424fde9..0af9d9e9 100644 --- a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx @@ -1,14 +1,16 @@ import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers"; import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; +import AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption"; import Form from "@Front/Components/DesignSystem/Form"; -import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld"; -import MultiSelect from "@Front/Components/DesignSystem/MultiSelect"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; import RadioBox from "@Front/Components/DesignSystem/RadioBox"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import BackArrow from "@Front/Components/Elements/BackArrow"; import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; import Module from "@Front/Config/Module"; +import { ValidationError } from "class-validator"; import { ECivility } from "le-coffre-resources/dist/Customer/Contact"; import { Contact, Customer, OfficeFolder } from "le-coffre-resources/dist/Notary"; import Link from "next/link"; @@ -16,8 +18,6 @@ import { NextRouter, useRouter } from "next/router"; import BasePage from "../../Base"; import classes from "./classes.module.scss"; -import TextField from "@Front/Components/DesignSystem/Form/TextField"; -import { ValidationError } from "class-validator"; enum ESelectedOption { EXISTING_CUSTOMER = "existing_customer", @@ -27,8 +27,8 @@ type IProps = {}; type IState = { selectedOption: ESelectedOption; availableCustomers: Customer[]; - selectedCustomers: readonly IOptionOld[]; - existingCustomers: IOptionOld[]; + selectedCustomers: IOption[]; + existingCustomers: IOption[]; isLoaded: boolean; validationError: ValidationError[]; }; @@ -54,7 +54,7 @@ class AddClientToFolderClass extends BasePage { this.onFormSubmit = this.onFormSubmit.bind(this); } public override render(): JSX.Element { - const selectOptions: IOptionOld[] = this.getSelectedOptions(); + const selectOptions: IOption[] = this.getSelectedOptions(); const backwardPath = Module.getInstance() .get() @@ -91,12 +91,13 @@ class AddClientToFolderClass extends BasePage {
{this.state.selectedOption === "existing_customer" && (
- +
diff --git a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx index 5e6a515e..69e21fb4 100644 --- a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx @@ -5,11 +5,10 @@ import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users"; import Button from "@Front/Components/DesignSystem/Button"; import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption"; import Form from "@Front/Components/DesignSystem/Form"; +import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; import SelectField from "@Front/Components/DesignSystem/Form/SelectField"; -import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld"; import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; -import MultiSelect from "@Front/Components/DesignSystem/MultiSelect"; import RadioBox from "@Front/Components/DesignSystem/RadioBox"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import BackArrow from "@Front/Components/Elements/BackArrow"; @@ -20,8 +19,7 @@ import { Deed, Office, OfficeFolder } from "le-coffre-resources/dist/Notary"; import User from "le-coffre-resources/dist/Notary"; import { DeedType } from "le-coffre-resources/dist/Notary"; import { useRouter } from "next/router"; -import React, { useEffect, useState } from "react"; -import { MultiValue } from "react-select"; +import React, { useCallback, useEffect, useState } from "react"; import classes from "./classes.module.scss"; @@ -89,12 +87,14 @@ export default function CreateFolder(): JSX.Element { const radioOnChange = (e: React.ChangeEvent) => setFolderAccessType(e.target.value as "whole_office" | "select_collaborators"); - const onSelectedCollaboratorsChange = (values: MultiValue) => { - const selectedCollaborators = availableCollaborators.filter((collaborator) => - values.some((value) => value.value === collaborator.uid), - ); - setSelectedCollaborators(selectedCollaborators); - }; + const onSelectedCollaboratorsChange = useCallback( + (options: IOption[] | null) => { + if (!options) return; + const collaborators = availableCollaborators.filter((collaborator) => options.find((option) => option.id === collaborator.uid)); + setSelectedCollaborators(collaborators); + }, + [availableCollaborators], + ); /** * UseEffect @@ -178,19 +178,17 @@ export default function CreateFolder(): JSX.Element {
{folderAccessType === "select_collaborators" && (
- ({ - label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name), - value: collaborator.uid, - })) as IOptionOld[] - } - defaultValue={selectedCollaborators.map((collaborator) => ({ - label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) as string, - value: collaborator.uid!, + ({ + label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "", + id: collaborator.uid ?? "", }))} - onChange={onSelectedCollaboratorsChange} - placeholder="Sélectionner les collaborateurs" + selectedOptions={selectedCollaborators.map((collaborator) => ({ + label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "", + id: collaborator.uid ?? "", + }))} + onSelectionChange={onSelectedCollaboratorsChange} validationError={validationError.find((error) => error.property === "stakeholders")} />
diff --git a/src/front/Components/Layouts/Folder/UpdateFolderCollaborators/index.tsx b/src/front/Components/Layouts/Folder/UpdateFolderCollaborators/index.tsx index d9967e4c..cd000302 100644 --- a/src/front/Components/Layouts/Folder/UpdateFolderCollaborators/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateFolderCollaborators/index.tsx @@ -2,9 +2,9 @@ import backgroundImage from "@Assets/images/background_refonte.svg"; import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; import Users, { IGetUsersParams } from "@Front/Api/LeCoffreApi/Notary/Users/Users"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; +import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption"; import Form from "@Front/Components/DesignSystem/Form"; -import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld"; -import MultiSelect from "@Front/Components/DesignSystem/MultiSelect"; +import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; import RadioBox from "@Front/Components/DesignSystem/RadioBox"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import BackArrow from "@Front/Components/Elements/BackArrow"; @@ -26,9 +26,8 @@ enum ERadioBoxValue { export default function UpdateFolderCollaborators() { const router = useRouter(); let { folderUid } = router.query; - const [availableCollaborators, setAvailableCollaborators] = useState([]); - const [selectedCollaborators, setSelectedCollaborators] = useState([]); + const [selectedCollaborators, setSelectedCollaborators] = useState([]); const [defaultCheckedAllOffice, setDefaultCheckedAllOffice] = useState(false); const [selectedOption, setSelectedOption] = useState(ERadioBoxValue.SELECTION); const [loading, setLoading] = useState(true); @@ -40,9 +39,7 @@ export default function UpdateFolderCollaborators() { try { let collaboratorsUid: User[] = availableCollaborators; if (selectedOption === ERadioBoxValue.SELECTION) { - collaboratorsUid = selectedCollaborators.map((collaborator) => - User.hydrate({ uid: collaborator.value as string }), - ); + collaboratorsUid = selectedCollaborators.map((collaborator) => User.hydrate({ uid: collaborator.id as string })); } await Folders.getInstance().put(folderUid, { stakeholders: collaboratorsUid }); router.push( @@ -61,8 +58,8 @@ export default function UpdateFolderCollaborators() { setSelectedOption(ERadioBoxValue.ALL); }, []); - const onChangeSelectedCollaborators = useCallback((selectedCollaborators: readonly IOptionOld[]) => { - setSelectedCollaborators(selectedCollaborators); + const onChangeSelectedCollaborators = useCallback((selectedCollaborators: IOption[] | null) => { + selectedCollaborators && setSelectedCollaborators(selectedCollaborators); }, []); const onSelectedOptionSpecific = useCallback((event: React.ChangeEvent) => { @@ -86,10 +83,10 @@ export default function UpdateFolderCollaborators() { let folder = null; try { folder = await Folders.getInstance().getByUid(folderUid, query); - const preSelectedCollaborators: IOptionOld[] = folder.stakeholders!.map((collaborator) => { + const preSelectedCollaborators: IOption[] = folder.stakeholders!.map((collaborator) => { return { label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name, - value: collaborator.uid, + id: collaborator.uid ?? "", }; }); @@ -126,10 +123,10 @@ export default function UpdateFolderCollaborators() { const foldersInformationPath = Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path; const backwardPath = foldersInformationPath.replace("[folderUid]", folderUid as string); - const selectOptions: IOptionOld[] = availableCollaborators.map((collaborator) => { + const selectOptions: IOption[] = availableCollaborators.map((collaborator) => { return { label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name, - value: collaborator.uid, + id: collaborator.uid ?? "", }; }); @@ -162,11 +159,11 @@ export default function UpdateFolderCollaborators() { {selectedOption === ERadioBoxValue.SELECTION && (
- error.property === "stakeholders")} />
From 68ee0483e5e6bbc57e9091e7a8510fdee144bd6b Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 29 Jul 2024 13:35:34 +0200 Subject: [PATCH 15/18] :sparkles: Footer everywhere --- .../DesignSystem/Footer/classes.module.scss | 14 +++++++++++++- .../Components/DesignSystem/Footer/desktop.tsx | 2 +- src/front/Components/DesignSystem/Footer/index.tsx | 6 ++++-- .../Components/DesignSystem/Footer/mobile.tsx | 2 +- .../Components/DesignSystem/Footer/tablet.tsx | 2 +- .../DefaultDoubleSidePage/index.tsx | 2 ++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/front/Components/DesignSystem/Footer/classes.module.scss b/src/front/Components/DesignSystem/Footer/classes.module.scss index 16d6a0fb..a66b89c7 100644 --- a/src/front/Components/DesignSystem/Footer/classes.module.scss +++ b/src/front/Components/DesignSystem/Footer/classes.module.scss @@ -8,6 +8,7 @@ font-size: 12px; font-weight: var(--font-text-weight-regular, 400); letter-spacing: 0.06px; + .sub-root { display: flex; align-items: center; @@ -21,7 +22,18 @@ } } - @media (max-width: 660px) or (min-width: 768px) { + &[data-has-left-padding="true"] { + .desktop { + padding: var(--spacing-1-5, 12px) var(--spacing-15, 120px); + } + } + + &[data-is-sticky="true"] { + position: sticky; + bottom: 0; + } + + @media (max-width: 660px) or (min-width: 769px) { .tablet { display: none; } diff --git a/src/front/Components/DesignSystem/Footer/desktop.tsx b/src/front/Components/DesignSystem/Footer/desktop.tsx index 023fb75e..f3937b1c 100644 --- a/src/front/Components/DesignSystem/Footer/desktop.tsx +++ b/src/front/Components/DesignSystem/Footer/desktop.tsx @@ -13,7 +13,7 @@ const legalPages = Module.getInstance().get().modules.pages.Legal.pages.LegalInf export default function Desktop({ className }: IProps) { return (
- © Copyright lecoffre 2024 + © Copyright lecoffre 2024 Conditions d'utilisation diff --git a/src/front/Components/DesignSystem/Footer/index.tsx b/src/front/Components/DesignSystem/Footer/index.tsx index 9a23212f..a212956f 100644 --- a/src/front/Components/DesignSystem/Footer/index.tsx +++ b/src/front/Components/DesignSystem/Footer/index.tsx @@ -6,14 +6,16 @@ import Tablet from "./tablet"; type IProps = { className?: string; + hasLeftPadding?: boolean; + isSticky?: boolean; }; -export default function Footer({ className }: IProps) { +export default function Footer({ className, hasLeftPadding = false, isSticky = false }: IProps) { useEffect(() => { document.documentElement.style.setProperty("--footer-height", `43px`); }); return ( -