Skip to content

Commit

Permalink
feat: added select field & fixed types & tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chesterkmr committed Dec 18, 2024
1 parent babea18 commit 7f07d19
Show file tree
Hide file tree
Showing 28 changed files with 344 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const DropdownInput: FunctionComponent<DropdownInputProps> = ({
testId,
onChange,
onBlur,
onFocus,
props,
textInputClassName,
}) => {
Expand Down Expand Up @@ -119,6 +120,7 @@ export const DropdownInput: FunctionComponent<DropdownInputProps> = ({
{searchable ? (
<CommandInput
onBlur={onBlur}
onFocus={onFocus}
placeholder={searchPlaceholder}
className={ctw('placeholder:text-muted-foreground h-9', textInputClassName)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface DropdownInputProps {
openOnFocus?: boolean;
onChange: (value: string, inputName: string) => void;
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
props?: {
trigger?: Pick<ComponentProps<typeof PopoverContent>, 'className'> & {
icon?: React.ReactNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import { useValidator } from '../../../Validator';
import { useDynamicForm } from '../../context';
import { useElement } from '../../hooks/external/useElement';
import { useField } from '../../hooks/external/useField';
import { TBaseFormElements, TDynamicFormElement } from '../../types';
import { TDynamicFormElement } from '../../types';

export interface ISubmitButtonParams {
disableWhenFormIsInvalid?: boolean;
text?: string;
}

export const SubmitButton: TDynamicFormElement<TBaseFormElements, ISubmitButtonParams> = ({
element,
}) => {
export const SubmitButton: TDynamicFormElement<string, ISubmitButtonParams> = ({ element }) => {
const { id } = useElement(element);
const { disabled: _disabled } = useField(element);
const { submit } = useDynamicForm();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useValidator } from '../../../Validator';
import { useDynamicForm } from '../../context';
import { useElement } from '../../hooks/external';
import { useField } from '../../hooks/external/useField';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { ISubmitButtonParams, SubmitButton } from './SubmitButton';

vi.mock('@/components/atoms', () => ({
Expand All @@ -31,8 +31,8 @@ describe('SubmitButton', () => {
id: 'test-button',
params: {},
valueDestination: 'test.path',
element: '' as TBaseFormElements,
} as IFormElement<TBaseFormElements, ISubmitButtonParams>;
element: '',
} as unknown as IFormElement<string, ISubmitButtonParams>;

const mockSubmit = vi.fn();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AutocompleteInput } from '@/components/molecules';
import { createTestId } from '@/components/organisms/Renderer';
import { useField } from '../../hooks/external/useField';
import { FieldLayout } from '../../layouts/FieldLayout';
import { TBaseFormElements, TDynamicFormField } from '../../types';
import { TDynamicFormField } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';

export interface IAutocompleteFieldOption {
Expand All @@ -15,9 +15,7 @@ export interface IAutocompleteFieldParams {
options: IAutocompleteFieldOption[];
}

export const AutocompleteField: TDynamicFormField<TBaseFormElements, IAutocompleteFieldParams> = ({
element,
}) => {
export const AutocompleteField: TDynamicFormField<IAutocompleteFieldParams> = ({ element }) => {
const { params } = element;
const { stack } = useStack();
const { value, onChange, onBlur, onFocus, disabled } = useField<string | undefined>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cleanup, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../hooks/external/useField';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';
import { AutocompleteField, IAutocompleteFieldParams } from './AutocompleteField';

Expand Down Expand Up @@ -52,7 +52,7 @@ describe('AutocompleteField', () => {
placeholder: 'Select an option',
options: mockOptions,
},
} as IFormElement<TBaseFormElements, IAutocompleteFieldParams>;
} as unknown as IFormElement<string, IAutocompleteFieldParams>;

const mockFieldProps = {
value: '',
Expand Down Expand Up @@ -131,7 +131,7 @@ describe('AutocompleteField', () => {
it('should use default params when none provided', () => {
const elementWithoutParams = {
id: 'test-autocomplete',
} as unknown as IFormElement<TBaseFormElements, IAutocompleteFieldParams>;
} as unknown as IFormElement<string, IAutocompleteFieldParams>;

render(<AutocompleteField element={elementWithoutParams} />);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../hooks/external';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';
import { CheckboxField } from './CheckboxField';

Expand Down Expand Up @@ -34,7 +34,7 @@ describe('CheckboxField', () => {
const mockElement = {
id: 'test-checkbox',
type: '',
} as unknown as IFormElement<TBaseFormElements>;
} as unknown as IFormElement<string>;

const mockFieldProps = {
value: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/atoms';
import { createTestId } from '@/components/organisms/Renderer';
import { useField } from '../../hooks/external';
import { FieldLayout } from '../../layouts/FieldLayout';
import { TBaseFormElements, TDynamicFormField } from '../../types';
import { TDynamicFormField } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';

export interface ICheckboxListOption {
Expand All @@ -15,9 +15,7 @@ export interface ICheckboxListFieldParams {
options: ICheckboxListOption[];
}

export const CheckboxListField: TDynamicFormField<TBaseFormElements, ICheckboxListFieldParams> = ({
element,
}) => {
export const CheckboxListField: TDynamicFormField<ICheckboxListFieldParams> = ({ element }) => {
const { options = [] } = element.params || {};
const { stack } = useStack();
const { value, onChange, onFocus, onBlur, disabled } = useField<string[]>(element, stack);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createTestId } from '@/components/organisms/Renderer';
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../hooks/external/useField';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { CheckboxListField, ICheckboxListFieldParams } from './CheckboxList';

// Mock dependencies
Expand Down Expand Up @@ -50,7 +50,7 @@ describe('CheckboxListField', () => {
params: {
options: mockOptions,
},
} as unknown as IFormElement<TBaseFormElements, ICheckboxListFieldParams>;
} as unknown as IFormElement<string, ICheckboxListFieldParams>;

beforeEach(() => {
cleanup();
Expand Down Expand Up @@ -178,7 +178,7 @@ describe('CheckboxListField', () => {
const emptyElement = {
...mockElement,
params: { options: [] },
} as unknown as IFormElement<TBaseFormElements, ICheckboxListFieldParams>;
} as unknown as IFormElement<string, ICheckboxListFieldParams>;

render(<CheckboxListField element={emptyElement} />);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { createTestId } from '@/components/organisms/Renderer';
import { useCallback } from 'react';
import { useField } from '../../hooks/external/useField';
import { FieldLayout } from '../../layouts/FieldLayout';
import { TBaseFormElements, TDynamicFormField } from '../../types';
import { TDynamicFormField } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';

export interface IDateFieldParams {
Expand All @@ -17,7 +17,7 @@ export interface IDateFieldParams {
outputFormat?: 'date' | 'iso';
}

export const DateField: TDynamicFormField<TBaseFormElements, IDateFieldParams> = ({ element }) => {
export const DateField: TDynamicFormField<IDateFieldParams> = ({ element }) => {
const {
disableFuture = false,
disablePast = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DatePickerInput } from '@/components/molecules';
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../hooks/external/useField';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { DateField, IDateFieldParams } from './DateField';

// Mock dependencies
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('DateField', () => {
disablePast: false,
outputFormat: 'iso',
},
} as unknown as IFormElement<TBaseFormElements, IDateFieldParams>;
} as unknown as IFormElement<string, IDateFieldParams>;

it('renders DatePickerInput with correct props', () => {
render(<DateField element={mockElement} />);
Expand Down Expand Up @@ -137,7 +137,7 @@ describe('DateField', () => {
});

it('passes correct params to DatePickerInput', () => {
const elementWithParams: IFormElement<TBaseFormElements, IDateFieldParams> = {
const elementWithParams: IFormElement<string, IDateFieldParams> = {
...mockElement,
params: {
disableFuture: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,19 @@ import { Button } from '@/components/atoms';
import { Renderer, TRendererSchema } from '@/components/organisms/Renderer';
import { useDynamicForm } from '../../context';
import { useElement } from '../../hooks/external';
import { TBaseFormElements, TDynamicFormElement } from '../../types';
import { IUseFieldParams, useFieldList } from './hooks/useFieldList';
import { TDynamicFormField } from '../../types';
import { useFieldList } from './hooks/useFieldList';
import { StackProvider, useStack } from './providers/StackProvider';

export type TFieldListValueType<T extends { _id: string }> = T[];

export interface IFieldListOptions {
export interface IFieldListParams {
defaultValue: AnyObject;
addButtonLabel?: string;
removeButtonLabel?: string;
}

export const FieldList: TDynamicFormElement<
TBaseFormElements,
{ addButtonLabel: string; removeButtonLabel: string } & IUseFieldParams<object>
> = props => {
export const FieldList: TDynamicFormField<IFieldListParams> = props => {
const { elementsMap } = useDynamicForm();
const { stack } = useStack();
const { element } = props;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useCallback } from 'react';
import { useField } from '../../../../hooks/external';
import { IFormElement, TBaseFormElements } from '../../../../types';
import { IFormElement } from '../../../../types';
import { useStack } from '../../providers/StackProvider';

export interface IUseFieldParams<T> {
defaultValue: T;
}
export interface IUseFieldListProps {
element: IFormElement<TBaseFormElements, IUseFieldParams<object>>;
element: IFormElement<string, IUseFieldParams<object>>;
}

export const useFieldList = ({ element }: IUseFieldListProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { renderHook } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../../../hooks/external';
import { IFormElement, TBaseFormElements } from '../../../../types';
import { IFormElement } from '../../../../types';
import { useStack } from '../../providers/StackProvider';
import { IUseFieldParams, useFieldList } from './useFieldList';

Expand All @@ -16,7 +16,7 @@ describe('useFieldList', () => {
params: {
defaultValue: { test: 'value' },
},
} as unknown as IFormElement<TBaseFormElements, IUseFieldParams<object>>;
} as unknown as IFormElement<string, IUseFieldParams<object>>;

const mockOnChange = vi.fn();
const mockStack = [0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ import { MultiSelect, MultiSelectOption, MultiSelectValue } from '@/components/m
import { SelectedElementParams } from '@/components/molecules/inputs/MultiSelect/types';
import { useCallback } from 'react';
import { useField } from '../../hooks/external';
import { TBaseFormElements, TDynamicFormField } from '../../types';
import { TDynamicFormField } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';
import { MultiselectfieldSelectedItem } from './MultiselectFieldSelectedItem';

export interface IMultiselectFieldParams {
options: MultiSelectOption[];
}

export const MultiselectField: TDynamicFormField<TBaseFormElements, IMultiselectFieldParams> = ({
element,
}) => {
export const MultiselectField: TDynamicFormField<IMultiselectFieldParams> = ({ element }) => {
const { stack } = useStack();
const { value, onChange, onBlur, onFocus, disabled } = useField<MultiSelectValue[] | undefined>(
element,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SelectedElementParams } from '@/components/molecules/inputs/MultiSelect
import { fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useField } from '../../hooks/external';
import { IFormElement, TBaseFormElements } from '../../types';
import { IFormElement } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';
import { IMultiselectFieldParams, MultiselectField } from './MultiselectField';
import { MultiselectfieldSelectedItem } from './MultiselectFieldSelectedItem';
Expand Down Expand Up @@ -52,7 +52,7 @@ describe('MultiselectField', () => {
params: {
options: mockOptions,
},
} as unknown as IFormElement<TBaseFormElements, IMultiselectFieldParams>;
} as unknown as IFormElement<string, IMultiselectFieldParams>;

beforeEach(() => {
vi.clearAllMocks();
Expand Down Expand Up @@ -103,7 +103,7 @@ describe('MultiselectField', () => {
const elementWithoutOptions = {
...mockElement,
params: {},
} as unknown as IFormElement<TBaseFormElements, IMultiselectFieldParams>;
} as unknown as IFormElement<string, IMultiselectFieldParams>;

render(<MultiselectField element={elementWithoutOptions} />);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { DropdownInput } from '@/components/molecules';
import { createTestId } from '@/components/organisms/Renderer';
import { useElement, useField } from '../../hooks/external';
import { IFieldLayoutBaseParams } from '../../layouts/FieldLayout';
import { TDynamicFormField } from '../../types';
import { useStack } from '../FieldList/providers/StackProvider';

export interface ISelectOption {
value: string;
label: string;
}

export interface ISelectFieldParams extends IFieldLayoutBaseParams {
placeholder?: string;
options: ISelectOption[];
}

export const SelectField: TDynamicFormField<ISelectFieldParams> = ({ element }) => {
const { stack } = useStack();
const { id } = useElement(element, stack);
const { value, disabled, onChange, onBlur, onFocus } = useField<string | undefined>(
element,
stack,
);

const { placeholder, options = [] } = element.params || {};

return (
<DropdownInput
name={id}
options={options}
value={value}
testId={createTestId(element, stack)}
placeholdersParams={{
placeholder: placeholder || '',
}}
disabled={disabled}
onChange={onChange}
onBlur={onBlur}
onFocus={onFocus}
/>
);
};
Loading

0 comments on commit 7f07d19

Please sign in to comment.