Refacto/folder information wip 2 (#173)

This commit is contained in:
Maxime Sallerin 2024-07-19 18:24:06 +02:00 committed by GitHub
parent 16de95254c
commit da0f70cb42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 143 additions and 23 deletions

View File

@ -3,6 +3,9 @@
.root { .root {
cursor: pointer; cursor: pointer;
border-radius: var(--button-icon-button-radius, 8px); border-radius: var(--button-icon-button-radius, 8px);
display: inline-flex;
padding: var(--spacing-sm, 8px);
align-items: flex-start;
svg { svg {
width: 24px; width: 24px;

View File

@ -1,5 +1,4 @@
import InfiniteScroll from "@Front/Components/Elements/InfiniteScroll"; import InfiniteScroll from "@Front/Components/Elements/InfiniteScroll";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody"; import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
@ -67,7 +66,7 @@ export default function MuiTable(props: IProps) {
color={ETypoColor.COLOR_NEUTRAL_600}> color={ETypoColor.COLOR_NEUTRAL_600}>
{column.title} {column.title}
</Typography> </Typography>
<ChevronDownIcon width={21} /> {/* <ChevronDownIcon width={21} /> */}
</span> </span>
)} )}
</TableCell> </TableCell>

View File

@ -0,0 +1,39 @@
import Modal from "@Front/Components/DesignSystem/Modal";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import React, { useCallback } from "react";
type IProps = {
customerUid: string;
isOpen: boolean;
onClose?: () => void;
onDeleteSuccess: (uid: string) => void;
};
export default function DeleteCustomerModal(props: IProps) {
const { isOpen, onClose, customerUid, onDeleteSuccess } = props;
const onDelete = useCallback(
() => onDeleteSuccess(customerUid),
// Documents.getInstance()
// .delete(documentUid)
// .then(() => onDeleteSuccess(documentUid))
// .then(onClose)
// .catch((error) => console.warn(error)),
[customerUid, onDeleteSuccess],
);
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title={"Êtes-vous sûr de vouloir supprimer ce client du dossier ?"}
firstButton={{ text: "Annuler", onClick: onClose }}
secondButton={{ text: "Supprimer le client", onClick: onDelete }}>
<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
dossier une fois supprimées.
</Typography>
</Modal>
);
}

View File

@ -8,4 +8,11 @@
gap: var(--spacing-md, 16px); gap: var(--spacing-md, 16px);
background: var(--primary-weak-higlight, #e5eefa); background: var(--primary-weak-higlight, #e5eefa);
min-width: 300px; min-width: 300px;
.header{
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
} }

View File

@ -1,9 +1,12 @@
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 Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import useOpenable from "@Front/Hooks/useOpenable";
import { PencilSquareIcon, TrashIcon } from "@heroicons/react/24/outline";
import { ICustomer } from ".."; import { ICustomer } from "..";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import { PencilSquareIcon, TrashIcon } from "@heroicons/react/24/outline"; import DeleteCustomerModal from "./DeleteCustomerModal";
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
type IProps = { type IProps = {
customer: ICustomer; customer: ICustomer;
@ -12,6 +15,8 @@ type IProps = {
export default function ClientBox(props: IProps) { export default function ClientBox(props: IProps) {
const { customer } = props; const { customer } = props;
const { isOpen, open, close } = useOpenable();
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
<div className={classes["header"]}> <div className={classes["header"]}>
@ -49,9 +54,11 @@ export default function ClientBox(props: IProps) {
className={classes["delete-button"]} className={classes["delete-button"]}
variant={EButtonVariant.ERROR} variant={EButtonVariant.ERROR}
styletype={EButtonstyletype.TEXT} styletype={EButtonstyletype.TEXT}
rightIcon={<TrashIcon />}> rightIcon={<TrashIcon />}
onClick={open}>
Supprimer le client Supprimer le client
</Button> </Button>
<DeleteCustomerModal isOpen={isOpen} onClose={close} customerUid={customer.uid ?? ""} onDeleteSuccess={() => {}} />
</div> </div>
); );
} }

View File

@ -0,0 +1,37 @@
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
import Modal from "@Front/Components/DesignSystem/Modal";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import React, { useCallback } from "react";
type IProps = {
documentUid: string;
isOpen: boolean;
onClose?: () => void;
onDeleteSuccess: (uid: string) => void;
};
export default function DeleteAskedDocumentModal(props: IProps) {
const { isOpen, onClose, documentUid, onDeleteSuccess } = props;
const onDelete = useCallback(
() =>
Documents.getInstance()
.delete(documentUid)
.then(() => onDeleteSuccess(documentUid))
.then(onClose)
.catch((error) => console.warn(error)),
[documentUid, onClose, onDeleteSuccess],
);
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title={"Êtes-vous sûr de vouloir supprimer cette demande de document ?"}
firstButton={{ text: "Annuler", onClick: onClose }}
secondButton={{ text: "Supprimer la demande", onClick: onDelete }}>
<Typography typo={ETypo.TEXT_MD_light}>Cette action annulera la demande du document en cours.</Typography>
</Modal>
);
}

View File

@ -1,16 +1,17 @@
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
import CircleProgress from "@Front/Components/DesignSystem/CircleProgress"; import CircleProgress from "@Front/Components/DesignSystem/CircleProgress";
import IconButton from "@Front/Components/DesignSystem/IconButton"; import IconButton from "@Front/Components/DesignSystem/IconButton";
import Table from "@Front/Components/DesignSystem/Table"; import Table from "@Front/Components/DesignSystem/Table";
import { IHead, IRowProps } from "@Front/Components/DesignSystem/Table/MuiTable"; import { IHead, IRowProps } from "@Front/Components/DesignSystem/Table/MuiTable";
import Tag, { ETagColor, ETagVariant } from "@Front/Components/DesignSystem/Tag"; import Tag, { ETagColor, ETagVariant } from "@Front/Components/DesignSystem/Tag";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import useOpenable from "@Front/Hooks/useOpenable";
import { ArrowDownTrayIcon, EyeIcon, TrashIcon } from "@heroicons/react/24/outline"; import { ArrowDownTrayIcon, EyeIcon, TrashIcon } from "@heroicons/react/24/outline";
import { Document } from "le-coffre-resources/dist/Customer"; import { Document } from "le-coffre-resources/dist/Customer";
import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal";
type IProps = { type IProps = {
documents: Document[]; documents: Document[];
@ -39,20 +40,21 @@ const header: readonly IHead[] = [
export default function DocumentTables(props: IProps) { export default function DocumentTables(props: IProps) {
const { documents: documentsProps, totalOfDocumentTypes } = props; const { documents: documentsProps, totalOfDocumentTypes } = props;
const [documents, setDocuments] = useState<Document[]>(documentsProps); const [documents, setDocuments] = useState<Document[]>(documentsProps);
const [documentUid, setDocumentUid] = useState<string | null>(null);
const deleteAskedOocumentModal = useOpenable();
useEffect(() => { useEffect(() => {
setDocuments(documentsProps); setDocuments(documentsProps);
}, [documentsProps]); }, [documentsProps]);
const deleteAskedDocument = useCallback( const openDeleteAskedDocumentModal = useCallback(
(uid: string | undefined) => { (uid: string | undefined) => {
if (!uid) return; if (!uid) return;
return Documents.getInstance() setDocumentUid(uid);
.delete(uid) deleteAskedOocumentModal.open();
.then(() => setDocuments(documents.filter((document) => document.uid !== uid)))
.catch((error) => console.warn(error));
}, },
[documents], [deleteAskedOocumentModal],
); );
const askDocuments: IRowProps[] = useMemo( const askDocuments: IRowProps[] = useMemo(
@ -67,11 +69,11 @@ export default function DocumentTables(props: IProps) {
<Tag color={ETagColor.INFO} variant={ETagVariant.SEMI_BOLD} label={document.document_status.toUpperCase()} /> <Tag color={ETagColor.INFO} variant={ETagVariant.SEMI_BOLD} label={document.document_status.toUpperCase()} />
), ),
created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_", created_at: document.created_at ? new Date(document.created_at).toLocaleDateString() : "_",
actions: <IconButton icon={<TrashIcon onClick={() => deleteAskedDocument(document.uid)} />} />, actions: <IconButton icon={<TrashIcon onClick={() => openDeleteAskedDocumentModal(document.uid)} />} />,
}; };
}) })
.filter((document) => document !== null) as IRowProps[], .filter((document) => document !== null) as IRowProps[],
[deleteAskedDocument, documents], [documents, openDeleteAskedDocumentModal],
); );
const toValidateDocuments: IRowProps[] = useMemo( const toValidateDocuments: IRowProps[] = useMemo(
@ -136,7 +138,11 @@ export default function DocumentTables(props: IProps) {
[documents], [documents],
); );
const progressValidated = useMemo(() => validatedDocuments.length / totalOfDocumentTypes, [validatedDocuments, totalOfDocumentTypes]); const progressValidated = useMemo(() => {
if (totalOfDocumentTypes === 0) return 100;
if (validatedDocuments.length === 0) return 0;
return (validatedDocuments.length / totalOfDocumentTypes) * 100;
}, [validatedDocuments, totalOfDocumentTypes]);
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>
@ -150,6 +156,14 @@ export default function DocumentTables(props: IProps) {
{toValidateDocuments.length > 0 && <Table header={header} rows={toValidateDocuments} />} {toValidateDocuments.length > 0 && <Table header={header} rows={toValidateDocuments} />}
{validatedDocuments.length > 0 && <Table header={header} rows={validatedDocuments} />} {validatedDocuments.length > 0 && <Table header={header} rows={validatedDocuments} />}
{refusedDocuments.length > 0 && <Table header={header} rows={refusedDocuments} />} {refusedDocuments.length > 0 && <Table header={header} rows={refusedDocuments} />}
{documentUid && (
<DeleteAskedDocumentModal
isOpen={deleteAskedOocumentModal.isOpen}
onClose={deleteAskedOocumentModal.close}
onDeleteSuccess={(uid: string) => setDocuments(documents.filter((document) => document.uid !== uid))}
documentUid={documentUid}
/>
)}
</div> </div>
); );
} }

