✨ burger modal
This commit is contained in:
parent
5efd8b3713
commit
f59f7ad9db
@ -1,18 +0,0 @@
|
|||||||
@import "@Themes/constants.scss";
|
|
||||||
|
|
||||||
.root {
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-menu {
|
|
||||||
padding: 24px;
|
|
||||||
text-align: center;
|
|
||||||
gap: 24px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
import classNames from "classnames";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import classes from "./classes.module.scss";
|
|
||||||
import { IAppRule } from "@Front/Api/Entities/rule";
|
|
||||||
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
|
||||||
import { IHeaderLinkProps } from "../../../ButtonHeader";
|
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
||||||
import HeaderSubmenuLink from "../../../HeaderSubmenu/HeaderSubmenuLink";
|
|
||||||
import useToggle from "@Front/Hooks/useToggle";
|
|
||||||
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline";
|
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
text: string | JSX.Element;
|
|
||||||
links: (IHeaderLinkProps & {
|
|
||||||
rules?: IAppRule[];
|
|
||||||
})[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function HeaderSubmenu(props: IProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
const { pathname } = router;
|
|
||||||
const [isActive, setIsActive] = useState(true);
|
|
||||||
const { active: isSubmenuOpened, toggle } = useToggle();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsActive(false);
|
|
||||||
if (props.links.some((link) => link.path === pathname)) setIsActive(true);
|
|
||||||
if (props.links.some((link) => link.routesActive?.some((routeActive) => pathname.includes(routeActive)))) setIsActive(true);
|
|
||||||
}, [isActive, pathname, props.links]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Rules mode={RulesMode.OPTIONAL} rules={props.links.flatMap((link) => link.rules ?? [])}>
|
|
||||||
<div className={classes["container"]}>
|
|
||||||
<div className={classNames(classes["root"], (isActive || isSubmenuOpened) && classes["active"])}>
|
|
||||||
<div className={classes["content"]} onClick={toggle}>
|
|
||||||
<Typography
|
|
||||||
typo={isActive || isSubmenuOpened ? ETypo.TEXT_LG_SEMIBOLD : ETypo.TEXT_LG_REGULAR}
|
|
||||||
color={isActive || isSubmenuOpened ? ETypoColor.COLOR_NEUTRAL_950 : ETypoColor.COLOR_NEUTRAL_500}>
|
|
||||||
{props.text}
|
|
||||||
</Typography>
|
|
||||||
{isSubmenuOpened ? <ChevronUpIcon height="20" width="20" /> : <ChevronDownIcon height="20" width="20" />}
|
|
||||||
</div>
|
|
||||||
<div className={classes["underline"]} data-active={(isActive || isSubmenuOpened).toString()} />
|
|
||||||
{isSubmenuOpened && (
|
|
||||||
<div className={classes["sub-menu"]}>
|
|
||||||
{props.links.map((link) => (
|
|
||||||
<Rules mode={RulesMode.NECESSARY} rules={link.rules ?? []} key={link.path}>
|
|
||||||
<HeaderSubmenuLink {...link} />
|
|
||||||
</Rules>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Rules>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,21 +1,22 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--header-height);
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
max-height: calc(100vh - var(--header-height));
|
||||||
|
padding: var(--spacing-05, 4px) var(--spacing-2, 16px);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
box-shadow: $shadow-nav;
|
|
||||||
padding: 24px;
|
|
||||||
position: absolute;
|
|
||||||
top: 83px;
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
text-align: center;
|
|
||||||
max-height: calc(100vh - var(--header-height));
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-bottom: 24px;
|
border-radius: var(--menu-radius, 0px);
|
||||||
}
|
background: var(--color-generic-white, #FFF);
|
||||||
|
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.10);
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,170 +1,196 @@
|
|||||||
|
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
|
||||||
import LogOutButton from "@Front/Components/DesignSystem/LogOutButton";
|
import LogOutButton from "@Front/Components/DesignSystem/LogOutButton";
|
||||||
|
import MenuItem from "@Front/Components/DesignSystem/Menu/MenuItem";
|
||||||
|
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import NavigationLink from "../../NavigationLink";
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
|
|
||||||
import BurgerModalSubmenu from "./BurgerModalSubmenu";
|
|
||||||
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
closeModal: () => void;
|
closeModal: () => void;
|
||||||
};
|
};
|
||||||
type IState = {};
|
|
||||||
|
|
||||||
export default class BurgerModal extends React.Component<IProps, IState> {
|
export default function BurgerModal(props: IProps) {
|
||||||
// TODO isEnabled depending on role given by DB
|
const { isOpen, closeModal } = props;
|
||||||
public override render(): JSX.Element | null {
|
if (!isOpen) return null;
|
||||||
if (!this.props.isOpen) return null;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classes["background"]} onClick={this.props.closeModal} />
|
<div className={classes["background"]} onClick={closeModal} />
|
||||||
<div className={classes["root"]}>
|
<div className={classes["root"]}>
|
||||||
<Rules
|
<Rules
|
||||||
mode={RulesMode.OPTIONAL}
|
mode={RulesMode.OPTIONAL}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
action: AppRuleActions.read,
|
action: AppRuleActions.read,
|
||||||
name: AppRuleNames.officeFolders,
|
name: AppRuleNames.officeFolders,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
<>
|
<>
|
||||||
<NavigationLink
|
<MenuItem
|
||||||
path={Module.getInstance().get().modules.pages.Folder.props.path}
|
item={{
|
||||||
text="Dossiers en cours"
|
text: "Dossiers en cours",
|
||||||
routesActive={[
|
routesActive: [
|
||||||
Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path,
|
Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path,
|
||||||
Module.getInstance().get().modules.pages.Folder.pages.CreateFolder.props.path,
|
Module.getInstance().get().modules.pages.Folder.pages.CreateFolder.props.path,
|
||||||
]}
|
],
|
||||||
/>
|
link: Module.getInstance().get().modules.pages.Folder.props.path,
|
||||||
<NavigationLink
|
}}
|
||||||
path={Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path}
|
/>
|
||||||
text="Dossiers archivés"
|
|
||||||
routesActive={[Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path]}
|
|
||||||
/>
|
|
||||||
<div className={classes["separator"]} />
|
|
||||||
</>
|
|
||||||
</Rules>
|
|
||||||
|
|
||||||
<BurgerModalSubmenu
|
<MenuItem
|
||||||
text={"Espace super admin"}
|
item={{
|
||||||
links={[
|
text: "Dossiers archivés",
|
||||||
{
|
routesActive: [Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path],
|
||||||
text: "Gestion des utilisateurs",
|
link: Module.getInstance().get().modules.pages.Folder.pages.FolderArchived.props.path,
|
||||||
path: Module.getInstance().get().modules.pages.Users.props.path,
|
hasSeparator: true,
|
||||||
routesActive: [
|
}}
|
||||||
Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path,
|
/>
|
||||||
Module.getInstance().get().modules.pages.Users.props.path,
|
</>
|
||||||
],
|
</Rules>
|
||||||
rules: [
|
|
||||||
{
|
<MenuItem
|
||||||
action: AppRuleActions.update,
|
item={{
|
||||||
name: AppRuleNames.offices,
|
text: "Espace super admin",
|
||||||
},
|
dropdown: {
|
||||||
],
|
items: [
|
||||||
},
|
{
|
||||||
{
|
text: "Gestion des utilisateurs",
|
||||||
text: "Gestion des offices",
|
link: Module.getInstance().get().modules.pages.Users.props.path,
|
||||||
path: Module.getInstance().get().modules.pages.Offices.props.path,
|
routesActive: [
|
||||||
routesActive: [
|
Module.getInstance().get().modules.pages.Users.pages.UsersInformations.props.path,
|
||||||
Module.getInstance().get().modules.pages.Offices.pages.OfficesInformations.props.path,
|
Module.getInstance().get().modules.pages.Users.props.path,
|
||||||
Module.getInstance().get().modules.pages.Offices.props.path,
|
],
|
||||||
],
|
rules: [
|
||||||
rules: [
|
{
|
||||||
{
|
action: AppRuleActions.update,
|
||||||
action: AppRuleActions.update,
|
name: AppRuleNames.offices,
|
||||||
name: AppRuleNames.offices,
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
},
|
],
|
||||||
]}
|
},
|
||||||
/>
|
}}
|
||||||
<BurgerModalSubmenu
|
/>
|
||||||
text="Espace office"
|
|
||||||
links={[
|
<MenuItem
|
||||||
{
|
item={{
|
||||||
text: "Collaborateurs",
|
text: "Espace office",
|
||||||
path: Module.getInstance().get().modules.pages.Collaborators.props.path,
|
hasSeparator: true,
|
||||||
routesActive: [
|
dropdown: {
|
||||||
Module.getInstance().get().modules.pages.Collaborators.pages.CollaboratorInformations.props.path,
|
items: [
|
||||||
Module.getInstance().get().modules.pages.Collaborators.props.path,
|
{
|
||||||
],
|
text: "Collaborateurs",
|
||||||
rules: [
|
link: Module.getInstance().get().modules.pages.Collaborators.props.path,
|
||||||
{
|
routesActive: [
|
||||||
action: AppRuleActions.update,
|
Module.getInstance().get().modules.pages.Collaborators.pages.CollaboratorInformations.props.path,
|
||||||
name: AppRuleNames.users,
|
Module.getInstance().get().modules.pages.Collaborators.props.path,
|
||||||
},
|
],
|
||||||
],
|
rules: [
|
||||||
},
|
{
|
||||||
{
|
action: AppRuleActions.update,
|
||||||
text: "Gestion des rôles",
|
name: AppRuleNames.users,
|
||||||
path: Module.getInstance().get().modules.pages.Roles.props.path,
|
},
|
||||||
routesActive: [
|
],
|
||||||
Module.getInstance().get().modules.pages.Roles.pages.Create.props.path,
|
},
|
||||||
Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path,
|
{
|
||||||
Module.getInstance().get().modules.pages.Roles.props.path,
|
text: "Gestion des rôles",
|
||||||
],
|
link: Module.getInstance().get().modules.pages.Roles.props.path,
|
||||||
rules: [
|
routesActive: [
|
||||||
{
|
Module.getInstance().get().modules.pages.Roles.pages.Create.props.path,
|
||||||
action: AppRuleActions.update,
|
Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path,
|
||||||
name: AppRuleNames.officeRoles,
|
Module.getInstance().get().modules.pages.Roles.props.path,
|
||||||
},
|
],
|
||||||
],
|
rules: [
|
||||||
},
|
{
|
||||||
{
|
action: AppRuleActions.update,
|
||||||
text: "Paramétrage des listes de pièces",
|
name: AppRuleNames.officeRoles,
|
||||||
path: Module.getInstance().get().modules.pages.DeedTypes.props.path,
|
},
|
||||||
routesActive: [
|
],
|
||||||
Module.getInstance().get().modules.pages.DeedTypes.pages.Create.props.path,
|
},
|
||||||
Module.getInstance().get().modules.pages.DeedTypes.pages.Edit.props.path,
|
{
|
||||||
Module.getInstance().get().modules.pages.DeedTypes.props.path,
|
text: "Paramétrage des listes de pièces",
|
||||||
Module.getInstance().get().modules.pages.DocumentTypes.props.path,
|
link: Module.getInstance().get().modules.pages.DeedTypes.props.path,
|
||||||
Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path,
|
routesActive: [
|
||||||
Module.getInstance().get().modules.pages.DocumentTypes.pages.Edit.props.path,
|
Module.getInstance().get().modules.pages.DeedTypes.pages.Create.props.path,
|
||||||
Module.getInstance().get().modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path,
|
Module.getInstance().get().modules.pages.DeedTypes.pages.Edit.props.path,
|
||||||
],
|
Module.getInstance().get().modules.pages.DeedTypes.props.path,
|
||||||
rules: [
|
Module.getInstance().get().modules.pages.DocumentTypes.props.path,
|
||||||
{
|
Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path,
|
||||||
action: AppRuleActions.update,
|
Module.getInstance().get().modules.pages.DocumentTypes.pages.Edit.props.path,
|
||||||
name: AppRuleNames.deedTypes,
|
Module.getInstance().get().modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path,
|
||||||
},
|
],
|
||||||
],
|
rules: [
|
||||||
},
|
{
|
||||||
{
|
action: AppRuleActions.update,
|
||||||
text: "RIB Office",
|
name: AppRuleNames.deedTypes,
|
||||||
path: Module.getInstance().get().modules.pages.OfficesRib.props.path,
|
},
|
||||||
rules: [
|
],
|
||||||
{
|
},
|
||||||
action: AppRuleActions.update,
|
{
|
||||||
name: AppRuleNames.rib,
|
text: "RIB Office",
|
||||||
},
|
link: Module.getInstance().get().modules.pages.OfficesRib.props.path,
|
||||||
],
|
rules: [
|
||||||
},
|
{
|
||||||
{
|
action: AppRuleActions.update,
|
||||||
text: "Abonnement",
|
name: AppRuleNames.rib,
|
||||||
path: Module.getInstance().get().modules.pages.Subscription.pages.Manage.props.path,
|
},
|
||||||
routesActive: [
|
],
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.Error.props.path,
|
},
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.Success.props.path,
|
{
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.Invite.props.path,
|
text: "Abonnement",
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.Manage.props.path,
|
link: Module.getInstance().get().modules.pages.Subscription.pages.Manage.props.path,
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.ManageCollaborators.props.path,
|
routesActive: [
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.New.props.path,
|
Module.getInstance().get().modules.pages.Subscription.pages.Error.props.path,
|
||||||
Module.getInstance().get().modules.pages.Subscription.pages.Subscribe.props.path,
|
Module.getInstance().get().modules.pages.Subscription.pages.Success.props.path,
|
||||||
],
|
Module.getInstance().get().modules.pages.Subscription.pages.Invite.props.path,
|
||||||
},
|
Module.getInstance().get().modules.pages.Subscription.pages.Manage.props.path,
|
||||||
]}
|
Module.getInstance().get().modules.pages.Subscription.pages.ManageCollaborators.props.path,
|
||||||
/>
|
Module.getInstance().get().modules.pages.Subscription.pages.New.props.path,
|
||||||
<div className={classes["separator"]} />
|
Module.getInstance().get().modules.pages.Subscription.pages.Subscribe.props.path,
|
||||||
<NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" />
|
],
|
||||||
<NavigationLink target="blank" path="https://ressources.lecoffre.io/" text="Guide de Prise en Main" />
|
},
|
||||||
<NavigationLink target="blank" path="https://tally.so/r/mBGaNY" text="Support" />
|
],
|
||||||
<NavigationLink target="blank" path="/CGU_LeCoffre_io.pdf" text="CGU" />
|
},
|
||||||
<LogOutButton />
|
}}
|
||||||
</div>
|
/>
|
||||||
</>
|
|
||||||
);
|
<MenuItem
|
||||||
}
|
item={{
|
||||||
|
text: "Mon compte",
|
||||||
|
link: Module.getInstance().get().modules.pages.MyAccount.props.path,
|
||||||
|
hasSeparator: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
item={{
|
||||||
|
text: "Guide de Prise en Main",
|
||||||
|
link: "https://ressources.lecoffre.io/",
|
||||||
|
target: "_blank",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
item={{
|
||||||
|
text: "Support",
|
||||||
|
link: "https://tally.so/r/mBGaNY",
|
||||||
|
target: "_blank",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
item={{
|
||||||
|
text: "CGU",
|
||||||
|
link: "/CGU_LeCoffre_io.pdf",
|
||||||
|
hasSeparator: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LogOutButton />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import React, { useEffect } from "react";
|
|
||||||
|
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
||||||
import useHoverable from "@Front/Hooks/useHoverable";
|
|
||||||
|
|
||||||
type IHeaderLinkProps = {
|
|
||||||
text: string | JSX.Element;
|
|
||||||
path: string;
|
|
||||||
routesActive?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function HeaderSubmenuLink(props: IHeaderLinkProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
const { pathname } = router;
|
|
||||||
const [isActive, setIsActive] = React.useState(props.path === pathname);
|
|
||||||
const { handleMouseLeave, handleMouseEnter, isHovered } = useHoverable();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.path === pathname) setIsActive(true);
|
|
||||||
if (props.routesActive) {
|
|
||||||
for (const routeActive of props.routesActive) {
|
|
||||||
if (isActive) break;
|
|
||||||
if (pathname.includes(routeActive)) setIsActive(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [isActive, pathname, props.path, props.routesActive]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link href={props.path} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
|
||||||
<Typography
|
|
||||||
typo={isActive || isHovered ? ETypo.TEXT_LG_SEMIBOLD : ETypo.TEXT_LG_REGULAR}
|
|
||||||
color={isActive || isHovered ? ETypoColor.COLOR_NEUTRAL_950 : ETypoColor.COLOR_NEUTRAL_500}>
|
|
||||||
{props.text}
|
|
||||||
</Typography>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
@import "@Themes/constants.scss";
|
|
||||||
|
|
||||||
.root {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
width: fit-content;
|
|
||||||
margin: auto;
|
|
||||||
height: 83px;
|
|
||||||
padding: 10px 16px;
|
|
||||||
.content {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
.underline {
|
|
||||||
width: 100%;
|
|
||||||
height: 3px;
|
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
&[data-active="true"] {
|
|
||||||
background-color: var(--color-generic-black);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.desactivated {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-menu {
|
|
||||||
box-shadow: 0px 8px 10px 0px #00000012;
|
|
||||||
padding: 24px;
|
|
||||||
text-align: center;
|
|
||||||
gap: 24px;
|
|
||||||
left: 0;
|
|
||||||
transform: translateX(-25%);
|
|
||||||
width: 300px;
|
|
||||||
top: 84px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: white;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
import classNames from "classnames";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import { IHeaderLinkProps } from "../ButtonHeader";
|
|
||||||
|
|
||||||
import Typography, { ETypo, ETypoColor } from "../../Typography";
|
|
||||||
import classes from "./classes.module.scss";
|
|
||||||
import useHoverable from "@Front/Hooks/useHoverable";
|
|
||||||
import HeaderSubmenuLink from "./HeaderSubmenuLink";
|
|
||||||
import { IAppRule } from "@Front/Api/Entities/rule";
|
|
||||||
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
text: string | JSX.Element;
|
|
||||||
links: (IHeaderLinkProps & {
|
|
||||||
rules?: IAppRule[];
|
|
||||||
})[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function HeaderSubmenu(props: IProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
const { pathname } = router;
|
|
||||||
const [isActive, setIsActive] = useState(false);
|
|
||||||
const { handleMouseLeave, handleMouseEnter, isHovered } = useHoverable(100);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsActive(false);
|
|
||||||
if (props.links.some((link) => link.path === pathname)) setIsActive(true);
|
|
||||||
if (props.links.some((link) => link.routesActive?.some((routeActive) => pathname.includes(routeActive)))) setIsActive(true);
|
|
||||||
}, [isActive, pathname, props.links]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Rules mode={RulesMode.OPTIONAL} rules={props.links.flatMap((link) => link.rules ?? [])}>
|
|
||||||
<div className={classes["container"]} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
|
||||||
<div className={classNames(classes["root"], (isActive || isHovered) && classes["active"])}>
|
|
||||||
<div className={classes["content"]}>
|
|
||||||
<Typography
|
|
||||||
typo={isActive || isHovered ? ETypo.TEXT_LG_SEMIBOLD : ETypo.TEXT_LG_REGULAR}
|
|
||||||
color={isActive || isHovered ? ETypoColor.COLOR_NEUTRAL_950 : ETypoColor.COLOR_NEUTRAL_500}>
|
|
||||||
{props.text}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div className={classes["underline"]} data-active={(isActive || isHovered).toString()} />
|
|
||||||
{isHovered && (
|
|
||||||
<div className={classes["sub-menu"]}>
|
|
||||||
{props.links.map((link) => (
|
|
||||||
<Rules mode={RulesMode.NECESSARY} rules={link.rules ?? []} key={link.path}>
|
|
||||||
<HeaderSubmenuLink {...link} />
|
|
||||||
</Rules>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Rules>
|
|
||||||
);
|
|
||||||
}
|
|
@ -8,7 +8,8 @@ import { AdjustmentsVerticalIcon, BanknotesIcon, Square3Stack3DIcon, TagIcon, Us
|
|||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import React, { useCallback, useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
import Menu, { IItem } from "../../Menu";
|
import Menu from "../../Menu";
|
||||||
|
import { IItem } from "../../Menu/MenuItem";
|
||||||
import ButtonHeader from "../ButtonHeader";
|
import ButtonHeader from "../ButtonHeader";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
@import "@Themes/constants.scss";
|
|
||||||
|
|
||||||
.root {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
width: fit-content;
|
|
||||||
margin: auto;
|
|
||||||
|
|
||||||
.content {
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import classes from "./classes.module.scss";
|
|
||||||
import Link from "next/link";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
text: string | JSX.Element;
|
|
||||||
path?: string;
|
|
||||||
onClick?: () => void;
|
|
||||||
isEnabled?: boolean;
|
|
||||||
isActive?: boolean;
|
|
||||||
routesActive?: string[];
|
|
||||||
target?: "blank" | "self" | "_blank";
|
|
||||||
};
|
|
||||||
|
|
||||||
type IPropsClass = IProps;
|
|
||||||
type IStateClass = {};
|
|
||||||
|
|
||||||
class NavigationLinkClass extends React.Component<IPropsClass, IStateClass> {
|
|
||||||
static defaultProps = { isEnabled: true };
|
|
||||||
public override render(): JSX.Element | null {
|
|
||||||
if (!this.props.isEnabled) return null;
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href={this.props.path ?? ""}
|
|
||||||
className={classNames(classes["root"], this.props.isActive && [classes["active"]])}
|
|
||||||
onClick={this.props.onClick}
|
|
||||||
target={this.props.target}>
|
|
||||||
<div className={classes["content"]}>
|
|
||||||
<Typography
|
|
||||||
typo={this.props.isActive ? ETypo.TEXT_LG_SEMIBOLD : ETypo.TEXT_LG_REGULAR}
|
|
||||||
color={this.props.isActive ? ETypoColor.COLOR_NEUTRAL_950 : ETypoColor.COLOR_NEUTRAL_500}>
|
|
||||||
{this.props.text}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function NavigationLink(props: IProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
const { pathname } = router;
|
|
||||||
let isActive = props.path === pathname;
|
|
||||||
if (props.routesActive) {
|
|
||||||
for (const routeActive of props.routesActive) {
|
|
||||||
if (isActive) break;
|
|
||||||
isActive = pathname.includes(routeActive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return <NavigationLinkClass {...props} isActive={isActive} />;
|
|
||||||
}
|
|
@ -1,14 +1,26 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
box-shadow: $shadow-nav;
|
|
||||||
padding: 24px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 107px;
|
top: 48px;
|
||||||
right: 66px;
|
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
padding: var(--spacing-05, 4px) var(--spacing-2, 16px);
|
||||||
|
|
||||||
|
border-radius: var(--menu-radius, 0);
|
||||||
|
border: 1px solid var(--menu-border, #d7dce0);
|
||||||
|
background: var(--color-generic-white, #fff);
|
||||||
|
|
||||||
|
text-wrap: nowrap;
|
||||||
|
|
||||||
|
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 3;
|
||||||
|
top: calc(var(--header-height) + 10px);
|
||||||
|
right: 32px;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
animation: smooth-appear 0.2s ease forwards;
|
animation: smooth-appear 0.2s ease forwards;
|
||||||
|
|
||||||
@ -20,15 +32,6 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid var(--color-neutral-200);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
|
@ -2,8 +2,8 @@ import LogOutButton from "@Front/Components/DesignSystem/LogOutButton";
|
|||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import NavigationLink from "../../NavigationLink";
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
import MenuItem from "@Front/Components/DesignSystem/Menu/MenuItem";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -19,10 +19,28 @@ export default class ProfileModal extends React.Component<IProps, IState> {
|
|||||||
<>
|
<>
|
||||||
<div className={classes["background"]} onClick={this.props.closeModal} />
|
<div className={classes["background"]} onClick={this.props.closeModal} />
|
||||||
<div className={classes["root"]}>
|
<div className={classes["root"]}>
|
||||||
<NavigationLink path={Module.getInstance().get().modules.pages.MyAccount.props.path} text="Mon compte" />
|
<MenuItem
|
||||||
<NavigationLink target="_blank" path="https://ressources.lecoffre.io/" text="Guide de Prise en Main" />
|
item={{
|
||||||
<NavigationLink target="_blank" path="/CGU_LeCoffre_io.pdf" text="CGU" />
|
text: "Mon compte",
|
||||||
<div className={classes["separator"]} />
|
link: Module.getInstance().get().modules.pages.MyAccount.props.path,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
item={{
|
||||||
|
text: "Guide de Prise en Main",
|
||||||
|
link: "https://ressources.lecoffre.io/",
|
||||||
|
target: "_blank",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
item={{
|
||||||
|
text: "CGU",
|
||||||
|
link: "/CGU_LeCoffre_io.pdf",
|
||||||
|
hasSeparator: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<LogOutButton />
|
<LogOutButton />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
import React from "react";
|
|
||||||
import Image from "next/image";
|
|
||||||
import DisconnectIcon from "@Assets/Icons/disconnect.svg";
|
|
||||||
import classes from "./classes.module.scss";
|
|
||||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import UserStore from "@Front/Stores/UserStore";
|
|
||||||
import { FrontendVariables } from "@Front/Config/VariablesFront";
|
import { FrontendVariables } from "@Front/Config/VariablesFront";
|
||||||
|
import UserStore from "@Front/Stores/UserStore";
|
||||||
|
import { PowerIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import React, { useCallback } from "react";
|
||||||
|
|
||||||
|
import MenuItem from "../Menu/MenuItem";
|
||||||
|
|
||||||
export default function LogOut() {
|
export default function LogOut() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const variables = FrontendVariables.getInstance();
|
const variables = FrontendVariables.getInstance();
|
||||||
|
|
||||||
const disconnect = async () => {
|
const disconnect = useCallback(() => {
|
||||||
await UserStore.instance.disconnect();
|
UserStore.instance
|
||||||
router.push(`https://qual-connexion.idnot.fr/user/auth/logout?sourceURL=${variables.FRONT_APP_HOST}`);
|
.disconnect()
|
||||||
};
|
.then(() => router.push(`https://qual-connexion.idnot.fr/user/auth/logout?sourceURL=${variables.FRONT_APP_HOST}`));
|
||||||
|
}, [router, variables.FRONT_APP_HOST]);
|
||||||
|
|
||||||
return (
|
return <MenuItem item={{ text: "Déconnexion", icon: <PowerIcon />, onClick: disconnect }} />;
|
||||||
<div className={classes["root"]} onClick={disconnect}>
|
|
||||||
<Typography typo={ETypo.TEXT_LG_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
||||||
Déconnexion
|
|
||||||
</Typography>
|
|
||||||
<Image src={DisconnectIcon} className={classes["disconnect-icon"]} alt="disconnect" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
.root {
|
.root {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--spacing-md, 16px);
|
padding: var(--spacing-md, 16px);
|
||||||
@ -7,12 +8,16 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-lg, 24px);
|
gap: var(--spacing-lg, 24px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
> svg {
|
svg {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
transition: all ease-in-out 0.1s;
|
transition: transform 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chevron.open {
|
||||||
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
@ -20,4 +25,14 @@
|
|||||||
height: 1px;
|
height: 1px;
|
||||||
background-color: var(--separator-stroke-light, #d7dce0);
|
background-color: var(--separator-stroke-light, #d7dce0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown.open {
|
||||||
|
max-height: 500px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,27 +3,71 @@ import classes from "./classes.module.scss";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useCallback, useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import useHoverable from "@Front/Hooks/useHoverable";
|
import useHoverable from "@Front/Hooks/useHoverable";
|
||||||
import { IItem } from "..";
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { IAppRule } from "@Front/Api/Entities/rule";
|
||||||
|
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||||
|
import useOpenable from "@Front/Hooks/useOpenable";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
item: IItem;
|
item: IItem;
|
||||||
closeMenuCb: () => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type IItemBase = {
|
||||||
|
text: string;
|
||||||
|
icon?: JSX.Element;
|
||||||
|
hasSeparator?: boolean;
|
||||||
|
color?: ETypoColor;
|
||||||
|
onClose?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IItemWithLink = IItemBase & {
|
||||||
|
link: string;
|
||||||
|
rules?: IAppRule[];
|
||||||
|
routesActive?: string[];
|
||||||
|
onClick?: never;
|
||||||
|
dropdown?: never;
|
||||||
|
target?: "_blank";
|
||||||
|
};
|
||||||
|
|
||||||
|
type IItemWithOnClick = IItemBase & {
|
||||||
|
onClick: () => void;
|
||||||
|
link?: never;
|
||||||
|
rules?: never;
|
||||||
|
routesActive?: never;
|
||||||
|
dropdown?: never;
|
||||||
|
target?: never;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IItemWithDropdown = IItemBase & {
|
||||||
|
dropdown: {
|
||||||
|
items: IItem[];
|
||||||
|
};
|
||||||
|
routesActive?: never;
|
||||||
|
link?: never;
|
||||||
|
rules?: never;
|
||||||
|
onClick?: never;
|
||||||
|
target?: never;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IItem = IItemWithLink | IItemWithOnClick | IItemWithDropdown;
|
||||||
|
|
||||||
export default function MenuItem(props: IProps) {
|
export default function MenuItem(props: IProps) {
|
||||||
const { item, closeMenuCb } = props;
|
const { item } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { pathname } = router;
|
const { pathname } = router;
|
||||||
const [isActive, setIsActive] = React.useState(item.link === pathname);
|
const [isActive, setIsActive] = React.useState(item.link === pathname);
|
||||||
|
|
||||||
|
const { isOpen, toggle, open } = useOpenable();
|
||||||
|
|
||||||
const handleClickElement = useCallback(
|
const handleClickElement = useCallback(
|
||||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
closeMenuCb();
|
item.onClose?.();
|
||||||
const link = e.currentTarget.getAttribute("data-link");
|
const link = e.currentTarget.getAttribute("data-link");
|
||||||
|
if (item.target === "_blank") window.open(item.link, "_blank");
|
||||||
if (link) router.push(link);
|
if (link) router.push(link);
|
||||||
if (item.onClick) item.onClick();
|
if (item.onClick) item.onClick();
|
||||||
},
|
},
|
||||||
[closeMenuCb, item, router],
|
[item, router],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { handleMouseEnter, handleMouseLeave, isHovered } = useHoverable();
|
const { handleMouseEnter, handleMouseLeave, isHovered } = useHoverable();
|
||||||
@ -44,7 +88,25 @@ export default function MenuItem(props: IProps) {
|
|||||||
if (pathname.includes(routeActive)) setIsActive(true);
|
if (pathname.includes(routeActive)) setIsActive(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isActive, item.link, item.routesActive, pathname]);
|
if (item.dropdown) {
|
||||||
|
for (const subItem of item.dropdown.items) {
|
||||||
|
if (isActive) break;
|
||||||
|
if (subItem.link === pathname) {
|
||||||
|
!isOpen && open();
|
||||||
|
setIsActive(true);
|
||||||
|
}
|
||||||
|
if (subItem.routesActive) {
|
||||||
|
for (const routeActive of subItem.routesActive) {
|
||||||
|
if (isActive) break;
|
||||||
|
if (pathname.includes(routeActive)) {
|
||||||
|
!isOpen && open();
|
||||||
|
setIsActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [isActive, isOpen, item.dropdown, item.link, item.routesActive, open, pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -53,12 +115,23 @@ export default function MenuItem(props: IProps) {
|
|||||||
data-link={item.link}
|
data-link={item.link}
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}>
|
onMouseLeave={handleMouseLeave}>
|
||||||
<div className={classes["menu-item"]}>
|
<div className={classes["menu-item"]} onClick={item.dropdown && toggle}>
|
||||||
{React.cloneElement(item.icon, { color: `var(${getColor()})` })}
|
{item.icon && React.cloneElement(item.icon, { color: `var(${getColor()})` })}
|
||||||
<Typography typo={ETypo.TEXT_LG_REGULAR} color={getColor()}>
|
<Typography typo={ETypo.TEXT_LG_REGULAR} color={getColor()}>
|
||||||
{item.text}
|
{item.text}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{item.dropdown &&
|
||||||
|
React.cloneElement(<ChevronDownIcon className={classNames(classes["chevron"], isOpen && [classes["open"]])} />, {
|
||||||
|
color: `var(${getColor()})`,
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
{item.dropdown && (
|
||||||
|
<div className={classNames(classes["dropdown"], isOpen && [classes["open"]])}>
|
||||||
|
{item.dropdown.items.map((subItem, index) => (
|
||||||
|
<MenuItem key={index} item={subItem} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{item.hasSeparator && <div className={classes["separator"]} />}
|
{item.hasSeparator && <div className={classes["separator"]} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,35 +1,10 @@
|
|||||||
import { IAppRule } from "@Front/Api/Entities/rule";
|
|
||||||
import { ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
||||||
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
||||||
import useHoverable from "@Front/Hooks/useHoverable";
|
import useHoverable from "@Front/Hooks/useHoverable";
|
||||||
import useOpenable from "@Front/Hooks/useOpenable";
|
import useOpenable from "@Front/Hooks/useOpenable";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import MenuItem from "./MenuItem";
|
import MenuItem, { IItem } from "./MenuItem";
|
||||||
|
|
||||||
type IItemBase = {
|
|
||||||
icon: JSX.Element;
|
|
||||||
text: string;
|
|
||||||
hasSeparator?: boolean;
|
|
||||||
color?: ETypoColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
type IItemWithLink = IItemBase & {
|
|
||||||
link: string;
|
|
||||||
rules?: IAppRule[];
|
|
||||||
routesActive?: string[];
|
|
||||||
onClick?: never;
|
|
||||||
};
|
|
||||||
|
|
||||||
type IItemWithOnClick = IItemBase & {
|
|
||||||
onClick: () => void;
|
|
||||||
link?: never;
|
|
||||||
rules?: never;
|
|
||||||
routesActive?: never;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type IItem = IItemWithLink | IItemWithOnClick;
|
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -79,7 +54,7 @@ export default function Menu(props: IProps) {
|
|||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<Rules mode={RulesMode.NECESSARY} rules={item.rules ?? []} key={item.link}>
|
<Rules mode={RulesMode.NECESSARY} rules={item.rules ?? []} key={item.link}>
|
||||||
<MenuItem item={item} key={index} closeMenuCb={close} />
|
<MenuItem item={item} key={index} />
|
||||||
</Rules>
|
</Rules>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import CircleProgress from "@Front/Components/DesignSystem/CircleProgress";
|
import CircleProgress from "@Front/Components/DesignSystem/CircleProgress";
|
||||||
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
|
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
|
||||||
import Menu, { IItem } from "@Front/Components/DesignSystem/Menu";
|
|
||||||
import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
|
import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
@ -10,6 +9,8 @@ import { useCallback } from "react";
|
|||||||
|
|
||||||
import { AnchorStatus } from "..";
|
import { AnchorStatus } from "..";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
import { IItem } from "@Front/Components/DesignSystem/Menu/MenuItem";
|
||||||
|
import Menu from "@Front/Components/DesignSystem/Menu";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
folder: OfficeFolder | null;
|
folder: OfficeFolder | null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user