Merge branch 'dev' into staging

This commit is contained in:
Max S 2024-08-26 15:45:48 +02:00
commit 96422bc142
33 changed files with 795 additions and 144 deletions

View File

@ -11,6 +11,36 @@
border: 1px solid var(--alerts-info-border);
background: var(--alerts-info-background);
@media screen and (max-width: 680px) {
flex-direction: column;
}
.top {
align-self: stretch;
display: flex;
justify-content: space-between;
align-items: center;
}
.close-button {
display: block;
&.desktop {
display: block;
@media screen and (max-width: 680px) {
display: none;
}
}
&.mobile {
display: none;
@media screen and (max-width: 680px) {
display: block;
}
}
}
.content {
display: flex;
flex-direction: column;
@ -25,64 +55,34 @@
.button-container {
display: flex;
gap: var(--spacing-md, 16px);
}
}
.icon {
display: flex;
padding: var(--spacing-1, 8px);
align-items: center;
align-self: flex-start;
border-radius: var(--alerts-badge-radius, 360px);
border: 1px solid var(--alerts-badge-border, rgba(0, 0, 0, 0));
background: var(--alerts-badge-background, #fff);
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.1);
svg {
width: 24px;
height: 24px;
min-width: 24px;
min-height: 24px;
stroke: var(--alerts-badge-contrast-info);
@media screen and (max-width: 680px) {
flex-direction: column;
button {
width: 100%;
}
}
}
}
&.error {
border-color: var(--alerts-error-border);
background: var(--alerts-error-background);
.icon svg {
stroke: var(--alerts-badge-contrast-error);
}
}
&.warning {
border-color: var(--alerts-warning-border);
background: var(--alerts-warning-background);
.icon svg {
stroke: var(--alerts-badge-contrast-warning);
}
}
&.success {
border-color: var(--alerts-success-border);
background: var(--alerts-success-background);
.icon svg {
stroke: var(--alerts-badge-contrast-success);
}
}
&.neutral {
border-color: var(--alerts-neutral-border);
background: var(--alerts-neutral-background);
.icon svg {
stroke: var(--alerts-badge-contrast-neutral);
}
}
&.fullwidth {

View File

@ -52,7 +52,13 @@ export default function Alert(props: IProps) {
return (
<div className={classNames(classes["root"], classes[variant], fullWidth && classes["fullwidth"])}>
<BadgeIcon icon={icon ?? <InformationCircleIcon />} color={variantColorMap[variant]} />
<div className={classes["top"]}>
<BadgeIcon icon={icon ?? <InformationCircleIcon />} color={variantColorMap[variant]} />
{closeButton && (
<IconButton className={classNames(classes["close-button"], classes["mobile"])} onClick={close} icon={<XMarkIcon />} />
)}
</div>
<div className={classes["content"]}>
<div className={classes["text-container"]}>
<Typography typo={ETypo.TEXT_LG_SEMIBOLD} color={ETypoColor.COLOR_NEUTRAL_950}>
@ -84,7 +90,7 @@ export default function Alert(props: IProps) {
)}
</div>
</div>
{closeButton && <IconButton onClick={close} icon={<XMarkIcon />} />}
{closeButton && <IconButton className={classNames(classes["close-button"], classes["desktop"])} onClick={close} icon={<XMarkIcon />} />}
</div>
);
}

View File

