Today: "Ta alle nå" bulk-take for a cluster of overdue doses
When two or more doses are due now (overdue and unresolved), show one button that takes them all in a single tap — the common case of a morning handful. It loops over DoseActions.ensureLog + take, the same path each cards "Ta nå" uses, so inventory decrement and escalation cancel stay consistent; take() is idempotent so a stale row cannot double-decrement. Scoped to due-now only, so a later dose cannot be taken early by accident. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
dfb7c5a826
commit
c3cb0177b2
1 changed files with 25 additions and 2 deletions
|
|
@ -69,6 +69,10 @@ private data class TodayDose(
|
||||||
) {
|
) {
|
||||||
val status: DoseStatus? get() = log?.status
|
val status: DoseStatus? get() = log?.status
|
||||||
val atMillis: Long get() = at.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
val atMillis: Long get() = at.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
||||||
|
val resolved: Boolean get() = status == DoseStatus.TAKEN || status == DoseStatus.SKIPPED
|
||||||
|
|
||||||
|
/** Due now = unresolved and its scheduled time has passed (what escalation nags about). */
|
||||||
|
fun isDueNow(now: LocalDateTime): Boolean = !resolved && at.isBefore(now)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|
@ -211,6 +215,25 @@ fun TodayScreen(nav: Nav) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Bulk "take now" for a cluster of overdue doses (e.g. a morning
|
||||||
|
// handful). Same path as each card's "Ta nå", just looped — take()
|
||||||
|
// is idempotent so a stale entry can't double-decrement stock.
|
||||||
|
val dueNow = doses.filter { it.isDueNow(LocalDateTime.now()) }
|
||||||
|
if (dueNow.size >= 2) {
|
||||||
|
item {
|
||||||
|
FilledTonalButton(
|
||||||
|
onClick = {
|
||||||
|
scope.launch {
|
||||||
|
for (d in dueNow) {
|
||||||
|
val log = actions.ensureLog(d.doseTime.id, d.atMillis)
|
||||||
|
actions.take(log.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) { Text("Ta alle nå (${dueNow.size})") }
|
||||||
|
}
|
||||||
|
}
|
||||||
items(doses, key = { "${it.doseTime.id}-${it.atMillis}" }) { dose ->
|
items(doses, key = { "${it.doseTime.id}-${it.atMillis}" }) { dose ->
|
||||||
DoseCard(
|
DoseCard(
|
||||||
dose = dose,
|
dose = dose,
|
||||||
|
|
@ -248,8 +271,8 @@ private fun DoseCard(
|
||||||
) {
|
) {
|
||||||
val time = "%02d:%02d".format(dose.doseTime.minuteOfDay / 60, dose.doseTime.minuteOfDay % 60)
|
val time = "%02d:%02d".format(dose.doseTime.minuteOfDay / 60, dose.doseTime.minuteOfDay % 60)
|
||||||
val statusText = dose.status?.label
|
val statusText = dose.status?.label
|
||||||
val resolved = dose.status == DoseStatus.TAKEN || dose.status == DoseStatus.SKIPPED
|
val resolved = dose.resolved
|
||||||
val overdue = !resolved && dose.at.isBefore(LocalDateTime.now())
|
val overdue = dose.isDueNow(LocalDateTime.now())
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
// Visual state: overdue screams a little, resolved fades back, upcoming is calm.
|
// Visual state: overdue screams a little, resolved fades back, upcoming is calm.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue