From 976d7356ec48854ec751074222005c61d722b96d Mon Sep 17 00:00:00 2001 From: Daniel Volz Date: Sat, 21 Feb 2026 18:00:23 +0100 Subject: [PATCH] feat: improve medication detail modal layout and display (#258) Widen detail modal on desktop (711px, up from 500px) with max-width override to beat modals-base.css specificity. Limit fullscreen mode to actual phones (<=500px) instead of all screens <=900px. Move intake schedule section before prescription details. Show per-intake takenBy person and bell icon with proper warning color. Right-align time in schedule rows. Move notes icon after label text. Replace emoji bell icons with Lucide Bell component in SchedulePage and MobileEditModal. Add common.on/common.off i18n keys. Closes #254 --- frontend/src/components/MedDetailModal.tsx | 104 +++++++++++---------- frontend/src/i18n/de.json | 5 +- frontend/src/i18n/en.json | 5 +- frontend/src/pages/SchedulePage.tsx | 5 +- frontend/src/styles.css | 25 ++++- 5 files changed, 88 insertions(+), 56 deletions(-) diff --git a/frontend/src/components/MedDetailModal.tsx b/frontend/src/components/MedDetailModal.tsx index 637be46..f67b5a5 100644 --- a/frontend/src/components/MedDetailModal.tsx +++ b/frontend/src/components/MedDetailModal.tsx @@ -626,7 +626,7 @@ export function MedDetailModal({
+ {/* Intake Schedule Section */} + {selectedMed.blisters.length > 0 && ( +
+

+ {t("modal.intakeSchedule")}{" "} + {selectedMed.intakeRemindersEnabled && ( + + + )} +

+
+ {selectedMed.blisters.map((blister, idx) => { + // When using new intakes format with per-intake takenBy, + // each intake already represents one person's dose — don't multiply. + // For legacy intakes (no per-intake takenBy), multiply by personCount. + const intake = selectedMed.intakes?.[idx]; + const hasPerIntakeTakenBy = !!intake?.takenBy; + const personCount = hasPerIntakeTakenBy ? 1 : Math.max(1, selectedMed.takenBy?.length || 1); + const totalUsage = blister.usage * personCount; + return ( +
+ + {totalUsage} {totalUsage !== 1 ? t("common.pills") : t("common.pill")} + {selectedMed.pillWeightMg && + ` (${totalUsage * selectedMed.pillWeightMg} ${selectedMed.doseUnit ?? "mg"})`} + + + {blister.every === 1 ? t("common.daily") : t("common.everyNDays", { count: blister.every })} + + {hasPerIntakeTakenBy && intake.takenBy && ( + {intake.takenBy} + )} + {intake?.intakeRemindersEnabled && ( + + + )} + + {t("modal.at")}{" "} + {new Date(blister.start).toLocaleTimeString(getSystemLocale(i18n.language), { + hour: "2-digit", + minute: "2-digit", + })} + +
+ ); + })} +
+
+ )} + {/* Prescription Details Section */} {selectedMed.prescriptionEnabled && (
@@ -839,50 +891,6 @@ export function MedDetailModal({
)} - {/* Intake Schedule Section */} - {selectedMed.blisters.length > 0 && ( -
-

- {t("modal.intakeSchedule")}{" "} - {selectedMed.intakeRemindersEnabled && ( - - - )} -

-
- {selectedMed.blisters.map((blister, idx) => { - // When using new intakes format with per-intake takenBy, - // each intake already represents one person's dose — don't multiply. - // For legacy intakes (no per-intake takenBy), multiply by personCount. - const intake = selectedMed.intakes?.[idx]; - const hasPerIntakeTakenBy = !!intake?.takenBy; - const personCount = hasPerIntakeTakenBy ? 1 : Math.max(1, selectedMed.takenBy?.length || 1); - const totalUsage = blister.usage * personCount; - return ( -
- - {totalUsage} {totalUsage !== 1 ? t("common.pills") : t("common.pill")} - {selectedMed.pillWeightMg && - ` (${totalUsage * selectedMed.pillWeightMg} ${selectedMed.doseUnit ?? "mg"})`} - - - {blister.every === 1 ? t("common.daily") : t("common.everyNDays", { count: blister.every })} - - - {t("modal.at")}{" "} - {new Date(blister.start).toLocaleTimeString(getSystemLocale(i18n.language), { - hour: "2-digit", - minute: "2-digit", - })} - -
- ); - })} -
-
- )} - {/* Coverage Status Section */} {medCoverage && status && (
@@ -909,10 +917,10 @@ export function MedDetailModal({ {selectedMed.notes && (

+ {t("modal.notes")}{" "} {" "} - {t("modal.notes")} +

{selectedMed.notes}
@@ -1111,7 +1119,7 @@ export function MedDetailModal({