210 lines
7.8 KiB
HTML
210 lines
7.8 KiB
HTML
{% extends 'core/base.html' %}
|
|
{% load static %}
|
|
{% load widget_tweaks %}
|
|
{% block title %}
|
|
Medwings | Take a measurement
|
|
{% endblock title %}
|
|
|
|
{% block content %}
|
|
<div class="flex flex-col justify-center items-center gap-2 py-4 mx-4 max-w-4xl">
|
|
<h1>Record your health status</h1>
|
|
<div id="help-div" class="flex flex-col gap-2 items-center justify-center call-to-action-box w-full text-center sm:text-start h-32">
|
|
<p class="fadeout font-semibold">Please start measuring your vitals using your devices now.</p>
|
|
<p class="fadeout">Your measurement results will be synchronized automatically.</p>
|
|
<p class="fadein hidden font-semibold text-success-200">All done! Thank you for taking a measurement.</p>
|
|
<a class="btn-outline fadein hidden" href="{% url 'dashboard' %}">Go to Dashboard</a>
|
|
</div>
|
|
<div id="pageContainer" class="grid grid-cols-3 gap-6 text-xl justify-center items-center w-full p-4 border border-secondary rounded-md overflow-hidden relative">
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>Blood Pressure (systolic)</p>
|
|
</div>
|
|
<div id="bloodPressureLoader" class="loader loader-bar loader--loading"></div>
|
|
<div id="bloodPressureValue" class="loader loader-value hidden">
|
|
<p><span id="bloodPressureValueNumber"></span> mmHG</p>
|
|
</div>
|
|
|
|
<div class="col-span-3 h-px bg-secondary"></div>
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>Body Temperature</p>
|
|
</div>
|
|
<div id="bodyTempLoader" class="loader loader-bar loader--loading"></div>
|
|
<div id="bodyTempValue" class="loader loader-value hidden">
|
|
<p><span id="bodyTempValueNumber"></span> °C</p>
|
|
</div>
|
|
|
|
<div class="col-span-3 h-px bg-secondary"></div>
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>Heart Rate</p>
|
|
</div>
|
|
<div id="heartRateLoader" class="loader loader-bar loader--loading"></div>
|
|
<div id="heartRateValue" class="loader loader-value hidden">
|
|
<p><span id="heartRateValueNumber"></span> bpm</p>
|
|
</div>
|
|
|
|
<div class="col-span-3 h-px bg-secondary"></div>
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>Blood Oxygenation</p>
|
|
</div>
|
|
<div id="spo2Loader" class="loader loader-bar loader--loading"></div>
|
|
<div id="spo2Value" class="loader loader-value hidden">
|
|
<p><span id="spo2ValueNumber"></span> %</p>
|
|
</div>
|
|
|
|
<div class="col-span-3 h-px bg-secondary"></div>
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>Respiration Score</p>
|
|
</div>
|
|
<div id="respirationScoreLoader" class="loader loader-bar loader--loading"></div>
|
|
<div id="respirationScoreValue" class="loader loader-value hidden">
|
|
<p><span id="respirationScoreValueNumber"></span></p>
|
|
</div>
|
|
|
|
<div class="col-span-3 h-0.5 bg-secondary"></div>
|
|
<div class="font-semibold text-center sm:text-start col-span-2">
|
|
<p>MEWS</p>
|
|
</div>
|
|
<div id="mewsLoader" class="loader loader-bar loader--loading"></div>
|
|
<div id="mewsValue" class="loader loader-value hidden">
|
|
<p><span id="mewsValueNumber"></span></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
const elements = {
|
|
"bloodPressure": {
|
|
"loader": document.getElementById("bloodPressureLoader"),
|
|
"value": document.getElementById("bloodPressureValue"),
|
|
"number": document.getElementById("bloodPressureValueNumber")
|
|
},
|
|
"bodyTemp": {
|
|
"loader": document.getElementById("bodyTempLoader"),
|
|
"value": document.getElementById("bodyTempValue"),
|
|
"number": document.getElementById("bodyTempValueNumber")
|
|
},
|
|
"heartRate": {
|
|
"loader": document.getElementById("heartRateLoader"),
|
|
"value": document.getElementById("heartRateValue"),
|
|
"number": document.getElementById("heartRateValueNumber")
|
|
},
|
|
"spo2": {
|
|
"loader": document.getElementById("spo2Loader"),
|
|
"value": document.getElementById("spo2Value"),
|
|
"number": document.getElementById("spo2ValueNumber")
|
|
},
|
|
"respirationScore": {
|
|
"loader": document.getElementById("respirationScoreLoader"),
|
|
"value": document.getElementById("respirationScoreValue"),
|
|
"number": document.getElementById("respirationScoreValueNumber")
|
|
},
|
|
"mews": {
|
|
"loader": document.getElementById("mewsLoader"),
|
|
"value": document.getElementById("mewsValue"),
|
|
"number": document.getElementById("mewsValueNumber")
|
|
},
|
|
}
|
|
|
|
function showError(message) {
|
|
let pageContainerDiv = document.getElementById("pageContainer");
|
|
pageContainerDiv.innerHTML = `<div class="col-span-3 flex justify-center items-center status-message error"><p>${message}</p></div>`
|
|
}
|
|
|
|
const pageTimeout = 10 * 60 * 1000;
|
|
setTimeout(() => {
|
|
if (!fetchingComplete)
|
|
showError('Your measurement timed out. Please <a class="underline" href="/mews/init/">start again</a>.')
|
|
}, pageTimeout);
|
|
|
|
let fetchingData = false;
|
|
let fetchingComplete = false;
|
|
const pollingInterval = 5000;
|
|
let currentData = {
|
|
"blood_pressure_value": null,
|
|
"body_temp_value": null,
|
|
"heart_rate_value": null,
|
|
"spo2_level_value": null,
|
|
"respiration_score_value": null,
|
|
"mews_value": null
|
|
};
|
|
|
|
const helpDiv = document.getElementById('help-div');
|
|
|
|
async function fetchData() {
|
|
if (fetchingData || fetchingComplete) return;
|
|
|
|
fetchingFata = true;
|
|
fetch("{% url 'mews-status' %}")
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('There was an error while retrieving your data.');
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
const names = {
|
|
"blood_pressure_value": "bloodPressure",
|
|
"body_temp_value": "bodyTemp",
|
|
"heart_rate_value": "heartRate",
|
|
"spo2_level_value": "spo2",
|
|
"respiration_score_value": "respirationScore",
|
|
"mews_value": "mews"
|
|
}
|
|
|
|
for (let type of Object.keys(names)) {
|
|
if (currentData[type] === null && data[type] !== null) {
|
|
currentData[type] = data[type];
|
|
setTimeout(() => {
|
|
loadValue(names[type], data[type])
|
|
}, Math.floor(Math.random() * (1500 - 500 + 1)) + 500);
|
|
}
|
|
}
|
|
|
|
if (Object.values(currentData).every(value => value !== null)) {
|
|
fetchingComplete = true;
|
|
|
|
helpDiv.classList.add('help-div--changing');
|
|
for (let element of document.getElementsByClassName('fadeout')) {
|
|
element.addEventListener('animationend', () => {
|
|
element.remove();
|
|
for (let element of document.getElementsByClassName('fadein')) {
|
|
element.classList.remove('hidden');
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
fetchingData = false;
|
|
|
|
if (!fetchingComplete) {
|
|
setTimeout(() => {
|
|
fetchData();
|
|
}, pollingInterval)
|
|
}
|
|
})
|
|
.catch(error => {
|
|
showError(error)
|
|
});
|
|
}
|
|
|
|
|
|
fetchData();
|
|
|
|
function loadValue(element, value) {
|
|
const loaderDiv = elements[element]["loader"];
|
|
const valueDiv = elements[element]["value"];
|
|
const numberSpan = elements[element]["number"];
|
|
|
|
loaderDiv.classList.remove("loader--loading");
|
|
loaderDiv.classList.add("loader--finished");
|
|
|
|
setTimeout(function() {
|
|
loaderDiv.classList.remove("loader--finished");
|
|
loaderDiv.classList.add("hidden");
|
|
|
|
valueDiv.classList.remove('hidden');
|
|
valueDiv.classList.add('loader--value');
|
|
numberSpan.textContent = value;
|
|
|
|
}, 2000);
|
|
}
|
|
</script>
|
|
{% endblock content %}
|