From a9ce560a1b550df88d6fd64d176bf6cc59383e6c Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 15:58:36 +0200 Subject: [PATCH 1/4] :sparkles: add error message when no client selected --- .../Form/AutocompleteField/index.tsx | 2 ++ .../AutocompleteMultiSelectField/index.tsx | 2 ++ .../DesignSystem/Form/SelectField/index.tsx | 3 +++ .../Layouts/Folder/SendDocuments/index.tsx | 21 +++++++++++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx b/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx index d774c9ac..28109308 100644 --- a/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx +++ b/src/front/Components/DesignSystem/Form/AutocompleteField/index.tsx @@ -34,6 +34,8 @@ export default class AutocompleteField extends BaseField { }; public override componentDidUpdate(prevProps: IProps): void { + super.componentDidUpdate(prevProps); + if (prevProps.selectedOption !== this.props.selectedOption) { this.setState({ selectedOption: this.props.selectedOption ?? null }); } diff --git a/src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/index.tsx b/src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/index.tsx index be59f164..95b468a6 100644 --- a/src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/index.tsx +++ b/src/front/Components/DesignSystem/Form/AutocompleteMultiSelectField/index.tsx @@ -34,6 +34,8 @@ export default class AutocompleteMultiSelectField extends BaseField { }; public override componentDidUpdate(prevProps: IProps): void { + super.componentDidUpdate(prevProps); + + if (prevProps.selectedOption !== this.props.selectedOption) { this.setState({ selectedOption: this.props.selectedOption ?? null }); } diff --git a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx index d9691b84..4bbed888 100644 --- a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx @@ -17,6 +17,9 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import classes from "./classes.module.scss"; import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; +import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; +import { ValidationError } from "class-validator"; +import TextField from "@Front/Components/DesignSystem/Form/TextField"; enum EClientSelection { ALL_CLIENTS = "all_clients", @@ -31,6 +34,7 @@ export default function SendDocuments() { const [selectedClients, setSelectedClients] = useState([]); const [files, setFiles] = useState([]); const [isSending, setIsSending] = useState(false); + const [validationError, setValidationError] = useState(null); const onFormSubmit = useCallback( async ( @@ -46,6 +50,17 @@ export default function SendDocuments() { try { setIsSending(true); + + if (selectedClients.length === 0) { + setValidationError({ + property: "clients", + constraints: { + isEmpty: "Veuillez sélectionner au moins un client", + }, + }); + throw new Error("No clients selected"); + } + await Promise.all( selectedClients.map(async (customer) => { const promises = files.map(async (file) => { @@ -72,7 +87,7 @@ export default function SendDocuments() { 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); + console.warn("Error while sending files: ", error); } }, [files, folderUid, router, selectedClients], @@ -163,10 +178,12 @@ export default function SendDocuments() {
{clientSelection === EClientSelection.SELECTED_CLIENTS && ( - )} {clientSelection && ( From 9dd57124c64d3e064146a41ade6e398a7007881c Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 16:12:36 +0200 Subject: [PATCH 2/4] :sparkles: add toaster when client upload file --- .../DepositDocumentComponent/index.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx b/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx index 943361af..37448dbd 100644 --- a/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx @@ -5,6 +5,7 @@ import { useCallback, useMemo } from "react"; import classes from "./classes.module.scss"; import Files from "@Front/Api/LeCoffreApi/Customer/Files/Files"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; type IProps = { document: Document; @@ -29,14 +30,22 @@ export default function DepositDocumentComponent(props: IProps) { formData.append("file", file, file.name); const query = JSON.stringify({ document: { uid: document.uid } }); formData.append("q", query); - return Files.getInstance().post(formData).then(onChange); + return Files.getInstance() + .post(formData) + .then(onChange) + .then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Fichier uploadé avec succès!" })) + .catch((error) => ToasterService.getInstance().error({ title: "Erreur !", description: error.message })); }, [document.uid, onChange], ); const deleteFile = useCallback( (filedUid: string) => { - return Files.getInstance().delete(filedUid).then(onChange); + return Files.getInstance() + .delete(filedUid) + .then(onChange) + .then(() => ToasterService.getInstance().success({ title: "Succès !", description: "Fichier supprimé avec succès!" })) + .catch((error) => ToasterService.getInstance().error({ title: "Erreur !", description: error.message })); }, [onChange], ); From 4243262b6b9604c51255030f5c8a700730d89402 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 17:29:34 +0200 Subject: [PATCH 3/4] chore: Refactor email reminder count logic and handle empty reminders list --- .../ClientView/EmailReminder/index.tsx | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) 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 bedb14b4..9992aa4e 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/EmailReminder/index.tsx @@ -44,14 +44,26 @@ export default function EmailReminder(props: IProps) { fetchReminders(); }, [fetchReminders]); - // 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; + // Vérifie que la liste `reminders` n'est pas vide ou null + if (!reminders || reminders.length === 0) { + return 0; + } + + const remindersGroupByDate = reminders.reduce((acc, reminder) => { + // Vérifie si `reminder_date` est bien défini + if (!reminder.reminder_date) return acc; + + // Normalise la date à la seconde près + const reminderDate = new Date(reminder.reminder_date).setMilliseconds(0); + + // Initialise ou incrémente le compteur + acc[reminderDate] = (acc[reminderDate] || 0) + 1; return acc; }, {} as Record); - return Object.keys(remindersGroupByDate ?? {}).length; + + // Retourne la longueur des clés, représentant le nombre de dates uniques + return Object.keys(remindersGroupByDate).length; }, [reminders]); const doesCustomerHaveNotValidatedDocuments = useMemo( From 7774488be73bcf7769e7aaaed8b2aadd64843515 Mon Sep 17 00:00:00 2001 From: Max S Date: Fri, 13 Sep 2024 17:30:44 +0200 Subject: [PATCH 4/4] remove unused import --- .../Components/Layouts/Folder/SendDocuments/index.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx index 4bbed888..0f743d79 100644 --- a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx @@ -1,25 +1,23 @@ import backgroundImage from "@Assets/images/background_refonte.svg"; import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary"; import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders"; -import AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import DragAndDrop from "@Front/Components/DesignSystem/DragAndDrop"; import Form from "@Front/Components/DesignSystem/Form"; +import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; import RadioBox from "@Front/Components/DesignSystem/RadioBox"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import BackArrow from "@Front/Components/Elements/BackArrow"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; import Module from "@Front/Config/Module"; import { PaperAirplaneIcon } from "@heroicons/react/24/outline"; +import { ValidationError } from "class-validator"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; 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"; -import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField"; -import { ValidationError } from "class-validator"; -import TextField from "@Front/Components/DesignSystem/Form/TextField"; enum EClientSelection { ALL_CLIENTS = "all_clients",