From c5e03a787de401bac5147b6bf373c28655ad3b64 Mon Sep 17 00:00:00 2001 From: Daniel Volz Date: Wed, 24 Dec 2025 09:41:55 +0100 Subject: [PATCH] feat: add overdue dose indication in UI with corresponding styles --- frontend/src/App.tsx | 12 +++++++++--- frontend/src/styles.css | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fab9430..aa9727d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -743,8 +743,9 @@ export default function App() {
{item.doses.map((dose) => { const isTaken = takenDoses.has(dose.id); + const isOverdue = dose.when < Date.now(); return ( -
+
{dose.timeStr} {dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && {t('dose.takenBy')} setSelectedUser(med.takenBy!)}>{med.takenBy}} {isTaken ? ( @@ -1350,8 +1351,9 @@ export default function App() {
{item.doses.map((dose) => { const isTaken = takenDoses.has(dose.id); + const isOverdue = !isTaken && dose.when < Date.now(); return ( -
+
{dose.timeStr} {dose.usage} {dose.usage !== 1 ? t('common.pills') : t('common.pill')}{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} mg)`}{med?.takenBy && {t('dose.takenBy')} setSelectedUser(med.takenBy!)}>{med.takenBy}} {isTaken ? ( @@ -1372,6 +1374,8 @@ export default function App() { } /> + {/* Catch-all: redirect unknown routes to dashboard */} + } /> {/* Medication Detail Modal */} @@ -1674,6 +1678,7 @@ END:VCALENDAR`; function buildSchedulePreview(meds: Medication[], locale: string) { const events: Array<{ id: string; medName: string; timeStr: string; dateStr: string; usage: number; when: number }> = []; const now = new Date(); + const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // Midnight today const end = new Date(); end.setDate(end.getDate() + 180); // 6 months horizon @@ -1682,7 +1687,8 @@ function buildSchedulePreview(meds: Medication[], locale: string) { const start = new Date(slice.start); if (Number.isNaN(start.getTime())) return; for (let d = new Date(start); d <= end; d.setDate(d.getDate() + slice.every)) { - if (d < now) continue; + // Include all doses from today onwards (even past ones from today) + if (d < todayStart) continue; const whenMs = d.getTime(); events.push({ id: `${med.id}-${idx}-${whenMs}`, diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 494ce22..1d0866a 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -448,6 +448,40 @@ textarea { color: var(--text-secondary); } +/* Overdue (past, not taken) doses */ +.dose-item.overdue { + background: var(--warning-bg); + border-color: rgba(252, 211, 77, 0.4); +} + +.dose-item.overdue .dose-time { + color: var(--warning); +} + +.dose-item.overdue .dose-btn.take { + background: var(--warning-bg); + border-color: var(--warning); + color: var(--warning); +} + +.dose-item.overdue .dose-btn.take:hover { + background: var(--warning); + color: #1a1a2e; +} + +/* Overdue AND taken = show it was late */ +.dose-item.overdue.taken { + background: rgba(252, 211, 77, 0.08); + border-color: rgba(252, 211, 77, 0.2); + opacity: 0.6; +} + +.dose-item.overdue.taken .dose-time, +.dose-item.overdue.taken .dose-usage { + text-decoration: line-through; + color: var(--text-secondary); +} + .dose-time { font-weight: 600; color: var(--accent-light);