2025-07-08 15:53:01 +02:00

253 lines
8.8 KiB
TypeScript

import backgroundImage from "@Assets/images/background_refonte.svg";
import Button from "@Front/Components/DesignSystem/Button";
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
import Form from "@Front/Components/DesignSystem/Form";
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
import SelectField from "@Front/Components/DesignSystem/Form/SelectField";
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
import TextField from "@Front/Components/DesignSystem/Form/TextField";
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
import { ToasterService } from "@Front/Components/DesignSystem/Toaster";
import BackArrow from "@Front/Components/Elements/BackArrow";
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
import JwtService from "@Front/Services/JwtService/JwtService";
import { ValidationError } from "class-validator/types/validation/ValidationError";
import { Deed, Office, OfficeFolder } from "le-coffre-resources/dist/Notary";
import User from "le-coffre-resources/dist/Notary";
import EFolderStatus from "le-coffre-resources/dist/Customer/EFolderStatus";
import { DeedType } from "le-coffre-resources/dist/Notary";
import { useRouter } from "next/router";
import React, { useCallback, useEffect, useState } from "react";
import classes from "./classes.module.scss";
import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService";
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
export default function CreateFolder(): JSX.Element {
/**
* State
*/
const [folderAccessType, setFolderAccessType] = useState<"whole_office" | "select_collaborators">("select_collaborators");
const [availableDeedTypes, setAvailableDeedTypes] = useState<DeedType[]>([]);
const [availableCollaborators, setAvailableCollaborators] = useState<User[]>([]);
const [validationError, setValidationError] = useState<ValidationError[]>([]);
const [selectedCollaborators, setSelectedCollaborators] = useState<User[]>([]);
/**
* Hooks call
*/
const router = useRouter();
/**
* Callbacks
*/
const onFormSubmit = async (
e: React.FormEvent<HTMLFormElement> | null,
values: {
[key: string]: any;
},
) => {
// TODO: review
console.log(JwtService.getInstance().decodeJwt());
const officeId = 'demo_notary_office_id'; //JwtService.getInstance().decodeJwt()?.office_Id;
const officeFolderModel = OfficeFolder.hydrate<OfficeFolder>({
folder_number: values["folder_number"],
name: values["name"],
description: values["description"],
deed: Deed.hydrate<Deed>({
deed_type: DeedType.hydrate<DeedType>({
uid: values["deed"],
}),
}),
office: Office.hydrate<Office>({
uid: officeId,
}),
customers: [],
stakeholders: folderAccessType === "whole_office" ? availableCollaborators : selectedCollaborators,
});
try {
await officeFolderModel.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: true });
} catch (validationErrors) {
setValidationError(validationErrors as ValidationError[]);
return;
}
try {
const folderData: any = {
folder_number: values["folder_number"],
name: values["name"],
deed: {
deed_type: {
uid: values["deed"],
}
},
description: values["description"],
office: {
uid: officeId
},
customers: [],
documents: [],
notes: [],
stakeholders: folderAccessType === "whole_office" ? availableCollaborators : selectedCollaborators,
status: EFolderStatus.LIVE
};
LoaderService.getInstance().show();
FolderService.createFolder(folderData, [], []).then((processCreated: any) => {
ToasterService.getInstance().success({
title: "Succès !",
description: "Dossier créé avec succès"
});
const folderUid: string = processCreated.processData.uid;
router.push(`/folders/${folderUid}`);
LoaderService.getInstance().hide();
});
} catch (backError) {
if (!Array.isArray(backError)) return;
setValidationError(backError as ValidationError[]);
return;
}
};
const radioOnChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setFolderAccessType(e.target.value as "whole_office" | "select_collaborators");
const onSelectedCollaboratorsChange = useCallback(
(options: IOption[] | null) => {
if (!options) return;
const collaborators = availableCollaborators.filter((collaborator) => options.find((option) => option.id === collaborator.uid));
setSelectedCollaborators(collaborators);
},
[availableCollaborators],
);
/**
* UseEffect
*/
useEffect(() => {
DeedTypeService.getDeedTypes().then((processes: any[]) => {
if (processes.length > 0) {
let deedTypes: any[] = processes.map((process: any) => process.processData);
// FilterBy archived_at = null or not defined
deedTypes = deedTypes.filter((deedType: any) => !deedType.archived_at);
setAvailableDeedTypes(deedTypes);
}
});
/* TODO: review
// no need to pass query 'where' param here, default query for notaries include only users which are in the same office as the caller
Users.getInstance()
.get({
include: { contact: true },
})
.then((users) => {
setAvailableCollaborators(users);
/ *
// set default selected collaborators to the connected user
const currentUser = users.find((user) => user.uid === JwtService.getInstance().decodeJwt()?.userId);
if (currentUser) {
setSelectedCollaborators([currentUser]);
}
* /
});
*/
}, []);
/**
* Renderer
*/
return (
<DefaultDoubleSidePage title={"Dossier"} image={backgroundImage} type="background" showHeader={true}>
<div className={classes["root"]}>
<BackArrow />
<div className={classes["header"]}>
<Typography typo={ETypo.DISPLAY_LARGE} color={ETypoColor.COLOR_GENERIC_BLACK} className={classes["title"]}>
Créer un dossier
</Typography>
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.COLOR_PRIMARY_500} className={classes["subtitle"]}>
Informations du dossier
</Typography>
</div>
<Form onSubmit={onFormSubmit} className={classes["form"]}>
<TextField
name="folder_number"
label="Numéro de dossier"
placeholder="Entrer le numéro de dossier"
validationError={validationError.find((error) => error.property === "folder_number")}
/>
<TextField
name="name"
label="Intitulé"
placeholder="Entrer l'intitulé du dossier"
validationError={validationError.find((error) => error.property === "name")}
/>
<SelectField
name="deed"
label="Type d'acte"
placeholder="Sélectionner un type d'acte"
options={
availableDeedTypes.map((deedType) => ({
id: deedType.uid,
label: deedType.name,
})) as IOption[]
}
validationError={validationError.find((error) => error.property === "deed")}
/>
<TextAreaField
name="description"
label="Note de dossier"
placeholder="Renseigner une note"
validationError={validationError.find((error) => error.property === "description")}
required={false}
/>
<div className={classes["bottom-container"]}>
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.COLOR_PRIMARY_500}>
Donner l'accès au dossier
</Typography>
<div className={classes["radio-container"]}>
<RadioBox name="file_access" onChange={radioOnChange} value="whole_office" label="Sélectionner tout l'office" />
<RadioBox
name="file_access"
defaultChecked
onChange={radioOnChange}
value="select_collaborators"
label="Sélectionner certains collaborateurs"
/>
</div>
{folderAccessType === "select_collaborators" && (
<div className={classes["collaborators-container"]}>
<AutocompleteMultiSelectField
label="Sélectionner les collaborateurs"
options={availableCollaborators.map((collaborator) => ({
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "",
id: collaborator.uid ?? "",
}))}
selectedOptions={selectedCollaborators.map((collaborator) => ({
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "",
id: collaborator.uid ?? "",
}))}
onSelectionChange={onSelectedCollaboratorsChange}
validationError={validationError.find((error) => error.property === "stakeholders")}
/>
</div>
)}
<div className={classes["buttons-container"]}>
<Button type="submit">Créer le dossier</Button>
</div>
</div>
</Form>
</div>
</DefaultDoubleSidePage>
);
}