From d6456199cf7b96add3a025d540959cfab335d0f2 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 12:19:18 +0200 Subject: [PATCH 1/4] :sparkles: add toaster and fix count email reminder --- .../Api/LeCoffreApi/Notary/Folders/Folders.ts | 1 + .../DeleteAskedDocumentModal/index.tsx | 2 ++ .../DeleteSentDocumentModal/index.tsx | 2 ++ .../EmailReminder/ReminderModal/index.tsx | 9 ++++-- .../ClientView/EmailReminder/index.tsx | 32 +++++++++++-------- .../Layouts/Folder/SendDocuments/index.tsx | 3 +- src/front/Components/Layouts/Folder/index.tsx | 1 + 7 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/front/Api/LeCoffreApi/Notary/Folders/Folders.ts b/src/front/Api/LeCoffreApi/Notary/Folders/Folders.ts index b7aa1342..ef7ad713 100644 --- a/src/front/Api/LeCoffreApi/Notary/Folders/Folders.ts +++ b/src/front/Api/LeCoffreApi/Notary/Folders/Folders.ts @@ -8,6 +8,7 @@ export interface IGetFoldersParams { select?: {}; where?: {}; include?: {}; + orderBy?: {}; }; } diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteAskedDocumentModal/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteAskedDocumentModal/index.tsx index 87d2586a..e43a3e1d 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteAskedDocumentModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteAskedDocumentModal/index.tsx @@ -1,5 +1,6 @@ import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; import Modal from "@Front/Components/DesignSystem/Modal"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import React, { useCallback } from "react"; @@ -18,6 +19,7 @@ export default function DeleteAskedDocumentModal(props: IProps) { Documents.getInstance() .delete(documentUid) .then(() => onDeleteSuccess(documentUid)) + .then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Le document a été supprimé avec succès." })) .then(onClose) .catch((error) => console.warn(error)), [documentUid, onClose, onDeleteSuccess], diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteSentDocumentModal/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteSentDocumentModal/index.tsx index 72fed16e..e3d6296e 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteSentDocumentModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/DeleteSentDocumentModal/index.tsx @@ -1,5 +1,6 @@ import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; import Modal from "@Front/Components/DesignSystem/Modal"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import React, { useCallback } from "react"; @@ -18,6 +19,7 @@ export default function DeleteSentDocumentModal(props: IProps) { DocumentsNotary.getInstance() .delete(documentUid) .then(() => onDeleteSuccess(documentUid)) + .then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Le document a été supprimé avec succès." })) .then(onClose) .catch((error) => console.warn(error)), [documentUid, onClose, onDeleteSuccess], diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx index 5c540d68..13629989 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx @@ -8,6 +8,7 @@ import React, { useCallback, useMemo, useState } from "react"; import classes from "./classes.module.scss"; import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; type IProps = { isOpen: boolean; @@ -22,9 +23,11 @@ export default function ReminderModal(props: IProps) { const [isAllSelected, setIsAllSelected] = useState(false); const onRemind = useCallback(() => { - Customers.getInstance().sendReminder(customer.uid!, selectedOptions.map((option) => option.value) as string[]); - onRemindSuccess(); - onClose?.(); + Customers.getInstance() + .sendReminder(customer.uid!, selectedOptions.map((option) => option.value) as string[]) + .then(onRemindSuccess) + .then(() => ToasterService.getInstance().success({ title: "Succès !", description: "La relance a été envoyée avec succès." })) + .then(onClose); }, [customer.uid, onClose, onRemindSuccess, selectedOptions]); const documentsOptions: IOption[] = useMemo( diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx index ca9155d2..54a5069b 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx @@ -9,7 +9,7 @@ import Customer from "le-coffre-resources/dist/Customer"; import { DocumentReminder } from "le-coffre-resources/dist/Notary"; import Link from "next/link"; import { useRouter } from "next/router"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import classes from "./classes.module.scss"; import ReminderModal from "./ReminderModal"; @@ -26,22 +26,33 @@ export default function EmailReminder(props: IProps) { const { isOpen, open, close } = useOpenable(); const router = useRouter(); + let { folderUid } = router.query; + const fetchReminders = useCallback(async () => { + if (!customer.uid || !folderUid) return; DocumentReminders.getInstance() .get({ - where: { document: { depositor: { uid: customer.uid } } }, + where: { document: { depositor: { uid: customer.uid }, folder: { uid: folderUid } } }, include: { document: "true" }, orderBy: { reminder_date: "desc" }, }) .then((reminders) => setReminders(reminders)) .catch((e) => console.warn(e)); - }, [customer.uid]); + }, [customer.uid, folderUid]); useEffect(() => { fetchReminders(); }, [fetchReminders]); - let { folderUid } = router.query; + // count the number of reminders group by reminder_date rounded at seconde + const remindersLength = useMemo(() => { + const remindersGroupByDate = reminders?.reduce((acc, reminder) => { + const reminderDate = new Date(reminder.reminder_date!).setSeconds(0, 0); + acc[reminderDate] = acc[reminderDate] ? acc[reminderDate] + 1 : 1; + return acc; + }, {} as Record); + return Object.keys(remindersGroupByDate ?? {}).length; + }, [reminders]); return (
@@ -68,21 +79,14 @@ export default function EmailReminder(props: IProps) {
Dernière relance:{" "} - {reminders && reminders.length > 0 ? new Date(reminders[0]!.reminder_date!).toLocaleDateString() : "-"} + {reminders && remindersLength > 0 ? new Date(reminders[0]!.reminder_date!).toLocaleDateString() : "-"} - Nombre de relance: {reminders && reminders.length > 0 ? reminders.length : "0"} + Nombre de relance: {remindersLength}
- { - window.location.reload(); - }} - onClose={close} - customer={customer} - /> + ); } diff --git a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx index 0449d17e..d9691b84 100644 --- a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx @@ -16,6 +16,7 @@ import { useRouter } from "next/router"; import React, { useCallback, useEffect, useMemo, useState } from "react"; import classes from "./classes.module.scss"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; enum EClientSelection { ALL_CLIENTS = "all_clients", @@ -68,7 +69,7 @@ export default function SendDocuments() { .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string), ); setIsSending(false); - console.log("All files have been successfully sent."); + ToasterService.getInstance().success({ title: "Succès !", description: "Votre document a été envoyée avec succès." }); } catch (error) { setIsSending(false); console.error("Error while sending files: ", error); diff --git a/src/front/Components/Layouts/Folder/index.tsx b/src/front/Components/Layouts/Folder/index.tsx index c7e2dd5e..a3f4ca4b 100644 --- a/src/front/Components/Layouts/Folder/index.tsx +++ b/src/front/Components/Layouts/Folder/index.tsx @@ -27,6 +27,7 @@ export default function Folder() { .get({ q: { where: { status: EFolderStatus.LIVE }, + orderBy: { created_at: "desc" }, }, }) .then((folders) => { From 3044bc16085672ef377c169a5d2c91effed2ba64 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 13:09:51 +0200 Subject: [PATCH 2/4] :hammer: handle better fetching documents in documents tables --- .../ClientView/DocumentTables/index.tsx | 60 +++++++++++++------ .../FolderInformation/ClientView/index.tsx | 18 +----- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx index a9b191d4..959a3c93 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx @@ -19,10 +19,13 @@ import classes from "./classes.module.scss"; import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal"; import DeleteSentDocumentModal from "./DeleteSentDocumentModal"; import FilesNotary from "@Front/Api/LeCoffreApi/Notary/FilesNotary/Files"; +import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; + +import NoDocument from "../NoDocument"; +import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; type IProps = { - documents: Document[]; - documentsNotary: DocumentNotary[]; + customerUid: string; folderUid: string; }; @@ -34,23 +37,46 @@ const tradDocumentStatus: Record = { }; export default function DocumentTables(props: IProps) { - const { documents: documentsProps, folderUid, documentsNotary } = props; - const [documents, setDocuments] = useState(documentsProps); - const [documentUid, setDocumentUid] = useState(null); + const { folderUid, customerUid } = props; + const [documents, setDocuments] = useState([]); + const [documentsNotary, setDocumentsNotary] = useState([]); + const [focusedDocumentUid, setFocusedDocumentUid] = useState(null); const isMobile = useMediaQuery("(max-width:524px)"); const deleteAskedDocumentModal = useOpenable(); const deleteSentDocumentModal = useOpenable(); + const fetchDocuments = useCallback( + () => + Documents.getInstance() + .get({ + where: { folder: { uid: folderUid }, depositor: { uid: customerUid } }, + include: { files: true, document_type: true }, + }) + .then(setDocuments) + .catch(console.warn), + [customerUid, folderUid], + ); + + const fetchDocumentsNotary = useCallback( + () => + DocumentsNotary.getInstance() + .get({ where: { folder: { uid: folderUid }, customer: { uid: customerUid } }, include: { files: true } }) + .then(setDocumentsNotary) + .catch(console.warn), + [customerUid, folderUid], + ); + useEffect(() => { - setDocuments(documentsProps); - }, [documentsProps]); + fetchDocuments(); + fetchDocumentsNotary(); + }, [fetchDocuments, fetchDocumentsNotary]); const openDeleteAskedDocumentModal = useCallback( (uid: string | undefined) => { if (!uid) return; - setDocumentUid(uid); + setFocusedDocumentUid(uid); deleteAskedDocumentModal.open(); }, [deleteAskedDocumentModal], @@ -59,7 +85,7 @@ export default function DocumentTables(props: IProps) { const openDeleteSentDocumentModal = useCallback( (uid: string | undefined) => { if (!uid) return; - setDocumentUid(uid); + setFocusedDocumentUid(uid); deleteSentDocumentModal.open(); }, [deleteSentDocumentModal], @@ -237,9 +263,9 @@ export default function DocumentTables(props: IProps) { return (validatedDocuments.length / total) * 100; }, [askedDocuments.length, refusedDocuments.length, toValidateDocuments.length, validatedDocuments.length]); - const handleDelete = useCallback((_documentUid: string) => { - window.location.reload(); - }, []); + console.log({ documents }); + + if (documents.length === 0 && documentsNotary.length === 0) return ; return (
@@ -254,19 +280,19 @@ export default function DocumentTables(props: IProps) { {validatedDocuments.length > 0 && } {refusedDocuments.length > 0 &&
} {sentDocuments.length > 0 &&
} - {documentUid && ( + {focusedDocumentUid && ( <> )} diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx index 17b5cc49..2608b960 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx @@ -1,4 +1,3 @@ -import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; 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"; @@ -7,16 +6,14 @@ 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 { DocumentNotary } from "le-coffre-resources/dist/Notary"; import Link from "next/link"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import { AnchorStatus } from ".."; import classes from "./classes.module.scss"; import ClientBox from "./ClientBox"; import DocumentTables from "./DocumentTables"; import EmailReminder from "./EmailReminder"; -import NoDocument from "./NoDocument"; type IProps = { folder: OfficeFolder; @@ -27,7 +24,6 @@ export type ICustomer = Customer & { id: string }; export default function ClientView(props: IProps) { const { folder, anchorStatus } = props; - const [documentsNotary, setDocumentsNotary] = useState([]); const customers: ICustomer[] = useMemo( () => @@ -77,12 +73,6 @@ export default function ClientView(props: IProps) { [folder], ); - useEffect(() => { - DocumentsNotary.getInstance() - .get({ where: { folder: { uid: folder.uid }, customer: { uid: customer.uid } }, include: { files: true } }) - .then((documentsNotary) => setDocumentsNotary(documentsNotary)); - }, [customer.uid, folder]); - return (
@@ -132,11 +122,7 @@ export default function ClientView(props: IProps) {
- {doesCustomerHaveDocument || documentsNotary.length > 0 ? ( - - ) : ( - - )} + {customer.uid && folder.uid && }
); From 1790cd51d6ea106af364216304f55b81a73c22d0 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 13:10:14 +0200 Subject: [PATCH 3/4] remove console.log() --- .../ClientView/DocumentTables/index.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx index 959a3c93..e38aacf4 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx @@ -1,4 +1,7 @@ +import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; +import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; import Files from "@Front/Api/LeCoffreApi/Notary/Files/Files"; +import FilesNotary from "@Front/Api/LeCoffreApi/Notary/FilesNotary/Files"; import CircleProgress from "@Front/Components/DesignSystem/CircleProgress"; import IconButton from "@Front/Components/DesignSystem/IconButton"; import Table from "@Front/Components/DesignSystem/Table"; @@ -15,14 +18,10 @@ import { DocumentNotary } from "le-coffre-resources/dist/Notary"; import Link from "next/link"; import { useCallback, useEffect, useMemo, useState } from "react"; +import NoDocument from "../NoDocument"; import classes from "./classes.module.scss"; import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal"; import DeleteSentDocumentModal from "./DeleteSentDocumentModal"; -import FilesNotary from "@Front/Api/LeCoffreApi/Notary/FilesNotary/Files"; -import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; - -import NoDocument from "../NoDocument"; -import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; type IProps = { customerUid: string; @@ -263,8 +262,6 @@ export default function DocumentTables(props: IProps) { return (validatedDocuments.length / total) * 100; }, [askedDocuments.length, refusedDocuments.length, toValidateDocuments.length, validatedDocuments.length]); - console.log({ documents }); - if (documents.length === 0 && documentsNotary.length === 0) return ; return ( From 68468f7793f805d635218d3357523ca166757075 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 13:26:15 +0200 Subject: [PATCH 4/4] :hammer: disabled email reminder button when validated documents --- .../EmailReminder/ReminderModal/index.tsx | 19 +++++++++++-------- .../ClientView/EmailReminder/index.tsx | 11 ++++++++--- .../FolderInformation/ClientView/index.tsx | 3 --- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx index 13629989..4da1f326 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/ReminderModal/index.tsx @@ -1,14 +1,15 @@ +import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers"; import CheckBox from "@Front/Components/DesignSystem/CheckBox"; import { IOption } from "@Front/Components/DesignSystem/Form/SelectFieldOld"; import Modal from "@Front/Components/DesignSystem/Modal"; import Separator, { ESeperatorColor } from "@Front/Components/DesignSystem/Separator"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import Customer from "le-coffre-resources/dist/Customer"; +import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; import React, { useCallback, useMemo, useState } from "react"; import classes from "./classes.module.scss"; -import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers"; -import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; type IProps = { isOpen: boolean; @@ -32,12 +33,14 @@ export default function ReminderModal(props: IProps) { const documentsOptions: IOption[] = useMemo( () => - customer.documents?.map((document) => { - return { - label: document.document_type?.name ?? "", - value: document.uid ?? "", - }; - }) ?? [], + customer.documents + ?.filter((document) => document.document_status !== EDocumentStatus.VALIDATED) + .map((document) => { + return { + label: document.document_type?.name ?? "", + value: document.uid ?? "", + }; + }) ?? [], [customer], ); diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx index 54a5069b..bedb14b4 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx @@ -13,15 +13,15 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import classes from "./classes.module.scss"; import ReminderModal from "./ReminderModal"; +import { EDocumentStatus } from "le-coffre-resources/dist/Customer/Document"; type IProps = { customer: Customer; - doesCustomerHaveDocument: boolean; isAnchored: boolean; }; export default function EmailReminder(props: IProps) { - const { customer, doesCustomerHaveDocument, isAnchored } = props; + const { customer, isAnchored } = props; const [reminders, setReminders] = useState(null); const { isOpen, open, close } = useOpenable(); const router = useRouter(); @@ -54,6 +54,11 @@ export default function EmailReminder(props: IProps) { return Object.keys(remindersGroupByDate ?? {}).length; }, [reminders]); + const doesCustomerHaveNotValidatedDocuments = useMemo( + () => customer.documents && customer.documents.some((document) => document.document_status !== EDocumentStatus.VALIDATED), + [customer.documents], + ); + return (
{!isAnchored && ( @@ -63,7 +68,7 @@ export default function EmailReminder(props: IProps) { variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED} fullwidth - disabled={doesCustomerHaveDocument}> + disabled={!doesCustomerHaveNotValidatedDocuments}> Relancer par mail )} diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx index 2608b960..22b7effa 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx @@ -56,8 +56,6 @@ export default function ClientView(props: IProps) { [customers], ); - const doesCustomerHaveDocument = useMemo(() => customer.documents && customer.documents.length > 0, [customer]); - const handleClientDelete = useCallback( (customerUid: string) => { if (!folder.uid) return; @@ -116,7 +114,6 @@ export default function ClientView(props: IProps) { )}