merge(DF2): v1.21.0

This commit is contained in:
Marc-André Bombeck committed 2026-06-26 12:39:17 +02:00
commit a5031607d8
10 files changed
+44 -38

No files matched your search

+3
View File
@@ -59,6 +59,9 @@ test.describe("medication wizard — daily", () => {
// Step 4 — course window (today by default).
await expectStep(page, 4);
// `DateField` keeps the ISO value on a hidden native date input
// (data-slot), while the visible overlay paints the locale-formatted
// string. Assert the committed ISO value on the hidden input.
await expect(
page.locator('[data-slot="course-window-starts"]'),
).toHaveValue(/^\d{4}-\d{2}-\d{2}$/);
+9 -1
View File
@@ -62,7 +62,15 @@ test.describe("medication wizard — one-shot", () => {
// Step 4 — course window. Set startsOn to a deterministic date so
// the post body assertion below is stable.
await expectStep(page, 4);
await page.locator('[data-slot="course-window-starts"]').fill("2026-10-15");
// `DateField` rides a visible text overlay (the data-testid) that parses
// a typed ISO string back to the canonical value; the hidden native input
// (data-slot) carries the committed ISO. Type into the overlay, then blur
// so the parse commits.
await page.getByTestId("course-window-starts-field").fill("2026-10-15");
await page.getByTestId("course-window-starts-field").blur();
await expect(
page.locator('[data-slot="course-window-starts"]'),
).toHaveValue("2026-10-15");
await clickNext(page);
// Step 5 — pick Einmalig. The path compresses to 5 steps the
+4 -4
View File
@@ -19,6 +19,7 @@ import { Activity, CalendarDays, NotebookPen, Thermometer } from "lucide-react";
import { ResponsiveSheet } from "@/components/ui/responsive-sheet";
import { SheetSection, SheetSectionCount } from "@/components/ui/sheet-section";
import { Button } from "@/components/ui/button";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
@@ -266,14 +267,13 @@ export function LogDaySheet({
<Label htmlFor="illness-log-date" className="sr-only">
{t("illness.sheet.day")}
</Label>
<Input
<DateField
id="illness-log-date"
type="date"
value={selectedDate}
min={onsetDate}
max={date}
onChange={(e) => {
if (e.target.value) setSelectedDate(e.target.value);
onChange={(value) => {
if (value) setSelectedDate(value);
}}
className="max-w-44"
/>
+3 -3
View File
@@ -10,6 +10,7 @@ import { useState } from "react";
import { ResponsiveSheet } from "@/components/ui/responsive-sheet";
import { Button } from "@/components/ui/button";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
@@ -230,12 +231,11 @@ export function NewEpisodeSheet({
<div className="space-y-1.5">
<Label htmlFor="illness-onset">{t("illness.new.onset")}</Label>
<Input
<DateField
id="illness-onset"
type="date"
value={onset}
max={today}
onChange={(e) => setOnset(e.target.value)}
onChange={setOnset}
className="max-w-44"
/>
</div>
+3 -5
View File
@@ -25,6 +25,7 @@ import {
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTranslations } from "@/lib/i18n/context";
@@ -178,13 +179,10 @@ export function OcrRowEditor({
<Label htmlFor={`${fieldId}-date`} className="text-xs">
{t("labs.ocr.dateLabel")}
</Label>
<Input
<DateField
id={`${fieldId}-date`}
type="date"
value={row.takenAt ?? ""}
onChange={(e) =>
onChange({ ...row, takenAt: e.target.value || null })
}
onChange={(value) => onChange({ ...row, takenAt: value || null })}
/>
</div>
</div>
@@ -64,6 +64,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DateField } from "@/components/ui/date-field";
import { EmptyState } from "@/components/ui/empty-state";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
@@ -598,12 +599,11 @@ export function VorsorgeSection({
<Label htmlFor="vorsorge-anchor">
{t("measurementReminders.form.firstDue")}
</Label>
<Input
<DateField
id="vorsorge-anchor"
type="date"
value={form.anchorDate}
onChange={(e) =>
setForm((f) => ({ ...f, anchorDate: e.target.value }))
onChange={(value) =>
setForm((f) => ({ ...f, anchorDate: value }))
}
/>
</div>
@@ -49,6 +49,7 @@
import { useCallback, useId, useMemo } from "react";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTranslations } from "@/lib/i18n/context";
@@ -602,13 +603,11 @@ function YearlyDate({
<Label htmlFor={id} className="text-sm">
{t(`${i18nPrefix}.yearly.date.label`)}
</Label>
<Input
<DateField
id={id}
type="date"
value={value}
disabled={disabled}
onChange={(e) => onChange(e.target.value)}
className="h-11"
onChange={onChange}
data-slot="cadence-yearly-date"
/>
</div>
@@ -25,7 +25,7 @@
import { useCallback, useId, useMemo } from "react";
import { Input } from "@/components/ui/input";
import { DateField } from "@/components/ui/date-field";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { useTranslations } from "@/lib/i18n/context";
@@ -135,15 +135,15 @@ export function CourseWindowRow({
<Label htmlFor={startId} className="text-sm">
{t(`${i18nPrefix}.startsOn.label`)}
</Label>
<Input
<DateField
id={startId}
type="date"
value={startsIso}
disabled={disabled}
onChange={(e) => onStartsChange(e.target.value)}
className="h-11 w-full"
onChange={onStartsChange}
className="w-full"
aria-label={t(`${i18nPrefix}.startsOn.label`)}
data-slot="course-window-starts"
data-testid="course-window-starts-field"
/>
</div>
@@ -152,17 +152,16 @@ export function CourseWindowRow({
<Label htmlFor={endId} className="text-sm">
{t(`${i18nPrefix}.endsOn.label`)}
</Label>
<Input
<DateField
id={endId}
type="date"
value={endsIso}
disabled={disabled || noEndDate || lockEndsToStart}
readOnly={lockEndsToStart}
onChange={(e) => onEndsChange(e.target.value)}
className="h-11 w-full"
onChange={onEndsChange}
className="w-full"
aria-label={t(`${i18nPrefix}.endsOn.label`)}
aria-invalid={!valid || undefined}
data-slot="course-window-ends"
data-testid="course-window-ends-field"
/>
{lockEndsToStart && (
<p
@@ -56,6 +56,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { DateField } from "@/components/ui/date-field";
import { EmptyState } from "@/components/ui/empty-state";
import { Input } from "@/components/ui/input";
import {
@@ -649,12 +650,10 @@ export function AddInventoryDialog({
>
{t("medications.detail.bestand.addExpiryLabel")}
</label>
<Input
<DateField
id="inventory-add-expiry"
type="date"
autoComplete="off"
value={expiry}
onChange={(e) => setExpiry(e.target.value)}
onChange={setExpiry}
/>
</div>
<DialogFooter>
@@ -13,7 +13,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { DateInput } from "@/components/ui/date-input";
import { DateField } from "@/components/ui/date-field";
import { Label } from "@/components/ui/label";
import { NativeSelect } from "@/components/ui/native-select";
import { PasswordInput } from "@/components/ui/password-input";
@@ -373,10 +373,10 @@ export function AccountSection() {
<div className="grid gap-4 sm:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="dob">{t("settings.dateOfBirth")}</Label>
<DateInput
<DateField
id="dob"
value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)}
onChange={setDateOfBirth}
max={new Date().toISOString().slice(0, 10)}
/>
<p className="text-muted-foreground text-xs">