From 7525d2ed005282a5c5665a7db0a2558c9df1392b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 8 Oct 2026 21:47:37 +0200 Subject: [PATCH] fix(settings): end the allergy and family-history cards in one action row The allergy card had two action rows, the list's add button and the free-text note's save, and the family-history card on a shared record put its sentence about relatives after the list's actions. The add button now rides the note's row before save, and the sentence moves above the list. --- .../records/allergy-free-text-note.tsx | 26 +++++++--- src/components/records/allergy-manager.tsx | 48 ++++++++++++------- .../anamnesis-about-me-relocation.test.tsx | 38 ++++++++++++++- .../record-anamnesis-card-order.test.tsx | 33 +++++++++++++ src/components/settings/anamnesis-section.tsx | 8 ++-- .../settings/record-anamnesis-section.tsx | 8 ++-- 6 files changed, 130 insertions(+), 31 deletions(-) create mode 100644 src/components/settings/__tests__/record-anamnesis-card-order.test.tsx diff --git a/src/components/records/allergy-free-text-note.tsx b/src/components/records/allergy-free-text-note.tsx index 1e0d63416..f9efc719b 100644 --- a/src/components/records/allergy-free-text-note.tsx +++ b/src/components/records/allergy-free-text-note.tsx @@ -21,7 +21,7 @@ * Plain text only — the value renders exclusively through the input; no * markdown anywhere. */ -import { useState } from "react"; +import { useState, type ReactNode } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Loader2 } from "lucide-react"; import { toast } from "sonner"; @@ -50,7 +50,15 @@ interface AboutMeData { const FIELD_CLASSES = "border-input bg-background placeholder:text-muted-foreground focus-visible:border-input-focus w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none"; -export function AllergyFreeTextNote() { +export function AllergyFreeTextNote({ + leadingAction, +}: { + /** + * The card's other action (the allergy list's add button), placed before + * Save so the card ends in one action row (design standards §12). + */ + leadingAction?: ReactNode; +} = {}) { const { t } = useTranslations(); const queryClient = useQueryClient(); const [draft, setDraft] = useState(null); @@ -121,12 +129,18 @@ export function AllergyFreeTextNote() { onChange={(e) => setDraft(e.target.value)} /> {query.isError ? ( - query.refetch()} - /> + <> + query.refetch()} + /> + {leadingAction ? ( + {leadingAction} + ) : null} + ) : ( + {leadingAction} + ) : null; + return (
{isLoading ? ( @@ -146,21 +169,12 @@ export function AllergyManager() { )} {/* The add action closes the list (design standards §12); an empty - list leaves it to the empty state's own button. Outline here, - because the card's primary is the free-text note's Save below. */} - {!isLoading && !isError && rows.length > 0 ? ( - - - - ) : null} + list leaves it to the empty state's own button. Outline, because + where the card carries the free-text note its Save is the primary + in the same row. */} + {afterList + ? afterList(addAction) + : addAction && {addAction}} ({ HealthProfileFactsManager: () => null, })); vi.mock("@/components/records/allergy-manager", () => ({ - AllergyManager: () =>
, + AllergyManager: ({ + afterList, + }: { + afterList?: (add: React.ReactNode) => React.ReactNode; + }) => ( +
+ {afterList ? ( + afterList(