-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase.js
More file actions
384 lines (314 loc) · 15.3 KB
/
database.js
File metadata and controls
384 lines (314 loc) · 15.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
let db;
// Open or create an IndexedDB with the name PatientsDB
function openDB() {
let request = indexedDB.open('patientsDB', 5);
request.onupgradeneeded = function(event) {
db = event.target.result;
// Create patients object store if it doesn't exist
if (!db.objectStoreNames.contains('patients')) {
let objectStore = db.createObjectStore('patients', { keyPath: 'id', autoIncrement: true });
}
// Create userLogins object store for patient login details
if (!db.objectStoreNames.contains('userLogins')) {
let loginStore = db.createObjectStore('userLogins', { keyPath: 'id' });
}
};
request.onsuccess = function(event) {
db = event.target.result;
console.log('Database opened successfully'); // if db successfully executes and opens then prints this to console log
fetchAndStorePatients(); // call and run function
populatePatientSelect(); // call and run function to populate data in select dropdown
};
request.onerror = function(event) {
console.error('Database error:', event.target.errorCode);
};
}
// Hash a password using SHA-256
async function hashPassword(password) {
const encoder = new TextEncoder();
const data = encoder.encode(password);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
}
// Function to add a new patient via the form
function addPatient() {
let nhs = document.getElementById('nhs').value;
let title = document.getElementById('title').value;
let first = document.getElementById('first').value;
let last = document.getElementById('last').value;
let dob = document.getElementById('dob').value;
let gender = document.getElementById('gender').value;
let address = document.getElementById('address').value;
let email = document.getElementById('email').value;
let telephone = document.getElementById('telephone').value;
// Start a transaction to get the next available ID
let transaction = db.transaction(['patients'], 'readwrite');
let objectStore = transaction.objectStore('patients');
// Get all patients and find the next available ID
let request = objectStore.getAll();
request.onsuccess = function(event) {
let allPatients = event.target.result;
let nextId = allPatients.length > 0 ? allPatients[allPatients.length - 1].id + 1 : 1;
// Create a new patient object with all form data and auto-incremented id
let newPatient = {
id: nextId, // assign the next available id
NHS: nhs,
Title: title,
First: first,
Last: last,
DOB: dob,
Gender: gender,
Address: address,
Email: email,
Telephone: telephone
};
// Add the new patient to the object store
objectStore.add(newPatient);
transaction.oncomplete = function() {
console.log('New patient added successfully');
alert('Patient added successfully!');
};
transaction.onerror = function(event) {
console.error('Error adding new patient:', event.target.error);
};
};
// Reset the form after submission
document.getElementById('patientForm').reset();
return false; // Prevent default form submission
}
// Fetch patients data from the JSON URL and store it in IndexedDB
function fetchAndStorePatients() {
fetch('https://jsethi-mdx.github.io/cst2572.github.io/patients.json')
.then(response => response.json())
.then(data => {
let batchSize = 20; // Handle data in small parts
let totalBatches = Math.ceil(data.length / batchSize);
for (let i = 0; i < totalBatches; i++) {
let batch = data.slice(i * batchSize, (i + 1) * batchSize);
let transaction = db.transaction(['patients'], 'readwrite');
let objectStore = transaction.objectStore('patients');
batch.forEach(patient => {
// Check if the patient already exists by using their 'id'
let checkRequest = objectStore.get(patient.id);
checkRequest.onsuccess = function(event) {
if (!event.target.result) {
// If patient does not exist, add it to the object store
objectStore.add(patient);
} else {
console.log(`Patient with id ${patient.id} already exists.`);
}
};
checkRequest.onerror = function(event) {
console.error('Error checking patient:', event.target.error);
};
});
transaction.oncomplete = function() {
console.log(`Batch ${i + 1} of ${totalBatches} processed successfully.`);
};
transaction.onerror = function(event) {
console.error('Error processing batch:', event.target.error);
};
}
})
.catch(error => console.error('Fetch error:', error));
}
// Load patient data and use OOP to access values
function loadPatientData() {
const patientId = document.getElementById('patientSelect').value;
const transaction = db.transaction(['patients'], 'readonly');
const store = transaction.objectStore('patients');
const request = store.get(parseInt(patientId)); // Convert patient ID into integer
console.log(`Selected Patient ID: ${patientId}`);
request.onsuccess = function(event) {
const patient = event.target.result;
if (patient) {
// Ensure the property names here match the object structure in IndexedDB
document.getElementById('first_name').value = patient.First; // First name
document.getElementById('last_name').value = patient.Last; // Last name
document.getElementById('email').value = patient.Email; // Email address
document.getElementById('gender').value = patient.Gender; // Gender
document.getElementById('address').value = patient.Address; // Address
document.getElementById('telephone').value = patient.Telephone; // Telephone
} else {
alert("Patient not found.");
}
};
// error handling
request.onerror = function(event) {
console.error("Error loading patient data:", event.target.error);
};
}
// Function to populate the patient select dropdown
function populatePatientSelect() {
const patientSelect = document.getElementById('patientSelect');
const transaction = db.transaction(['patients'], 'readonly');
const objectStore = transaction.objectStore('patients');
const request = objectStore.getAll(); // Get all patients
request.onsuccess = function(event) {
const patients = event.target.result;
// if patient select box exists on current page
if (patientSelect) {
// for each patient loop through each item and output as an <option> into the <select> box
patients.forEach(patient => {
const option = document.createElement('option');
option.value = patient.id; // Use patient id as the value
option.textContent = `${patient.First} ${patient.Last}`; // Display full name using backticks
patientSelect.appendChild(option); // Add option to the select element
});
}
};
request.onerror = function(event) {
console.error('Error loading patients:', event.target.error);
};
}
async function createPatientLoginDetails() {
// Get the selected patient ID, username, and password from the form
let patientId = document.getElementById('patientSelect').value;
let username = document.getElementById('username').value;
let password = document.getElementById('password').value;
// Hash the password for security
let hashedPassword = await hashPassword(password);
// Transaction on the patients and userLogins object stores
let transaction = db.transaction(['patients', 'userLogins'], 'readwrite');
let patientStore = transaction.objectStore('patients');
let loginStore = transaction.objectStore('userLogins');
// Get the patient based on the selected patient's ID
let request = patientStore.get(parseInt(patientId)); // convert to integer
request.onsuccess = function(event) {
let patient = event.target.result; // Get the patient object
if (patient) {
// Create a login record
let loginDetails = {
id: patient.id, // Reuse the patient's ID as the key
username: username,
password: hashedPassword,
NHS: patient.NHS // The patient's NHS value
};
// Attempt to add the login details to the userLogins store within DB
let loginRequest = loginStore.add(loginDetails);
loginRequest.onsuccess = function() {
alert("Account details created successfully for patient! The NHS number has been successfully linked to the user account.");
// display alert to user to notify success
};
// error event handling
loginRequest.onerror = function(event) {
console.error("Error creating user login details: ", event.target.error);
alert("Error creating user login details."); // display alert to user
};
} else {
alert("Selected patient does not exist."); // display alert to user
}
};
request.onerror = function(event) {
console.error("Error fetching patient: ", event.target.error);
};
// Reset the form after submission
document.getElementById("patientLoginForm").reset();
return false; // Prevent default form submission
}
// Add new function to handle the edit patient form page
function editPatient() {
const patientId = document.getElementById('patientSelect').value; // get value of selected patient and get the ID
const updatedPatient = {
id: parseInt(patientId),
first_name: document.getElementById('first_name').value,
last_name: document.getElementById('last_name').value,
email: document.getElementById('email').value,
gender: document.getElementById('gender').value,
address: document.getElementById('address').value,
telephone: document.getElementById('telephone').value
};
const transaction = db.transaction(["patients"], "readwrite");
const store = transaction.objectStore("patients"); // access patients object store
const request = store.put(updatedPatient);
request.onsuccess = function() {
alert("Patient updated successfully!"); // using alert() function to display notification popup
location.reload(); // Reload the page to see the updated data
};
request.onerror = function() {
alert("Error updating patient.");
};
}
// Delete patient from DB
function deletePatient() {
const patientId = document.getElementById('patientSelect').value;
// Confirm before deletion
if (confirm("Are you sure you want to delete this patient?")) {
// Start a transaction on 'patients' object store
const transaction = db.transaction(['patients'], 'readwrite');
const objectStore = transaction.objectStore('patients');
// Delete patient based on ID selected in dropdown
const deleteRequest = objectStore.delete(parseInt(patientId)); // Convert patient ID to integer
deleteRequest.onsuccess = function() {
alert("Patient deleted successfully!");
location.reload(); // Reload the page to reflect the patient being deleted to avoid existing data displaying
};
deleteRequest.onerror = function(event) {
console.error("Error deleting patient:", event.target.error);
alert("Error deleting patient.");
};
}
}
async function validateLogin() {
let username = document.getElementById('username').value.trim(); // Trim to avoid whitespace issues
let password = document.getElementById('password').value; // get value of password field
const hashedPassword = await hashPassword(password); // Hash the inputted password
// console.log("Input password (hashed):", hashedPassword); // removing this now for security reasons as it was for debugging
let transaction = db.transaction(['userLogins'], 'readonly');
let objectStore = transaction.objectStore('userLogins'); // access userLogins object store
let request = objectStore.getAll(); // Get all user logins
request.onsuccess = function(event) {
let users = event.target.result;
// console.log("Retrieved users from IndexedDB:", users);
// Find the matching user
let user = users.find(u => u.username === username && u.password === hashedPassword);
if (user) {
alert("Login successful");
// Save logged-in status and other details
localStorage.setItem('isPatientLoggedIn', 'true');
localStorage.setItem('loggedInUsername', username);
localStorage.setItem('loggedInUserId', user.id);
window.location.href = 'admin.html'; // Redirect after login
} else {
alert("Invalid login details");
}
};
// error handling for failing to get users
request.onerror = function(event) {
console.error("Error getting users from DB:", event.target.error);
alert("Login failed. Please try again."); // display alert msg to user
};
}
// Function to update the username field when a doctor is selected
function updateUsername() {
const doctorId = document.getElementById('patientSelect').value; // get value of patientSelect <select> dropdown
if (doctorId) {
const transaction = db.transaction(['patients'], 'readonly');
const objectStore = transaction.objectStore('patients'); // access object store called patients
const request = objectStore.get(parseInt(doctorId)); // convert doctor ID to integer
request.onsuccess = function(event) {
const doctor = event.target.result;
if (doctor) {
// Populate the username field with the doctor's email
document.getElementById('username').value = doctor.Email;
// console.log("Selected patient ID:", doctor.Email); // commenting this out now as no longer need to output this to console log
}
};
}
}
// DOMCONTENTLOADED: run the following code when the html page has been fully loaded
// Attach the updateUsername function to the change event of the doctorSelect dropdown
document.addEventListener('DOMContentLoaded', () => {
const doctorSelect = document.getElementById('patientSelect');
// If patient <select> box exists then run the following conditional logic
if (doctorSelect) {
doctorSelect.addEventListener('change', updateUsername);
} else {
return; // break out
}
});
// Start the database when the page loads
window.onload = function() {
openDB(); // open and execute database
};