Skip to content

Commit bbf57b5

Browse files
committed
First form for patient
1 parent cc9b2f7 commit bbf57b5

4 files changed

Lines changed: 271 additions & 14 deletions

File tree

index.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
7+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8+
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
9+
<link rel="icon" href="https://healthdatasafe.github.io/style/images/Favicon/favicon.ico" type="image/x-icon">
10+
<link rel="stylesheet" type="text/css" href="https://healthdatasafe.github.io/style/hds.min.css">
11+
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400">
12+
<title>Demo Form HDS</title>
13+
</head>
14+
15+
<body>
16+
<div class="container">
17+
<img src="https://healthdatasafe.github.io/style/images/Horizontal/hds-logo-hz-1024x400-hz-color.png" alt="Logo" width="300px">
18+
<h1>Demo Form</h1>
19+
<table width="100%">
20+
<td>
21+
<div class="card-body">
22+
<h3><A HREF="dr.html">Dr's Page</A></h3>
23+
</div>
24+
</td>
25+
<td>
26+
<div class="card-body">
27+
<h3><A HREF="patient.html">Patient's Page</A></h3>
28+
</div>
29+
</td>
30+
</table>
31+
</div>
32+
</body>

patient-controler.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,64 @@
88

99
window.onload = (event) => {
1010
stateChange('loggedOut');
11-
drLib.showLoginButton('login-button', stateChange);
11+
patientLib.showLoginButton('login-button', stateChange);
12+
document.getElementById('submit-button').addEventListener("click", submitForm);
1213
};
1314

1415
function stateChange(state) {
1516
if (state === 'loggedIN') {
1617
document.getElementById('please-login').style.visibility = 'hidden';
17-
document.getElementById('data-view').style.visibility = 'visible';
18+
document.getElementById('card-form').style.visibility = 'visible';
19+
updateFormContent();
1820
} else {
1921
document.getElementById('please-login').style.visibility = 'visible';
20-
document.getElementById('data-view').style.visibility = 'hidden';
22+
document.getElementById('card-form').style.visibility = 'hidden';
2123
}
2224
}
25+
26+
27+
/**
28+
* Take the from content from the definition and actual values and create the HTML
29+
*/
30+
async function updateFormContent() {
31+
const formContent = await patientLib.getFormContent();
32+
console.log('Form content:', formContent);
33+
34+
document.getElementById('inputs-list').innerHTML = ''; // Clear previous content
35+
for (let i = 0; i < formContent.length; i++) {
36+
const formField = formContent[i];
37+
const fieldId = formField.id;
38+
const fieldValue = formField.value || '';
39+
const fieldType = formField.type;
40+
const fieldLabel = formField.label;
41+
42+
// Create the HTML for the form field
43+
let fieldHTML = `\n<BR><label for="${fieldId}">${fieldLabel}</label>`;
44+
if (fieldType === 'text' || fieldType === 'number') {
45+
fieldHTML += `<input type="${fieldType}" id="${fieldId}" value="${fieldValue}" class="form-control"/>`;
46+
} else if (fieldType === 'select') {
47+
fieldHTML += `<select id="${fieldId}">`;
48+
for (const option of fieldValue) {
49+
fieldHTML += `<option value="${option.value}">${option.label}</option>`;
50+
}
51+
fieldHTML += `</select>`;
52+
}
53+
// Append the HTML to the form
54+
document.getElementById('inputs-list').innerHTML += fieldHTML;
55+
}
56+
}
57+
58+
/**
59+
* Submit the form and send the data to the API
60+
*/
61+
async function submitForm() {
62+
const values = {};
63+
const formContent = await patientLib.getFormContent();
64+
for (let i = 0; i < formContent.length; i++) {
65+
const field = formContent[i];
66+
const fieldId = field.id;
67+
const fieldValue = document.getElementById(fieldId).value.trim();
68+
values[field.id] = fieldValue; // Store the value in the values object
69+
}
70+
await patientLib.handleFormSubmit(values);
71+
};

