Merge branch 'dev' into staging
This commit is contained in:
commit
bf6e443c36
@ -34,6 +34,8 @@ export default class AutocompleteField extends BaseField<IProps, IState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public override componentDidUpdate(prevProps: IProps): void {
|
public override componentDidUpdate(prevProps: IProps): void {
|
||||||
|
super.componentDidUpdate(prevProps);
|
||||||
|
|
||||||
if (prevProps.selectedOption !== this.props.selectedOption) {
|
if (prevProps.selectedOption !== this.props.selectedOption) {
|
||||||
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ export default class AutocompleteMultiSelectField extends BaseField<IProps, ISta
|
|||||||
};
|
};
|
||||||
|
|
||||||
public override componentDidUpdate(prevProps: IProps): void {
|
public override componentDidUpdate(prevProps: IProps): void {
|
||||||
|
super.componentDidUpdate(prevProps);
|
||||||
|
|
||||||
if (prevProps.selectedOptions !== this.props.selectedOptions) {
|
if (prevProps.selectedOptions !== this.props.selectedOptions) {
|
||||||
this.setState({ selectedOptions: this.props.selectedOptions ?? null });
|
this.setState({ selectedOptions: this.props.selectedOptions ?? null });
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,9 @@ export default class SelectField extends BaseField<IProps, IState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public override componentDidUpdate(prevProps: IProps): void {
|
public override componentDidUpdate(prevProps: IProps): void {
|
||||||
|
super.componentDidUpdate(prevProps);
|
||||||
|
|
||||||
|
|
||||||
if (prevProps.selectedOption !== this.props.selectedOption) {
|
if (prevProps.selectedOption !== this.props.selectedOption) {
|
||||||
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { useCallback, useMemo } from "react";
|
|||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import Files from "@Front/Api/LeCoffreApi/Customer/Files/Files";
|
import Files from "@Front/Api/LeCoffreApi/Customer/Files/Files";
|
||||||
|
import { ToasterService } from "@Front/Components/DesignSystem/Toaster";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
document: Document;
|
document: Document;
|
||||||
@ -29,14 +30,22 @@ export default function DepositDocumentComponent(props: IProps) {
|
|||||||
formData.append("file", file, file.name);
|
formData.append("file", file, file.name);
|
||||||
const query = JSON.stringify({ document: { uid: document.uid } });
|
const query = JSON.stringify({ document: { uid: document.uid } });
|
||||||
formData.append("q", query);
|
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],
|
[document.uid, onChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const deleteFile = useCallback(
|
const deleteFile = useCallback(
|
||||||
(filedUid: string) => {
|
(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],
|
[onChange],
|
||||||
);
|
);
|
||||||
|
@ -44,14 +44,26 @@ export default function EmailReminder(props: IProps) {
|
|||||||
fetchReminders();
|
fetchReminders();
|
||||||
}, [fetchReminders]);
|
}, [fetchReminders]);
|
||||||
|
|
||||||
// count the number of reminders group by reminder_date rounded at seconde
|
|
||||||
const remindersLength = useMemo(() => {
|
const remindersLength = useMemo(() => {
|
||||||
const remindersGroupByDate = reminders?.reduce((acc, reminder) => {
|
// Vérifie que la liste `reminders` n'est pas vide ou null
|
||||||
const reminderDate = new Date(reminder.reminder_date!).setSeconds(0, 0);
|
if (!reminders || reminders.length === 0) {
|
||||||
acc[reminderDate] = acc[reminderDate] ? acc[reminderDate] + 1 : 1;
|
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;
|
return acc;
|
||||||
}, {} as Record<number, number>);
|
}, {} as Record<number, number>);
|
||||||
return Object.keys(remindersGroupByDate ?? {}).length;
|
|
||||||
|
// Retourne la longueur des clés, représentant le nombre de dates uniques
|
||||||
|
return Object.keys(remindersGroupByDate).length;
|
||||||
}, [reminders]);
|
}, [reminders]);
|
||||||
|
|
||||||
const doesCustomerHaveNotValidatedDocuments = useMemo(
|
const doesCustomerHaveNotValidatedDocuments = useMemo(
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import backgroundImage from "@Assets/images/background_refonte.svg";
|
import backgroundImage from "@Assets/images/background_refonte.svg";
|
||||||
import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
|
import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
|
||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
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 Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import DragAndDrop from "@Front/Components/DesignSystem/DragAndDrop";
|
import DragAndDrop from "@Front/Components/DesignSystem/DragAndDrop";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
|
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
|
||||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||||
|
import { ToasterService } from "@Front/Components/DesignSystem/Toaster";
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||||
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
import { PaperAirplaneIcon } from "@heroicons/react/24/outline";
|
import { PaperAirplaneIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { ValidationError } from "class-validator";
|
||||||
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { ToasterService } from "@Front/Components/DesignSystem/Toaster";
|
|
||||||
|
|
||||||
enum EClientSelection {
|
enum EClientSelection {
|
||||||
ALL_CLIENTS = "all_clients",
|
ALL_CLIENTS = "all_clients",
|
||||||
@ -31,6 +32,7 @@ export default function SendDocuments() {
|
|||||||
const [selectedClients, setSelectedClients] = useState<string[]>([]);
|
const [selectedClients, setSelectedClients] = useState<string[]>([]);
|
||||||
const [files, setFiles] = useState<File[]>([]);
|
const [files, setFiles] = useState<File[]>([]);
|
||||||
const [isSending, setIsSending] = useState(false);
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
const [validationError, setValidationError] = useState<ValidationError | null>(null);
|
||||||
|
|
||||||
const onFormSubmit = useCallback(
|
const onFormSubmit = useCallback(
|
||||||
async (
|
async (
|
||||||
@ -46,6 +48,17 @@ export default function SendDocuments() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setIsSending(true);
|
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(
|
await Promise.all(
|
||||||
selectedClients.map(async (customer) => {
|
selectedClients.map(async (customer) => {
|
||||||
const promises = files.map(async (file) => {
|
const promises = files.map(async (file) => {
|
||||||
@ -72,7 +85,7 @@ export default function SendDocuments() {
|
|||||||
ToasterService.getInstance().success({ title: "Succès !", description: "Votre document a été envoyée avec succès." });
|
ToasterService.getInstance().success({ title: "Succès !", description: "Votre document a été envoyée avec succès." });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsSending(false);
|
setIsSending(false);
|
||||||
console.error("Error while sending files: ", error);
|
console.warn("Error while sending files: ", error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[files, folderUid, router, selectedClients],
|
[files, folderUid, router, selectedClients],
|
||||||
@ -163,10 +176,12 @@ export default function SendDocuments() {
|
|||||||
|
|
||||||
<Form onSubmit={onFormSubmit} className={classes["form"]}>
|
<Form onSubmit={onFormSubmit} className={classes["form"]}>
|
||||||
{clientSelection === EClientSelection.SELECTED_CLIENTS && (
|
{clientSelection === EClientSelection.SELECTED_CLIENTS && (
|
||||||
<AutocompleteMultiSelect
|
<AutocompleteMultiSelectField
|
||||||
|
name="clients"
|
||||||
label="Choisir le ou les clients: "
|
label="Choisir le ou les clients: "
|
||||||
options={clientsOptions}
|
options={clientsOptions}
|
||||||
onSelectionChange={handleClientSelectionChange}
|
onSelectionChange={handleClientSelectionChange}
|
||||||
|
validationError={validationError ?? undefined}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{clientSelection && (
|
{clientSelection && (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user