Skip to content

Commit

Permalink
refactor: use react-hook-form to validate Settings/DataModel/Field Ab…
Browse files Browse the repository at this point in the history
…out form
  • Loading branch information
thaisguigon committed Apr 15, 2024
1 parent 325fff4 commit 55b02da
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import { RelationType } from '@/settings/data-model/types/RelationType';
import {
CreateRelationInput,
Field,
FieldMetadataType,
RelationMetadataType,
} from '~/generated-metadata/graphql';

import { formatFieldMetadataItemInput } from './formatFieldMetadataItemInput';

export type FormatRelationMetadataInputParams = {
relationType: RelationType;
field: Pick<Field, 'label' | 'icon' | 'description' | 'type'>;
field: Pick<Field, 'label' | 'icon' | 'description'>;
objectMetadataId: string;
connect: {
field: Pick<Field, 'label' | 'icon' | 'type'>;
field: Pick<Field, 'label' | 'icon'>;
objectMetadataId: string;
};
};
Expand All @@ -37,13 +38,19 @@ export const formatRelationMetadataInput = (
icon: fromIcon,
label: fromLabel,
name: fromName,
} = formatFieldMetadataItemInput(fromField);
} = formatFieldMetadataItemInput({
type: FieldMetadataType.Relation,
...fromField,
});
const {
description: toDescription,
icon: toIcon,
label: toLabel,
name: toName,
} = formatFieldMetadataItemInput(toField);
} = formatFieldMetadataItemInput({
type: FieldMetadataType.Relation,
...toField,
});

return {
fromDescription,
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { z } from 'zod';

import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
import { IconPicker } from '@/ui/input/components/IconPicker';
import { TextArea } from '@/ui/input/components/TextArea';
import { TextInput } from '@/ui/input/components/TextInput';

export const settingsDataModelFieldAboutFormSchema =
fieldMetadataItemSchema.pick({
description: true,
icon: true,
label: true,
});

type SettingsDataModelFieldAboutFormValues = z.infer<
typeof settingsDataModelFieldAboutFormSchema
>;

type SettingsDataModelFieldAboutFormProps = {
disabled?: boolean;
fieldMetadataItem?: FieldMetadataItem;
};

const StyledInputsContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
margin-bottom: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;

export const SettingsDataModelFieldAboutForm = ({
disabled,
fieldMetadataItem,
}: SettingsDataModelFieldAboutFormProps) => {
const { control } = useFormContext<SettingsDataModelFieldAboutFormValues>();

return (
<>
<StyledInputsContainer>
<Controller
name="icon"
control={control}
defaultValue={fieldMetadataItem?.icon ?? 'IconUsers'}
render={({ field: { onChange, value } }) => (
<IconPicker
disabled={disabled}
selectedIconKey={value}
onChange={({ iconKey }) => onChange(iconKey)}
variant="primary"
/>
)}
/>
<Controller
name="label"
control={control}
defaultValue={fieldMetadataItem?.label}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Employees"
value={value}
onChange={onChange}
disabled={disabled}
fullWidth
/>
)}
/>
</StyledInputsContainer>
<Controller
name="description"
control={control}
defaultValue={fieldMetadataItem?.description}
render={({ field: { onChange, value } }) => (
<TextArea
placeholder="Write a description"
minRows={4}
value={value ?? undefined}
onChange={onChange}
disabled={disabled}
/>
)}
/>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Meta, StoryObj } from '@storybook/react';

import { mockedPersonObjectMetadataItem } from '@/object-record/record-field/__mocks__/fieldDefinitions';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';

import { SettingsDataModelFieldAboutForm } from '../SettingsDataModelFieldAboutForm';

const meta: Meta<typeof SettingsDataModelFieldAboutForm> = {
title: 'Modules/Settings/DataModel/SettingsDataModelFieldAboutForm',
component: SettingsDataModelFieldAboutForm,
decorators: [ComponentDecorator],
};

export default meta;
type Story = StoryObj<typeof SettingsDataModelFieldAboutForm>;

export const Default: Story = {};

export const WithDefaultValues: Story = {
args: {
fieldMetadataItem: mockedPersonObjectMetadataItem.fields.find(
({ name }) => name === 'name',
)!,
},
};

export const Disabled: Story = {
args: {
disabled: true,
},
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { act, renderHook } from '@testing-library/react';

import { FieldMetadataType } from '~/generated/graphql';

import { useFieldMetadataForm } from '../useFieldMetadataForm';

describe('useFieldMetadataForm', () => {
Expand All @@ -14,8 +16,6 @@ describe('useFieldMetadataForm', () => {

expect(result.current.isInitialized).toBe(true);
expect(result.current.formValues).toEqual({
icon: 'IconUsers',
label: '',
type: 'TEXT',
currency: { currencyCode: 'USD' },
relation: {
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('useFieldMetadataForm', () => {
expect(result.current.hasSelectFormChanged).toBe(false);

act(() => {
result.current.handleFormChange({ label: 'New Label' });
result.current.handleFormChange({ type: FieldMetadataType.Number });
});

expect(result.current.hasFieldFormChanged).toBe(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DeepPartial } from 'react-hook-form';
import { v4 } from 'uuid';
import { z } from 'zod';

import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema';
Expand All @@ -15,16 +16,11 @@ import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { SettingsDataModelFieldSettingsFormValues } from '../components/SettingsDataModelFieldSettingsFormCard';

type FormValues = {
description?: string;
icon: string;
label: string;
defaultValue: any;
type: SettingsSupportedFieldType;
} & SettingsDataModelFieldSettingsFormValues;

export const fieldMetadataFormDefaultValues: FormValues = {
icon: 'IconUsers',
label: '',
type: FieldMetadataType.Text,
currency: { currencyCode: CurrencyCode.USD },
relation: {
Expand All @@ -37,9 +33,6 @@ export const fieldMetadataFormDefaultValues: FormValues = {
multiSelect: [{ color: 'green', label: 'Option 1', value: v4() }],
};
const fieldSchema = z.object({
description: z.string().optional(),
icon: z.string().startsWith('Icon'),
label: z.string().min(1),
defaultValue: z.any(),
type: z.enum(
Object.values(FieldMetadataType) as [
Expand All @@ -62,7 +55,7 @@ const relationSchema = fieldSchema.merge(
z.object({
type: z.literal(FieldMetadataType.Relation),
relation: z.object({
field: fieldSchema,
field: fieldMetadataItemSchema.pick({ icon: true, label: true }),
objectMetadataId: z.string().uuid(),
type: z.enum([
RelationMetadataType.OneToMany,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { settingsDataModelFieldAboutFormSchema } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldAboutForm';

export const settingsFieldFormSchema = settingsDataModelFieldAboutFormSchema;
Loading

0 comments on commit 55b02da

Please sign in to comment.