Files
medicaltracker/public/tracker.php
T
2026-07-03 18:00:34 -04:00

602 lines
36 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/../app/bootstrap.php';
if (!app_tracker_area_enabled()) {
http_response_code(404);
$pageTitle = 'Tracker Unavailable | Medical Tracker';
$activePage = '';
require __DIR__ . '/partials/site-header.php';
?>
<main>
<section class="admin-public-shell record-shell">
<p class="site-eyebrow">Private area disabled</p>
<h1>Tracker is not available.</h1>
<p>This public site is currently configured for reference browsing only.</p>
<a class="site-primary" href="/">Return home</a>
</section>
</main>
<?php
require __DIR__ . '/partials/site-footer.php';
exit;
}
app_db();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Medical Tracker</title>
<link rel="stylesheet" href="/assets/styles.css">
</head>
<body data-theme="dark" data-accent="green">
<div class="app-shell">
<header class="topbar">
<div class="brand-block">
<div class="brand-mark" aria-hidden="true">
<span></span>
<span></span>
<span></span>
</div>
<div>
<h1>Medical Tracker</h1>
<p id="profileFocus">Loading profile</p>
</div>
</div>
<div class="topbar-controls">
<label class="field compact-field">
<span>Profile</span>
<select id="profileSelect"></select>
</label>
<div class="segmented" aria-label="Planner scope">
<button type="button" data-view="daily">Daily</button>
<button type="button" data-view="weekly">Weekly</button>
<button type="button" data-view="monthly">Monthly</button>
</div>
<label class="field date-field">
<span>Date</span>
<input id="datePicker" type="date">
</label>
</div>
</header>
<main>
<section class="control-strip">
<div class="range-copy" id="rangeCopy">Loading range</div>
<div class="theme-controls">
<div class="toggle-group" aria-label="Theme mode">
<button type="button" id="darkModeButton">Dark</button>
<button type="button" id="lightModeButton">Light</button>
</div>
<div class="accent-swatches" aria-label="Accent color">
<button type="button" data-accent="green" title="Green"></button>
<button type="button" data-accent="blue" title="Blue"></button>
<button type="button" data-accent="red" title="Red"></button>
<button type="button" data-accent="pink" title="Pink"></button>
<button type="button" data-accent="orange" title="Orange"></button>
</div>
</div>
</section>
<section class="summary-grid" id="summaryGrid" aria-live="polite"></section>
<section class="workspace-grid medical-workspace">
<div class="panel planner-panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Medication Plan</p>
<h2>Medication Log</h2>
</div>
<button class="text-button" type="button" data-jump="#medicationLogForm">Log medication</button>
</div>
<div class="timeline" id="medicationLogList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Vitals</p>
<h2>Latest Readings</h2>
</div>
<button class="text-button" type="button" data-jump="#vitalLogForm">Log vitals</button>
</div>
<div class="nutrition-list" id="vitalLogList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Labs</p>
<h2>Lab Results</h2>
</div>
<button class="text-button" type="button" data-jump="#labResultForm">Log lab</button>
</div>
<div class="nutrition-list" id="labResultList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Symptoms</p>
<h2>Symptom Journal</h2>
</div>
<button class="text-button" type="button" data-jump="#symptomLogForm">Log symptom</button>
</div>
<div class="nutrition-list" id="symptomLogList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Safety</p>
<h2>Allergies</h2>
</div>
<button class="text-button" type="button" data-jump="#allergyRecordForm">Add allergy</button>
</div>
<div class="nutrition-list" id="allergyRecordList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Care Plan</p>
<h2>Appointments</h2>
</div>
<button class="text-button" type="button" data-jump="#appointmentForm">Add appointment</button>
</div>
<div class="nutrition-list" id="appointmentList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Prevention</p>
<h2>Immunizations</h2>
</div>
<button class="text-button" type="button" data-jump="#immunizationRecordForm">Add vaccine</button>
</div>
<div class="nutrition-list" id="immunizationRecordList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Reference</p>
<h2>NIH/NLM Studies</h2>
</div>
<a class="text-button" href="/medical.php">Open database</a>
</div>
<div class="supplement-list" id="studyList"></div>
</div>
</section>
<section class="panel admin-panel" id="adminPanel" hidden>
<div class="panel-heading">
<div>
<p class="eyebrow">Admin</p>
<h2>User Management</h2>
</div>
<button class="text-button" type="button" id="newAdminUserButton">New profile</button>
</div>
<div class="admin-stats" id="adminStats"></div>
<div class="admin-layout">
<div class="admin-user-list" id="adminUserList"></div>
<form class="admin-editor" id="adminUserForm">
<input type="hidden" name="target_user_id">
<div class="panel-heading">
<div>
<p class="eyebrow">Profile Editor</p>
<h2 id="adminUserFormTitle">Create Profile</h2>
</div>
<button class="text-button" type="button" id="clearAdminUserFormButton">Clear</button>
</div>
<div class="form-grid two">
<label class="field"><span>Name</span><input name="name" required></label>
<label class="field"><span>Email</span><input name="email" type="email"></label>
<label class="field"><span>Role</span><select name="role"><option value="member">member</option><option value="admin">admin</option></select></label>
<label class="field"><span>Status</span><select name="status"><option value="active">active</option><option value="inactive">inactive</option></select></label>
<label class="field"><span>Phone</span><input name="phone" type="tel"></label>
<label class="field"><span>Birthday</span><input name="birthday" type="date"></label>
<label class="field"><span>Height in</span><input name="height_in" type="number" min="0" step="0.5"></label>
<label class="field"><span>Tracking comfort</span><select name="training_level"><option></option><option>Getting started</option><option>Comfortable</option><option>Advanced</option><option>Caregiver</option></select></label>
<label class="field"><span>Theme</span><select name="theme_mode"><option>dark</option><option>light</option></select></label>
<label class="field"><span>Accent</span><select name="theme_accent"><option>green</option><option>blue</option><option>red</option><option>pink</option><option>orange</option></select></label>
<label class="field wide"><span>Care focus</span><input name="fitness_focus" placeholder="Blood pressure, glucose, asthma"></label>
<label class="field wide"><span>Emergency contact</span><input name="emergency_contact" placeholder="Name and phone"></label>
</div>
<button class="primary-button" type="submit">Save profile</button>
</form>
</div>
</section>
<section class="workspace-grid">
<div class="panel planner-panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Legacy Fitness</p>
<h2>Workout Schedule</h2>
</div>
<button class="text-button" type="button" data-jump="#workoutForm">Add workout</button>
</div>
<div class="timeline" id="workoutTimeline"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Balance</p>
<h2>Nutrition Target vs Actual</h2>
</div>
<button class="text-button" type="button" data-jump="#nutritionLogForm">Log meal</button>
</div>
<div id="nutritionCompare"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Plan Library</p>
<h2>Routines</h2>
</div>
<button class="text-button" type="button" data-jump="#routineForm">Add routine</button>
</div>
<div class="routine-list" id="routineList"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Recovery Stack</p>
<h2>Supplements</h2>
</div>
<button class="text-button" type="button" data-jump="#supplementLogForm">Log dose</button>
</div>
<div class="supplement-list" id="supplementLogList"></div>
</div>
</section>
<section class="forms-grid" aria-label="Tracker forms">
<form class="panel form-panel" id="medicationLogForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Medication</p>
<h2>Log Medication</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="taken_on" type="date" required></label>
<label class="field"><span>Medication</span><select name="medication_id"></select></label>
<label class="field"><span>Name</span><input name="medication_name" placeholder="Custom medicine"></label>
<label class="field"><span>Dose</span><input name="dose" placeholder="500 mg"></label>
<label class="field"><span>Route</span><input name="route" placeholder="oral"></label>
<label class="field"><span>Frequency</span><input name="frequency" placeholder="twice daily"></label>
<label class="field"><span>Status</span><select name="status"><option>planned</option><option>taken</option><option>skipped</option><option>stopped</option></select></label>
<label class="field"><span>Prescriber</span><input name="prescriber"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save medication</button>
</form>
<form class="panel form-panel" id="vitalLogForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Vitals</p>
<h2>Log Vitals</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="measured_on" type="date" required></label>
<label class="field"><span>Blood pressure</span><input name="systolic" type="number" min="0" placeholder="Systolic"></label>
<label class="field"><span>Diastolic</span><input name="diastolic" type="number" min="0"></label>
<label class="field"><span>Pulse</span><input name="pulse" type="number" min="0"></label>
<label class="field"><span>Temp F</span><input name="temperature_f" type="number" min="0" step="0.1"></label>
<label class="field"><span>Oxygen %</span><input name="oxygen_pct" type="number" min="0" max="100" step="0.1"></label>
<label class="field"><span>Glucose mg/dL</span><input name="glucose_mg_dl" type="number" min="0" step="1"></label>
<label class="field"><span>Pain 0-10</span><input name="pain_score" type="number" min="0" max="10" step="1"></label>
<label class="field wide"><span>Symptoms</span><input name="symptoms" placeholder="Cough, dizziness, none"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save vitals</button>
</form>
<form class="panel form-panel" id="labResultForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Labs</p>
<h2>Log Lab Result</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="collected_on" type="date" required></label>
<label class="field"><span>Test</span><input name="test_name" placeholder="A1C" required></label>
<label class="field"><span>Result</span><input name="result_value" placeholder="6.2" required></label>
<label class="field"><span>Unit</span><input name="unit" placeholder="%"></label>
<label class="field"><span>Reference range</span><input name="reference_range"></label>
<label class="field"><span>Clinician</span><input name="ordering_clinician"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save lab</button>
</form>
<form class="panel form-panel" id="symptomLogForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Symptoms</p>
<h2>Log Symptom</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="observed_on" type="date" required></label>
<label class="field"><span>Symptom</span><input name="symptom" placeholder="Headache" required></label>
<label class="field"><span>Body area</span><input name="body_area" placeholder="Head, chest, abdomen"></label>
<label class="field"><span>Severity 0-10</span><input name="severity" type="number" min="0" max="10" step="1"></label>
<label class="field"><span>Duration</span><input name="duration" placeholder="2 hours"></label>
<label class="field"><span>Triggers</span><input name="triggers" placeholder="Food, activity, stress"></label>
<label class="field wide"><span>Action taken</span><input name="action_taken" placeholder="Rested, called clinic, took medicine"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save symptom</button>
</form>
<form class="panel form-panel" id="allergyRecordForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Safety</p>
<h2>Add Allergy</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Allergen</span><input name="allergen" placeholder="Penicillin" required></label>
<label class="field"><span>Reaction</span><input name="reaction" placeholder="Rash, hives, swelling"></label>
<label class="field"><span>Severity</span><select name="severity"><option>unknown</option><option>mild</option><option>moderate</option><option>severe</option><option>life-threatening</option></select></label>
<label class="field"><span>First noted</span><input name="first_noted_on" type="date"></label>
<label class="field"><span>Status</span><select name="status"><option>active</option><option>resolved</option></select></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save allergy</button>
</form>
<form class="panel form-panel" id="appointmentForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Care Plan</p>
<h2>Add Appointment</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="appointment_on" type="date" required></label>
<label class="field"><span>Clinician</span><input name="clinician" placeholder="Dr. Morgan"></label>
<label class="field"><span>Specialty</span><input name="specialty" placeholder="Primary care"></label>
<label class="field"><span>Location</span><input name="location" placeholder="Clinic or telehealth"></label>
<label class="field wide"><span>Reason</span><input name="reason" placeholder="Medication follow-up" required></label>
<label class="field"><span>Status</span><select name="status"><option>scheduled</option><option>completed</option><option>canceled</option></select></label>
<label class="field wide"><span>Follow-up notes</span><textarea name="follow_up_notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save appointment</button>
</form>
<form class="panel form-panel" id="immunizationRecordForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Prevention</p>
<h2>Add Immunization</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Vaccine</span><input name="vaccine_name" placeholder="Influenza" required></label>
<label class="field"><span>Administered</span><input name="administered_on" type="date" required></label>
<label class="field"><span>Dose</span><input name="dose" placeholder="0.5 mL"></label>
<label class="field"><span>Lot number</span><input name="lot_number"></label>
<label class="field"><span>Site</span><input name="clinician_or_site" placeholder="Pharmacy, clinic"></label>
<label class="field"><span>Next due</span><input name="next_due_on" type="date"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save immunization</button>
</form>
<form class="panel form-panel" id="workoutForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Schedule</p>
<h2>Add Workout</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="scheduled_on" type="date" required></label>
<label class="field"><span>Routine</span><select name="routine_id"></select></label>
<label class="field"><span>Exercise</span><select name="exercise_id"></select></label>
<label class="field"><span>Workout type</span><input name="workout_type" list="workoutTypes" value="Weight lifting"></label>
<label class="field wide"><span>Title</span><input name="title" placeholder="Push strength" required></label>
<label class="field"><span>Sets</span><input name="sets" type="number" min="0" step="1"></label>
<label class="field"><span>Reps</span><input name="reps" type="number" min="0" step="1"></label>
<label class="field"><span>Weight lb</span><input name="weight_lbs" type="number" min="0" step="0.5"></label>
<label class="field"><span>Minutes</span><input name="duration_min" type="number" min="0" step="1"></label>
<label class="field"><span>Miles</span><input name="distance_mi" type="number" min="0" step="0.01"></label>
<label class="field"><span>Intensity</span><input name="intensity" placeholder="RPE 8"></label>
<label class="field"><span>Status</span><select name="status"><option>planned</option><option>complete</option><option>skipped</option></select></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save workout</button>
</form>
<form class="panel form-panel" id="routineForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Program</p>
<h2>Add Routine</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Name</span><input name="name" placeholder="Strength + swim" required></label>
<label class="field"><span>Workout type</span><input name="workout_type" list="workoutTypes" value="Hybrid"></label>
<label class="field"><span>Planner scope</span><select name="planner_scope"><option>daily</option><option selected>weekly</option><option>monthly</option></select></label>
<label class="field"><span>Nutrition target</span><select name="nutrition_goal_id"></select></label>
<label class="field"><span>Start date</span><input name="start_date" type="date" required></label>
<label class="field"><span>Intensity</span><input name="intensity" placeholder="Moderate"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save routine</button>
</form>
<form class="panel form-panel" id="nutritionGoalForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Targets</p>
<h2>Add Nutrition Goal</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Label</span><input name="label" placeholder="Cutting day" required></label>
<label class="field"><span>Scope</span><select name="scope"><option>daily</option><option>weekly</option><option>monthly</option></select></label>
<label class="field"><span>Start date</span><input name="start_date" type="date" required></label>
<label class="field"><span>Calories</span><input name="calories" type="number" min="0" step="1"></label>
<label class="field"><span>Protein g</span><input name="protein_g" type="number" min="0" step="1"></label>
<label class="field"><span>Carbs g</span><input name="carbs_g" type="number" min="0" step="1"></label>
<label class="field"><span>Fat g</span><input name="fat_g" type="number" min="0" step="1"></label>
<label class="field"><span>Water ml</span><input name="water_ml" type="number" min="0" step="50"></label>
</div>
<button class="primary-button" type="submit">Save target</button>
</form>
<form class="panel form-panel" id="nutritionLogForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Food</p>
<h2>Log Nutrition</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="logged_on" type="date" required></label>
<label class="field"><span>Calories</span><input name="calories" type="number" min="0" step="1"></label>
<label class="field"><span>Protein g</span><input name="protein_g" type="number" min="0" step="1"></label>
<label class="field"><span>Carbs g</span><input name="carbs_g" type="number" min="0" step="1"></label>
<label class="field"><span>Fat g</span><input name="fat_g" type="number" min="0" step="1"></label>
<label class="field"><span>Water ml</span><input name="water_ml" type="number" min="0" step="50"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save nutrition</button>
</form>
<form class="panel form-panel" id="supplementLogForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Dose</p>
<h2>Log Supplement</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="taken_on" type="date" required></label>
<label class="field"><span>Supplement</span><select name="supplement_id"></select></label>
<label class="field"><span>Timing</span><input name="timing" list="supplementTiming" value="Daily"></label>
<label class="field"><span>Dose</span><input name="dose" placeholder="5 g"></label>
<label class="field"><span>Status</span><select name="status"><option>planned</option><option>taken</option><option>skipped</option></select></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save dose</button>
</form>
<form class="panel form-panel" id="metricForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Health</p>
<h2>Log Body Metrics</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Date</span><input name="measured_on" type="date" required></label>
<label class="field"><span>Weight lb</span><input name="weight_lbs" type="number" min="0" step="0.1"></label>
<label class="field"><span>Body fat %</span><input name="body_fat_pct" type="number" min="0" step="0.1"></label>
<label class="field"><span>Sleep hr</span><input name="sleep_hours" type="number" min="0" step="0.1"></label>
<label class="field"><span>Resting HR</span><input name="resting_hr" type="number" min="0" step="1"></label>
<label class="field"><span>Mood</span><input name="mood" placeholder="Focused"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save metrics</button>
</form>
<form class="panel form-panel" id="exerciseForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Exercises</p>
<h2>Add Custom Exercise</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Name</span><input name="name" required></label>
<label class="field"><span>Category</span><input name="category" list="workoutTypes" value="Custom"></label>
<label class="field"><span>Muscle group</span><input name="muscle_group" placeholder="Back"></label>
<label class="field"><span>Default unit</span><input name="default_unit" placeholder="sets x reps"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save exercise</button>
</form>
<form class="panel form-panel" id="supplementForm">
<div class="panel-heading">
<div>
<p class="eyebrow">Supplements</p>
<h2>Add Custom Supplement</h2>
</div>
</div>
<div class="form-grid two">
<label class="field"><span>Name</span><input name="name" required></label>
<label class="field"><span>Timing</span><input name="timing" list="supplementTiming" value="Daily"></label>
<label class="field"><span>Dose</span><input name="default_dose" placeholder="1 serving"></label>
<label class="field"><span>Purpose</span><input name="purpose" placeholder="Recovery"></label>
<label class="field wide"><span>Notes</span><textarea name="notes" rows="3"></textarea></label>
</div>
<button class="primary-button" type="submit">Save supplement</button>
</form>
</section>
<section class="library-grid">
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Known Movements</p>
<h2>Exercise Library</h2>
</div>
</div>
<div class="chip-cloud" id="exerciseLibrary"></div>
</div>
<div class="panel">
<div class="panel-heading">
<div>
<p class="eyebrow">Known Stack</p>
<h2>Supplement Library</h2>
</div>
</div>
<div class="chip-cloud" id="supplementLibrary"></div>
</div>
</section>
</main>
</div>
<datalist id="workoutTypes">
<option value="Weight lifting"></option>
<option value="Cycling"></option>
<option value="Running"></option>
<option value="Swimming"></option>
<option value="Conditioning"></option>
<option value="Mobility"></option>
<option value="Hybrid"></option>
<option value="Outdoor"></option>
<option value="Core"></option>
</datalist>
<datalist id="supplementTiming">
<option value="Pre-workout"></option>
<option value="Intra-workout"></option>
<option value="Post-workout"></option>
<option value="Daily"></option>
<option value="Evening"></option>
</datalist>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="/assets/app.js" defer></script>
</body>
</html>