View File

@ -1,13 +1,15 @@
import CircleProgress from "@Front/Components/DesignSystem/CircleProgress"; import CircleProgress from "@Front/Components/DesignSystem/CircleProgress";
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag"; import Tag, { ETagColor } from "@Front/Components/DesignSystem/Tag";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import { UserGroupIcon, PencilSquareIcon, ArchiveBoxIcon } from "@heroicons/react/24/outline"; import Module from "@Front/Config/Module";
import { ArchiveBoxIcon, PencilSquareIcon, UserGroupIcon } from "@heroicons/react/24/outline";
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 { useCallback } from "react"; import { useCallback } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import IconButton, { EIconButtonVariant } from "@Front/Components/DesignSystem/IconButton";
type IProps = { type IProps = {
folder: OfficeFolder | null; folder: OfficeFolder | null;
@ -51,11 +53,23 @@ export default function InformationSection(props: IProps) {
<div className={classes["progress-container"]}> <div className={classes["progress-container"]}>
<CircleProgress percentage={getCompletionNumber()} /> <CircleProgress percentage={getCompletionNumber()} />
<div className={classes["icon-container"]}> <div className={classes["icon-container"]}>
<IconButton icon={<UserGroupIcon title="Modifier les collaborateurs" />} variant={EIconButtonVariant.NEUTRAL} /> <Link
<IconButton href={Module.getInstance()
icon={<PencilSquareIcon title="Modifier les informations du dossiers" />} .get()
variant={EIconButtonVariant.NEUTRAL} .modules.pages.Folder.pages.EditCollaborators.props.path.replace("[folderUid]", folder?.uid ?? "")}
/> title="Modifier les collaborateurs">
<IconButton icon={<UserGroupIcon title="Modifier les collaborateurs" />} variant={EIconButtonVariant.NEUTRAL} />
</Link>
<Link
href={Module.getInstance()
.get()
.modules.pages.Folder.pages.EditInformations.props.path.replace("[folderUid]", folder?.uid ?? "")}
title="Modifier les informations du dossiers">
<IconButton
icon={<PencilSquareIcon title="Modifier les informations du dossiers" />}
variant={EIconButtonVariant.NEUTRAL}
/>
</Link>
<IconButton icon={<ArchiveBoxIcon title="Archiver le dossier" />} variant={EIconButtonVariant.ERROR} /> <IconButton icon={<ArchiveBoxIcon title="Archiver le dossier" />} variant={EIconButtonVariant.ERROR} />
</div> </div>
</div> </div>