Skip to content

Commit

Permalink
Merge 354-generic-resource-list. Fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
vesnushka committed Dec 3, 2024
2 parents 11cf04b + 02496fd commit 597d7fb
Show file tree
Hide file tree
Showing 22 changed files with 1,471 additions and 154 deletions.
140 changes: 140 additions & 0 deletions resources/seeds/Questionnaire/group-wizard.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@

name: Group wizard
title: Group wizard
subjectType:
- Encounter
- Patient
item:
- type: group
linkId: wizard
itemControl:
coding:
- code: wizard
item:
- item:
- text: How many days a week do you engage in physical activity?
type: integer
linkId: 'q11'
required: true
- text: >-
On average, how many minutes do you engage in physical activity each
day?
type: integer
linkId: 'q12'
required: true
- text: >-
What types of physical activities do you participate in? (Select all
that apply)
type: choice
linkId: 'q13'
required: false
answerOption:
- value:
string: Walking
- value:
string: Running
- value:
string: Cycling
- value:
string: Swimming
- value:
string: Weightlifting
- value:
string: Other
text: Physical Activity
type: group
linkId: physical-activity
- item:
- text: How many servings of fruits and vegetables do you consume daily?
type: integer
linkId: 'q21'
required: true
- text: How often do you eat fast food?
type: choice
linkId: 'q22'
required: true
answerOption:
- value:
string: Never
- value:
string: Once a week
- value:
string: Several times a week
- value:
string: Daily
- text: >-
Do you follow any specific dietary restrictions? (e.g., vegetarian,
vegan, gluten-free)
type: string
linkId: 'q23'
required: false
text: Dietary Habits
type: group
linkId: 'dietary-habits'
- item:
- text: On average, how many hours of sleep do you get per night?
type: integer
linkId: 'q31'
required: true
- text: Do you have trouble falling asleep or staying asleep?
type: choice
linkId: 'q32'
required: true
answerOption:
- value:
string: 'Yes'
- value:
string: 'No'
- text: Do you use any sleep aids (e.g., medication, herbal supplements)?
type: choice
linkId: 'q33'
required: false
answerOption:
- value:
string: 'Yes'
- value:
string: 'No'
text: Sleep Patterns
type: group
linkId: 'sleep-patterns'
- item:
- text: Do you smoke tobacco or use nicotine products?
type: choice
linkId: 'q41'
required: true
answerOption:
- value:
string: 'Yes'
- value:
string: 'No'
- text: How often do you consume alcoholic beverages?
type: choice
linkId: 'q42'
required: true
answerOption:
- value:
string: Never
- value:
string: Occasionally
- value:
string: Regularly
- text: Have you ever used recreational drugs?
type: choice
linkId: 'q43'
required: false
answerOption:
- value:
string: 'Yes'
- value:
string: 'No'
text: Substance Use
type: group
linkId: 'substance-use'
resourceType: Questionnaire
status: active
id: group-wizard
meta:
profile:
- https://beda.software/beda-emr-questionnaire
url: >-
https://aidbox.emr.beda.software/ui/console#/entities/Questionnaire/group-wizard
108 changes: 91 additions & 17 deletions src/components/BaseQuestionnaireResponseForm/FormFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { CheckOutlined } from '@ant-design/icons';
import { Trans } from '@lingui/macro';
import { Button } from 'antd';
import { DebouncedFunc } from 'lodash';
import { CSSProperties } from 'react';
import { useWatch } from 'react-hook-form';
import { FormItems } from 'sdc-qrf';

import { QuestionnaireResponseFormSaveResponse } from 'src/hooks/questionnaire-response-form-data';
import { isLoading, isSuccess } from '@beda.software/remote-data';

import { BaseQuestionnaireResponseFormProps } from '.';
import { S } from './BaseQuestionnaireResponseForm.styles';

