354 lines
11 KiB
TypeScript
354 lines
11 KiB
TypeScript
import backgroundImage from "@Assets/images/404-background-image.jpeg";
|
|
import DeedTypes from "@Front/Api/LeCoffreApi/SuperAdmin/DeedTypes/DeedTypes";
|
|
import Folders from "@Front/Api/LeCoffreApi/SuperAdmin/Folders/Folders";
|
|
import Users from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users";
|
|
import Button from "@Front/Components/DesignSystem/Button";
|
|
import Form from "@Front/Components/DesignSystem/Form";
|
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
|
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
|
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
|
import { Deed, DeedType, Office, OfficeFolder, OfficeFolderHasStakeholder } from "le-coffre-resources/dist/Notary";
|
|
|
|
import User from "le-coffre-resources/dist/Notary";
|
|
import { NextRouter, useRouter } from "next/router";
|
|
import React from "react";
|
|
import { ActionMeta, MultiValue } from "react-select";
|
|
|
|
import BasePage from "../../Base";
|
|
import classes from "./classes.module.scss";
|
|
import { ValidationError } from "class-validator";
|
|
import SelectField, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
|
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
|
|
|
type IFormValues = {
|
|
folder_number: string;
|
|
entitled: string;
|
|
act_typ: IOption | null;
|
|
personal_note: string;
|
|
collaborators: MultiValue<IOption>;
|
|
};
|
|
|
|
type IProps = {};
|
|
|
|
type IPropsClass = IProps & {
|
|
router: NextRouter;
|
|
};
|
|
|
|
type IState = {
|
|
folder_access: string;
|
|
formValues: IFormValues;
|
|
deedTypes: DeedType[];
|
|
deedTypesOptions: IOption[];
|
|
collaborators: User[];
|
|
collaboratorsOptions: IOption[];
|
|
validationError: ValidationError[];
|
|
};
|
|
class CreateFolderClass extends BasePage<IPropsClass, IState> {
|
|
public constructor(props: IPropsClass) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
folder_access: "",
|
|
formValues: {
|
|
folder_number: "",
|
|
entitled: "",
|
|
act_typ: null,
|
|
personal_note: "",
|
|
collaborators: [],
|
|
},
|
|
deedTypes: [],
|
|
deedTypesOptions: [],
|
|
collaborators: [],
|
|
collaboratorsOptions: [],
|
|
validationError: [],
|
|
};
|
|
|
|
this.radioOnChange = this.radioOnChange.bind(this);
|
|
this.onFolderNumberChange = this.onFolderNumberChange.bind(this);
|
|
this.onEntitleChange = this.onEntitleChange.bind(this);
|
|
this.onActTypeChange = this.onActTypeChange.bind(this);
|
|
this.onPersonalNoteChange = this.onPersonalNoteChange.bind(this);
|
|
this.onCollaboratorsChange = this.onCollaboratorsChange.bind(this);
|
|
this.isFormSubmittable = this.isFormSubmittable.bind(this);
|
|
this.onFormSubmit = this.onFormSubmit.bind(this);
|
|
}
|
|
|
|
public override render(): JSX.Element {
|
|
return (
|
|
<DefaultDoubleSidePage title={"Dossier"} image={backgroundImage} type="background" showHeader={true}>
|
|
<div className={classes["root"]}>
|
|
<BackArrow />
|
|
<Typography typo={ITypo.H1} color={ITypoColor.BLACK} className={classes["title"]}>
|
|
Créer un dossier
|
|
</Typography>
|
|
<Typography typo={ITypo.H3} color={ITypoColor.PURPLE_FLASH} className={classes["subtitle"]}>
|
|
Informations dossier
|
|
</Typography>
|
|
<Form onSubmit={this.onFormSubmit}>
|
|
<div className={classes["form-container"]}>
|
|
<TextField
|
|
name="folder_number"
|
|
placeholder="Numéro de dossier"
|
|
onChange={this.onFolderNumberChange}
|
|
validationError={this.state.validationError.find((error) => error.property === "folder_number")}
|
|
/>
|
|
<TextField
|
|
name="name"
|
|
placeholder="Intitulé"
|
|
onChange={this.onEntitleChange}
|
|
validationError={this.state.validationError.find((error) => error.property === "name")}
|
|
/>
|
|
<SelectField
|
|
options={this.state.deedTypesOptions}
|
|
placeholder={"Type d'acte"}
|
|
onChange={this.onActTypeChange}
|
|
errors={this.state.validationError.find((error) => error.property === "deed")}
|
|
/>
|
|
<TextAreaField
|
|
name="description"
|
|
placeholder="Note du dossier"
|
|
onChange={this.onPersonalNoteChange}
|
|
validationError={this.state.validationError.find((error) => error.property === "description")}
|
|
/>
|
|
</div>
|
|
<div className={classes["access-container"]}>
|
|
<Typography typo={ITypo.H3} color={ITypoColor.PURPLE_FLASH}>
|
|
Accès au dossier
|
|
</Typography>
|
|
<div className={classes["radio-container"]}>
|
|
<RadioBox name="file_access" defaultChecked onChange={this.radioOnChange} value="whole_office">
|
|
Sélectionner tout l'office
|
|
</RadioBox>
|
|
<RadioBox name="file_access" onChange={this.radioOnChange} value="select_collaborators">
|
|
Sélectionner certains collaborateurs
|
|
</RadioBox>
|
|
</div>
|
|
{this.state.folder_access === "select_collaborators" && (
|
|
<div className={classes["collaborators-container"]}>
|
|
<MultiSelect
|
|
options={this.state.collaboratorsOptions}
|
|
placeholder="Sélectionner les collaborateurs"
|
|
onChange={this.onCollaboratorsChange}
|
|
defaultValue={this.state.formValues.collaborators ?? []}
|
|
/>
|
|
</div>
|
|
)}
|
|
<div className={classes["buttons-container"]}>
|
|
<Button fullwidth type="submit">
|
|
Créer un dossier
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
</DefaultDoubleSidePage>
|
|
);
|
|
}
|
|
|
|
public override async componentDidMount() {
|
|
const deedTypes = await DeedTypes.getInstance().get({ q: {} });
|
|
|
|
// TODO SETUP userStore and get the user's office membership -> Replace IwJ70M471c by the user's office membership uid
|
|
const usersMock = await Users.getInstance().get({ include: { office_membership: true } });
|
|
const userMock = usersMock[0];
|
|
// -------------------
|
|
const collaborators = await Users.getInstance().get({
|
|
where: { office_membership: { uid: userMock?.office_membership?.uid } },
|
|
include: { contact: true },
|
|
});
|
|
this.setState({
|
|
deedTypes,
|
|
deedTypesOptions: this.mapDeedOptions(deedTypes),
|
|
collaborators,
|
|
collaboratorsOptions: this.mapUsersOptions(collaborators),
|
|
});
|
|
}
|
|
|
|
private mapDeedOptions(deedTypes: DeedType[]) {
|
|
return deedTypes.map((deedType) => ({
|
|
label: deedType.name,
|
|
value: deedType.uid,
|
|
})) as IOption[];
|
|
}
|
|
|
|
private mapUsersOptions(collaborators: User[]) {
|
|
return collaborators.map((collaborator) => ({
|
|
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name),
|
|
value: collaborator.uid,
|
|
})) as IOption[];
|
|
}
|
|
|
|
private onFolderNumberChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) {
|
|
this.setState({
|
|
formValues: {
|
|
...this.state.formValues,
|
|
folder_number: e.target.value,
|
|
},
|
|
});
|
|
}
|
|
|
|
private onEntitleChange(e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) {
|
|
this.setState({
|
|
formValues: {
|
|
...this.state.formValues,
|
|
entitled: e.target.value,
|
|
},
|
|
});
|
|
}
|
|
|
|
private onActTypeChange(selectedOption: IOption) {
|
|
this.setState({
|
|
formValues: {
|
|
...this.state.formValues,
|
|
act_typ: selectedOption,
|
|
},
|
|
});
|
|
}
|
|
|
|
private onPersonalNoteChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) {
|
|
this.setState({
|
|
formValues: {
|
|
...this.state.formValues,
|
|
personal_note: e.target.value,
|
|
},
|
|
});
|
|
}
|
|
|
|
private onCollaboratorsChange(newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) {
|
|
this.setState({
|
|
formValues: {
|
|
...this.state.formValues,
|
|
collaborators: newValue,
|
|
},
|
|
});
|
|
}
|
|
|
|
private async onFormSubmit(
|
|
e: React.FormEvent<HTMLFormElement> | null,
|
|
values: {
|
|
[key: string]: any;
|
|
},
|
|
) {
|
|
const selectedDeedTypeUid: DeedType | undefined = this.state.deedTypes.find(
|
|
(deedType) => deedType.uid === this.state.formValues.act_typ?.value,
|
|
);
|
|
|
|
/**
|
|
* MOCK DATA
|
|
*/
|
|
const usersMock = await Users.getInstance().get({ include: { office_membership: true } });
|
|
const userMock = usersMock[0];
|
|
|
|
let stakeholders = this.getStakeholders();
|
|
let testUsers = stakeholders.map((stakeholder) => ({
|
|
user_stakeholder: {
|
|
uid: stakeholder.user_stakeholder.uid,
|
|
},
|
|
}));
|
|
|
|
const officeFolderForm = OfficeFolder.hydrate<OfficeFolder>({
|
|
folder_number: values["folder_number"],
|
|
name: values["name"],
|
|
description: values["description"],
|
|
deed: Deed.hydrate<Deed>({
|
|
deed_type: DeedType.hydrate<DeedType>({
|
|
uid: selectedDeedTypeUid?.uid,
|
|
}),
|
|
}),
|
|
office: Office.hydrate<Office>({
|
|
uid: userMock?.office_membership?.uid,
|
|
}),
|
|
office_folder_has_stakeholder: testUsers.map((user) => {
|
|
return OfficeFolderHasStakeholder.hydrate<OfficeFolderHasStakeholder>({
|
|
user_stakeholder: User.hydrate<User>({
|
|
uid: user.user_stakeholder.uid,
|
|
}),
|
|
});
|
|
}),
|
|
});
|
|
|
|
try {
|
|
await officeFolderForm.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false });
|
|
} catch (validationErrors) {
|
|
console.log(validationErrors);
|
|
this.setState({
|
|
validationError: validationErrors as ValidationError[],
|
|
});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const newOfficeFolder = await Folders.getInstance().post(officeFolderForm);
|
|
if (!newOfficeFolder) return;
|
|
this.props.router.push(`/folders/${newOfficeFolder.uid}`);
|
|
} catch (backError: any) {
|
|
if(backError.target && backError.property){
|
|
|
|
this.setState({
|
|
validationError: backError as ValidationError[],
|
|
});
|
|
}else{
|
|
console.error(backError);
|
|
this.setState({
|
|
validationError: [{
|
|
constraints: {
|
|
unique: "Le numéro de dossier est déjà utilisé"
|
|
},
|
|
property: "folder_number",
|
|
} as ValidationError],
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
private isFormSubmittable(): boolean {
|
|
if (
|
|
this.state.formValues.entitled === "" ||
|
|
this.state.formValues.personal_note === "" ||
|
|
this.state.formValues.folder_number === "" ||
|
|
this.state.formValues.act_typ === null
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if (this.state.folder_access === "select_collaborators" && this.state.formValues.collaborators.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private radioOnChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
this.setState({
|
|
folder_access: e.target.value,
|
|
});
|
|
}
|
|
|
|
private getStakeholders() {
|
|
let collaborators: User[] = this.state.collaborators;
|
|
|
|
let office_folder_has_stakeholders = collaborators.map((collaborator) => {
|
|
return OfficeFolderHasStakeholder.hydrate<OfficeFolderHasStakeholder>({
|
|
user_stakeholder: collaborator,
|
|
});
|
|
});
|
|
|
|
if (this.state.folder_access === "select_collaborators") {
|
|
office_folder_has_stakeholders = office_folder_has_stakeholders.filter((collaborator) => {
|
|
return this.state.formValues.collaborators?.some((selectedCollaborator) => {
|
|
return selectedCollaborator.value === collaborator.user_stakeholder.uid;
|
|
});
|
|
});
|
|
}
|
|
return office_folder_has_stakeholders;
|
|
}
|
|
}
|
|
|
|
export default function CreateFolder(props: IProps): JSX.Element {
|
|
const router = useRouter();
|
|
return <CreateFolderClass {...props} router={router} />;
|
|
}
|