New left nav everywhere + fix button

This commit is contained in:
Maxime Lalo 2024-07-24 17:37:22 +02:00
parent 288b2bb3e4
commit 02994a2959
11 changed files with 93 additions and 228 deletions

View File

@ -1,17 +1,12 @@
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document";
import Link from "next/link";
import { NextRouter, useRouter } from "next/router"; import { NextRouter, useRouter } from "next/router";
import React from "react"; import React from "react";
import Button from "../Button";
import SearchBar from "../SearchBar";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
import { IBlock } from "../SearchBlockList/BlockList/Block"; import { IBlock } from "../SearchBlockList/BlockList/Block";
import BlockList from "../SearchBlockList/BlockList"; import SearchBlockList from "../SearchBlockList";
type IProps = { type IProps = {
folders: OfficeFolder[]; folders: OfficeFolder[];
@ -45,33 +40,9 @@ class FolderArchivedListContainerClass extends React.Component<IPropsClass, ISta
} }
public override render(): JSX.Element { public override render(): JSX.Element {
const navigatePath = Module.getInstance().get().modules.pages.Folder.pages.CreateFolder.props.path;
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList blocks={this.state.blocks} onSelectedBlock={this.onSelectedFolder} />
<div className={classes["searchbar"]}>
<SearchBar onChange={this.filterFolders} placeholder="Chercher un dossier" />
</div>
<div className={classes["folderlist-container"]}>
<BlockList blocks={this.state.blocks} onSelectedBlock={this.onSelectedFolder} />
</div>
</div>
{!this.props.isArchived && (
<div>
<Rules
mode={RulesMode.NECESSARY}
rules={[
{
action: AppRuleActions.create,
name: AppRuleNames.officeFolders,
},
]}>
<Link href={navigatePath}>
<Button fullwidth={true}>Créer un dossier</Button>
</Link>
</Rules>
</div>
)}
</div> </div>
); );
} }

View File

@ -29,7 +29,9 @@ export default function Block(props: IProps) {
<Typography typo={ETypo.TEXT_MD_LIGHT} color={ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}> <Typography typo={ETypo.TEXT_MD_LIGHT} color={ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
{secondaryText} {secondaryText}
</Typography> </Typography>
<Typography typo={ETypo.TEXT_MD_BOLD} color={ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}> <Typography
typo={ETypo.TEXT_MD_BOLD}
color={isActive ? ETypoColor.NAVIGATION_BUTTON_CONTRAST_ACTIVE : ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
{primaryText} {primaryText}
</Typography> </Typography>
</div> </div>

View File

@ -24,6 +24,5 @@
.bottom-container { .bottom-container {
margin-top: auto; margin-top: auto;
width: 336px;
} }
} }

View File

@ -4,7 +4,7 @@ import { IBlock } from "./BlockList/Block";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import SearchBar from "../SearchBar"; import SearchBar from "../SearchBar";
import Button from "../Button"; import Button from "../Button";
import Link from "next/link"; import { useRouter } from "next/router";
type IProps = { type IProps = {
blocks: IBlock[]; blocks: IBlock[];
@ -17,6 +17,8 @@ type IProps = {
export default function SearchBlockList(props: IProps) { export default function SearchBlockList(props: IProps) {
const { blocks, onSelectedBlock, bottomButton } = props; const { blocks, onSelectedBlock, bottomButton } = props;
const router = useRouter();
const [blocksShowing, setBlocksShowing] = useState<IBlock[]>(blocks); const [blocksShowing, setBlocksShowing] = useState<IBlock[]>(blocks);
const bottomButtonRef = useRef<HTMLAnchorElement>(null); const bottomButtonRef = useRef<HTMLAnchorElement>(null);
const searchBarRef = useRef<HTMLDivElement>(null); const searchBarRef = useRef<HTMLDivElement>(null);
@ -47,6 +49,11 @@ export default function SearchBlockList(props: IProps) {
}; };
}, [bottomButton]); }, [bottomButton]);
const redirectOnBottomButtonClick = useCallback(() => {
if (!bottomButton) return;
router.push(bottomButton.link);
}, [bottomButton, router]);
useEffect(() => { useEffect(() => {
setBlocksShowing(blocks); setBlocksShowing(blocks);
}, [blocks]); }, [blocks]);
@ -60,9 +67,11 @@ export default function SearchBlockList(props: IProps) {
<BlockList blocks={blocksShowing} onSelectedBlock={onSelectedBlock} /> <BlockList blocks={blocksShowing} onSelectedBlock={onSelectedBlock} />
</div> </div>
{bottomButton && ( {bottomButton && (
<Link href={bottomButton.link} className={classes["bottom-container"]} ref={bottomButtonRef}> <div className={classes["bottom-container"]}>
<Button fullwidth>{bottomButton.text}</Button> <Button fullwidth onClick={redirectOnBottomButtonClick}>
</Link> {bottomButton.text}
</Button>
</div>
)} )}
</div> </div>
); );