export interface FormFooterComponentProps {
Expand All @@ -11,44 +17,112 @@ export interface FormFooterComponentProps {
onCancel?: () => void;
}

export interface Props {
onCancel?: () => void;
onSuccess?: (data: QuestionnaireResponseFormSaveResponse) => Promise<any> | void;
onFailure?: (error: any) => Promise<any> | void;

export interface Props extends BaseQuestionnaireResponseFormProps {
submitting: boolean;
readOnly?: boolean;

FormFooterComponent?: React.ElementType<FormFooterComponentProps>;
saveButtonTitle?: string;
cancelButtonTitle?: string;
debouncedSaveDraft?: DebouncedFunc<(currentFormValues: FormItems) => Promise<void>>;
className?: string | undefined;
style?: CSSProperties | undefined;
submitDisabled?: boolean;
}

export function FormFooter(props: Props) {
const { readOnly, onCancel, FormFooterComponent, saveButtonTitle, cancelButtonTitle, submitting } = props;
const submitDisabled = submitting;
const {
formData,
readOnly,
onCancel,
FormFooterComponent,
saveButtonTitle,
cancelButtonTitle,
submitting,
debouncedSaveDraft,
autoSave,
draftSaveResponse,
setDraftSaveResponse,
className,
style,
submitDisabled: initialSubmitDisabled,
} = props;

const formValues = useWatch();
const assembledFromQuestionnaireId = formData.context.questionnaire.assembledFrom;

if (readOnly) {
return null;
}

const submitLoading = submitting;
const submitDisabled = submitting || initialSubmitDisabled;

const draftLoading = draftSaveResponse && isLoading(draftSaveResponse);
const draftSaved = draftSaveResponse && isSuccess(draftSaveResponse);

const isSomeButtonInLoading = submitLoading || draftLoading;

const renderDraftButton = () => {
if (!assembledFromQuestionnaireId) {
return null;
}

if (!setDraftSaveResponse || !debouncedSaveDraft) {
return null;
}

if (!autoSave) {
return (
<Button
loading={draftLoading}
disabled={isSomeButtonInLoading}
onClick={() => debouncedSaveDraft(formValues)}
>
<Trans>Save as draft</Trans>
</Button>
);
}

if (autoSave && draftLoading) {
return (
<Button type="ghost" disabled loading={draftLoading}>
<Trans>Saving draft</Trans>
</Button>
);
}

if (autoSave && draftSaved) {
return (
<Button type="ghost" disabled icon={<CheckOutlined />}>
<span>
<Trans>Saved as draft</Trans>
</span>
</Button>
);
}

return null;
};

return (
<>
{FormFooterComponent ? (
<FormFooterComponent submitting={submitting} submitDisabled={submitDisabled} onCancel={onCancel} />
) : (
<S.Footer>
<S.Footer className={className} style={style}>
{renderDraftButton()}
{onCancel && (
<Button type="default" onClick={onCancel} data-testid="cancel-button">
<Button
type="default"
onClick={onCancel}
data-testid="cancel-button"
disabled={isSomeButtonInLoading}
>
{cancelButtonTitle ?? <Trans>Cancel</Trans>}
</Button>
)}
<Button
type="primary"
htmlType="submit"
loading={submitting}
data-testid="submit-button"
disabled={submitDisabled}
loading={submitLoading}
disabled={submitDisabled || isSomeButtonInLoading}
>
{saveButtonTitle ?? <Trans>Save</Trans>}
</Button>
Expand Down
13 changes: 12 additions & 1 deletion src/components/BaseQuestionnaireResponseForm/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { DebouncedFunc } from 'lodash';
import { createContext } from 'react';
import { ItemControlGroupItemComponentMapping, ItemControlQuestionItemComponentMapping } from 'sdc-qrf';
import { FormItems, ItemControlGroupItemComponentMapping, ItemControlQuestionItemComponentMapping } from 'sdc-qrf';

import { BaseQuestionnaireResponseFormProps } from '.';

export const ItemControlQuestionItemWidgetsContext = createContext<ItemControlQuestionItemComponentMapping>({});
export const ItemControlGroupItemWidgetsContext = createContext<ItemControlGroupItemComponentMapping>({});

interface BaseQuestionnaireResponseFormPropsContextProps extends BaseQuestionnaireResponseFormProps {
submitting: boolean;
debouncedSaveDraft?: DebouncedFunc<(currentFormValues: FormItems) => Promise<void>>;
}
export const BaseQuestionnaireResponseFormPropsContext = createContext<
BaseQuestionnaireResponseFormPropsContextProps | undefined
>(undefined);
3 changes: 3 additions & 0 deletions src/components/BaseQuestionnaireResponseForm/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
Grid,
} from './widgets';
import { Display } from './widgets/display';
import { GroupWizard, GroupWizardWithTooltips } from './widgets/GroupWizard';
import { PasswordInput } from './widgets/PasswordInput';
import { QuestionReference } from './widgets/reference';
import { ReferenceRadioButton } from './widgets/ReferenceRadioButton';
Expand Down Expand Up @@ -73,4 +74,6 @@ export const groupControlComponents: ItemControlGroupItemComponentMapping = {
grid: Grid,
'blood-pressure': BloodPressure,
'time-range-picker': TimeRangePickerControl,
wizard: GroupWizard,
'wizard-with-tooltips': GroupWizardWithTooltips,
};
Loading

0 comments on commit 597d7fb

Please sign in to comment.