From 547c6286a7d51fcfb5b31b7b07b882949ac0d040 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 27 Mar 2020 10:20:56 -0500 Subject: [PATCH 01/29] template for react component --- pwa/src/components/PatientInfoForm.tsx | 63 ++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 pwa/src/components/PatientInfoForm.tsx diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx new file mode 100644 index 0000000..7e10e71 --- /dev/null +++ b/pwa/src/components/PatientInfoForm.tsx @@ -0,0 +1,63 @@ +import React, { ReactElement, useState } from 'react' +import {DatePicker, InputItem, List, TextareaItem, Button} from 'antd-mobile' +import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; +import '../scss/Login.scss' + +const nowTimeStamp = Date.now(); +const now = new Date(nowTimeStamp); + +export default function Form(): ReactElement { + // useState returns a value, and a function to set that value + const [name, setName] = useState() + + const onSubmit = () => { + const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement + console.log("First name:", firstNameField.value) + } + + return ( + <> + + + + + + + + Birth Date + + + + + + + + + ) +} From 38cfe4a650f7e8d68f0b6101aa87419b28c38727 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 27 Mar 2020 13:25:49 -0500 Subject: [PATCH 02/29] added logging & several new fields --- pwa/src/components/PatientInfoForm.tsx | 43 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 7e10e71..5148559 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,21 +1,29 @@ -import React, { ReactElement, useState } from 'react' +import React, { ReactElement } from 'react' import {DatePicker, InputItem, List, TextareaItem, Button} from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' +import { render } from '@testing-library/react'; -const nowTimeStamp = Date.now(); -const now = new Date(nowTimeStamp); +// const nowTimeStamp = Date.now(); +// const now = new Date(nowTimeStamp); export default function Form(): ReactElement { - // useState returns a value, and a function to set that value - const [name, setName] = useState() + // // useState returns a value, and a function to set that value + // const [name, setName] = useState() const onSubmit = () => { const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement + const lastNameField: HTMLInputElement = document.getElementById('lastname') as HTMLInputElement + const nicknameField: HTMLInputElement = document.getElementById('nickname') as HTMLInputElement + const weightField: HTMLInputElement = document.getElementById('weight') as HTMLInputElement console.log("First name:", firstNameField.value) + console.log("Last name:", lastNameField.value) + console.log("Nickname:", nicknameField.value) + console.log("Weight:", weightField.value) } return ( + <> @@ -36,6 +46,7 @@ export default function Form(): ReactElement { title="Nickname" placeholder="optional" data-seed="nickname" + id="nickname" autoHeight /> @@ -44,17 +55,35 @@ export default function Form(): ReactElement { locale={enUs} title="Birth Date" extra="Birth Date" + data-seed="birthDate" > Birth Date + {/* TODO: figure out how to access this value */} + id = 'weight' + >Weight (kg) + {/* TODO: figure out how to access this value */} + + 'Chief Complaint'}> + + + From 3836077047d314f6bc4d2953d2ea7ac8fe2d6424 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 27 Mar 2020 13:44:45 -0500 Subject: [PATCH 03/29] added pulse, temp, height --- pwa/src/components/PatientInfoForm.tsx | 41 ++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 5148559..5e5b16c 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -12,14 +12,18 @@ export default function Form(): ReactElement { // const [name, setName] = useState() const onSubmit = () => { + // This shows how to access the values of the form const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement const lastNameField: HTMLInputElement = document.getElementById('lastname') as HTMLInputElement const nicknameField: HTMLInputElement = document.getElementById('nickname') as HTMLInputElement - const weightField: HTMLInputElement = document.getElementById('weight') as HTMLInputElement + const complaintField1: HTMLInputElement = document.getElementById('complaint1') as HTMLInputElement + const complaintField2: HTMLInputElement = document.getElementById('complaint2') as HTMLInputElement + const complaintField3: HTMLInputElement = document.getElementById('complaint3') as HTMLInputElement + console.log("First name:", firstNameField.value) console.log("Last name:", lastNameField.value) console.log("Nickname:", nicknameField.value) - console.log("Weight:", weightField.value) + console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) } return ( @@ -60,6 +64,13 @@ export default function Form(): ReactElement { Birth Date {/* TODO: figure out how to access this value */} + Age + {/* these don't technically need to be in their own */} Weight (kg) - {/* TODO: figure out how to access this value */} + + Height (cm) + + Temp (F) + + Pulse + {/* TODO: figure out how to access these values from the money keyboard */} 'Chief Complaint'}> From 4de822f2ddfd1e91398c5721c1e9f14964200925 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Sun, 29 Mar 2020 18:18:14 -0500 Subject: [PATCH 04/29] added more fields --- pwa/src/components/PatientInfoForm.tsx | 196 ++++++++++++++----------- 1 file changed, 114 insertions(+), 82 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 5e5b16c..86ab463 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -27,99 +27,131 @@ export default function Form(): ReactElement { } return ( - - <> - + <> + - + - + - - Birth Date - {/* TODO: figure out how to access this value */} - - Age - {/* these don't technically need to be in their own */} + + Birth Date + {/* TODO: figure out how to access this value */} + + Age - - Weight (kg) + Phone - Height (cm) - - Temp (F) - - Pulse - {/* TODO: figure out how to access these values from the money keyboard */} - - 'Chief Complaint'}> + {/* TODO: only display this section for patients marked as Female */} + - + + + + + {/* these don't technically need to be in their own */} + + + Weight (kg) + + Height (cm) + + Temp (F) + + Pulse + {/* TODO: figure out how to access these values from the money keyboard */} + + 'Chief Complaint'}> + + + + From 8eb3759c3d90e0deae1a0b6e79f0988b8db27dd1 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Wed, 8 Apr 2020 12:33:53 -0500 Subject: [PATCH 05/29] not compiling; error with typing --- pwa/src/components/PatientInfoForm.tsx | 259 +++++++++++++------------ 1 file changed, 135 insertions(+), 124 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 86ab463..9263880 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,15 +1,15 @@ -import React, { ReactElement } from 'react' -import {DatePicker, InputItem, List, TextareaItem, Button} from 'antd-mobile' +import React, { ReactElement, useState, useEffect } from 'react' +import {DatePicker, InputItem, List, TextareaItem, Button, Radio} from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' -import { render } from '@testing-library/react'; +// import { render } from '@testing-library/react'; +const RadioItem = Radio.RadioItem; -// const nowTimeStamp = Date.now(); -// const now = new Date(nowTimeStamp); export default function Form(): ReactElement { - // // useState returns a value, and a function to set that value - // const [name, setName] = useState() + // useState returns a value, and a function to set that value + const [name, setName] = useState() + const [planning, setPlanning] = useState(0) const onSubmit = () => { // This shows how to access the values of the form @@ -26,134 +26,145 @@ export default function Form(): ReactElement { console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) } + const wantsPlanning = [ + { value: 0, label: 'Yes' }, + { value: 1, label: 'No' }, + ]; + + const onChange = (value :any) => { //todo change type here + console.log('checkbox'); + }; + return ( - <> - +
+ - + - + - - Birth Date - {/* TODO: figure out how to access this value */} - - Age + + Birth Date + {/* TODO: figure out how to access this value */} + + Age - Phone + Phone - {/* TODO: only display this section for patients marked as Female */} - - - - - - - + {/* TODO: only display this section for patients marked as Female */} +
+ + + + + 'Wants Planning?'}> + {wantsPlanning.map(i => ( + onChange(i.value)}> + {i.label} + + ))} + +
- {/* these don't technically need to be in their own */} + {/* these don't technically need to be in their own */} - - Weight (kg) + + Weight (kg) - Height (cm) + Height (cm) - Temp (F) + Temp (F) - Pulse - {/* TODO: figure out how to access these values from the money keyboard */} - - 'Chief Complaint'}> - - - - - + Pulse + {/* TODO: figure out how to access these values from the money keyboard */} + + 'Chief Complaint'}> + + + + + - +
) } From 3c0f9c79376ba815832427919d93c1ceba27c6fc Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Wed, 8 Apr 2020 20:51:11 -0500 Subject: [PATCH 06/29] radio buttons working --- pwa/src/components/PatientInfoForm.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 9263880..0f93331 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -8,7 +8,7 @@ const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { // useState returns a value, and a function to set that value - const [name, setName] = useState() + // const [name, setName] = useState() const [planning, setPlanning] = useState(0) const onSubmit = () => { @@ -31,8 +31,9 @@ export default function Form(): ReactElement { { value: 1, label: 'No' }, ]; - const onChange = (value :any) => { //todo change type here + const onChange = (value :number) => { //todo change type here console.log('checkbox'); + setPlanning(value) }; return ( @@ -106,7 +107,7 @@ export default function Form(): ReactElement { /> 'Wants Planning?'}> {wantsPlanning.map(i => ( - onChange(i.value)}> + onChange(i.value)}> {i.label} ))} From b5b8179cff59f0e2ddd879c5b672c3fc4365ccaf Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Wed, 8 Apr 2020 22:12:52 -0500 Subject: [PATCH 07/29] added more fields & toggle female only form fields --- pwa/src/components/PatientInfoForm.tsx | 148 +++++++++++++++++-------- 1 file changed, 103 insertions(+), 45 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 0f93331..4b571a4 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,15 +1,19 @@ -import React, { ReactElement, useState, useEffect } from 'react' +import React, { ReactElement, useState } from 'react' import {DatePicker, InputItem, List, TextareaItem, Button, Radio} from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' -// import { render } from '@testing-library/react'; const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { // useState returns a value, and a function to set that value - // const [name, setName] = useState() - const [planning, setPlanning] = useState(0) + const [displayFemaleOptions, setDisplayFemaleOptions] = useState(0) + const [sex, setSex] = useState() // Default: null + const [albendazole, setAlbendazole] = useState(0) // Default: No + const [visit, setVisit] = useState(0) // Default: No + const [pregnant, setPregnant] = useState(0) // Default: No + const [planning, setPlanning] = useState(0) // Default: No + const onSubmit = () => { // This shows how to access the values of the form @@ -24,17 +28,34 @@ export default function Form(): ReactElement { console.log("Last name:", lastNameField.value) console.log("Nickname:", nicknameField.value) console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) + console.log("Wants Planning?: " + planning) } - const wantsPlanning = [ - { value: 0, label: 'Yes' }, - { value: 1, label: 'No' }, + // Data for Radio Buttons + const sexValues = [ + {value: 0, label: 'Male'}, + {value: 1, label: 'Female'} + ] + + const radioYesNo = [ + { value: 0, label: 'No' }, + { value: 1, label: 'Yes' }, ]; - const onChange = (value :number) => { //todo change type here - console.log('checkbox'); - setPlanning(value) - }; + // const onChangePlanning = (value :number) => { //todo change type here + // setPlanning(value) + // }; + + // const changeSex = (value :number) => { + // setSex(value) + // if (value) { + // // Male = 0 - do not display female-only div + // setDisplayFemaleOptions(0) + // } else { + // setDisplayFemaleOptions + + // } + // } return (
@@ -63,16 +84,25 @@ export default function Form(): ReactElement { autoHeight /> + 'Sex'}> + {sexValues.map(i => ( + setSex(i.value)}> + {i.label} + + ))} + + - Birth Date - {/* TODO: figure out how to access this value */} + Birth Date + {/* TODO: figure out how to access this value */} + Phone - {/* TODO: only display this section for patients marked as Female */} -
- - - - - 'Wants Planning?'}> - {wantsPlanning.map(i => ( - onChange(i.value)}> - {i.label} - - ))} - -
+ 'Visit?'}> + {radioYesNo.map(i => ( + setVisit(i.value)}> + {i.label} + + ))} + - {/* these don't technically need to be in their own */} + {/* Only display the following div if the patient is female */} + {sex ? +
+ 'Pregnant?'}> + {radioYesNo.map(i => ( + setPregnant(i.value)}> + {i.label} + + ))} + + + + + + + 'Wants Planning?'}> + {radioYesNo.map(i => ( + setPlanning(i.value)}> + {i.label} + + ))} + +
+ : null + } + + {/* TODO these don't technically need to be in their own */} Pulse {/* TODO: figure out how to access these values from the money keyboard */} + + 'Albendazole?'}> + {radioYesNo.map(i => ( + setAlbendazole(i.value)}> + {i.label} + + ))} + + 'Chief Complaint'}> Date: Thu, 9 Apr 2020 22:36:33 -0500 Subject: [PATCH 08/29] almost all fields added --- pwa/src/components/PatientInfoForm.tsx | 97 +++++++++++++++++--------- 1 file changed, 64 insertions(+), 33 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 4b571a4..1fd94c1 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -7,7 +7,6 @@ const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { // useState returns a value, and a function to set that value - const [displayFemaleOptions, setDisplayFemaleOptions] = useState(0) const [sex, setSex] = useState() // Default: null const [albendazole, setAlbendazole] = useState(0) // Default: No const [visit, setVisit] = useState(0) // Default: No @@ -42,20 +41,7 @@ export default function Form(): ReactElement { { value: 1, label: 'Yes' }, ]; - // const onChangePlanning = (value :number) => { //todo change type here - // setPlanning(value) - // }; - - // const changeSex = (value :number) => { - // setSex(value) - // if (value) { - // // Male = 0 - do not display female-only div - // setDisplayFemaleOptions(0) - // } else { - // setDisplayFemaleOptions - - // } - // } + // TODO - get rid of the "money" input type return (
@@ -78,7 +64,7 @@ export default function Form(): ReactElement { Phone + + 'Visit?'}> {radioYesNo.map(i => ( setVisit(i.value)}> @@ -167,32 +161,39 @@ export default function Form(): ReactElement { Weight (kg) Height (cm) Temp (F) Pulse + + Z-Score {/* TODO: figure out how to access these values from the money keyboard */} @@ -204,6 +205,21 @@ export default function Form(): ReactElement { ))} + 'Alergies'}> + + + {/* TODO: this would be nice as a dynamic entry */} + + 'Medicines'}> + + + 'Chief Complaint'}> - + + 'History'}> + + + + 'Exam'}> + + + +
) From ec54426706e98acc9df032dd0481c5a639a60b36 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Thu, 9 Apr 2020 22:38:14 -0500 Subject: [PATCH 09/29] updated formatting --- pwa/src/components/PatientInfoForm.tsx | 418 ++++++++++++------------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 1fd94c1..be4bf60 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,260 +1,260 @@ import React, { ReactElement, useState } from 'react' -import {DatePicker, InputItem, List, TextareaItem, Button, Radio} from 'antd-mobile' +import { DatePicker, InputItem, List, TextareaItem, Button, Radio } from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { - // useState returns a value, and a function to set that value - const [sex, setSex] = useState() // Default: null - const [albendazole, setAlbendazole] = useState(0) // Default: No - const [visit, setVisit] = useState(0) // Default: No - const [pregnant, setPregnant] = useState(0) // Default: No - const [planning, setPlanning] = useState(0) // Default: No + // useState returns a value, and a function to set that value + const [sex, setSex] = useState() // Default: null + const [albendazole, setAlbendazole] = useState(0) // Default: No + const [visit, setVisit] = useState(0) // Default: No + const [pregnant, setPregnant] = useState(0) // Default: No + const [planning, setPlanning] = useState(0) // Default: No - const onSubmit = () => { - // This shows how to access the values of the form - const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement - const lastNameField: HTMLInputElement = document.getElementById('lastname') as HTMLInputElement - const nicknameField: HTMLInputElement = document.getElementById('nickname') as HTMLInputElement - const complaintField1: HTMLInputElement = document.getElementById('complaint1') as HTMLInputElement - const complaintField2: HTMLInputElement = document.getElementById('complaint2') as HTMLInputElement - const complaintField3: HTMLInputElement = document.getElementById('complaint3') as HTMLInputElement + const onSubmit = () => { + // This shows how to access the values of the form + const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement + const lastNameField: HTMLInputElement = document.getElementById('lastname') as HTMLInputElement + const nicknameField: HTMLInputElement = document.getElementById('nickname') as HTMLInputElement + const complaintField1: HTMLInputElement = document.getElementById('complaint1') as HTMLInputElement + const complaintField2: HTMLInputElement = document.getElementById('complaint2') as HTMLInputElement + const complaintField3: HTMLInputElement = document.getElementById('complaint3') as HTMLInputElement - console.log("First name:", firstNameField.value) - console.log("Last name:", lastNameField.value) - console.log("Nickname:", nicknameField.value) - console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) - console.log("Wants Planning?: " + planning) - } + console.log("First name:", firstNameField.value) + console.log("Last name:", lastNameField.value) + console.log("Nickname:", nicknameField.value) + console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) + console.log("Wants Planning?: " + planning) + } - // Data for Radio Buttons - const sexValues = [ - {value: 0, label: 'Male'}, - {value: 1, label: 'Female'} - ] + // Data for Radio Buttons + const sexValues = [ + { value: 0, label: 'Male' }, + { value: 1, label: 'Female' } + ] - const radioYesNo = [ - { value: 0, label: 'No' }, - { value: 1, label: 'Yes' }, - ]; + const radioYesNo = [ + { value: 0, label: 'No' }, + { value: 1, label: 'Yes' }, + ]; - // TODO - get rid of the "money" input type + // TODO - get rid of the "money" input type - return ( -
- + + /> - + /> - + /> - 'Sex'}> - {sexValues.map(i => ( - setSex(i.value)}> - {i.label} - + 'Sex'}> + {sexValues.map(i => ( + setSex(i.value)}> + {i.label} + + ))} + + + + Birth Date + {/* TODO: figure out how to access this value */} + + + Age + + Phone + + + + 'Visit?'}> + {radioYesNo.map(i => ( + setVisit(i.value)}> + {i.label} + + ))} + + + {/* Only display the following div if the patient is female */} + {sex ? +
+ 'Pregnant?'}> + {radioYesNo.map(i => ( + setPregnant(i.value)}> + {i.label} + ))} - + - - Birth Date - {/* TODO: figure out how to access this value */} - + + + + + 'Wants Planning?'}> + {radioYesNo.map(i => ( + setPlanning(i.value)}> + {i.label} + + ))} + +
+ : null + } + + {/* TODO these don't technically need to be in their own */} + + + Weight (kg) Age + type="money" + moneyKeyboardAlign="left" + clear + id='height' + >Height (cm) Phone + type="money" + moneyKeyboardAlign="left" + clear + id='temp' + >Temp (F) + Pulse + + Z-Score + {/* TODO: figure out how to access these values from the money keyboard */} + + + 'Albendazole?'}> + {radioYesNo.map(i => ( + setAlbendazole(i.value)}> + {i.label} + + ))} + + + 'Alergies'}> + + {/* TODO: this would be nice as a dynamic entry */} - 'Visit?'}> - {radioYesNo.map(i => ( - setVisit(i.value)}> - {i.label} - - ))} - + 'Medicines'}> + + - {/* Only display the following div if the patient is female */} - {sex ? -
- 'Pregnant?'}> - {radioYesNo.map(i => ( - setPregnant(i.value)}> - {i.label} - - ))} - + 'Chief Complaint'}> + + + + - - - - - 'Wants Planning?'}> - {radioYesNo.map(i => ( - setPlanning(i.value)}> - {i.label} - - ))} - -
- : null - } + 'History'}> + + - {/* TODO these don't technically need to be in their own */} + 'Exam'}> + + - - Weight (kg) - - Height (cm) - - Temp (F) - - Pulse - - Z-Score - {/* TODO: figure out how to access these values from the money keyboard */} - - - 'Albendazole?'}> - {radioYesNo.map(i => ( - setAlbendazole(i.value)}> - {i.label} - - ))} - - - 'Alergies'}> - - - {/* TODO: this would be nice as a dynamic entry */} - - 'Medicines'}> - - - - 'Chief Complaint'}> - - - - - - 'History'}> - - - - 'Exam'}> - - - - +
- ) + ) } From d0c6abe69086e7e0ac0d0a11ea2ab4b003b09977 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 10 Apr 2020 12:16:38 -0500 Subject: [PATCH 10/29] changed money input to number input; removed redundant Lists --- pwa/src/components/PatientInfoForm.tsx | 49 +++++++++++--------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index be4bf60..b7db88e 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -2,6 +2,7 @@ import React, { ReactElement, useState } from 'react' import { DatePicker, InputItem, List, TextareaItem, Button, Radio } from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' + const RadioItem = Radio.RadioItem; @@ -41,8 +42,6 @@ export default function Form(): ReactElement { { value: 1, label: 'Yes' }, ]; - // TODO - get rid of the "money" input type - return (
Age Phone @@ -119,7 +115,7 @@ export default function Form(): ReactElement { ))} - {/* Only display the following div if the patient is female */} + {/* Only display the female-only div if the patient is female */} {sex ?
'Pregnant?'}> @@ -130,16 +126,19 @@ export default function Form(): ReactElement { ))} - - - */} - Weight (kg) Height (cm) BP + + Temp (F) Pulse Z-Score - {/* TODO: figure out how to access these values from the money keyboard */} - 'Albendazole?'}> {radioYesNo.map(i => ( From 33cd324da68ba10916d50deaed96740ed72f0496 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 10 Apr 2020 12:17:12 -0500 Subject: [PATCH 11/29] changed money input to number input; removed redundant Lists --- pwa/src/components/PatientInfoForm.tsx | 50 +++++++++++++------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index b7db88e..2c54d17 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -156,37 +156,35 @@ export default function Form(): ReactElement { : null } - {/* TODO these don't technically need to be in their own */} + Weight (kg) - Weight (kg) + Height (cm) - Height (cm) + BP - BP + Temp (F) - Temp (F) + Pulse - Pulse - - Z-Score + Z-Score 'Albendazole?'}> {radioYesNo.map(i => ( From 25d7b83fcedede3bd31158db7e1c48f02ef3e92e Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 10 Apr 2020 12:19:21 -0500 Subject: [PATCH 12/29] removed data-seed attributes --- pwa/src/components/PatientInfoForm.tsx | 37 +++++++++++--------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 2c54d17..ca5e95f 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -7,13 +7,24 @@ const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { + // State Hooks for Radio Buttons // useState returns a value, and a function to set that value - const [sex, setSex] = useState() // Default: null - const [albendazole, setAlbendazole] = useState(0) // Default: No - const [visit, setVisit] = useState(0) // Default: No - const [pregnant, setPregnant] = useState(0) // Default: No - const [planning, setPlanning] = useState(0) // Default: No + const [sex, setSex] = useState() // Default: null + const [albendazole, setAlbendazole] = useState(0) // Default: No + const [visit, setVisit] = useState(0) // Default: No + const [pregnant, setPregnant] = useState(0) // Default: No + const [planning, setPlanning] = useState(0) // Default: No + // Data for Radio Buttons + const sexValues = [ + { value: 0, label: 'Male' }, + { value: 1, label: 'Female' } + ] + + const radioYesNo = [ + { value: 0, label: 'No' }, + { value: 1, label: 'Yes' }, + ]; const onSubmit = () => { // This shows how to access the values of the form @@ -31,23 +42,11 @@ export default function Form(): ReactElement { console.log("Wants Planning?: " + planning) } - // Data for Radio Buttons - const sexValues = [ - { value: 0, label: 'Male' }, - { value: 1, label: 'Female' } - ] - - const radioYesNo = [ - { value: 0, label: 'No' }, - { value: 1, label: 'Yes' }, - ]; - return (
@@ -55,16 +54,13 @@ export default function Form(): ReactElement { @@ -102,7 +98,6 @@ export default function Form(): ReactElement { From 5956e268f2f2be88865b8958bdf64402b5fa1aa4 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Fri, 10 Apr 2020 12:27:52 -0500 Subject: [PATCH 13/29] formatting --- pwa/src/components/PatientInfoForm.tsx | 39 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index ca5e95f..ebaf079 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,5 +1,5 @@ import React, { ReactElement, useState } from 'react' -import { DatePicker, InputItem, List, TextareaItem, Button, Radio } from 'antd-mobile' +import { DatePicker, InputItem, List, TextareaItem, Button, Radio, WhiteSpace} from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' @@ -73,6 +73,8 @@ export default function Form(): ReactElement { ))} + + Age Phone @@ -110,9 +113,10 @@ export default function Form(): ReactElement { ))} - {/* Only display the female-only div if the patient is female */} + {/* Only display the 'female-only' div if the patient is female */} {sex ?
+ 'Pregnant?'}> {radioYesNo.map(i => ( setPregnant(i.value)}> @@ -125,21 +129,25 @@ export default function Form(): ReactElement { title="G" type="number" id='gravida' - /> + >G + + >P + + >A + + 'Wants Planning?'}> {radioYesNo.map(i => ( setPlanning(i.value)}> @@ -151,33 +159,41 @@ export default function Form(): ReactElement { : null } + + Weight (kg) Height (cm) BP Temp (F) Pulse Z-Score @@ -195,7 +211,6 @@ export default function Form(): ReactElement { id='alergies' /> - {/* TODO: this would be nice as a dynamic entry */} 'Medicines'}> @@ -237,6 +252,8 @@ export default function Form(): ReactElement { /> + +
From 5adacc2f70bf59e85f0f481828ae4b870c050f62 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Sun, 12 Apr 2020 20:29:45 -0500 Subject: [PATCH 14/29] start of unit tests for PatientInfoForm --- pwa/src/components/PatientInfoForm.test.tsx | 58 +++++++++++++++++++++ pwa/src/components/PatientInfoForm.tsx | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pwa/src/components/PatientInfoForm.test.tsx diff --git a/pwa/src/components/PatientInfoForm.test.tsx b/pwa/src/components/PatientInfoForm.test.tsx new file mode 100644 index 0000000..743742f --- /dev/null +++ b/pwa/src/components/PatientInfoForm.test.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { render, fireEvent, screen } from "@testing-library/react"; +import PatientInfoForm from "./PatientInfoForm"; + +test("female-only div is only displayed if the sex is selected as female", () => { + const femaleOnlyFormFields = [ + "pregnant", + "LMP", + "wants planning" + ] + + render(); + + // ensure the female-only div is not displayed + femaleOnlyFormFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(screen.queryByText(re)).toBeNull(); + }) + + // click the radio button for 'female' + fireEvent.click(screen.getByText(/female/i)) + + // ensure the female-only div is displayed + femaleOnlyFormFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(screen.getByText(re)).toBeInTheDocument(); + }) +}) + + +test("renders the Patient Info Form fields", () => { + const formFields = [ + "First Name", + "Last Name", + "Nickname", + "Town", + "Sex", + "Birth", + "Age", + "Phone", + "Temp", + "Pulse", + "Weight", + "Height", + "Albendazole", + "Alergies", + "Medicines", + "Exam" + ]; + + const { getByText } = render(); + + + formFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(getByText(re)).toBeInTheDocument(); + }) +}) \ No newline at end of file diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index ebaf079..045aaa6 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -9,7 +9,7 @@ const RadioItem = Radio.RadioItem; export default function Form(): ReactElement { // State Hooks for Radio Buttons // useState returns a value, and a function to set that value - const [sex, setSex] = useState() // Default: null + const [sex, setSex] = useState(null as Number) // Default: null const [albendazole, setAlbendazole] = useState(0) // Default: No const [visit, setVisit] = useState(0) // Default: No const [pregnant, setPregnant] = useState(0) // Default: No From 0e44ac694e6890432d2572a20b3956cb48c350e1 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Sun, 12 Apr 2020 23:47:06 -0500 Subject: [PATCH 15/29] React Router Init --- pwa/package-lock.json | 126 ++++++++++++++++++++++++++++++++++++++++ pwa/package.json | 2 + pwa/src/App.tsx | 23 ++++++-- pwa/src/Wrapper.tsx | 11 ++++ pwa/src/scss/Login.scss | 44 ++++++++------ 5 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 pwa/src/Wrapper.tsx diff --git a/pwa/package-lock.json b/pwa/package-lock.json index caea114..9c88623 100644 --- a/pwa/package-lock.json +++ b/pwa/package-lock.json @@ -1678,6 +1678,11 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.5.tgz", + "integrity": "sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", @@ -1755,6 +1760,25 @@ "@types/react": "*" } }, + "@types/react-router": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.5.tgz", + "integrity": "sha512-RZPdCtZympi6X7EkGyaU7ISiAujDYTWgqMF9owE3P6efITw27IWQykcti0BvA5h4Mu1LLl5rxrpO3r8kHyUZ/Q==", + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.4.tgz", + "integrity": "sha512-LO0z5qqSfWdYtCNsRm8/OMnnkv52hwADJKrAfpKIyfHclORllcgAMGypEA7ajHm38+jOonKLx8nPygNAAZGxtg==", + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/react-test-renderer": { "version": "16.9.2", "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz", @@ -6636,6 +6660,11 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -6771,6 +6800,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -6781,6 +6823,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", @@ -9586,6 +9636,16 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz", "integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=" }, + "mini-create-react-context": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz", + "integrity": "sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw==", + "requires": { + "@babel/runtime": "^7.4.0", + "gud": "^1.0.0", + "tiny-warning": "^1.0.2" + } + }, "mini-css-extract-plugin": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", @@ -12269,6 +12329,52 @@ "react-tween-state": "^0.1.5" } }, + "react-router": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz", + "integrity": "sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.3.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.1.2.tgz", + "integrity": "sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.1.2", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.3.1.tgz", @@ -12980,6 +13086,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -14891,6 +15002,16 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tinycolor2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", @@ -15364,6 +15485,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/pwa/package.json b/pwa/package.json index 2e874b8..9abda9f 100644 --- a/pwa/package.json +++ b/pwa/package.json @@ -11,10 +11,12 @@ "@types/node": "^12.12.26", "@types/react": "^16.9.19", "@types/react-dom": "^16.9.5", + "@types/react-router-dom": "^5.1.4", "antd-mobile": "^2.3.1", "node-sass": "^4.13.1", "react": "^16.12.0", "react-dom": "^16.12.0", + "react-router-dom": "^5.1.2", "react-scripts": "3.3.1", "typescript": "^3.7.5" }, diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 4006c0f..0c9bdad 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -1,14 +1,27 @@ import React from "react"; +import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; + +import Login from "./components/Login"; +import LandingPage from "./components/LandingPage"; + import "./scss/App.scss"; import "./antd-mobile.css"; -import Login from "./components/Login"; - const App = () => { return ( - <> - - + + + + + + + + + + + + + ); }; diff --git a/pwa/src/Wrapper.tsx b/pwa/src/Wrapper.tsx new file mode 100644 index 0000000..f1a791f --- /dev/null +++ b/pwa/src/Wrapper.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +type props = { + children: React.ReactNode; +}; + +const Wrapper = (props: props) => { + return
{props.children}
; +}; + +export default Wrapper; diff --git a/pwa/src/scss/Login.scss b/pwa/src/scss/Login.scss index ea78e88..f2dd399 100644 --- a/pwa/src/scss/Login.scss +++ b/pwa/src/scss/Login.scss @@ -21,7 +21,7 @@ #imgWrap { width: 28%; margin: auto; - padding: .2rem; + padding: 0.2rem; background-color: #eee; border-radius: 5px; img { @@ -37,13 +37,13 @@ animation-name: fade-in; animation-duration: 2s; } - #buttonFlex{ + #buttonFlex { animation-name: fade-in; animation-duration: 2s; display: flex; justify-content: center; .am-button { - background-color: #9BD7FF; + background-color: #9bd7ff; width: 40%; &.am-button-active { background-color: #ccebff; @@ -51,21 +51,29 @@ } } } -} + $animationDelay: 1; + @for $i from 1 through 15 { + .loginGrid :nth-child(#{$i}) { + animation-delay: #{0.3+ ($i)/30}s; + } + } -$animationDelay: 1; -@for $i from 1 through 15 { - .loginGrid :nth-child(#{$i}) { - animation-delay: #{0.3+($i)/30}s; + @keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + + @keyframes fade-in-from-up { + 0% { + opacity: 0; + transform: translateY(-100px); + } + 100% { + opacity: 1; + } } } - -@keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@keyframes fade-in-from-up { - 0% { opacity: 0; transform: translateY(-100px)} - 100% { opacity: 1; } -} \ No newline at end of file From 676efa6f1d3f4928fa16614c9636c2b953a403a1 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 20:28:44 -0500 Subject: [PATCH 16/29] remove animation --- pwa/src/scss/LandingPage.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/pwa/src/scss/LandingPage.scss b/pwa/src/scss/LandingPage.scss index 905257e..73ed522 100644 --- a/pwa/src/scss/LandingPage.scss +++ b/pwa/src/scss/LandingPage.scss @@ -1,6 +1,4 @@ .button-flex { - animation-name: fade-in; - animation-duration: 2s; display: flex; justify-content: center; margin: 2em 0; From f8d2729ae424f383bb21c092e8fbdc99ad29b760 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 20:54:29 -0500 Subject: [PATCH 17/29] PatientInfoPlaceholder --- pwa/src/App.tsx | 7 +++++++ pwa/src/Wrapper.tsx | 8 +++++++- pwa/src/components/PatientInfoPlaceholder.tsx | 11 +++++++++++ pwa/src/scss/Wrapper.scss | 10 ++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 pwa/src/components/PatientInfoPlaceholder.tsx create mode 100644 pwa/src/scss/Wrapper.scss diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 0c9bdad..62c9e19 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -3,6 +3,8 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import Login from "./components/Login"; import LandingPage from "./components/LandingPage"; +import PatientInfoPlaceholder from "./components/PatientInfoPlaceholder"; +import Wrapper from "./Wrapper"; import "./scss/App.scss"; import "./antd-mobile.css"; @@ -17,6 +19,11 @@ const App = () => { + + + + + diff --git a/pwa/src/Wrapper.tsx b/pwa/src/Wrapper.tsx index f1a791f..5e678fb 100644 --- a/pwa/src/Wrapper.tsx +++ b/pwa/src/Wrapper.tsx @@ -1,11 +1,17 @@ import React from "react"; +import "./scss/Wrapper.scss"; + type props = { children: React.ReactNode; }; const Wrapper = (props: props) => { - return
{props.children}
; + return ( +
+
{props.children}
+
+ ); }; export default Wrapper; diff --git a/pwa/src/components/PatientInfoPlaceholder.tsx b/pwa/src/components/PatientInfoPlaceholder.tsx new file mode 100644 index 0000000..e92d505 --- /dev/null +++ b/pwa/src/components/PatientInfoPlaceholder.tsx @@ -0,0 +1,11 @@ +import React, { ReactElement } from "react"; + +export default function PatientInfoPlaceholder(): ReactElement { + return ( + placeholder + ); +} diff --git a/pwa/src/scss/Wrapper.scss b/pwa/src/scss/Wrapper.scss new file mode 100644 index 0000000..82f8333 --- /dev/null +++ b/pwa/src/scss/Wrapper.scss @@ -0,0 +1,10 @@ +#primary-wrapper { + width: 100%; + height: 100%; + display: flex; + justify-content: space-around; + #wrapper-contents { + max-width: 50em; + height: 100%; + } +} From b81c161a0806e572c79774cc5ad19b1d44739e7e Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:04:15 -0500 Subject: [PATCH 18/29] demo navbar --- pwa/src/Wrapper.tsx | 16 +++++++++++++++- pwa/src/scss/Wrapper.scss | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pwa/src/Wrapper.tsx b/pwa/src/Wrapper.tsx index 5e678fb..443e89e 100644 --- a/pwa/src/Wrapper.tsx +++ b/pwa/src/Wrapper.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { NavBar, Icon } from "antd-mobile"; import "./scss/Wrapper.scss"; @@ -9,7 +10,20 @@ type props = { const Wrapper = (props: props) => { return (
-
{props.children}
+
+ } + onLeftClick={() => console.log("onLeftClick")} + rightContent={[ + , + , + ]} + > + NavBar + + {props.children} +
); }; diff --git a/pwa/src/scss/Wrapper.scss b/pwa/src/scss/Wrapper.scss index 82f8333..0894364 100644 --- a/pwa/src/scss/Wrapper.scss +++ b/pwa/src/scss/Wrapper.scss @@ -4,7 +4,8 @@ display: flex; justify-content: space-around; #wrapper-contents { + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); max-width: 50em; - height: 100%; + max-height: 94%; } } From 21cb60a3e898ba96c62727041878c66b3e8a0c45 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:17:33 -0500 Subject: [PATCH 19/29] wrapper uses props for nav --- pwa/src/App.tsx | 6 +++++- pwa/src/Wrapper.tsx | 16 +++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 62c9e19..868d4d7 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -20,7 +20,11 @@ const App = () => { - + diff --git a/pwa/src/Wrapper.tsx b/pwa/src/Wrapper.tsx index 443e89e..f59aef4 100644 --- a/pwa/src/Wrapper.tsx +++ b/pwa/src/Wrapper.tsx @@ -1,26 +1,28 @@ import React from "react"; import { NavBar, Icon } from "antd-mobile"; +import { useHistory } from "react-router-dom"; import "./scss/Wrapper.scss"; type props = { + title: string; + leftArrowText: string; + leftArrowRoute: string; children: React.ReactNode; }; const Wrapper = (props: props) => { + const hist = useHistory(); + return (
} - onLeftClick={() => console.log("onLeftClick")} - rightContent={[ - , - , - ]} + onLeftClick={() => hist.push(`${props.leftArrowRoute}`)} + leftContent={[, `${props.leftArrowText}`]} > - NavBar + {`${props.title}`} {props.children}
From 2c18d2165b1f395bdf0d94fa9597ff7fbd62f49d Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:17:40 -0500 Subject: [PATCH 20/29] vh for wrapper height --- pwa/src/scss/Wrapper.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwa/src/scss/Wrapper.scss b/pwa/src/scss/Wrapper.scss index 0894364..ed3f753 100644 --- a/pwa/src/scss/Wrapper.scss +++ b/pwa/src/scss/Wrapper.scss @@ -6,6 +6,6 @@ #wrapper-contents { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); max-width: 50em; - max-height: 94%; + max-height: 94.6vh; } } From 75ef687f32baad99becc1805a809a4f6f48fe355 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:20:15 -0500 Subject: [PATCH 21/29] lint warnings --- pwa/src/components/LandingPage.tsx | 2 +- pwa/src/components/Login.tsx | 34 ++++++++++++++---------------- pwa/src/hooks/useApi.tsx | 20 +++++++++--------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/pwa/src/components/LandingPage.tsx b/pwa/src/components/LandingPage.tsx index 3a787c4..bfccc57 100644 --- a/pwa/src/components/LandingPage.tsx +++ b/pwa/src/components/LandingPage.tsx @@ -1,6 +1,6 @@ import React, { ReactElement } from "react"; import { WhiteSpace, Button } from "antd-mobile"; -import Icon, { UserAddOutlined } from "@ant-design/icons"; +import { UserAddOutlined } from "@ant-design/icons"; import "../scss/LandingPage.scss"; diff --git a/pwa/src/components/Login.tsx b/pwa/src/components/Login.tsx index 5766b06..d181260 100644 --- a/pwa/src/components/Login.tsx +++ b/pwa/src/components/Login.tsx @@ -1,31 +1,29 @@ -import React, { ReactElement } from 'react' -import useApi from '../hooks/useApi' -import {InputItem, Button} from 'antd-mobile' -import '../scss/Login.scss' +import React, { ReactElement } from "react"; +import useApi from "../hooks/useApi"; +import { InputItem, Button } from "antd-mobile"; +import "../scss/Login.scss"; export default function Login(): ReactElement { - const {response, error, isLoading} = useApi("") + const { response, isLoading } = useApi(""); return ( <>
-
-
- CHI Logo -
-
- - -
- +
+
+ CHI Logo
+
+ + +
+ +

Loading API Fetch: {isLoading.toString()}

- {response && -

API Fetch Result: {JSON.stringify(response)}

- } + {response &&

API Fetch Result: {JSON.stringify(response)}

} - ) + ); } diff --git a/pwa/src/hooks/useApi.tsx b/pwa/src/hooks/useApi.tsx index 50eb0cd..a292d8b 100644 --- a/pwa/src/hooks/useApi.tsx +++ b/pwa/src/hooks/useApi.tsx @@ -1,19 +1,18 @@ -import React from 'react' +import React from "react"; const useApi = (route: string) => { const [response, setResponse] = React.useState(null); const [error, setError] = React.useState(null); const [isLoading, setIsLoading] = React.useState(false); - + /* istanbul ignore next */ const getUrl = () => { - if (process.env.environment === "docker"){ - return "http://api:4000/" + if (process.env.environment === "docker") { + return "http://api:4000/"; + } else { + return "http://localhost:4000/"; } - else { - return "http://localhost:4000/" - } - } + }; React.useEffect(() => { const fetchData = async () => { @@ -22,14 +21,15 @@ const useApi = (route: string) => { const res = await fetch(getUrl() + route); const json = await res.json(); setResponse(json); - setIsLoading(false) + setIsLoading(false); } catch (error) { setError(error); } }; fetchData(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { response, error, isLoading }; }; -export default useApi \ No newline at end of file +export default useApi; From f59d0bfd0c8b90a69e4184d76315db0954312c9e Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:52:32 -0500 Subject: [PATCH 22/29] propNames --- pwa/src/App.tsx | 2 +- pwa/src/Wrapper.tsx | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 868d4d7..66aed54 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -21,7 +21,7 @@ const App = () => { diff --git a/pwa/src/Wrapper.tsx b/pwa/src/Wrapper.tsx index f59aef4..4a76bc0 100644 --- a/pwa/src/Wrapper.tsx +++ b/pwa/src/Wrapper.tsx @@ -5,25 +5,34 @@ import { useHistory } from "react-router-dom"; import "./scss/Wrapper.scss"; type props = { - title: string; - leftArrowText: string; - leftArrowRoute: string; + navTitle?: string; + leftArrowText?: string; + leftArrowRoute?: string; children: React.ReactNode; }; const Wrapper = (props: props) => { + const { navTitle, leftArrowText, leftArrowRoute } = props; const hist = useHistory(); + const needNavBar = navTitle || leftArrowText || leftArrowRoute; + const leftContentArr = leftArrowText + ? [, `${leftArrowText}`] + : []; + const leftRoute = leftArrowRoute ? `${leftArrowRoute}` : "/"; return (
- hist.push(`${props.leftArrowRoute}`)} - leftContent={[, `${props.leftArrowText}`]} - > - {`${props.title}`} - + {needNavBar && ( + hist.push(leftRoute)} + leftContent={leftContentArr} + > + {`${navTitle}`} + + )} {props.children}
From 30b893781f2d1632055785c72cac24c3b49cbefb Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 21:56:27 -0500 Subject: [PATCH 23/29] Initial Tests --- pwa/src/Wrapper.test.tsx | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 pwa/src/Wrapper.test.tsx diff --git a/pwa/src/Wrapper.test.tsx b/pwa/src/Wrapper.test.tsx new file mode 100644 index 0000000..0b97813 --- /dev/null +++ b/pwa/src/Wrapper.test.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { render, queryByAttribute } from "@testing-library/react"; +import Wrapper from "./Wrapper"; + +const mockHistoryPush = jest.fn(); +jest.mock("react-router-dom", () => ({ + useHistory: () => ({ + push: mockHistoryPush, + }), +})); + +test("renders it's inner contents", () => { + const dom = render( + +
Hello!
+
+ ); + + const textContents = dom.getByText("Hello!"); + + expect(textContents).toBeInTheDocument(); +}); + +test("renders navBar when given navTitle", () => { + const dom = render( + +
Hello!
+
+ ); + + const getById = queryByAttribute.bind(null, "id"); + const renderedNavBar = getById(dom.container, "nav-bar"); + const navTitle = dom.getByText("CHI"); + + expect(renderedNavBar).toBeTruthy(); + expect(navTitle).toBeInTheDocument(); +}); + +test("renders no navBar when not given props", () => { + const dom = render( + +
Hello!
+
+ ); + const getById = queryByAttribute.bind(null, "id"); + const renderedNavBar = getById(dom.container, "nav-bar"); + expect(renderedNavBar).toBeFalsy(); +}); + +test("renders leftArrowText", () => { + const dom = render( + +
Hello!
+
+ ); + + const leftArrowText = dom.getByText("back"); + + expect(leftArrowText).toBeInTheDocument(); +}); From e4e3a72c686c826a0f8996800fc1b2e1d6657029 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 22:42:20 -0500 Subject: [PATCH 24/29] placeholder file ignore --- pwa/src/components/PatientInfoPlaceholder.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/pwa/src/components/PatientInfoPlaceholder.tsx b/pwa/src/components/PatientInfoPlaceholder.tsx index e92d505..8dd19d3 100644 --- a/pwa/src/components/PatientInfoPlaceholder.tsx +++ b/pwa/src/components/PatientInfoPlaceholder.tsx @@ -1,3 +1,4 @@ +/* istanbul ignore file */ import React, { ReactElement } from "react"; export default function PatientInfoPlaceholder(): ReactElement { From 314bd357855f5a9c254e64751d5b76a21229f242 Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Mon, 13 Apr 2020 22:49:42 -0500 Subject: [PATCH 25/29] nav onClick test - 100% Coverage --- pwa/src/Wrapper.test.tsx | 16 ++++++++++++- pwa/src/components/LandingPage.tsx | 1 + pwa/src/hooks/useApi.test.tsx | 38 ++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/pwa/src/Wrapper.test.tsx b/pwa/src/Wrapper.test.tsx index 0b97813..00848e8 100644 --- a/pwa/src/Wrapper.test.tsx +++ b/pwa/src/Wrapper.test.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { render, queryByAttribute } from "@testing-library/react"; +import { render, queryByAttribute, fireEvent } from "@testing-library/react"; +import { useHistory } from "react-router-dom"; import Wrapper from "./Wrapper"; const mockHistoryPush = jest.fn(); @@ -58,3 +59,16 @@ test("renders leftArrowText", () => { expect(leftArrowText).toBeInTheDocument(); }); + +test("redirects on left arrow click ", () => { + const dom = render( + +
Hello!
+
+ ); + + const leftArrowText = dom.getByText("back"); + fireEvent.click(leftArrowText); + + expect(useHistory().push).toBeCalledWith("/"); +}); diff --git a/pwa/src/components/LandingPage.tsx b/pwa/src/components/LandingPage.tsx index bfccc57..b8a0df4 100644 --- a/pwa/src/components/LandingPage.tsx +++ b/pwa/src/components/LandingPage.tsx @@ -6,6 +6,7 @@ import "../scss/LandingPage.scss"; export default function LandingPage(): ReactElement { /* istanbul ignore next */ + // TODO: these onClick functions could be mocked in a unit test const patientLookup = () => { console.log("Clicked Patient Lookup"); }; diff --git a/pwa/src/hooks/useApi.test.tsx b/pwa/src/hooks/useApi.test.tsx index 42286bf..aafd6d8 100644 --- a/pwa/src/hooks/useApi.test.tsx +++ b/pwa/src/hooks/useApi.test.tsx @@ -1,16 +1,28 @@ -import { renderHook } from '@testing-library/react-hooks' -import useApi from './useApi' +import { renderHook } from "@testing-library/react-hooks"; +import useApi from "./useApi"; -test('should return loading and then a response', async () => { - const { result, waitForNextUpdate } = renderHook(() => useApi("")) - - expect(result.current.response).toBeNull() - expect(result.current.error).toBeNull() - expect(result.current.isLoading).toBeTruthy() +test("should return loading and then a response", async () => { + const { result, waitForNextUpdate } = renderHook(() => useApi("")); - await waitForNextUpdate() + expect(result.current.response).toBeNull(); + expect(result.current.error).toBeNull(); + expect(result.current.isLoading).toBeTruthy(); - expect(result.current.response).toBeTruthy() - expect(result.current.error).toBeNull() - expect(result.current.isLoading).toBeFalsy() -}) \ No newline at end of file + await waitForNextUpdate(); + + expect(result.current.response).toBeTruthy(); + expect(result.current.error).toBeNull(); + expect(result.current.isLoading).toBeFalsy(); +}); + +test("should return an error on a non existent route", async () => { + const { result, waitForNextUpdate } = renderHook(() => useApi("/404")); + + expect(result.current.response).toBeNull(); + expect(result.current.error).toBeNull(); + + await waitForNextUpdate(); + + expect(result.current.response).toBeFalsy(); + expect(result.current.error).toBeTruthy(); +}); From 0ddaa4233400c006a5cdc1e9c4d1d4849cb90e43 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Tue, 14 Apr 2020 19:33:00 -0500 Subject: [PATCH 26/29] adding cypress tests --- pwa/cypress/integration/PatientInfoForm.ts | 35 +++++++ pwa/src/App.tsx | 2 + pwa/src/components/PatientInfoForm.test.tsx | 100 +++++++++++--------- pwa/src/components/PatientInfoForm.tsx | 39 ++++---- 4 files changed, 112 insertions(+), 64 deletions(-) create mode 100644 pwa/cypress/integration/PatientInfoForm.ts diff --git a/pwa/cypress/integration/PatientInfoForm.ts b/pwa/cypress/integration/PatientInfoForm.ts new file mode 100644 index 0000000..22e13f8 --- /dev/null +++ b/pwa/cypress/integration/PatientInfoForm.ts @@ -0,0 +1,35 @@ +// Testing for the Patient Info Form fields +/// + +describe('female-only fields show only if Female is selected', () => { + const femaleOnlyFormFields = [ + 'Pregnant?', + 'LMP', + 'Wants Planning?' + ] + + it('does not display fields is no slection is made', function () { + cy.visit('http://localhost:3000'); + femaleOnlyFormFields.forEach((fieldText) => { + cy.contains(fieldText).should('not.exist'); + }) + }); + + it('does not display fields if Male is selected', function () { + cy.visit('http://localhost:3000'); + cy.get('#male-button').click(); + femaleOnlyFormFields.forEach((fieldText) => { + cy.contains(fieldText).should('not.exist'); + }) + }); + + it('displays fields if Female is selected', function () { + cy.visit('http://localhost:3000'); + cy.get('#female-button').click(); + femaleOnlyFormFields.forEach((fieldText) => { + cy.contains(fieldText); + }) + }); +}); + +export { }; \ No newline at end of file diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 4006c0f..4cbb061 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -3,11 +3,13 @@ import "./scss/App.scss"; import "./antd-mobile.css"; import Login from "./components/Login"; +import PatientInfoForm from './components/PatientInfoForm' const App = () => { return ( <> + ); }; diff --git a/pwa/src/components/PatientInfoForm.test.tsx b/pwa/src/components/PatientInfoForm.test.tsx index 743742f..34558a0 100644 --- a/pwa/src/components/PatientInfoForm.test.tsx +++ b/pwa/src/components/PatientInfoForm.test.tsx @@ -1,58 +1,68 @@ import React from "react"; -import { render, fireEvent, screen } from "@testing-library/react"; +import { render} from "@testing-library/react"; import PatientInfoForm from "./PatientInfoForm"; +/* +test("female-only div is only displayed if the sex is selected as female", async () => { + const femaleOnlyFormFields = [ + "Pregnant", + "LMP", + "wants planning" + ] -test("female-only div is only displayed if the sex is selected as female", () => { - const femaleOnlyFormFields = [ - "pregnant", - "LMP", - "wants planning" - ] + // render(); + const { getByText } = render(); - render(); + // ensure the female-only div is not displayed + femaleOnlyFormFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(screen.queryByText(re)).toBeNull(); + }) - // ensure the female-only div is not displayed - femaleOnlyFormFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); - expect(screen.queryByText(re)).toBeNull(); - }) + // click the radio button for 'female' + fireEvent.click(screen.getByText(/Female/i)); - // click the radio button for 'female' - fireEvent.click(screen.getByText(/female/i)) - - // ensure the female-only div is displayed - femaleOnlyFormFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); - expect(screen.getByText(re)).toBeInTheDocument(); - }) + // ensure the female-only div is displayed + femaleOnlyFormFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(screen.getByText(re)).toBeInTheDocument(); + }) }) +*/ + test("renders the Patient Info Form fields", () => { - const formFields = [ - "First Name", - "Last Name", - "Nickname", - "Town", - "Sex", - "Birth", - "Age", - "Phone", - "Temp", - "Pulse", - "Weight", - "Height", - "Albendazole", - "Alergies", - "Medicines", - "Exam" - ]; - - const { getByText } = render(); + const formFields = [ + "First Name", + "First Name", + "Last Name", + "Last Name", + "Sex", + "Birth", + "Age", + "Phone", + "Town", + "Visit", + "Nickname", + "BP", + "Temp", + "Pulse", + "Weight", + "Height", + "Z-Score", + "Albendazole", + "Alergies", + "Medicines", + "Chief Complaint", + "History", + "Exam" + ]; + + const { getByText } = render(); - formFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); - expect(getByText(re)).toBeInTheDocument(); - }) + formFields.forEach((fieldText) => { + let re = new RegExp(fieldText, 'gi'); + expect(getByText(re)).toBeInTheDocument(); + }) }) \ No newline at end of file diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 045aaa6..c813917 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,5 +1,5 @@ import React, { ReactElement, useState } from 'react' -import { DatePicker, InputItem, List, TextareaItem, Button, Radio, WhiteSpace} from 'antd-mobile' +import { DatePicker, InputItem, List, TextareaItem, Button, Radio, WhiteSpace } from 'antd-mobile' import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; import '../scss/Login.scss' @@ -15,17 +15,18 @@ export default function Form(): ReactElement { const [pregnant, setPregnant] = useState(0) // Default: No const [planning, setPlanning] = useState(0) // Default: No - // Data for Radio Buttons - const sexValues = [ - { value: 0, label: 'Male' }, - { value: 1, label: 'Female' } - ] - - const radioYesNo = [ - { value: 0, label: 'No' }, - { value: 1, label: 'Yes' }, - ]; + // Data for Radio Buttons + const sexValues = [ + { value: 0, label: 'Male' }, + { value: 1, label: 'Female' } + ] + const radioYesNo = [ + { value: 0, label: 'No' }, + { value: 1, label: 'Yes' }, + ]; + + /* istanbul ignore next */ const onSubmit = () => { // This shows how to access the values of the form const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement @@ -67,13 +68,13 @@ export default function Form(): ReactElement { 'Sex'}> {sexValues.map(i => ( - setSex(i.value)}> + setSex(i.value)}> {i.label} ))} - + 'Visit?'}> {radioYesNo.map(i => ( - setVisit(i.value)}> + setVisit(i.value)}> {i.label} ))} @@ -116,10 +117,10 @@ export default function Form(): ReactElement { {/* Only display the 'female-only' div if the patient is female */} {sex ?
- + 'Pregnant?'}> {radioYesNo.map(i => ( - setPregnant(i.value)}> + setPregnant(i.value)}> {i.label} ))} @@ -150,7 +151,7 @@ export default function Form(): ReactElement { 'Wants Planning?'}> {radioYesNo.map(i => ( - setPlanning(i.value)}> + setPlanning(i.value)}> {i.label} ))} @@ -159,7 +160,7 @@ export default function Form(): ReactElement { : null } - + - + From d52ee1378796fb3cdcfce97de31839a98a45ab1b Mon Sep 17 00:00:00 2001 From: Ben Mitchinson Date: Tue, 14 Apr 2020 22:23:16 -0500 Subject: [PATCH 27/29] 100% Unit Coverage (+ Accidental Linting) --- pwa/src/components/PatientInfoForm.test.tsx | 87 ++++-- pwa/src/components/PatientInfoForm.tsx | 298 ++++++++++---------- 2 files changed, 213 insertions(+), 172 deletions(-) diff --git a/pwa/src/components/PatientInfoForm.test.tsx b/pwa/src/components/PatientInfoForm.test.tsx index 34558a0..b1009fd 100644 --- a/pwa/src/components/PatientInfoForm.test.tsx +++ b/pwa/src/components/PatientInfoForm.test.tsx @@ -1,35 +1,73 @@ import React from "react"; -import { render} from "@testing-library/react"; +import { render, fireEvent, prettyDOM } from "@testing-library/react"; import PatientInfoForm from "./PatientInfoForm"; -/* -test("female-only div is only displayed if the sex is selected as female", async () => { - const femaleOnlyFormFields = [ - "Pregnant", - "LMP", - "wants planning" - ] - // render(); - const { getByText } = render(); +test("female-only div is only displayed if the sex is selected as female", async () => { + const femaleOnlyFormFields = ["Pregnant?", "LMP", "Wants Planning?"]; + + const dom = render(); // ensure the female-only div is not displayed femaleOnlyFormFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); - expect(screen.queryByText(re)).toBeNull(); - }) + expect(dom.queryByText(fieldText)).toBeNull(); + }); // click the radio button for 'female' - fireEvent.click(screen.getByText(/Female/i)); + const femaleButton = dom.getByTestId("female-button"); + fireEvent.click(femaleButton); - // ensure the female-only div is displayed femaleOnlyFormFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); - expect(screen.getByText(re)).toBeInTheDocument(); - }) -}) -*/ + expect(dom.queryByText(fieldText)).toBeTruthy(); + }); +}); +test("sets visit input", () => { + const dom = render(); + const visitYesInput = dom.queryByTestId("visit-Yes"); + const checkBox = visitYesInput.getElementsByTagName("span")[0]; + expect(checkBox).not.toHaveClass("am-radio-checked"); + fireEvent.click(visitYesInput); + expect(checkBox).toHaveClass("am-radio-checked"); +}); + +test("sets pregnant input", () => { + const dom = render(); + const femaleButton = dom.getByTestId("female-button"); + fireEvent.click(femaleButton); + + const pregnantYesInput = dom.queryByTestId("pregnant-Yes"); + const checkBox = pregnantYesInput.getElementsByTagName("span")[0]; + + expect(checkBox).not.toHaveClass("am-radio-checked"); + fireEvent.click(pregnantYesInput); + expect(checkBox).toHaveClass("am-radio-checked"); +}); + +test("sets planning input", () => { + const dom = render(); + const femaleButton = dom.getByTestId("female-button"); + fireEvent.click(femaleButton); + + const planningYesInput = dom.queryByTestId("planning-Yes"); + const checkBox = planningYesInput.getElementsByTagName("span")[0]; + + expect(checkBox).not.toHaveClass("am-radio-checked"); + fireEvent.click(planningYesInput); + expect(checkBox).toHaveClass("am-radio-checked"); +}); + +test("sets albendazole input", () => { + const dom = render(); + const femaleButton = dom.getByTestId("female-button"); + + const albendazoleYesInput = dom.queryByTestId("albendazole-Yes"); + const checkBox = albendazoleYesInput.getElementsByTagName("span")[0]; + + expect(checkBox).not.toHaveClass("am-radio-checked"); + fireEvent.click(albendazoleYesInput); + expect(checkBox).toHaveClass("am-radio-checked"); +}); test("renders the Patient Info Form fields", () => { const formFields = [ @@ -55,14 +93,13 @@ test("renders the Patient Info Form fields", () => { "Medicines", "Chief Complaint", "History", - "Exam" + "Exam", ]; const { getByText } = render(); - formFields.forEach((fieldText) => { - let re = new RegExp(fieldText, 'gi'); + let re = new RegExp(fieldText, "gi"); expect(getByText(re)).toBeInTheDocument(); - }) -}) \ No newline at end of file + }); +}); diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index c813917..305f398 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -1,50 +1,76 @@ -import React, { ReactElement, useState } from 'react' -import { DatePicker, InputItem, List, TextareaItem, Button, Radio, WhiteSpace } from 'antd-mobile' -import enUs from 'antd-mobile/lib/date-picker/locale/en_US'; -import '../scss/Login.scss' +import React, { ReactElement, useState } from "react"; +import { + DatePicker, + InputItem, + List, + TextareaItem, + Button, + Radio, + WhiteSpace, +} from "antd-mobile"; +import enUs from "antd-mobile/lib/date-picker/locale/en_US"; +import "../scss/Login.scss"; const RadioItem = Radio.RadioItem; - export default function Form(): ReactElement { // State Hooks for Radio Buttons // useState returns a value, and a function to set that value - const [sex, setSex] = useState(null as Number) // Default: null - const [albendazole, setAlbendazole] = useState(0) // Default: No - const [visit, setVisit] = useState(0) // Default: No - const [pregnant, setPregnant] = useState(0) // Default: No - const [planning, setPlanning] = useState(0) // Default: No + const [sex, setSex] = useState(null as Number); // Default: null + const [albendazole, setAlbendazole] = useState(0); // Default: No + const [visit, setVisit] = useState(0); // Default: No + const [pregnant, setPregnant] = useState(0); // Default: No + const [planning, setPlanning] = useState(0); // Default: No // Data for Radio Buttons const sexValues = [ - { value: 0, label: 'Male' }, - { value: 1, label: 'Female' } - ] + { value: 0, label: "Male" }, + { value: 1, label: "Female" }, + ]; const radioYesNo = [ - { value: 0, label: 'No' }, - { value: 1, label: 'Yes' }, + { value: 0, label: "No" }, + { value: 1, label: "Yes" }, ]; /* istanbul ignore next */ const onSubmit = () => { // This shows how to access the values of the form - const firstNameField: HTMLInputElement = document.getElementById('firstname') as HTMLInputElement - const lastNameField: HTMLInputElement = document.getElementById('lastname') as HTMLInputElement - const nicknameField: HTMLInputElement = document.getElementById('nickname') as HTMLInputElement - const complaintField1: HTMLInputElement = document.getElementById('complaint1') as HTMLInputElement - const complaintField2: HTMLInputElement = document.getElementById('complaint2') as HTMLInputElement - const complaintField3: HTMLInputElement = document.getElementById('complaint3') as HTMLInputElement + const firstNameField: HTMLInputElement = document.getElementById( + "firstname" + ) as HTMLInputElement; + const lastNameField: HTMLInputElement = document.getElementById( + "lastname" + ) as HTMLInputElement; + const nicknameField: HTMLInputElement = document.getElementById( + "nickname" + ) as HTMLInputElement; + const complaintField1: HTMLInputElement = document.getElementById( + "complaint1" + ) as HTMLInputElement; + const complaintField2: HTMLInputElement = document.getElementById( + "complaint2" + ) as HTMLInputElement; + const complaintField3: HTMLInputElement = document.getElementById( + "complaint3" + ) as HTMLInputElement; - console.log("First name:", firstNameField.value) - console.log("Last name:", lastNameField.value) - console.log("Nickname:", nicknameField.value) - console.log("Complaints: ", complaintField1.value + " " + complaintField2.value + " " + complaintField3.value) - console.log("Wants Planning?: " + planning) - } + console.log("First name:", firstNameField.value); + console.log("Last name:", lastNameField.value); + console.log("Nickname:", nicknameField.value); + console.log( + "Complaints: ", + complaintField1.value + + " " + + complaintField2.value + + " " + + complaintField3.value + ); + console.log("Wants Planning?: " + planning); + }; return ( -
+
- 'Sex'}> - {sexValues.map(i => ( - setSex(i.value)}> + "Sex"}> + {sexValues.map((i) => ( + setSex(i.value)} + > {i.label} ))} @@ -87,176 +120,147 @@ export default function Form(): ReactElement { {/* TODO: figure out how to access this value */} - Age + + Age{" "} + - Phone + + Phone + - + - 'Visit?'}> - {radioYesNo.map(i => ( - setVisit(i.value)}> + "Visit?"}> + {radioYesNo.map((i) => ( + setVisit(i.value)} + > {i.label} ))} {/* Only display the 'female-only' div if the patient is female */} - {sex ? -
+ {sex ? ( +
- 'Pregnant?'}> - {radioYesNo.map(i => ( - setPregnant(i.value)}> + "Pregnant?"}> + {radioYesNo.map((i) => ( + setPregnant(i.value)} + > {i.label} ))} - G + + G + - P + + P + - A + + A + - + - 'Wants Planning?'}> - {radioYesNo.map(i => ( - setPlanning(i.value)}> + "Wants Planning?"}> + {radioYesNo.map((i) => ( + setPlanning(i.value)} + > {i.label} ))}
- : null - } + ) : null} - Weight (kg) + + Weight (kg) + - Height (cm) + + Height (cm) + - BP + + BP + - Temp (F) + + Temp (F) + - Pulse + + Pulse + - Z-Score + + Z-Score + - 'Albendazole?'}> - {radioYesNo.map(i => ( - setAlbendazole(i.value)}> + "Albendazole?"}> + {radioYesNo.map((i) => ( + setAlbendazole(i.value)} + > {i.label} ))} - 'Alergies'}> - + "Alergies"}> + - 'Medicines'}> - + "Medicines"}> + - 'Chief Complaint'}> + "Chief Complaint"}> - - + + - 'History'}> - + "History"}> + - 'Exam'}> - + "Exam"}> + - - +
- ) + ); } From 7e55e0bf17d64618561eb5bbc1b2bad690798618 Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Wed, 15 Apr 2020 09:28:23 -0500 Subject: [PATCH 28/29] removing integ test now covered in unit testing, replaced placeholder with actual component --- pwa/cypress/integration/PatientInfoForm.ts | 35 ---------------------- pwa/src/App.tsx | 4 +-- 2 files changed, 2 insertions(+), 37 deletions(-) delete mode 100644 pwa/cypress/integration/PatientInfoForm.ts diff --git a/pwa/cypress/integration/PatientInfoForm.ts b/pwa/cypress/integration/PatientInfoForm.ts deleted file mode 100644 index 22e13f8..0000000 --- a/pwa/cypress/integration/PatientInfoForm.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Testing for the Patient Info Form fields -/// - -describe('female-only fields show only if Female is selected', () => { - const femaleOnlyFormFields = [ - 'Pregnant?', - 'LMP', - 'Wants Planning?' - ] - - it('does not display fields is no slection is made', function () { - cy.visit('http://localhost:3000'); - femaleOnlyFormFields.forEach((fieldText) => { - cy.contains(fieldText).should('not.exist'); - }) - }); - - it('does not display fields if Male is selected', function () { - cy.visit('http://localhost:3000'); - cy.get('#male-button').click(); - femaleOnlyFormFields.forEach((fieldText) => { - cy.contains(fieldText).should('not.exist'); - }) - }); - - it('displays fields if Female is selected', function () { - cy.visit('http://localhost:3000'); - cy.get('#female-button').click(); - femaleOnlyFormFields.forEach((fieldText) => { - cy.contains(fieldText); - }) - }); -}); - -export { }; \ No newline at end of file diff --git a/pwa/src/App.tsx b/pwa/src/App.tsx index 66aed54..016b820 100644 --- a/pwa/src/App.tsx +++ b/pwa/src/App.tsx @@ -3,7 +3,7 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import Login from "./components/Login"; import LandingPage from "./components/LandingPage"; -import PatientInfoPlaceholder from "./components/PatientInfoPlaceholder"; +import PatientInfoForm from "./components/PatientInfoForm"; import Wrapper from "./Wrapper"; import "./scss/App.scss"; @@ -25,7 +25,7 @@ const App = () => { leftArrowText="Home" leftArrowRoute="/" > - + From 2efb19fc8c604b6af043678e6bdf27ce573aeb0e Mon Sep 17 00:00:00 2001 From: Meghan McLaughlin Date: Wed, 15 Apr 2020 10:53:32 -0500 Subject: [PATCH 29/29] update date field --- pwa/src/components/PatientInfoForm.tsx | 28 +++++++++---------- pwa/src/components/PatientInfoPlaceholder.tsx | 12 -------- pwa/src/scss/PatientInfoForm.scss | 8 ++++++ 3 files changed, 21 insertions(+), 27 deletions(-) delete mode 100644 pwa/src/components/PatientInfoPlaceholder.tsx create mode 100644 pwa/src/scss/PatientInfoForm.scss diff --git a/pwa/src/components/PatientInfoForm.tsx b/pwa/src/components/PatientInfoForm.tsx index 305f398..980d8e8 100644 --- a/pwa/src/components/PatientInfoForm.tsx +++ b/pwa/src/components/PatientInfoForm.tsx @@ -9,7 +9,7 @@ import { WhiteSpace, } from "antd-mobile"; import enUs from "antd-mobile/lib/date-picker/locale/en_US"; -import "../scss/Login.scss"; +import "../scss/PatientInfoForm.scss"; const RadioItem = Radio.RadioItem; @@ -45,6 +45,9 @@ export default function Form(): ReactElement { const nicknameField: HTMLInputElement = document.getElementById( "nickname" ) as HTMLInputElement; + const birthdateField: HTMLInputElement = document.getElementById( + "birthdate" + ) as HTMLInputElement; const complaintField1: HTMLInputElement = document.getElementById( "complaint1" ) as HTMLInputElement; @@ -58,15 +61,17 @@ export default function Form(): ReactElement { console.log("First name:", firstNameField.value); console.log("Last name:", lastNameField.value); console.log("Nickname:", nicknameField.value); + console.log("Birth Date:", birthdateField.value); console.log( "Complaints: ", complaintField1.value + - " " + - complaintField2.value + - " " + - complaintField3.value + " " + + complaintField2.value + + " " + + complaintField3.value ); console.log("Wants Planning?: " + planning); + }; return ( @@ -109,16 +114,9 @@ export default function Form(): ReactElement { - - Birth Date - {/* TODO: figure out how to access this value */} - + + Birth Date + Age{" "} diff --git a/pwa/src/components/PatientInfoPlaceholder.tsx b/pwa/src/components/PatientInfoPlaceholder.tsx deleted file mode 100644 index 8dd19d3..0000000 --- a/pwa/src/components/PatientInfoPlaceholder.tsx +++ /dev/null @@ -1,12 +0,0 @@ -/* istanbul ignore file */ -import React, { ReactElement } from "react"; - -export default function PatientInfoPlaceholder(): ReactElement { - return ( - placeholder - ); -} diff --git a/pwa/src/scss/PatientInfoForm.scss b/pwa/src/scss/PatientInfoForm.scss new file mode 100644 index 0000000..6451bb9 --- /dev/null +++ b/pwa/src/scss/PatientInfoForm.scss @@ -0,0 +1,8 @@ +#patient-info-wrapper { + display: flex; + flex-direction: column; + + height: 100%; + width: 100%; + } + \ No newline at end of file