Merge branch 'dev' into staging

This commit is contained in:
Maxime Lalo 2024-07-24 15:00:03 +02:00
commit 6cfe801c10
28 changed files with 402 additions and 277 deletions

View File

@ -49,7 +49,7 @@ export default function Alert(props: IProps) {
<Typography typo={ETypo.TEXT_LG_SEMIBOLD} color={ETypoColor.COLOR_NEUTRAL_950}> <Typography typo={ETypo.TEXT_LG_SEMIBOLD} color={ETypoColor.COLOR_NEUTRAL_950}>
{title} {title}
</Typography> </Typography>
<Typography typo={ETypo.TEXT_MD_light} color={ETypoColor.COLOR_NEUTRAL_700}> <Typography typo={ETypo.TEXT_MD_LIGHT} color={ETypoColor.COLOR_NEUTRAL_700}>
{description} {description}
</Typography> </Typography>
</div> </div>

View File

@ -1,48 +0,0 @@
import React, { useCallback } from "react";
import classes from "./classes.module.scss";
import Typography, { ETypo } from "../Typography";
import ChevronIcon from "@Assets/Icons/chevron.svg";
import Image from "next/image";
import WarningBadge from "../WarningBadge";
export type IBlock = {
name: string;
id: string;
selected: boolean;
rightIcon?: JSX.Element;
hasFlag?: boolean;
};
type IProps = {
blocks: IBlock[];
onSelectedBlock: (block: IBlock) => void;
};
export default function BlockList({ blocks, onSelectedBlock }: IProps) {
const selectBlock = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
onSelectedBlock && onSelectedBlock(blocks.find((folder) => folder.id === e.currentTarget.id)!);
},
[blocks, onSelectedBlock],
);
return (
<div>
{blocks.map((folder) => {
return (
<div onClick={selectBlock} key={folder.id} id={folder.id}>
<div className={classes["root"]} data-selected={folder.selected.toString()}>
<div className={classes["left-side"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR}>{folder.name}</Typography>
</div>
<div className={classes["right-side"]}>
{folder.hasFlag && <WarningBadge />}
{folder.rightIcon}
<Image alt="chevron" src={ChevronIcon} />
</div>
</div>
</div>
);
})}
</div>
);
}

View File

@ -5,12 +5,13 @@ 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 BlockList, { IBlock } from "../BlockList";
import Button from "../Button"; import Button from "../Button";
import SearchBar from "../SearchBar"; 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 Rules, { RulesMode } from "@Front/Components/Elements/Rules";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule"; import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
import { IBlock } from "../SearchBlockList/BlockList/Block";
import BlockList from "../SearchBlockList/BlockList";
type IProps = { type IProps = {
folders: OfficeFolder[]; folders: OfficeFolder[];
@ -106,9 +107,10 @@ class FolderArchivedListContainerClass extends React.Component<IPropsClass, ISta
return [...pendingFolders, ...otherFolders].map((folder) => { return [...pendingFolders, ...otherFolders].map((folder) => {
return { return {
id: folder.uid!, id: folder.uid!,
name: folder.folder_number! + " - " + folder.name!, primaryText: folder.name,
selected: this.props.selectedFolder === folder.uid, isActive: this.props.selectedFolder === folder.uid,
hasFlag: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED), secondaryText: folder.folder_number,
showAlert: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED),
}; };
}); });
} }

View File

