mirror of
https://github.com/Haiti-Distributed-Healthcare-System/hdhs.git
synced 2026-11-06 22:35:57 +00:00
Merge remote-tracking branch 'origin/patient-info-form' into feature/diagnosis-component
This commit is contained in:
commit
8d5dc9623c
15 files changed
+740
-67
No files matched your search
Generated
+126
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
+29
-5
@@ -1,14 +1,38 @@
|
||||
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 PatientInfoForm from "./components/PatientInfoForm";
|
||||
import Wrapper from "./Wrapper";
|
||||
|
||||
import "./scss/App.scss";
|
||||
import "./antd-mobile.css";
|
||||
|
||||
import Login from "./components/Login";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<>
|
||||
<Login />
|
||||
</>
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path="/login">
|
||||
<Login />
|
||||
</Route>
|
||||
<Route path="/landing">
|
||||
<LandingPage />
|
||||
</Route>
|
||||
<Route path="/patientinfo">
|
||||
<Wrapper
|
||||
navTitle="Patient Information"
|
||||
leftArrowText="Home"
|
||||
leftArrowRoute="/"
|
||||
>
|
||||
<PatientInfoForm />
|
||||
</Wrapper>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<Login />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import React from "react";
|
||||
import { render, queryByAttribute, fireEvent } from "@testing-library/react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
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(
|
||||
<Wrapper leftArrowText="back">
|
||||
<div>Hello!</div>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
const textContents = dom.getByText("Hello!");
|
||||
|
||||
expect(textContents).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("renders navBar when given navTitle", () => {
|
||||
const dom = render(
|
||||
<Wrapper navTitle="CHI">
|
||||
<div>Hello!</div>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
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(
|
||||
<Wrapper>
|
||||
<div>Hello!</div>
|
||||
</Wrapper>
|
||||
);
|
||||
const getById = queryByAttribute.bind(null, "id");
|
||||
const renderedNavBar = getById(dom.container, "nav-bar");
|
||||
expect(renderedNavBar).toBeFalsy();
|
||||
});
|
||||
|
||||
test("renders leftArrowText", () => {
|
||||
const dom = render(
|
||||
<Wrapper leftArrowText="back">
|
||||
<div>Hello!</div>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
const leftArrowText = dom.getByText("back");
|
||||
|
||||
expect(leftArrowText).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("redirects on left arrow click ", () => {
|
||||
const dom = render(
|
||||
<Wrapper leftArrowText="back" leftArrowRoute="/">
|
||||
<div>Hello!</div>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
const leftArrowText = dom.getByText("back");
|
||||
fireEvent.click(leftArrowText);
|
||||
|
||||
expect(useHistory().push).toBeCalledWith("/");
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import { NavBar, Icon } from "antd-mobile";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import "./scss/Wrapper.scss";
|
||||
|
||||
type props = {
|
||||
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
|
||||
? [<Icon type="left" />, `${leftArrowText}`]
|
||||
: [];
|
||||
const leftRoute = leftArrowRoute ? `${leftArrowRoute}` : "/";
|
||||
|
||||
return (
|
||||
<div id="primary-wrapper">
|
||||
<div id="wrapper-contents">
|
||||
{needNavBar && (
|
||||
<NavBar
|
||||
id="nav-bar"
|
||||
mode="light"
|
||||
onLeftClick={() => hist.push(leftRoute)}
|
||||
leftContent={leftContentArr}
|
||||
>
|
||||
{`${navTitle}`}
|
||||
</NavBar>
|
||||
)}
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
@@ -1,11 +1,12 @@
|
||||
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";
|
||||
|
||||
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");
|
||||
};
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<div id="loginWrapper">
|
||||
<div id="loginGrid">
|
||||
<div id="iconCard">
|
||||
<div id="imgWrap">
|
||||
<img src="/logoIcon512.jpg" alt="CHI Logo"></img>
|
||||
</div>
|
||||
</div>
|
||||
<InputItem placeholder="username"/>
|
||||
<InputItem placeholder="password" type="password"/>
|
||||
<div id="buttonFlex">
|
||||
<Button>Login</Button>
|
||||
<div id="iconCard">
|
||||
<div id="imgWrap">
|
||||
<img src="/logoIcon512.jpg" alt="CHI Logo"></img>
|
||||
</div>
|
||||
</div>
|
||||
<InputItem placeholder="username" />
|
||||
<InputItem placeholder="password" type="password" />
|
||||
<div id="buttonFlex">
|
||||
<Button>Login</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>Loading API Fetch: {isLoading.toString()}</p>
|
||||
{response &&
|
||||
<p>API Fetch Result: {JSON.stringify(response)}</p>
|
||||
}
|
||||
{response && <p>API Fetch Result: {JSON.stringify(response)}</p>}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import React from "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?"];
|
||||
|
||||
const dom = render(<PatientInfoForm />);
|
||||
|
||||
// ensure the female-only div is not displayed
|
||||
femaleOnlyFormFields.forEach((fieldText) => {
|
||||
expect(dom.queryByText(fieldText)).toBeNull();
|
||||
});
|
||||
|
||||
// click the radio button for 'female'
|
||||
const femaleButton = dom.getByTestId("female-button");
|
||||
fireEvent.click(femaleButton);
|
||||
|
||||
femaleOnlyFormFields.forEach((fieldText) => {
|
||||
expect(dom.queryByText(fieldText)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
test("sets visit input", () => {
|
||||
const dom = render(<PatientInfoForm />);
|
||||
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(<PatientInfoForm />);
|
||||
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(<PatientInfoForm />);
|
||||
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(<PatientInfoForm />);
|
||||
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 = [
|
||||
"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(<PatientInfoForm />);
|
||||
|
||||
formFields.forEach((fieldText) => {
|
||||
let re = new RegExp(fieldText, "gi");
|
||||
expect(getByText(re)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,264 @@
|
||||
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/PatientInfoForm.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
|
||||
|
||||
// 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;
|
||||
const lastNameField: HTMLInputElement = document.getElementById(
|
||||
"lastname"
|
||||
) as HTMLInputElement;
|
||||
const nicknameField: HTMLInputElement = document.getElementById(
|
||||
"nickname"
|
||||
) as HTMLInputElement;
|
||||
const birthdateField: HTMLInputElement = document.getElementById(
|
||||
"birthdate"
|
||||
) 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("Birth Date:", birthdateField.value);
|
||||
console.log(
|
||||
"Complaints: ",
|
||||
complaintField1.value +
|
||||
" " +
|
||||
complaintField2.value +
|
||||
" " +
|
||||
complaintField3.value
|
||||
);
|
||||
console.log("Wants Planning?: " + planning);
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<div id="patient-info-wrapper">
|
||||
<TextareaItem
|
||||
title="First Name"
|
||||
placeholder="First Name"
|
||||
autoHeight
|
||||
id="firstname"
|
||||
/>
|
||||
|
||||
<TextareaItem
|
||||
title="Last Name"
|
||||
placeholder="Last Name"
|
||||
id="lastname"
|
||||
autoHeight
|
||||
/>
|
||||
|
||||
<TextareaItem
|
||||
title="Nickname"
|
||||
placeholder="Nickname"
|
||||
id="nickname"
|
||||
autoHeight
|
||||
/>
|
||||
|
||||
<List renderHeader={() => "Sex"}>
|
||||
{sexValues.map((i) => (
|
||||
<RadioItem
|
||||
data-testid={`${i.label.toLowerCase()}-button`}
|
||||
id={`${i.label.toLowerCase()}-button`}
|
||||
key={i.value}
|
||||
name="sex"
|
||||
checked={sex === i.value}
|
||||
onClick={() => setSex(i.value)}
|
||||
>
|
||||
{i.label}
|
||||
</RadioItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<WhiteSpace />
|
||||
|
||||
<InputItem placeholder="YYYY-MM-DD" id="birthdate">
|
||||
Birth Date
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Age" id="age">
|
||||
Age{" "}
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Phone" id="phone">
|
||||
Phone
|
||||
</InputItem>
|
||||
|
||||
<TextareaItem title="Town" placeholder="Town" id="town" autoHeight />
|
||||
|
||||
<List renderHeader={() => "Visit?"}>
|
||||
{radioYesNo.map((i) => (
|
||||
<RadioItem
|
||||
key={i.value}
|
||||
data-testid={`visit-${i.label}`}
|
||||
name="visit"
|
||||
checked={visit === i.value}
|
||||
onClick={() => setVisit(i.value)}
|
||||
>
|
||||
{i.label}
|
||||
</RadioItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
{/* Only display the 'female-only' div if the patient is female */}
|
||||
{sex ? (
|
||||
<div id="female-only">
|
||||
<WhiteSpace />
|
||||
<List renderHeader={() => "Pregnant?"}>
|
||||
{radioYesNo.map((i) => (
|
||||
<RadioItem
|
||||
data-testid={`pregnant-${i.label}`}
|
||||
key={i.value}
|
||||
name="pregnant"
|
||||
checked={pregnant === i.value}
|
||||
onClick={() => setPregnant(i.value)}
|
||||
>
|
||||
{i.label}
|
||||
</RadioItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<InputItem title="G" type="number" id="gravida">
|
||||
G
|
||||
</InputItem>
|
||||
|
||||
<InputItem title="P" type="number" id="para">
|
||||
P
|
||||
</InputItem>
|
||||
|
||||
<InputItem title="A" type="number" id="abortus">
|
||||
A
|
||||
</InputItem>
|
||||
|
||||
<TextareaItem title="LMP" id="lmp" />
|
||||
|
||||
<List renderHeader={() => "Wants Planning?"}>
|
||||
{radioYesNo.map((i) => (
|
||||
<RadioItem
|
||||
data-testid={`planning-${i.label}`}
|
||||
key={i.value}
|
||||
name="planning"
|
||||
checked={planning === i.value}
|
||||
onClick={() => setPlanning(i.value)}
|
||||
>
|
||||
{i.label}
|
||||
</RadioItem>
|
||||
))}
|
||||
</List>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<WhiteSpace />
|
||||
|
||||
<InputItem type="number" placeholder="Weight" id="weight">
|
||||
Weight (kg)
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Height" id="height">
|
||||
Height (cm)
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Blood Pressure" id="bp">
|
||||
BP
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Temp" id="temp">
|
||||
Temp (F)
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Pulse" id="pulse">
|
||||
Pulse
|
||||
</InputItem>
|
||||
|
||||
<InputItem type="number" placeholder="Z-Score" id="z-score">
|
||||
Z-Score
|
||||
</InputItem>
|
||||
|
||||
<List renderHeader={() => "Albendazole?"}>
|
||||
{radioYesNo.map((i) => (
|
||||
<RadioItem
|
||||
data-testid={`albendazole-${i.label}`}
|
||||
key={i.value}
|
||||
checked={albendazole === i.value}
|
||||
onClick={() => setAlbendazole(i.value)}
|
||||
>
|
||||
{i.label}
|
||||
</RadioItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<List renderHeader={() => "Alergies"}>
|
||||
<TextareaItem autoHeight id="alergies" />
|
||||
</List>
|
||||
|
||||
<List renderHeader={() => "Medicines"}>
|
||||
<TextareaItem autoHeight id="medicines" />
|
||||
</List>
|
||||
|
||||
<List renderHeader={() => "Chief Complaint"}>
|
||||
<TextareaItem
|
||||
placeholder="1."
|
||||
// autoHeight
|
||||
autoHeight
|
||||
id="complaint1"
|
||||
/>
|
||||
<TextareaItem placeholder="2." autoHeight id="complaint2" />
|
||||
<TextareaItem placeholder="3." autoHeight id="complaint3" />
|
||||
</List>
|
||||
|
||||
<List renderHeader={() => "History"}>
|
||||
<TextareaItem autoHeight id="history" />
|
||||
</List>
|
||||
|
||||
<List renderHeader={() => "Exam"}>
|
||||
<TextareaItem autoHeight id="exam" />
|
||||
</List>
|
||||
|
||||
<WhiteSpace />
|
||||
|
||||
<Button onClick={onSubmit}>Submit</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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()
|
||||
})
|
||||
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();
|
||||
});
|
||||
+10
-10
@@ -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
|
||||
export default useApi;
|
||||
@@ -1,6 +1,4 @@
|
||||
.button-flex {
|
||||
animation-name: fade-in;
|
||||
animation-duration: 2s;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 2em 0;
|
||||
|
||||
+26
-18
@@ -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; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#patient-info-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#primary-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
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;
|
||||
max-height: 94.6vh;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user