This commit is contained in:
Maxime Lalo 2023-05-16 17:51:17 +02:00
parent b06d9bf0ec
commit 65dee0696e
7 changed files with 81 additions and 62 deletions

View File

@ -90,8 +90,10 @@ export default abstract class BaseField<P extends IProps, S extends IState = ISt
}
protected hasError(): boolean {
if(!this.context) return false;
return this.state.validationError !== null && this.context.isInputFocused(this.props.name);
return this.state.validationError !== null;
// if(!this.context) return false;
// if(!this.context.hasOneFocusedInput() && this.state.validationError !== null) return true;
// return this.state.validationError !== null && this.context.isInputFocused(this.props.name);
}
protected renderErrors(): JSX.Element[] | null {

View File

@ -15,7 +15,7 @@ type IProps = {
hasBorderRightCollapsed?: boolean;
placeholder?: string;
className?: string;
name?: string;
name: string;
disabled: boolean;
errors?: ValidationError;
};
@ -60,53 +60,58 @@ export default class SelectField extends React.Component<IProps, IState> {
public override render(): JSX.Element {
const selectedOption = this.state.selectedOption ?? this.props.selectedOption;
return (
<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={ITypo.P_18}>
<span className={classes["text"]}>{selectedOption?.label}</span>
</Typography>
</>
)}
{!selectedOption && (
<div className={classes["placeholder"]} data-open={(selectedOption ? true : false).toString()}>
<Typography typo={ITypo.NAV_INPUT_16}>
<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>
<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={ITypo.P_18}>
<span className={classes["text"]}>{selectedOption?.label}</span>
</Typography>
</>
)}
{!selectedOption && (
<div className={classes["placeholder"]} data-open={(selectedOption ? true : false).toString()}>
<Typography typo={ITypo.NAV_INPUT_16}>
<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={ITypo.P_18}>{option.label}</Typography>
</li>
))}
</ul>
<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={ITypo.P_18}>{option.label}</Typography>
</li>
))}
</ul>
{this.state.isOpen && <div className={classes["backdrop"]} onClick={this.toggle} />}
{this.state.isOpen && <div className={classes["backdrop"]} onClick={this.toggle} />}
</div>
{this.state.errors !== null && <div className={classes["errors-container"]}>{this.renderErrors()}</div>}
</div>
);
@ -172,16 +177,12 @@ export default class SelectField extends React.Component<IProps, IState> {
this.toggle(e);
}
private renderErrors(): JSX.Element[] | null {
if (!this.state.errors || !this.state.errors.constraints) return null;
let errors: JSX.Element[] = [];
Object.entries(this.state.errors.constraints).forEach(([key, value]) => {
errors.push(
<Typography key={key} typo={ITypo.CAPTION_14} color={ITypoColor.RED_FLASH}>
{value}
</Typography>,
);
});
return errors;
private renderErrors(): JSX.Element | null {
if (!this.state.errors) return null;
return (
<Typography typo={ITypo.CAPTION_14} color={ITypoColor.RED_FLASH}>
{this.props.placeholder} est requis
</Typography>
);
}
}

View File

@ -10,6 +10,7 @@ export type IFormContext = {
onFieldChange: (name: string, field: IBaseField) => void;
onFieldFocusChange: (name: string, field: IBaseField, focused: boolean) => void;
isInputFocused: (name: string) => boolean;
hasOneFocusedInput: () => boolean;
};
type IFields = {
@ -32,7 +33,14 @@ export type IProps = {
children?: ReactNode;
};
export const FormContext = React.createContext<IFormContext>({ setField: () => {}, unSetField: () => {}, onFieldChange: () => {}, onFieldFocusChange: () => {}, isInputFocused: () => false});
export const FormContext = React.createContext<IFormContext>({
setField: () => {},
unSetField: () => {},
onFieldChange: () => {},
onFieldFocusChange: () => {},
isInputFocused: () => false,
hasOneFocusedInput: () => false,
});
export default class Form extends React.Component<IProps, IState> {
protected fields: IFields = {};
@ -56,6 +64,7 @@ export default class Form extends React.Component<IProps, IState> {
this.formRef = React.createRef();
this.onFieldFocusChange = this.onFieldFocusChange.bind(this);
this.isInputFocused = this.isInputFocused.bind(this);
this.hasOneFocusedInput = this.hasOneFocusedInput.bind(this);
}
public override render() {
@ -67,6 +76,7 @@ export default class Form extends React.Component<IProps, IState> {
onFieldChange: this.onFieldChange,
onFieldFocusChange: this.onFieldFocusChange,
isInputFocused: this.isInputFocused,
hasOneFocusedInput: this.hasOneFocusedInput,
}}>
<form className={this.props.className} ref={this.formRef} onSubmit={this.onSubmit}>
{this.props.children}
@ -125,8 +135,11 @@ export default class Form extends React.Component<IProps, IState> {
delete this.fields[name];
}
protected hasOneFocusedInput() {
return this.state.inputFocused.focused;
}
protected isInputFocused(name: string) {
console.log(this.state.inputFocused);
return this.state.inputFocused.name === name && this.state.inputFocused.focused;
}

View File

@ -200,6 +200,7 @@ export default class DesignSystem extends BasePage<IProps, IState> {
<div className={classes["sub-section"]}>
<div className={classes["folder-conatainer"]}>
<SelectField
name="select"
options={selectOptions}
onChange={this.onSelectedOption}
placeholder={"Type d'acte"}

View File

@ -102,6 +102,7 @@ class CreateFolderClass extends BasePage<IPropsClass, IState> {
/>
<SelectField
options={this.state.deedTypesOptions}
name="deed"
placeholder={"Type d'acte"}
onChange={this.onActTypeChange}
errors={this.state.validationError.find((error) => error.property === "deed")}

View File

@ -58,7 +58,7 @@ class UpdateFolderMetadataClass extends BasePage<IPropsClass, IState> {
placeholder="Numéro de dossier"
defaultValue={this.state.selectedFolder?.folder_number}
/>
<Select options={[]} placeholder={"Type d'acte"} selectedOption={deedOption} disabled />
<Select name="deed" options={[]} placeholder={"Type d'acte"} selectedOption={deedOption} disabled />
<TextField placeholder="Ouverture du dossier" defaultValue={openingDate.toLocaleDateString("fr-FR")} disabled />
</div>

View File

@ -50,6 +50,7 @@ class UpdateFolderMetadataClass extends BasePage<IProps, IState> {
<TextField name="input field" placeholder="Intitulé du dossier" />
<TextField name="input field" placeholder="Numéro de dossier" />
<Select
name="deed"
options={selectOptions}
onChange={this.onSelectedOption}
placeholder={"Type d'acte"}