patient-lib.js

Lines changed: 172 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
let connection = null;
22

3-
const drLib = {
4-
showLoginButton
5-
3+
const patientLib = {
4+
showLoginButton,
5+
handleFormSubmit,
6+
getFormContent,
67
}
78

89
function showLoginButton (loginSpanId, stateChangeCallBack) {
@@ -14,15 +15,41 @@ function showLoginButton (loginSpanId, stateChangeCallBack) {
1415
requestingAppId: 'demo-dr-form-patient', // to customize for your own app
1516
requestedPermissions: [
1617
{
17-
streamId: '*',
18+
streamId: 'profile',
19+
defaultName: 'Profile',
20+
level: 'manage'
21+
},
22+
{
23+
streamId: 'family',
24+
defaultName: 'Family',
25+
level: 'manage'
26+
},
27+
{
28+
streamId: 'fertility',
29+
defaultName: 'Fertility',
30+
level: 'manage'
31+
},
32+
{
33+
streamId: 'body-height',
34+
defaultName: 'Body height',
35+
level: 'manage'
36+
},
37+
{
38+
streamId: 'body-weight',
39+
defaultName: 'Body weight',
1840
level: 'manage'
1941
}
2042
],
2143
clientData: {
2244
'app-web-auth:description': {
2345
'type': 'note/txt',
2446
'content': 'This app allows to fill a form and share information with your doctor.'
25-
}
47+
},
48+
'app-web-auth:ensureBaseStreams': [
49+
{id: 'body', name: 'Body metrics'},
50+
{id: 'body-height', name: 'Body height', parentId: 'body'},
51+
{id: 'body-weight', name: 'Body weight', parentId: 'body'}
52+
]
2653
},
2754
}
2855
};
@@ -45,7 +72,146 @@ function showLoginButton (loginSpanId, stateChangeCallBack) {
4572
}
4673
}
4774

