Skip to content

Commit

Permalink
WIP: Remove react-final-form from QRFormWrapper
Browse files Browse the repository at this point in the history
Ref: #66
  • Loading branch information
projkov committed May 31, 2024
1 parent 1cdd3a2 commit 7d9bc32
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AnswerValue, QuestionItemProps } from '@beda.software/fhir-questionnaire/vendor/sdc-qrf';
import _ from 'lodash';

import { isSuccess, RemoteDataResult, success } from 'aidbox-react/lib/libs/remoteData';
import { RemoteDataResult, isSuccess, success } from 'aidbox-react/lib/libs/remoteData';
import { applyDataTransformer, service } from 'aidbox-react/lib/services/service';

import {
Expand All @@ -10,6 +10,7 @@ import {
ValueSet,
} from 'shared/src/contrib/aidbox';


export function getDisplay(value: AnswerValue): string {
const valueType = _.keys(value)[0];
//@ts-ignore
Expand Down Expand Up @@ -104,5 +105,5 @@ export function useAnswerChoice({ questionItem, parentPath }: QuestionItemProps)

const deps = [linkId];

return { fieldName, loadOptions, validate, deps };
return { fieldName, loadOptions, validate, deps, fieldPath };
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFieldController } from '@beda.software/fhir-questionnaire/components/QuestionnaireResponseForm';
import {
QuestionItemProps,
useQuestionnaireResponseFormContext,
Expand All @@ -13,9 +14,13 @@ import { QuestionLabel } from '../label';

export function QuestionChoice(props: QuestionItemProps) {
const { questionItem } = props;
const { fieldName, loadOptions, validate, deps } = useAnswerChoice(props);
const { fieldName, loadOptions, validate, deps, fieldPath } = useAnswerChoice(props);
const { text, repeats, readOnly, hidden, linkId } = questionItem;
const qrfContext = useQuestionnaireResponseFormContext();
const { value, onChange, disabled, formItem, onBlur } = useFieldController(
fieldPath,
questionItem,
);

if (hidden) {
return null;
Expand All @@ -24,26 +29,22 @@ export function QuestionChoice(props: QuestionItemProps) {
const fieldProps = { validate };

return (
<QuestionField name={fieldName} {...fieldProps}>
{({ input }) => {
return (
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<AsyncSelectField<QuestionnaireItemAnswerOption>
key={`answer-choice-${deps.join('-')}`}
data-testid={`choice-${linkId}`}
id={fieldName}
input={input}
label={text}
loadOptions={loadOptions}
isMulti={!!repeats}
getOptionLabel={(option) => getAnswerDisplay(option.value)}
getOptionValue={(option) => getAnswerCode(option.value)}
readOnly={qrfContext.readOnly || readOnly}
/>
</>
);
}}
</QuestionField>
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<AsyncSelectField<QuestionnaireItemAnswerOption>
key={`answer-choice-${deps.join('-')}`}
data-testid={`choice-${linkId}`}
id={fieldName}
onChange={onChange}
value={value}
// input={input}
label={text}
loadOptions={loadOptions}
isMulti={!!repeats}
getOptionLabel={(option) => getAnswerDisplay(option.value)}
getOptionValue={(option) => getAnswerCode(option.value)}
readOnly={qrfContext.readOnly || readOnly}
/>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { QuestionnaireResponseItemAnswer } from 'fhir/r4b';
import _ from 'lodash';
// eslint-disable-next-line import/named
import { FieldInputProps } from 'react-final-form';
import { ActionMeta, PropsValue } from 'react-select';
import { AsyncSelect } from 'web/src/components/Select';
// eslint-disable-next-line import/named

interface Props<T> {
label?: string;
id?: string;
placeholder?: string;
helpText?: string;
input: FieldInputProps<any, HTMLElement>;
formItemProps?: any;
loadOptions: (searchText: string) => Promise<T[]>;
readOnly?: boolean;
Expand All @@ -18,19 +17,20 @@ interface Props<T> {
getOptionValue: (option: T) => string;
isMulti?: boolean;
testId?: string;
value?: QuestionnaireResponseItemAnswer[];
}

export function AsyncSelectField<T>(props: Props<T>) {
const {
readOnly,
input,
id,
placeholder = 'Select...',
getOptionLabel,
getOptionValue,
onChange,
isMulti,
loadOptions,
value,
} = props;

const debouncedLoadOptions = _.debounce(
Expand All @@ -42,23 +42,23 @@ export function AsyncSelectField<T>(props: Props<T>) {

return (
<AsyncSelect
value={value}
defaultOptions
isDisabled={readOnly}
loadOptions={debouncedLoadOptions}
placeholder={placeholder}
getOptionLabel={getOptionLabel}
getOptionValue={getOptionValue}
id={id}
{...input}
onChange={(value, action) => {
input.onChange(value ?? undefined);
// onChange(value ?? undefined);

if (onChange) {
onChange(value, action);
}
}}
isMulti={isMulti}
styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }) }}
// styles={{ menuPortal: (base) => ({ ...base, zIndex: 9999 }) }}
menuPortalTarget={document.body}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFieldController } from '@beda.software/fhir-questionnaire/components/QuestionnaireResponseForm';
import {
QuestionItemProps,
useQuestionnaireResponseFormContext,
Expand All @@ -11,22 +12,22 @@ export function QuestionDecimal({ parentPath, questionItem }: QuestionItemProps)
const { linkId, readOnly, hidden } = questionItem;
const fieldPath = [...parentPath, linkId, 0, 'value', 'decimal'];
const fieldName = fieldPath.join('.');
const { value, onChange, disabled, formItem, onBlur } = useFieldController(
fieldPath,
questionItem,
);

return (
<QuestionField name={fieldName}>
{({ input, meta }) => (
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<input
type="numeric"
id={fieldName}
{...input}
readOnly={qrfContext.readOnly || readOnly || hidden}
onChange={(e) => input.onChange(parseInt(e.target.value))}
/>
{meta.touched && meta.error && <span>{meta.error}</span>}
</>
)}
</QuestionField>
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<input
type="numeric"
id={fieldName}
value={value ?? ''}
disabled={disabled}
readOnly={qrfContext.readOnly || readOnly || hidden}
onChange={(e) => onChange(Number(e.target.value))}
/>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFieldController } from '@beda.software/fhir-questionnaire/components/QuestionnaireResponseForm';
import { useQuestionnaireResponseFormContext } from '@beda.software/fhir-questionnaire/vendor/sdc-qrf';
import { getAnswerCode, getAnswerDisplay } from 'web/src/utils/questionnaire';

Expand All @@ -8,43 +9,43 @@ import { AsyncSelectField } from '../choice/select';
import { QuestionField } from '../field';
import { QuestionLabel } from '../label';


function QuestionReferenceUnsafe<R extends Resource = any, IR extends Resource = any>(
props: AnswerReferenceProps<R, IR>,
) {
const { questionItem, parentPath } = props;
const { loadOptions, onChange, deps, validate } = useAnswerReference(props);
const { loadOptions, deps, validate } = useAnswerReference(props);
const { text, repeats, linkId, helpText, readOnly } = questionItem;
const qrfContext = useQuestionnaireResponseFormContext();

const fieldPath = [...parentPath, questionItem.linkId!];
const fieldName = fieldPath.join('.');

const { value, onChange, disabled, formItem, onBlur } = useFieldController(
fieldPath,
questionItem,
);

const fieldProps = { validate };

return (
<QuestionField name={fieldName} {...fieldProps}>
{({ input }) => {
return (
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<AsyncSelectField<QuestionnaireItemAnswerOption>
key={`answer-choice-${deps.join('-')}`}
input={input}
id={fieldName}
testId={linkId!}
label={text}
loadOptions={loadOptions}
isMulti={!!repeats}
getOptionLabel={(option) => getAnswerDisplay(option.value)}
getOptionValue={(option) => getAnswerCode(option.value)}
onChange={onChange}
readOnly={qrfContext.readOnly || readOnly}
helpText={helpText}
/>
</>
);
}}
</QuestionField>
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<AsyncSelectField<QuestionnaireItemAnswerOption>
key={`answer-choice-${deps.join('-')}`}
value={value}
id={fieldName}
testId={linkId!}
label={text}
loadOptions={loadOptions}
isMulti={!!repeats}
getOptionLabel={(option) => getAnswerDisplay(option.value)}
getOptionValue={(option) => getAnswerCode(option.value)}
onChange={onChange}
readOnly={qrfContext.readOnly || readOnly}
helpText={helpText}
/>
</>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFieldController } from '@beda.software/fhir-questionnaire/components/QuestionnaireResponseForm';
import {
QuestionItemProps,
useQuestionnaireResponseFormContext,
Expand All @@ -11,21 +12,21 @@ export function QuestionString({ parentPath, questionItem }: QuestionItemProps)
const { linkId, readOnly, hidden } = questionItem;
const fieldPath = [...parentPath, linkId, 0, 'value', 'string'];
const fieldName = fieldPath.join('.');

const { value, onChange, disabled, formItem, onBlur } = useFieldController(
fieldPath,
questionItem,
);
return (
<QuestionField name={fieldName}>
{({ input, meta }) => (
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<input
type="text"
id={fieldName}
{...input}
readOnly={qrfContext.readOnly || readOnly || hidden}
/>
{meta.touched && meta.error && <span>{meta.error}</span>}
</>
)}
</QuestionField>
<>
<QuestionLabel questionItem={questionItem} htmlFor={fieldName} />
<input
type="text"
id={fieldName}
value={value ?? ''}
disabled={disabled}
readOnly={qrfContext.readOnly || readOnly || hidden}
onChange={(e) => onChange(e.target.value)}
/>
</>
);
}
Loading

0 comments on commit 7d9bc32

Please sign in to comment.