@ -1,13 +1,15 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import Typography, { ETypo, ETypoColor } from "../Typography";
import classes from "./classes.module.scss";
import classNames from "classnames";
type IProps = {
percentage: number;
className?: string;
};
export default function CircleProgress(props: IProps) {
const { percentage } = props;
const { percentage, className } = props;
const [animatedProgress, setAnimatedProgress] = useState(0);
const requestRef = useRef<number>();
@ -41,7 +43,7 @@ export default function CircleProgress(props: IProps) {
const offset = circumference - (animatedProgress / 100) * circumference;
return (
<div className={classes["root"]}>
<div className={classNames(classes["root"], className)}>
<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27" viewBox="0 0 27 27" fill="none">
<circle className={classes["circleBackground"]} cx="13.5" cy="13.5" r={radius} strokeWidth="3" />
<circle
@ -59,4 +61,4 @@ export default function CircleProgress(props: IProps) {
</Typography>
</div>
);
}
}

View File

@ -20,14 +20,15 @@ type IProps = {
direction?: ESeperatorDirection;
size?: number;
thickness?: number;
className?: string;
};
export default function Separator(props: IProps) {
const { color = ESeperatorColor.DEFAULT, direction = ESeperatorDirection.HORIZONTAL, size, thickness = 1 } = props;
const { color = ESeperatorColor.DEFAULT, direction = ESeperatorDirection.HORIZONTAL, size, thickness = 1, className } = props;
return (
<div
className={classNames(classes["root"], classes[color], classes[direction])}
className={classNames(classes["root"], classes[color], classes[direction], className)}
style={direction === ESeperatorDirection.HORIZONTAL ? { width: size, height: thickness } : { height: size, width: thickness }}
/>
);

View File

@ -5,6 +5,7 @@ import React from "react";
type IProps = {
url?: string;
text?: string;
};
type IPropsClass = IProps & {
@ -26,7 +27,7 @@ class BackArrowClass extends React.Component<IPropsClass, IState> {
styletype={EButtonstyletype.TEXT}
size={EButtonSize.SM}
onClick={this.handleClick}>
Retour
{this.props.text ?? "Retour"}
</Button>
);
}

View File

@ -0,0 +1,5 @@
.root {
display: flex;
flex-direction: column;
gap: var(--spacing-sm, 8px);
}

View File

@ -0,0 +1,39 @@
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import classes from "./classes.module.scss";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import Link from "next/link";
export type IProps = {
title: string;
description: string;
button: { text: string; link?: string; onClick?: () => void };
};
export default function HelpBox(props: IProps) {
const { title, description, button } = props;
return (
<div className={classes["root"]}>
<Typography typo={ETypo.TEXT_MD_SEMIBOLD} color={ETypoColor.TEXT_SECONDARY}>
{title}
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
{description}
</Typography>
{button.link ? (
<Link href={button.link}>
<Button
variant={EButtonVariant.SECONDARY}
styletype={EButtonstyletype.TEXT}
size={EButtonSize.MD}
onClick={button.onClick}>
Contactez le support
</Button>
</Link>
) : (
<Button variant={EButtonVariant.SECONDARY} styletype={EButtonstyletype.TEXT} size={EButtonSize.MD} onClick={button.onClick}>
Contactez le support
</Button>
)}
</div>
);
}

View File

@ -32,6 +32,10 @@
.right-side {
min-width: 100%;
.right-side-content {
overflow-y: hidden;
}
}
}
}

View File

@ -0,0 +1,23 @@
@import "@Themes/constants.scss";
.root {
padding: var(--spacing-3) var(--spacing-15);
max-width: 1156px;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xl, 32px);
.table{
width: 100%;
}
@media screen and (max-width: $screen-m) {
padding: var(--spacing-3);
}
@media screen and (max-width: $screen-s) {
padding: var(--spacing-2);
}
}

View File

@ -0,0 +1,59 @@
import React from "react";
import classes from "./classes.module.scss";
import { useRouter } from "next/router";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
import Module from "@Front/Config/Module";
import BackArrow from "@Front/Components/Elements/BackArrow";
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import { IHead } from "@Front/Components/DesignSystem/Table/MuiTable";
import Table from "@Front/Components/DesignSystem/Table";
type IProps = {};
const header: readonly IHead[] = [
{
key: "name",
title: "Nom",
},
{
key: "sentAt",
title: "Envoyé le",
},
{
key: "actions",
title: "Action",
},
];
export default function ReceivedDocuments(props: IProps) {
const router = useRouter();
let { folderUid } = router.query;
return (
<DefaultTemplate title={"Documents reçus"} isPadding={false}>
<div className={classes["root"]}>
<BackArrow
text="Retour aux dossiers"
url={Module.getInstance()
.get()
.modules.pages.ClientDashboard.props.path.replace("[folderUid]", folderUid as string)}
/>
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}>
Un document vous a é envoyé
</Typography>
<Table className={classes["table"]} header={header} rows={[{ key: "1", name: "todo", sentAt: "todo", actions: "todo" }]} />
<Button
variant={EButtonVariant.PRIMARY}
size={EButtonSize.LG}
styletype={EButtonstyletype.CONTAINED}
leftIcon={<ArrowDownTrayIcon />}>
Tout télécharger
</Button>
</div>
</DefaultTemplate>
);
}

View File

@ -19,6 +19,8 @@ import ContactBox from "@Front/Components/Elements/ContactBox";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
import DepositDocumentComponent from "./DepositDocumentComponent";
import Link from "next/link";
import Module from "@Front/Config/Module";
type IProps = {};
@ -169,9 +171,17 @@ export default function ClientDashboard(props: IProps) {
Télécharger le RIB
</Button>
)}
<Button fullwidth variant={EButtonVariant.PRIMARY} size={EButtonSize.LG} styletype={EButtonstyletype.OUTLINED}>
Voir les documents reçus
</Button>
<Link
href={Module.getInstance()
.get()
.modules.pages.ClientDashboard.pages.ReceiveDocuments.props.path.replace(
"[folderUid]",
folderUid as string,
)}>
<Button fullwidth variant={EButtonVariant.PRIMARY} size={EButtonSize.LG} styletype={EButtonstyletype.OUTLINED}>
Voir les documents reçus
</Button>
</Link>
</div>
<div className={classes["documents"]}>
<Typography typo={ETypo.TEXT_LG_BOLD} color={ETypoColor.TABLE_COLUMN_CONTRAST}>

