fix(medications): render intake datetime fields through the format-aware picker

The three intake dialogs (log, edit, dose-history add) still used a raw
datetime-local input, so they ignored the user's date-format preference.
Route them through DateTimeField like every other date surface. Also
correct a stale diastolic-floor comment in the dashboard verdict.
This commit is contained in:
Marc-André Bombeck committed 2026-06-26 14:03:39 +02:00
1 parent 1cee07b9f0
commit 8c5ef5df10
5 files changed
+38 -12

No files matched your search

@@ -26,6 +26,33 @@ vi.mock("@tanstack/react-query", () => ({
useQueryClient: () => ({}),
}));
// DateTimeField reads the client date/hour-cycle preference context, which the
// wholesale i18n mock above strips. The dialog test pins the field's value/max
// contract, not the field's own rendering, so a passthrough native input keeps
// the assertions meaningful while staying SSR-renderable.
vi.mock("@/components/ui/date-time-field", () => ({
DateTimeField: ({
id,
value,
max,
disabled,
}: {
id?: string;
value?: string;
max?: string;
disabled?: boolean;
}) => (
<input
id={id}
type="datetime-local"
value={value}
max={max}
disabled={disabled}
readOnly
/>
),
}));
vi.mock("@/components/ui/dialog", () => ({
Dialog: ({ children }: { children: React.ReactNode }) => (
<div data-slot="mock-dialog">{children}</div>
@@ -32,7 +32,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { DateTimeField } from "@/components/ui/date-time-field";
import { Switch } from "@/components/ui/switch";
import { useTranslations } from "@/lib/i18n/context";
import { invalidateKeys, medicationDependentKeys } from "@/lib/query-keys";
@@ -227,12 +227,11 @@ export function LedgerAddDialog({
<Label htmlFor="ledger-add-taken-at">
{t("medications.detail.verlauf.addDialog.takenAtLabel")}
</Label>
<Input
<DateTimeField
id="ledger-add-taken-at"
type="datetime-local"
value={takenAt}
max={toDateTimeLocal(new Date())}
onChange={(e) => setTakenAt(e.target.value)}
onChange={(value) => setTakenAt(value)}
disabled={skipped}
/>
</div>
@@ -34,7 +34,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { DateTimeField } from "@/components/ui/date-time-field";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { useFormatters, useTranslations } from "@/lib/i18n/context";
@@ -166,12 +166,11 @@ function IntakeEditDialogBody({
<Label htmlFor="intake-edit-taken-at">
{t("medications.detail.intake.edit.takenAtLabel")}
</Label>
<Input
<DateTimeField
id="intake-edit-taken-at"
type="datetime-local"
value={takenAt}
max={toDateTimeLocal(new Date())}
onChange={(e) => setTakenAt(e.target.value)}
onChange={(value) => setTakenAt(value)}
disabled={skipped}
/>
{scheduledFor && (
@@ -35,6 +35,7 @@ import {
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { DateTimeField } from "@/components/ui/date-time-field";
import { NativeSelect } from "@/components/ui/native-select";
import { Switch } from "@/components/ui/switch";
import { useTranslations } from "@/lib/i18n/context";
@@ -297,12 +298,11 @@ export function LogIntakeDialog({
<Label htmlFor="log-intake-taken-at">
{t("medications.logIntake.takenAtLabel")}
</Label>
<Input
<DateTimeField
id="log-intake-taken-at"
type="datetime-local"
value={takenAt}
max={toDateTimeLocal(new Date())}
onChange={(e) => setTakenAt(e.target.value)}
onChange={(value) => setTakenAt(value)}
disabled={skipped}
/>
<p className="text-muted-foreground text-xs">
+2 -1
View File
@@ -126,7 +126,8 @@ export function resolveDashboardVerdict(
const lastSeen = snapshot.tiles.lastSeenByType;
// ── 1 · bpCritical ─────────────────────────────────────────────────
// Fixed floors (sys ≥ 180 OR dia ≥ 110), never user thresholds, and
// Fixed floors (sys ≥ 180 OR dia ≥ 120, from clinical-floors), never user
// thresholds, and
// only while the reading is fresh (≤ 1 day, re-derived against the
// injected `now`). Sits ABOVE the overdue dose: a fresh crisis-level
// reading is the one item that must not hide behind a routine