feat(past-days): enhance past days toggle with missed doses indication and styling

This commit is contained in:
Daniel Volz
2025-12-27 22:11:51 +01:00
parent cfb8494be3
commit d2324640f4
4 changed files with 88 additions and 41 deletions
+62 -39
View File
@@ -1076,18 +1076,27 @@ function AppContent() {
</div>
<div className="timeline">
{/* Past days toggle */}
{pastDays.length > 0 && (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : ''}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
</div>
)}
{pastDays.length > 0 && (() => {
const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
return (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
{missedPastDoses > 0 ? (
<span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}> {missedPastDoses}</span>
) : totalPastDoses.length > 0 ? (
<span className="past-days-complete" title={t('dashboard.schedules.allTaken')}></span>
) : null}
</div>
);
})()}
{/* Past days (when expanded) */}
{showPastDays && pastDays.map((day) => {
const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
@@ -1110,7 +1119,7 @@ function AppContent() {
{allDayTaken ? (
<span className="day-complete"> {t('dashboard.schedules.allTaken')}</span>
) : (
<span className="day-progress">{takenCount}/{allDoseIds.length}</span>
<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}></span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
)}
</span>
</div>
@@ -1841,18 +1850,23 @@ function AppContent() {
</div>
<div className="timeline">
{/* Past days toggle */}
{pastDays.length > 0 && (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : ''}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
</div>
)}
{pastDays.length > 0 && (() => {
const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
return (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
{missedPastDoses > 0 && <span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}> {missedPastDoses}</span>}
</div>
);
})()}
{/* Past days (when expanded) */}
{showPastDays && pastDays.map((day) => {
const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
@@ -1874,7 +1888,7 @@ function AppContent() {
{allDayTaken ? (
<span className="day-complete"> {t('dashboard.schedules.allTaken')}</span>
) : (
<span className="day-progress">{takenCount}/{allDoseIds.length}</span>
<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}></span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
)}
</span>
</div>
@@ -3062,18 +3076,27 @@ function SharedSchedule() {
) : (
<>
{/* Past days toggle */}
{pastDays.length > 0 && (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : ''}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
</div>
)}
{pastDays.length > 0 && (() => {
const totalPastDoses = pastDays.flatMap(d => d.meds.flatMap(m => m.doses.map(dose => dose.id)));
const missedPastDoses = totalPastDoses.filter(id => !takenDoses.has(id)).length;
return (
<div
className={`past-days-toggle ${showPastDays ? 'expanded' : ''} ${missedPastDoses > 0 ? 'has-missed' : ''}`}
onClick={() => setShowPastDays(!showPastDays)}
>
<span className="past-days-icon">{showPastDays ? '▼' : '▶'}</span>
<span className="past-days-label">
{showPastDays ? t('dashboard.schedules.hidePastDays') : t('dashboard.schedules.showPastDays')}
</span>
<span className="past-days-count">({t('dashboard.schedules.pastDaysCount', { count: pastDays.length })})</span>
{missedPastDoses > 0 ? (
<span className="past-days-warning" title={t('dashboard.schedules.missedDoses', { count: missedPastDoses })}> {missedPastDoses}</span>
) : totalPastDoses.length > 0 ? (
<span className="past-days-complete" title={t('dashboard.schedules.allTaken')}></span>
) : null}
</div>
);
})()}
{/* Past days (when expanded) */}
{showPastDays && pastDays.map((day) => {
const allDoseIds = day.meds.flatMap((item) => item.doses.map((d) => d.id));
@@ -3098,7 +3121,7 @@ function SharedSchedule() {
{allDayTaken ? (
<span className="day-complete"> {t('dashboard.schedules.allTaken')}</span>
) : (
<span className="day-progress">{takenCount}/{allDoseIds.length}</span>
<><span className="day-warning" title={t('dashboard.schedules.missedDoses', { count: allDoseIds.length - takenCount })}></span><span className="day-progress">{takenCount}/{allDoseIds.length}</span></>
)}
</span>
</div>
+3 -1
View File
@@ -36,7 +36,9 @@
"showPastDays": "Vergangene Tage anzeigen",
"hidePastDays": "Vergangene Tage ausblenden",
"pastDaysCount": "{{count}} vergangener Tag",
"pastDaysCount_other": "{{count}} vergangene Tage"
"pastDaysCount_other": "{{count}} vergangene Tage",
"missedDoses": "{{count}} verpasste Dosis",
"missedDoses_other": "{{count}} verpasste Dosen"
},
"reminders": {
"active": "Automatische Erinnerungen aktiv",
+3 -1
View File
@@ -38,7 +38,9 @@
"showPastDays": "Show past days",
"hidePastDays": "Hide past days",
"pastDaysCount": "{{count}} past day",
"pastDaysCount_other": "{{count}} past days"
"pastDaysCount_other": "{{count}} past days",
"missedDoses": "{{count}} missed dose",
"missedDoses_other": "{{count}} missed doses"
},
"reminders": {
"active": "Automatic reminders active",
+20
View File
@@ -432,6 +432,25 @@ textarea {
opacity: 0.6;
font-size: 0.85rem;
}
.past-days-warning {
margin-left: auto;
color: var(--warning);
font-size: 0.9rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.25rem;
}
.past-days-complete {
margin-left: auto;
color: var(--success);
font-size: 1rem;
font-weight: 700;
}
.past-days-toggle.has-missed {
border-color: var(--warning);
background: rgba(234, 179, 8, 0.08);
}
/* Past day blocks styling */
.day-block.past {
@@ -489,6 +508,7 @@ textarea {
}
.day-complete { color: var(--success); }
.day-progress { color: var(--text-secondary); }
.day-warning { margin-right: 0.35rem; }
.day-block.collapsed .day-divider {
margin-bottom: 0;
padding-bottom: 0;