Skip to content

Commit

Permalink
[EN-4026] chore(inputs): modified rules and rule manager. Typing
Browse files Browse the repository at this point in the history
  • Loading branch information
emile-bex committed Aug 4, 2023
1 parent 9531888 commit b3b9310
Show file tree
Hide file tree
Showing 40 changed files with 857 additions and 1,507 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"@testing-library/react": "^12.1.5",
"@types/node": "^18.11.9",
"@types/react": "^18.0.1",
"@types/validator": "^13.9.0",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"babel-loader": "^8.2.5",
Expand Down
230 changes: 177 additions & 53 deletions src/components/forms/FormSchema/FormSchema.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,100 +2,211 @@ import { RadioTypes } from 'src/components/utils/Inputs/Radio/Radio.types';
import { FilterConstant } from 'src/constants';
import { AnyCantFix, AnyToFix } from 'src/utils/Types';

export const InputComponents = [
'datepicker',
'text-input',
'tel-input',
'textarea',
'checkbox',
const FormComponents = {
DATEPICKER: 'datepicker',
TEXT_INPUT: 'text-input',
TEL_INPUT: 'tel-input',
TEXTAREA: 'textarea',
CHECKBOX: 'checkbox',
SELECT_SIMPLE: 'select-simple',
SELECT: 'select',
SELECT_CREATABLE: 'select-creatable',
SELECT_ASYNC: 'select-async',
RADIO: 'radio',
RADIO_ASYNC: 'radio-async',
HEADING: 'heading',
TEXT: 'text',
FIELDGROUP: 'fieldgroup',
MULTIPLE_FIELDS: 'multiple-fields',
} as const;

export type FormComponent =
(typeof FormComponents)[keyof typeof FormComponents];

export type FieldValue =
| string
| boolean
| number
| FilterConstant
| FilterConstant[];

type MultiFilterConstant<M extends boolean> = M extends true
? FilterConstant[]
: FilterConstant;

interface FormComponentValues<M extends boolean>
extends Record<FormComponent, FieldValue> {
[FormComponents.DATEPICKER]: string;
[FormComponents.TEXT_INPUT]: string;
[FormComponents.TEL_INPUT]: string;
[FormComponents.TEXTAREA]: string;
[FormComponents.CHECKBOX]: boolean;
[FormComponents.SELECT_SIMPLE]: string | number;
[FormComponents.SELECT]: MultiFilterConstant<M>;
[FormComponents.SELECT_CREATABLE]: MultiFilterConstant<M>;
[FormComponents.SELECT_ASYNC]: MultiFilterConstant<M>;
[FormComponents.RADIO]: string | number;
[FormComponents.RADIO_ASYNC]: string | number;
}

export const TextInputComponents = [
FormComponents.DATEPICKER,
FormComponents.TEXT_INPUT,
FormComponents.TEL_INPUT,
FormComponents.TEXTAREA,
] as const;

export type TextInputComponent = (typeof TextInputComponents)[number];

export const CheckBoxComponents = [FormComponents.CHECKBOX] as const;

export type CheckBoxComponent = (typeof CheckBoxComponents)[number];
export const SelectRequestComponents = [
FormComponents.SELECT,
FormComponents.SELECT_CREATABLE,
FormComponents.SELECT_ASYNC,
] as const;

export type InputComponent = (typeof InputComponents)[number];
export type SelectRequestComponent = (typeof SelectRequestComponents)[number];

export const SelectComponents = [
'select-simple',
'select',
'select-creatable',
'select-async',
'radio',
'radio-async',
FormComponents.SELECT_SIMPLE,
FormComponents.RADIO,
FormComponents.RADIO_ASYNC,
] as const;

export type SelectComponent = (typeof SelectComponents)[number];

export const TextComponents = ['heading', 'text'] as const;
export const TextComponents = [
FormComponents.HEADING,
FormComponents.TEXT,
] as const;
export type TextComponent = (typeof TextComponents)[number];

export const GroupComponents = ['fieldgroup'] as const;
export const GroupComponents = [FormComponents.FIELDGROUP] as const;
export type GroupComponent = (typeof GroupComponents)[number];

export const MultipleComponents = ['multiple-fields'] as const;
export const MultipleComponents = [FormComponents.MULTIPLE_FIELDS] as const;

export type MultipleComponent = (typeof MultipleComponents)[number];

export type FormComponent =
| InputComponent
type InputComponent =
| TextInputComponent
| CheckBoxComponent
| SelectComponent
| TextComponent
| GroupComponent
| MultipleComponent;
| SelectRequestComponent;

interface FormFieldCommonProperties {
id: string;
name: string;
}

interface FormFieldInputCommonProperties extends FormFieldCommonProperties {
interface FormTypes {
test: string;
}

export type FormType = keyof FormTypes;

// export type GetValueType<K extends FormType> = (name: K) => FormTypes[K];
export type GetValueType = (name: string) => AnyToFix;

interface Rule<T extends InputComponent, M extends boolean> {
method: (
fieldValue: FormComponentValues<M>[T],
fieldValues: { [K in FormType]: FormTypes[K] }
) => boolean;
args?: AnyToFix[];
message: string;
}

interface FormFieldInputCommonProperties<
T extends InputComponent,
M extends boolean = false
> extends FormFieldCommonProperties {
isRequired?: boolean;
title:
| string
| JSX.Element
| ((getValue: (name: string) => AnyToFix) => string);
rules?: Rule<T, M>[];
title: string | JSX.Element | ((getValue: GetValueType) => string);
disabled?: boolean;
disable?: (getValue: (name: string) => AnyToFix) => boolean;
disable?: (getValue: GetValueType) => boolean;
hidden?: boolean;
hide?: (
getValue: (name: string) => AnyToFix,
fieldOptions?: AnyToFix
) => boolean;
hide?: (getValue: GetValueType, fieldOptions?: AnyToFix) => boolean;
placeholder?: string;
showLabel?: boolean;
}

export interface FormFieldInput extends FormFieldInputCommonProperties {
component: InputComponent;
export interface FormFieldTextInput
extends FormFieldInputCommonProperties<TextInputComponent> {
component: TextInputComponent;
type?: 'text' | 'email' | 'password';
rows?: number;
maxLines?: { lines: number; width: number };
maxLength?: number;
min?: string;
max?: string;
}

export interface FormFieldSelect<T extends FilterConstant[] = AnyCantFix>
extends FormFieldInputCommonProperties {
export interface FormFieldCheckBox
extends FormFieldInputCommonProperties<CheckBoxComponent> {
component: CheckBoxComponent;
}

export interface FormFieldSelect<K extends FilterConstant[] = AnyToFix>
extends FormFieldInputCommonProperties<SelectComponent> {
component: SelectComponent;
dynamicFilter?: (getValue: (name: string) => AnyToFix) => string;
dynamicFilter?: (getValue: GetValueType) => string;
fieldsToReset?: string[];
options?: T;
options?: K;
loadOptions?: (
callback: (options: FilterConstant[] | RadioTypes[]) => void,
inputValue?: string,
getValue?: (name: string) => AnyToFix
getValue?: GetValueType
) => Promise<void> | void;
isMulti?: boolean | ((getValue: (name: string) => AnyToFix) => boolean);
openMenuOnClick?: boolean;
errorMessage?: string;
limit?: number;
}
export interface FormFieldSelectRequestCommon<
K extends FilterConstant[],
M extends boolean
> extends FormFieldInputCommonProperties<SelectRequestComponent, M> {
component: SelectRequestComponent;
fieldsToReset?: string[];
options?: K;
loadOptions?: (
callback: (options: FilterConstant[] | RadioTypes[]) => void,
inputValue?: string,
getValue?: GetValueType
) => Promise<void> | void;
openMenuOnClick?: boolean;
isMulti?: boolean | ((getValue: (name: string) => AnyToFix) => boolean);
}

// TODO fix type depending on is Multi
interface FormFieldSelectRequestMulti<K extends FilterConstant[]>
extends FormFieldSelectRequestCommon<K, true> {
isMulti?: true;
}

interface FormFieldSelectRequestSingle<K extends FilterConstant[]>
extends FormFieldSelectRequestCommon<K, false> {
isMulti?: false;
}

export type FormFieldSelectRequest<K extends FilterConstant[] = AnyToFix> =
| FormFieldSelectRequestMulti<K>
| FormFieldSelectRequestSingle<K>

export type FormFieldInput =
| FormFieldTextInput
| FormFieldCheckBox
| FormFieldSelect
| FormFieldSelectRequest;

export interface FormFieldText extends FormFieldCommonProperties {
id: string;
name: string;
title: string | ((getValue: (name: string) => AnyToFix) => string);
title: string | ((getValue: GetValueType) => string);
component: TextComponent;
hide?: (
getValue: (name: string) => AnyToFix,
fieldOptions?: AnyToFix
) => boolean;
hide?: (getValue: GetValueType, fieldOptions?: AnyToFix) => boolean;
hidden?: boolean;
}

Expand All @@ -104,29 +215,42 @@ export interface FormFieldMultiple extends FormFieldCommonProperties {
name: string;
action: string;
component: MultipleComponent;
fields: (FormFieldInput | FormFieldSelect)[];
hide?: (getValue: (name: string) => AnyToFix) => boolean;
fields: FormFieldInput[];
hide?: (getValue: GetValueType) => boolean;
hidden?: boolean;
}

export interface FormFieldGroup extends FormFieldCommonProperties {
component: GroupComponent;
fields: (FormFieldInput | FormFieldSelect | FormFieldText)[];
hide?: (getValue: (name: string) => AnyToFix) => boolean;
fields: (FormFieldInput | FormFieldText)[];
hide?: (getValue: GetValueType) => boolean;
hidden?: boolean;
}

export type FormField =
| FormFieldInput
| FormFieldSelect
| FormFieldText
| FormFieldMultiple
| FormFieldGroup;

interface FormRule {}

export interface FormSchema {
id: string;
fields: FormField[];
rules: AnyToFix; // to be typed
}

const test: FormFieldSelectRequest = {
component: undefined,
id: '',
name: '',
options: undefined,
title: undefined,
isMulti: true,
rules: [
{
method: (fieldValue) => {
return true;
},
message: 'oui',
},
],
};
35 changes: 28 additions & 7 deletions src/components/forms/FormSchema/FormSchema.utils.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,52 @@
import {
CheckBoxComponent,
CheckBoxComponents,
FormComponent,
FormField,
FormFieldCheckBox,
FormFieldGroup,
FormFieldInput,
FormFieldMultiple,
FormFieldSelect,
FormFieldSelect, FormFieldSelectRequest,
FormFieldText,
FormFieldTextInput,
GroupComponent,
GroupComponents,
InputComponent,
InputComponents,
MultipleComponent,
MultipleComponents,
SelectComponent,
SelectComponents,
SelectRequestComponent,
SelectRequestComponents,
TextComponent,
TextComponents,
} from './FormSchema.types';
TextInputComponent,
TextInputComponents
} from "./FormSchema.types";

export function isFormFieldInput(field: FormField): field is FormFieldInput {
return InputComponents.includes(field.component as InputComponent);
export function isFormFieldTextInput(
field: FormField
): field is FormFieldTextInput {
return TextInputComponents.includes(field.component as TextInputComponent);
}

export function isFormFieldCheckbox(
field: FormField
): field is FormFieldCheckBox {
return CheckBoxComponents.includes(field.component as CheckBoxComponent);
}

export function isFormFieldSelect(field: FormField): field is FormFieldSelect {
return SelectComponents.includes(field.component as SelectComponent);
}

export function isFormFieldSelectRequest(
field: FormField
): field is FormFieldSelectRequest {
return SelectRequestComponents.includes(
field.component as SelectRequestComponent
);
}

export function isFormFieldText(field: FormField): field is FormFieldText {
return TextComponents.includes(field.component as TextComponent);
}
Expand Down
Loading

0 comments on commit b3b9310

Please sign in to comment.