View File

@ -0,0 +1,23 @@
@import "@Themes/constants.scss";
.root {
padding: var(--spacing-3) var(--spacing-15);
max-width: 1156px;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xl, 32px);
.table{
width: 100%;
}
@media screen and (max-width: $screen-m) {
padding: var(--spacing-3);
}
@media screen and (max-width: $screen-s) {
padding: var(--spacing-2);
}
}

View File

@ -0,0 +1,53 @@
import Table from "@Front/Components/DesignSystem/Table";
import { IHead } from "@Front/Components/DesignSystem/Table/MuiTable";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import BackArrow from "@Front/Components/Elements/BackArrow";
import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
import Module from "@Front/Config/Module";
import { useRouter } from "next/router";
import React from "react";
import classes from "./classes.module.scss";
type IProps = {};
const header: readonly IHead[] = [
{
key: "remindedAt",
title: "Date de relance",
},
{
key: "customer",
title: "Client",
},
{
key: "document_type",
title: "Type de document",
},
{
key: "statut",
title: "Satut",
},
];
export default function DocumentsReminderHistory(props: IProps) {
const router = useRouter();
let { folderUid } = router.query;
return (
<DefaultTemplate title={"Historique des relances de documents"} isPadding={false}>
<div className={classes["root"]}>
<BackArrow
text="Retour"
url={Module.getInstance()
.get()
.modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string)}
/>
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}>
Historique des relances de documents
</Typography>
<Table className={classes["table"]} header={header} rows={[{ key: "1", name: "todo", sentAt: "todo", actions: "todo" }]} />
</div>
</DefaultTemplate>
);
}

View File