View File

@ -154,6 +154,7 @@ export enum ETypoColor {
CONTRAST_HOVERED = "--contrast-hovered", CONTRAST_HOVERED = "--contrast-hovered",
ERROR_WEAK_CONTRAST = "--error-weak-contrast", ERROR_WEAK_CONTRAST = "--error-weak-contrast",
NAVIGATION_BUTTON_CONTRAST_DEFAULT = "--navigation-button-contrast-default", NAVIGATION_BUTTON_CONTRAST_DEFAULT = "--navigation-button-contrast-default",
NAVIGATION_BUTTON_CONTRAST_ACTIVE = "--navigation-button-contrast-active",
} }
export default function Typography(props: IProps) { export default function Typography(props: IProps) {

View File

@ -1,12 +1,11 @@
import React, { useCallback, useState } from "react"; import React, { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import User from "le-coffre-resources/dist/Notary"; import User from "le-coffre-resources/dist/Notary";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList"; import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
type IProps = { type IProps = {
collaborators: User[]; collaborators: User[];
@ -15,22 +14,9 @@ type IProps = {
}; };
export default function CollaboratorListContainer(props: IProps) { export default function CollaboratorListContainer(props: IProps) {
const [filteredUsers, setFilteredUsers] = useState<User[]>(props.collaborators);
const router = useRouter(); const router = useRouter();
const { collaboratorUid } = router.query; const { collaboratorUid } = router.query;
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( const onSelectedBlock = useCallback(
(block: IBlock) => { (block: IBlock) => {
@ -43,35 +29,16 @@ export default function CollaboratorListContainer(props: IProps) {
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList
<div className={classes["searchbar"]}> blocks={props.collaborators.map((user) => {
<SearchBar onChange={filterUsers} placeholder="Chercher un collaborateur" /> return {
</div> primaryText: user.contact?.first_name + " " + user.contact?.last_name,
<div className={classes["folderlist-container"]}> id: user.uid!,
<BlockList isActive: user.uid === collaboratorUid,
blocks={filteredUsers.map((user) => { };
return { })}
primaryText: user.contact?.first_name + " " + user.contact?.last_name, onSelectedBlock={onSelectedBlock}
id: user.uid!, />
selected: user.uid === collaboratorUid,
rightIcon: user.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) ? (
<div
style={{
height: "12px",
width: "12px",
borderRadius: "100px",
backgroundColor: "var(--color-success-600)",
}}
/>
) : (
<></>
),
};
})}
onSelectedBlock={onSelectedBlock}
/>
</div>
</div>
</div> </div>
); );
} }

View File

@ -34,7 +34,7 @@ export default function DeedListContainer(props: IProps) {
return { return {
primaryText: deed.name, primaryText: deed.name,
id: deed.uid!, id: deed.uid!,
selected: deedTypeUid === deed.uid, isActive: deedTypeUid === deed.uid,
}; };
})} })}
onSelectedBlock={onSelectedBlock} onSelectedBlock={onSelectedBlock}

View File

@ -1,14 +1,11 @@
import Button from "@Front/Components/DesignSystem/Button";
import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin"; import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList"; import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
type IProps = { type IProps = {
documentTypes: DocumentType[]; documentTypes: DocumentType[];
@ -17,19 +14,9 @@ type IProps = {
}; };
export default function DocumentTypeListContainer(props: IProps) { export default function DocumentTypeListContainer(props: IProps) {
const [filteredDocumentTypes, setFilteredDocumentTypes] = useState<DocumentType[]>(props.documentTypes);
const router = useRouter(); const router = useRouter();
const { documentTypeUid } = router.query; const { documentTypeUid } = router.query;
const filterDocumentTypes = useCallback(
(input: string) => {
const filteredDocumentTypes = props.documentTypes.filter((documentType) => {
return documentType.name.toLowerCase().includes(input.toLowerCase());
});
setFilteredDocumentTypes(filteredDocumentTypes);
},
[props.documentTypes],
);
const onSelectedBlock = useCallback( const onSelectedBlock = useCallback(
(block: IBlock) => { (block: IBlock) => {
@ -42,28 +29,20 @@ export default function DocumentTypeListContainer(props: IProps) {
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList
<div className={classes["searchbar"]}> blocks={props.documentTypes.map((documentType) => {
<SearchBar onChange={filterDocumentTypes} placeholder="Chercher un document" /> return {
</div> primaryText: documentType.name,
<div className={classes["folderlist-container"]}> id: documentType.uid!,
<BlockList isActive: documentType.uid === documentTypeUid,
blocks={filteredDocumentTypes.map((documentType) => { };
return { })}
primaryText: documentType.name, onSelectedBlock={onSelectedBlock}
id: documentType.uid!, bottomButton={{
selected: documentType.uid === documentTypeUid, link: Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path,
}; text: "Créer un type de document",
})} }}
onSelectedBlock={onSelectedBlock} />
/>
</div>
</div>
<div className={classes["create-container"]}>
<Link href={Module.getInstance().get().modules.pages.DocumentTypes.pages.Create.props.path}>
<Button fullwidth={true}>Créer un type de document</Button>
</Link>
</div>
</div> </div>
); );
} }

View File

@ -1,12 +1,11 @@
import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import { Office } from "le-coffre-resources/dist/SuperAdmin"; import { Office } from "le-coffre-resources/dist/SuperAdmin";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList"; import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
type IProps = { type IProps = {
offices: Office[]; offices: Office[];
@ -15,21 +14,9 @@ type IProps = {
}; };
export default function OfficeListContainer(props: IProps) { export default function OfficeListContainer(props: IProps) {
const [filteredOffices, setFilteredOffices] = useState<Office[]>(props.offices);
const router = useRouter(); const router = useRouter();
const { officeUid } = router.query; const { officeUid } = router.query;
const filterOffices = useCallback(
(input: string) => {
const filteredOffices = props.offices.filter((office) => {
return (
office.name.toLowerCase().includes(input.toLowerCase()) || office.crpcen?.toLowerCase().includes(input.toLowerCase())
);
});
setFilteredOffices(filteredOffices);
},
[props.offices],
);
const onSelectedBlock = useCallback( const onSelectedBlock = useCallback(
(block: IBlock) => { (block: IBlock) => {
@ -42,23 +29,16 @@ export default function OfficeListContainer(props: IProps) {
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList
<div className={classes["searchbar"]}> blocks={props.offices.map((office) => {
<SearchBar onChange={filterOffices} placeholder="Chercher un office" /> return {
</div> primaryText: office.crpcen + " - " + office.name,
<div className={classes["folderlist-container"]}> id: office.uid!,
<BlockList isActive: office.uid === officeUid,
blocks={filteredOffices.map((office) => { };
return { })}
primaryText: office.crpcen + " - " + office.name, onSelectedBlock={onSelectedBlock}
id: office.uid!, />
selected: office.uid === officeUid,
};
})}
onSelectedBlock={onSelectedBlock}
/>
</div>
</div>
</div> </div>
); );
} }

View File

@ -1,14 +1,11 @@
import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import { OfficeRole } from "le-coffre-resources/dist/Admin"; import { OfficeRole } from "le-coffre-resources/dist/Admin";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Link from "next/link";
import Button from "@Front/Components/DesignSystem/Button";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList"; import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
type IProps = { type IProps = {
roles: OfficeRole[]; roles: OfficeRole[];
@ -17,21 +14,10 @@ type IProps = {
}; };
export default function RoleListContainer(props: IProps) { export default function RoleListContainer(props: IProps) {
const [filteredRoles, setFilteredRoles] = useState<OfficeRole[]>(props.roles);
const router = useRouter(); const router = useRouter();
const { roleUid } = router.query; const { roleUid } = router.query;
const filterRoles = useCallback(
(input: string) => {
const filteredRoles = props.roles.filter((role) => {
return role.name?.toLowerCase().includes(input.toLowerCase());
});
setFilteredRoles(filteredRoles);
},
[props.roles],
);
const onSelectedBlock = useCallback( const onSelectedBlock = useCallback(
(block: IBlock) => { (block: IBlock) => {
props.onCloseLeftSide && props.onCloseLeftSide(); props.onCloseLeftSide && props.onCloseLeftSide();
@ -43,33 +29,25 @@ export default function RoleListContainer(props: IProps) {
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList
<div className={classes["searchbar"]}> blocks={props.roles
<SearchBar onChange={filterRoles} placeholder="Chercher un rôle" /> .filter((role) => {
</div> if (role.name === "admin") return false;
<div className={classes["folderlist-container"]}> return true;
<BlockList })
blocks={filteredRoles .map((role) => {
.filter((role) => { return {
if (role.name === "admin") return false; primaryText: role.name,
return true; id: role.uid!,
}) isActive: role.uid === roleUid,
.map((role) => { };
return { })}
primaryText: role.name, onSelectedBlock={onSelectedBlock}
id: role.uid!, bottomButton={{
selected: role.uid === roleUid, link: Module.getInstance().get().modules.pages.Roles.pages.Create.props.path,
}; text: "Créer un rôle",
})} }}
onSelectedBlock={onSelectedBlock} />
/>
</div>
</div>
<div className={classes["create-container"]}>
<Link href={Module.getInstance().get().modules.pages.Roles.pages.Create.props.path}>
<Button fullwidth={true}>Créer un rôle</Button>
</Link>
</div>
</div> </div>
); );
} }

View File

@ -1,12 +1,11 @@
import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import User from "le-coffre-resources/dist/Notary"; import User from "le-coffre-resources/dist/Notary";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block"; import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList"; import SearchBlockList from "@Front/Components/DesignSystem/SearchBlockList";
type IProps = { type IProps = {
users: User[]; users: User[];
@ -15,22 +14,9 @@ type IProps = {
}; };
export default function UserListContainer(props: IProps) { export default function UserListContainer(props: IProps) {
const [filteredUsers, setFilteredUsers] = useState<User[]>(props.users);
const router = useRouter(); const router = useRouter();
const { userUid } = router.query; const { userUid } = router.query;
const filterUsers = useCallback(
(input: string) => {
const filteredUsers = props.users.filter((user) => {
return (
user.contact?.first_name?.toLowerCase().includes(input.toLowerCase()) ||
user.contact?.last_name?.toLowerCase().includes(input.toLowerCase())
);
});
setFilteredUsers(filteredUsers);
},
[props.users],
);
const onSelectedBlock = useCallback( const onSelectedBlock = useCallback(
(block: IBlock) => { (block: IBlock) => {
@ -43,23 +29,16 @@ export default function UserListContainer(props: IProps) {
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <SearchBlockList
<div className={classes["searchbar"]}> blocks={props.users.map((user) => {
<SearchBar onChange={filterUsers} placeholder="Chercher un utilisateur" /> return {
</div> primaryText: user.contact?.first_name + " " + user.contact?.last_name,
<div className={classes["folderlist-container"]}> id: user.uid!,
<BlockList isActive: user.uid === userUid,
blocks={filteredUsers.map((user) => { };
return { })}
primaryText: user.contact?.first_name + " " + user.contact?.last_name, onSelectedBlock={onSelectedBlock}
id: user.uid!, />
selected: user.uid === userUid,
};
})}
onSelectedBlock={onSelectedBlock}
/>
</div>
</div>
</div> </div>
); );
} }