75+
// Creates the streams structure for the patient account after the user has logged in
4876
async function initPatientAccount (connection) {
49-
77+
const patientBaseStreams = [
78+
// profile
79+
{id: 'profile-name', name: 'Name', parentId: 'profile'},
80+
{id: 'profile-nationality', name: 'Nationality', parentId: 'profile'},
81+
{id: 'profile-date-of-birth', name: 'Date of Birth', parentId: 'profile'},
82+
{id: 'profile-location', name: 'Location', parentId: 'profile'},
83+
{id: 'profile-sex', name: 'Sex', parentId: 'profile'},
84+
// family
85+
{id: 'family-children', name: 'Children', parentId: 'family'},
86+
// fertility
87+
{id: 'fertility-miscarriages', name: 'Miscarriages', parentId: 'fertility'},
88+
{id: 'fertility-traings', name: 'Trainings', parentId: 'fertility'},
89+
{id: 'fertility-cycles', name: 'Cycles', parentId: 'fertility'},
90+
{id: 'fertility-cycles-charted-extimation', name: 'Cycles charted estimation', parentId: 'fertility'},
91+
{id: 'fertility-ttc-tta', name: 'Trying to conceive / Avoiding pregnancy', parentId: 'fertility'},
92+
];
93+
const apiCalls = patientBaseStreams.map(stream => ({
94+
method: 'streams.create',
95+
params: {
96+
id: stream.id,
97+
name: stream.name,
98+
parentId: stream.parentId
99+
}
100+
}));
101+
// create stream structure (even if already exists)
102+
const res = await connection.api(apiCalls);
103+
console.log('## Patient account streams created', res);
50104
console.log('## Patient account initialized')
105+
}
106+
107+
// ---------------- form content ---------------- //
108+
109+
const formContent = [
110+
{
111+
streamId: 'profile-name',
112+
eventType: 'contact/name',
113+
contentField: 'name',
114+
type: 'text',
115+
label: 'Name',
116+
},
117+
{
118+
streamId: 'profile-name',
119+
eventType: 'contact/surname',
120+
contentField: 'surname',
121+
type: 'text',
122+
label: 'Surname',
123+
},
124+
{
125+
streamId: 'profile-nationality',
126+
eventType: 'contact/nationality',
127+
type: 'text',
128+
label: 'Nationality',
129+
},
130+
];
131+
132+
let formInitialized = null;
133+
async function getFormContent () {
134+
if (formInitialized) { return formContent; }
135+
formInitialized = true; // prevent multiple calls to this function
136+
137+
// get the values from the API
138+
const apiCalls = formContent.map(field => ({
139+
method: 'events.get',
140+
params: {
141+
streams: [field.streamId],
142+
types: [field.eventType],
143+
limit: 1,
144+
}
145+
}));
146+
147+
const res = await connection.api(apiCalls);
148+
for (let i = 0; i < res.length; i++) {
149+
const e = res[i];
150+
const field = formContent[i];
151+
field.id = 'field-' + i; // generate a unique id for the field
152+
console.log('## getFormContent ' + i, e);
153+
if (e.events && e.events.length > 0) {
154+
const event = e.events[0];
155+
field.value = event.content;
156+
field.eventId = event.id; // will allow t track if the event is to be updated
157+
}
158+
}
159+
return formContent;
160+
};
161+
162+
// ---------------- create / update data ---------------- //
163+
async function handleFormSubmit (values) {
164+
const apiCalls = [];
165+
for (const field of formContent) {
166+
const streamId = field.streamId;
167+
const eventType = field.eventType;
168+
const eventId = field.eventId;
169+
const value = values[field.id];
170+
171+
if (value === '' && eventId) {
172+
// delete the event
173+
apiCalls.push({
174+
method: 'events.delete',
175+
params: {
176+
id: eventId,
177+
}
178+
});
179+
continue;
180+
}
181+
182+
if (value === field.value || value === '') {
183+
// no change
184+
continue;
185+
}
186+
187+
if (eventId) {
188+
// update the event
189+
apiCalls.push({
190+
method: 'events.update',
191+
params: {
192+
id: eventId,
193+
update: {
194+
content: value
195+
}
196+
}
197+
});
198+
continue;
199+
}
200+
// create a new event
201+
apiCalls.push({
202+
method: 'events.create',
203+
params: {
204+
streamId: streamId,
205+
type: eventType,
206+
content: value,
207+
}
208+
});
209+
}
210+
if (apiCalls.length === 0) {
211+
console.log('## No changes to submit');
212+
return;
213+
}
214+
// send the API calls
215+
const res = await connection.api(apiCalls);
216+
console.log('## Form submitted', res);
51217
}

patient.html

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
88
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
9-
<link rel="stylesheet" type="text/css" href="https://api.pryv.com/style/pryv2.min.css">
9+
<link rel="icon" href="https://healthdatasafe.github.io/style/images/Favicon/favicon.ico" type="image/x-icon">
10+
<link rel="stylesheet" type="text/css" href="https://healthdatasafe.github.io/style/hds.min.css">
1011
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400">
1112
<title>Demo Form - Patient's page</title>
1213
</head>
@@ -34,11 +35,20 @@ <h2 class="card-title">Welcome</h2>
3435
</span>
3536
</div>
3637
</div>
37-
<div class="card" id="data-view" style="visibility: hidden;">
38-
Data
38+
<div class="card" id="card-form" style="visibility: hidden;">
39+
<form id="form">
40+
<h2 class="card-title">Form</h2>
41+
<div class="form-group">
42+
<label for="input-bp">
43+
Please ...
44+
</label>
45+
<div class="input-group" id="inputs-list">
46+
<!-- HERE WILL GO THE INPUTS-->
47+
</div>
48+
</div>
49+
<button type="button" id="submit-button" class="btn btn-primary mb-2">Submit</button>
50+
</form>
3951
</div>
40-
41-
4252
</div>
4353
</body>
4454

0 commit comments

Comments
 (0)