connect files notary + handle download

This commit is contained in:
Max S 2024-09-10 19:26:54 +02:00
parent dfba3474d5
commit eee11aa4bb
12 changed files with 254 additions and 127 deletions

View File

@ -1,15 +1,13 @@
import { DocumentNotary } from "le-coffre-resources/dist/Notary"; import { DocumentNotary } from "le-coffre-resources/dist/Notary";
import BaseNotary from "../BaseNotary"; import BaseNotary from "../BaseNotary";
// TODO Type get query params -> Where + inclue + orderby
export interface IGetDocumentNotaryparams { export interface IGetDocumentNotaryparams {
where?: {}; where?: {};
include?: {}; include?: {};
orderBy?: {}; orderBy?: {};
} }
// TODO Type getbyuid query params
export default class DocumentsNotary extends BaseNotary { export default class DocumentsNotary extends BaseNotary {
private static instance: DocumentsNotary; private static instance: DocumentsNotary;
private readonly baseURl = this.namespaceUrl.concat("/documents_notary"); private readonly baseURl = this.namespaceUrl.concat("/documents_notary");
@ -26,17 +24,17 @@ export default class DocumentsNotary extends BaseNotary {
} }
} }
// public async get(q: IGetDocumentNotaryparams): Promise<DocumentNotary[]> { public async get(q: IGetDocumentNotaryparams): Promise<DocumentNotary[]> {
// const url = new URL(this.baseURl); const url = new URL(this.baseURl);
// const query = { q }; const query = { q };
// Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value))); Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
// try { try {
// return await this.getRequest<DocumentNotary[]>(url); return await this.getRequest<DocumentNotary[]>(url);
// } catch (err) { } catch (err) {
// this.onError(err); this.onError(err);
// return Promise.reject(err); return Promise.reject(err);
// } }
// } }
/** /**
* @description : Create a Document Notary * @description : Create a Document Notary
@ -50,4 +48,18 @@ export default class DocumentsNotary extends BaseNotary {
return Promise.reject(err); return Promise.reject(err);
} }
} }
/**
* @description : Delete a Document Notary
*/
public async delete(uid: string): Promise<void> {
const url = new URL(this.baseURl);
url.pathname = url.pathname.concat(`/${uid}`);
try {
await this.deleteRequest(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
} }

View File

@ -0,0 +1,71 @@
import { File } from "le-coffre-resources/dist/SuperAdmin";
import BaseNotary from "../BaseNotary";
export interface IGetFilesparams {
where?: {};
include?: {};
}
export type IPutFilesParams = {};
export interface IPostFilesParams {}
export default class FilesNotary extends BaseNotary {
private static instance: FilesNotary;
private readonly baseURl = this.namespaceUrl.concat("/files-notary");
private constructor() {
super();
}
public static getInstance() {
return (this.instance ??= new this());
}
public async get(q: IGetFilesparams): Promise<File[]> {
const url = new URL(this.baseURl);
const query = { q };
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try {
const files = await this.getRequest<File[]>(url);
return files;
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
public async getByUid(uid: string, q?: any): Promise<File> {
const url = new URL(this.baseURl.concat(`/${uid}`));
const query = { q };
if (q) Object.entries(query).forEach(([key, value]) => url.searchParams.set(key, JSON.stringify(value)));
try {
const file = await this.getRequest<File>(url);
return file;
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
public async delete(uid: string): Promise<File> {
const url = new URL(this.baseURl.concat(`/${uid}`));
try {
return await this.deleteRequest<File>(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
public async download(uid: string): Promise<any> {
const url = new URL(this.baseURl.concat(`/download/${uid}`));
try {
return await this.getRequest<any>(url);
} catch (err) {
this.onError(err);
return Promise.reject(err);
}
}
}

View File

@ -27,7 +27,6 @@ export default function Autocomplete(props: IProps) {
useEffect(() => { useEffect(() => {
if (searchValue) { if (searchValue) {
const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase())); const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase()));
console.log(filteredOptions);
if (filteredOptions.length === 0) if (filteredOptions.length === 0)
return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]); return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]);
return setFilteredOptions(filteredOptions); return setFilteredOptions(filteredOptions);

View File

@ -39,7 +39,6 @@ class ToastElementClass extends React.Component<IPropsClass, IState> {
public override render(): JSX.Element { public override render(): JSX.Element {
const toast = this.props.toast; const toast = this.props.toast;
console.log(toast);
const style = { const style = {
"--data-duration": `${toast.time}ms`, "--data-duration": `${toast.time}ms`,

View File

@ -80,7 +80,6 @@ export default function Tabs<T>({ onSelect, tabs: propsTabs }: IProps<T>) {
newTabs.splice(index, 1); newTabs.splice(index, 1);
newTabs.unshift(tabs.current[index]!); newTabs.unshift(tabs.current[index]!);
tabs.current = newTabs; tabs.current = newTabs;
console.log("Updated values ; ", tabs.current);
handleSelect(value); handleSelect(value);
}, },
[handleSelect], [handleSelect],

View File

@ -1,18 +1,22 @@
import React from "react"; import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
import FilesNotary from "@Front/Api/LeCoffreApi/Notary/FilesNotary/Files";
import classes from "./classes.module.scss"; import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import { useRouter } from "next/router"; import IconButton from "@Front/Components/DesignSystem/IconButton";
import Table from "@Front/Components/DesignSystem/Table";
import { IHead, IRowProps } from "@Front/Components/DesignSystem/Table/MuiTable";
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 DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate";
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import BackArrow from "@Front/Components/Elements/BackArrow"; import JwtService from "@Front/Services/JwtService/JwtService";
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline"; import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import { saveAs } from "file-saver";
import { IHead } from "@Front/Components/DesignSystem/Table/MuiTable"; import JSZip from "jszip";
import Table from "@Front/Components/DesignSystem/Table"; import { DocumentNotary } from "le-coffre-resources/dist/Notary";
import { useRouter } from "next/router";
import React, { useCallback, useEffect, useState } from "react";
type IProps = {}; import classes from "./classes.module.scss";
const header: readonly IHead[] = [ const header: readonly IHead[] = [
{ {
@ -29,9 +33,60 @@ const header: readonly IHead[] = [
}, },
]; ];
export default function ReceivedDocuments(props: IProps) { export default function ReceivedDocuments() {
const router = useRouter(); const router = useRouter();
let { folderUid } = router.query; let { folderUid } = router.query;
const [documentsNotary, setDocumentsNotary] = useState<DocumentNotary[]>([]);
useEffect(() => {
const customerUid = JwtService.getInstance().decodeCustomerJwt()?.customerId;
if (!folderUid || !customerUid) return;
DocumentsNotary.getInstance()
.get({ where: { folder: { uid: folderUid }, customer: { uid: customerUid } }, include: { files: true } })
.then((documentsNotary) => setDocumentsNotary(documentsNotary));
}, [folderUid]);
const onDownload = useCallback((doc: DocumentNotary) => {
const file = doc.files?.[0];
if (!file || !file?.uid) return;
return FilesNotary.getInstance()
.download(file.uid)
.then((blob) => {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = file.file_name ?? "file";
a.click();
URL.revokeObjectURL(url);
})
.catch((e) => console.warn(e));
}, []);
const onDownloadAll = useCallback(async () => {
if (documentsNotary.length === 0) return;
const zip = new JSZip();
const folder = zip.folder("documents") || zip;
const downloadPromises = documentsNotary.map(async (doc) => {
const file = doc.files?.[0];
if (file && file.uid) {
const blob = await FilesNotary.getInstance().download(file.uid);
folder.file(file.file_name ?? "file", blob);
}
});
await Promise.all(downloadPromises);
zip.generateAsync({ type: "blob" })
.then((blob: any) => {
saveAs(blob, "documents.zip");
})
.catch((error: any) => {
console.error("Error generating ZIP file: ", error);
});
}, [documentsNotary]);
return ( return (
<DefaultTemplate title={"Documents reçus"} isPadding={false}> <DefaultTemplate title={"Documents reçus"} isPadding={false}>
@ -45,15 +100,25 @@ export default function ReceivedDocuments(props: IProps) {
<Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}> <Typography typo={ETypo.TITLE_H1} color={ETypoColor.TEXT_PRIMARY}>
Un document vous a é envoyé Un document vous a é envoyé
</Typography> </Typography>
<Table className={classes["table"]} header={header} rows={[{ key: "1", name: "todo", sentAt: "todo", actions: "todo" }]} /> <Table className={classes["table"]} header={header} rows={buildRows(documentsNotary, onDownload)} />
<Button <Button
variant={EButtonVariant.PRIMARY} variant={EButtonVariant.PRIMARY}
size={EButtonSize.LG} size={EButtonSize.LG}
styletype={EButtonstyletype.CONTAINED} styletype={EButtonstyletype.CONTAINED}
leftIcon={<ArrowDownTrayIcon />}> leftIcon={<ArrowDownTrayIcon />}
onClick={onDownloadAll}>
Tout télécharger Tout télécharger
</Button> </Button>
</div> </div>
</DefaultTemplate> </DefaultTemplate>
); );
} }
function buildRows(documentsNotary: DocumentNotary[], onDownloadFileNotary: (doc: DocumentNotary) => void): IRowProps[] {
return documentsNotary.map((documentNotary) => ({
key: documentNotary.uid ?? "",
name: documentNotary.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
sentAt: new Date(documentNotary.created_at!).toLocaleDateString(),
actions: <IconButton onClick={() => onDownloadFileNotary(documentNotary)} icon={<ArrowDownTrayIcon />} />,
}));
}

View File

@ -1,4 +1,4 @@
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents"; import DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
import Modal from "@Front/Components/DesignSystem/Modal"; import Modal from "@Front/Components/DesignSystem/Modal";
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
import React, { useCallback } from "react"; import React, { useCallback } from "react";
@ -15,7 +15,7 @@ export default function DeleteSentDocumentModal(props: IProps) {
const onDelete = useCallback( const onDelete = useCallback(
() => () =>
Documents.getInstance() DocumentsNotary.getInstance()
.delete(documentUid) .delete(documentUid)
.then(() => onDeleteSuccess(documentUid)) .then(() => onDeleteSuccess(documentUid))
.then(onClose) .then(onClose)

View File

@ -8,18 +8,21 @@ import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Ty
import Module from "@Front/Config/Module"; import Module from "@Front/Config/Module";
import useOpenable from "@Front/Hooks/useOpenable"; 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 { useMediaQuery } from "@mui/material";
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 { DocumentNotary } from "le-coffre-resources/dist/Notary";
import Link from "next/link"; import Link from "next/link";
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"; import DeleteAskedDocumentModal from "./DeleteAskedDocumentModal";
import DeleteSentDocumentModal from "./DeleteSentDocumentModal"; import DeleteSentDocumentModal from "./DeleteSentDocumentModal";
import { useMediaQuery } from "@mui/material"; import FilesNotary from "@Front/Api/LeCoffreApi/Notary/FilesNotary/Files";
type IProps = { type IProps = {
documents: Document[]; documents: Document[];
documentsNotary: DocumentNotary[];
folderUid: string; folderUid: string;
}; };
@ -31,7 +34,7 @@ const tradDocumentStatus: Record<EDocumentStatus, string> = {
}; };
export default function DocumentTables(props: IProps) { export default function DocumentTables(props: IProps) {
const { documents: documentsProps, folderUid } = props; const { documents: documentsProps, folderUid, documentsNotary } = props;
const [documents, setDocuments] = useState<Document[]>(documentsProps); const [documents, setDocuments] = useState<Document[]>(documentsProps);
const [documentUid, setDocumentUid] = useState<string | null>(null); const [documentUid, setDocumentUid] = useState<string | null>(null);
@ -79,6 +82,23 @@ export default function DocumentTables(props: IProps) {
.catch((e) => console.warn(e)); .catch((e) => console.warn(e));
}, []); }, []);
const onDownloadFileNotary = useCallback((doc: DocumentNotary) => {
const file = doc.files?.[0];
if (!file || !file?.uid) return;
return FilesNotary.getInstance()
.download(file.uid)
.then((blob) => {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = file.file_name ?? "file";
a.click();
URL.revokeObjectURL(url);
})
.catch((e) => console.warn(e));
}, []);
const askedDocuments: IRowProps[] = useMemo( const askedDocuments: IRowProps[] = useMemo(
() => () =>
documents documents
@ -190,27 +210,25 @@ export default function DocumentTables(props: IProps) {
[documents], [documents],
); );
//TODO: modify accordingly when the back will handle sent documents
const sentDocuments: IRowProps[] = useMemo( const sentDocuments: IRowProps[] = useMemo(
() => () =>
documents documentsNotary
.map((document) => { .map((document) => {
if (document.document_status !== "sent") return null;
return { return {
key: document.uid, key: document.uid,
document_type: document.document_type?.name ?? "_", document_type: document.files?.[0]?.file_name?.split(".")?.[0] ?? "_",
document_status: <Tag color={ETagColor.ERROR} variant={ETagVariant.SEMI_BOLD} label={"Envoyé"} />, document_status: <Tag color={ETagColor.NEUTRAL} variant={ETagVariant.SEMI_BOLD} label={"ENVOYÉ"} />,
date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_", date: document.updated_at ? new Date(document.updated_at).toLocaleDateString() : "_",
actions: ( actions: (
<div className={classes["actions"]}> <div className={classes["actions"]}>
<IconButton onClick={() => onDownload(document)} icon={<ArrowDownTrayIcon />} /> <IconButton onClick={() => onDownloadFileNotary(document)} icon={<ArrowDownTrayIcon />} />
<IconButton icon={<TrashIcon onClick={() => openDeleteSentDocumentModal(document.uid)} />} /> <IconButton icon={<TrashIcon onClick={() => openDeleteSentDocumentModal(document.uid)} />} />
</div> </div>
), ),
}; };
}) })
.filter((document) => document !== null) as IRowProps[], .filter((document) => document !== null) as IRowProps[],
[documents, onDownload, openDeleteSentDocumentModal], [documentsNotary, onDownloadFileNotary, openDeleteSentDocumentModal],
); );
const progress = useMemo(() => { const progress = useMemo(() => {
@ -219,13 +237,9 @@ export default function DocumentTables(props: IProps) {
return (validatedDocuments.length / total) * 100; return (validatedDocuments.length / total) * 100;
}, [askedDocuments.length, refusedDocuments.length, toValidateDocuments.length, validatedDocuments.length]); }, [askedDocuments.length, refusedDocuments.length, toValidateDocuments.length, validatedDocuments.length]);
const handleDelete = useCallback( const handleDelete = useCallback((_documentUid: string) => {
(documentUid: string) => {
setDocuments(documents.filter((document) => document.uid !== documentUid));
window.location.reload(); window.location.reload();
}, }, []);
[documents],
);
return ( return (
<div className={classes["root"]}> <div className={classes["root"]}>

View File

@ -22,11 +22,10 @@ export default function ReminderModal(props: IProps) {
const [isAllSelected, setIsAllSelected] = useState(false); const [isAllSelected, setIsAllSelected] = useState(false);
const onRemind = useCallback(() => { const onRemind = useCallback(() => {
console.log("selectedOptions", selectedOptions);
Customers.getInstance().sendReminder(customer.uid!, selectedOptions.map((option) => option.value) as string[]); Customers.getInstance().sendReminder(customer.uid!, selectedOptions.map((option) => option.value) as string[]);
onRemindSuccess(); onRemindSuccess();
onClose?.(); onClose?.();
}, [onClose, onRemindSuccess, selectedOptions]); }, [customer.uid, onClose, onRemindSuccess, selectedOptions]);
const documentsOptions: IOption[] = useMemo( const documentsOptions: IOption[] = useMemo(
() => () =>

View File

@ -1,3 +1,4 @@
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 Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Button, { EButtonSize, EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
import Tabs from "@Front/Components/Elements/Tabs"; import Tabs from "@Front/Components/Elements/Tabs";
@ -6,8 +7,9 @@ import { DocumentIcon, UserPlusIcon } from "@heroicons/react/24/outline";
import Customer from "le-coffre-resources/dist/Customer"; import Customer 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 { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import { DocumentNotary } from "le-coffre-resources/dist/Notary";
import Link from "next/link"; import Link from "next/link";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { AnchorStatus } from ".."; import { AnchorStatus } from "..";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
@ -25,6 +27,7 @@ export type ICustomer = Customer & { id: string };
export default function ClientView(props: IProps) { export default function ClientView(props: IProps) {
const { folder, anchorStatus } = props; const { folder, anchorStatus } = props;
const [documentsNotary, setDocumentsNotary] = useState<DocumentNotary[]>([]);
const customers: ICustomer[] = useMemo( const customers: ICustomer[] = useMemo(
() => () =>
@ -74,6 +77,12 @@ export default function ClientView(props: IProps) {
[folder], [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 ( return (
<section className={classes["root"]}> <section className={classes["root"]}>
<div className={classes["tab-container"]}> <div className={classes["tab-container"]}>
@ -123,8 +132,8 @@ export default function ClientView(props: IProps) {
</div> </div>
</div> </div>
{doesCustomerHaveDocument ? ( {doesCustomerHaveDocument || documentsNotary.length > 0 ? (
<DocumentTables documents={customer.documents ?? []} folderUid={folder?.uid ?? ""} /> <DocumentTables documents={customer.documents ?? []} documentsNotary={documentsNotary} folderUid={folder?.uid ?? ""} />
) : ( ) : (
<NoDocument /> <NoDocument />
)} )}

View File

@ -1,4 +1,5 @@
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 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 AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect";
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
@ -15,95 +16,62 @@ 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 DocumentsNotary from "@Front/Api/LeCoffreApi/Notary/DocumentsNotary/DocumentsNotary";
enum EClientSelection { enum EClientSelection {
ALL_CLIENTS = "all_clients", ALL_CLIENTS = "all_clients",
SELECTED_CLIENTS = "selected_clients", SELECTED_CLIENTS = "selected_clients",
} }
// type IDocumentFileBase = {
// id: string;
// file: File | null;
// uid?: string;
// isLoading?: boolean;
// error?: string;
// };
// export type IDocumentFileWithUid = IDocumentFileBase & {
// uid: string;
// };
// type IDocumentFile = IDocumentFileBase | IDocumentFileWithUid;
export default function SendDocuments() { export default function SendDocuments() {
const router = useRouter(); const router = useRouter();
let { folderUid } = router.query; let { folderUid } = router.query;
const [folder, setFolder] = useState<OfficeFolder | null>(null); const [folder, setFolder] = useState<OfficeFolder | null>(null);
const [clientSelection, setClientSelection] = useState<EClientSelection | null>(EClientSelection.SELECTED_CLIENTS); const [clientSelection, setClientSelection] = useState<EClientSelection | null>(null);
const [selectedClients, setSelectedClients] = useState<string[]>([]); const [selectedClients, setSelectedClients] = useState<string[]>([]);
const [files, setFiles] = useState<File[]>([]); const [files, setFiles] = useState<File[]>([]);
const onFormSubmit = useCallback( const onFormSubmit = useCallback(
async ( async (
_e: React.FormEvent<HTMLFormElement> | null, _e: React.FormEvent<HTMLFormElement> | null,
values: { _values: {
[key: string]: any; [key: string]: any;
}, },
//TODO: when back is done
) => { ) => {
if (folder?.customers && clientSelection === EClientSelection.ALL_CLIENTS) { if (!files.length) {
const allClientIds = folder.customers.map((customer) => customer.uid ?? "");
setSelectedClients(allClientIds);
}
const formData = new FormData();
console.log("files", files);
// get the files from the input which name is "files"
// console.log({ values });
// const files: File[] = values["files"];
// console.log({ files });
selectedClients.forEach(async (customer) => {
formData.append("customerUid", customer as string);
formData.append("folderUid", folderUid as string);
if (!files[0]) {
console.error("No files to send"); console.error("No files to send");
return; return;
} }
formData.append("file", files[0]);
const documentNotary = await DocumentsNotary.getInstance().post(formData); try {
console.log(documentNotary); await Promise.all(
selectedClients.map(async (customer) => {
const promises = files.map(async (file) => {
const formData = new FormData();
formData.append("customerUid", customer as string);
formData.append("folderUid", folderUid as string);
formData.append("name", file.name);
formData.append("file", file);
// Envoi de chaque fichier pour chaque client
return DocumentsNotary.getInstance().post(formData);
}); });
// const formData = new FormData();
// files.forEach((file) => { // Attendre que tous les fichiers pour un client soient envoyés
// if (file.file) { await Promise.all(promises);
// formData.append("file", file.file); }),
// } );
// }); router.push(
// selectedClients.forEach((client) => { Module.getInstance()
// formData.append("customers", client); .get()
// }); .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string),
// formData.append("folder", folderUid as string); );
// const documentNotary = await DocumentsNotary.getInstance().post(formData); console.log("All files have been successfully sent.");
// console.log(documentNotary); } catch (error) {
}, console.error("Error while sending files: ", error);
[clientSelection, selectedClients, files], }
},
[files, folderUid, router, selectedClients],
); );
// const onAddToList = useCallback((documentFile: IDocumentFile) => {
// const test = files;
// test.push(documentFile);
// setFiles(test);
// }, []);
// const onRemoveFromList = useCallback((documentFile: IDocumentFile) => {
// const test = files;
// const index = test.findIndex((doc) => doc.id === documentFile.id);
// if (index === -1) return;
// test.splice(index, 1);
// setFiles(test);
// }, []);
const fetchFolder = useCallback(async () => { const fetchFolder = useCallback(async () => {
Folders.getInstance() Folders.getInstance()
@ -126,11 +94,9 @@ export default function SendDocuments() {
setClientSelection(selection); setClientSelection(selection);
if (selection === EClientSelection.ALL_CLIENTS && folder?.customers) { if (selection === EClientSelection.ALL_CLIENTS && folder?.customers) {
// Automatically select all customers
const allClientIds = folder.customers.map((customer) => customer.uid ?? ""); const allClientIds = folder.customers.map((customer) => customer.uid ?? "");
setSelectedClients(allClientIds); setSelectedClients(allClientIds);
} else { } else {
// Clear selected clients when selecting "Sélectionner certains clients"
setSelectedClients([]); setSelectedClients([]);
} }
}, },
@ -143,11 +109,7 @@ export default function SendDocuments() {
useEffect(() => { useEffect(() => {
fetchFolder(); fetchFolder();
if (folder?.customers && clientSelection === EClientSelection.ALL_CLIENTS) { }, [fetchFolder]);
const allClientIds = folder.customers.map((customer) => customer.uid ?? "");
setSelectedClients(allClientIds);
}
}, []);
const backUrl = useMemo( const backUrl = useMemo(
() => () =>
@ -191,7 +153,6 @@ export default function SendDocuments() {
value={EClientSelection.SELECTED_CLIENTS} value={EClientSelection.SELECTED_CLIENTS}
label="Sélectionner certains clients" label="Sélectionner certains clients"
onChange={onClientSelectionChange} onChange={onClientSelectionChange}
defaultChecked
/> />
</div> </div>

View File

@ -30,7 +30,6 @@ export default function Folder() {
}, },
}) })
.then((folders) => { .then((folders) => {
console.log(folders);
if (folders.length > 0) if (folders.length > 0)
router.push( router.push(
Module.getInstance() Module.getInstance()