@ -6,16 +6,15 @@ import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Ty
import Module from "@Front/Config/Module";
import useOpenable from "@Front/Hooks/useOpenable";
import { PencilSquareIcon, TrashIcon, UsersIcon } from "@heroicons/react/24/outline";
import { Note } from "le-coffre-resources/dist/Customer";
import Customer, { Note } from "le-coffre-resources/dist/Customer";
import { useCallback } from "react";
import { ICustomer } from "..";
import { AnchorStatus } from "../..";
import classes from "./classes.module.scss";
import DeleteCustomerModal from "./DeleteCustomerModal";
type IProps = {
customer: ICustomer;
customer: Customer;
anchorStatus: AnchorStatus;
folderUid: string | undefined;
customerNote: Note | null;

View File

@ -16,6 +16,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import classes from "./classes.module.scss";
import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal";
import DeleteSentDocumentModal from "./DeleteSentDocumentModal";
import { useMediaQuery } from "@mui/material";
type IProps = {
documents: Document[];
@ -34,6 +35,8 @@ export default function DocumentTables(props: IProps) {
const [documents, setDocuments] = useState<Document[]>(documentsProps);
const [documentUid, setDocumentUid] = useState<string | null>(null);
const isMobile = useMediaQuery("(max-width:524px)");
const deleteAskedDocumentModal = useOpenable();
const deleteSentDocumentModal = useOpenable();
@ -232,11 +235,11 @@ export default function DocumentTables(props: IProps) {
</Typography>
<CircleProgress percentage={progress} />
</div>
{askedDocuments.length > 0 && <Table header={getHeader("Demandé le")} rows={askedDocuments} />}
{toValidateDocuments.length > 0 && <Table header={getHeader("Déposé le")} rows={toValidateDocuments} />}
{validatedDocuments.length > 0 && <Table header={getHeader("Validé le")} rows={validatedDocuments} />}
{refusedDocuments.length > 0 && <Table header={getHeader("Demandé le")} rows={refusedDocuments} />}
{sentDocuments.length > 0 && <Table header={getHeader("Envoyé le")} rows={sentDocuments} />}
{askedDocuments.length > 0 && <Table header={getHeader("Demandé le", isMobile)} rows={askedDocuments} />}
{toValidateDocuments.length > 0 && <Table header={getHeader("Déposé le", isMobile)} rows={toValidateDocuments} />}
{validatedDocuments.length > 0 && <Table header={getHeader("Validé le", isMobile)} rows={validatedDocuments} />}
{refusedDocuments.length > 0 && <Table header={getHeader("Demandé le", isMobile)} rows={refusedDocuments} />}
{sentDocuments.length > 0 && <Table header={getHeader("Envoyé le", isMobile)} rows={sentDocuments} />}
{documentUid && (
<>
<DeleteAskedDocumentModal
@ -257,7 +260,23 @@ export default function DocumentTables(props: IProps) {
);
}
function getHeader(dateColumnTitle: string): IHead[] {
function getHeader(dateColumnTitle: string, isMobile: boolean): IHead[] {
if (isMobile) {
return [
{
key: "document_type",
title: "Type de document",
},
{
key: "document_status",
title: "Statut",
},
{
key: "actions",
title: "Action",
},
];
}
return [
{
key: "document_type",

View File

@ -0,0 +1,5 @@
@import "@Themes/constants.scss";
.root {
}

View File

@ -0,0 +1,37 @@
import Modal from "@Front/Components/DesignSystem/Modal";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import Customer from "le-coffre-resources/dist/Customer";
import React, { useCallback } from "react";
import classes from "./classes.module.scss";
type IProps = {
isOpen: boolean;
onClose?: () => void;
onRemindSuccess: () => void;
customer: Customer;
};
export default function ReminderModal(props: IProps) {
const { isOpen, onClose, onRemindSuccess, customer } = props;
const onRemind = useCallback(() => {
onRemindSuccess();
onClose?.();
}, [onClose, onRemindSuccess]);
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title={`Relancer votre client ${customer.contact?.last_name}`}
firstButton={{ children: "Annuler", onClick: onClose }}
secondButton={{ children: "Relancer", onClick: onRemind }}>
<div className={classes["root"]}>
<Typography typo={ETypo.TEXT_MD_LIGHT}>
Sélectionnez le(s) document(s) pour lequel vous souhaitez relancer le client.
</Typography>
</div>
</Modal>
);
}

View File

@ -0,0 +1,19 @@
@import "@Themes/constants.scss";
.root {
display: flex;
flex-direction: column;
gap: var(--spacing-md, 32px);
.reminder-info {
display: flex;
gap: 8px;
align-items: center;
.info {
display: flex;
flex-direction: column;
gap: 4px;
}
}
}

View File

@ -0,0 +1,55 @@
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import useOpenable from "@Front/Hooks/useOpenable";
import { ClockIcon, EnvelopeIcon } from "@heroicons/react/24/outline";
import Customer from "le-coffre-resources/dist/Customer";
import classes from "./classes.module.scss";
import ReminderModal from "./ReminderModal";
import { useRouter } from "next/router";
import Module from "@Front/Config/Module";
import Link from "next/link";
type IProps = {
customer: Customer;
};
export default function EmailReminder(props: IProps) {
const { customer } = props;
const { isOpen, open, close } = useOpenable();
const router = useRouter();
let { folderUid } = router.query;
return (
<div className={classes["root"]}>
<Button
onClick={open}
rightIcon={<EnvelopeIcon />}
variant={EButtonVariant.PRIMARY}
styletype={EButtonstyletype.OUTLINED}
fullwidth>
Relancer par mail
</Button>
<div className={classes["reminder-info"]}>
<Link
title={"Voir l'historique des relances"}
href={Module.getInstance()
.get()
.modules.pages.Folder.pages.DocumentsReminderHistory.props.path.replace("[folderUid]", folderUid as string)}>
<IconButton icon={<ClockIcon />} variant={EIconButtonVariant.NEUTRAL} />
</Link>
<div className={classes["info"]}>
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Dernière relance: todo
</Typography>
<Typography typo={ETypo.TEXT_XS_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Nombre de relance: todo
</Typography>
</div>
</div>
<ReminderModal isOpen={isOpen} onRemindSuccess={() => {}} onClose={close} customer={customer} />
</div>
);
}

View File

@ -1,5 +1,7 @@
@import "@Themes/constants.scss";
$mobile-breakpoint: 664px;
.root {
display: flex;
flex-direction: column;
@ -20,11 +22,30 @@
display: flex;
gap: var(--spacing-lg, 24px);
.client-box {
@media screen and (max-width: $screen-s) {
flex-direction: column;
}
.client-box-container {
display: flex;
flex-direction: column;
gap: var(--spacing-lg, 24px);
.button-container {
display: flex;
flex-direction: column;
gap: var(--spacing-lg, 24px);
}
@media screen and (max-width: $screen-s) {
flex-direction: row;
}
@media screen and (max-width: $mobile-breakpoint) {
flex-direction: column;
margin: auto;
}
}
}
}

View File

@ -1,20 +1,20 @@
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import Tabs from "@Front/Components/Elements/Tabs";
import Module from "@Front/Config/Module";
import { DocumentIcon, UserPlusIcon } from "@heroicons/react/24/outline";
import Customer from "le-coffre-resources/dist/Customer";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import Link from "next/link";
import { useCallback, useMemo, useState } from "react";
import { AnchorStatus } from "..";
import classes from "./classes.module.scss";
import ClientBox from "./ClientBox";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import { DocumentIcon, UserPlusIcon } from "@heroicons/react/24/outline";
import Module from "@Front/Config/Module";
import Link from "next/link";
import NoDocument from "./NoDocument";
import DocumentTables from "./DocumentTables";
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import EmailReminder from "./EmailReminder";
import NoDocument from "./NoDocument";
type IProps = {
folder: OfficeFolder;
@ -95,7 +95,7 @@ export default function ClientView(props: IProps) {
)}
</div>
<div className={classes["content"]}>
<div className={classes["client-box"]}>
<div className={classes["client-box-container"]}>
<ClientBox
customer={customer}
anchorStatus={anchorStatus}
@ -103,18 +103,22 @@ export default function ClientView(props: IProps) {
onDelete={handleClientDelete}
customerNote={folder.notes!.find((value) => value.customer?.uid === customer.uid) ?? null}
/>
{anchorStatus === AnchorStatus.NOT_ANCHORED && (
<Link
href={Module.getInstance()
.get()
.modules.pages.Folder.pages.AskDocument.props.path.replace("[folderUid]", folder.uid ?? "")
.replace("[customerUid]", customer.uid ?? "")}>
<Button rightIcon={<DocumentIcon />} variant={EButtonVariant.PRIMARY} fullwidth>
Demander un document
</Button>
</Link>
)}
<div className={classes["button-container"]}>
{anchorStatus === AnchorStatus.NOT_ANCHORED && (
<Link
href={Module.getInstance()
.get()
.modules.pages.Folder.pages.AskDocument.props.path.replace("[folderUid]", folder.uid ?? "")
.replace("[customerUid]", customer.uid ?? "")}>
<Button rightIcon={<DocumentIcon />} variant={EButtonVariant.PRIMARY} fullwidth>
Demander un document
</Button>
</Link>
)}
<EmailReminder customer={customer} />
</div>
</div>
{doesCustomerHaveDocument ? (
<DocumentTables documents={customer.documents ?? []} folderUid={folder?.uid ?? ""} />
) : (

View File

@ -1,18 +1,41 @@
@import "@Themes/constants.scss";
$mobile-breakpoint: 600px;
.root {
display: flex;
gap: var(--spacing-lg, 40px);
gap: var(--spacing-lg, 24px);
@media screen and (max-width: $mobile-breakpoint) {
flex-direction: column;
}
.info-box1 {
display: flex;
width: 100%;
flex-direction: column;
gap: var(--spacing-sm, 8px);
.folder-number-container {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--spacing-lg, 24px);
}
.open-date {
display: flex;
gap: var(--spacing-sm, 8px);
}
@media screen and (max-width: $screen-s) {
width: 54vw;
}
@media screen and (max-width: $mobile-breakpoint) {
width: 100%;
}
}
.info-box2 {
@ -22,22 +45,74 @@
width: 100%;
max-width: 400px;
@media screen and (max-width: $mobile-breakpoint) {
max-width: 100%;
}
.progress-container {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.icon-container {
display: flex;
gap: var(--spacing-md, 8px);
@media screen and (max-width: $screen-s) {
flex-direction: column-reverse;
gap: var(--spacing-lg, 24px);
}
@media screen and (max-width: $mobile-breakpoint) {
align-items: flex-start;
}
}
}
.icon-container {
display: flex;
gap: var(--spacing-md, 8px);
&.desktop {
display: flex;
@media screen and (max-width: $mobile-breakpoint) {
display: none;
}
}
.description-container {
.text {
max-height: 60px;
overflow-y: auto;
&.mobile {
display: none;
@media screen and (max-width: $mobile-breakpoint) {
display: flex;
}
}
}
.description-container {
.text {
max-height: 60px;
overflow-y: auto;
white-space: normal;
word-wrap: break-word;
}
&.desktop {
@media screen and (max-width: $screen-s) {
display: none;
}
}
&.ipad {
display: none;
@media screen and (max-width: $screen-s) {
display: block;
}
@media screen and (max-width: $mobile-breakpoint) {
display: none;
}
}
&.mobile {
display: none;
@media screen and (max-width: $mobile-breakpoint) {
display: block;
}
}
}
@ -46,5 +121,10 @@
background-color: var(--separator-stroke-light);
width: 1px;
align-self: stretch;
@media screen and (max-width: $mobile-breakpoint) {
height: 1px;
width: 100%;
}
}
}

View File

@ -6,12 +6,13 @@ import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import Module from "@Front/Config/Module";
import { ArchiveBoxIcon, EllipsisHorizontalIcon, PaperAirplaneIcon, PencilSquareIcon, UsersIcon } from "@heroicons/react/24/outline";
import classNames from "classnames";
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import Link from "next/link";
import { useMemo } from "react";
import { AnchorStatus } from "..";
import classes from "./classes.module.scss";
import Link from "next/link";
type IProps = {
folder: OfficeFolder | null;
@ -24,7 +25,7 @@ type IProps = {
export default function InformationSection(props: IProps) {
const { folder, progress, onArchive, anchorStatus, isArchived } = props;
const menuItems = useMemo(() => {
const menuItemsDekstop = useMemo(() => {
let elements: IItem[] = [];
// Creating the three elements and adding them conditionnally
@ -48,17 +49,71 @@ export default function InformationSection(props: IProps) {
// If the folder is not anchored, we can modify the collaborators and the informations
if (anchorStatus === AnchorStatus.NOT_ANCHORED) {
elements.push(modifyCollaboratorsElement);
elements.push(modifyInformationsElement);
}
return elements;
}, [anchorStatus, folder?.uid]);
const menuItemsMobile = useMemo(() => {
let elements: IItem[] = [];
// Creating the three elements and adding them conditionnally
const modifyCollaboratorsElement = {
icon: <UsersIcon />,
text: "Modifier les collaborateurs",
link: Module.getInstance()
.get()
.modules.pages.Folder.pages.EditCollaborators.props.path.replace("[folderUid]", folder?.uid ?? ""),
hasSeparator: true,
};
const modifyInformationsElement = {
icon: <PencilSquareIcon />,
text: "Modifier les informations du dossier",
link: Module.getInstance()
.get()
.modules.pages.Folder.pages.EditInformations.props.path.replace("[folderUid]", folder?.uid ?? ""),
hasSeparator: true,
};
// If the folder is not anchored, we can modify the collaborators and the informations
if (anchorStatus === AnchorStatus.NOT_ANCHORED) {
elements.push(modifyCollaboratorsElement);
elements.push(modifyInformationsElement);
}
elements.push({
icon: <PaperAirplaneIcon />,
text: "Envoyer des documents",
link: Module.getInstance()
.get()
.modules.pages.Folder.pages.SendDocuments.props.path.replace("[folderUid]", folder?.uid ?? ""),
hasSeparator: !isArchived,
});
if (!isArchived) {
elements.push({
icon: <ArchiveBoxIcon />,
text: "Archiver le dossier",
onClick: onArchive,
hasSeparator: false,
});
}
return elements;
}, [anchorStatus, folder?.uid, isArchived, onArchive]);
return (
<section className={classes["root"]}>
<div className={classes["info-box1"]}>
<div>
<Typography typo={ETypo.TEXT_MD_REGULAR}>{folder?.folder_number}</Typography>
<div className={classes["folder-number-container"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR}>{folder?.folder_number}</Typography>
<div className={classNames(classes["icon-container"], classes["mobile"])}>
<Menu items={menuItemsMobile}>
<IconButton icon={<EllipsisHorizontalIcon />} variant={EIconButtonVariant.NEUTRAL} />
</Menu>
</div>
</div>
<Typography typo={ETypo.TITLE_H4}>{folder?.name}</Typography>
</div>
@ -69,13 +124,22 @@ export default function InformationSection(props: IProps) {
{folder?.created_at ? new Date(folder.created_at).toLocaleDateString() : ""}
</Typography>
</div>
<div className={classNames(classes["description-container"], classes["ipad"])}>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_700}>
Note du dossier
</Typography>
<Typography typo={ETypo.TEXT_LG_REGULAR} className={classes["text"]}>
{folder?.description}
</Typography>
</div>
</div>
<div className={classes["separator"]} />
<div className={classes["info-box2"]}>
<div className={classes["progress-container"]}>
<CircleProgress percentage={progress} />
<div className={classes["icon-container"]}>
<div className={classNames(classes["icon-container"], classes["desktop"])}>
<Link
href={Module.getInstance()
.get()
@ -83,13 +147,14 @@ export default function InformationSection(props: IProps) {
title="Envoyer des documents">
<IconButton icon={<PaperAirplaneIcon />} variant={EIconButtonVariant.NEUTRAL} />
</Link>
<Menu items={menuItems}>
<Menu items={menuItemsDekstop}>
<IconButton icon={<EllipsisHorizontalIcon />} variant={EIconButtonVariant.NEUTRAL} />
</Menu>
{!isArchived && <IconButton onClick={onArchive} icon={<ArchiveBoxIcon />} variant={EIconButtonVariant.ERROR} />}
</div>
</div>
<div className={classes["description-container"]}>
<div className={classNames(classes["description-container"], classes["desktop"], classes["mobile"])}>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_700}>
Note du dossier
</Typography>

View File

@ -3,7 +3,7 @@
.root {
.content {
display: flex;
width: 648px;
max-width: 648px;
flex-direction: column;
justify-content: center;
gap: var(--spacing-2xl, 40px);
@ -14,8 +14,8 @@
gap: var(--spacing-md, 16px);
align-self: stretch;
.logo{
fill: "red"
.logo {
fill: "red";
}
}
@ -39,17 +39,23 @@
display: flex;
gap: var(--spacing-lg, 24px);
.box {
display: flex;
@media screen and (max-width: 600px) {
flex-direction: column;
gap: var(--spacing-sm, 8px);
}
.separator {
background-color: var(--separator-stroke-light);
width: 1px;
align-self: stretch;
}
}
}
.mobile {
display: none;
@media screen and (max-width: 600px) {
display: flex;
}
}
.desktop {
display: flex;
@media screen and (max-width: 600px) {
display: none;
}
}
}

View File

@ -1,9 +1,12 @@
import LogoIcon from "@Assets/logo_small_blue.svg";
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
import Separator, { ESeperatorColor, ESeperatorDirection } from "@Front/Components/DesignSystem/Separator";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import HelpBox from "@Front/Components/Elements/HelpBox";
import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
import Module from "@Front/Config/Module";
import useUser from "@Front/Hooks/useUser";
import { DocumentIcon } from "@heroicons/react/24/outline";
import EFolderStatus from "le-coffre-resources/dist/Customer/EFolderStatus";
import Image from "next/image";
@ -12,7 +15,6 @@ import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import classes from "./classes.module.scss";
import useUser from "@Front/Hooks/useUser";
export default function Folder() {
const [_isArchivedModalOpen, _setIsArchivedModalOpen] = useState(true);
@ -37,7 +39,6 @@ export default function Folder() {
);
});
}, [router]);
return (
<DefaultNotaryDashboard title={"Dossier"} mobileBackText={"Liste des dossiers"}>
<div className={classes["root"]}>
@ -80,22 +81,25 @@ export default function Folder() {
</div>
<div className={classes["help-container"]}>
<div className={classes["box"]}>
<Typography typo={ETypo.TEXT_MD_SEMIBOLD}>Besoin d'aide ?</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR}>Consultez nos guides pour bien démarrer.</Typography>
<Button variant={EButtonVariant.SECONDARY} styletype={EButtonstyletype.TEXT} size={EButtonSize.MD}>
Accéder aux guides
</Button>
</div>
<div className={classes["separator"]} />
<HelpBox
title="Besoin d'aide ?"
description="Consultez nos guides pour bien démarrer."
button={{ text: "Accéder aux guides" }}
/>
<div className={classes["box"]}>
<Typography typo={ETypo.TEXT_MD_SEMIBOLD}>Vous avez des questions ?</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR}>Notre équipe de support est pour vous aider.</Typography>
<Button variant={EButtonVariant.SECONDARY} styletype={EButtonstyletype.TEXT} size={EButtonSize.MD}>
Contactez le support
</Button>
</div>
<Separator
className={classes["desktop"]}
direction={ESeperatorDirection.VERTICAL}
size={128}
color={ESeperatorColor.LIGHT}
/>
<Separator className={classes["mobile"]} direction={ESeperatorDirection.HORIZONTAL} color={ESeperatorColor.LIGHT} />
<HelpBox
title="Vous avez des questions ?"
description="Notre équipe de support est là pour vous aider."
button={{ text: "Contactez le support" }}
/>
</div>
</div>
</div>

View File

@ -1,21 +1,34 @@
@import "@Themes/constants.scss";
@import "@Themes/animation.scss";
@import "@Themes/constants.scss";
.root {
height: 100%;
width: 100%;
margin: 80px auto;
width: 474px;
display: flex;
flex-direction: column;
gap: var(--spacing-xl, 32px);
.content {
@media (max-width: $screen-s) {
width: 100%;
margin: auto;
.text {
margin: 32px 0;
}
@media(max-width: $screen-s) {
text-align: center;
}
padding: var(--spacing-md, 16px);
}
}
.content {
display: flex;
padding: var(--spacing-xl, 32px) var(--spacing-lg, 24px);
flex-direction: column;
gap: var(--spacing-lg, 24px);
border-radius: var(--radius-rounded, 16px);
background: var(--background-primary, #fff);
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.1);
.text {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
}
}

View File

@ -1,27 +1,51 @@
import backgroundImage from "@Assets/images/background_refonte.svg";
import LogoIcon from "@Assets/logo_small_blue.svg";
import Button from "@Front/Components/DesignSystem/Button";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import HelpBox from "@Front/Components/Elements/HelpBox";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import Module from "@Front/Config/Module";
import Image from "next/image";
import Link from "next/link";
import BasePage from "../Base";
import classes from "./classes.module.scss";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import backgroundImage from "@Assets/images/404-background-image.jpeg";
export default class PageNotFound extends BasePage {
public override render(): JSX.Element {
return (
<DefaultDoubleSidePage title={"Project Not Found"} image={backgroundImage} type="background" showHeader>
<div className={classes["root"]}>
<div className={classes["content"]}>
<Typography typo={ETypo.DISPLAY_LARGE}>Erreur 404</Typography>
<Typography typo={ETypo.TEXT_LG_REGULAR} className={classes["text"]}>
La page que vous recherchez semble introuvable.
<div className={classes["title-container"]}>
<Image src={LogoIcon} alt="logo" width={56} />
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_ACCENT}>
Oups ! Page introuvable
</Typography>
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.TEXT_PRIMARY}>
Il semble que la page que vous recherchez n'existe pas ou a é déplacée.
</Typography>
</div>
<div className={classes["content"]}>
<div className={classes["text"]}>
<Typography typo={ETypo.TEXT_LG_SEMIBOLD} color={ETypoColor.TEXT_PRIMARY}>
Pas de panique ! Voici ce que vous pouvez faire :
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Retourner à la page d'accueil en cliquant sur le bouton ci-dessous.
</Typography>
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.TEXT_SECONDARY}>
Contactez-nous si vous avez besoin d'aide.
</Typography>
</div>
<Link href={Module.getInstance().get().modules.pages.Home.props.path}>
<Button>Retour à l'accueil</Button>
</Link>
</div>
<HelpBox
title="Vous avez des questions ?"
description="Notre équipe de support est là pour vous aider."
button={{ text: "Contactez le support" }}
/>
</div>
</DefaultDoubleSidePage>
);

View File

@ -36,6 +36,15 @@
"props": {
"path": "/client-dashboard/[folderUid]",
"labelKey": "client-dashboard"
},
"pages": {
"ReceiveDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/received-documents",
"labelKey": "received_documents"
}
}
}
},
"Folder": {
@ -52,6 +61,13 @@
"labelKey": "folder_information"
}
},
"DocumentsReminderHistory": {
"enabled": true,
"props": {
"path": "/folders/[folderUid]/documents-reminder-history",
"labelKey": "documents_reminder_history"
}
},
"CreateFolder": {
"enabled": true,
"props": {

View File

@ -36,6 +36,15 @@
"props": {
"path": "/client-dashboard/[folderUid]",
"labelKey": "client-dashboard"
},
"pages": {
"ReceiveDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/received-documents",
"labelKey": "received_documents"
}
}
}
},
"Folder": {
@ -52,6 +61,13 @@
"labelKey": "folder_information"
}
},
"DocumentsReminderHistory": {
"enabled": true,
"props": {
"path": "/folders/[folderUid]/documents-reminder-history",
"labelKey": "documents_reminder_history"
}
},
"CreateFolder": {
"enabled": true,
"props": {

View File

@ -36,6 +36,15 @@
"props": {
"path": "/client-dashboard/[folderUid]",
"labelKey": "client-dashboard"
},
"pages": {
"ReceiveDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/received-documents",
"labelKey": "received_documents"
}
}
}
},
"Folder": {
@ -52,6 +61,13 @@
"labelKey": "folder_information"
}
},
"DocumentsReminderHistory": {
"enabled": true,
"props": {
"path": "/folders/[folderUid]/documents-reminder-history",
"labelKey": "documents_reminder_history"
}
},
"CreateFolder": {
"enabled": true,
"props": {

View File

@ -36,6 +36,15 @@
"props": {
"path": "/client-dashboard/[folderUid]",
"labelKey": "client-dashboard"
},
"pages": {
"ReceiveDocuments": {
"enabled": true,
"props": {
"path": "/client-dashboard/[folderUid]/received-documents",
"labelKey": "received_documents"
}
}
}
},
"Folder": {
@ -52,6 +61,13 @@
"labelKey": "folder_information"
}
},
"DocumentsReminderHistory": {
"enabled": true,
"props": {
"path": "/folders/[folderUid]/documents-reminder-history",
"labelKey": "documents_reminder_history"
}
},
"CreateFolder": {
"enabled": true,
"props": {

View File

@ -0,0 +1,5 @@
import ReceivedDocuments from "@Front/Components/Layouts/ClientDashboard/ReceivedDocuments";
export default function Route() {
return <ReceivedDocuments />;
}

View File

@ -0,0 +1,5 @@
import DocumentsReminderHistory from "@Front/Components/Layouts/Folder/DocumentsReminderHistory";
export default function Route() {
return <DocumentsReminderHistory />;
}