diff --git a/src/front/Components/DesignSystem/BlockList/classes.module.scss b/src/front/Components/DesignSystem/BlockList/classes.module.scss new file mode 100644 index 00000000..989c0eca --- /dev/null +++ b/src/front/Components/DesignSystem/BlockList/classes.module.scss @@ -0,0 +1,25 @@ +@import "@Themes/constants.scss"; + +.root { + display: inline-flex; + justify-content: space-between; + align-items: center; + width: 100%; + padding: 24px; + border: 1px solid $grey-medium; + cursor: pointer; + + &:hover { + background-color: $grey-medium; + } + + .left-side { + display: inline-flex; + justify-content: space-between; + align-items: center; + + .warning { + margin-left: 32px; + } + } +} diff --git a/src/front/Components/DesignSystem/BlockList/index.tsx b/src/front/Components/DesignSystem/BlockList/index.tsx new file mode 100644 index 00000000..a61b1ba7 --- /dev/null +++ b/src/front/Components/DesignSystem/BlockList/index.tsx @@ -0,0 +1,39 @@ +import React, { useCallback } from "react"; +import classes from "./classes.module.scss"; +import Typography, { ITypo } from "../Typography"; +import ChevronIcon from "@Assets/Icons/chevron.svg"; +import Image from "next/image"; + +export type IBlock = { + name: string; + id: string; +}; + +type IProps = { + blocks: IBlock[]; + onSelectedBlock: (block: IBlock) => void; +}; +export default function BlockList({ blocks, onSelectedBlock }: IProps) { + const selectBlock = useCallback( + (e: React.MouseEvent) => { + onSelectedBlock && onSelectedBlock(blocks.find((block) => block.id === e.currentTarget.id)!); + }, + [blocks, onSelectedBlock], + ); + return ( +
+ {blocks.map((block) => { + return ( +
+
+
+ {block.name} +
+ chevron +
+
+ ); + })} +
+ ); +} diff --git a/src/front/Components/DesignSystem/Header/BurgerMenu/BurgerModal/index.tsx b/src/front/Components/DesignSystem/Header/BurgerMenu/BurgerModal/index.tsx index 2c6cd1d5..857c731c 100644 --- a/src/front/Components/DesignSystem/Header/BurgerMenu/BurgerModal/index.tsx +++ b/src/front/Components/DesignSystem/Header/BurgerMenu/BurgerModal/index.tsx @@ -32,6 +32,11 @@ export default class BurgerModal extends React.Component { text="Dossiers archivés" routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]} /> +
diff --git a/src/front/Components/DesignSystem/Header/Navigation/index.tsx b/src/front/Components/DesignSystem/Header/Navigation/index.tsx index 16025e88..3145fec9 100644 --- a/src/front/Components/DesignSystem/Header/Navigation/index.tsx +++ b/src/front/Components/DesignSystem/Header/Navigation/index.tsx @@ -24,6 +24,11 @@ export default class Navigation extends React.Component { path={Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path} routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]} /> + ); } diff --git a/src/front/Components/DesignSystem/SearchBar/index.tsx b/src/front/Components/DesignSystem/SearchBar/index.tsx index 40590a95..d2b8f05f 100644 --- a/src/front/Components/DesignSystem/SearchBar/index.tsx +++ b/src/front/Components/DesignSystem/SearchBar/index.tsx @@ -1,16 +1,17 @@ import LoopIcon from "@Assets/Icons/loop.svg"; -import { IDashBoardFolder } from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; import Image from "next/image"; import React from "react"; import Typography, { ITypo } from "../Typography"; import classes from "./classes.module.scss"; +import { IBlock } from "../BlockList"; type IProps = { - folders: IDashBoardFolder[]; - onChange?: (folders: IDashBoardFolder[]) => IDashBoardFolder[]; + blocks: IBlock[]; + onChange?: (input: string) => void; placeholder?: string; }; + type IState = { hasValue: boolean; }; @@ -46,30 +47,10 @@ export default class SearchBar extends React.Component { const hasValue = event.target.value.length > 0; this.doesInputHaveValue(hasValue); if (!this.props.onChange) return; - this.props.onChange(this.filterFolders(event)!); + this.props.onChange(event.target.value); } private doesInputHaveValue(hasValue: boolean) { this.setState({ hasValue }); } - - private filterFolders(event: React.ChangeEvent) { - const filteredFolders: IDashBoardFolder[] = this.props.folders.filter((folder) => { - const name = folder.name.toLowerCase(); - const number = folder.folder_number.toLowerCase(); - const value = event.target.value.toLowerCase(); - - if (folder.customers) { - const customerNames = folder.customers - .map((customer) => { - return `${customer.contact?.first_name.toLowerCase()} ${customer.contact?.last_name.toLowerCase()}`; - }) - .join(", "); - return name.includes(value) || number.includes(value) || customerNames.includes(value); - } - - return name.includes(value) || number.includes(value); - }); - return filteredFolders; - } } diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss new file mode 100644 index 00000000..300d46f2 --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/classes.module.scss @@ -0,0 +1,21 @@ +@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 { + height: 100%; + border-right: 1px solid var(--grey-medium); + } +} diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx new file mode 100644 index 00000000..4f13a71b --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/CollaboratorListContainer/index.tsx @@ -0,0 +1,69 @@ +import React, { useCallback, useState } from "react"; + +import classes from "./classes.module.scss"; +import SearchBar from "@Front/Components/DesignSystem/SearchBar"; +import User from "le-coffre-resources/dist/Notary"; +import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList"; +import { useRouter } from "next/router"; + +type IProps = { + collaborators: User[]; + onSelectedCollaborator?: (user: User) => void; + onCloseLeftSide?: () => void; +}; + +export default function CollaboratorListContainer(props: IProps) { + const [filteredUsers, setFilteredUsers] = useState(props.collaborators); + const router = useRouter(); + + const filterUsers = useCallback( + (input: string) => { + const filteredUsers = props.collaborators.filter((user) => { + return ( + user.contact?.first_name?.toLowerCase().includes(input.toLowerCase()) || + user.contact?.last_name?.toLowerCase().includes(input.toLowerCase()) + ); + }); + setFilteredUsers(filteredUsers); + }, + [props.collaborators], + ); + + const onSelectedBlock = useCallback( + (block: IBlock) => { + props.onCloseLeftSide && props.onCloseLeftSide(); + router.push("/collaborators/" + block.id); + }, + [props, router], + ); + + return ( +
+
+
+ { + return { + name: collaborator.contact?.first_name + " " + collaborator.contact?.last_name, + id: collaborator.uid!, + }; + })} + onChange={filterUsers} + placeholder="Chercher un collaborateur" + /> +
+
+ { + return { + name: user.contact?.first_name + " " + user.contact?.last_name, + id: user.uid!, + }; + })} + onSelectedBlock={onSelectedBlock} + /> +
+
+
+ ); +} diff --git a/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss new file mode 100644 index 00000000..a5ba79a3 --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/classes.module.scss @@ -0,0 +1,117 @@ +@import "@Themes/constants.scss"; + +@keyframes growWidth { + 0% { + width: 100%; + } + + 100% { + width: 200%; + } +} + +.root { + .content { + display: flex; + overflow: hidden; + height: calc(100vh - 83px); + + .overlay { + position: absolute; + width: 100%; + height: 100%; + background-color: var(--white); + opacity: 0.5; + z-index: 2; + transition: all 0.3s $custom-easing; + } + + .left-side { + background-color: $white; + z-index: 3; + display: flex; + width: 389px; + min-width: 389px; + 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: 389px; + min-width: 389px; + } + } + + @media (max-width: $screen-s) { + width: 0px; + min-width: 0px; + + &.opened { + width: 100vw; + min-width: 100vw; + } + } + } + + .closable-left-side { + position: absolute; + background-color: $white; + z-index: 0; + display: flex; + justify-content: center; + min-width: 56px; + max-width: 56px; + height: calc(100vh - 83px); + border-right: 1px $grey-medium 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: 64px 48px; + overflow-y: auto; + + @media (max-width: ($screen-m - 1px)) { + min-width: calc(100vw - 56px); + } + + @media (max-width: $screen-s) { + padding: 40px 16px 64px 16px; + 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 new file mode 100644 index 00000000..1c2067f5 --- /dev/null +++ b/src/front/Components/LayoutTemplates/DefaultCollaboratorDashboard/index.tsx @@ -0,0 +1,118 @@ +import ChevronIcon from "@Assets/Icons/chevron.svg"; +import Button, { 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 Image from "next/image"; +import React, { ReactNode } from "react"; + +import classes from "./classes.module.scss"; +import Users, { IGetUsersparams } from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users"; +import User from "le-coffre-resources/dist/Notary"; +import CollaboratorListContainer from "./CollaboratorListContainer"; + +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)); + const query: IGetUsersparams = { + where: { office_uid: "6981326f-8a0a-4437-b15c-4cd5c4d80f6e" }, + include: { contact: true }, + }; + + const collaborators = await Users.getInstance().get(query); + this.setState({ collaborators }); + } + 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 }); + } +} diff --git a/src/front/Components/Layouts/Collaborators/classes.module.scss b/src/front/Components/Layouts/Collaborators/classes.module.scss new file mode 100644 index 00000000..a425a01a --- /dev/null +++ b/src/front/Components/Layouts/Collaborators/classes.module.scss @@ -0,0 +1,72 @@ +@import "@Themes/constants.scss"; + +.root { + display: flex; + align-items: center; + flex-direction: column; + min-height: 100%; + + .no-folder-selected { + width: 100%; + + .choose-a-folder { + margin-top: 96px; + text-align: center; + } + } + + .folder-informations { + width: 100%; + min-height: 100%; + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: column; + flex-grow: 1; + + .folder-header { + width: 100%; + + .header { + margin-bottom: 32px; + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + } + } + + .second-box { + margin-top: 24px; + margin-bottom: 32px; + } + + .progress-bar { + margin-bottom: 32px; + } + + .button-container { + width: 100%; + text-align: center; + :first-child { + margin-right: 12px; + } + > * { + margin: auto; + } + @media (max-width: $screen-m) { + :first-child { + margin-right: 0; + margin-bottom: 12px; + } + > * { + width: 100%; + } + } + } + .modal-title { + margin-bottom: 24px; + } + } +} diff --git a/src/front/Components/Layouts/Collaborators/index.tsx b/src/front/Components/Layouts/Collaborators/index.tsx new file mode 100644 index 00000000..c0cfc8f7 --- /dev/null +++ b/src/front/Components/Layouts/Collaborators/index.tsx @@ -0,0 +1,44 @@ +import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography"; +import { IDashBoardFolder } from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; + +import BasePage from "../Base"; +import classes from "./classes.module.scss"; +import DefaultCollaboratorDashboard from "@Front/Components/LayoutTemplates/DefaultCollaboratorDashboard"; + +type IProps = {}; +type IState = { + selectedFolder: IDashBoardFolder | null; + isArchivedModalOpen: boolean; +}; +export default class Folder extends BasePage { + public constructor(props: IProps) { + super(props); + this.state = { + selectedFolder: null, + isArchivedModalOpen: false, + }; + this.onSelectedFolder = this.onSelectedFolder.bind(this); + } + + // TODO: Message if the user has not created any folder yet + public override render(): JSX.Element { + return ( + +
+
+ Informations du collaboraeur +
+ + Sélectionnez un collaborateur + +
+
+
+
+ ); + } + + private onSelectedFolder(folder: IDashBoardFolder): void { + this.setState({ selectedFolder: folder }); + } +} diff --git a/src/front/Config/Module/development.json b/src/front/Config/Module/development.json index 740f6ee9..fd9cced8 100644 --- a/src/front/Config/Module/development.json +++ b/src/front/Config/Module/development.json @@ -119,6 +119,13 @@ "labelKey": "my_account" } }, + "Collaborators": { + "enabled": true, + "props": { + "path": "/collaborators", + "labelKey": "collaborators" + } + }, "404": { "enabled": true, "props": { diff --git a/src/front/Config/Module/preprod.json b/src/front/Config/Module/preprod.json index 740f6ee9..fd9cced8 100644 --- a/src/front/Config/Module/preprod.json +++ b/src/front/Config/Module/preprod.json @@ -119,6 +119,13 @@ "labelKey": "my_account" } }, + "Collaborators": { + "enabled": true, + "props": { + "path": "/collaborators", + "labelKey": "collaborators" + } + }, "404": { "enabled": true, "props": { diff --git a/src/front/Config/Module/production.json b/src/front/Config/Module/production.json index 740f6ee9..fd9cced8 100644 --- a/src/front/Config/Module/production.json +++ b/src/front/Config/Module/production.json @@ -119,6 +119,13 @@ "labelKey": "my_account" } }, + "Collaborators": { + "enabled": true, + "props": { + "path": "/collaborators", + "labelKey": "collaborators" + } + }, "404": { "enabled": true, "props": { diff --git a/src/front/Config/Module/staging.json b/src/front/Config/Module/staging.json index 740f6ee9..fd9cced8 100644 --- a/src/front/Config/Module/staging.json +++ b/src/front/Config/Module/staging.json @@ -119,6 +119,13 @@ "labelKey": "my_account" } }, + "Collaborators": { + "enabled": true, + "props": { + "path": "/collaborators", + "labelKey": "collaborators" + } + }, "404": { "enabled": true, "props": { diff --git a/src/pages/collaborators/[collaboratorUid]/index.tsx b/src/pages/collaborators/[collaboratorUid]/index.tsx new file mode 100644 index 00000000..300413ce --- /dev/null +++ b/src/pages/collaborators/[collaboratorUid]/index.tsx @@ -0,0 +1,5 @@ +import Collaborators from "@Front/Components/Layouts/Collaborators"; + +export default function Route() { + return ; +} diff --git a/src/pages/collaborators/index.tsx b/src/pages/collaborators/index.tsx new file mode 100644 index 00000000..300413ce --- /dev/null +++ b/src/pages/collaborators/index.tsx @@ -0,0 +1,5 @@ +import Collaborators from "@Front/Components/Layouts/Collaborators"; + +export default function Route() { + return ; +}