Skip to content

Commit

Permalink
Drop unused context from Form Fields due to unnecessary complexity (#…
Browse files Browse the repository at this point in the history
…7983)

* Drop unused `context` from Form Fields as it was adding unnecessary complexity and decreased type-safety

* try fixing storybook vite config

* update vite config
  • Loading branch information
rithviknishad authored Jun 14, 2024
1 parent 07e0ca0 commit a62d3d1
Show file tree
Hide file tree
Showing 17 changed files with 38 additions and 81 deletions.
10 changes: 2 additions & 8 deletions .storybook/vite.config.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
import { defineConfig } from "vite";

export default defineConfig({
esbuild: {
loader: "tsx",
include: [/src\/.*\.[tj]sx?$/, /.storybook\/.*\.[tj]sx?$/],
},
});
/** @type {import('vite').UserConfig} */
export default {};
2 changes: 1 addition & 1 deletion src/Components/Common/BloodPressureFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { BloodPressure } from "../Patient/models";
type Props = FormFieldBaseProps<BloodPressure>;

export default function BloodPressureFormField(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);

const handleChange = (event: FieldChangeEvent<number>) => {
const value: BloodPressure = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type PMJAYPackageItem = {
type Props = FormFieldBaseProps<PMJAYPackageItem>;

export default function PMJAYProcedurePackageAutocomplete(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);

const { fetchOptions, isLoading, options } =
useAsyncOptions<PMJAYPackageItem>("code");
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Common/RouteToFacilitySelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const keys = Object.keys(ROUTE_TO_FACILITY_OPTIONS).map((key) =>
type Props = FormFieldBaseProps<keyof typeof ROUTE_TO_FACILITY_OPTIONS>;

export default function RouteToFacilitySelect(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);

return (
<SelectFormField
Expand Down
4 changes: 3 additions & 1 deletion src/Components/Common/UserAutocompleteFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Props = FormFieldBaseProps<UserModel> & {
};

export default function UserAutocompleteFormField(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
const { fetchOptions, isLoading, options } = useAsyncOptions<UserModel>(
"id",
{ queryResponseExtractor: (data) => data.results },
Expand Down Expand Up @@ -65,6 +65,8 @@ export default function UserAutocompleteFormField(props: Props) {
<Autocomplete
id={field.id}
disabled={field.disabled}
// Voluntarily casting type as true to ignore type errors.
required={field.required as true}
placeholder={props.placeholder}
value={field.value}
onChange={field.handleChange}
Expand Down
4 changes: 1 addition & 3 deletions src/Components/Form/FormContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, createContext } from "react";
import { createContext } from "react";
import { FieldError, FieldValidator } from "./FieldValidators";
import { FormDetails } from "./Utils";

Expand All @@ -14,7 +14,5 @@ export type FormContextValue<T extends FormDetails> = (
error: FieldError | undefined;
};

export type FormContext<T extends FormDetails> = Context<FormContextValue<T>>;

export const createFormContext = <T extends FormDetails>() =>
createContext<FormContextValue<T>>(undefined as any);
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/DateFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type Props = FormFieldBaseProps<Date> & {
* ```
*/
const DateFormField = (props: Props) => {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
return (
<FormField field={field}>
<DateInputV2
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/DateRangeFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Props = FormFieldBaseProps<DateRange> & {
* ```
*/
const DateRangeFormField = (props: Props) => {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
return (
<FormField field={field}>
<DateRangeInputV2
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/Month.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const MonthLabels = [
];

const MonthFormField = (props: Props) => {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);

const [month, setMonth] = useState(field.value?.getMonth());
const [year, setYear] = useState(field.value?.getFullYear());
Expand Down
9 changes: 6 additions & 3 deletions src/Components/Form/FormFields/PhoneNumberFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface Props extends FormFieldBaseProps<string> {
}

export default function PhoneNumberFormField(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
const [error, setError] = useState<FieldError | undefined>();
const [country, setCountry] = useState<CountryData>({
flag: "🇮🇳",
Expand Down Expand Up @@ -183,8 +183,11 @@ const conditionPhoneCode = (code: string) => {
return code.startsWith("+") ? code : "+" + code;
};

const formatPhoneNumber = (value: string, types: PhoneNumberType[]) => {
if (value === undefined || value === null) {
const formatPhoneNumber = (
value: string | undefined,
types: PhoneNumberType[],
) => {
if (value == null) {
return "+91 ";
}

Expand Down
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/TextAreaFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const TextAreaFormField = forwardRef(
{ rows = 3, ...props }: TextAreaFormFieldProps,
ref?: React.Ref<HTMLTextAreaElement>,
) => {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
return (
<FormField field={field}>
<textarea
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Form/FormFields/TextFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type TextFormFieldProps = FormFieldBaseProps<string> & {
};

const TextFormField = forwardRef((props: TextFormFieldProps, ref) => {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
const { leading, trailing } = props;
const leadingFocused = props.leadingFocused || props.leading;
const trailingFocused = props.trailingFocused || props.trailing;
Expand Down
62 changes: 10 additions & 52 deletions src/Components/Form/FormFields/Utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { useContext } from "react";
import { FieldError, FieldValidator } from "../FieldValidators";
import { FormContext } from "../FormContext";
import { FormDetails } from "../Utils";
import { FieldError } from "../FieldValidators";

export type FieldChangeEvent<T> = { name: string; value: T };
export type FieldChangeEventHandler<T> = (event: FieldChangeEvent<T>) => void;
Expand All @@ -18,36 +15,21 @@ export type FieldChangeEventHandler<T> = (event: FieldChangeEvent<T>) => void;
* @template T The type of the field value.
* @template Form The type of the form details.
*/
export type FormFieldBaseProps<
T,
Form extends FormDetails | undefined = undefined,
> = {
export type FormFieldBaseProps<T> = {
label?: React.ReactNode;
labelSuffix?: React.ReactNode;
disabled?: boolean;
className?: string;
required?: boolean;
labelClassName?: string;
errorClassName?: string;
} & (Form extends FormDetails
? {
context: FormContext<Form>;
name: keyof Form;
validate?: FieldValidator<Form[keyof Form]>;
id: undefined;
onChange: undefined;
value: undefined;
error: undefined;
}
: {
context?: undefined;
name: string;
validate?: undefined;
id?: string;
onChange: FieldChangeEventHandler<T>;
value?: T;
error?: FieldError;
});
name: string;
validate?: undefined;
id?: string;
onChange: FieldChangeEventHandler<T>;
value?: T;
error?: FieldError;
};

/**
* Resolves the props for a form field.
Expand All @@ -57,31 +39,7 @@ export type FormFieldBaseProps<
* @param props The props for the field.
* @returns The resolved props along with a handleChange function.
*/
export const useFormFieldPropsResolver = <
T,
Form extends FormDetails | undefined = undefined,
>(
props: FormFieldBaseProps<T, Form>,
) => {
if (props.context) {
// Voluntarily disabling the rule of hooks here because we want to use the
// context hook only if the context is defined. If the context is not
// defined, we want to use the props instead.
//
// eslint-disable-next-line react-hooks/rules-of-hooks
const registerField = useContext(props.context);
const fieldProps = registerField(props.name, props.validate);

const handleChange = (value: T) =>
fieldProps.onChange({ name: props.name, value });

return {
...props,
...fieldProps,
handleChange,
};
}

export const useFormFieldPropsResolver = <T>(props: FormFieldBaseProps<T>) => {
const handleChange = (value: T) =>
props.onChange({ name: props.name, value });

Expand Down
2 changes: 1 addition & 1 deletion src/Components/HCX/ClaimsItemsBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { HCXItemModel } from "./models";
type Props = FormFieldBaseProps<HCXItemModel[]>;

export default function ClaimsItemsBuilder(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);

const handleUpdate = (index: number) => {
return (event: FieldChangeEvent<any>) => {
Expand Down
2 changes: 1 addition & 1 deletion src/Components/HCX/InsuranceDetailsBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import useConfig from "../../Common/hooks/useConfig";
type Props = FormFieldBaseProps<HCXPolicyModel[]> & { gridView?: boolean };

export default function InsuranceDetailsBuilder(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
const dispatch = useDispatch<any>();

const handleUpdate = (index: number) => {
Expand Down
4 changes: 3 additions & 1 deletion src/Components/HCX/InsurerAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ type Props = FormFieldBaseProps<InsurerOptionModel> & {
};

export default function InsurerAutocomplete(props: Props) {
const field = useFormFieldPropsResolver(props as any);
const field = useFormFieldPropsResolver(props);
const { fetchOptions, isLoading, options } =
useAsyncOptions<InsurerOptionModel>("code");

return (
<FormField field={field}>
<Autocomplete
id={field.id}
// Voluntarily casting type as true to ignore type errors.
required={field.required as true}
disabled={field.disabled}
placeholder={props.placeholder}
value={field.value}
Expand Down
6 changes: 3 additions & 3 deletions vite.config.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { VitePWA } from "vite-plugin-pwa";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import checker from "vite-plugin-checker";
import { treeShakeCareIcons } from "./plugins/treeShakeCareIcons";
Expand All @@ -12,7 +11,8 @@ const cdnUrls =
"http://localhost:4566",
].join(" ");

export default defineConfig({
/** @type {import('vite').UserConfig} */
export default {
envPrefix: "REACT_",
plugins: [
react(),
Expand Down Expand Up @@ -105,4 +105,4 @@ export default defineConfig({
},
},
},
});
};

0 comments on commit a62d3d1

Please sign in to comment.