diff --git a/pwa/package-lock.json b/pwa/package-lock.json
index 2202d87..d085876 100644
--- a/pwa/package-lock.json
+++ b/pwa/package-lock.json
@@ -2198,9 +2198,9 @@
},
"dependencies": {
"acorn": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
- "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw=="
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
}
}
},
@@ -7866,9 +7866,9 @@
},
"dependencies": {
"acorn": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
- "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw=="
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
},
"jsdom": {
"version": "14.1.0",
@@ -8807,9 +8807,9 @@
},
"dependencies": {
"acorn": {
- "version": "5.7.3",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
- "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
+ "version": "5.7.4",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
+ "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg=="
}
}
},
diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx
index 8ac8774..db766c4 100644
--- a/pwa/src/App.tsx
+++ b/pwa/src/App.tsx
@@ -8,6 +8,7 @@ import Login from './components/Login'
import LandingPage from './components/LandingPage'
import Wrapper from './Wrapper'
import PatientInfoForm from './components/PatientInfoForm'
+import DiagnosisForm from './components/DiagnosisForm'
import './scss/App.scss'
import './antd-mobile.css'
@@ -33,6 +34,15 @@ const App: React.FunctionComponent = () => {
+
+
+
+
+
diff --git a/pwa/src/components/DiagnosisFields.json b/pwa/src/components/DiagnosisFields.json
new file mode 100644
index 0000000..7c43993
--- /dev/null
+++ b/pwa/src/components/DiagnosisFields.json
@@ -0,0 +1,189 @@
+{
+ "diagnoses": [
+ {
+ "name": "Asthma",
+ "id": "asthma"
+ },
+ {
+ "name": "Allergies",
+ "id": "allergies"
+ },
+ {
+ "name": "Anemia",
+ "id": "anemia"
+ },
+ {
+ "name": "Malnutrition",
+ "id": "malnutrition"
+ },
+ {
+ "name": "Depression",
+ "id": "depression"
+ },
+ {
+ "name": "Diabetes",
+ "id": "diabetes"
+ },
+ {
+ "id": "eye",
+ "group-title": "Eye",
+ "group": [
+ {
+ "name": "Ptergium",
+ "id": "ptergium"
+ },
+ {
+ "name": "Cataract",
+ "id": "cataract"
+ },
+ {
+ "name": "Dry Eye",
+ "id": "dry-eye"
+ },
+ {
+ "name": "Conjuntivitis",
+ "id": "conjuntivitis"
+ }
+ ]
+ },
+ {
+ "name": "Fever",
+ "id": "fever"
+ },
+ {
+ "name": "Possible Malaria",
+ "id": "malaria"
+ },
+ {
+ "name": "Filariasis",
+ "id": "filariasis"
+ },
+ {
+ "id": "intestinal",
+ "group-title": "Intestinal",
+ "group": [
+ { "name": "Gastritis", "id": "gastritis" },
+ { "name": "GERD", "id": "gerd" },
+ { "name": "Gastroenteritis", "id": "gastroenteritis" },
+ { "name": "Dysentery", "id": "dysentery" },
+ { "name": "Possible Cholera", "id": "cholera" }
+ ]
+ },
+ {
+ "name": "Headache",
+ "id": "headache"
+ },
+ {
+ "group-title": "Hernia",
+ "id": "hernia",
+ "group": [
+ { "name": "Inguinal", "id": "inguinal" },
+ { "name": "Umbilical", "id": "umbilical" }
+ ]
+ },
+ {
+ "id": "cardiovascular",
+ "group-title": "Cardiovascular",
+ "group": [
+ { "name": "Hypertension", "id": "hypertension" },
+ { "name": "Stroke", "id": "stroke" },
+ { "name": "Angina", "id": "angina" },
+ { "name": "CHF", "id": "chf" }
+ ]
+ },
+ {
+ "name": "Healthy",
+ "id": "healthy"
+ },
+
+ {
+ "name": "Musculoskeletal Pain",
+ "id": "musculoskeletal"
+ },
+ {
+ "group-title": "Otitis",
+ "id": "otitis",
+ "group": [
+ { "name": "Right", "id": "otitis-right" },
+ { "name": "Left", "id": "otitis-left" }
+ ]
+ },
+ {
+ "name": "Pneumonia",
+ "id": "pneumonia"
+ },
+ {
+ "id": "sinusitis",
+ "name": "Sinusitis"
+ },
+ {
+ "name": "URI",
+ "id": "uri"
+ },
+ {
+ "name": "Pregnancy",
+ "id": "pregnancy",
+ "text-input-title": "Weeks",
+ "text-input-type": "number",
+ "max-length": 2,
+ "text-input-id": "pregnancy-weeks"
+ },
+ {
+ "group-title": "Dermatological",
+ "id": "dermatological",
+ "group": [
+ { "name": "Atopic Derm", "id": "atopic-derm" },
+ { "name": "Fungal", "id": "fungal" },
+ { "name": "Scabies", "id": "scabies" },
+ { "name": "Impetigo", "id": "Impetigo" },
+ { "name": "Tinea Capitus (kerion)", "id": "tinea-capitus" }
+ ]
+ },
+ {
+ "name": "Possible STD",
+ "id": "std"
+ },
+ {
+ "name": "Possible TB",
+ "id": "tb"
+ },
+ {
+ "name": "Possible Parasites",
+ "id": "parasites"
+ },
+ {
+ "name": "UTI",
+ "id": "uti"
+ },
+ {
+ "group-title": "Vaginal",
+ "id": "vaginal",
+ "group": [
+ { "name": "Vaginitis", "id": "vaginitis" },
+ { "name": "Candidal", "id": "candidal" },
+ { "name": "Trich", "id": "trich" },
+ { "name": "BV", "id": "bv" }
+ ]
+ },
+ {
+ "name": "Needs to see Dentist",
+ "id": "dentist"
+ },
+ {
+ "name": "Needs to see Eye Doctor",
+ "id": "eye-doctor"
+ },
+ {
+ "name": "Surgical candidate",
+ "id": "surgical-candidate"
+ },
+ {
+ "text-input-title": "Other Diagnosis",
+ "text-input-id": "other-diagnosis"
+ },
+ {
+ "text-input-title": "Diagnoses Comments",
+ "text-input-id": "comments"
+ }
+ ]
+}
diff --git a/pwa/src/components/DiagnosisForm.test.tsx b/pwa/src/components/DiagnosisForm.test.tsx
new file mode 100644
index 0000000..767f94a
--- /dev/null
+++ b/pwa/src/components/DiagnosisForm.test.tsx
@@ -0,0 +1,135 @@
+import React from 'react'
+import { render, fireEvent } from '@testing-library/react'
+import DiagnosisForm from './DiagnosisForm'
+import * as data from './DiagnosisFields.json'
+
+/*
+
+Diagnosis Fields are stored in DiagnosisFields.json in the format:
+
+{
+ "diagnoses" : [
+ {
+ "name": "Name",
+ "id": "id",
+ "text-input-title": "Title",
+ "text-input-type": "type" (i.e. number)
+ "group-title": "Group Title",
+ "group": [
+ { "name": "Name1", "id": "id1" },
+ { "name": "Name2", "id": "id2" }
+ ]
+ },
+ {...}
+ ]
+}
+*/
+
+const diagnosisFields = data.diagnoses
+
+test('renders the form', async () => {
+ const dom = render()
+ expect(dom.getByTestId('diagnosis-form-wrapper')).toBeTruthy()
+})
+
+test('renders each diagnoses.name data field', () => {
+ const { getByText } = render()
+
+ diagnosisFields.forEach((diagnosis) => {
+ if (diagnosis.name != null) {
+ const re = new RegExp(diagnosis.name, 'gi')
+ const field = getByText(re)
+ expect(field).toBeInTheDocument()
+ }
+ })
+})
+
+test(' each diagnoses.name has a corresponding checkbox and is able to be checked/unchecked', () => {
+ const { getByTestId } = render()
+ diagnosisFields.forEach((diagnosis) => {
+ if (diagnosis.name != null && diagnosis.id != null) {
+ const re = new RegExp(diagnosis.id, 'gi')
+ const checkboxItem = getByTestId(re)
+ expect(checkboxItem).toHaveClass('am-checkbox-item')
+
+ const checkBox = checkboxItem.getElementsByTagName('span')[0]
+ expect(checkBox).not.toHaveClass('am-checkbox-checked')
+ const checkBoxInput = checkboxItem.getElementsByClassName(
+ 'am-checkbox-input',
+ )[0]
+ fireEvent.click(checkBoxInput)
+ expect(checkBox).toHaveClass('am-checkbox-checked')
+ }
+ })
+})
+
+test('renders each diagnoses.text-input-title data field as a text entry field', () => {
+ const { getByTestId } = render()
+
+ diagnosisFields.forEach((diagnosis) => {
+ if (
+ diagnosis['text-input-title'] != null &&
+ diagnosis['text-input-title'] != null
+ ) {
+ const re = new RegExp(diagnosis['text-input-id'], 'gi')
+ const field = getByTestId(re)
+ expect(field).toBeInTheDocument()
+ expect(field).toHaveAttribute('type', 'text')
+ }
+ })
+})
+
+test('renders each diagnoses.group-title data field as a header', () => {
+ const { getByText } = render()
+ diagnosisFields.forEach((diagnosis) => {
+ if (diagnosis['group-title'] != null && diagnosis.group != null) {
+ const re = new RegExp(`\^${diagnosis['group-title']}\$`, 'gi')
+ const field = getByText(re)
+ expect(field).toBeInTheDocument()
+ expect(field).toHaveClass('am-list-header')
+ }
+ })
+})
+
+test('renders each diagnoses.group entry in the same list element', () => {
+ const { getByTestId } = render()
+ diagnosisFields.forEach((diagnosis) => {
+ if (diagnosis.group != null && diagnosis.id != null) {
+ // get the list by diagnosis.id
+ const re = new RegExp(`\^${diagnosis.id}\$`, 'gi')
+ const field = getByTestId(re)
+ expect(field).toBeInTheDocument()
+ expect(field).toHaveClass('am-list')
+
+ // For each element in the group, ensure it is contained in the list
+ diagnosis.group.forEach((groupElement) => {
+ const el = getByTestId(groupElement.id)
+ expect(field).toContainElement(el)
+ })
+ }
+ })
+})
+
+test('renders each diagnoses.[el] as a checkbox that can be checked/unchecked', () => {
+ const { getByTestId } = render()
+ diagnosisFields.forEach((diagnosis) => {
+ if (diagnosis.group != null) {
+ diagnosis.group.forEach((groupElement) => {
+ const re = new RegExp(groupElement.id, 'gi')
+ const groupCheckboxItem = getByTestId(re)
+ expect(groupCheckboxItem).toBeInTheDocument()
+ expect(groupCheckboxItem).toHaveClass('am-checkbox-item')
+
+ const checkBox = groupCheckboxItem.getElementsByTagName(
+ 'span',
+ )[0]
+ expect(checkBox).not.toHaveClass('am-checkbox-checked')
+ const checkBoxInput = groupCheckboxItem.getElementsByClassName(
+ 'am-checkbox-input',
+ )[0]
+ fireEvent.click(checkBoxInput)
+ expect(checkBox).toHaveClass('am-checkbox-checked')
+ })
+ }
+ })
+})
diff --git a/pwa/src/components/DiagnosisForm.tsx b/pwa/src/components/DiagnosisForm.tsx
new file mode 100644
index 0000000..a242d96
--- /dev/null
+++ b/pwa/src/components/DiagnosisForm.tsx
@@ -0,0 +1,117 @@
+import React, { ReactElement } from 'react'
+import { List, Checkbox, InputItem, WhiteSpace } from 'antd-mobile'
+import '../scss/DiagnosisForm.scss'
+import * as data from './DiagnosisFields.json'
+
+/*
+
+Diagnosis Fields are stored in DiagnosisFields.json in the format:
+
+{
+ "diagnoses" : [
+ {
+ "name": "Name",
+ "id": "id",
+ "text-input-title": "Title",
+ "text-input-id": "id" for `id` and `data-testid` attributes
+ "text-input-type": "type" (i.e. number)
+ "max-length": 3
+ "group-title": "Group Title",
+ "group": [
+ { "name": "Name1", "id": "id1" },
+ { "name": "Name2", "id": "id2" }
+ ]
+ },
+ {...}
+ ]
+}
+*/
+
+const CheckboxItem = Checkbox.CheckboxItem
+const diagnosisFields = data.diagnoses
+
+export default function DiagnosisForm(): ReactElement {
+ return (
+
+ {diagnosisFields.map((field) => {
+ const formElements: ReactElement[] = []
+
+ if (field.name != null) {
+ formElements.push(
+
+
+ {field.name}
+
+
,
+ )
+ }
+
+ if (
+ field['text-input-title'] != null &&
+ field['text-input-id'] != null
+ ) {
+ formElements.push(
+ field['text-input-title']}>
+
+
,
+ )
+ }
+
+ if (field.group != null) {
+ const groupElements: ReactElement[] = []
+
+ // add each group element to the internalElement array
+ field.group.forEach((ele: any) => {
+ if (ele.id != null && ele.name != null) {
+ groupElements.push(
+
+ {ele.name}
+ ,
+ )
+ }
+ })
+
+ // Render the entire list with the internal elements
+ if (field['group-title'] != null && field.id !== null) {
+ formElements.push(
+ field['group-title']}
+ data-testid={field.id}
+ >
+ {groupElements}
+
+
,
+ )
+ }
+ }
+
+ return <> {formElements} >
+ })}
+
+ )
+}
diff --git a/pwa/src/scss/DiagnosisForm.scss b/pwa/src/scss/DiagnosisForm.scss
new file mode 100644
index 0000000..3ee4ed2
--- /dev/null
+++ b/pwa/src/scss/DiagnosisForm.scss
@@ -0,0 +1,5 @@
+#diagnosis-form-wrapper {
+ .list-whitespace {
+ background-color: #f5f5f9;
+ }
+}