Files
bio-performx/app/templates/edit.html
T
bolade 83f50882e2 Add HTML templates for medical report generator with navigation, upload, edit, and preview functionalities
- Created base template with navigation and layout structure
- Implemented upload.html for patient data and file uploads
- Developed edit.html for editing calculated metrics
- Added preview.html for displaying generated report previews
- Enhanced user experience with Tailwind CSS styling
2025-11-17 17:15:44 +01:00

198 lines
15 KiB
HTML

{% extends "base.html" %}
{% block title %}Edit Metrics - Report Generator{% endblock %}
{% block content %}
<div class="px-4 py-6 sm:px-0">
{% if not session.get('metrics') %}
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-6">
<p class="text-yellow-800">No metrics found. Please <a href="/" class="underline">generate a report</a> first.</p>
</div>
{% else %}
{% 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 %}
<div class="bg-white shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold text-gray-900">Edit Calculated Metrics</h2>
<a href="/preview" class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
Back to Preview
</a>
</div>
<form action="/edit" method="post" class="space-y-8">
<!-- Pnoe Metrics Section -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Pnoe Metrics</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label for="vo2_max" class="block text-sm font-medium text-gray-700">VO2 Max (ml/min)</label>
<input type="number" step="0.01" name="vo2_max" id="vo2_max"
value="{{ '%.2f'|format(session.metrics.pnoe['vo2_max']) if session.metrics.pnoe.get('vo2_max') else '' }}"
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="vo2_max_per_kg" class="block text-sm font-medium text-gray-700">VO2 Max per kg (ml/min/kg)</label>
<input type="number" step="0.01" name="vo2_max_per_kg" id="vo2_max_per_kg"
value="{{ '%.2f'|format(session.metrics.pnoe['vo2_max_per_kg']) if session.metrics.pnoe.get('vo2_max_per_kg') else '' }}"
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="peak_vt" class="block text-sm font-medium text-gray-700">Peak VT (L)</label>
<input type="number" step="0.01" name="peak_vt" id="peak_vt"
value="{{ '%.2f'|format(session.metrics.pnoe['peak_vt']) if session.metrics.pnoe.get('peak_vt') else '' }}"
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="peak_vt_hr" class="block text-sm font-medium text-gray-700">Peak VT HR (bpm)</label>
<input type="number" step="1" name="peak_vt_hr" id="peak_vt_hr"
value="{{ '%.0f'|format(session.metrics.pnoe['peak_vt_hr']) if session.metrics.pnoe.get('peak_vt_hr') else '' }}"
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="fat_max_value" class="block text-sm font-medium text-gray-700">Fat Max Value (kcal/min)</label>
<input type="number" step="0.01" name="fat_max_value" id="fat_max_value"
value="{{ '%.2f'|format(session.metrics.pnoe['fat_max_value']) if session.metrics.pnoe.get('fat_max_value') else '' }}"
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="fat_max_hr" class="block text-sm font-medium text-gray-700">Fat Max HR (bpm)</label>
<input type="number" step="1" name="fat_max_hr" id="fat_max_hr"
value="{{ '%.0f'|format(session.metrics.pnoe['fat_max_hr']) if session.metrics.pnoe.get('fat_max_hr') else '' }}"
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>
</div>
<!-- VT1 Section -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">VT1 Threshold</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-3">
<div>
<label for="vt1_hr" class="block text-sm font-medium text-gray-700">Heart Rate (bpm)</label>
<input type="number" step="1" name="vt1_hr" id="vt1_hr"
value="{{ '%.0f'|format(session.metrics.pnoe['vt1']['HeartRate']) if session.metrics.pnoe.get('vt1') and session.metrics.pnoe['vt1'].get('HeartRate') else '' }}"
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="vt1_speed" class="block text-sm font-medium text-gray-700">Speed (mph)</label>
<input type="number" step="0.01" name="vt1_speed" id="vt1_speed"
value="{{ '%.2f'|format(session.metrics.pnoe['vt1']['Speed']) if session.metrics.pnoe.get('vt1') and session.metrics.pnoe['vt1'].get('Speed') else '' }}"
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="vt1_time" class="block text-sm font-medium text-gray-700">Time (sec)</label>
<input type="number" step="1" name="vt1_time" id="vt1_time"
value="{{ '%.0f'|format(session.metrics.pnoe['vt1']['Time']) if session.metrics.pnoe.get('vt1') and session.metrics.pnoe['vt1'].get('Time') else '' }}"
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>
</div>
<!-- VT2 Section -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">VT2 Threshold</h3>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-3">
<div>
<label for="vt2_hr" class="block text-sm font-medium text-gray-700">Heart Rate (bpm)</label>
<input type="number" step="1" name="vt2_hr" id="vt2_hr"
value="{{ '%.0f'|format(session.metrics.pnoe['vt2']['HeartRate']) if session.metrics.pnoe.get('vt2') and session.metrics.pnoe['vt2'].get('HeartRate') else '' }}"
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="vt2_speed" class="block text-sm font-medium text-gray-700">Speed (mph)</label>
<input type="number" step="0.01" name="vt2_speed" id="vt2_speed"
value="{{ '%.2f'|format(session.metrics.pnoe['vt2']['Speed']) if session.metrics.pnoe.get('vt2') and session.metrics.pnoe['vt2'].get('Speed') else '' }}"
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="vt2_time" class="block text-sm font-medium text-gray-700">Time (sec)</label>
<input type="number" step="1" name="vt2_time" id="vt2_time"
value="{{ '%.0f'|format(session.metrics.pnoe['vt2']['Time']) if session.metrics.pnoe.get('vt2') and session.metrics.pnoe['vt2'].get('Time') else '' }}"
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>
</div>
<!-- Heart Rate Zones -->
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Heart Rate Zones</h3>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-5">
{% for i in range(1, 6) %}
{% set zone_key = "zone" + i|string + "_bpm" %}
<div>
<label for="{{ zone_key }}" class="block text-sm font-medium text-gray-700">Zone {{ i }} (e.g., 120-140bpm)</label>
<input type="text" name="{{ zone_key }}" id="{{ zone_key }}"
value="{{ session.metrics.pnoe[zone_key] if session.metrics.pnoe.get(zone_key) else '' }}"
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>
{% endfor %}
</div>
</div>
<!-- Spirometry Metrics -->
{% if session.metrics.spirometry %}
<div class="border-b border-gray-200 pb-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Spirometry Metrics</h3>
<div class="space-y-4">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<label for="fvc_best" class="block text-sm font-medium text-gray-700">FVC Best (L)</label>
<input type="number" step="0.01" name="fvc_best" id="fvc_best"
value="{{ '%.2f'|format(session.metrics.spirometry['fvc_best']) if session.metrics.spirometry.get('fvc_best') else '' }}"
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="fvc_pred" class="block text-sm font-medium text-gray-700">FVC % Predicted</label>
<input type="number" step="0.1" name="fvc_pred" id="fvc_pred"
value="{{ '%.1f'|format(session.metrics.spirometry['fvc_pred']) if session.metrics.spirometry.get('fvc_pred') else '' }}"
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="fev1_best" class="block text-sm font-medium text-gray-700">FEV1 Best (L)</label>
<input type="number" step="0.01" name="fev1_best" id="fev1_best"
value="{{ '%.2f'|format(session.metrics.spirometry['fev1_best']) if session.metrics.spirometry.get('fev1_best') else '' }}"
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="fev1_pred" class="block text-sm font-medium text-gray-700">FEV1 % Predicted</label>
<input type="number" step="0.1" name="fev1_pred" id="fev1_pred"
value="{{ '%.1f'|format(session.metrics.spirometry['fev1_pred']) if session.metrics.spirometry.get('fev1_pred') else '' }}"
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="fev1_fvc_pct_best" class="block text-sm font-medium text-gray-700">FEV1/FVC% Best</label>
<input type="number" step="0.01" name="fev1_fvc_pct_best" id="fev1_fvc_pct_best"
value="{{ '%.2f'|format(session.metrics.spirometry['fev1_fvc_pct_best']) if session.metrics.spirometry.get('fev1_fvc_pct_best') else '' }}"
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="fev1_fvc_pct_pred" class="block text-sm font-medium text-gray-700">FEV1/FVC% % Predicted</label>
<input type="number" step="0.1" name="fev1_fvc_pct_pred" id="fev1_fvc_pct_pred"
value="{{ '%.1f'|format(session.metrics.spirometry['fev1_fvc_pct_pred']) if session.metrics.spirometry.get('fev1_fvc_pct_pred') else '' }}"
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>
</div>
</div>
{% endif %}
<!-- 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">
Regenerate Report
</button>
</div>
</form>
</div>
</div>
{% endif %}
</div>
{% endblock %}