- Implemented the symptom database as a full searchable reference area, parallel to terminology.
Added: New medical_symptoms SQLite catalog with 242 seeded symptom records, categories, body systems, tracking notes, urgency-context notes, search terms, and MedlinePlus links: [app/bootstrap.php (line 186)](/Users/tyemeclifford/Documents/GH/workout/app/bootstrap.php:186), [seed logic (line 635)](/Users/tyemeclifford/Documents/GH/workout/app/bootstrap.php:635) New searchable symptom directory: [public/symptoms.php (line 1)](/Users/tyemeclifford/Documents/GH/workout/public/symptoms.php:1) New dynamic per-symptom page, e.g. /symptom.php?id=24: [public/symptom.php (line 1)](/Users/tyemeclifford/Documents/GH/workout/public/symptom.php:1) Symptom helper/link lookup functions: [app/bootstrap.php (line 1473)](/Users/tyemeclifford/Documents/GH/workout/app/bootstrap.php:1473) medicalSymptoms added to the combined library search/API: [app/bootstrap.php (line 2024)](/Users/tyemeclifford/Documents/GH/workout/app/bootstrap.php:2024) Symptoms added to nav, homepage, and combined medical search: [site-header.php (line 27)](/Users/tyemeclifford/Documents/GH/workout/public/partials/site-header.php:27), [index.php (line 11)](/Users/tyemeclifford/Documents/GH/workout/public/index.php:11), [medical.php (line 13)](/Users/tyemeclifford/Documents/GH/workout/public/medical.php:13)
This commit is contained in:
@@ -25,7 +25,6 @@ try {
|
||||
$data = json_input();
|
||||
$routes = [
|
||||
'create_user' => 'create_user',
|
||||
'public_signup' => 'public_signup',
|
||||
'update_user' => 'update_user',
|
||||
'delete_user' => 'delete_user',
|
||||
'update_theme' => 'update_theme',
|
||||
|
||||
+4
-155
@@ -105,7 +105,6 @@ p {
|
||||
|
||||
.site-logo,
|
||||
.site-nav,
|
||||
.site-actions,
|
||||
.admin-access-row,
|
||||
.admin-user-main,
|
||||
.admin-badges,
|
||||
@@ -206,48 +205,7 @@ p {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.site-hero {
|
||||
width: min(1440px, calc(100% - 32px));
|
||||
min-height: min(760px, calc(100vh - 44px));
|
||||
margin: 12px auto 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.site-hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(90deg, rgba(8, 9, 13, 0.92), rgba(8, 9, 13, 0.35) 55%, rgba(8, 9, 13, 0.2));
|
||||
}
|
||||
|
||||
.site-hero img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.site-hero-copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: min(780px, 100%);
|
||||
padding: clamp(24px, 6vw, 72px);
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.site-lede,
|
||||
.site-hero-copy p:not(.site-eyebrow),
|
||||
.detail-hero p,
|
||||
.signup-copy p,
|
||||
.site-split p,
|
||||
.site-section-heading p {
|
||||
color: var(--muted-2);
|
||||
}
|
||||
@@ -259,43 +217,18 @@ p {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.site-actions {
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.photo-credit {
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
bottom: 10px;
|
||||
z-index: 1;
|
||||
max-width: min(460px, calc(100% - 28px));
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.photo-credit a,
|
||||
figcaption a {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.site-band,
|
||||
.site-split,
|
||||
.cta-strip,
|
||||
.detail-hero,
|
||||
.detail-grid,
|
||||
.signup-layout,
|
||||
.admin-public-shell,
|
||||
.site-footer {
|
||||
width: min(1180px, calc(100% - 32px));
|
||||
margin: 14px auto 0;
|
||||
}
|
||||
|
||||
.site-band,
|
||||
.site-split,
|
||||
.cta-strip,
|
||||
.signup-layout,
|
||||
.admin-public-shell,
|
||||
.site-footer {
|
||||
border: 1px solid var(--line);
|
||||
@@ -321,8 +254,6 @@ figcaption a {
|
||||
|
||||
.feature-grid article,
|
||||
.detail-grid article,
|
||||
.site-metric-stack article,
|
||||
.signup-steps article,
|
||||
.term-table article,
|
||||
.library-row,
|
||||
.record-field,
|
||||
@@ -363,8 +294,6 @@ figcaption a {
|
||||
.feature-grid p,
|
||||
.detail-grid p,
|
||||
.term-table p,
|
||||
.site-metric-stack span,
|
||||
.signup-steps span,
|
||||
.details-line,
|
||||
.timeline-meta {
|
||||
color: var(--muted);
|
||||
@@ -566,7 +495,7 @@ figcaption a {
|
||||
|
||||
.library-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
@@ -589,39 +518,18 @@ figcaption a {
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.site-split,
|
||||
.detail-hero,
|
||||
.signup-layout {
|
||||
.detail-hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(360px, 0.8fr);
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.site-split > div:first-child,
|
||||
.detail-hero > div,
|
||||
.signup-copy {
|
||||
.detail-hero > div {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.site-metric-stack {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.site-metric-stack article {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.cta-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.detail-hero {
|
||||
align-items: center;
|
||||
}
|
||||
@@ -647,48 +555,6 @@ figcaption {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.signup-card {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
background: color-mix(in srgb, var(--panel-2), transparent 2%);
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.signup-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.signup-steps {
|
||||
display: grid;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.signup-steps article {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.signup-steps strong {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: #06100b;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.signup-result {
|
||||
min-height: 24px;
|
||||
color: var(--muted-2);
|
||||
}
|
||||
|
||||
.site-field,
|
||||
.field {
|
||||
display: grid;
|
||||
@@ -936,7 +802,7 @@ textarea:focus {
|
||||
@media (max-width: 1020px) {
|
||||
.site-header,
|
||||
.site-footer,
|
||||
.cta-strip {
|
||||
.footer-links {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -951,9 +817,7 @@ textarea:focus {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.site-split,
|
||||
.detail-hero,
|
||||
.signup-layout,
|
||||
.admin-layout,
|
||||
.admin-source-form {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -966,32 +830,17 @@ textarea:focus {
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.site-header,
|
||||
.site-hero,
|
||||
.site-band,
|
||||
.site-split,
|
||||
.cta-strip,
|
||||
.detail-hero,
|
||||
.detail-grid,
|
||||
.signup-layout,
|
||||
.admin-public-shell,
|
||||
.site-footer {
|
||||
width: min(100% - 20px, 620px);
|
||||
}
|
||||
|
||||
.site-hero {
|
||||
min-height: 720px;
|
||||
}
|
||||
|
||||
.site-hero-copy {
|
||||
padding: 22px;
|
||||
padding-bottom: 74px;
|
||||
}
|
||||
|
||||
.feature-grid,
|
||||
.detail-grid,
|
||||
.admin-stats,
|
||||
.library-stats,
|
||||
.signup-row,
|
||||
.form-grid.two {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
const siteForm = document.querySelector("#publicSignupForm");
|
||||
const siteResult = document.querySelector("#signupResult");
|
||||
|
||||
function showSignupMessage(message) {
|
||||
if (siteResult) {
|
||||
siteResult.textContent = message;
|
||||
}
|
||||
}
|
||||
|
||||
async function siteApi(action, payload) {
|
||||
const response = await fetch(`/api.php?action=${encodeURIComponent(action)}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const json = await response.json();
|
||||
if (!response.ok || json.error) {
|
||||
throw new Error(json.error || "Request failed.");
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
if (siteForm) {
|
||||
siteForm.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const payload = Object.fromEntries(new FormData(siteForm).entries());
|
||||
showSignupMessage("Creating profile...");
|
||||
try {
|
||||
const result = await siteApi("public_signup", payload);
|
||||
if (result.user?.id) {
|
||||
localStorage.setItem("nht:userId", String(result.user.id));
|
||||
}
|
||||
siteForm.reset();
|
||||
const adminCopy = result.first_admin ? " You are the first user, so this profile is an admin." : "";
|
||||
showSignupMessage(`Profile created.${adminCopy} Opening tracker...`);
|
||||
window.setTimeout(() => {
|
||||
window.location.href = "/tracker.php";
|
||||
}, 900);
|
||||
} catch (error) {
|
||||
showSignupMessage(error.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
+76
-50
@@ -2,81 +2,107 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../app/bootstrap.php';
|
||||
app_db();
|
||||
$pdo = app_db();
|
||||
|
||||
$pageTitle = 'Neon Medical Tracker';
|
||||
$pageTitle = 'Medical Reference Library | Neon Medical Tracker';
|
||||
$activePage = 'home';
|
||||
$heroImage = 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Jogging_Woman_in_Grass.jpg/1280px-Jogging_Woman_in_Grass.jpg';
|
||||
$totalMedicines = (int) db_value($pdo, 'SELECT COUNT(*) FROM medication_catalog');
|
||||
$totalTerms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_terms');
|
||||
$totalSymptoms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_symptoms');
|
||||
$totalConditions = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_conditions');
|
||||
$totalStudies = (int) db_value($pdo, 'SELECT COUNT(*) FROM research_studies');
|
||||
|
||||
require __DIR__ . '/partials/site-header.php';
|
||||
?>
|
||||
<main>
|
||||
<section class="site-hero">
|
||||
<img src="<?= htmlspecialchars($heroImage, ENT_QUOTES) ?>" alt="Runner training outdoors in bright green grass">
|
||||
<div class="site-hero-copy">
|
||||
<p class="site-eyebrow">Medication logs, vitals, labs, terminology, NIH/NLM research links</p>
|
||||
<h1>Neon Medical Tracker</h1>
|
||||
<p class="site-lede">A multi-user medical tracking workspace for people who want medicines, readings, labs, symptoms, source links, and profile administration in one web dashboard.</p>
|
||||
<div class="site-actions">
|
||||
<a class="site-primary" href="/signup.php">Start tracking</a>
|
||||
<a class="site-secondary" href="/medical.php">Explore database</a>
|
||||
</div>
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Medical reference</p>
|
||||
<h1>Medicines, symptoms, terminology, conditions, and NIH/NLM study links.</h1>
|
||||
<p>Search the reference database or open the tracker/admin tools for profile-managed medical logs.</p>
|
||||
</div>
|
||||
|
||||
<form class="library-search" method="get" action="/medical.php">
|
||||
<label>
|
||||
<span>Search medical library</span>
|
||||
<input name="q" placeholder="Try warfarin, CBC, blood pressure, metformin, asthma">
|
||||
</label>
|
||||
<button class="site-primary" type="submit">Search</button>
|
||||
</form>
|
||||
|
||||
<div class="library-stats" aria-label="Library totals">
|
||||
<article><strong><?= number_format($totalMedicines) ?></strong><span>medicines</span></article>
|
||||
<article><strong><?= number_format($totalSymptoms) ?></strong><span>symptoms</span></article>
|
||||
<article><strong><?= number_format($totalTerms) ?></strong><span>terms</span></article>
|
||||
<article><strong><?= number_format($totalConditions) ?></strong><span>conditions</span></article>
|
||||
<article><strong><?= number_format($totalStudies) ?></strong><span>study categories</span></article>
|
||||
</div>
|
||||
<p class="photo-credit">
|
||||
Photo: <a href="https://commons.wikimedia.org/wiki/File:Jogging_Woman_in_Grass.jpg">Jogging Woman in Grass</a>
|
||||
by Mike Baird, <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="site-band">
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Built for daily use</p>
|
||||
<h2>One workspace for personal health records and sourced reference links.</h2>
|
||||
<p class="site-eyebrow">Reference sections</p>
|
||||
<h2>Open a database area.</h2>
|
||||
</div>
|
||||
<div class="feature-grid">
|
||||
<article>
|
||||
<span>01</span>
|
||||
<h3>Medication tracking</h3>
|
||||
<p>Log prescription and over-the-counter medicines by date, dose, route, frequency, status, prescriber, and notes.</p>
|
||||
<span>Rx</span>
|
||||
<h3>Medicines</h3>
|
||||
<p>Search by generic name, chemical name, active ingredient, brand name, or medication class.</p>
|
||||
<a class="site-secondary" href="/nutrition.php">Open medicines</a>
|
||||
</article>
|
||||
<article>
|
||||
<span>02</span>
|
||||
<h3>Vitals and symptoms</h3>
|
||||
<p>Track blood pressure, pulse, temperature, oxygen saturation, glucose, pain scores, symptoms, and context.</p>
|
||||
<span>ABC</span>
|
||||
<h3>Terminology</h3>
|
||||
<p>Browse plain-language medical terms with clinical context and reference links.</p>
|
||||
<a class="site-secondary" href="/medical.php">Open terminology</a>
|
||||
</article>
|
||||
<article>
|
||||
<span>03</span>
|
||||
<h3>Labs and terminology</h3>
|
||||
<p>Store lab values and browse plain-language medical terms connected to MedlinePlus, RxNorm, PubMed, and ClinicalTrials.gov.</p>
|
||||
<span>Sx</span>
|
||||
<h3>Symptoms</h3>
|
||||
<p>Search symptom names, body systems, tracking notes, and urgency-context references.</p>
|
||||
<a class="site-secondary" href="/symptoms.php">Open symptoms</a>
|
||||
</article>
|
||||
<article>
|
||||
<span>04</span>
|
||||
<h3>NIH/NLM studies</h3>
|
||||
<p>Browse NIH/NLM research categories and study-search links related to the medicines included in the catalog.</p>
|
||||
<span>NIH</span>
|
||||
<h3>Research</h3>
|
||||
<p>Open NIH/NLM, PubMed, and ClinicalTrials.gov study categories tied to medicines.</p>
|
||||
<a class="site-secondary" href="/recovery.php">Open research</a>
|
||||
</article>
|
||||
<article>
|
||||
<span>Dx</span>
|
||||
<h3>Conditions</h3>
|
||||
<p>Review condition-tracking topics for vitals, labs, symptoms, medications, and notes.</p>
|
||||
<a class="site-secondary" href="/workouts.php">Open conditions</a>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="site-split">
|
||||
<div>
|
||||
<p class="site-eyebrow">For households, caregivers, and small teams</p>
|
||||
<h2>Profiles stay separate, admins stay in control.</h2>
|
||||
<p>Each user gets a profile, theme preference, medication logs, vitals, lab results, medical notes, and research references. Admins can create users, edit details, activate or deactivate accounts, and remove profiles from a dedicated dashboard.</p>
|
||||
<a class="site-secondary inline-link" href="/admin.php">Open admin dashboard</a>
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Profile tools</p>
|
||||
<h2>Manage medical logs through Tracker and Admin.</h2>
|
||||
</div>
|
||||
<div class="site-metric-stack">
|
||||
<article><strong>Daily</strong><span>Log today’s medicines, readings, symptoms, and notes.</span></article>
|
||||
<article><strong>Weekly</strong><span>Review medication adherence, vital trends, labs, and follow-up context.</span></article>
|
||||
<article><strong>Monthly</strong><span>Keep longer-term records ready for visits with clinicians or caregivers.</span></article>
|
||||
<div class="library-list">
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3>Tracker</h3>
|
||||
<p>Use existing profiles for medications, vitals, labs, symptoms, allergies, appointments, immunizations, and notes.</p>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-primary" href="/tracker.php">Open tracker</a>
|
||||
</div>
|
||||
</article>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3>Admin</h3>
|
||||
<p>Create, update, activate, deactivate, and remove profiles from the admin dashboard.</p>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-secondary" href="/admin.php">Manage profiles</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-strip">
|
||||
<div>
|
||||
<p class="site-eyebrow">Ready when you are</p>
|
||||
<h2>Create your profile and open the medical tracker.</h2>
|
||||
</div>
|
||||
<a class="site-primary" href="/signup.php">Sign up</a>
|
||||
</section>
|
||||
</main>
|
||||
<?php require __DIR__ . '/partials/site-footer.php'; ?>
|
||||
|
||||
+36
-2
@@ -10,9 +10,11 @@ $searchQuery = trim((string) ($_GET['q'] ?? ''));
|
||||
$library = library_search_payload(['q' => $searchQuery, 'limit' => 500]);
|
||||
$terms = $library['medicalTerms'];
|
||||
$conditions = $library['medicalConditions'];
|
||||
$symptoms = $library['medicalSymptoms'];
|
||||
$medicines = $library['medicationCatalog'];
|
||||
$studies = $library['researchStudies'];
|
||||
$totalMedicines = (int) db_value($pdo, 'SELECT COUNT(*) FROM medication_catalog');
|
||||
$totalSymptoms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_symptoms');
|
||||
|
||||
require __DIR__ . '/partials/site-header.php';
|
||||
?>
|
||||
@@ -20,14 +22,14 @@ require __DIR__ . '/partials/site-header.php';
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Searchable medical library</p>
|
||||
<h1>Search terms, conditions, medicines, chemical names, and brands.</h1>
|
||||
<h1>Search symptoms, terms, conditions, medicines, chemical names, and brands.</h1>
|
||||
<p>Entries are concise app-authored summaries with links to NIH/NLM systems such as MedlinePlus, RxNorm, DailyMed, PubChem, PubMed, and ClinicalTrials.gov. This is a tracking/reference aid, not medical advice.</p>
|
||||
</div>
|
||||
|
||||
<form class="library-search" method="get" action="/medical.php">
|
||||
<label>
|
||||
<span>Search medical library</span>
|
||||
<input name="q" value="<?= htmlspecialchars($searchQuery, ENT_QUOTES) ?>" placeholder="Try Lipitor, atorvastatin, blood pressure, CBC, metformin">
|
||||
<input name="q" value="<?= htmlspecialchars($searchQuery, ENT_QUOTES) ?>" placeholder="Try chest pain, rash, Lipitor, blood pressure, CBC, metformin">
|
||||
</label>
|
||||
<button class="site-primary" type="submit">Search</button>
|
||||
<?php if ($searchQuery !== ''): ?>
|
||||
@@ -37,6 +39,7 @@ require __DIR__ . '/partials/site-header.php';
|
||||
|
||||
<div class="library-stats" aria-label="Search result counts">
|
||||
<article><strong><?= count($medicines) ?></strong><span><?= $searchQuery === '' ? 'medicines shown of ' . number_format($totalMedicines) : 'medicine results' ?></span></article>
|
||||
<article><strong><?= count($symptoms) ?></strong><span><?= $searchQuery === '' ? 'symptoms shown of ' . number_format($totalSymptoms) : 'symptom results' ?></span></article>
|
||||
<article><strong><?= count($terms) ?></strong><span>terms</span></article>
|
||||
<article><strong><?= count($conditions) ?></strong><span>conditions</span></article>
|
||||
<article><strong><?= count($studies) ?></strong><span>study links</span></article>
|
||||
@@ -61,6 +64,37 @@ require __DIR__ . '/partials/site-header.php';
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Symptoms</p>
|
||||
<h2>Symptom reference records</h2>
|
||||
</div>
|
||||
<?php if (!$symptoms): ?>
|
||||
<article class="empty-state">
|
||||
<h3>No symptoms found.</h3>
|
||||
<p>Try a body system, symptom name, sign, or tracking phrase.</p>
|
||||
</article>
|
||||
<?php else: ?>
|
||||
<div class="library-list">
|
||||
<?php foreach ($symptoms as $symptom): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars((string) $symptom['name'], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) $symptom['plain_language_description'], ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) $symptom['category'], ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars((string) ($symptom['body_system'] ?: 'Symptom'), ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-primary" href="<?= htmlspecialchars(symptom_detail_path($symptom), ENT_QUOTES) ?>">View symptom</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Terminology</p>
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
<p>Medication logs, vitals, lab results, terminology, NIH/NLM study links, and admin-managed profiles.</p>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<a href="/signup.php">Create profile</a>
|
||||
<a href="/tracker.php">Open medical tracker</a>
|
||||
<a href="/admin.php">Admin dashboard</a>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/assets/site.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -24,9 +24,9 @@ function site_active(string $page, string $activePage): string
|
||||
<a<?= site_active('home', $activePage) ?> href="/">Home</a>
|
||||
<a<?= site_active('conditions', $activePage) ?> href="/workouts.php">Conditions</a>
|
||||
<a<?= site_active('medicines', $activePage) ?> href="/nutrition.php">Medicines</a>
|
||||
<a<?= site_active('symptoms', $activePage) ?> href="/symptoms.php">Symptoms</a>
|
||||
<a<?= site_active('research', $activePage) ?> href="/recovery.php">Research</a>
|
||||
<a<?= site_active('terminology', $activePage) ?> href="/medical.php">Terminology</a>
|
||||
<a<?= site_active('signup', $activePage) ?> href="/signup.php">Sign up</a>
|
||||
<a href="/tracker.php">Tracker</a>
|
||||
<a href="/admin.php">Admin</a>
|
||||
</nav>
|
||||
|
||||
+2
-44
@@ -1,47 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../app/bootstrap.php';
|
||||
app_db();
|
||||
|
||||
$pageTitle = 'Sign Up | Neon Medical Tracker';
|
||||
$activePage = 'signup';
|
||||
require __DIR__ . '/partials/site-header.php';
|
||||
?>
|
||||
<main>
|
||||
<section class="signup-layout">
|
||||
<div class="signup-copy">
|
||||
<p class="site-eyebrow">Create your profile</p>
|
||||
<h1>Start with the basics. Add records as care changes.</h1>
|
||||
<p>Your profile keeps medications, vitals, labs, symptoms, allergies, appointments, vaccines, notes, and theme preferences separate from every other user.</p>
|
||||
<div class="signup-steps">
|
||||
<article><strong>1</strong><span>Create profile</span></article>
|
||||
<article><strong>2</strong><span>Open tracker</span></article>
|
||||
<article><strong>3</strong><span>Add medical records</span></article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="signup-card" id="publicSignupForm">
|
||||
<div>
|
||||
<p class="site-eyebrow">Sign up</p>
|
||||
<h2>New profile</h2>
|
||||
</div>
|
||||
<label class="site-field"><span>Name</span><input name="name" required autocomplete="name"></label>
|
||||
<label class="site-field"><span>Email</span><input name="email" type="email" autocomplete="email"></label>
|
||||
<label class="site-field"><span>Phone</span><input name="phone" type="tel" autocomplete="tel"></label>
|
||||
<label class="site-field"><span>Care focus</span><input name="fitness_focus" placeholder="Blood pressure, glucose, asthma"></label>
|
||||
<div class="signup-row">
|
||||
<label class="site-field"><span>Birthday</span><input name="birthday" type="date"></label>
|
||||
<label class="site-field"><span>Height in</span><input name="height_in" type="number" min="0" step="0.5"></label>
|
||||
</div>
|
||||
<label class="site-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>
|
||||
<div class="signup-row">
|
||||
<label class="site-field"><span>Theme</span><select name="theme_mode"><option>dark</option><option>light</option></select></label>
|
||||
<label class="site-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>
|
||||
</div>
|
||||
<button class="site-primary full" type="submit">Create profile</button>
|
||||
<p class="signup-result" id="signupResult" role="status" aria-live="polite"></p>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
<?php require __DIR__ . '/partials/site-footer.php'; ?>
|
||||
header('Location: /tracker.php', true, 302);
|
||||
exit;
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../app/bootstrap.php';
|
||||
$pdo = app_db();
|
||||
|
||||
$symptom = find_medical_symptom_item($pdo, $_GET);
|
||||
$pageTitle = $symptom
|
||||
? (string) $symptom['name'] . ' | Symptom Detail | Neon Medical Tracker'
|
||||
: 'Symptom Not Found | Neon Medical Tracker';
|
||||
$activePage = 'symptoms';
|
||||
|
||||
$relatedTerms = [];
|
||||
$relatedConditions = [];
|
||||
$relatedMedicines = [];
|
||||
$relatedStudies = [];
|
||||
if ($symptom) {
|
||||
$related = library_search_payload(['q' => (string) $symptom['name'], 'limit' => 8]);
|
||||
$relatedTerms = $related['medicalTerms'];
|
||||
$relatedConditions = $related['medicalConditions'];
|
||||
$relatedMedicines = $related['medicationCatalog'];
|
||||
$relatedStudies = $related['researchStudies'];
|
||||
} else {
|
||||
http_response_code(404);
|
||||
}
|
||||
|
||||
require __DIR__ . '/partials/site-header.php';
|
||||
?>
|
||||
<main>
|
||||
<?php if (!$symptom): ?>
|
||||
<section class="admin-public-shell record-shell">
|
||||
<p class="site-eyebrow">Symptom database</p>
|
||||
<h1>Symptom not found.</h1>
|
||||
<p>The requested symptom link does not match a current database record.</p>
|
||||
<a class="site-primary" href="/symptoms.php">Search symptoms</a>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
<section class="admin-public-shell record-shell">
|
||||
<div class="record-heading">
|
||||
<div>
|
||||
<p class="site-eyebrow">Symptom detail</p>
|
||||
<h1><?= htmlspecialchars((string) $symptom['name'], ENT_QUOTES) ?></h1>
|
||||
<p><?= htmlspecialchars((string) $symptom['plain_language_description'], ENT_QUOTES) ?></p>
|
||||
</div>
|
||||
<div class="record-actions">
|
||||
<a class="site-primary" href="/tracker.php">Open tracker</a>
|
||||
<a class="site-secondary" href="/symptoms.php?q=<?= rawurlencode((string) $symptom['name']) ?>">Symptom search</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="record-meta">
|
||||
<span><?= htmlspecialchars((string) $symptom['category'], ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars((string) ($symptom['body_system'] ?: 'Symptom'), ENT_QUOTES) ?></span>
|
||||
<span>ID <?= htmlspecialchars((string) $symptom['id'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="admin-public-shell">
|
||||
<div class="record-detail-grid">
|
||||
<article class="record-field wide">
|
||||
<span>Common Tracking</span>
|
||||
<p><?= htmlspecialchars((string) $symptom['common_tracking'], ENT_QUOTES) ?></p>
|
||||
</article>
|
||||
<article class="record-field wide">
|
||||
<span>Urgency Context</span>
|
||||
<p><?= htmlspecialchars((string) $symptom['urgency_note'], ENT_QUOTES) ?></p>
|
||||
</article>
|
||||
<article class="record-field wide">
|
||||
<span>Source</span>
|
||||
<div class="source-links">
|
||||
<a href="<?= htmlspecialchars((string) $symptom['source_url'], ENT_QUOTES) ?>"><?= htmlspecialchars((string) $symptom['source_name'], ENT_QUOTES) ?></a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if ($relatedTerms || $relatedConditions || $relatedMedicines || $relatedStudies): ?>
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Connected records</p>
|
||||
<h2>Database matches for this symptom</h2>
|
||||
</div>
|
||||
<div class="library-list">
|
||||
<?php foreach ($relatedTerms as $term): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars((string) $term['term'], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) $term['plain_language_definition'], ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) $term['category'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-secondary" href="<?= htmlspecialchars(term_detail_path($term), ENT_QUOTES) ?>">View term</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($relatedConditions as $condition): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars((string) $condition['name'], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) $condition['overview'], ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) $condition['category'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-secondary" href="<?= htmlspecialchars((string) $condition['source_url'], ENT_QUOTES) ?>">Source</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($relatedMedicines as $medicine): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars(ucfirst((string) $medicine['generic_name']), ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) ($medicine['common_use'] ?: $medicine['class_name']), ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) ($medicine['class_name'] ?: 'Medication'), ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-secondary" href="<?= htmlspecialchars(medicine_detail_path($medicine), ENT_QUOTES) ?>">View medicine</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($relatedStudies as $study): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars((string) $study['title'], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) $study['summary'], ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) $study['category'], ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars((string) $study['related_medicine'], ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-secondary" href="<?= htmlspecialchars((string) $study['source_url'], ENT_QUOTES) ?>">Study link</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
<?php require __DIR__ . '/partials/site-footer.php'; ?>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/../app/bootstrap.php';
|
||||
$pdo = app_db();
|
||||
|
||||
$pageTitle = 'Symptom Database | Neon Medical Tracker';
|
||||
$activePage = 'symptoms';
|
||||
$searchQuery = trim((string) ($_GET['q'] ?? ''));
|
||||
$library = library_search_payload(['q' => $searchQuery, 'limit' => 500]);
|
||||
$symptoms = $library['medicalSymptoms'];
|
||||
$totalSymptoms = (int) db_value($pdo, 'SELECT COUNT(*) FROM medical_symptoms');
|
||||
|
||||
require __DIR__ . '/partials/site-header.php';
|
||||
?>
|
||||
<main>
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Symptom database</p>
|
||||
<h1>Search symptoms by name, body system, tracking context, and urgency notes.</h1>
|
||||
<p>These entries are reference summaries with MedlinePlus source links. They support tracking and discussion, not diagnosis or treatment decisions.</p>
|
||||
</div>
|
||||
|
||||
<form class="library-search" method="get" action="/symptoms.php">
|
||||
<label>
|
||||
<span>Search symptoms</span>
|
||||
<input name="q" value="<?= htmlspecialchars($searchQuery, ENT_QUOTES) ?>" placeholder="Try chest pain, rash, nausea, dizziness, urinary, sleep">
|
||||
</label>
|
||||
<button class="site-primary" type="submit">Search</button>
|
||||
<?php if ($searchQuery !== ''): ?>
|
||||
<a class="site-secondary" href="/symptoms.php">Clear</a>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
|
||||
<div class="library-stats" aria-label="Symptom result count">
|
||||
<article><strong><?= count($symptoms) ?></strong><span><?= $searchQuery === '' ? 'shown of ' . number_format($totalSymptoms) . ' symptoms' : 'symptom results' ?></span></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="admin-public-shell">
|
||||
<div class="site-section-heading">
|
||||
<p class="site-eyebrow">Catalog directory</p>
|
||||
<h2>Symptom records</h2>
|
||||
</div>
|
||||
|
||||
<?php if (!$symptoms): ?>
|
||||
<article class="empty-state">
|
||||
<h3>No symptoms found.</h3>
|
||||
<p>Try a body system, symptom name, sign, or tracking phrase.</p>
|
||||
</article>
|
||||
<?php else: ?>
|
||||
<div class="library-list">
|
||||
<?php foreach ($symptoms as $symptom): ?>
|
||||
<article class="library-row">
|
||||
<div class="library-row-main">
|
||||
<h3><?= htmlspecialchars((string) $symptom['name'], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars((string) $symptom['plain_language_description'], ENT_QUOTES) ?></p>
|
||||
<div class="library-row-meta">
|
||||
<span><?= htmlspecialchars((string) $symptom['category'], ENT_QUOTES) ?></span>
|
||||
<span><?= htmlspecialchars((string) ($symptom['body_system'] ?: 'Symptom'), ENT_QUOTES) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-row-actions">
|
||||
<a class="site-primary" href="<?= htmlspecialchars(symptom_detail_path($symptom), ENT_QUOTES) ?>">View symptom</a>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</main>
|
||||
<?php require __DIR__ . '/partials/site-footer.php'; ?>
|
||||
+1
-1
@@ -16,7 +16,7 @@ require __DIR__ . '/partials/site-header.php';
|
||||
<p class="site-eyebrow">Condition tracking</p>
|
||||
<h1>Track readings, symptoms, labs, and medications by condition.</h1>
|
||||
<p>Use structured logs for blood pressure, glucose, pain, oxygen, temperature, lab results, medications, and notes. The condition library links back to NIH/NLM patient-information sources.</p>
|
||||
<a class="site-primary" href="/signup.php">Create a profile</a>
|
||||
<a class="site-primary" href="/tracker.php">Open tracker</a>
|
||||
</div>
|
||||
<figure>
|
||||
<img src="<?= htmlspecialchars($photo, ENT_QUOTES) ?>" alt="People cycling outdoors">
|
||||
|
||||
Reference in New Issue
Block a user