diff --git a/__mocks__/forms/ohri-forms/sample_fields.json b/__mocks__/forms/ohri-forms/sample_fields.json new file mode 100644 index 000000000..c97278f04 --- /dev/null +++ b/__mocks__/forms/ohri-forms/sample_fields.json @@ -0,0 +1,36 @@ +{ + "name": "Field tester", + "pages": [ + { + "label": "One", + "sections": [ + { + "label": "Sec One", + "isExpanded": "true", + "questions": [ + { + "label": "Text question", + "type": "obs", + "required": false, + "id": "id_text", + "questionInfo":"sample tooltip info for text", + "questionOptions": { + "rendering": "text", + "concept": "928def39-33c1-4ddb-8430-165db28448c8", + "conceptMappings": [], + "answers": [] + }, + "validators": [] + } + ] + } + ] + } + ], + "processor": "EncounterFormProcessor", + "encounterType": "e22e39fd-7db2-45e7-80f1-60fa0d5a4378", + "referencedForms": [], + "uuid": "0859d9ad-2ed4-48db-96eb-7b0ce0c9903e", + "description": "A form containing most fields, to be used for testing purposes", + "version": "1.0" + } \ No newline at end of file diff --git a/src/api/types.ts b/src/api/types.ts index 4317388e0..7a56fc42a 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -116,6 +116,7 @@ export interface OHRIFormField { inlineRendering?: 'single-line' | 'multiline' | 'automatic'; validators?: Array>; behaviours?: Array>; + questionInfo?: string; } export interface OHRIFormFieldProps { diff --git a/src/components/group/ohri-obs-group.component.tsx b/src/components/group/ohri-obs-group.component.tsx index 1ca5e4557..7a52ab95a 100644 --- a/src/components/group/ohri-obs-group.component.tsx +++ b/src/components/group/ohri-obs-group.component.tsx @@ -5,6 +5,7 @@ import { OHRIUnspecified } from '../inputs/unspecified/ohri-unspecified.componen import styles from './ohri-obs-group.scss'; import { useField } from 'formik'; import { getFieldControlWithFallback, isUnspecifiedSupported } from '../section/helpers'; +import { OHRITooltip } from '../inputs/tooltip/ohri-tooltip'; export interface ObsGroupProps extends OHRIFormFieldProps { deleteControl?: any; @@ -17,16 +18,16 @@ export const OHRIObsGroup: React.FC = ({ question, onChange, dele useEffect(() => { if (question.questions) { Promise.all( - question.questions.map(field => { - return getFieldControlWithFallback(field)?.then(result => ({ field, control: result })); + question.questions.map((field) => { + return getFieldControlWithFallback(field)?.then((result) => ({ field, control: result })); }), - ).then(results => { + ).then((results) => { setGroupMembersControlMap(results); }); } }, [question.questions]); const groupContent = groupMembersControlMap - .filter(groupMemberMapItem => !!groupMemberMapItem && !groupMemberMapItem.field.isHidden) + .filter((groupMemberMapItem) => !!groupMemberMapItem && !groupMemberMapItem.field.isHidden) .map((groupMemberMapItem, index) => { const { control, field } = groupMemberMapItem; if (control) { @@ -37,16 +38,18 @@ export const OHRIObsGroup: React.FC = ({ question, onChange, dele handler: formFieldHandlers[field.type], useField, }); + return (
- {isUnspecifiedSupported(field) ? ( - <> - {questionFragment} - - - ) : ( - questionFragment - )} +
+ {questionFragment} +
+ {isUnspecifiedSupported(field) && ( + + )} + {field.questionInfo && } +
+
); } diff --git a/src/components/group/ohri-obs-group.scss b/src/components/group/ohri-obs-group.scss index f0d3984f9..6f632eef4 100644 --- a/src/components/group/ohri-obs-group.scss +++ b/src/components/group/ohri-obs-group.scss @@ -16,10 +16,6 @@ max-width: 18rem; } -.obsGroupColumn input[class*="cds--date-picker__input"] { - width: 18rem !important; -} - .obsGroupColumn > div, .obsGroupColumn div[class*="cds--number"] { margin-top: 0 !important; } @@ -33,3 +29,20 @@ .obsGroupColumn > div > div > div > div { max-width: 18rem !important; } + +.parent{ + width: 360px; +} + +.tooltipWithUnspecified{ + display: flex; + justify-content: space-between; + align-items: center; +} + +.tooltip{ + display: flex; + justify-content: flex-end; + align-items: center; + margin-top: 0.5rem; +} \ No newline at end of file diff --git a/src/components/inputs/tooltip/ohri-tooltip.scss b/src/components/inputs/tooltip/ohri-tooltip.scss new file mode 100644 index 000000000..655095865 --- /dev/null +++ b/src/components/inputs/tooltip/ohri-tooltip.scss @@ -0,0 +1,6 @@ +.tooltip{ + border: none; + background-color: #f4f4f4; + z-index: 999; + margin-top: 0.25rem; +} diff --git a/src/components/inputs/tooltip/ohri-tooltip.tsx b/src/components/inputs/tooltip/ohri-tooltip.tsx new file mode 100644 index 000000000..5b33b7270 --- /dev/null +++ b/src/components/inputs/tooltip/ohri-tooltip.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Tooltip } from '@carbon/react'; +import { Information } from '@carbon/react/icons'; +import styles from './ohri-tooltip.scss'; +import { OHRIFormField } from '../../../api/types'; + +interface OHRITooltipProps { + field: OHRIFormField; +} + +export const OHRITooltip: React.FC = ({ field }) => { + return ( + + + + + + ); +}; diff --git a/src/components/section/ohri-form-section.component.tsx b/src/components/section/ohri-form-section.component.tsx index c75a94361..deeb4e99c 100644 --- a/src/components/section/ohri-form-section.component.tsx +++ b/src/components/section/ohri-form-section.component.tsx @@ -7,6 +7,8 @@ import { OHRIUnspecified } from '../inputs/unspecified/ohri-unspecified.componen import { OHRIFormField, OHRIFormFieldProps, SubmissionHandler } from '../../api/types'; import styles from './ohri-form-section.scss'; import { getFieldControlWithFallback, isUnspecifiedSupported } from './helpers'; +import { OHRITooltip } from '../inputs/tooltip/ohri-tooltip'; +import { subtle } from 'crypto'; interface FieldComponentMap { fieldComponent: React.ComponentType; @@ -19,12 +21,12 @@ const OHRIFormSection = ({ fields, onFieldChange }) => { useEffect(() => { Promise.all( - fields.map(async fieldDescriptor => { + fields.map(async (fieldDescriptor) => { const fieldComponent = await getFieldControlWithFallback(fieldDescriptor); const handler = await getRegisteredFieldSubmissionHandler(fieldDescriptor.type); return { fieldDescriptor, fieldComponent, handler }; }), - ).then(results => { + ).then((results) => { setFieldComponentMapEntries(results); }); }, [fields]); @@ -33,7 +35,7 @@ const OHRIFormSection = ({ fields, onFieldChange }) => { {}}>
{fieldComponentMapEntries - .filter(entry => entry?.fieldComponent) + .filter((entry) => entry?.fieldComponent) .map((entry, index) => { const { fieldComponent: FieldComponent, fieldDescriptor, handler } = entry; if (FieldComponent) { @@ -46,13 +48,21 @@ const OHRIFormSection = ({ fields, onFieldChange }) => { useField={useField} /> ); - return isUnspecifiedSupported(fieldDescriptor) && fieldDescriptor.questionOptions.rendering != 'group' ? ( -
+ + return ( +
{qnFragment} - +
+ {isUnspecifiedSupported(fieldDescriptor) && + fieldDescriptor.questionOptions.rendering != 'group' && ( + + )} + {fieldDescriptor.questionInfo && } +
- ) : ( -
{qnFragment}
); } })} diff --git a/src/components/section/ohri-form-section.scss b/src/components/section/ohri-form-section.scss index f95682cb6..bda3d49d7 100644 --- a/src/components/section/ohri-form-section.scss +++ b/src/components/section/ohri-form-section.scss @@ -5,6 +5,21 @@ margin-bottom: 3.063rem; } +.parent{ + width: 360px; +} + +.tooltipWithUnspecified{ + display: flex; + justify-content: space-between; +} + +.tooltip{ + display: flex; + justify-content: flex-end; + align-items: center; +} + .sectionTitle { max-width: 200px; font-size: 1rem; diff --git a/src/ohri-form.component.test.tsx b/src/ohri-form.component.test.tsx index fb8227c3e..b50dd62a9 100644 --- a/src/ohri-form.component.test.tsx +++ b/src/ohri-form.component.test.tsx @@ -10,6 +10,7 @@ import { findAllByRole, getAllByRole, queryAllByRole, + findByTestId, } from '@testing-library/react'; import { when } from 'jest-when'; import * as api from '../src/api/api'; @@ -33,6 +34,7 @@ import { mockSessionDataResponse } from '../__mocks__/session.mock'; import demoHtsOpenmrsForm from '../__mocks__/forms/omrs-forms/demo_hts-form.json'; import demoHtsOhriForm from '../__mocks__/forms/ohri-forms/demo_hts-form.json'; import obsGroup_test_form from '../__mocks__/forms/ohri-forms/obs-group-test_form.json'; +import sample_fields_form from '../__mocks__/forms/ohri-forms/sample_fields.json'; import { assertFormHasAllFields, @@ -148,6 +150,27 @@ describe('OHRI Forms:', () => { } }); // Form submission + + describe('Question Info', () => { + fit('Should ascertain that each field with questionInfo passed will display a tooltip', async () => { + //render the test form + await act(async () => renderForm(null, sample_fields_form)); + + //check for text field + const textField = await findTextOrDateInput(screen, 'Text question'); + expect(textField).toBeInTheDocument(); + + // check for tooltip icon on text field + const textFIeldTooltip = await screen.findByTestId('id_text'); + expect(textFIeldTooltip).toBeInTheDocument(); + + //testing for the tooltip + fireEvent.mouseOver(textFIeldTooltip); + const textFieldTooltipMessage = await screen.findByText(/sample tooltip info for text/i); + expect(textFieldTooltipMessage).toBeInTheDocument(); + }); + }); + describe('Form submission', () => { it('Should validate form submission', async () => { // Mock the form submission function to simulate success