Merge remote-tracking branch 'origin/dev' into staging
This commit is contained in:
commit
6c44f321aa
@ -0,0 +1,7 @@
|
|||||||
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
|
.root {
|
||||||
|
.label {
|
||||||
|
padding: 0px var(--spacing-2, 16px);
|
||||||
|
}
|
||||||
|
}
|
82
src/front/Components/DesignSystem/Autocomplete/index.tsx
Normal file
82
src/front/Components/DesignSystem/Autocomplete/index.tsx
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import useOpenable from "@Front/Hooks/useOpenable";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import DropdownMenu from "../Dropdown/DropdownMenu";
|
||||||
|
import { IOption } from "../Dropdown/DropdownMenu/DropdownOption";
|
||||||
|
import SearchBar from "../SearchBar";
|
||||||
|
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||||
|
import classes from "./classes.module.scss";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
options: IOption[];
|
||||||
|
placeholder?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
label?: string;
|
||||||
|
onSelect?: (option: IOption) => void;
|
||||||
|
selectedOption?: IOption | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Autocomplete(props: IProps) {
|
||||||
|
const { options, placeholder, disabled, label, selectedOption: selectedOptionProps } = props;
|
||||||
|
const [selectedOption, setSelectedOption] = useState<IOption | null>(selectedOptionProps ?? null);
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
const [filteredOptions, setFilteredOptions] = useState<IOption[]>(options);
|
||||||
|
const openable = useOpenable({ defaultOpen: false });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchValue) {
|
||||||
|
const filteredOptions = options.filter((option) => getLabel(option)?.toLowerCase().includes(searchValue.toLowerCase()));
|
||||||
|
console.log(filteredOptions);
|
||||||
|
if (filteredOptions.length === 0)
|
||||||
|
return setFilteredOptions([{ id: "no-results", label: "Aucun résulats", notSelectable: true }]);
|
||||||
|
return setFilteredOptions(filteredOptions);
|
||||||
|
}
|
||||||
|
return setFilteredOptions(options);
|
||||||
|
}, [searchValue, options]);
|
||||||
|
|
||||||
|
const handleSearchChange = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
setSearchValue(value);
|
||||||
|
if (value) {
|
||||||
|
openable.open();
|
||||||
|
} else {
|
||||||
|
openable.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[openable],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedOption(selectedOptionProps ?? null);
|
||||||
|
}, [selectedOptionProps]);
|
||||||
|
|
||||||
|
const handleSelectOption = useCallback(
|
||||||
|
(option: IOption) => {
|
||||||
|
setSelectedOption(option);
|
||||||
|
setSearchValue(getLabel(option) || "");
|
||||||
|
openable.close();
|
||||||
|
},
|
||||||
|
[openable],
|
||||||
|
);
|
||||||
|
|
||||||
|
function getLabel(option: IOption | null): string | null {
|
||||||
|
if (!option) return null;
|
||||||
|
if (typeof option.label === "string") {
|
||||||
|
return option.label;
|
||||||
|
}
|
||||||
|
return `${option.label.text} ${option.label.subtext}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu options={filteredOptions} openable={openable} onSelect={handleSelectOption} selectedOption={selectedOption}>
|
||||||
|
<div className={classes["root"]}>
|
||||||
|
{label && (
|
||||||
|
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<SearchBar placeholder={placeholder} disabled={disabled} onChange={handleSearchChange} value={searchValue} />
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { IOption } from "../Form/SelectField";
|
|
||||||
import Tooltip from "../ToolTip";
|
import Tooltip from "../ToolTip";
|
||||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { IOptionOld } from "../Form/SelectFieldOld";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
name?: string;
|
name?: string;
|
||||||
option: IOption;
|
option: IOptionOld;
|
||||||
toolTip?: string;
|
toolTip?: string;
|
||||||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -10,6 +10,18 @@
|
|||||||
|
|
||||||
background: var(--dropdown-option-background-default, #fff);
|
background: var(--dropdown-option-background-default, #fff);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--dropdown-option-background-hovered);
|
background-color: var(--dropdown-option-background-hovered);
|
||||||
}
|
}
|
||||||
@ -18,4 +30,9 @@
|
|||||||
&:active {
|
&:active {
|
||||||
background-color: var(--dropdown-option-background-pressed);
|
background-color: var(--dropdown-option-background-pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[data-not-selectable="true"] {
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ import { CheckIcon } from "@heroicons/react/24/outline";
|
|||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import IconButton from "@Front/Components/DesignSystem/IconButton";
|
|
||||||
|
|
||||||
export type IOption = {
|
export type IOption = {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string | { text: string; subtext: string };
|
||||||
|
notSelectable?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
@ -22,13 +22,35 @@ export default function DropdownOption(props: IProps) {
|
|||||||
const handleOnClick = useCallback(() => onClick && onClick(option), [onClick, option]);
|
const handleOnClick = useCallback(() => onClick && onClick(option), [onClick, option]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes["root"]} onClick={handleOnClick}>
|
<div className={classes["root"]} data-not-selectable={!!option.notSelectable} onClick={handleOnClick}>
|
||||||
|
{getContent(option.label)}
|
||||||
|
{isActive && <CheckIcon />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
function getContent(label: string | { text: string; subtext: string }) {
|
||||||
|
if (typeof label === "string") {
|
||||||
|
return (
|
||||||
<Typography
|
<Typography
|
||||||
typo={isActive ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
typo={isActive ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
||||||
color={isActive ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
color={isActive ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
||||||
{option.label}
|
{label}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={classes["content"]}>
|
||||||
|
<Typography
|
||||||
|
typo={ETypo.TEXT_MD_LIGHT}
|
||||||
|
color={isActive ? ETypoColor.NAVIGATION_BUTTON_CONTRAST_ACTIVE : ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
|
||||||
|
{label.text}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
typo={ETypo.TEXT_MD_BOLD}
|
||||||
|
color={isActive ? ETypoColor.NAVIGATION_BUTTON_CONTRAST_ACTIVE : ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
|
||||||
|
{label.subtext}
|
||||||
</Typography>
|
</Typography>
|
||||||
{isActive && <IconButton icon={<CheckIcon />} />}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
z-index: 3;
|
||||||
|
|
||||||
padding: var(--spacing-sm, 8px);
|
padding: var(--spacing-sm, 8px);
|
||||||
border-radius: var(--dropdown-radius, 0px);
|
border-radius: var(--dropdown-radius, 0px);
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
.label {
|
||||||
|
padding: 0px var(--spacing-2, 16px);
|
||||||
|
}
|
||||||
|
.container {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 56px;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 56px;
|
||||||
|
|
||||||
padding: var(--spacing-2, 16px) var(--spacing-sm, 8px);
|
padding: var(--spacing-2, 16px) var(--spacing-sm, 8px);
|
||||||
gap: var(--spacing-2, 16px);
|
gap: var(--spacing-2, 16px);
|
||||||
@ -15,6 +19,12 @@
|
|||||||
background: var(--dropdown-input-background, #fff);
|
background: var(--dropdown-input-background, #fff);
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 24px;
|
||||||
|
.value {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0px var(--spacing-2, 16px);
|
padding: 0px var(--spacing-2, 16px);
|
||||||
@ -22,6 +32,14 @@
|
|||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
stroke: var(--button-icon-button-default-default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--dropdown-input-border-hovered);
|
border-color: var(--dropdown-input-border-hovered);
|
||||||
}
|
}
|
||||||
@ -42,4 +60,5 @@
|
|||||||
opacity: var(--opacity-disabled, 0.3);
|
opacity: var(--opacity-disabled, 0.3);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,50 @@
|
|||||||
import useOpenable from "@Front/Hooks/useOpenable";
|
import useOpenable from "@Front/Hooks/useOpenable";
|
||||||
|
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import DropdownMenu from "./DropdownMenu";
|
import DropdownMenu from "./DropdownMenu";
|
||||||
import { IOption } from "./DropdownMenu/DropdownOption";
|
import { IOption } from "./DropdownMenu/DropdownOption";
|
||||||
import IconButton from "../IconButton";
|
|
||||||
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
options: IOption[];
|
options: IOption[];
|
||||||
placeholder: string;
|
label?: string;
|
||||||
|
placeholder?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
onSelect?: (option: IOption) => void;
|
||||||
|
selectedOption?: IOption | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Dropdown(props: IProps) {
|
export default function Dropdown(props: IProps) {
|
||||||
const { options, placeholder, disabled } = props;
|
const { options, placeholder, disabled, onSelect, selectedOption: selectedOptionProps, label } = props;
|
||||||
const [selectedOption, setSelectedOption] = useState<IOption | null>(null);
|
const [selectedOption, setSelectedOption] = useState<IOption | null>(selectedOptionProps ?? null);
|
||||||
const openable = useOpenable({ defaultOpen: false });
|
const openable = useOpenable({ defaultOpen: false });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedOption(selectedOptionProps ?? null);
|
||||||
|
}, [selectedOptionProps]);
|
||||||
|
|
||||||
|
const handleOnSelect = useCallback(
|
||||||
|
(option: IOption) => {
|
||||||
|
setSelectedOption(option);
|
||||||
|
onSelect?.(option);
|
||||||
|
},
|
||||||
|
[onSelect],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu options={options} openable={openable} onSelect={setSelectedOption} selectedOption={selectedOption}>
|
<DropdownMenu options={options} openable={openable} onSelect={handleOnSelect} selectedOption={selectedOption}>
|
||||||
|
<div className={classes["root"]}>
|
||||||
|
{label && (
|
||||||
|
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={classNames([
|
className={classNames([
|
||||||
classes["root"],
|
classes["container"],
|
||||||
openable.isOpen && classes["open"],
|
openable.isOpen && classes["open"],
|
||||||
disabled && classes["disabled"],
|
disabled && classes["disabled"],
|
||||||
!!selectedOption && classes["active"],
|
!!selectedOption && classes["active"],
|
||||||
@ -32,13 +52,23 @@ export default function Dropdown(props: IProps) {
|
|||||||
onClick={openable.toggle}>
|
onClick={openable.toggle}>
|
||||||
<div className={classes["content"]}>
|
<div className={classes["content"]}>
|
||||||
<Typography
|
<Typography
|
||||||
typo={ETypo.TEXT_MD_REGULAR}
|
className={classes["value"]}
|
||||||
|
typo={!!selectedOption ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
||||||
color={!!selectedOption ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
color={!!selectedOption ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
||||||
{selectedOption?.label ?? placeholder}
|
{getLabel(selectedOption) ?? placeholder}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<ChevronDownIcon />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<IconButton icon={<ChevronDownIcon />} />
|
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLabel(option: IOption | null): string | null {
|
||||||
|
if (!option) return null;
|
||||||
|
if (typeof option.label === "string") {
|
||||||
|
return option.label;
|
||||||
|
}
|
||||||
|
return `${option.label.text} ${option.label.subtext}`;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
|
.root {
|
||||||
|
.hidden-input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.errors-container {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
import Autocomplete from "../../Autocomplete";
|
||||||
|
import { IOption } from "../../Dropdown/DropdownMenu/DropdownOption";
|
||||||
|
import BaseField, { IProps as IBaseFieldProps, IState as IBaseFieldState } from "../BaseField";
|
||||||
|
import classes from "./classes.module.scss";
|
||||||
|
|
||||||
|
export type IProps = IBaseFieldProps & {
|
||||||
|
onSelect?: (option: IOption) => void;
|
||||||
|
options: IOption[];
|
||||||
|
selectedOption?: IOption | null;
|
||||||
|
label?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IState = IBaseFieldState & {
|
||||||
|
selectedOption: IOption | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class AutocompleteField extends BaseField<IProps, IState> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
selectedOption: this.props.selectedOption ?? null,
|
||||||
|
...this.getDefaultState(),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.handleOnChange = this.handleOnChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOnChange = (option: IOption) => {
|
||||||
|
this.setState({ selectedOption: option });
|
||||||
|
this.props.onSelect?.(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
public override componentDidUpdate(prevProps: IProps): void {
|
||||||
|
if (prevProps.selectedOption !== this.props.selectedOption) {
|
||||||
|
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render(): ReactNode {
|
||||||
|
return (
|
||||||
|
<div className={classes["root"]}>
|
||||||
|
<Autocomplete
|
||||||
|
options={this.props.options}
|
||||||
|
placeholder={this.props.placeholder}
|
||||||
|
onSelect={this.handleOnChange}
|
||||||
|
selectedOption={this.state.selectedOption}
|
||||||
|
label={this.props.label}
|
||||||
|
/>
|
||||||
|
{this.state.selectedOption && (
|
||||||
|
<input
|
||||||
|
className={classes["hidden-input"]}
|
||||||
|
name={this.props.name}
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.selectedOption.id}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{this.hasError() && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ export type IProps = {
|
|||||||
label?: string;
|
label?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IState = {
|
export type IState = {
|
||||||
value: string;
|
value: string;
|
||||||
validationError: ValidationError | null;
|
validationError: ValidationError | null;
|
||||||
};
|
};
|
||||||
|
@ -1,143 +1,11 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: flex;
|
.hidden-input {
|
||||||
position: relative;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid var(--color-neutral-200);
|
|
||||||
|
|
||||||
&[data-errored="true"] {
|
|
||||||
border: 1px solid var(--color-error-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-disabled="true"] {
|
|
||||||
.container-label {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 24px;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&[data-border-right-collapsed="true"] {
|
|
||||||
border-radius: 8px 0 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-input chevron-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
display: flex;
|
|
||||||
margin-right: 8px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 24px;
|
|
||||||
left: 8px;
|
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
padding: 0 16px;
|
|
||||||
|
|
||||||
&[data-open="true"] {
|
|
||||||
transform: translateY(-36px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chevron-icon {
|
|
||||||
height: 24px;
|
|
||||||
|
|
||||||
fill: var(--color-neutral-500);
|
|
||||||
transition: all 350ms $custom-easing;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
|
|
||||||
&[data-open="true"] {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-ul {
|
|
||||||
padding-left: 24px;
|
|
||||||
z-index: 3;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
outline: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
transition: height 350ms $custom-easing, opacity 350ms $custom-easing;
|
|
||||||
opacity: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
top: 50px;
|
|
||||||
background-color: var(--color-generic-white);
|
|
||||||
|
|
||||||
&[data-open="false"] {
|
|
||||||
height: 0;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
border: none;
|
|
||||||
}
|
}
|
||||||
}
|
.errors-container {
|
||||||
|
margin-top: 8px;
|
||||||
.container-li {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
padding-bottom: 24px;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
background: var(--color-neutral-50);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-neutral-100);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background: var(--color-neutral-200);
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.token-icon {
|
|
||||||
max-width: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 11px;
|
|
||||||
|
|
||||||
> svg {
|
|
||||||
height: 20px;
|
|
||||||
margin-right: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> img {
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.backdrop {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1;
|
|
||||||
inset: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,212 +1,65 @@
|
|||||||
import ChevronIcon from "@Assets/Icons/chevron.svg";
|
import React from "react";
|
||||||
import WindowStore from "@Front/Stores/WindowStore";
|
import { ReactNode } from "react";
|
||||||
import { ValidationError } from "class-validator";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import Image from "next/image";
|
|
||||||
import React, { FormEvent, ReactNode } from "react";
|
|
||||||
|
|
||||||
import Typography, { ETypo, ETypoColor } from "../../Typography";
|
import { IOption } from "../../Dropdown/DropdownMenu/DropdownOption";
|
||||||
|
import BaseField, { IProps as IBaseFieldProps, IState as IBaseFieldState } from "../BaseField";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { NextRouter, useRouter } from "next/router";
|
import Dropdown from "../../Dropdown";
|
||||||
|
|
||||||
type IProps = {
|
export type IProps = IBaseFieldProps & {
|
||||||
selectedOption?: IOption;
|
onSelect?: (option: IOption) => void;
|
||||||
onChange?: (selectedOption: IOption) => void;
|
|
||||||
options: IOption[];
|
options: IOption[];
|
||||||
hasBorderRightCollapsed?: boolean;
|
selectedOption?: IOption | null;
|
||||||
placeholder?: string;
|
label?: string;
|
||||||
className?: string;
|
|
||||||
name: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
errors?: ValidationError;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IOption = {
|
type IState = IBaseFieldState & {
|
||||||
value: unknown;
|
|
||||||
label: string;
|
|
||||||
icon?: ReactNode;
|
|
||||||
description?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type IState = {
|
|
||||||
isOpen: boolean;
|
|
||||||
listWidth: number;
|
|
||||||
listHeight: number;
|
|
||||||
selectedOption: IOption | null;
|
selectedOption: IOption | null;
|
||||||
errors: ValidationError | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type IPropsClass = IProps & {
|
export default class SelectField extends BaseField<IProps, IState> {
|
||||||
router: NextRouter;
|
constructor(props: IProps) {
|
||||||
};
|
|
||||||
|
|
||||||
class SelectFieldClass extends React.Component<IPropsClass, IState> {
|
|
||||||
private contentRef = React.createRef<HTMLUListElement>();
|
|
||||||
private rootRef = React.createRef<HTMLDivElement>();
|
|
||||||
private removeOnresize = () => {};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
disabled: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: IPropsClass) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isOpen: false,
|
|
||||||
listHeight: 0,
|
|
||||||
listWidth: 0,
|
|
||||||
selectedOption: null,
|
|
||||||
errors: this.props.errors ?? null,
|
|
||||||
};
|
|
||||||
this.toggle = this.toggle.bind(this);
|
|
||||||
this.onSelect = this.onSelect.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override render(): JSX.Element {
|
|
||||||
const selectedOption = this.state.selectedOption ?? this.props.selectedOption;
|
|
||||||
return (
|
|
||||||
<div className={classes["container"]}>
|
|
||||||
<div
|
|
||||||
className={classNames(classes["root"], this.props.className)}
|
|
||||||
ref={this.rootRef}
|
|
||||||
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
|
|
||||||
className={classNames(classes["container-label"])}
|
|
||||||
data-open={this.state.isOpen}
|
|
||||||
onClick={this.toggle}
|
|
||||||
data-border-right-collapsed={this.props.hasBorderRightCollapsed}>
|
|
||||||
<div className={classNames(classes["container-input"])}>
|
|
||||||
{selectedOption && (
|
|
||||||
<>
|
|
||||||
<span className={classNames(classes["icon"], classes["token-icon"])}>{selectedOption?.icon}</span>
|
|
||||||
<Typography typo={ETypo.TEXT_LG_REGULAR}>
|
|
||||||
<span className={classes["text"]}>{selectedOption?.label}</span>
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{!selectedOption && (
|
|
||||||
<div className={classes["placeholder"]} data-open={(selectedOption ? true : false).toString()}>
|
|
||||||
<Typography typo={ETypo.TEXT_MD_REGULAR}>
|
|
||||||
<span className={classes["text"]}>{this.props.placeholder ?? ""}</span>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Image className={classes["chevron-icon"]} data-open={this.state.isOpen} src={ChevronIcon} alt="chevron icon" />
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
className={classes["container-ul"]}
|
|
||||||
data-open={this.state.isOpen}
|
|
||||||
ref={this.contentRef}
|
|
||||||
style={{
|
|
||||||
height: this.state.listHeight + "px",
|
|
||||||
}}>
|
|
||||||
{this.props.options.map((option, index) => (
|
|
||||||
<li
|
|
||||||
key={`${index}-${option.value}`}
|
|
||||||
className={classes["container-li"]}
|
|
||||||
onClick={(e) => this.onSelect(option, e)}>
|
|
||||||
<div className={classes["token-icon"]}>{option.icon}</div>
|
|
||||||
<Typography typo={ETypo.TEXT_LG_REGULAR}>{option.label}</Typography>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{this.state.isOpen && <div className={classes["backdrop"]} onClick={this.toggle} />}
|
|
||||||
</div>
|
|
||||||
{this.state.errors !== null && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
|
||||||
</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) {
|
|
||||||
this.setState({
|
|
||||||
errors: this.props.errors ?? null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.selectedOption !== prevProps.selectedOption) {
|
|
||||||
this.setState({
|
|
||||||
selectedOption: this.props.selectedOption ?? null,
|
selectedOption: this.props.selectedOption ?? null,
|
||||||
});
|
...this.getDefaultState(),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromProps(props: IProps, state: IState) {
|
|
||||||
if (props.selectedOption?.value) {
|
|
||||||
return {
|
|
||||||
value: props.selectedOption?.value,
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
return null;
|
this.handleOnChange = this.handleOnChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onResize() {
|
private handleOnChange = (option: IOption) => {
|
||||||
let listHeight = 0;
|
this.setState({ selectedOption: option });
|
||||||
let listWidth = 0;
|
this.props.onSelect?.(option);
|
||||||
listWidth = this.rootRef.current?.scrollWidth ?? 0;
|
};
|
||||||
if (this.state.listHeight) {
|
|
||||||
listHeight = this.contentRef.current?.scrollHeight ?? 0;
|
public override componentDidUpdate(prevProps: IProps): void {
|
||||||
|
if (prevProps.selectedOption !== this.props.selectedOption) {
|
||||||
|
this.setState({ selectedOption: this.props.selectedOption ?? null });
|
||||||
}
|
}
|
||||||
this.setState({ listHeight, listWidth });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggle(e: FormEvent) {
|
public override render(): ReactNode {
|
||||||
if (this.props.disabled) return;
|
|
||||||
e.preventDefault();
|
|
||||||
let listHeight = 0;
|
|
||||||
let listWidth = this.rootRef.current?.scrollWidth ?? 0;
|
|
||||||
|
|
||||||
if (!this.state.listHeight) {
|
|
||||||
listHeight = this.contentRef.current?.scrollHeight ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState((state) => {
|
|
||||||
return { isOpen: !state.isOpen, listHeight, listWidth };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private onSelect(option: IOption, e: React.MouseEvent<HTMLLIElement, MouseEvent>) {
|
|
||||||
if (this.props.disabled) return;
|
|
||||||
this.props.onChange && this.props.onChange(option);
|
|
||||||
this.setState({
|
|
||||||
selectedOption: option,
|
|
||||||
});
|
|
||||||
this.toggle(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderErrors(): JSX.Element | null {
|
|
||||||
if (!this.state.errors) return null;
|
|
||||||
return (
|
return (
|
||||||
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_ERROR_600}>
|
<div className={classes["root"]}>
|
||||||
{this.props.placeholder} ne peut pas être vide
|
<Dropdown
|
||||||
</Typography>
|
options={this.props.options}
|
||||||
|
placeholder={this.props.placeholder}
|
||||||
|
onSelect={this.handleOnChange}
|
||||||
|
selectedOption={this.state.selectedOption}
|
||||||
|
label={this.props.label}
|
||||||
|
/>
|
||||||
|
{this.state.selectedOption && (
|
||||||
|
<input
|
||||||
|
className={classes["hidden-input"]}
|
||||||
|
name={this.props.name}
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.selectedOption.id}
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{this.hasError() && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SelectField(props: IProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
return <SelectFieldClass {...props} router={router} />;
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
|
.root {
|
||||||
|
.hidden-input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.errors-container {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
212
src/front/Components/DesignSystem/Form/SelectFieldOld/index.tsx
Normal file
212
src/front/Components/DesignSystem/Form/SelectFieldOld/index.tsx
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
import ChevronIcon from "@Assets/Icons/chevron.svg";
|
||||||
|
import WindowStore from "@Front/Stores/WindowStore";
|
||||||
|
import { ValidationError } from "class-validator";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import Image from "next/image";
|
||||||
|
import React, { FormEvent, ReactNode } from "react";
|
||||||
|
|
||||||
|
import Typography, { ETypo, ETypoColor } from "../../Typography";
|
||||||
|
import classes from "./classes.module.scss";
|
||||||
|
import { NextRouter, useRouter } from "next/router";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
selectedOption?: IOptionOld;
|
||||||
|
onChange?: (selectedOption: IOptionOld) => void;
|
||||||
|
options: IOptionOld[];
|
||||||
|
hasBorderRightCollapsed?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
className?: string;
|
||||||
|
name: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
errors?: ValidationError;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IOptionOld = {
|
||||||
|
value: unknown;
|
||||||
|
label: string;
|
||||||
|
icon?: ReactNode;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IState = {
|
||||||
|
isOpen: boolean;
|
||||||
|
listWidth: number;
|
||||||
|
listHeight: number;
|
||||||
|
selectedOption: IOptionOld | null;
|
||||||
|
errors: ValidationError | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type IPropsClass = IProps & {
|
||||||
|
router: NextRouter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectFieldClass extends React.Component<IPropsClass, IState> {
|
||||||
|
private contentRef = React.createRef<HTMLUListElement>();
|
||||||
|
private rootRef = React.createRef<HTMLDivElement>();
|
||||||
|
private removeOnresize = () => {};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: IPropsClass) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isOpen: false,
|
||||||
|
listHeight: 0,
|
||||||
|
listWidth: 0,
|
||||||
|
selectedOption: null,
|
||||||
|
errors: this.props.errors ?? null,
|
||||||
|
};
|
||||||
|
this.toggle = this.toggle.bind(this);
|
||||||
|
this.onSelect = this.onSelect.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render(): JSX.Element {
|
||||||
|
const selectedOption = this.state.selectedOption ?? this.props.selectedOption;
|
||||||
|
return (
|
||||||
|
<div className={classes["container"]}>
|
||||||
|
<div
|
||||||
|
className={classNames(classes["root"], this.props.className)}
|
||||||
|
ref={this.rootRef}
|
||||||
|
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
|
||||||
|
className={classNames(classes["container-label"])}
|
||||||
|
data-open={this.state.isOpen}
|
||||||
|
onClick={this.toggle}
|
||||||
|
data-border-right-collapsed={this.props.hasBorderRightCollapsed}>
|
||||||
|
<div className={classNames(classes["container-input"])}>
|
||||||
|
{selectedOption && (
|
||||||
|
<>
|
||||||
|
<span className={classNames(classes["icon"], classes["token-icon"])}>{selectedOption?.icon}</span>
|
||||||
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>
|
||||||
|
<span className={classes["text"]}>{selectedOption?.label}</span>
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!selectedOption && (
|
||||||
|
<div className={classes["placeholder"]} data-open={(selectedOption ? true : false).toString()}>
|
||||||
|
<Typography typo={ETypo.TEXT_MD_REGULAR}>
|
||||||
|
<span className={classes["text"]}>{this.props.placeholder ?? ""}</span>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Image className={classes["chevron-icon"]} data-open={this.state.isOpen} src={ChevronIcon} alt="chevron icon" />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<ul
|
||||||
|
className={classes["container-ul"]}
|
||||||
|
data-open={this.state.isOpen}
|
||||||
|
ref={this.contentRef}
|
||||||
|
style={{
|
||||||
|
height: this.state.listHeight + "px",
|
||||||
|
}}>
|
||||||
|
{this.props.options.map((option, index) => (
|
||||||
|
<li
|
||||||
|
key={`${index}-${option.value}`}
|
||||||
|
className={classes["container-li"]}
|
||||||
|
onClick={(e) => this.onSelect(option, e)}>
|
||||||
|
<div className={classes["token-icon"]}>{option.icon}</div>
|
||||||
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>{option.label}</Typography>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{this.state.isOpen && <div className={classes["backdrop"]} onClick={this.toggle} />}
|
||||||
|
</div>
|
||||||
|
{this.state.errors !== null && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||||
|
</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) {
|
||||||
|
this.setState({
|
||||||
|
errors: this.props.errors ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.selectedOption !== prevProps.selectedOption) {
|
||||||
|
this.setState({
|
||||||
|
selectedOption: this.props.selectedOption ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromProps(props: IProps, state: IState) {
|
||||||
|
if (props.selectedOption?.value) {
|
||||||
|
return {
|
||||||
|
value: props.selectedOption?.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onResize() {
|
||||||
|
let listHeight = 0;
|
||||||
|
let listWidth = 0;
|
||||||
|
listWidth = this.rootRef.current?.scrollWidth ?? 0;
|
||||||
|
if (this.state.listHeight) {
|
||||||
|
listHeight = this.contentRef.current?.scrollHeight ?? 0;
|
||||||
|
}
|
||||||
|
this.setState({ listHeight, listWidth });
|
||||||
|
}
|
||||||
|
|
||||||
|
private toggle(e: FormEvent) {
|
||||||
|
if (this.props.disabled) return;
|
||||||
|
e.preventDefault();
|
||||||
|
let listHeight = 0;
|
||||||
|
let listWidth = this.rootRef.current?.scrollWidth ?? 0;
|
||||||
|
|
||||||
|
if (!this.state.listHeight) {
|
||||||
|
listHeight = this.contentRef.current?.scrollHeight ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState((state) => {
|
||||||
|
return { isOpen: !state.isOpen, listHeight, listWidth };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private onSelect(option: IOptionOld, e: React.MouseEvent<HTMLLIElement, MouseEvent>) {
|
||||||
|
if (this.props.disabled) return;
|
||||||
|
this.props.onChange && this.props.onChange(option);
|
||||||
|
this.setState({
|
||||||
|
selectedOption: option,
|
||||||
|
});
|
||||||
|
this.toggle(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderErrors(): JSX.Element | null {
|
||||||
|
if (!this.state.errors) return null;
|
||||||
|
return (
|
||||||
|
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_ERROR_600}>
|
||||||
|
{this.props.placeholder} ne peut pas être vide
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SelectField(props: IProps) {
|
||||||
|
const router = useRouter();
|
||||||
|
return <SelectFieldClass {...props} router={router} />;
|
||||||
|
}
|
@ -1,28 +1,28 @@
|
|||||||
|
import { ValidationError } from "class-validator";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select";
|
import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select";
|
||||||
|
|
||||||
import { IOption } from "../Form/SelectField";
|
import { IOptionOld } from "../Form/SelectFieldOld";
|
||||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { styles } from "./styles";
|
import { styles } from "./styles";
|
||||||
import { ValidationError } from "class-validator";
|
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
options: IOption[];
|
options: IOptionOld[];
|
||||||
label?: string | JSX.Element;
|
label?: string | JSX.Element;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
onChange?: (newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) => void;
|
onChange?: (newValue: MultiValue<IOptionOld>, actionMeta: ActionMeta<IOptionOld>) => void;
|
||||||
defaultValue?: PropsValue<IOption>;
|
defaultValue?: PropsValue<IOptionOld>;
|
||||||
value?: PropsValue<IOption>;
|
value?: PropsValue<IOptionOld>;
|
||||||
isMulti?: boolean;
|
isMulti?: boolean;
|
||||||
shouldCloseMenuOnSelect: boolean;
|
shouldCloseMenuOnSelect: boolean;
|
||||||
isOptionDisabled?: (option: IOption, selectValue: Options<IOption>) => boolean;
|
isOptionDisabled?: (option: IOptionOld, selectValue: Options<IOptionOld>) => boolean;
|
||||||
validationError?: ValidationError;
|
validationError?: ValidationError;
|
||||||
};
|
};
|
||||||
type IState = {
|
type IState = {
|
||||||
isFocused: boolean;
|
isFocused: boolean;
|
||||||
selectedOptions: MultiValue<IOption>;
|
selectedOptions: MultiValue<IOptionOld>;
|
||||||
validationError: ValidationError | null;
|
validationError: ValidationError | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ export default class MultiSelect extends React.Component<IProps, IState> {
|
|||||||
this.setState({ isFocused: false });
|
this.setState({ isFocused: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
private onChange(newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) {
|
private onChange(newValue: MultiValue<IOptionOld>, actionMeta: ActionMeta<IOptionOld>) {
|
||||||
this.props.onChange && this.props.onChange(newValue, actionMeta);
|
this.props.onChange && this.props.onChange(newValue, actionMeta);
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedOptions: newValue,
|
selectedOptions: newValue,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
@import "@Themes/constants.scss";
|
@import "@Themes/constants.scss";
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
|
height: 56px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--spacing-2, 16px) var(--spacing-sm, 8px);
|
padding: var(--spacing-2, 16px) var(--spacing-sm, 8px);
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@ -10,6 +12,10 @@
|
|||||||
border: 1px solid var(--input-main-border-default, #d7dce0);
|
border: 1px solid var(--input-main-border-default, #d7dce0);
|
||||||
background: var(--input-background, #fff);
|
background: var(--input-background, #fff);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
stroke: var(--button-icon-button-default-default);
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-radius: var(--input-radius, 0px);
|
border-radius: var(--input-radius, 0px);
|
||||||
border: 1px solid var(--input-main-border-hovered, #b4bec5);
|
border: 1px solid var(--input-main-border-hovered, #b4bec5);
|
||||||
@ -28,8 +34,14 @@
|
|||||||
background: var(--input-background, #fff);
|
background: var(--input-background, #fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[data-is-disabled="true"] {
|
||||||
|
opacity: var(--opacity-disabled, 0.3);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.input-container {
|
.input-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 0px var(--spacing-2, 16px);
|
padding: 0px var(--spacing-2, 16px);
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
onChange?: (input: string) => void;
|
onChange?: (input: string) => void;
|
||||||
|
value?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SearchBar({ onChange, placeholder = "Rechercher" }: IProps) {
|
export default function SearchBar({ onChange, value: propValue, placeholder = "Rechercher", disabled = false }: IProps) {
|
||||||
const [isFocused, setIsFocused] = React.useState(false);
|
const [isFocused, setIsFocused] = React.useState(false);
|
||||||
const [value, setValue] = React.useState("");
|
const [value, setValue] = React.useState(propValue || "");
|
||||||
|
|
||||||
const changeValue = useCallback(
|
const changeValue = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
@ -25,8 +27,14 @@ export default function SearchBar({ onChange, placeholder = "Rechercher" }: IPro
|
|||||||
const handleBlur = () => setIsFocused(false);
|
const handleBlur = () => setIsFocused(false);
|
||||||
const clearValue = () => changeValue("");
|
const clearValue = () => changeValue("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (propValue !== undefined) {
|
||||||
|
setValue(propValue);
|
||||||
|
}
|
||||||
|
}, [propValue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className={classes["root"]} data-is-focused={isFocused} data-has-value={value !== ""}>
|
<label className={classes["root"]} data-is-focused={isFocused} data-has-value={value !== ""} data-is-disabled={disabled}>
|
||||||
<div className={classes["input-container"]}>
|
<div className={classes["input-container"]}>
|
||||||
<MagnifyingGlassIcon width="24" height="24" />
|
<MagnifyingGlassIcon width="24" height="24" />
|
||||||
<input
|
<input
|
||||||
|
@ -3,7 +3,6 @@ import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles";
|
|||||||
import Roles from "@Front/Api/LeCoffreApi/Admin/Roles/Roles";
|
import Roles from "@Front/Api/LeCoffreApi/Admin/Roles/Roles";
|
||||||
import Users from "@Front/Api/LeCoffreApi/Admin/Users/Users";
|
import Users from "@Front/Api/LeCoffreApi/Admin/Users/Users";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import SelectField, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
|
||||||
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
||||||
import Switch from "@Front/Components/DesignSystem/Switch";
|
import Switch from "@Front/Components/DesignSystem/Switch";
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||||
@ -15,6 +14,9 @@ import { useRouter } from "next/router";
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||||
|
import { getLabel } from "@Front/Components/DesignSystem/Dropdown";
|
||||||
|
import SelectField from "@Front/Components/DesignSystem/Form/SelectField";
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
export default function CollaboratorInformations(props: IProps) {
|
export default function CollaboratorInformations(props: IProps) {
|
||||||
@ -44,7 +46,7 @@ export default function CollaboratorInformations(props: IProps) {
|
|||||||
const closeRoleModal = useCallback(() => {
|
const closeRoleModal = useCallback(() => {
|
||||||
setRoleModalOpened(false);
|
setRoleModalOpened(false);
|
||||||
setSelectedOption({
|
setSelectedOption({
|
||||||
value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid,
|
id: (userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid) ?? "",
|
||||||
label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint",
|
label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint",
|
||||||
});
|
});
|
||||||
}, [userSelected?.office_role, userSelected?.role?.uid]);
|
}, [userSelected?.office_role, userSelected?.role?.uid]);
|
||||||
@ -55,7 +57,7 @@ export default function CollaboratorInformations(props: IProps) {
|
|||||||
User.hydrate<User>({
|
User.hydrate<User>({
|
||||||
uid: userSelected?.uid as string,
|
uid: userSelected?.uid as string,
|
||||||
office_role: OfficeRole.hydrate<OfficeRole>({
|
office_role: OfficeRole.hydrate<OfficeRole>({
|
||||||
uid: selectedOption?.value as string,
|
uid: selectedOption?.id as string,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -134,10 +136,10 @@ export default function CollaboratorInformations(props: IProps) {
|
|||||||
|
|
||||||
const roles = await OfficeRoles.getInstance().get();
|
const roles = await OfficeRoles.getInstance().get();
|
||||||
if (!roles) return;
|
if (!roles) return;
|
||||||
setAvailableRoles(roles.map((role) => ({ value: role.uid, label: role.name })));
|
setAvailableRoles(roles.map((role) => ({ id: role.uid ?? "", label: role.name })));
|
||||||
setUserSelected(user);
|
setUserSelected(user);
|
||||||
setSelectedOption({
|
setSelectedOption({
|
||||||
value: user?.office_role ? user?.office_role?.uid : user?.role?.uid,
|
id: (user?.office_role ? user?.office_role?.uid : user?.role?.uid) ?? "",
|
||||||
label: user?.office_role ? user?.office_role?.name : "Utilisateur restreint",
|
label: user?.office_role ? user?.office_role?.name : "Utilisateur restreint",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -206,8 +208,8 @@ export default function CollaboratorInformations(props: IProps) {
|
|||||||
options={availableRoles.filter((role) => {
|
options={availableRoles.filter((role) => {
|
||||||
return role.label !== "admin";
|
return role.label !== "admin";
|
||||||
})}
|
})}
|
||||||
selectedOption={selectedOption!}
|
onSelect={handleRoleChange}
|
||||||
onChange={handleRoleChange}
|
selectedOption={selectedOption}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{userSelected?.role?.name !== "super-admin" && (
|
{userSelected?.role?.name !== "super-admin" && (
|
||||||
@ -226,7 +228,7 @@ export default function CollaboratorInformations(props: IProps) {
|
|||||||
cancelText={"Annuler"}>
|
cancelText={"Annuler"}>
|
||||||
<div className={classes["modal-content"]}>
|
<div className={classes["modal-content"]}>
|
||||||
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
|
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
|
||||||
Attribuer le rôle de <span className={classes["role-name"]}>{selectedOption?.label}</span> à{" "}
|
Attribuer le rôle de <span className={classes["role-name"]}>{getLabel(selectedOption)}</span> à{" "}
|
||||||
{userSelected?.contact?.first_name} {userSelected?.contact?.last_name} ?
|
{userSelected?.contact?.first_name} {userSelected?.contact?.last_name} ?
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,9 +4,10 @@ import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes";
|
|||||||
import DocumentTypes from "@Front/Api/LeCoffreApi/Admin/DocumentTypes/DocumentTypes";
|
import DocumentTypes from "@Front/Api/LeCoffreApi/Admin/DocumentTypes/DocumentTypes";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
|
||||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||||
|
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
||||||
|
import Tooltip from "@Front/Components/DesignSystem/ToolTip";
|
||||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||||
import DefaultDeedTypesDashboard from "@Front/Components/LayoutTemplates/DefaultDeedTypeDashboard";
|
import DefaultDeedTypesDashboard from "@Front/Components/LayoutTemplates/DefaultDeedTypeDashboard";
|
||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
@ -19,7 +20,6 @@ import { useCallback, useEffect, useState } from "react";
|
|||||||
import { MultiValue } from "react-select";
|
import { MultiValue } from "react-select";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import Tooltip from "@Front/Components/DesignSystem/ToolTip";
|
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
export default function DeedTypesInformations(props: IProps) {
|
export default function DeedTypesInformations(props: IProps) {
|
||||||
@ -28,7 +28,7 @@ export default function DeedTypesInformations(props: IProps) {
|
|||||||
|
|
||||||
const [deedTypeSelected, setDeedTypeSelected] = useState<DeedType | null>(null);
|
const [deedTypeSelected, setDeedTypeSelected] = useState<DeedType | null>(null);
|
||||||
const [availableDocuments, setAvailableDocuments] = useState<DocumentType[]>([]);
|
const [availableDocuments, setAvailableDocuments] = useState<DocumentType[]>([]);
|
||||||
const [selectedDocuments, setSelectedDocuments] = useState<IOption[]>([]);
|
const [selectedDocuments, setSelectedDocuments] = useState<IOptionOld[]>([]);
|
||||||
|
|
||||||
const [isDeleteModalOpened, setIsDeleteModalOpened] = useState<boolean>(false);
|
const [isDeleteModalOpened, setIsDeleteModalOpened] = useState<boolean>(false);
|
||||||
const [isSaveModalOpened, setIsSaveModalOpened] = useState<boolean>(false);
|
const [isSaveModalOpened, setIsSaveModalOpened] = useState<boolean>(false);
|
||||||
@ -71,7 +71,7 @@ export default function DeedTypesInformations(props: IProps) {
|
|||||||
setDeedTypeSelected(deedType);
|
setDeedTypeSelected(deedType);
|
||||||
|
|
||||||
if (!deedType.document_types) return;
|
if (!deedType.document_types) return;
|
||||||
const documentsOptions: IOption[] = deedType.document_types
|
const documentsOptions: IOptionOld[] = deedType.document_types
|
||||||
?.map((documentType) => {
|
?.map((documentType) => {
|
||||||
return {
|
return {
|
||||||
label: documentType.name,
|
label: documentType.name,
|
||||||
@ -106,11 +106,11 @@ export default function DeedTypesInformations(props: IProps) {
|
|||||||
closeSaveModal();
|
closeSaveModal();
|
||||||
}, [closeSaveModal, deedTypeUid, selectedDocuments]);
|
}, [closeSaveModal, deedTypeUid, selectedDocuments]);
|
||||||
|
|
||||||
const onDocumentChangeHandler = useCallback((values: MultiValue<IOption>) => {
|
const onDocumentChangeHandler = useCallback((values: MultiValue<IOptionOld>) => {
|
||||||
setSelectedDocuments(values as IOption[]);
|
setSelectedDocuments(values as IOptionOld[]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const formattedOptions: IOption[] = availableDocuments
|
const formattedOptions: IOptionOld[] = availableDocuments
|
||||||
.map((document) => ({
|
.map((document) => ({
|
||||||
label: document.name,
|
label: document.name,
|
||||||
value: document.uid,
|
value: document.uid,
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
import { useCallback, useMemo, useState } from "react";
|
import { useCallback, useMemo, useState } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
|
import Autocomplete from "@Front/Components/DesignSystem/Autocomplete";
|
||||||
|
|
||||||
export default function DesignSystem() {
|
export default function DesignSystem() {
|
||||||
const { isOpen, open, close } = useOpenable();
|
const { isOpen, open, close } = useOpenable();
|
||||||
@ -81,7 +82,31 @@ export default function DesignSystem() {
|
|||||||
<Typography typo={ETypo.DISPLAY_LARGE}>DesignSystem</Typography>
|
<Typography typo={ETypo.DISPLAY_LARGE}>DesignSystem</Typography>
|
||||||
<Newsletter isOpen={false} />
|
<Newsletter isOpen={false} />
|
||||||
<div className={classes["root"]}>
|
<div className={classes["root"]}>
|
||||||
|
<div />
|
||||||
<div className={classes["components"]}>
|
<div className={classes["components"]}>
|
||||||
|
<Typography typo={ETypo.TEXT_LG_BOLD}>Autocomplete</Typography>
|
||||||
|
<Autocomplete
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
label: "Option 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
label: "Option 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
label: "Option 3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
label: { text: "Option 4", subtext: "Subtext" },
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
placeholder="Placeholder"
|
||||||
|
label="Label"
|
||||||
|
/>
|
||||||
<Typography typo={ETypo.TEXT_LG_BOLD}>Dropdown</Typography>
|
<Typography typo={ETypo.TEXT_LG_BOLD}>Dropdown</Typography>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
options={[
|
options={[
|
||||||
@ -97,11 +122,14 @@ export default function DesignSystem() {
|
|||||||
id: "3",
|
id: "3",
|
||||||
label: "Option 3",
|
label: "Option 3",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
label: { text: "Option 4", subtext: "Subtext" },
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
placeholder="Placeholder"
|
placeholder="Placeholder"
|
||||||
|
label="Label"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div className={classes["components"]}>
|
|
||||||
<Typography typo={ETypo.TEXT_LG_BOLD}>Navigation latérale</Typography>
|
<Typography typo={ETypo.TEXT_LG_BOLD}>Navigation latérale</Typography>
|
||||||
<SearchBlockList
|
<SearchBlockList
|
||||||
blocks={[
|
blocks={[
|
||||||
|
@ -2,7 +2,7 @@ import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers";
|
|||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
@ -27,8 +27,8 @@ type IProps = {};
|
|||||||
type IState = {
|
type IState = {
|
||||||
selectedOption: ESelectedOption;
|
selectedOption: ESelectedOption;
|
||||||
availableCustomers: Customer[];
|
availableCustomers: Customer[];
|
||||||
selectedCustomers: readonly IOption[];
|
selectedCustomers: readonly IOptionOld[];
|
||||||
existingCustomers: IOption[];
|
existingCustomers: IOptionOld[];
|
||||||
isLoaded: boolean;
|
isLoaded: boolean;
|
||||||
validationError: ValidationError[];
|
validationError: ValidationError[];
|
||||||
};
|
};
|
||||||
@ -54,7 +54,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
this.onFormSubmit = this.onFormSubmit.bind(this);
|
this.onFormSubmit = this.onFormSubmit.bind(this);
|
||||||
}
|
}
|
||||||
public override render(): JSX.Element {
|
public override render(): JSX.Element {
|
||||||
const selectOptions: IOption[] = this.getSelectedOptions();
|
const selectOptions: IOptionOld[] = this.getSelectedOptions();
|
||||||
|
|
||||||
const backwardPath = Module.getInstance()
|
const backwardPath = Module.getInstance()
|
||||||
.get()
|
.get()
|
||||||
@ -153,7 +153,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
public override async componentDidMount() {
|
public override async componentDidMount() {
|
||||||
const query = {};
|
const query = {};
|
||||||
const availableCustomers = await Customers.getInstance().get(query);
|
const availableCustomers = await Customers.getInstance().get(query);
|
||||||
let preExistingCustomers: IOption[] | undefined = await this.getFolderPreSelectedCustomers(this.props.selectedFolderUid);
|
let preExistingCustomers: IOptionOld[] | undefined = await this.getFolderPreSelectedCustomers(this.props.selectedFolderUid);
|
||||||
const existingCustomers = preExistingCustomers ?? [];
|
const existingCustomers = preExistingCustomers ?? [];
|
||||||
|
|
||||||
existingCustomers.forEach((customer) => {
|
existingCustomers.forEach((customer) => {
|
||||||
@ -169,7 +169,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
this.setState({ availableCustomers, existingCustomers, isLoaded: true, selectedOption });
|
this.setState({ availableCustomers, existingCustomers, isLoaded: true, selectedOption });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getFolderPreSelectedCustomers(folderUid: string): Promise<IOption[] | undefined> {
|
private async getFolderPreSelectedCustomers(folderUid: string): Promise<IOptionOld[] | undefined> {
|
||||||
const query = {
|
const query = {
|
||||||
q: {
|
q: {
|
||||||
customers: {
|
customers: {
|
||||||
@ -179,7 +179,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let preExistingCustomers: IOption[] = [];
|
let preExistingCustomers: IOptionOld[] = [];
|
||||||
try {
|
try {
|
||||||
const folder = await Folders.getInstance().getByUid(folderUid, query);
|
const folder = await Folders.getInstance().getByUid(folderUid, query);
|
||||||
preExistingCustomers = folder.customers!.map((customer) => {
|
preExistingCustomers = folder.customers!.map((customer) => {
|
||||||
@ -195,7 +195,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
return preExistingCustomers;
|
return preExistingCustomers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSelectedOptions(): IOption[] {
|
private getSelectedOptions(): IOptionOld[] {
|
||||||
let options = this.state.availableCustomers?.map((customer) => {
|
let options = this.state.availableCustomers?.map((customer) => {
|
||||||
return {
|
return {
|
||||||
label: customer.contact?.first_name + " " + customer.contact?.last_name,
|
label: customer.contact?.first_name + " " + customer.contact?.last_name,
|
||||||
@ -206,7 +206,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMutiSelectChange(selectedCustomers: readonly IOption[]): void {
|
private onMutiSelectChange(selectedCustomers: readonly IOptionOld[]): void {
|
||||||
this.setState({ selectedCustomers });
|
this.setState({ selectedCustomers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
|
||||||
import classes from "./classes.module.scss";
|
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
|
||||||
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
|
||||||
import { ChangeEvent, useCallback, useEffect, useState } from "react";
|
|
||||||
import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes";
|
|
||||||
import { DocumentType, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
|
||||||
import Deeds from "@Front/Api/LeCoffreApi/Notary/Deeds/Deeds";
|
import Deeds from "@Front/Api/LeCoffreApi/Notary/Deeds/Deeds";
|
||||||
|
import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes";
|
||||||
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
|
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
||||||
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||||
import { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
||||||
import { MultiValue } from "react-select";
|
|
||||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
|
import { DocumentType, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||||
|
import { ChangeEvent, useCallback, useEffect, useState } from "react";
|
||||||
|
import { MultiValue } from "react-select";
|
||||||
|
|
||||||
|
import classes from "./classes.module.scss";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
isCreateDocumentModalVisible: boolean;
|
isCreateDocumentModalVisible: boolean;
|
||||||
@ -24,13 +25,13 @@ export default function ParameterDocuments(props: IProps) {
|
|||||||
|
|
||||||
const [addOrEditDocument, setAddOrEditDocument] = useState<"add" | "edit">("edit");
|
const [addOrEditDocument, setAddOrEditDocument] = useState<"add" | "edit">("edit");
|
||||||
|
|
||||||
const [selectedDocuments, setSelectedDocuments] = useState<IOption[]>([]);
|
const [selectedDocuments, setSelectedDocuments] = useState<IOptionOld[]>([]);
|
||||||
const [formattedOptions, setFormattedOptions] = useState<IOption[]>([]);
|
const [formattedOptions, setFormattedOptions] = useState<IOptionOld[]>([]);
|
||||||
|
|
||||||
const getAvailableDocuments = useCallback(async () => {
|
const getAvailableDocuments = useCallback(async () => {
|
||||||
const documents = await DocumentTypes.getInstance().get({});
|
const documents = await DocumentTypes.getInstance().get({});
|
||||||
|
|
||||||
const formattedOptions: IOption[] = documents
|
const formattedOptions: IOptionOld[] = documents
|
||||||
.filter((document) => {
|
.filter((document) => {
|
||||||
return !props.folder.deed?.document_types?.some((documentType) => documentType.uid === document.uid);
|
return !props.folder.deed?.document_types?.some((documentType) => documentType.uid === document.uid);
|
||||||
})
|
})
|
||||||
@ -52,8 +53,8 @@ export default function ParameterDocuments(props: IProps) {
|
|||||||
setDocumentName(event.target.value);
|
setDocumentName(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDocumentChangeHandler = useCallback((values: MultiValue<IOption>) => {
|
const onDocumentChangeHandler = useCallback((values: MultiValue<IOptionOld>) => {
|
||||||
setSelectedDocuments(values as IOption[]);
|
setSelectedDocuments(values as IOptionOld[]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { PlusIcon } from "@heroicons/react/24/outline";
|
|
||||||
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
|
import Documents from "@Front/Api/LeCoffreApi/Notary/Documents/Documents";
|
||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
|
import CheckBox from "@Front/Components/DesignSystem/CheckBox";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
|
||||||
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 DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
|
import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard";
|
||||||
import Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
|
import { PlusIcon } from "@heroicons/react/24/outline";
|
||||||
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||||
import { NextRouter, useRouter } from "next/router";
|
import { NextRouter, useRouter } from "next/router";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -16,6 +15,7 @@ import React from "react";
|
|||||||
import BasePage from "../../Base";
|
import BasePage from "../../Base";
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import ParameterDocuments from "./ParameterDocuments";
|
import ParameterDocuments from "./ParameterDocuments";
|
||||||
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
type IPropsClass = IProps & {
|
type IPropsClass = IProps & {
|
||||||
@ -25,7 +25,7 @@ type IPropsClass = IProps & {
|
|||||||
};
|
};
|
||||||
type IState = {
|
type IState = {
|
||||||
isCreateDocumentModalVisible: boolean;
|
isCreateDocumentModalVisible: boolean;
|
||||||
documentTypes: IOption[];
|
documentTypes: IOptionOld[];
|
||||||
folder: OfficeFolder | null;
|
folder: OfficeFolder | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ class AskDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getAvailableDocuments(folder: OfficeFolder): Promise<IOption[]> {
|
private async getAvailableDocuments(folder: OfficeFolder): Promise<IOptionOld[]> {
|
||||||
// Getting already asked documents UIDs in an array
|
// Getting already asked documents UIDs in an array
|
||||||
const userDocumentTypesUids = folder
|
const userDocumentTypesUids = folder
|
||||||
.documents!.filter((document) => document.depositor!.uid! === this.props.customerUid!)
|
.documents!.filter((document) => document.depositor!.uid! === this.props.customerUid!)
|
||||||
@ -157,7 +157,7 @@ class AskDocumentsClass extends BasePage<IPropsClass, IState> {
|
|||||||
if (!documentTypes) return [];
|
if (!documentTypes) return [];
|
||||||
|
|
||||||
// Else, return an array document types formatted as IOPtions
|
// Else, return an array document types formatted as IOPtions
|
||||||
const documentTypesOptions: IOption[] = documentTypes.map((documentType) => {
|
const documentTypesOptions: IOptionOld[] = documentTypes.map((documentType) => {
|
||||||
return {
|
return {
|
||||||
label: documentType!.name!,
|
label: documentType!.name!,
|
||||||
value: documentType!.uid!,
|
value: documentType!.uid!,
|
||||||
|
@ -3,25 +3,27 @@ import DeedTypes from "@Front/Api/LeCoffreApi/Notary/DeedTypes/DeedTypes";
|
|||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
||||||
import Button from "@Front/Components/DesignSystem/Button";
|
import Button from "@Front/Components/DesignSystem/Button";
|
||||||
|
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import SelectField, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import SelectField from "@Front/Components/DesignSystem/Form/SelectField";
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
||||||
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||||
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 JwtService from "@Front/Services/JwtService/JwtService";
|
||||||
import { ValidationError } from "class-validator/types/validation/ValidationError";
|
import { ValidationError } from "class-validator/types/validation/ValidationError";
|
||||||
import { Deed, Office, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
import { Deed, Office, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||||
import User from "le-coffre-resources/dist/Notary";
|
import User from "le-coffre-resources/dist/Notary";
|
||||||
|
import { DeedType } from "le-coffre-resources/dist/Notary";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { MultiValue } from "react-select";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
|
||||||
import { DeedType } from "le-coffre-resources/dist/Notary";
|
|
||||||
import { MultiValue } from "react-select";
|
|
||||||
|
|
||||||
export default function CreateFolder(): JSX.Element {
|
export default function CreateFolder(): JSX.Element {
|
||||||
/**
|
/**
|
||||||
@ -87,7 +89,7 @@ export default function CreateFolder(): JSX.Element {
|
|||||||
const radioOnChange = (e: React.ChangeEvent<HTMLInputElement>) =>
|
const radioOnChange = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
setFolderAccessType(e.target.value as "whole_office" | "select_collaborators");
|
setFolderAccessType(e.target.value as "whole_office" | "select_collaborators");
|
||||||
|
|
||||||
const onSelectedCollaboratorsChange = (values: MultiValue<IOption>) => {
|
const onSelectedCollaboratorsChange = (values: MultiValue<IOptionOld>) => {
|
||||||
const selectedCollaborators = availableCollaborators.filter((collaborator) =>
|
const selectedCollaborators = availableCollaborators.filter((collaborator) =>
|
||||||
values.some((value) => value.value === collaborator.uid),
|
values.some((value) => value.value === collaborator.uid),
|
||||||
);
|
);
|
||||||
@ -142,16 +144,18 @@ export default function CreateFolder(): JSX.Element {
|
|||||||
validationError={validationError.find((error) => error.property === "name")}
|
validationError={validationError.find((error) => error.property === "name")}
|
||||||
/>
|
/>
|
||||||
<SelectField
|
<SelectField
|
||||||
|
name="deed"
|
||||||
|
label="Type d'acte"
|
||||||
|
placeholder="Sélectionner un type d'acte"
|
||||||
options={
|
options={
|
||||||
availableDeedTypes.map((deedType) => ({
|
availableDeedTypes.map((deedType) => ({
|
||||||
|
id: deedType.uid,
|
||||||
label: deedType.name,
|
label: deedType.name,
|
||||||
value: deedType.uid,
|
|
||||||
})) as IOption[]
|
})) as IOption[]
|
||||||
}
|
}
|
||||||
name="deed"
|
validationError={validationError.find((error) => error.property === "deed")}
|
||||||
placeholder={"Type d'acte"}
|
|
||||||
errors={validationError.find((error) => error.property === "deed")}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextAreaField
|
<TextAreaField
|
||||||
name="description"
|
name="description"
|
||||||
label="Note de dossier"
|
label="Note de dossier"
|
||||||
@ -179,7 +183,7 @@ export default function CreateFolder(): JSX.Element {
|
|||||||
availableCollaborators.map((collaborator) => ({
|
availableCollaborators.map((collaborator) => ({
|
||||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name),
|
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name),
|
||||||
value: collaborator.uid,
|
value: collaborator.uid,
|
||||||
})) as IOption[]
|
})) as IOptionOld[]
|
||||||
}
|
}
|
||||||
defaultValue={selectedCollaborators.map((collaborator) => ({
|
defaultValue={selectedCollaborators.map((collaborator) => ({
|
||||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) as string,
|
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) as string,
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
|
import backgroundImage from "@Assets/images/background_refonte.svg";
|
||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Users, { IGetUsersParams } from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
import Users, { IGetUsersParams } from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } 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 Module from "@Front/Config/Module";
|
import Module from "@Front/Config/Module";
|
||||||
|
import { ValidationError } from "class-validator";
|
||||||
import User from "le-coffre-resources/dist/Notary/User";
|
import User from "le-coffre-resources/dist/Notary/User";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import classes from "./classes.module.scss";
|
import classes from "./classes.module.scss";
|
||||||
import { ValidationError } from "class-validator";
|
|
||||||
import backgroundImage from "@Assets/images/background_refonte.svg";
|
|
||||||
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
|
||||||
import { useCallback, useEffect, useState } from "react";
|
|
||||||
|
|
||||||
enum ERadioBoxValue {
|
enum ERadioBoxValue {
|
||||||
ALL = "all",
|
ALL = "all",
|
||||||
@ -28,7 +28,7 @@ export default function UpdateFolderCollaborators() {
|
|||||||
let { folderUid } = router.query;
|
let { folderUid } = router.query;
|
||||||
|
|
||||||
const [availableCollaborators, setAvailableCollaborators] = useState<User[]>([]);
|
const [availableCollaborators, setAvailableCollaborators] = useState<User[]>([]);
|
||||||
const [selectedCollaborators, setSelectedCollaborators] = useState<readonly IOption[]>([]);
|
const [selectedCollaborators, setSelectedCollaborators] = useState<readonly IOptionOld[]>([]);
|
||||||
const [defaultCheckedAllOffice, setDefaultCheckedAllOffice] = useState<boolean>(false);
|
const [defaultCheckedAllOffice, setDefaultCheckedAllOffice] = useState<boolean>(false);
|
||||||
const [selectedOption, setSelectedOption] = useState<ERadioBoxValue>(ERadioBoxValue.SELECTION);
|
const [selectedOption, setSelectedOption] = useState<ERadioBoxValue>(ERadioBoxValue.SELECTION);
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
@ -61,7 +61,7 @@ export default function UpdateFolderCollaborators() {
|
|||||||
setSelectedOption(ERadioBoxValue.ALL);
|
setSelectedOption(ERadioBoxValue.ALL);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onChangeSelectedCollaborators = useCallback((selectedCollaborators: readonly IOption[]) => {
|
const onChangeSelectedCollaborators = useCallback((selectedCollaborators: readonly IOptionOld[]) => {
|
||||||
setSelectedCollaborators(selectedCollaborators);
|
setSelectedCollaborators(selectedCollaborators);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ export default function UpdateFolderCollaborators() {
|
|||||||
let folder = null;
|
let folder = null;
|
||||||
try {
|
try {
|
||||||
folder = await Folders.getInstance().getByUid(folderUid, query);
|
folder = await Folders.getInstance().getByUid(folderUid, query);
|
||||||
const preSelectedCollaborators: IOption[] = folder.stakeholders!.map((collaborator) => {
|
const preSelectedCollaborators: IOptionOld[] = folder.stakeholders!.map((collaborator) => {
|
||||||
return {
|
return {
|
||||||
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
||||||
value: collaborator.uid,
|
value: collaborator.uid,
|
||||||
@ -126,7 +126,7 @@ export default function UpdateFolderCollaborators() {
|
|||||||
|
|
||||||
const foldersInformationPath = Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path;
|
const foldersInformationPath = Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path;
|
||||||
const backwardPath = foldersInformationPath.replace("[folderUid]", folderUid as string);
|
const backwardPath = foldersInformationPath.replace("[folderUid]", folderUid as string);
|
||||||
const selectOptions: IOption[] = availableCollaborators.map((collaborator) => {
|
const selectOptions: IOptionOld[] = availableCollaborators.map((collaborator) => {
|
||||||
return {
|
return {
|
||||||
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
||||||
value: collaborator.uid,
|
value: collaborator.uid,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import Select, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import Select, { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||||
@ -81,7 +81,7 @@ export default function UpdateFolderMetadata() {
|
|||||||
const deedOption = {
|
const deedOption = {
|
||||||
label: selectedFolder?.deed?.deed_type?.name,
|
label: selectedFolder?.deed?.deed_type?.name,
|
||||||
value: selectedFolder?.deed?.deed_type?.uid,
|
value: selectedFolder?.deed?.deed_type?.uid,
|
||||||
} as IOption;
|
} as IOptionOld;
|
||||||
const openingDate = new Date(selectedFolder?.created_at ?? "");
|
const openingDate = new Date(selectedFolder?.created_at ?? "");
|
||||||
if (!selectedFolder?.created_at) return <></>;
|
if (!selectedFolder?.created_at) return <></>;
|
||||||
const defaultValue = openingDate.toISOString().split("T")[0];
|
const defaultValue = openingDate.toISOString().split("T")[0];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||||
import Form from "@Front/Components/DesignSystem/Form";
|
import Form from "@Front/Components/DesignSystem/Form";
|
||||||
import Select, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
|
import Select, { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||||
@ -18,7 +18,7 @@ type IProps = {
|
|||||||
};
|
};
|
||||||
type IState = {
|
type IState = {
|
||||||
selectedFolder: OfficeFolder | null;
|
selectedFolder: OfficeFolder | null;
|
||||||
selectedOption?: IOption;
|
selectedOption?: IOptionOld;
|
||||||
};
|
};
|
||||||
class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
@ -74,7 +74,7 @@ class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSelectedOption(option: IOption) {
|
private onSelectedOption(option: IOptionOld) {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedOption: option,
|
selectedOption: option,
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user