@ -1,16 +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 { useRouter } from "next/router";
import { NextRouter, useRouter } from "next/router"; import React, { useCallback, useEffect } from "react";
import React from "react";
import BlockList, { IBlock } from "../BlockList";
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 { IBlock } from "../SearchBlockList/BlockList/Block";
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule"; import SearchBlockList from "../SearchBlockList";
type IProps = { type IProps = {
folders: OfficeFolder[]; folders: OfficeFolder[];
@ -19,68 +15,17 @@ type IProps = {
onCloseLeftSide?: () => void; onCloseLeftSide?: () => void;
}; };
type IPropsClass = IProps & { export default function FolderListContainer(props: IProps) {
router: NextRouter; const router = useRouter();
selectedFolder: string; const { folderUid } = router.query;
}; const { folders, isArchived } = props;
type IState = { const redirectPath: string = isArchived
filteredFolders: OfficeFolder[];
blocks: IBlock[];
};
class FolderListContainerClass extends React.Component<IPropsClass, IState> {
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.FolderArchived.pages.FolderInformation.props.path
: Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path; : Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path;
public constructor(props: IPropsClass) {
super(props);
this.state = {
filteredFolders: this.props.folders,
blocks: this.getBlocks(this.props.folders),
};
this.filterFolders = this.filterFolders.bind(this);
this.onSelectedFolder = this.onSelectedFolder.bind(this);
}
public override render(): JSX.Element { const getBlocks = useCallback(
const navigatePath = Module.getInstance().get().modules.pages.Folder.pages.CreateFolder.props.path; (folders: OfficeFolder[]): IBlock[] => {
return (
<div className={classes["root"]}>
<div className={classes["header"]}>
<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>
);
}
public override componentDidUpdate(prevProps: Readonly<IPropsClass>, prevState: Readonly<IState>, snapshot?: any): void {
if (prevProps.selectedFolder !== this.props.selectedFolder) {
this.setState({ filteredFolders: this.props.folders, blocks: this.getBlocks(this.props.folders) });
}
}
private getBlocks(folders: OfficeFolder[]): IBlock[] {
const pendingFolders = folders const pendingFolders = folders
.filter((folder) => { .filter((folder) => {
const pendingDocuments = (folder.documents ?? []).filter( const pendingDocuments = (folder.documents ?? []).filter(
@ -106,45 +51,40 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
return [...pendingFolders, ...otherFolders].map((folder) => { return [...pendingFolders, ...otherFolders].map((folder) => {
return { return {
id: folder.uid!, id: folder.uid!,
name: folder.folder_number! + " - " + folder.name!, primaryText: folder.name,
selected: this.props.selectedFolder === folder.uid, secondaryText: folder.folder_number,
hasFlag: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED), isActive: folderUid === folder.uid,
showAlert: folder.documents?.some((document) => document.document_status === EDocumentStatus.DEPOSITED),
}; };
}); });
} },
[folderUid],
);
private onSelectedFolder(block: IBlock) { const [blocks, setBlocks] = React.useState<IBlock[]>(getBlocks(folders));
const folder = this.props.folders.find((folder) => folder.uid === block.id);
const onSelectedFolder = (block: IBlock) => {
const folder = folders.find((folder) => folder.uid === block.id);
if (!folder) return; if (!folder) return;
this.props.onSelectedFolder && this.props.onSelectedFolder(folder); props.onSelectedFolder && props.onSelectedFolder(folder);
const path = this.redirectPath.replace("[folderUid]", folder.uid ?? ""); const path = redirectPath.replace("[folderUid]", folder.uid ?? "");
this.props.router.push(path); router.push(path);
} };
private filterFolders(value: string): void { useEffect(() => {
const filteredFolders: OfficeFolder[] = this.props.folders.filter((folder) => { setBlocks(getBlocks(folders));
const name = folder.name.toLowerCase(); }, [folders, getBlocks]);
const number = folder.folder_number.toLowerCase();
value = 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 (
} <div className={classes["root"]}>
<SearchBlockList
return name.includes(value) || number.includes(value); blocks={blocks}
}); onSelectedBlock={onSelectedFolder}
bottomButton={{
this.setState({ filteredFolders, blocks: this.getBlocks(filteredFolders) }); link: Module.getInstance().get().modules.pages.Folder.pages.CreateFolder.props.path,
} text: "Créer un dossier",
} }}
/>
export default function FolderListContainer(props: IProps) { </div>
const router = useRouter(); );
const { folderUid } = router.query;
return <FolderListContainerClass {...props} router={router} selectedFolder={folderUid as string} />;
} }

View File

@ -2,30 +2,67 @@
.root { .root {
display: flex; display: flex;
align-items: center; padding: var(--spacing-2, 16px) var(--spacing-sm, 8px);
padding-left: 24px; align-items: flex-start;
background-color: var(--color-generic-white); gap: var(--spacing-2, 16px);
border: 1px solid var(--color-neutral-200);
position: relative;
.fake-placeholder { border-radius: var(--input-radius, 0px);
position: absolute; border: 1px solid var(--input-main-border-default, #d7dce0);
left: 47px; background: var(--input-background, #fff);
top: 24px;
color: var(--color-neutral-500); &:hover {
pointer-events: none; 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);
}
.input-container {
display: flex;
flex: 1;
gap: 8px;
padding: 0px var(--spacing-2, 16px);
.input { .input {
border: 0; flex: 1;
margin-left: 8px; border: none;
padding: 24px 0;
width: 100%; color: var(--input-placeholder-filled, #24282e);
font-family: "Inter", sans-serif;
/* text/md/semibold */
font-family: var(--font-text-family, Poppins);
font-size: 16px;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: var(--font-text-weight-semibold, 600);
font-size: 18px; line-height: normal;
line-height: 22px; letter-spacing: 0.08px;
color: var(--color-neutral-500); 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;
}
}
.cross {
cursor: pointer;
}
} }
} }

View File

@ -1,54 +1,45 @@
import LoopIcon from "@Assets/Icons/loop.svg"; import React, { useCallback } from "react";
import Image from "next/image";
import React from "react";
import Typography, { ETypo, ETypoColor } from "../Typography";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
type IProps = { type IProps = {
onChange?: (input: string) => void; onChange?: (input: string) => void;
placeholder?: string; placeholder?: string;
}; };
type IState = { export default function SearchBar({ onChange, placeholder = "Rechercher" }: IProps) {
hasValue: boolean; const [isFocused, setIsFocused] = React.useState(false);
}; const [value, setValue] = React.useState("");
export default class SearchBar extends React.Component<IProps, IState> { const changeValue = useCallback(
static defaultProps = { (value: string) => {
placeholder: "Search", setValue(value);
}; onChange && onChange(value);
},
public constructor(props: IProps) { [onChange],
super(props);
this.state = {
hasValue: false,
};
this.doesInputHaveValue = this.doesInputHaveValue.bind(this);
this.onChange = this.onChange.bind(this);
}
public override render(): JSX.Element {
return (
<div className={classes["root"]}>
<Image src={LoopIcon} alt="Loop icon" />
{!this.state.hasValue && (
<Typography typo={ETypo.TEXT_LG_REGULAR} color={ETypoColor.COLOR_ERROR_600}>
<div className={classes["fake-placeholder"]}>{this.props.placeholder}</div>
</Typography>
)}
<input type="text" placeholder="" className={classes["input"]} onChange={this.onChange} />
</div>
); );
}
private onChange(event: React.ChangeEvent<HTMLInputElement>) { const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => changeValue(event.target.value);
const hasValue = event.target.value.length > 0; const handleFocus = () => setIsFocused(true);
this.doesInputHaveValue(hasValue); const handleBlur = () => setIsFocused(false);
if (!this.props.onChange) return; const clearValue = () => changeValue("");
this.props.onChange(event.target.value);
}
private doesInputHaveValue(hasValue: boolean) { return (
this.setState({ hasValue }); <label className={classes["root"]} data-is-focused={isFocused} data-has-value={value !== ""}>
} <div className={classes["input-container"]}>
<MagnifyingGlassIcon width="24" height="24" />
<input
type="text"
value={value}
placeholder={placeholder}
className={classes["input"]}
onChange={handleOnChange}
onFocus={handleFocus}
onBlur={handleBlur}
/>
{value !== "" && <XMarkIcon width="24" height="24" className={classes["cross"]} onClick={clearValue} />}
</div>
</label>
);
} }

View File

@ -0,0 +1,29 @@
.root {
background: var(--navigation-button-background-default, #f7f8f8);
cursor: pointer;
&:hover {
background: var(--navigation-button-background-actived, #edeff1);
}
&[data-is-active="true"] {
border-left: 3px solid var(--navigation-border, #005bcb);
background: var(--navigation-button-background-actived, #edeff1);
}
.content {
display: flex;
padding: var(--spacing-md, 16px) var(--spacing-lg, 24px);
align-items: center;
gap: var(--spacing-sm, 8px);
.text-container {
flex: 1;
}
}
.separator {
width: 100%;
height: 1px;
background: var(--separator-stroke-light, #d7dce0);
}
}

View File

@ -0,0 +1,44 @@
import { ChevronRightIcon } from "@heroicons/react/24/outline";
import classes from "./classes.module.scss";
import { useCallback } from "react";
import { ExclamationCircleIcon } from "@heroicons/react/20/solid";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
export type IBlock = {
id: string;
primaryText: string;
secondaryText?: string;
showAlert?: boolean;
isActive?: boolean;
};
type IProps = IBlock & {
hasSeparator?: boolean;
onClick?: (id: string) => void;
};
export default function Block(props: IProps) {
const { primaryText, secondaryText, showAlert = false, hasSeparator = true, isActive = false, onClick } = props;
const handleOnClick = useCallback(() => onClick && onClick(props.id), [onClick, props.id]);
return (
<div className={classes["root"]} data-is-active={isActive} onClick={handleOnClick}>
<div className={classes["content"]}>
<div className={classes["text-container"]}>
<Typography typo={ETypo.TEXT_MD_LIGHT} color={ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
{secondaryText}
</Typography>
<Typography typo={ETypo.TEXT_MD_BOLD} color={ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
{primaryText}
</Typography>
</div>
{showAlert && (
<ExclamationCircleIcon width="24" height="24" className={classes["icon"]} color={"var(--warning-default-base)"} />
)}
<ChevronRightIcon width="24" height="24" className={classes["icon"]} color={"var(--button-icon-button-default-default)"} />
</div>
{hasSeparator && <div className={classes["separator"]} />}
</div>
);
}

View File

@ -0,0 +1,23 @@
import React, { useCallback } from "react";
import Block, { IBlock } from "./Block";
type IProps = {
blocks: IBlock[];
onSelectedBlock: (block: IBlock) => void;
};
export default function BlockList({ blocks, onSelectedBlock }: IProps) {
const selectBlock = useCallback(
(id: string) => {
onSelectedBlock && onSelectedBlock(blocks.find((folder) => folder.id === id)!);
},
[blocks, onSelectedBlock],
);
return (
<div>
{blocks.map((block) => {
return <Block {...block} hasSeparator onClick={selectBlock} key={block.id} />;
})}
</div>
);
}

View File

@ -0,0 +1,30 @@
.root {
width: 336px;
height: 100%;
max-height: 100%;
border-radius: var(--navigation-radius, 0px);
background: var(--navigation-button-background-default, #f7f8f8);
display: flex;
flex-direction: column;
justify-content: flex-start;
.block-list {
overflow-y: auto;
::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.searchbar {
padding: var(--spacing-md, 16px);
}
.bottom-container {
position: fixed;
bottom: 0;
width: 336px;
}
}

View File

@ -0,0 +1,69 @@
import { useCallback, useEffect, useRef, useState } from "react";
import BlockList from "./BlockList";
import { IBlock } from "./BlockList/Block";
import classes from "./classes.module.scss";
import SearchBar from "../SearchBar";
import Button from "../Button";
import Link from "next/link";
type IProps = {
blocks: IBlock[];
onSelectedBlock: (block: IBlock) => void;
bottomButton?: {
text: string;
link: string;
};
};
export default function SearchBlockList(props: IProps) {
const { blocks, onSelectedBlock, bottomButton } = props;
const [blocksShowing, setBlocksShowing] = useState<IBlock[]>(blocks);
const bottomButtonRef = useRef<HTMLAnchorElement>(null);
const searchBarRef = useRef<HTMLDivElement>(null);
const handleSearchChange = useCallback(
(value: string) => {
const filteredBlocks = blocks.filter((block) => {
const name = block.primaryText.toLowerCase();
const number = block.secondaryText?.toLowerCase();
value = value.toLowerCase();
return name.includes(value) || number?.includes(value);
});
setBlocksShowing(filteredBlocks);
},
[blocks],
);
const getHeight = useCallback(() => {
let heightToSubstract = 0;
if (bottomButton && bottomButtonRef.current) {
heightToSubstract += bottomButtonRef.current.clientHeight;
}
if (searchBarRef.current) {
heightToSubstract += searchBarRef.current.clientHeight;
}
return {
maxHeight: `calc(100% - ${heightToSubstract}px)`,
};
}, [bottomButton]);
useEffect(() => {
setBlocksShowing(blocks);
}, [blocks]);
return (
<div className={classes["root"]}>
<div className={classes["searchbar"]} ref={searchBarRef}>
<SearchBar placeholder="Chercher" onChange={handleSearchChange} />
</div>
<div className={classes["block-list"]} style={getHeight()}>
<BlockList blocks={blocksShowing} onSelectedBlock={onSelectedBlock} />
</div>
{bottomButton && (
<Link href={bottomButton.link} className={classes["bottom-container"]} ref={bottomButtonRef}>
<Button fullwidth>{bottomButton.text}</Button>
</Link>
)}
</div>
);
}

View File

@ -28,25 +28,25 @@ export enum ETypo {
TEXT_LG_SEMIBOLD = "text-lg-semibold", TEXT_LG_SEMIBOLD = "text-lg-semibold",
TEXT_LG_REGULAR = "text-lg-regular", TEXT_LG_REGULAR = "text-lg-regular",
TEXT_LG_UPPERCASE = "text-lg-uppercase", TEXT_LG_UPPERCASE = "text-lg-uppercase",
TEXT_LG_light = "text-lg-light", TEXT_LG_LIGHT = "text-lg-light",
TEXT_MD_BOLD = "text-md-bold", TEXT_MD_BOLD = "text-md-bold",
TEXT_MD_SEMIBOLD = "text-md-semibold", TEXT_MD_SEMIBOLD = "text-md-semibold",
TEXT_MD_REGULAR = "text-md-regular", TEXT_MD_REGULAR = "text-md-regular",
TEXT_MD_UPPERCASE = "text-md-uppercase", TEXT_MD_UPPERCASE = "text-md-uppercase",
TEXT_MD_light = "text-md-light", TEXT_MD_LIGHT = "text-md-light",
TEXT_SM_BOLD = "text-sm-bold", TEXT_SM_BOLD = "text-sm-bold",
TEXT_SM_SEMIBOLD = "text-sm-semibold", TEXT_SM_SEMIBOLD = "text-sm-semibold",
TEXT_SM_REGULAR = "text-sm-regular", TEXT_SM_REGULAR = "text-sm-regular",
TEXT_SM_UPPERCASE = "text-sm-uppercase", TEXT_SM_UPPERCASE = "text-sm-uppercase",
TEXT_SM_light = "text-sm-light", TEXT_SM_LIGHT = "text-sm-light",
TEXT_XS_BOLD = "text-xs-bold", TEXT_XS_BOLD = "text-xs-bold",
TEXT_XS_SEMIBOLD = "text-xs-semibold", TEXT_XS_SEMIBOLD = "text-xs-semibold",
TEXT_XS_REGULAR = "text-xs-regular", TEXT_XS_REGULAR = "text-xs-regular",
TEXT_XS_UPPERCASE = "text-xs-uppercase", TEXT_XS_UPPERCASE = "text-xs-uppercase",
TEXT_XS_light = "text-xs-light", TEXT_XS_LIGHT = "text-xs-light",
CAPTION_BOLD = "caption-bold", CAPTION_BOLD = "caption-bold",
CAPTION_SEMIBOLD = "caption-semibold", CAPTION_SEMIBOLD = "caption-semibold",
@ -153,6 +153,7 @@ export enum ETypoColor {
CONTRAST_DEFAULT = "--contrast-default", CONTRAST_DEFAULT = "--contrast-default",
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",
} }
export default function Typography(props: IProps) { export default function Typography(props: IProps) {

View File

@ -3,9 +3,10 @@ import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import User from "le-coffre-resources/dist/Notary"; import User from "le-coffre-resources/dist/Notary";
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
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 BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
collaborators: User[]; collaborators: User[];
@ -50,7 +51,7 @@ export default function CollaboratorListContainer(props: IProps) {
<BlockList <BlockList
blocks={filteredUsers.map((user) => { blocks={filteredUsers.map((user) => {
return { return {
name: user.contact?.first_name + " " + user.contact?.last_name, primaryText: user.contact?.first_name + " " + user.contact?.last_name,
id: user.uid!, id: user.uid!,
selected: user.uid === collaboratorUid, selected: user.uid === collaboratorUid,
rightIcon: user.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) ? ( rightIcon: user.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) ? (

View File

@ -1,5 +1,4 @@
import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes"; import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes";
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import Button from "@Front/Components/DesignSystem/Button"; import Button from "@Front/Components/DesignSystem/Button";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
@ -9,6 +8,8 @@ import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
deedTypes: DeedType[]; deedTypes: DeedType[];
@ -50,7 +51,7 @@ export default function DeedListContainer(props: IProps) {
<BlockList <BlockList
blocks={filteredUsers.map((deed) => { blocks={filteredUsers.map((deed) => {
return { return {
name: deed.name, primaryText: deed.name,
id: deed.uid!, id: deed.uid!,
selected: deedTypeUid === deed.uid, selected: deedTypeUid === deed.uid,
}; };

View File

@ -1,4 +1,3 @@
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import Button from "@Front/Components/DesignSystem/Button"; import Button from "@Front/Components/DesignSystem/Button";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; import SearchBar from "@Front/Components/DesignSystem/SearchBar";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
@ -8,6 +7,8 @@ import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
documentTypes: DocumentType[]; documentTypes: DocumentType[];
@ -49,7 +50,7 @@ export default function DocumentTypeListContainer(props: IProps) {
<BlockList <BlockList
blocks={filteredDocumentTypes.map((documentType) => { blocks={filteredDocumentTypes.map((documentType) => {
return { return {
name: documentType.name, primaryText: documentType.name,
id: documentType.uid!, id: documentType.uid!,
selected: documentType.uid === documentTypeUid, selected: documentType.uid === documentTypeUid,
}; };

View File

@ -1,4 +1,3 @@
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; 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";
@ -6,6 +5,8 @@ import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
offices: Office[]; offices: Office[];
@ -49,7 +50,7 @@ export default function OfficeListContainer(props: IProps) {
<BlockList <BlockList
blocks={filteredOffices.map((office) => { blocks={filteredOffices.map((office) => {
return { return {
name: office.crpcen + " - " + office.name, primaryText: office.crpcen + " - " + office.name,
id: office.uid!, id: office.uid!,
selected: office.uid === officeUid, selected: office.uid === officeUid,
}; };

View File

@ -1,4 +1,3 @@
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; 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";
@ -8,6 +7,8 @@ import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Link from "next/link"; import Link from "next/link";
import Button from "@Front/Components/DesignSystem/Button"; import Button from "@Front/Components/DesignSystem/Button";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
roles: OfficeRole[]; roles: OfficeRole[];
@ -55,7 +56,7 @@ export default function RoleListContainer(props: IProps) {
}) })
.map((role) => { .map((role) => {
return { return {
name: role.name, primaryText: role.name,
id: role.uid!, id: role.uid!,
selected: role.uid === roleUid, selected: role.uid === roleUid,
}; };

View File

@ -1,4 +1,3 @@
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import SearchBar from "@Front/Components/DesignSystem/SearchBar"; 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";
@ -6,6 +5,8 @@ import { useRouter } from "next/router";
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
type IProps = { type IProps = {
users: User[]; users: User[];
@ -50,7 +51,7 @@ export default function UserListContainer(props: IProps) {
<BlockList <BlockList
blocks={filteredUsers.map((user) => { blocks={filteredUsers.map((user) => {
return { return {
name: user.contact?.first_name + " " + user.contact?.last_name, primaryText: user.contact?.first_name + " " + user.contact?.last_name,
id: user.uid!, id: user.uid!,
selected: user.uid === userUid, selected: user.uid === userUid,
}; };

View File

@ -24,7 +24,7 @@ export default function DeleteCustomerModal(props: IProps) {
title={"Êtes-vous sûr de vouloir supprimer ce client du dossier ?"} title={"Êtes-vous sûr de vouloir supprimer ce client du dossier ?"}
firstButton={{ children: "Annuler", onClick: onClose }} firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Supprimer le client", onClick: handleDelete }}> secondButton={{ children: "Supprimer le client", onClick: handleDelete }}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Cette action retirera le client de ce dossier. Vous ne pourrez plus récupérer les informations associées à ce client dans ce Cette action retirera le client de ce dossier. Vous ne pourrez plus récupérer les informations associées à ce client dans ce
dossier une fois supprimées. dossier une fois supprimées.
</Typography> </Typography>

View File

@ -131,7 +131,7 @@ export default function ClientBox(props: IProps) {
onClose={closeErrorModal} onClose={closeErrorModal}
title={"Suppression impossible"} title={"Suppression impossible"}
secondButton={{ children: "Fermer", onClick: closeErrorModal, fullwidth: true }}> secondButton={{ children: "Fermer", onClick: closeErrorModal, fullwidth: true }}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Ce client ne peut pas être supprimé car des documents sont associés à son dossier. Veuillez d'abord gérer ou supprimer Ce client ne peut pas être supprimé car des documents sont associés à son dossier. Veuillez d'abord gérer ou supprimer
ces documents avant de tenter de supprimer le client. ces documents avant de tenter de supprimer le client.
</Typography> </Typography>

View File

@ -31,7 +31,7 @@ export default function DeleteAskedDocumentModal(props: IProps) {
title={"Êtes-vous sûr de vouloir supprimer cette demande de document ?"} title={"Êtes-vous sûr de vouloir supprimer cette demande de document ?"}
firstButton={{ children: "Annuler", onClick: onClose }} firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Supprimer la demande", onClick: onDelete }}> secondButton={{ children: "Supprimer la demande", onClick: onDelete }}>
<Typography typo={ETypo.TEXT_MD_light}>Cette action annulera la demande du document en cours.</Typography> <Typography typo={ETypo.TEXT_MD_LIGHT}>Cette action annulera la demande du document en cours.</Typography>
</Modal> </Modal>
); );
} }

View File

@ -34,7 +34,7 @@ export default function DeleteFolderModal(props: IProps) {
title={"Êtes-vous sûr de vouloir supprimer ce dossier ?"} title={"Êtes-vous sûr de vouloir supprimer ce dossier ?"}
firstButton={{ children: "Annuler", onClick: onClose }} firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Supprimer le dossier", onClick: onDelete }}> secondButton={{ children: "Supprimer le dossier", onClick: onDelete }}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Cette action est irréversible. En supprimant ce dossier, toutes les informations associées seront définitivement perdues. Cette action est irréversible. En supprimant ce dossier, toutes les informations associées seront définitivement perdues.
</Typography> </Typography>
</Modal> </Modal>

View File

@ -44,13 +44,13 @@ export default function AnchoringModal(props: IProps) {
firstButton={!isAnchoring ? { children: "Non, Annuler", onClick: onClose } : undefined} firstButton={!isAnchoring ? { children: "Non, Annuler", onClick: onClose } : undefined}
secondButton={!isAnchoring ? { children: "Oui, certifier et ancrer", onClick: anchor } : undefined}> secondButton={!isAnchoring ? { children: "Oui, certifier et ancrer", onClick: anchor } : undefined}>
{!isAnchoring ? ( {!isAnchoring ? (
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
La certification et l'ancrage de ce dossier dans la blockchain sont des actions définitives et garantiront la sécurité La certification et l'ancrage de ce dossier dans la blockchain sont des actions définitives et garantiront la sécurité
et l'authenticité de tous les documents. Veuillez confirmer que vous souhaitez continuer. et l'authenticité de tous les documents. Veuillez confirmer que vous souhaitez continuer.
</Typography> </Typography>
) : ( ) : (
<div className={classes["anchoring"]}> <div className={classes["anchoring"]}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Vos documents sont en train d'être ancrés dans la blockchain. Cela peut prendre quelques instants. Merci de votre Vos documents sont en train d'être ancrés dans la blockchain. Cela peut prendre quelques instants. Merci de votre
patience. patience.
</Typography> </Typography>

View File

@ -37,7 +37,7 @@ export default function ArchiveModal(props: IProps) {
firstButton={{ children: "Annuler", onClick: onClose }} firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Archiver le dossier", onClick: archive }}> secondButton={{ children: "Archiver le dossier", onClick: archive }}>
<div className={classes["root"]}> <div className={classes["root"]}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Archiver ce dossier le déplacera dans la section des dossiers archivés. Vous pouvez ajouter une note de dossier avant Archiver ce dossier le déplacera dans la section des dossiers archivés. Vous pouvez ajouter une note de dossier avant
d'archiver si vous le souhaitez. d'archiver si vous le souhaitez.
</Typography> </Typography>

View File

@ -38,7 +38,7 @@ export default function DownloadAnchoringProofModal(props: IProps) {
title={"Félicitations ! Dossier ancré avec succès"} title={"Félicitations ! Dossier ancré avec succès"}
firstButton={{ children: "Fermer", onClick: onClose }} firstButton={{ children: "Fermer", onClick: onClose }}
secondButton={{ children: "Télécharger la preuve dancrage", onClick: downloadAnchoringProof }}> secondButton={{ children: "Télécharger la preuve dancrage", onClick: downloadAnchoringProof }}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Votre dossier a é validé et ancré dans la blockchain. Vous pouvez maintenant télécharger la preuve d'ancrage pour vos Votre dossier a é validé et ancré dans la blockchain. Vous pouvez maintenant télécharger la preuve d'ancrage pour vos
archives. archives.
</Typography> </Typography>

View File

@ -23,7 +23,7 @@ export default function RequireAnchoringModal(props: IProps) {
title={"Archiver le dossier, action requise : Ancrer et certifier le dossier"} title={"Archiver le dossier, action requise : Ancrer et certifier le dossier"}
firstButton={{ children: "Annuler", onClick: onClose }} firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Ancrer le dossier", onClick: onAnchor }}> secondButton={{ children: "Ancrer le dossier", onClick: onAnchor }}>
<Typography typo={ETypo.TEXT_MD_light}> <Typography typo={ETypo.TEXT_MD_LIGHT}>
Pour archiver ce dossier, il est nécessaire de l'ancrer dans la blockchain afin de garantir la sécurité et l'authenticité Pour archiver ce dossier, il est nécessaire de l'ancrer dans la blockchain afin de garantir la sécurité et l'authenticité
des documents. Veuillez procéder à l'ancrage avant de continuer. des documents. Veuillez procéder à l'ancrage avant de continuer.
</Typography> </Typography>

View File

@ -1,5 +1,4 @@
import Folders from "@Front/Api/LeCoffreApi/Customer/Folders/Folders"; import Folders from "@Front/Api/LeCoffreApi/Customer/Folders/Folders";
import BlockList, { IBlock } from "@Front/Components/DesignSystem/BlockList";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import JwtService from "@Front/Services/JwtService/JwtService"; import JwtService from "@Front/Services/JwtService/JwtService";
@ -9,6 +8,8 @@ import { useCallback, useEffect, useState } from "react";
import LandingImage from "../Login/landing-connect.jpeg"; import LandingImage from "../Login/landing-connect.jpeg";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { IBlock } from "@Front/Components/DesignSystem/SearchBlockList/BlockList/Block";
import BlockList from "@Front/Components/DesignSystem/SearchBlockList/BlockList";
export default function SelectFolder() { export default function SelectFolder() {
const [folders, setFolders] = useState<OfficeFolder[]>([]); const [folders, setFolders] = useState<OfficeFolder[]>([]);
@ -66,7 +67,7 @@ export default function SelectFolder() {
blocks={folders.map((folder) => { blocks={folders.map((folder) => {
return { return {
id: folder.uid!, id: folder.uid!,
name: folder.name!, primaryText: folder.name!,
selected: false, selected: false,
}; };
})} })}