mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(checkups): say "overdue since yesterday" instead of "overdue by 1 days"
The due phrase on the check-up card and the checkups page counted a check-up one day past its date as "Overdue by 1 days", and the same counted form read wrongly in German. One day over now has its own phrase in all seven languages. Both overdue phrases keep the warning colour through a shared `isOverdueDue` helper, so a surface no longer compares against a single key.
This commit is contained in:
1 parent
5fb5145d7a
commit
f5bab3258a
12 files changed
+60
-9
No files matched your search
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "In {days} Tagen"
|
||||
},
|
||||
"overdueByDays": "Überfällig seit {days} Tagen",
|
||||
"overdueSinceYesterday": "Überfällig seit gestern",
|
||||
"cadence": {
|
||||
"everyNDays": "Alle {days} Tage",
|
||||
"custom": "Eigener Zeitplan",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "In {days} days"
|
||||
},
|
||||
"overdueByDays": "Overdue by {days} days",
|
||||
"overdueSinceYesterday": "Overdue since yesterday",
|
||||
"cadence": {
|
||||
"everyNDays": "Every {days} days",
|
||||
"custom": "Custom schedule",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "En {days} días"
|
||||
},
|
||||
"overdueByDays": "Vencido hace {days} días",
|
||||
"overdueSinceYesterday": "Vencido desde ayer",
|
||||
"cadence": {
|
||||
"everyNDays": "Cada {days} días",
|
||||
"custom": "Programación personalizada",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "Dans {days} jours"
|
||||
},
|
||||
"overdueByDays": "En retard de {days} jours",
|
||||
"overdueSinceYesterday": "En retard depuis hier",
|
||||
"cadence": {
|
||||
"everyNDays": "Tous les {days} jours",
|
||||
"custom": "Planning personnalisé",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "Tra {days} giorni"
|
||||
},
|
||||
"overdueByDays": "In ritardo di {days} giorni",
|
||||
"overdueSinceYesterday": "In ritardo da ieri",
|
||||
"cadence": {
|
||||
"everyNDays": "Ogni {days} giorni",
|
||||
"custom": "Pianificazione personalizzata",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "{days}일 후"
|
||||
},
|
||||
"overdueByDays": "{days}일 지남",
|
||||
"overdueSinceYesterday": "어제부터 지남",
|
||||
"cadence": {
|
||||
"everyNDays": "{days}일마다",
|
||||
"custom": "사용자 지정 일정",
|
||||
|
||||
@@ -8527,6 +8527,7 @@
|
||||
"inDays": "Za {days} dni"
|
||||
},
|
||||
"overdueByDays": "Zaległe od {days} dni",
|
||||
"overdueSinceYesterday": "Zaległe od wczoraj",
|
||||
"cadence": {
|
||||
"everyNDays": "Co {days} dni",
|
||||
"custom": "Własny harmonogram",
|
||||
|
||||
@@ -52,6 +52,7 @@ const MINTED_ONLY_BY_THE_BUCKET = [
|
||||
"measurementReminders.nextDue.tomorrow",
|
||||
"measurementReminders.nextDue.inDays",
|
||||
"measurementReminders.nextDue.none",
|
||||
"measurementReminders.overdueSinceYesterday",
|
||||
];
|
||||
|
||||
/** The hook that yields the zone the surrounding dates are printed in. */
|
||||
|
||||
@@ -275,7 +275,9 @@ describe("<VorsorgeSection> loading + empty", () => {
|
||||
} as MeasurementReminder;
|
||||
remindersMock.mockReturnValue({ data: [reminder], isLoading: false });
|
||||
const html = render(<VorsorgeSection />);
|
||||
expect(html).toContain("Overdue by 1 days");
|
||||
// One day over reads "since yesterday": the counted form printed
|
||||
// "Overdue by 1 days", and the warning hue must follow both phrases.
|
||||
expect(html).toContain("Overdue since yesterday");
|
||||
expect(html).toContain("text-warning");
|
||||
});
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ import {
|
||||
useDisplayTimezone,
|
||||
} from "@/lib/i18n/context";
|
||||
import { relativeCalendarDate } from "@/lib/i18n/relative-time";
|
||||
import { relativeDueKey } from "@/lib/measurement-reminders/due-day";
|
||||
import {
|
||||
isOverdueDue,
|
||||
relativeDueKey,
|
||||
} from "@/lib/measurement-reminders/due-day";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { applyOrder, useModuleListPrefs } from "@/lib/module-list-prefs";
|
||||
import { EncounterSheet } from "@/components/encounters/encounter-sheet";
|
||||
@@ -899,8 +902,7 @@ function VorsorgeCard({
|
||||
// routes to the check-in page), never the numeric value-entry wording.
|
||||
const isScreening = isScreeningReminderType(reminder.measurementType);
|
||||
const isDue =
|
||||
due.key === "measurementReminders.nextDue.today" ||
|
||||
due.key === "measurementReminders.overdueByDays";
|
||||
due.key === "measurementReminders.nextDue.today" || isOverdueDue(due);
|
||||
const progress = intervalProgress(reminder, now);
|
||||
|
||||
// Category-style header badge: the measurement label, or "self-planned"
|
||||
@@ -1361,7 +1363,7 @@ function VorsorgeCard({
|
||||
// normal muted-resolved date. The card surface stays neutral per the house
|
||||
// rule; only this inline label carries the status hue.
|
||||
const dueIsToday = due.key === "measurementReminders.nextDue.today";
|
||||
const dueIsOverdue = due.key === "measurementReminders.overdueByDays";
|
||||
const dueIsOverdue = isOverdueDue(due);
|
||||
const nextLastSlot = (
|
||||
<div className="min-h-[2.75rem] space-y-1.5 text-sm">
|
||||
<div className="text-muted-foreground flex items-baseline justify-between gap-3">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import { relativeDueKey } from "../due-day";
|
||||
import { isOverdueDue, relativeDueKey } from "../due-day";
|
||||
|
||||
/**
|
||||
* The profile zone under test. July is deliberate: no IANA zone shifts its
|
||||
@@ -84,11 +84,33 @@ describe("relativeDueKey", () => {
|
||||
).toEqual(TOMORROW);
|
||||
});
|
||||
|
||||
it("counts a checkup from yesterday as one day overdue, however recent", () => {
|
||||
// Forty-five minutes in the past. It was still yesterday's checkup.
|
||||
it("calls a checkup from yesterday overdue since yesterday, however recent", () => {
|
||||
// Forty-five minutes in the past. It was still yesterday's checkup. Its
|
||||
// own phrase, because "overdue by 1 days" is what the counted form reads
|
||||
// as on the one day an open check-up is most likely to be looked at.
|
||||
expect(
|
||||
relativeDueKey(zoned(FRIDAY, 23, 30), at(SATURDAY, 0, 15), ZONE),
|
||||
).toEqual({ key: "measurementReminders.overdueByDays", days: 1 });
|
||||
).toEqual({ key: "measurementReminders.overdueSinceYesterday", days: 1 });
|
||||
});
|
||||
|
||||
it("counts the days for a checkup overdue longer than that", () => {
|
||||
expect(relativeDueKey(zoned(FRIDAY, 9), at(FRIDAY + 2, 10), ZONE)).toEqual({
|
||||
key: "measurementReminders.overdueByDays",
|
||||
days: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("reads both overdue phrases as overdue, and nothing else", () => {
|
||||
const now = at(SATURDAY, 12);
|
||||
expect(isOverdueDue(relativeDueKey(zoned(FRIDAY, 9), now, ZONE))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(isOverdueDue(relativeDueKey(zoned(FRIDAY - 3, 9), now, ZONE))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(isOverdueDue(relativeDueKey(zoned(SATURDAY, 9), now, ZONE))).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it("counts whole calendar days for a checkup further out", () => {
|
||||
|
||||
@@ -86,6 +86,11 @@ export function relativeDueKey(
|
||||
if (Number.isNaN(due.getTime()))
|
||||
return { key: "measurementReminders.nextDue.none", days: 0 };
|
||||
const deltaDays = calendarDaysUntil(due, new Date(now), timeZone);
|
||||
// Its own phrase rather than the counted one: "overdue by 1 days" is what
|
||||
// the counted form reads as, on the one day an open check-up (which since
|
||||
// v1.39.2 stays due after its reminder) is most likely to be looked at.
|
||||
if (deltaDays === -1)
|
||||
return { key: "measurementReminders.overdueSinceYesterday", days: 1 };
|
||||
if (deltaDays < 0)
|
||||
return {
|
||||
key: "measurementReminders.overdueByDays",
|
||||
@@ -97,3 +102,15 @@ export function relativeDueKey(
|
||||
return { key: "measurementReminders.nextDue.tomorrow", days: 1 };
|
||||
return { key: "measurementReminders.nextDue.inDays", days: deltaDays };
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a phrase from {@link relativeDueKey} says "overdue". Two keys do —
|
||||
* "since yesterday" and the counted one — so a surface that colours an
|
||||
* overdue badge asks here rather than comparing against one of them.
|
||||
*/
|
||||
export function isOverdueDue(due: RelativeDue): boolean {
|
||||
return (
|
||||
due.key === "measurementReminders.overdueByDays" ||
|
||||
due.key === "measurementReminders.overdueSinceYesterday"
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user