diff --git a/src/components/measurement-reminders/__tests__/checkup-card-badges.test.tsx b/src/components/measurement-reminders/__tests__/checkup-card-badges.test.tsx new file mode 100644 index 000000000..a506fa832 --- /dev/null +++ b/src/components/measurement-reminders/__tests__/checkup-card-badges.test.tsx @@ -0,0 +1,74 @@ +import { describe, expect, it, vi } from "vitest"; +import { renderToStaticMarkup } from "react-dom/server"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +import { I18nProvider } from "@/lib/i18n/context"; +import type { MeasurementReminder } from "@/hooks/use-measurement-reminders"; + +/** + * A checkup that is switched off, or that the Coach created, says so in the + * card view. The list view used to drop both badges, so a disabled checkup + * looked active there; which view a person sees is a remembered preference, + * so the same checkup read differently depending on a toggle. + */ + +vi.mock("next/navigation", () => ({ + useRouter: () => ({ replace: vi.fn(), push: vi.fn() }), +})); + +import { VorsorgeCard } from "../checkups/checkup-card"; + +const reminder = { + id: "coach-off", + label: "Check blood pressure", + measurementType: null, + intervalDays: 30, + rrule: null, + anchorDate: null, + endsOn: null, + origin: "COACH", + nextDueAt: null, + notifyHour: 9, + location: null, + lastSatisfiedAt: null, + enabled: false, + createdAt: "2030-01-01T00:00:00.000Z", + updatedAt: "2030-01-01T00:00:00.000Z", +} as MeasurementReminder; + +function render(view: "cards" | "list"): string { + const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, + }); + const noop = () => {}; + return renderToStaticMarkup( + + + + + , + ); +} + +describe("checkup state badges", () => { + it.each(["cards", "list"] as const)( + "show the Coach and switched-off badges in the %s view", + (view) => { + const html = render(view); + expect(html).toContain("Check blood pressure"); + expect(html).toContain(">Coach<"); + expect(html).toContain(">Off<"); + }, + ); +}); diff --git a/src/components/measurement-reminders/checkups/checkup-card.tsx b/src/components/measurement-reminders/checkups/checkup-card.tsx index 94777114b..744da0d82 100644 --- a/src/components/measurement-reminders/checkups/checkup-card.tsx +++ b/src/components/measurement-reminders/checkups/checkup-card.tsx @@ -244,6 +244,30 @@ function NextLastSlot({ ); } +/** + * The Coach-origin and switched-off badges, shared by the card and the list + * view; `undefined` when neither applies, so no empty row is drawn. + */ +function checkupStateBadges( + reminder: MeasurementReminder, + t: (key: string) => string, +): React.ReactNode { + const isCoach = reminder.origin === "COACH"; + if (!isCoach && reminder.enabled) return undefined; + return ( + <> + {isCoach && ( + {t("measurementReminders.originCoach")} + )} + {!reminder.enabled && ( + + {t("measurementReminders.disabledBadge")} + + )} + + ); +} + /** The dense list variant of a checkup. */ function CheckupListRow({ reminder, @@ -251,6 +275,7 @@ function CheckupListRow({ categoryLabel, cadenceText, meta, + stateBadges, isLinked, isScreening, canManageMeasurements, @@ -265,6 +290,8 @@ function CheckupListRow({ categoryLabel: string; cadenceText: string | null; meta: React.ReactNode; + /** The same Coach and disabled badges the card view shows. */ + stateBadges: React.ReactNode; isLinked: boolean; isScreening: boolean; canManageMeasurements: boolean; @@ -283,6 +310,7 @@ function CheckupListRow({ {resolveReminderLabel(reminder, t)} + {stateBadges} {/* Cadence rides on the metric line, styled like the metric text (no shaded pill). */} @@ -537,7 +565,6 @@ export function VorsorgeCard({ : reminder.rrule ? t("measurementReminders.cadence.custom") : ""; - const isCoach = reminder.origin === "COACH"; const isLinked = reminder.measurementType != null; // A screening reminder's action starts the check-in, never numeric entry. const isScreening = isScreeningReminderType(reminder.measurementType); @@ -558,20 +585,7 @@ export function VorsorgeCard({ ? `/measurements?type=${encodeURIComponent(reminder.measurementType as string)}` : undefined; - // Provenance and disabled badges get a row only when one applies. - const hasStateBadges = isCoach || !reminder.enabled; - const stateBadges = hasStateBadges ? ( - <> - {isCoach && ( - {t("measurementReminders.originCoach")} - )} - {!reminder.enabled && ( - - {t("measurementReminders.disabledBadge")} - - )} - - ) : undefined; + const stateBadges = checkupStateBadges(reminder, t); const headerActions = canManageMeasurements ? (