diff --git a/server/main.js b/server/main.js index 15afdc62..61d68c40 100644 --- a/server/main.js +++ b/server/main.js @@ -1,5 +1,7 @@ const express = require('express'); const fhirKitClient = require('fhir-kit-client'); +const bodyParser = require('body-parser'); +const { URL } = require('url'); const config = { baseUrl: 'https://sb-fhir-stu3.smarthealthit.org/smartstu3/open/' }; const client = new fhirKitClient(config); @@ -12,11 +14,14 @@ if (process.env.NODE_ENV === 'production') { app.use(express.static('build')); } +app.use(bodyParser.urlencoded({ extended: false })); +app.use(bodyParser.json()); + app.get('/api/patient', (req, res) => { if (req.query.name) { client.search({ resourceType: 'Patient', - searchParams: { name: req.query.name } + searchParams: { name: req.query.name, _count: 4 } }).then((response) => { const patients = response.entry ? response.entry.map((obj) => { return { @@ -27,8 +32,29 @@ app.get('/api/patient', (req, res) => { } }) : response; - res.status(200).json(patients); + res.status(200).json({ patients: patients, bundle: response, total: response.total }); + }); + } +}); + +app.post('/api/patient', (req, res) => { + client.pagination.initialize(req.body.bundle); + + if (req.query.page) { + client.pagination.goToPage(req.query.page) + .then((response) => { + const patients = response.entry ? response.entry.map((obj) => { + return { + id: obj.resource.id, + name: `${obj.resource.name[0].given} ${obj.resource.name[0].family}`, + gender: obj.resource.gender, + birthDate: obj.resource.birthDate + } + }) : response; + + res.status(200).json({ patients: patients, bundle: response, total: response.total }); }); + } else { res.status(200).json({ patients: []}); } diff --git a/server/package.json b/server/package.json index 4beb3c23..6a0fae36 100644 --- a/server/package.json +++ b/server/package.json @@ -10,6 +10,7 @@ "author": "", "license": "MIT", "dependencies": { + "body-parser": "^1.18.3", "express": "^4.16.3", "fhir-kit-client": "^0.2.2" } diff --git a/server/yarn.lock b/server/yarn.lock index 5ab1674b..b1073649 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -35,6 +35,21 @@ body-parser@1.18.2: raw-body "2.3.2" type-is "~1.6.15" +body-parser@^1.18.3: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -172,7 +187,7 @@ http-errors@1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-errors@~1.6.2: +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" dependencies: @@ -185,6 +200,12 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -256,6 +277,10 @@ qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -269,10 +294,23 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" +raw-body@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" diff --git a/src/App.jsx.js b/src/App.jsx.js index 8c75ab4a..9ab1c45c 100644 --- a/src/App.jsx.js +++ b/src/App.jsx.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import Patient from './Patient.jsx'; -import { Layout, Input, List, Card, Row, Col, Spin } from 'antd'; +import { Layout, Input, List, Card, Row, Col, Spin, Pagination } from 'antd'; import './App.css'; const { Header, Content } = Layout; @@ -23,17 +23,56 @@ class App extends Component { .then((response) => ( response.json() )) - .then((patients) => { - this.setState({ patients: patients, loading: false, searchResolved: true }) + .then((results) => { + this.setState({ + patients: results.patients, + loading: false, + searchResolved: true, + bundle: results.bundle, + total: results.total + }); }) .catch((err) => { console.log(err); this.setState({ loading: false }); + }); + } + + turnPage = (page, _pageSize) => { + + fetch(`api/patient?page=${page}`, { + body: JSON.stringify({ bundle: this.state.bundle }), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + accept: 'application/json', + method: 'POST', + mode: 'cors' + }) + .then((response) => ( + response.json() + )) + .then((results) => { + this.setState({ + patients: results.patients, + bundle: results.bundle, + total: results.total + }); }) } + itemRender(current, type, originalElement) { + if (type === 'prev') { + return Previous; + } else if (type === 'next') { + return Next; + } + return originalElement; + } + render() { - const { patients, loading, searchResolved } = this.state; + const { patients, loading, searchResolved, total } = this.state; return ( @@ -61,25 +100,35 @@ class App extends Component { ) : ( - ( - - - - - - )} - /> + + +

{ total ? (total + ' result(s)') : ''}

+ ( + + + + + + )} + /> + + +
) } -
);