✨ change old multiselect with new autocomplete multi select
This commit is contained in:
parent
b33037d8df
commit
67ffca67f8
@ -13,12 +13,12 @@ type IProps = {
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
label?: string;
|
||||
onSelect?: (option: IOption) => void;
|
||||
onSelectionChange?: (option: IOption | null) => void;
|
||||
selectedOption?: IOption | null;
|
||||
};
|
||||
|
||||
export default function Autocomplete(props: IProps) {
|
||||
const { options, placeholder, disabled, label, selectedOption: selectedOptionProps } = props;
|
||||
const { onSelectionChange, 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);
|
||||
@ -47,17 +47,25 @@ export default function Autocomplete(props: IProps) {
|
||||
[openable],
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(option: IOption | null) => {
|
||||
setSelectedOption(option);
|
||||
onSelectionChange?.(option);
|
||||
},
|
||||
[onSelectionChange],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedOption(selectedOptionProps ?? null);
|
||||
}, [selectedOptionProps]);
|
||||
|
||||
const handleSelectOption = useCallback(
|
||||
(newOption: IOption, _options: IOption[]) => {
|
||||
setSelectedOption(newOption);
|
||||
handleChange(newOption);
|
||||
setSearchValue(getLabel(newOption) || "");
|
||||
openable.close();
|
||||
},
|
||||
[openable],
|
||||
[handleChange, openable],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -65,8 +73,7 @@ export default function Autocomplete(props: IProps) {
|
||||
options={filteredOptions}
|
||||
openable={openable}
|
||||
onSelect={handleSelectOption}
|
||||
selectedOptions={selectedOption ? [selectedOption] : []}
|
||||
>
|
||||
selectedOptions={selectedOption ? [selectedOption] : []}>
|
||||
<div className={classes["root"]}>
|
||||
{label && (
|
||||
<Typography className={classes["label"]} typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.CONTRAST_DEFAULT}>
|
||||
@ -79,7 +86,7 @@ export default function Autocomplete(props: IProps) {
|
||||
disabled={disabled}
|
||||
onChange={handleSearchChange}
|
||||
value={searchValue}
|
||||
onClear={() => setSelectedOption(null)}
|
||||
onClear={() => handleChange(null)}
|
||||
onFocus={openable.open}
|
||||
/>
|
||||
</DropdownMenu>
|
||||
|
@ -1,24 +1,24 @@
|
||||
import useOpenable from "@Front/Hooks/useOpenable";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { getLabel } from "../Dropdown";
|
||||
import DropdownMenu from "../Dropdown/DropdownMenu";
|
||||
import { IOption } from "../Dropdown/DropdownMenu/DropdownOption";
|
||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||
import classes from "./classes.module.scss";
|
||||
import ChipContainer from "./ChipContainer";
|
||||
import { getLabel } from "../Dropdown";
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
type IProps = {
|
||||
options: IOption[];
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
label?: string;
|
||||
onSelect?: (option: IOption) => void;
|
||||
onSelectionChange?: (options: IOption[] | null) => void;
|
||||
selectedOptions?: IOption[] | null;
|
||||
};
|
||||
|
||||
export default function AutocompleteMultiSelect(props: IProps) {
|
||||
const { options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props;
|
||||
const { onSelectionChange, options, placeholder, disabled, label, selectedOptions: selectedOptionsProps } = props;
|
||||
const [selectedOptions, setSelectedOptions] = useState<IOption[] | null>(selectedOptionsProps ?? null);
|
||||
const [searchValue, setSearchValue] = useState("");
|
||||
const [filteredOptions, setFilteredOptions] = useState<IOption[]>(options);
|
||||
@ -27,7 +27,6 @@ export default function AutocompleteMultiSelect(props: IProps) {
|
||||
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);
|
||||
@ -47,17 +46,25 @@ export default function AutocompleteMultiSelect(props: IProps) {
|
||||
[openable],
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(options: IOption[] | null) => {
|
||||
setSelectedOptions(options);
|
||||
onSelectionChange?.(options);
|
||||
},
|
||||
[onSelectionChange],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedOptions(selectedOptionsProps ?? null);
|
||||
}, [selectedOptionsProps]);
|
||||
|
||||
const handleSelectOption = useCallback(
|
||||
(_newOption: IOption, options: IOption[]) => {
|
||||
setSelectedOptions(options);
|
||||
handleChange(options);
|
||||
setSearchValue("");
|
||||
openable.close();
|
||||
},
|
||||
[openable],
|
||||
[handleChange, openable],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -78,10 +85,10 @@ export default function AutocompleteMultiSelect(props: IProps) {
|
||||
disabled={disabled}
|
||||
onChange={handleSearchChange}
|
||||
value={searchValue}
|
||||
onClear={() => setSelectedOptions(null)}
|
||||
onClear={() => handleChange(null)}
|
||||
onFocus={openable.open}
|
||||
selectedOptions={selectedOptions ?? []}
|
||||
onSelectedOptionsChange={setSelectedOptions}
|
||||
onSelectedOptionsChange={handleChange}
|
||||
/>
|
||||
</DropdownMenu>
|
||||
);
|
||||
|
@ -30,6 +30,7 @@
|
||||
padding: 0px var(--spacing-2, 16px);
|
||||
align-items: center;
|
||||
flex: 1 0 0;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -13,12 +13,12 @@ type IProps = {
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
onSelect?: (option: IOption) => void;
|
||||
onSelectionChange?: (option: IOption) => void;
|
||||
selectedOption?: IOption | null;
|
||||
};
|
||||
|
||||
export default function Dropdown(props: IProps) {
|
||||
const { options, placeholder, disabled, onSelect, selectedOption: selectedOptionProps, label } = props;
|
||||
const { options, placeholder, disabled, onSelectionChange, selectedOption: selectedOptionProps, label } = props;
|
||||
const [selectedOption, setSelectedOption] = useState<IOption | null>(selectedOptionProps ?? null);
|
||||
const openable = useOpenable({ defaultOpen: false });
|
||||
|
||||
@ -29,9 +29,9 @@ export default function Dropdown(props: IProps) {
|
||||
const handleOnSelect = useCallback(
|
||||
(newOption: IOption, _options: IOption[]) => {
|
||||
setSelectedOption(newOption);
|
||||
onSelect?.(newOption);
|
||||
onSelectionChange?.(newOption);
|
||||
},
|
||||
[onSelect],
|
||||
[onSelectionChange],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -55,12 +55,7 @@ export default function Dropdown(props: IProps) {
|
||||
])}
|
||||
onClick={openable.toggle}>
|
||||
<div className={classes["content"]}>
|
||||
<Typography
|
||||
className={classes["value"]}
|
||||
typo={!!selectedOption ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
||||
color={!!selectedOption ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
||||
{getLabel(selectedOption) ?? placeholder}
|
||||
</Typography>
|
||||
{getLabelContent(selectedOption, placeholder)}
|
||||
<ChevronDownIcon />
|
||||
</div>
|
||||
</div>
|
||||
@ -74,5 +69,44 @@ export function getLabel(option: IOption | null): string | null {
|
||||
if (typeof option.label === "string") {
|
||||
return option.label;
|
||||
}
|
||||
return `${option.label.text} ${option.label.subtext}`;
|
||||
return `${option.label.text}, ${option.label.subtext}`;
|
||||
}
|
||||
|
||||
function getLabelContent(option: IOption | null, placeholder?: string) {
|
||||
if (!option)
|
||||
return (
|
||||
<Typography
|
||||
className={classes["value"]}
|
||||
typo={!!option ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
||||
color={!!option ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
||||
{placeholder}
|
||||
</Typography>
|
||||
);
|
||||
|
||||
if (typeof option.label === "string") {
|
||||
return (
|
||||
<Typography
|
||||
className={classes["value"]}
|
||||
typo={!!option ? ETypo.TEXT_MD_SEMIBOLD : ETypo.TEXT_MD_REGULAR}
|
||||
color={!!option ? ETypoColor.DROPDOWN_CONTRAST_ACTIVE : ETypoColor.DROPDOWN_CONTRAST_DEFAULT}>
|
||||
{option.label}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={classes["value"]}>
|
||||
<Typography
|
||||
typo={ETypo.TEXT_MD_LIGHT}
|
||||
color={!!option ? ETypoColor.NAVIGATION_BUTTON_CONTRAST_ACTIVE : ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
|
||||
{`${option.label.text} , `}
|
||||
</Typography>
|
||||
<Typography
|
||||
typo={ETypo.TEXT_MD_BOLD}
|
||||
type="span"
|
||||
color={!!option ? ETypoColor.NAVIGATION_BUTTON_CONTRAST_ACTIVE : ETypoColor.NAVIGATION_BUTTON_CONTRAST_DEFAULT}>
|
||||
{option.label.subtext}
|
||||
</Typography>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import BaseField, { IProps as IBaseFieldProps, IState as IBaseFieldState } from
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
export type IProps = IBaseFieldProps & {
|
||||
onSelect?: (option: IOption) => void;
|
||||
onSelectionChange?: (option: IOption | null) => void;
|
||||
options: IOption[];
|
||||
selectedOption?: IOption | null;
|
||||
label?: string;
|
||||
@ -28,9 +28,9 @@ export default class AutocompleteField extends BaseField<IProps, IState> {
|
||||
this.handleOnChange = this.handleOnChange.bind(this);
|
||||
}
|
||||
|
||||
private handleOnChange = (option: IOption) => {
|
||||
private handleOnChange = (option: IOption | null) => {
|
||||
this.setState({ selectedOption: option });
|
||||
this.props.onSelect?.(option);
|
||||
this.props.onSelectionChange?.(option);
|
||||
};
|
||||
|
||||
public override componentDidUpdate(prevProps: IProps): void {
|
||||
@ -45,9 +45,10 @@ export default class AutocompleteField extends BaseField<IProps, IState> {
|
||||
<Autocomplete
|
||||
options={this.props.options}
|
||||
placeholder={this.props.placeholder}
|
||||
onSelect={this.handleOnChange}
|
||||
onSelectionChange={this.handleOnChange}
|
||||
selectedOption={this.state.selectedOption}
|
||||
label={this.props.label}
|
||||
disabled={this.props.disabled}
|
||||
/>
|
||||
{this.state.selectedOption && (
|
||||
<input
|
||||
|
@ -0,0 +1,11 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
.hidden-input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
.errors-container {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
import React from "react";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { IOption } from "../../Dropdown/DropdownMenu/DropdownOption";
|
||||
import BaseField, { IProps as IBaseFieldProps, IState as IBaseFieldState } from "../BaseField";
|
||||
import classes from "./classes.module.scss";
|
||||
import AutocompleteMultiSelect from "../../AutocompleteMultiSelect";
|
||||
|
||||
export type IProps = IBaseFieldProps & {
|
||||
onSelectionChange?: (options: IOption[] | null) => void;
|
||||
options: IOption[];
|
||||
selectedOptions?: IOption[] | null;
|
||||
label?: string;
|
||||
};
|
||||
|
||||
type IState = IBaseFieldState & {
|
||||
selectedOptions: IOption[] | null;
|
||||
};
|
||||
|
||||
export default class AutocompleteMultiSelectField extends BaseField<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedOptions: this.props.selectedOptions ?? null,
|
||||
...this.getDefaultState(),
|
||||
};
|
||||
|
||||
this.handleOnChange = this.handleOnChange.bind(this);
|
||||
}
|
||||
|
||||
private handleOnChange = (options: IOption[] | null) => {
|
||||
this.setState({ selectedOptions: options });
|
||||
this.props.onSelectionChange?.(options);
|
||||
};
|
||||
|
||||
public override componentDidUpdate(prevProps: IProps): void {
|
||||
if (prevProps.selectedOptions !== this.props.selectedOptions) {
|
||||
this.setState({ selectedOptions: this.props.selectedOptions ?? null });
|
||||
}
|
||||
}
|
||||
|
||||
public override render(): ReactNode {
|
||||
return (
|
||||
<div className={classes["root"]}>
|
||||
<AutocompleteMultiSelect
|
||||
options={this.props.options}
|
||||
placeholder={this.props.placeholder}
|
||||
onSelectionChange={this.handleOnChange}
|
||||
selectedOptions={this.state.selectedOptions}
|
||||
label={this.props.label}
|
||||
disabled={this.props.disabled}
|
||||
/>
|
||||
{this.state.selectedOptions && (
|
||||
<input
|
||||
className={classes["hidden-input"]}
|
||||
name={this.props.name}
|
||||
type="text"
|
||||
defaultValue={JSON.stringify(this.state.selectedOptions)}
|
||||
hidden
|
||||
/>
|
||||
)}
|
||||
{this.hasError() && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import classes from "./classes.module.scss";
|
||||
import Dropdown from "../../Dropdown";
|
||||
|
||||
export type IProps = IBaseFieldProps & {
|
||||
onSelect?: (option: IOption) => void;
|
||||
onSelectionChange?: (option: IOption) => void;
|
||||
options: IOption[];
|
||||
selectedOption?: IOption | null;
|
||||
label?: string;
|
||||
@ -30,7 +30,7 @@ export default class SelectField extends BaseField<IProps, IState> {
|
||||
|
||||
private handleOnChange = (option: IOption) => {
|
||||
this.setState({ selectedOption: option });
|
||||
this.props.onSelect?.(option);
|
||||
this.props.onSelectionChange?.(option);
|
||||
};
|
||||
|
||||
public override componentDidUpdate(prevProps: IProps): void {
|
||||
@ -45,9 +45,10 @@ export default class SelectField extends BaseField<IProps, IState> {
|
||||
<Dropdown
|
||||
options={this.props.options}
|
||||
placeholder={this.props.placeholder}
|
||||
onSelect={this.handleOnChange}
|
||||
onSelectionChange={this.handleOnChange}
|
||||
selectedOption={this.state.selectedOption}
|
||||
label={this.props.label}
|
||||
disabled={this.props.disabled}
|
||||
/>
|
||||
{this.state.selectedOption && (
|
||||
<input
|
||||
|
@ -1,79 +0,0 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
.label-container {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
background-color: transparent;
|
||||
|
||||
.placeholder {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: top 0.3s ease-in-out;
|
||||
background-color: white;
|
||||
padding: 0 4px;
|
||||
&[data-selected="true"] {
|
||||
top: -12px;
|
||||
}
|
||||
}
|
||||
.label {
|
||||
font-family: var(--font-text-family);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-primary-8);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
outline: none;
|
||||
gap: 16px;
|
||||
border: none;
|
||||
width: 100%;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
> div:first-of-type > div:first-of-type {
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.input-container {
|
||||
> div > div > div {
|
||||
padding: 24px 16px 16px 16px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-active-placeholder {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
left: 8px;
|
||||
background-color: #ffffff;
|
||||
z-index: 1;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
&[data-is-errored="true"] {
|
||||
.input {
|
||||
border: 1px solid var(--color-error-600);
|
||||
~ .fake-placeholder {
|
||||
color: var(--color-error-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
import { ValidationError } from "class-validator";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select";
|
||||
|
||||
import { IOptionOld } from "../Form/SelectFieldOld";
|
||||
import Typography, { ETypo, ETypoColor } from "../Typography";
|
||||
import classes from "./classes.module.scss";
|
||||
import { styles } from "./styles";
|
||||
|
||||
type IProps = {
|
||||
options: IOptionOld[];
|
||||
label?: string | JSX.Element;
|
||||
placeholder?: string;
|
||||
onChange?: (newValue: MultiValue<IOptionOld>, actionMeta: ActionMeta<IOptionOld>) => void;
|
||||
defaultValue?: PropsValue<IOptionOld>;
|
||||
value?: PropsValue<IOptionOld>;
|
||||
isMulti?: boolean;
|
||||
shouldCloseMenuOnSelect: boolean;
|
||||
isOptionDisabled?: (option: IOptionOld, selectValue: Options<IOptionOld>) => boolean;
|
||||
validationError?: ValidationError;
|
||||
};
|
||||
type IState = {
|
||||
isFocused: boolean;
|
||||
selectedOptions: MultiValue<IOptionOld>;
|
||||
validationError: ValidationError | null;
|
||||
};
|
||||
|
||||
export default class MultiSelect extends React.Component<IProps, IState> {
|
||||
public static defaultProps: Partial<IProps> = {
|
||||
placeholder: "Sélectionner une option...",
|
||||
shouldCloseMenuOnSelect: false,
|
||||
};
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isFocused: false,
|
||||
selectedOptions: [],
|
||||
validationError: this.props.validationError ?? null,
|
||||
};
|
||||
this.hasError = this.hasError.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onEmptyResearch = this.onEmptyResearch.bind(this);
|
||||
this.onFocus = this.onFocus.bind(this);
|
||||
this.onBlur = this.onBlur.bind(this);
|
||||
this.renderErrors = this.renderErrors.bind(this);
|
||||
}
|
||||
public override render(): JSX.Element {
|
||||
return (
|
||||
<div className={classes["root"]}>
|
||||
<div className={classNames(classes["label-container"], this.state.selectedOptions.length >= 1 && classes["active"])}>
|
||||
{this.props.label && <div className={classes["label"]}>{this.props.label}</div>}
|
||||
{this.props.placeholder && (
|
||||
<div
|
||||
className={classes["placeholder"]}
|
||||
data-selected={(this.state.isFocused || this.state.selectedOptions.length >= 1).toString()}>
|
||||
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
||||
{this.props.placeholder}
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
<div className={classes["input-container"]}>
|
||||
<ReactSelect
|
||||
placeholder={""}
|
||||
options={this.props.options}
|
||||
styles={styles}
|
||||
onChange={this.onChange}
|
||||
value={this.props.defaultValue}
|
||||
defaultValue={this.state.selectedOptions}
|
||||
closeMenuOnSelect={this.props.shouldCloseMenuOnSelect}
|
||||
isMulti
|
||||
isOptionDisabled={this.props.isOptionDisabled}
|
||||
noOptionsMessage={this.onEmptyResearch}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
classNamePrefix="react-select"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{this.hasError() && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public override componentDidMount(): void {
|
||||
if (this.props.defaultValue) {
|
||||
// If default value contains multiple IOptions
|
||||
if (Array.isArray(this.props.defaultValue)) {
|
||||
this.setState({ selectedOptions: this.props.defaultValue });
|
||||
}
|
||||
|
||||
// If default value is a single IOption
|
||||
if ("label" in this.props.defaultValue) {
|
||||
this.setState({ selectedOptions: [this.props.defaultValue] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override componentDidUpdate(prevProps: IProps): void {
|
||||
if (this.props.validationError !== prevProps.validationError) {
|
||||
this.setState({
|
||||
validationError: this.props.validationError ?? null,
|
||||
});
|
||||
}
|
||||
if (this.props.defaultValue && this.props.defaultValue !== prevProps.defaultValue) {
|
||||
// If default value contains multiple IOptions
|
||||
if (Array.isArray(this.props.defaultValue)) {
|
||||
this.setState({ selectedOptions: this.props.defaultValue });
|
||||
}
|
||||
|
||||
// If default value is a single IOption
|
||||
if ("label" in this.props.defaultValue) {
|
||||
this.setState({ selectedOptions: [this.props.defaultValue] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onFocus() {
|
||||
this.setState({ isFocused: true });
|
||||
}
|
||||
|
||||
private onBlur() {
|
||||
this.setState({ isFocused: false });
|
||||
}
|
||||
|
||||
private onChange(newValue: MultiValue<IOptionOld>, actionMeta: ActionMeta<IOptionOld>) {
|
||||
this.props.onChange && this.props.onChange(newValue, actionMeta);
|
||||
this.setState({
|
||||
selectedOptions: newValue,
|
||||
validationError: null,
|
||||
});
|
||||
}
|
||||
|
||||
private onEmptyResearch() {
|
||||
if (this.state.selectedOptions.length === this.props.options.length) {
|
||||
return null;
|
||||
}
|
||||
return "Aucune option trouvée";
|
||||
}
|
||||
|
||||
protected hasError(): boolean {
|
||||
return this.state.validationError !== null;
|
||||
}
|
||||
|
||||
protected renderErrors(): JSX.Element[] | null {
|
||||
if (!this.state.validationError || !this.state.validationError.constraints) return null;
|
||||
let errors: JSX.Element[] = [];
|
||||
Object.entries(this.state.validationError.constraints).forEach(([key, value]) => {
|
||||
errors.push(
|
||||
<Typography key={key} typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_ERROR_600}>
|
||||
{value}
|
||||
</Typography>,
|
||||
);
|
||||
});
|
||||
return errors;
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
export const styles = {
|
||||
option: (provided: any, props: { isSelected: boolean; isFocused: boolean }) => ({
|
||||
...provided,
|
||||
cursor: "pointer",
|
||||
padding: "8px 24px",
|
||||
fontFamily: "var(--font-text-family)",
|
||||
fontStyle: "normal",
|
||||
fontWeight: "400",
|
||||
fontSize: "18px",
|
||||
lineHeight: "21.78px",
|
||||
color: "#939393",
|
||||
backgroundColor: props.isSelected ? "var(--color-primary-3)" : props.isFocused ? "var(--color-primary-3)" : undefined,
|
||||
|
||||
":active": {
|
||||
...provided[":active"],
|
||||
backgroundColor: props.isSelected ? "var(--color-primary-3)" : undefined,
|
||||
},
|
||||
}),
|
||||
control: () => ({
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
background: "transparent",
|
||||
}),
|
||||
valueContainer: (provided: any) => ({
|
||||
...provided,
|
||||
padding: 0,
|
||||
minWidth: "100px",
|
||||
fontFamily: "var(--font-text-family)",
|
||||
fontStyle: "normal",
|
||||
fontWeight: "600",
|
||||
fontSize: "16px",
|
||||
lineHeight: "22px",
|
||||
color: "#939393",
|
||||
letter: "0.5 px",
|
||||
}),
|
||||
multiValue: (provided: any) => ({
|
||||
...provided,
|
||||
margin: "4px",
|
||||
padding: "8px 16px",
|
||||
fontStyle: "normal",
|
||||
fontWeight: "400",
|
||||
fontSize: "16px",
|
||||
lineHeight: "22px",
|
||||
background: "transparent",
|
||||
border: "1px solid black",
|
||||
borderRadius: "100px",
|
||||
}),
|
||||
multiValueLabel: (provided: any) => ({
|
||||
...provided,
|
||||
fontSize: "16px",
|
||||
color: "#939393",
|
||||
fontWeight: "400",
|
||||
}),
|
||||
input: (provided: any) => ({
|
||||
...provided,
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
}),
|
||||
placeholder: (provided: any) => ({
|
||||
...provided,
|
||||
fontSize: "16px",
|
||||
lineHeight: "22px",
|
||||
fontWeight: "400",
|
||||
color: "#939393",
|
||||
}),
|
||||
indicatorSeparator: () => ({
|
||||
display: "none",
|
||||
}),
|
||||
menu: (provided: any) => ({
|
||||
...provided,
|
||||
position: "static",
|
||||
border: "0",
|
||||
boxShadow: "none",
|
||||
}),
|
||||
menuList: (provided: any) => ({
|
||||
...provided,
|
||||
}),
|
||||
multiValueRemove: (provided: any) => ({
|
||||
...provided,
|
||||
backgroundColor: "transparent",
|
||||
color: "black",
|
||||
"&:hover": {
|
||||
color: "grey",
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
">svg": {
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
},
|
||||
}),
|
||||
indicatorsContainer: (provided: any) => ({
|
||||
...provided,
|
||||
display: "none",
|
||||
}),
|
||||
listBox: (provided: any) => ({
|
||||
...provided,
|
||||
color: "red",
|
||||
fontSize: "16px",
|
||||
}),
|
||||
};
|
@ -38,8 +38,12 @@ export default function DropdownNavigation({ blocks, onSelectedBlock, defaultSel
|
||||
},
|
||||
} as IOption;
|
||||
})}
|
||||
onSelect={handleDropDownSelect}
|
||||
selectedOption={selectedBlock ? { id: selectedBlock.id, label: selectedBlock.primaryText } : undefined}
|
||||
onSelectionChange={handleDropDownSelect}
|
||||
selectedOption={
|
||||
selectedBlock
|
||||
? { id: selectedBlock.id, label: { text: selectedBlock.secondaryText ?? "", subtext: selectedBlock.primaryText } }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -208,7 +208,7 @@ export default function CollaboratorInformations(props: IProps) {
|
||||
options={availableRoles.filter((role) => {
|
||||
return role.label !== "admin";
|
||||
})}
|
||||
onSelect={handleRoleChange}
|
||||
onSelectionChange={handleRoleChange}
|
||||
selectedOption={selectedOption}
|
||||
/>
|
||||
</div>
|
||||
|
@ -3,9 +3,9 @@ import PenICon from "@Assets/Icons/pen.svg";
|
||||
import DeedTypes from "@Front/Api/LeCoffreApi/Admin/DeedTypes/DeedTypes";
|
||||
import DocumentTypes from "@Front/Api/LeCoffreApi/Admin/DocumentTypes/DocumentTypes";
|
||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||
import Form from "@Front/Components/DesignSystem/Form";
|
||||
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
|
||||
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
||||
import Tooltip from "@Front/Components/DesignSystem/ToolTip";
|
||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
@ -17,7 +17,6 @@ import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { MultiValue } from "react-select";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
@ -28,7 +27,7 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
|
||||
const [deedTypeSelected, setDeedTypeSelected] = useState<DeedType | null>(null);
|
||||
const [availableDocuments, setAvailableDocuments] = useState<DocumentType[]>([]);
|
||||
const [selectedDocuments, setSelectedDocuments] = useState<IOptionOld[]>([]);
|
||||
const [selectedDocuments, setSelectedDocuments] = useState<IOption[]>([]);
|
||||
|
||||
const [isDeleteModalOpened, setIsDeleteModalOpened] = useState<boolean>(false);
|
||||
const [isSaveModalOpened, setIsSaveModalOpened] = useState<boolean>(false);
|
||||
@ -71,11 +70,11 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
setDeedTypeSelected(deedType);
|
||||
|
||||
if (!deedType.document_types) return;
|
||||
const documentsOptions: IOptionOld[] = deedType.document_types
|
||||
const documentsOptions: IOption[] = deedType.document_types
|
||||
?.map((documentType) => {
|
||||
return {
|
||||
label: documentType.name,
|
||||
value: documentType.uid,
|
||||
id: documentType.uid ?? "",
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
@ -101,19 +100,19 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
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 })),
|
||||
document_types: selectedDocuments.map((document) => DocumentType.hydrate<DocumentType>({ uid: document.id as string })),
|
||||
});
|
||||
closeSaveModal();
|
||||
}, [closeSaveModal, deedTypeUid, selectedDocuments]);
|
||||
|
||||
const onDocumentChangeHandler = useCallback((values: MultiValue<IOptionOld>) => {
|
||||
setSelectedDocuments(values as IOptionOld[]);
|
||||
const onDocumentChangeHandler = useCallback((options: IOption[] | null) => {
|
||||
options && setSelectedDocuments(options);
|
||||
}, []);
|
||||
|
||||
const formattedOptions: IOptionOld[] = availableDocuments
|
||||
const formattedOptions: IOption[] = availableDocuments
|
||||
.map((document) => ({
|
||||
label: document.name,
|
||||
value: document.uid,
|
||||
id: document.uid ?? "",
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
@ -161,11 +160,11 @@ export default function DeedTypesInformations(props: IProps) {
|
||||
<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
|
||||
<AutocompleteMultiSelectField
|
||||
label="Sélectionner des documents"
|
||||
options={formattedOptions}
|
||||
placeholder="Cliquez pour sélectionner des documents"
|
||||
onChange={onDocumentChangeHandler}
|
||||
defaultValue={selectedDocuments}
|
||||
onSelectionChange={onDocumentChangeHandler}
|
||||
selectedOptions={selectedDocuments}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes["button-container"]}>
|
||||
|
@ -1,14 +1,16 @@
|
||||
import Customers from "@Front/Api/LeCoffreApi/Notary/Customers/Customers";
|
||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||
import AutocompleteMultiSelect from "@Front/Components/DesignSystem/AutocompleteMultiSelect";
|
||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||
import Form from "@Front/Components/DesignSystem/Form";
|
||||
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||
import Typography, { ETypo } 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 { ValidationError } from "class-validator";
|
||||
import { ECivility } from "le-coffre-resources/dist/Customer/Contact";
|
||||
import { Contact, Customer, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
import Link from "next/link";
|
||||
@ -16,8 +18,6 @@ import { NextRouter, useRouter } from "next/router";
|
||||
|
||||
import BasePage from "../../Base";
|
||||
import classes from "./classes.module.scss";
|
||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||
import { ValidationError } from "class-validator";
|
||||
|
||||
enum ESelectedOption {
|
||||
EXISTING_CUSTOMER = "existing_customer",
|
||||
@ -27,8 +27,8 @@ type IProps = {};
|
||||
type IState = {
|
||||
selectedOption: ESelectedOption;
|
||||
availableCustomers: Customer[];
|
||||
selectedCustomers: readonly IOptionOld[];
|
||||
existingCustomers: IOptionOld[];
|
||||
selectedCustomers: IOption[];
|
||||
existingCustomers: IOption[];
|
||||
isLoaded: boolean;
|
||||
validationError: ValidationError[];
|
||||
};
|
||||
@ -54,7 +54,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
this.onFormSubmit = this.onFormSubmit.bind(this);
|
||||
}
|
||||
public override render(): JSX.Element {
|
||||
const selectOptions: IOptionOld[] = this.getSelectedOptions();
|
||||
const selectOptions: IOption[] = this.getSelectedOptions();
|
||||
|
||||
const backwardPath = Module.getInstance()
|
||||
.get()
|
||||
@ -91,12 +91,13 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
<Form className={classes["form"]} onSubmit={this.onFormSubmit}>
|
||||
{this.state.selectedOption === "existing_customer" && (
|
||||
<div className={classes["existing-client"]}>
|
||||
<MultiSelect
|
||||
<AutocompleteMultiSelect
|
||||
label="Clients"
|
||||
options={selectOptions}
|
||||
placeholder="Clients"
|
||||
onChange={this.onMutiSelectChange}
|
||||
defaultValue={this.state.selectedCustomers}
|
||||
selectedOptions={this.state.selectedCustomers}
|
||||
onSelectionChange={this.onMutiSelectChange}
|
||||
/>
|
||||
|
||||
<div className={classes["button-container"]}>
|
||||
<Link href={backwardPath} className={classes["cancel-button"]}>
|
||||
<Button variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED}>
|
||||
@ -153,11 +154,11 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
public override async componentDidMount() {
|
||||
const query = {};
|
||||
const availableCustomers = await Customers.getInstance().get(query);
|
||||
let preExistingCustomers: IOptionOld[] | undefined = await this.getFolderPreSelectedCustomers(this.props.selectedFolderUid);
|
||||
let preExistingCustomers: IOption[] | undefined = await this.getFolderPreSelectedCustomers(this.props.selectedFolderUid);
|
||||
const existingCustomers = preExistingCustomers ?? [];
|
||||
|
||||
existingCustomers.forEach((customer) => {
|
||||
const index = availableCustomers.findIndex((availableCustomer) => availableCustomer.uid === customer.value);
|
||||
const index = availableCustomers.findIndex((availableCustomer) => availableCustomer.uid === customer.id);
|
||||
if (index !== -1) availableCustomers.splice(index, 1);
|
||||
});
|
||||
|
||||
@ -169,7 +170,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
this.setState({ availableCustomers, existingCustomers, isLoaded: true, selectedOption });
|
||||
}
|
||||
|
||||
private async getFolderPreSelectedCustomers(folderUid: string): Promise<IOptionOld[] | undefined> {
|
||||
private async getFolderPreSelectedCustomers(folderUid: string): Promise<IOption[] | undefined> {
|
||||
const query = {
|
||||
q: {
|
||||
customers: {
|
||||
@ -179,13 +180,13 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
},
|
||||
},
|
||||
};
|
||||
let preExistingCustomers: IOptionOld[] = [];
|
||||
let preExistingCustomers: IOption[] = [];
|
||||
try {
|
||||
const folder = await Folders.getInstance().getByUid(folderUid, query);
|
||||
preExistingCustomers = folder.customers!.map((customer) => {
|
||||
return {
|
||||
label: customer.contact?.first_name + " " + customer.contact?.last_name,
|
||||
value: customer.uid,
|
||||
id: customer.uid ?? "",
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
@ -195,19 +196,19 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
return preExistingCustomers;
|
||||
}
|
||||
|
||||
private getSelectedOptions(): IOptionOld[] {
|
||||
private getSelectedOptions(): IOption[] {
|
||||
let options = this.state.availableCustomers?.map((customer) => {
|
||||
return {
|
||||
label: customer.contact?.first_name + " " + customer.contact?.last_name,
|
||||
value: customer.uid,
|
||||
id: customer.uid ?? "",
|
||||
};
|
||||
});
|
||||
if (!options) options = [];
|
||||
return options;
|
||||
}
|
||||
|
||||
private onMutiSelectChange(selectedCustomers: readonly IOptionOld[]): void {
|
||||
this.setState({ selectedCustomers });
|
||||
private onMutiSelectChange(selectedCustomers: IOption[] | null): void {
|
||||
selectedCustomers && this.setState({ selectedCustomers });
|
||||
}
|
||||
|
||||
private onExistingClientSelected(): void {
|
||||
@ -228,7 +229,7 @@ class AddClientToFolderClass extends BasePage<IPropsClass, IState> {
|
||||
|
||||
const allCustomersToLink = this.state.selectedCustomers.concat(this.state.existingCustomers);
|
||||
let customersToLink: Partial<Customer>[] = allCustomersToLink.map((customer) => {
|
||||
return Customer.hydrate<Customer>({ uid: customer.value as string });
|
||||
return Customer.hydrate<Customer>({ uid: customer.id as string });
|
||||
}) as Partial<Customer>[];
|
||||
|
||||
if (this.state.selectedOption === "new_customer") {
|
||||
|
@ -1,15 +1,14 @@
|
||||
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 { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
|
||||
import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField";
|
||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||
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";
|
||||
|
||||
@ -25,20 +24,20 @@ export default function ParameterDocuments(props: IProps) {
|
||||
|
||||
const [addOrEditDocument, setAddOrEditDocument] = useState<"add" | "edit">("edit");
|
||||
|
||||
const [selectedDocuments, setSelectedDocuments] = useState<IOptionOld[]>([]);
|
||||
const [formattedOptions, setFormattedOptions] = useState<IOptionOld[]>([]);
|
||||
const [selectedDocuments, setSelectedDocuments] = useState<IOption[]>([]);
|
||||
const [formattedOptions, setFormattedOptions] = useState<IOption[]>([]);
|
||||
|
||||
const getAvailableDocuments = useCallback(async () => {
|
||||
const documents = await DocumentTypes.getInstance().get({});
|
||||
|
||||
const formattedOptions: IOptionOld[] = documents
|
||||
const formattedOptions: IOption[] = documents
|
||||
.filter((document) => {
|
||||
return !props.folder.deed?.document_types?.some((documentType) => documentType.uid === document.uid);
|
||||
})
|
||||
.map((document) => {
|
||||
return {
|
||||
label: document.name,
|
||||
value: document.uid,
|
||||
id: document.uid ?? "",
|
||||
};
|
||||
});
|
||||
formattedOptions.sort((a, b) => (a.label > b.label ? 1 : -1));
|
||||
@ -53,8 +52,8 @@ export default function ParameterDocuments(props: IProps) {
|
||||
setDocumentName(event.target.value);
|
||||
};
|
||||
|
||||
const onDocumentChangeHandler = useCallback((values: MultiValue<IOptionOld>) => {
|
||||
setSelectedDocuments(values as IOptionOld[]);
|
||||
const onDocumentChangeHandler = useCallback((options: IOption[] | null) => {
|
||||
options && setSelectedDocuments(options);
|
||||
}, []);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
@ -94,7 +93,7 @@ export default function ParameterDocuments(props: IProps) {
|
||||
await Deeds.getInstance().put(props.folder.deed?.uid!, {
|
||||
document_types: [
|
||||
...oldDocumentsType,
|
||||
...selectedDocuments.map((document) => DocumentType.hydrate<DocumentType>({ uid: document.value as string })),
|
||||
...selectedDocuments.map((document) => DocumentType.hydrate<DocumentType>({ uid: document.id as string })),
|
||||
],
|
||||
});
|
||||
|
||||
@ -148,11 +147,11 @@ export default function ParameterDocuments(props: IProps) {
|
||||
</>
|
||||
)}
|
||||
{addOrEditDocument === "edit" && (
|
||||
<MultiSelect
|
||||
<AutocompleteMultiSelectField
|
||||
label="Sélectionner des documents"
|
||||
options={formattedOptions}
|
||||
placeholder="Cliquez pour sélectionner des documents"
|
||||
onChange={onDocumentChangeHandler}
|
||||
defaultValue={selectedDocuments}
|
||||
onSelectionChange={onDocumentChangeHandler}
|
||||
selectedOptions={selectedDocuments}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -5,11 +5,10 @@ import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
||||
import Button from "@Front/Components/DesignSystem/Button";
|
||||
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||
import Form from "@Front/Components/DesignSystem/Form";
|
||||
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
|
||||
import SelectField from "@Front/Components/DesignSystem/Form/SelectField";
|
||||
import { 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 RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||
@ -20,8 +19,7 @@ import { Deed, Office, OfficeFolder } 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 React, { useEffect, useState } from "react";
|
||||
import { MultiValue } from "react-select";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
@ -89,12 +87,14 @@ export default function CreateFolder(): JSX.Element {
|
||||
const radioOnChange = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setFolderAccessType(e.target.value as "whole_office" | "select_collaborators");
|
||||
|
||||
const onSelectedCollaboratorsChange = (values: MultiValue<IOptionOld>) => {
|
||||
const selectedCollaborators = availableCollaborators.filter((collaborator) =>
|
||||
values.some((value) => value.value === collaborator.uid),
|
||||
const onSelectedCollaboratorsChange = useCallback(
|
||||
(options: IOption[] | null) => {
|
||||
if (!options) return;
|
||||
const collaborators = availableCollaborators.filter((collaborator) => options.find((option) => option.id === collaborator.uid));
|
||||
setSelectedCollaborators(collaborators);
|
||||
},
|
||||
[availableCollaborators],
|
||||
);
|
||||
setSelectedCollaborators(selectedCollaborators);
|
||||
};
|
||||
|
||||
/**
|
||||
* UseEffect
|
||||
@ -178,19 +178,17 @@ export default function CreateFolder(): JSX.Element {
|
||||
</div>
|
||||
{folderAccessType === "select_collaborators" && (
|
||||
<div className={classes["collaborators-container"]}>
|
||||
<MultiSelect
|
||||
options={
|
||||
availableCollaborators.map((collaborator) => ({
|
||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name),
|
||||
value: collaborator.uid,
|
||||
})) as IOptionOld[]
|
||||
}
|
||||
defaultValue={selectedCollaborators.map((collaborator) => ({
|
||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) as string,
|
||||
value: collaborator.uid!,
|
||||
<AutocompleteMultiSelectField
|
||||
label="Sélectionner les collaborateurs"
|
||||
options={availableCollaborators.map((collaborator) => ({
|
||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "",
|
||||
id: collaborator.uid ?? "",
|
||||
}))}
|
||||
onChange={onSelectedCollaboratorsChange}
|
||||
placeholder="Sélectionner les collaborateurs"
|
||||
selectedOptions={selectedCollaborators.map((collaborator) => ({
|
||||
label: collaborator.contact?.last_name.concat(" ", collaborator.contact.first_name) ?? "",
|
||||
id: collaborator.uid ?? "",
|
||||
}))}
|
||||
onSelectionChange={onSelectedCollaboratorsChange}
|
||||
validationError={validationError.find((error) => error.property === "stakeholders")}
|
||||
/>
|
||||
</div>
|
||||
|
@ -2,9 +2,9 @@ import backgroundImage from "@Assets/images/background_refonte.svg";
|
||||
import Folders from "@Front/Api/LeCoffreApi/Notary/Folders/Folders";
|
||||
import Users, { IGetUsersParams } from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
||||
import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
||||
import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/DropdownOption";
|
||||
import Form from "@Front/Components/DesignSystem/Form";
|
||||
import { IOptionOld } from "@Front/Components/DesignSystem/Form/SelectFieldOld";
|
||||
import MultiSelect from "@Front/Components/DesignSystem/MultiSelect";
|
||||
import AutocompleteMultiSelectField from "@Front/Components/DesignSystem/Form/AutocompleteMultiSelectField";
|
||||
import RadioBox from "@Front/Components/DesignSystem/RadioBox";
|
||||
import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import BackArrow from "@Front/Components/Elements/BackArrow";
|
||||
@ -26,9 +26,8 @@ enum ERadioBoxValue {
|
||||
export default function UpdateFolderCollaborators() {
|
||||
const router = useRouter();
|
||||
let { folderUid } = router.query;
|
||||
|
||||
const [availableCollaborators, setAvailableCollaborators] = useState<User[]>([]);
|
||||
const [selectedCollaborators, setSelectedCollaborators] = useState<readonly IOptionOld[]>([]);
|
||||
const [selectedCollaborators, setSelectedCollaborators] = useState<IOption[]>([]);
|
||||
const [defaultCheckedAllOffice, setDefaultCheckedAllOffice] = useState<boolean>(false);
|
||||
const [selectedOption, setSelectedOption] = useState<ERadioBoxValue>(ERadioBoxValue.SELECTION);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
@ -40,9 +39,7 @@ export default function UpdateFolderCollaborators() {
|
||||
try {
|
||||
let collaboratorsUid: User[] = availableCollaborators;
|
||||
if (selectedOption === ERadioBoxValue.SELECTION) {
|
||||
collaboratorsUid = selectedCollaborators.map((collaborator) =>
|
||||
User.hydrate<User>({ uid: collaborator.value as string }),
|
||||
);
|
||||
collaboratorsUid = selectedCollaborators.map((collaborator) => User.hydrate<User>({ uid: collaborator.id as string }));
|
||||
}
|
||||
await Folders.getInstance().put(folderUid, { stakeholders: collaboratorsUid });
|
||||
router.push(
|
||||
@ -61,8 +58,8 @@ export default function UpdateFolderCollaborators() {
|
||||
setSelectedOption(ERadioBoxValue.ALL);
|
||||
}, []);
|
||||
|
||||
const onChangeSelectedCollaborators = useCallback((selectedCollaborators: readonly IOptionOld[]) => {
|
||||
setSelectedCollaborators(selectedCollaborators);
|
||||
const onChangeSelectedCollaborators = useCallback((selectedCollaborators: IOption[] | null) => {
|
||||
selectedCollaborators && setSelectedCollaborators(selectedCollaborators);
|
||||
}, []);
|
||||
|
||||
const onSelectedOptionSpecific = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@ -86,10 +83,10 @@ export default function UpdateFolderCollaborators() {
|
||||
let folder = null;
|
||||
try {
|
||||
folder = await Folders.getInstance().getByUid(folderUid, query);
|
||||
const preSelectedCollaborators: IOptionOld[] = folder.stakeholders!.map((collaborator) => {
|
||||
const preSelectedCollaborators: IOption[] = folder.stakeholders!.map((collaborator) => {
|
||||
return {
|
||||
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
||||
value: collaborator.uid,
|
||||
id: collaborator.uid ?? "",
|
||||
};
|
||||
});
|
||||
|
||||
@ -126,10 +123,10 @@ export default function UpdateFolderCollaborators() {
|
||||
|
||||
const foldersInformationPath = Module.getInstance().get().modules.pages.Folder.pages.FolderInformation.props.path;
|
||||
const backwardPath = foldersInformationPath.replace("[folderUid]", folderUid as string);
|
||||
const selectOptions: IOptionOld[] = availableCollaborators.map((collaborator) => {
|
||||
const selectOptions: IOption[] = availableCollaborators.map((collaborator) => {
|
||||
return {
|
||||
label: collaborator.contact?.first_name + " " + collaborator.contact?.last_name,
|
||||
value: collaborator.uid,
|
||||
id: collaborator.uid ?? "",
|
||||
};
|
||||
});
|
||||
|
||||
@ -162,11 +159,11 @@ export default function UpdateFolderCollaborators() {
|
||||
|
||||
{selectedOption === ERadioBoxValue.SELECTION && (
|
||||
<div className={classes["sub-content"]}>
|
||||
<MultiSelect
|
||||
onChange={onChangeSelectedCollaborators}
|
||||
<AutocompleteMultiSelectField
|
||||
label="Collaborateurs"
|
||||
options={selectOptions}
|
||||
placeholder="Collaborateurs"
|
||||
defaultValue={selectedCollaborators}
|
||||
selectedOptions={selectedCollaborators}
|
||||
onSelectionChange={onChangeSelectedCollaborators}
|
||||
validationError={validationError?.find((error) => error.property === "stakeholders")}
|
||||
/>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user