Merge branch 'dev-without-id-not' into dev
This commit is contained in:
commit
26d597411f
@ -75,6 +75,11 @@ class FolderListContainerClass extends React.Component<IPropsClass, IState> {
|
||||
);
|
||||
}
|
||||
|
||||
public override componentDidUpdate(prevProps: Readonly<IPropsClass>, prevState: Readonly<IState>, snapshot?: any): void {
|
||||
if (prevProps.selectedFolder !== this.props.selectedFolder) {
|
||||
this.setState({ filteredFolders: this.props.folders, blocks: this.getBlocks(this.props.folders) });
|
||||
}
|
||||
}
|
||||
private getBlocks(folders: OfficeFolder[]): IBlock[] {
|
||||
const pendingFolders = folders
|
||||
.filter((folder) => {
|
||||
|
@ -0,0 +1,102 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
position: relative;
|
||||
|
||||
.input {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 24px;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
border: 1px solid var(--grey-medium);
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
~ .fake-placeholder {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
}
|
||||
|
||||
&:not([data-value=""]) {
|
||||
~ .fake-placeholder {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
}
|
||||
|
||||
&[type="number"] {
|
||||
&:focus {
|
||||
~ .fake-placeholder {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
}
|
||||
|
||||
&:not([data-value=""]) {
|
||||
~ .fake-placeholder {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-inner-spin-button,
|
||||
&::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* For Chrome, Safari, and Opera */
|
||||
&::-webkit-inner-spin-button,
|
||||
&::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* For IE 10+ */
|
||||
&::-ms-inner-spin-button,
|
||||
&::-ms-outer-spin-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:not([data-value=""]) {
|
||||
~ .fake-placeholder {
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
}
|
||||
|
||||
~ .fake-placeholder {
|
||||
z-index: 2;
|
||||
top: 35%;
|
||||
margin-left: 8px;
|
||||
padding: 0 16px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
background: $white;
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-is-errored="true"] {
|
||||
.input {
|
||||
border: 1px solid var(--red-flash);
|
||||
~ .fake-placeholder {
|
||||
color: var(--red-flash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 24px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
56
src/front/Components/DesignSystem/Form/DateField/index.tsx
Normal file
56
src/front/Components/DesignSystem/Form/DateField/index.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import React from "react";
|
||||
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
import { ReactNode } from "react";
|
||||
import CopyIcon from "@Assets/Icons/copy.svg";
|
||||
import BaseField, { IProps as IBaseFieldProps } from "../BaseField";
|
||||
import classes from "./classes.module.scss";
|
||||
import classnames from "classnames";
|
||||
import Image from "next/image";
|
||||
|
||||
export type IProps = IBaseFieldProps & {
|
||||
canCopy?: boolean;
|
||||
};
|
||||
|
||||
export default class DateField extends BaseField<IProps> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = this.getDefaultState();
|
||||
}
|
||||
|
||||
public override render(): ReactNode {
|
||||
const value = this.state.value ?? "";
|
||||
return (
|
||||
<Typography typo={ITypo.NAV_INPUT_16} color={ITypoColor.GREY}>
|
||||
<div className={classes["root"]} data-is-errored={this.hasError().toString()}>
|
||||
<input
|
||||
onChange={this.onChange}
|
||||
data-value={value}
|
||||
data-has-validation-errors={(this.state.validationError === null).toString()}
|
||||
className={classnames(classes["input"], this.props.className)}
|
||||
value={value}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
name={this.props.name}
|
||||
disabled={this.props.disabled}
|
||||
type={"date"}
|
||||
/>
|
||||
<div className={classes["fake-placeholder"]}>
|
||||
{this.props.placeholder} {!this.props.required && " (Facultatif)"}
|
||||
</div>
|
||||
{this.props.canCopy && (
|
||||
<div className={classes["copy-icon"]} onClick={this.onCopyClick}>
|
||||
<Image src={CopyIcon} alt="Copy icon" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{this.hasError() && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
private onCopyClick = (): void => {
|
||||
if (this.props.canCopy) {
|
||||
navigator.clipboard.writeText(this.state.value ?? "");
|
||||
}
|
||||
};
|
||||
}
|
@ -7,6 +7,7 @@ import React, { FormEvent, ReactNode } from "react";
|
||||
|
||||
import Typography, { ITypo, ITypoColor } from "../../Typography";
|
||||
import classes from "./classes.module.scss";
|
||||
import { NextRouter, useRouter } from "next/router";
|
||||
|
||||
type IProps = {
|
||||
selectedOption?: IOption;
|
||||
@ -16,7 +17,7 @@ type IProps = {
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
name: string;
|
||||
disabled: boolean;
|
||||
disabled?: boolean;
|
||||
errors?: ValidationError;
|
||||
};
|
||||
|
||||
@ -35,7 +36,11 @@ type IState = {
|
||||
errors: ValidationError | null;
|
||||
};
|
||||
|
||||
export default class SelectField extends React.Component<IProps, IState> {
|
||||
type IPropsClass = IProps & {
|
||||
router: NextRouter;
|
||||
};
|
||||
|
||||
class SelectFieldClass extends React.Component<IPropsClass, IState> {
|
||||
private contentRef = React.createRef<HTMLUListElement>();
|
||||
private rootRef = React.createRef<HTMLDivElement>();
|
||||
private removeOnresize = () => {};
|
||||
@ -44,7 +49,7 @@ export default class SelectField extends React.Component<IProps, IState> {
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
constructor(props: IProps) {
|
||||
constructor(props: IPropsClass) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
@ -64,7 +69,7 @@ export default class SelectField extends React.Component<IProps, IState> {
|
||||
<div
|
||||
className={classNames(classes["root"], this.props.className)}
|
||||
ref={this.rootRef}
|
||||
data-disabled={this.props.disabled.toString()}
|
||||
data-disabled={this.props.disabled?.toString()}
|
||||
data-errored={(this.state.errors !== null).toString()}>
|
||||
{selectedOption && <input type="text" defaultValue={selectedOption.value as string} name={this.props.name} hidden />}
|
||||
<label
|
||||
@ -116,6 +121,23 @@ export default class SelectField extends React.Component<IProps, IState> {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
public override componentDidMount(): void {
|
||||
this.onResize();
|
||||
this.removeOnresize = WindowStore.getInstance().onResize(() => this.onResize());
|
||||
|
||||
this.props.router.events.on("routeChangeStart", () => {
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
selectedOption: null,
|
||||
listHeight: 0,
|
||||
listWidth: 0,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public override componentWillUnmount() {
|
||||
this.removeOnresize();
|
||||
}
|
||||
|
||||
public override componentDidUpdate(prevProps: IProps) {
|
||||
if (this.props.errors !== prevProps.errors) {
|
||||
@ -140,15 +162,6 @@ export default class SelectField extends React.Component<IProps, IState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public override componentDidMount(): void {
|
||||
this.onResize();
|
||||
this.removeOnresize = WindowStore.getInstance().onResize(() => this.onResize());
|
||||
}
|
||||
|
||||
public override componentWillUnmount() {
|
||||
this.removeOnresize();
|
||||
}
|
||||
|
||||
private onResize() {
|
||||
let listHeight = 0;
|
||||
let listWidth = 0;
|
||||
@ -192,3 +205,8 @@ export default class SelectField extends React.Component<IProps, IState> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function SelectField(props: IProps) {
|
||||
const router = useRouter();
|
||||
return <SelectFieldClass {...props} router={router} />;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useCallback, useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import Module from "@Front/Config/Module";
|
||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
||||
import { IAppRule } from "@Front/Api/Entities/rule";
|
||||
import { useRouter } from "next/router";
|
||||
import Module from "@Front/Config/Module";
|
||||
|
||||
export enum RulesMode {
|
||||
OPTIONAL = "optional",
|
||||
@ -10,16 +10,18 @@ export enum RulesMode {
|
||||
}
|
||||
|
||||
type IProps = {
|
||||
isPage?: boolean;
|
||||
mode: RulesMode;
|
||||
rules: IAppRule[];
|
||||
no?: boolean;
|
||||
children: JSX.Element;
|
||||
isPage?: boolean;
|
||||
};
|
||||
|
||||
export default function Rules(props: IProps) {
|
||||
const router = useRouter();
|
||||
|
||||
const [isShowing, setIsShowing] = React.useState(false);
|
||||
const [hasJwt, setHasJwt] = React.useState(false);
|
||||
|
||||
const getShowValue = useCallback(() => {
|
||||
if (props.mode === RulesMode.NECESSARY) {
|
||||
return props.rules.every((rule) => JwtService.getInstance().hasRule(rule.name, rule.action));
|
||||
@ -27,19 +29,18 @@ export default function Rules(props: IProps) {
|
||||
return !!props.rules.find((rule) => JwtService.getInstance().hasRule(rule.name, rule.action));
|
||||
}, [props.mode, props.rules]);
|
||||
|
||||
const show = getShowValue();
|
||||
const [isShowing, setIsShowing] = React.useState(props.no ? !show : show);
|
||||
|
||||
useEffect(() => {
|
||||
setIsShowing(props.no ? !show : show);
|
||||
}, [props.no, show]);
|
||||
if (!JwtService.getInstance().decodeJwt()) return;
|
||||
setHasJwt(true);
|
||||
setIsShowing(getShowValue());
|
||||
}, [getShowValue, isShowing]);
|
||||
|
||||
if (!isShowing && props.isPage) {
|
||||
router.push(Module.getInstance().get().modules.pages.Home.props.path);
|
||||
}
|
||||
|
||||
if (!JwtService.getInstance().decodeJwt() || !isShowing) {
|
||||
if (props.isPage && !isShowing) {
|
||||
router.push(Module.getInstance().get().modules.pages[404].props.path);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!hasJwt || !isShowing) return null;
|
||||
|
||||
return props.children;
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
setRoleModalOpened(false);
|
||||
setSelectedOption({
|
||||
value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid,
|
||||
label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.name!,
|
||||
label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint",
|
||||
});
|
||||
}, [userSelected?.office_role, userSelected?.role?.name, userSelected?.role?.uid]);
|
||||
}, [userSelected?.office_role, userSelected?.role?.uid]);
|
||||
|
||||
const changeRole = useCallback(async () => {
|
||||
await Users.getInstance().put(
|
||||
@ -133,7 +133,7 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
setUserSelected(user);
|
||||
setSelectedOption({
|
||||
value: user?.office_role ? user?.office_role?.uid : user?.role?.uid,
|
||||
label: user?.office_role ? user?.office_role?.name : user?.role?.name!,
|
||||
label: user?.office_role ? user?.office_role?.name : "Utilisateur restreint",
|
||||
});
|
||||
}
|
||||
|
||||
@ -197,7 +197,6 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
})}
|
||||
selectedOption={selectedOption!}
|
||||
onChange={handleRoleChange}
|
||||
disabled={userSelected?.role?.name === "super-admin"}
|
||||
/>
|
||||
</div>
|
||||
{userSelected?.role?.name !== "super-admin" && (
|
||||
|
@ -72,6 +72,9 @@
|
||||
border: 1px solid var(--grey);
|
||||
|
||||
.container-title {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.documents {
|
||||
|
@ -19,6 +19,7 @@ import { useCallback, useEffect, useState } from "react";
|
||||
import { MultiValue } from "react-select";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import Tooltip from "@Front/Components/DesignSystem/ToolTip";
|
||||
|
||||
type IProps = {};
|
||||
export default function DeedTypesInformations(props: IProps) {
|
||||
@ -30,6 +31,7 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
const [selectedDocuments, setSelectedDocuments] = useState<IOption[]>([]);
|
||||
|
||||
const [isDeleteModalOpened, setIsDeleteModalOpened] = useState<boolean>(false);
|
||||
const [isSaveModalOpened, setIsSaveModalOpened] = useState<boolean>(false);
|
||||
|
||||
const openDeleteModal = useCallback(() => {
|
||||
setIsDeleteModalOpened(true);
|
||||
@ -39,6 +41,14 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
setIsDeleteModalOpened(false);
|
||||
}, []);
|
||||
|
||||
const openSaveModal = useCallback(() => {
|
||||
setIsSaveModalOpened(true);
|
||||
}, []);
|
||||
|
||||
const closeSaveModal = useCallback(() => {
|
||||
setIsSaveModalOpened(false);
|
||||
}, []);
|
||||
|
||||
const deleteDeedType = useCallback(async () => {
|
||||
await DeedTypes.getInstance().put(
|
||||
deedTypeUid as string,
|
||||
@ -81,14 +91,19 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
|
||||
const onSubmitHandler = useCallback(
|
||||
async (e: React.FormEvent<HTMLFormElement> | null, values: { [key: string]: string }) => {
|
||||
await DeedTypes.getInstance().put(deedTypeUid as string, {
|
||||
uid: deedTypeUid as string,
|
||||
document_types: selectedDocuments.map((document) => DocumentType.hydrate<DocumentType>({ uid: document.value as string })),
|
||||
});
|
||||
openSaveModal();
|
||||
},
|
||||
[deedTypeUid, selectedDocuments],
|
||||
[openSaveModal],
|
||||
);
|
||||
|
||||
const saveDocumentTypes = useCallback(async () => {
|
||||
await DeedTypes.getInstance().put(deedTypeUid as string, {
|
||||
uid: deedTypeUid as string,
|
||||
document_types: selectedDocuments.map((document) => DocumentType.hydrate<DocumentType>({ uid: document.value as string })),
|
||||
});
|
||||
closeSaveModal();
|
||||
}, [closeSaveModal, deedTypeUid, selectedDocuments]);
|
||||
|
||||
const onDocumentChangeHandler = useCallback((values: MultiValue<IOption>) => {
|
||||
setSelectedDocuments(values as IOption[]);
|
||||
}, []);
|
||||
@ -137,7 +152,8 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
<div className={classes["documents-container"]}>
|
||||
<Form onSubmit={onSubmitHandler}>
|
||||
<div className={classes["container-title"]}>
|
||||
<Typography typo={ITypo.P_SB_18}>Documents paramétrés</Typography>
|
||||
<Typography typo={ITypo.P_SB_18}>Sélectionner les documents associés à ce type d'acte</Typography>
|
||||
<Tooltip text="Si vous ne trouvez pas le document que vous souhaitez dans la liste, cliquez sur « Modifier la liste des documents » pour créer ce type de document à la liste" />
|
||||
</div>
|
||||
<div className={classes["documents"]}>
|
||||
<MultiSelect
|
||||
@ -171,6 +187,20 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
</Typography>
|
||||
</div>
|
||||
</Confirm>
|
||||
<Confirm
|
||||
isOpen={isSaveModalOpened}
|
||||
onClose={closeSaveModal}
|
||||
onAccept={saveDocumentTypes}
|
||||
closeBtn
|
||||
header={"Enregistrer les modifications ?"}
|
||||
confirmText={"Enregistrer"}
|
||||
cancelText={"Annuler"}>
|
||||
<div className={classes["modal-content"]}>
|
||||
<Typography typo={ITypo.P_16} className={classes["text"]}>
|
||||
Les documents seront associés à ce type d'acte.
|
||||
</Typography>
|
||||
</div>
|
||||
</Confirm>
|
||||
</div>
|
||||
</DefaultDeedTypesDashboard>
|
||||
);
|
||||
|
@ -1,6 +1,18 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
@media (max-width: $screen-l) {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.document-infos {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
@ -1,3 +1,4 @@
|
||||
import ChevronIcon from "@Assets/Icons/chevron.svg";
|
||||
import PenICon from "@Assets/Icons/pen.svg";
|
||||
import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes";
|
||||
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
@ -10,6 +11,7 @@ import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
|
||||
export default function DocumentTypesInformations() {
|
||||
const router = useRouter();
|
||||
@ -33,8 +35,14 @@ export default function DocumentTypesInformations() {
|
||||
return (
|
||||
<DefaultDocumentTypesDashboard mobileBackText={"Liste des collaborateurs"}>
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["folder-header"]}>
|
||||
<Typography typo={ITypo.H1Bis}>Paramétrage des documents</Typography>
|
||||
<div className={classes["header"]}>
|
||||
<Typography typo={ITypo.H1Bis}>Paramétrage des listes de pièces</Typography>
|
||||
<Link href={Module.getInstance().get().modules.pages.DeedTypes.props.path}>
|
||||
<Button variant={EButtonVariant.LINE}>
|
||||
Retour au paramétrage des types d'actes
|
||||
<Image src={ChevronIcon} alt="Chevron" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className={classes["document-infos"]}>
|
||||
<div className={classes["left"]}>
|
||||
|
@ -9,7 +9,6 @@ import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||
import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
|
||||
import Module from "@Front/Config/Module";
|
||||
import { TextField } from "@mui/material";
|
||||
import { ECivility } from "le-coffre-resources/dist/Customer/Contact";
|
||||
import { Customer, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
import Link from "next/link";
|
||||
@ -17,6 +16,7 @@ import { NextRouter, useRouter } from "next/router";
|
||||
|
||||
import BasePage from "../../Base";
|
||||
import classes from "./classes.module.scss";
|
||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||
|
||||
enum ESelectedOption {
|
||||
EXISTING_CUSTOMER = "existing_customer",
|
||||
|
@ -34,6 +34,7 @@ type IState = {
|
||||
inputArchivedDescripton: string;
|
||||
isValidateModalVisible: boolean;
|
||||
hasValidateAnchoring: boolean;
|
||||
isVerifDeleteModalVisible: boolean;
|
||||
};
|
||||
class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
public constructor(props: IPropsClass) {
|
||||
@ -44,6 +45,7 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
inputArchivedDescripton: "",
|
||||
isValidateModalVisible: false,
|
||||
hasValidateAnchoring: false,
|
||||
isVerifDeleteModalVisible: false,
|
||||
};
|
||||
this.onSelectedFolder = this.onSelectedFolder.bind(this);
|
||||
this.openArchivedModal = this.openArchivedModal.bind(this);
|
||||
@ -55,6 +57,8 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
this.closeModal = this.closeModal.bind(this);
|
||||
this.validateAnchoring = this.validateAnchoring.bind(this);
|
||||
this.openValidateModal = this.openValidateModal.bind(this);
|
||||
this.openVerifDeleteFolder = this.openVerifDeleteFolder.bind(this);
|
||||
this.closeVerifDeleteFolder = this.closeVerifDeleteFolder.bind(this);
|
||||
}
|
||||
|
||||
// TODO: Message if the user has not created any folder yet
|
||||
@ -109,7 +113,7 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
</Button>
|
||||
)}
|
||||
{!this.doesFolderHaveCustomer() && (
|
||||
<span className={classes["delete-folder"]} onClick={this.deleteFolder}>
|
||||
<span className={classes["delete-folder"]} onClick={this.openVerifDeleteFolder}>
|
||||
<Button variant={EButtonVariant.SECONDARY}>Supprimer le dossier</Button>
|
||||
</span>
|
||||
)}
|
||||
@ -131,6 +135,18 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
onChange={this.onArchivedDescriptionInputChange}
|
||||
/>
|
||||
</Confirm>
|
||||
<Confirm
|
||||
isOpen={this.state.isVerifDeleteModalVisible}
|
||||
onAccept={this.deleteFolder}
|
||||
onClose={this.closeVerifDeleteFolder}
|
||||
closeBtn
|
||||
header={"Êtes-vous sûr de vouloir supprimer ce dossier ?"}
|
||||
cancelText={"Annuler"}
|
||||
confirmText={"Confirmer"}>
|
||||
<div className={classes["modal-title"]}>
|
||||
<Typography typo={ITypo.P_16}>Cette action sera irréversible.</Typography>
|
||||
</div>
|
||||
</Confirm>
|
||||
</div>
|
||||
) : (
|
||||
<div className={classes["no-folder-selected"]}>
|
||||
@ -187,6 +203,18 @@ class FolderInformationClass extends BasePage<IPropsClass, IState> {
|
||||
});
|
||||
}
|
||||
|
||||
public openVerifDeleteFolder() {
|
||||
this.setState({
|
||||
isVerifDeleteModalVisible: true,
|
||||
});
|
||||
}
|
||||
|
||||
public closeVerifDeleteFolder() {
|
||||
this.setState({
|
||||
isVerifDeleteModalVisible: false,
|
||||
});
|
||||
}
|
||||
|
||||
private closeModal() {
|
||||
this.setState({
|
||||
isValidateModalVisible: false,
|
||||
|
@ -13,6 +13,7 @@ import { NextRouter, useRouter } from "next/router";
|
||||
|
||||
import BasePage from "../../Base";
|
||||
import classes from "./classes.module.scss";
|
||||
import DateField from "@Front/Components/DesignSystem/Form/DateField";
|
||||
|
||||
type IProps = {};
|
||||
|
||||
@ -43,6 +44,8 @@ class UpdateFolderMetadataClass extends BasePage<IPropsClass, IState> {
|
||||
value: this.state.selectedFolder?.deed?.deed_type?.uid,
|
||||
} as IOption;
|
||||
const openingDate = new Date(this.state.selectedFolder?.created_at ?? "");
|
||||
if (!this.state.selectedFolder?.created_at) return <></>;
|
||||
const defaultValue = openingDate.toISOString().split("T")[0];
|
||||
return (
|
||||
<DefaultNotaryDashboard title={"Ajouter client(s)"} onSelectedFolder={this.onSelectedFolder}>
|
||||
<div className={classes["root"]}>
|
||||
@ -60,7 +63,7 @@ class UpdateFolderMetadataClass extends BasePage<IPropsClass, IState> {
|
||||
defaultValue={this.state.selectedFolder?.folder_number}
|
||||
/>
|
||||
<Select name="deed" options={[]} placeholder={"Type d'acte"} selectedOption={deedOption} disabled />
|
||||
<TextField placeholder="Ouverture du dossier" defaultValue={openingDate.toLocaleDateString("fr-FR")} disabled />
|
||||
<DateField name="opening_date" placeholder="Ouverture du dossier" defaultValue={defaultValue} disabled />
|
||||
</div>
|
||||
|
||||
<div className={classes["button-container"]}>
|
||||
|
@ -49,6 +49,7 @@ export default class ClientSection extends React.Component<IProps, IState> {
|
||||
key={customer.uid}
|
||||
isOpened={this.state.openedCustomer === customer.uid}
|
||||
onChange={this.changeUserFolder}
|
||||
isArchived
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -12,6 +12,8 @@ import { useCallback, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
||||
import Rules, { RulesMode } from "@Front/Components/Elements/Rules";
|
||||
import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule";
|
||||
|
||||
type IProps = {};
|
||||
export default function RolesCreate(props: IProps) {
|
||||
@ -61,35 +63,44 @@ export default function RolesCreate(props: IProps) {
|
||||
}, [hasChanged, redirect]);
|
||||
|
||||
return (
|
||||
<DefaultRolesDashboard mobileBackText={"Liste des rôles"} hasBackArrow title="Créer un rôle">
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["header"]}>
|
||||
<Typography typo={ITypo.H1Bis}>Créer un rôle</Typography>
|
||||
<Rules
|
||||
mode={RulesMode.NECESSARY}
|
||||
rules={[
|
||||
{
|
||||
action: AppRuleActions.create,
|
||||
name: AppRuleNames.officeRoles,
|
||||
},
|
||||
]}>
|
||||
<DefaultRolesDashboard mobileBackText={"Liste des rôles"} hasBackArrow title="Créer un rôle">
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["header"]}>
|
||||
<Typography typo={ITypo.H1Bis}>Créer un rôle</Typography>
|
||||
</div>
|
||||
<Form onSubmit={onSubmitHandler} className={classes["form-container"]} onFieldChange={onFieldChange}>
|
||||
<TextField name="name" placeholder="Nom du rôle" />
|
||||
<div className={classes["buttons-container"]}>
|
||||
<Button variant={EButtonVariant.GHOST} onClick={onCancel}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button type="submit">Créer le rôle</Button>
|
||||
</div>
|
||||
</Form>
|
||||
<Confirm
|
||||
isOpen={isConfirmModalVisible}
|
||||
onClose={closeConfirmModal}
|
||||
onAccept={redirect}
|
||||
closeBtn
|
||||
header={"Êtes-vous sur de vouloir quitter sans enregistrer ?"}
|
||||
cancelText={"Annuler"}
|
||||
confirmText={"Quitter"}>
|
||||
<div className={classes["modal-content"]}>
|
||||
<Typography typo={ITypo.P_16} className={classes["text"]}>
|
||||
Si vous quittez, toutes les modifications que vous avez effectuées ne seront pas enregistrées.
|
||||
</Typography>
|
||||
</div>
|
||||
</Confirm>
|
||||
</div>
|
||||
<Form onSubmit={onSubmitHandler} className={classes["form-container"]} onFieldChange={onFieldChange}>
|
||||
<TextField name="name" placeholder="Nom du rôle" />
|
||||
<div className={classes["buttons-container"]}>
|
||||
<Button variant={EButtonVariant.GHOST} onClick={onCancel}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button type="submit">Créer le rôle</Button>
|
||||
</div>
|
||||
</Form>
|
||||
<Confirm
|
||||
isOpen={isConfirmModalVisible}
|
||||
onClose={closeConfirmModal}
|
||||
onAccept={redirect}
|
||||
closeBtn
|
||||
header={"Êtes-vous sur de vouloir quitter sans enregistrer ?"}
|
||||
cancelText={"Annuler"}
|
||||
confirmText={"Quitter"}>
|
||||
<div className={classes["modal-content"]}>
|
||||
<Typography typo={ITypo.P_16} className={classes["text"]}>
|
||||
Si vous quittez, toutes les modifications que vous avez effectuées ne seront pas enregistrées.
|
||||
</Typography>
|
||||
</div>
|
||||
</Confirm>
|
||||
</div>
|
||||
</DefaultRolesDashboard>
|
||||
</DefaultRolesDashboard>
|
||||
</Rules>
|
||||
);
|
||||
}
|
||||
|
@ -81,7 +81,11 @@ export default function UserInformations(props: IProps) {
|
||||
|
||||
useEffect(() => {
|
||||
if (!userSelected) return;
|
||||
setCurrentAppointment(userSelected?.appointment?.find((appointment) => appointment.status === EAppointmentStatus.OPEN && appointment.votes?.length != 0) ?? null);
|
||||
setCurrentAppointment(
|
||||
userSelected?.appointment?.find(
|
||||
(appointment) => appointment.status === EAppointmentStatus.OPEN && appointment.votes?.length != 0,
|
||||
) ?? null,
|
||||
);
|
||||
}, [userSelected]);
|
||||
|
||||
/** Functions for the admin modal */
|
||||
@ -271,7 +275,7 @@ export default function UserInformations(props: IProps) {
|
||||
onChange={handleRoleChange}
|
||||
selectedOption={{
|
||||
value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid,
|
||||
label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.label!,
|
||||
label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -282,7 +286,12 @@ export default function UserInformations(props: IProps) {
|
||||
</div>
|
||||
<div className={classes["second-line"]}>
|
||||
<Switch label="Admin de son office" checked={isAdminChecked} onChange={handleAdminChanged} />
|
||||
<Switch label="Super-admin LeCoffre.io" checked={isSuperAdminChecked} disabled={userHasVoted()} onChange={handleSuperAdminChanged} />
|
||||
<Switch
|
||||
label="Super-admin LeCoffre.io"
|
||||
checked={isSuperAdminChecked}
|
||||
disabled={userHasVoted()}
|
||||
onChange={handleSuperAdminChanged}
|
||||
/>
|
||||
{currentAppointment && (
|
||||
<div className={classes["votes-block"]}>
|
||||
<div className={classes["left"]}>
|
||||
|
@ -68,10 +68,8 @@ export default class JwtService {
|
||||
}
|
||||
|
||||
public hasRule(name: string, action: string) {
|
||||
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||
if (!accessToken) return false;
|
||||
const decodedToken = this.decodeJwt();
|
||||
if (!decodedToken) return false;
|
||||
return decodedToken?.rules?.some((rule: string) => rule === `${action} ${name}`);
|
||||
const token = this.decodeJwt();
|
||||
if (!token) return false;
|
||||
return token?.rules?.some((rule: string) => rule === `${action} ${name}`);
|
||||
}
|
||||
}
|
||||
|
@ -22,22 +22,6 @@ export async function middleware(request: NextRequest) {
|
||||
return NextResponse.redirect(new URL("/login", request.url));
|
||||
}
|
||||
|
||||
const requestUrlPath = request.nextUrl.pathname;
|
||||
if (
|
||||
requestUrlPath.startsWith("/collaborators") ||
|
||||
requestUrlPath.startsWith("/deed-types") ||
|
||||
requestUrlPath.startsWith("/customer") ||
|
||||
requestUrlPath.startsWith("/offices") ||
|
||||
requestUrlPath.startsWith("/roles") ||
|
||||
requestUrlPath.startsWith("/users")
|
||||
) {
|
||||
if (userDecodedToken.role !== "admin" && userDecodedToken.role !== "super-admin")
|
||||
return NextResponse.redirect(new URL("/404", request.url));
|
||||
}
|
||||
if ((requestUrlPath.startsWith("/my-account") || requestUrlPath.startsWith("/document-types")) && !userDecodedToken)
|
||||
return NextResponse.redirect(new URL("/404", request.url));
|
||||
if (requestUrlPath.startsWith("/client-dashboard") && !customerDecodedToken) return NextResponse.redirect(new URL("/404", request.url));
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user