Skip to content

Commit

Permalink
Removed all usages of the "react-final-form" package from the applica…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
ialakey committed Jun 20, 2024
1 parent 0e50edf commit 94aba65
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 131 deletions.
1 change: 0 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"react": "18.2.0",
"react-app-rewired": "^2.2.1",
"react-dom": "18.2.0",
"react-final-form": "^6.5.9",
"react-final-form-arrays": "^3.1.3",
"react-final-form-listeners": "^1.0.3",
"react-router-dom": "^6.15.0",
Expand Down
31 changes: 19 additions & 12 deletions web/src/components/QRFormWrapper/components/field.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
// eslint-disable-next-line import/named
import { Field, FieldProps } from 'react-final-form';
import { ReactNode } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import s from '../QuestionnaireResponseForm.module.scss';

interface Props extends FieldProps<any, any> {}
interface Props {
name: string;
children: ReactNode | ((props: any) => ReactNode);
}

export function QuestionField(props: Props) {
const { children, ...other } = props;
export function QuestionField({ name, children }: Props) {
const { control } = useFormContext();

return (
<Field {...other}>
{children instanceof Function ? (
(props) => <div className={s.field}>{children(props)}</div>
) : (
<div className={s.field}>{children}</div>
)}
</Field>
<Controller
name={name}
control={control}
render={({ field }) =>
typeof children === 'function' ? (
<div className={s.field}>{children(field)}</div>
) : (
<div className={s.field}>{children}</div>
)
}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { GroupItemProps } from '@beda.software/fhir-questionnaire/vendor/sdc-qrf';
import _ from 'lodash';
import React from 'react';
// eslint-disable-next-line import/named
import { Field, FieldInputProps } from 'react-final-form';
import { useFormContext, useFieldArray } from 'react-hook-form';

import s from './RepeatableGroups.module.scss';
import { QuestionItems } from '../../questionItems';
Expand All @@ -20,82 +18,63 @@ export function RepeatableGroups(props: RepeatableGroupsProps) {
const baseFieldPath = [...parentPath, linkId];
const fieldName = baseFieldPath.join('.');

return (
<Field name={fieldName}>
{({ input }) => {
const items =
input.value.items && input.value.items.length
? input.value.items
: required
? [{}]
: [];
const { control, watch } = useFormContext();
const { fields, append, remove } = useFieldArray({
control,
name: fieldName,
});

const items = watch(fieldName) || (required ? [{}] : []);

return (
<div className={s.group}>
{_.map(items, (_elem, index: number) => {
if (!input.value.items[index]) {
return null;
}
return (
<div className={s.group}>
{fields.map((field, index) => {
if (!items[index]) {
return null;
}

return renderGroup ? (
<React.Fragment key={`${fieldName}-${index}`}>
{renderGroup({
index,
input,
groupItem,
})}
</React.Fragment>
) : (
<RepeatableGroupDefault
key={index}
index={index}
groupItem={groupItem}
input={input}
/>
);
return renderGroup ? (
<React.Fragment key={`${fieldName}-${index}`}>
{renderGroup({
index,
field,
groupItem,
remove: () => remove(index),
})}
<div>
<button
className={s.addButton}
onClick={() => {
const existingItems = input.value.items || [];
const updatedInput = { items: [...existingItems, {}] };
input.onChange(updatedInput);
}}
>
{`+ Add another answer`}
</button>
</div>
</div>
</React.Fragment>
) : (
<RepeatableGroupDefault
key={index}
index={index}
groupItem={groupItem}
field={field}
remove={() => remove(index)}
/>
);
}}
</Field>
})}
<div>
<button className={s.addButton} onClick={() => append({})}>
{`+ Add another answer`}
</button>
</div>
</div>
);
}

interface RepeatableGroupProps {
index: number;
input: FieldInputProps<any, HTMLElement>;
field: Record<'id', string>;
groupItem: GroupItemProps;
remove: () => void;
}

function useRepeatableGroup(props: RepeatableGroupProps) {
const { index, input, groupItem } = props;
const { index, groupItem, remove } = props;
const { parentPath, questionItem, context } = groupItem;
const { linkId } = questionItem;

const onRemove = () => {
const filteredArray = _.filter(
input.value.items,
(_val, valIndex: number) => valIndex !== index,
);
input.onChange({
items: [...filteredArray],
});
};

return {
onRemove,
onRemove: remove,
parentPath: [...parentPath, linkId, 'items', index.toString()],
context: context[0]!,
};
Expand Down
32 changes: 15 additions & 17 deletions web/src/components/TerminologyField/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _ from 'lodash';
import { useCallback } from 'react';
import { Field } from 'react-final-form';
import { useController, useFormContext } from 'react-hook-form';
import AsyncSelect from 'react-select/async';

import { isSuccess } from 'fhir-react/lib/libs/remoteData';
Expand Down Expand Up @@ -32,6 +32,8 @@ function getOptionValue({ value }: Option) {
}

export function TerminologyField({ label, name, valueSetId, repeats }: TerminologyFieldProps) {
const { control } = useFormContext();
const { field } = useController({ name, control });
const loadOptions = useCallback(
async (searchText: string) => {
const response = mapSuccess(
Expand Down Expand Up @@ -77,21 +79,17 @@ export function TerminologyField({ label, name, valueSetId, repeats }: Terminolo
);

return (
<Field name={name}>
{({ input }) => (
<div className={s.wrapper}>
<label className={s.groupLabel}>{label}</label>
<AsyncSelect<Option>
loadOptions={debouncedLoadOptions}
defaultOptions
getOptionLabel={getOptionLabel}
getOptionValue={getOptionValue}
onChange={input.onChange}
value={input.value}
isMulti={repeats === false ? false : undefined}
/>
</div>
)}
</Field>
<div className={s.wrapper}>
<label className={s.groupLabel}>{label}</label>
<AsyncSelect<Option>
loadOptions={debouncedLoadOptions}
defaultOptions
getOptionLabel={getOptionLabel}
getOptionValue={getOptionValue}
onChange={field.onChange}
value={field.value}
isMulti={repeats === false ? false : undefined}
/>
</div>
);
}
82 changes: 43 additions & 39 deletions web/src/containers/Main/PromptForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Field, Form } from 'react-final-form';
import { useForm, Controller } from 'react-hook-form';
import { Button } from 'web/src/components/Button';

import { RemoteDataResult, isFailure, isSuccess } from 'fhir-react/lib/libs/remoteData';
Expand All @@ -22,49 +22,53 @@ export function PromptForm(props: Props) {
const [isLoading, setIsLoading] = useState(false);
const disabled = isLoading;

return (
<Form<PromptFormInterface>
onSubmit={async (values) => {
setIsLoading(true);
const response = await onSubmit(values.prompt);
const { handleSubmit, control } = useForm<PromptFormInterface>();

const handleFormSubmit = async (values: PromptFormInterface) => {
setIsLoading(true);
const response = await onSubmit(values.prompt);

if (isSuccess(response)) {
setIsLoading(false);
goBack();
}
if (isSuccess(response)) {
setIsLoading(false);
goBack();
}

if (isFailure(response)) {
setIsLoading(false);
}
}}
render={({ handleSubmit }) => (
<form onSubmit={handleSubmit} className={s.form}>
<div className={s.field}>
<label className={s.label} htmlFor={`prompt-${id}`}>
{label}
</label>
<Field
name="prompt"
component="textarea"
if (isFailure(response)) {
setIsLoading(false);
}
};

return (
<form onSubmit={handleSubmit(handleFormSubmit)} className={s.form}>
<div className={s.field}>
<label className={s.label} htmlFor={`prompt-${id}`}>
{label}
</label>
<Controller
name="prompt"
control={control}
defaultValue=""
render={({ field }) => (
<textarea
{...field}
rows={5}
style={{ resize: 'vertical' }}
id={`prompt-${id}`}
/>
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
<Button type="submit" disabled={disabled}>
{'Submit'}
</Button>
{isLoading ? <div className={s.label}>Loading... </div> : null}
</div>
</div>
{isLoading ? (
<div className={s.label}>
The process of generating may require some time to complete. Please
wait.
</div>
) : null}
</form>
)}
/>
)}
/>
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
<Button type="submit" disabled={disabled}>
{'Submit'}
</Button>
{isLoading ? <div className={s.label}>Loading... </div> : null}
</div>
</div>
{isLoading ? (
<div className={s.label}>
The process of generating may require some time to complete. Please wait.
</div>
) : null}
</form>
);
}

0 comments on commit 94aba65

Please sign in to comment.