96de47be43
Added: Live source updater for RxNorm, DailyMed, and openFDA. Admin dashboard panel to refresh medicine sources. CLI updater for periodic jobs: [scripts/update_medicine_catalog.php](/Users/tyemeclifford/Documents/GH/workout/scripts/update_medicine_catalog.php) Update history table: medication_source_updates. Curl fallback for external fetches when PHP stream DNS fails. README instructions for periodic updates. I also ran the imports: Current medication catalog count: 6,002. Latest source imports:RxNorm: 3,875 inserted, 1,125 updated. openFDA: 912 inserted, 88 updated. DailyMed: 95 inserted. Periodic update command: /Users/tyemeclifford/frankenphp php-cli scripts/update_medicine_catalog.php 5000 all
83 lines
5.2 KiB
PHP
83 lines
5.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/../app/bootstrap.php';
|
|
app_db();
|
|
|
|
$pageTitle = 'Admin Dashboard | Neon Medical Tracker';
|
|
$activePage = 'admin';
|
|
require __DIR__ . '/partials/site-header.php';
|
|
?>
|
|
<main>
|
|
<section class="admin-public-shell">
|
|
<div class="site-section-heading">
|
|
<p class="site-eyebrow">Admin dashboard</p>
|
|
<h1>Manage users and their profiles.</h1>
|
|
<p>Use an active admin profile to create users, update profile details, assign roles, activate or deactivate accounts, and remove users with their medical tracker records.</p>
|
|
</div>
|
|
|
|
<div class="admin-access-row">
|
|
<label class="site-field">
|
|
<span>Acting profile</span>
|
|
<select id="adminProfileSelect"></select>
|
|
</label>
|
|
<a class="site-secondary" href="/tracker.php">Open tracker</a>
|
|
</div>
|
|
|
|
<div class="admin-denied" id="adminDenied" hidden>
|
|
<h2>Admin access required</h2>
|
|
<p>Select an active admin profile to manage users. The first user in the database is automatically promoted to admin.</p>
|
|
</div>
|
|
|
|
<section class="admin-panel site-admin-panel" id="adminPanel" hidden>
|
|
<div class="admin-stats" id="adminStats"></div>
|
|
|
|
<section class="admin-source-panel">
|
|
<div class="site-section-heading">
|
|
<p class="site-eyebrow">Medicine source updater</p>
|
|
<h2>Refresh the medication catalog from public sources.</h2>
|
|
<p>Pull medicine concepts from RxNorm, DailyMed, and openFDA. Use a smaller limit for quick checks or a larger limit for periodic maintenance.</p>
|
|
</div>
|
|
<form class="admin-source-form" id="medicineSourceRefreshForm">
|
|
<label class="site-field"><span>Source</span><select name="source"><option value="all">All sources</option><option>RxNorm</option><option>DailyMed</option><option>openFDA</option></select></label>
|
|
<label class="site-field"><span>Max rows per source</span><input name="limit" type="number" min="25" max="5000" step="25" value="1000"></label>
|
|
<button class="site-primary" type="submit">Refresh medicines</button>
|
|
</form>
|
|
<div class="source-refresh-result" id="medicineSourceRefreshResult" role="status" aria-live="polite"></div>
|
|
</section>
|
|
|
|
<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="site-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="site-primary full" type="submit">Save profile</button>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
</main>
|
|
<div class="site-toast" id="siteToast" role="status" aria-live="polite"></div>
|
|
<script src="/assets/admin.js" defer></script>
|
|
<?php require __DIR__ . '/partials/site-footer.php'; ?>
|