Files
bio-performx/app/templates/upload.html
T
2025-11-26 22:17:30 +01:00

387 lines
20 KiB
HTML

{% extends "base.html" %} {% block title %}Upload Patient Data - Report
Generator{% endblock %} {% block content %}
<div class="px-4 py-6 sm:px-0">
<div class="bg-white shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<h2 class="text-2xl font-bold text-gray-900 mb-6">
Upload Patient Data and Files
</h2>
{% if error %}
<div class="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
<p class="text-red-800">{{ error }}</p>
</div>
{% endif %}
<form
id="upload-form"
action="/upload"
method="post"
enctype="multipart/form-data"
class="space-y-6"
>
<!-- Patient Information Section -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">
Patient Information
</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label
for="first_name"
class="block text-sm font-medium text-gray-700"
>First Name</label
>
<input
type="text"
name="first_name"
id="first_name"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
/>
</div>
<div>
<label
for="last_name"
class="block text-sm font-medium text-gray-700"
>Last Name</label
>
<input
type="text"
name="last_name"
id="last_name"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
/>
</div>
<div>
<label
for="age"
class="block text-sm font-medium text-gray-700"
>Age</label
>
<input
type="number"
name="age"
id="age"
required
min="1"
max="120"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
/>
</div>
<div>
<label
for="height"
class="block text-sm font-medium text-gray-700"
>Height (e.g., 5'4" or 165cm)</label
>
<input
type="text"
name="height"
id="height"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
placeholder="5'4&quot;"
/>
</div>
<div>
<label
for="weight"
class="block text-sm font-medium text-gray-700"
>Weight (e.g., 123lbs or 56kg)</label
>
<input
type="text"
name="weight"
id="weight"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
placeholder="123lbs"
/>
</div>
<div>
<label
for="gender"
class="block text-sm font-medium text-gray-700"
>Gender</label
>
<select
name="gender"
id="gender"
required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
>
<option value="">Select...</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label
for="focus"
class="block text-sm font-medium text-gray-700"
>Training Focus</label
>
<input
type="text"
name="focus"
id="focus"
value="Endurance"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
/>
</div>
<div>
<label
for="session_id"
class="block text-sm font-medium text-gray-700"
>Session ID</label
>
<input
type="text"
name="session_id"
id="session_id"
value="default"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
/>
</div>
<div>
<label
class="block text-sm font-medium text-gray-700 mb-2"
>Report Type</label
>
<div class="mt-1 space-y-2">
<div class="flex items-center">
<input
type="radio"
name="report_type"
id="report_type_full"
value="full"
checked
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
/>
<label
for="report_type_full"
class="ml-2 block text-sm text-gray-700"
>
Full Report
</label>
</div>
<div class="flex items-center">
<input
type="radio"
name="report_type"
id="report_type_minimal"
value="minimal"
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300"
/>
<label
for="report_type_minimal"
class="ml-2 block text-sm text-gray-700"
>
Minimal Report
</label>
</div>
</div>
</div>
<div>
<label
class="block text-sm font-medium text-gray-700"
>Recommended Next Testing Date</label
>
<div class="mt-1 grid grid-cols-2 gap-3">
<select
id="next_testing_month"
required
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
>
<option value="">Month</option>
<option value="January">January</option>
<option value="February">February</option>
<option value="March">March</option>
<option value="April">April</option>
<option value="May">May</option>
<option value="June">June</option>
<option value="July">July</option>
<option value="August">August</option>
<option value="September">September</option>
<option value="October">October</option>
<option value="November">November</option>
<option value="December">December</option>
</select>
<select
id="next_testing_year"
required
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
>
<option value="">Year</option>
</select>
</div>
<input
type="hidden"
name="next_testing_date"
id="next_testing_date"
required
/>
</div>
<script>
// Populate year dropdown
(function () {
const yearSelect =
document.getElementById(
"next_testing_year"
);
const currentYear = new Date().getFullYear();
for (
let i = currentYear;
i <= currentYear + 10;
i++
) {
const option =
document.createElement("option");
option.value = i;
option.textContent = i;
yearSelect.appendChild(option);
}
// Combine month and year into hidden input
const monthSelect =
document.getElementById(
"next_testing_month"
);
const dateInput =
document.getElementById(
"next_testing_date"
);
function updateDateInput() {
const month = monthSelect.value;
const year = yearSelect.value;
if (month && year) {
dateInput.value = month + " " + year;
} else {
dateInput.value = "";
}
}
monthSelect.addEventListener(
"change",
updateDateInput
);
yearSelect.addEventListener(
"change",
updateDateInput
);
// Validate form submission
const form =
document.getElementById("upload-form");
form.addEventListener("submit", function (e) {
const month = monthSelect.value;
const year = yearSelect.value;
if (!month || !year) {
e.preventDefault();
alert(
"Please select both month and year for the recommended next testing date."
);
return false;
}
// Ensure hidden input is set before submission
updateDateInput();
});
})();
</script>
</div>
</div>
<!-- File Upload Section -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">
Upload Files
</h3>
<div class="space-y-4">
<div>
<label
for="spirometry_pdf"
class="block text-sm font-medium text-gray-700"
>Spirometry PDF</label
>
<input
type="file"
name="spirometry_pdf"
id="spirometry_pdf"
accept=".pdf"
required
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100"
/>
</div>
<div>
<label
for="pnoe_csv"
class="block text-sm font-medium text-gray-700"
>Pnoe CSV</label
>
<input
type="file"
name="pnoe_csv"
id="pnoe_csv"
accept=".csv"
required
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100"
/>
</div>
<div>
<label
for="fat_percentage"
class="block text-sm font-medium text-gray-700"
>Body Fat Percentage (%)</label
>
<input
type="number"
step="0.1"
name="fat_percentage"
id="fat_percentage"
required
min="0"
max="100"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm px-3 py-2 border"
placeholder="22.5"
/>
</div>
<div>
<label
for="oxygenation_csv"
class="block text-sm font-medium text-gray-700"
>Muscle Oxygenation CSV (Optional)</label
>
<input
type="file"
name="oxygenation_csv"
id="oxygenation_csv"
accept=".csv"
class="mt-1 block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100"
/>
<p class="mt-1 text-xs text-gray-500">
Upload NIRS muscle oxygen CSV file to generate
TSI graph
</p>
</div>
</div>
</div>
<!-- Submit Button -->
<div class="flex justify-end">
<button
type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Generate Report
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}