diff --git a/messages/de.json b/messages/de.json
index 9930facb5..3dcafb78a 100644
--- a/messages/de.json
+++ b/messages/de.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Erlaubte Stellen",
"allowedSitesHint": "Alle ausgewählt lassen für keine Einschränkung. Global ausgeschlossene Stellen werden nie angeboten.",
"viewToggleLabel": "Ansicht",
+ "viewToggleHint": "Wähle, ob deine Medikamente als Karten oder als Tabelle angezeigt werden.",
"viewCards": "Kartenansicht",
"viewTable": "Tabellenansicht",
"viewSaveFailed": "Ansicht konnte nicht gespeichert werden",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Reihenfolge anpassen",
"reorderDescription": "Bestimme die Reihenfolge deiner Medikamente – sie gilt für die Karten- und die Tabellenansicht.",
"reorderSaved": "Reihenfolge gespeichert",
- "reorderSaveFailed": "Reihenfolge konnte nicht gespeichert werden"
+ "reorderSaveFailed": "Reihenfolge konnte nicht gespeichert werden",
+ "customize": "Medikamente anpassen"
},
"charts": {
"loadingLabel": "Diagramm wird geladen…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Insights",
"description": "Reihenfolge der Übersicht und der Navigations-Pills."
+ },
+ "medications": {
+ "title": "Medikamente",
+ "description": "Listenansicht und Reihenfolge der Medikamente."
}
},
"profile": "Profil",
diff --git a/messages/en.json b/messages/en.json
index f5927bd8b..a9ea8f561 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Allowed sites",
"allowedSitesHint": "Leave all selected for no restriction. Sites you excluded globally are never offered.",
"viewToggleLabel": "View",
+ "viewToggleHint": "Choose whether your medications appear as cards or as a table.",
"viewCards": "Card view",
"viewTable": "Table view",
"viewSaveFailed": "View could not be saved",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Adjust order",
"reorderDescription": "Set the order of your medications – it applies to both the card and the table view.",
"reorderSaved": "Order saved",
- "reorderSaveFailed": "Order could not be saved"
+ "reorderSaveFailed": "Order could not be saved",
+ "customize": "Customize medications"
},
"charts": {
"loadingLabel": "Loading chart…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Insights",
"description": "Overview and navigation-pill order."
+ },
+ "medications": {
+ "title": "Medications",
+ "description": "List view and medication order."
}
},
"profile": "Profile",
diff --git a/messages/es.json b/messages/es.json
index 514b42a15..63018e39e 100644
--- a/messages/es.json
+++ b/messages/es.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Sitios permitidos",
"allowedSitesHint": "Deja todos seleccionados para no aplicar restricciones. Los sitios que excluiste globalmente nunca se ofrecen.",
"viewToggleLabel": "Vista",
+ "viewToggleHint": "Elige si tus medicamentos se muestran como tarjetas o como tabla.",
"viewCards": "Vista de tarjetas",
"viewTable": "Vista de tabla",
"viewSaveFailed": "No se pudo guardar la vista",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Ajustar orden",
"reorderDescription": "Define el orden de tus medicamentos: se aplica a la vista de tarjetas y a la de tabla.",
"reorderSaved": "Orden guardado",
- "reorderSaveFailed": "No se pudo guardar el orden"
+ "reorderSaveFailed": "No se pudo guardar el orden",
+ "customize": "Personalizar medicamentos"
},
"charts": {
"loadingLabel": "Cargando la gráfica…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Análisis",
"description": "Orden de la vista general y de las pestañas de navegación."
+ },
+ "medications": {
+ "title": "Medicamentos",
+ "description": "Vista de lista y orden de los medicamentos."
}
},
"profile": "Perfil",
diff --git a/messages/fr.json b/messages/fr.json
index 68b82779e..9e24dfa09 100644
--- a/messages/fr.json
+++ b/messages/fr.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Sites autorisés",
"allowedSitesHint": "Laissez tout sélectionné pour aucune restriction. Les sites exclus globalement ne sont jamais proposés.",
"viewToggleLabel": "Affichage",
+ "viewToggleHint": "Choisis si tes médicaments s'affichent sous forme de cartes ou de tableau.",
"viewCards": "Vue cartes",
"viewTable": "Vue tableau",
"viewSaveFailed": "L'affichage n'a pas pu être enregistré",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Modifier l'ordre",
"reorderDescription": "Définis l'ordre de tes médicaments – il s'applique à la vue cartes et à la vue tableau.",
"reorderSaved": "Ordre enregistré",
- "reorderSaveFailed": "L'ordre n'a pas pu être enregistré"
+ "reorderSaveFailed": "L'ordre n'a pas pu être enregistré",
+ "customize": "Personnaliser les médicaments"
},
"charts": {
"loadingLabel": "Chargement du graphique…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Analyses",
"description": "Ordre de la vue d'ensemble et des onglets de navigation."
+ },
+ "medications": {
+ "title": "Médicaments",
+ "description": "Vue de la liste et ordre des médicaments."
}
},
"profile": "Profil",
diff --git a/messages/it.json b/messages/it.json
index 7290f0b4e..692bf94fe 100644
--- a/messages/it.json
+++ b/messages/it.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Siti consentiti",
"allowedSitesHint": "Lascia tutti selezionati per nessuna restrizione. I siti esclusi globalmente non vengono mai proposti.",
"viewToggleLabel": "Vista",
+ "viewToggleHint": "Scegli se i tuoi farmaci vengono mostrati come schede o come tabella.",
"viewCards": "Vista a schede",
"viewTable": "Vista tabella",
"viewSaveFailed": "Impossibile salvare la vista",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Modifica ordine",
"reorderDescription": "Imposta l'ordine dei tuoi farmaci: vale per la vista a schede e per la tabella.",
"reorderSaved": "Ordine salvato",
- "reorderSaveFailed": "Impossibile salvare l’ordine"
+ "reorderSaveFailed": "Impossibile salvare l’ordine",
+ "customize": "Personalizza i farmaci"
},
"charts": {
"loadingLabel": "Caricamento del grafico…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Approfondimenti",
"description": "Ordine della panoramica e delle schede di navigazione."
+ },
+ "medications": {
+ "title": "Farmaci",
+ "description": "Vista elenco e ordine dei farmaci."
}
},
"profile": "Profilo",
diff --git a/messages/pl.json b/messages/pl.json
index 21e72f180..03223cb51 100644
--- a/messages/pl.json
+++ b/messages/pl.json
@@ -1718,6 +1718,7 @@
"allowedSitesLabel": "Dozwolone miejsca",
"allowedSitesHint": "Pozostaw wszystkie zaznaczone, aby nie stosować ograniczeń. Miejsca wykluczone globalnie nigdy nie są proponowane.",
"viewToggleLabel": "Widok",
+ "viewToggleHint": "Wybierz, czy leki mają być wyświetlane jako karty, czy jako tabela.",
"viewCards": "Widok kart",
"viewTable": "Widok tabeli",
"viewSaveFailed": "Nie udało się zapisać widoku",
@@ -1737,7 +1738,8 @@
"reorderTitle": "Zmień kolejność",
"reorderDescription": "Ustal kolejność swoich leków – obowiązuje w widoku kart i w tabeli.",
"reorderSaved": "Kolejność zapisana",
- "reorderSaveFailed": "Nie udało się zapisać kolejności"
+ "reorderSaveFailed": "Nie udało się zapisać kolejności",
+ "customize": "Dostosuj leki"
},
"charts": {
"loadingLabel": "Ładowanie wykresu…",
@@ -3767,6 +3769,10 @@
"insights": {
"title": "Analizy",
"description": "Kolejność przeglądu i pigułek nawigacyjnych."
+ },
+ "medications": {
+ "title": "Leki",
+ "description": "Widok listy i kolejność leków."
}
},
"profile": "Profil",
diff --git a/src/app/medications/__tests__/list-view-toggle.test.tsx b/src/app/medications/__tests__/list-view-toggle.test.tsx
index 409997fb9..305737dd9 100644
--- a/src/app/medications/__tests__/list-view-toggle.test.tsx
+++ b/src/app/medications/__tests__/list-view-toggle.test.tsx
@@ -33,9 +33,6 @@ vi.mock("@/components/medications/wizard/MedicationWizardDialog", () => ({
vi.mock("@/components/medications/log-intake-dialog", () => ({
LogIntakeDialog: () => null,
}));
-vi.mock("@/components/medications/medication-reorder-dialog", () => ({
- MedicationReorderDialog: () => null,
-}));
import MedicationsPage from "@/app/medications/page";
import { I18nProvider } from "@/lib/i18n/context";
@@ -133,9 +130,15 @@ describe("/medications — view renders from the persisted preference", () => {
);
});
- it("offers the manual-order editor from the header", () => {
+ it("links the header customize glyph to /settings/medications", () => {
+ // v1.16.10 — same entry-point logic as the dashboard and insights
+ // headers: the Settings2 ghost icon is a plain link to the page's
+ // settings section (view preference + manual order live there).
const html = renderPage({ version: 1, view: "cards", order: [] });
- expect(html).toContain('aria-label="Adjust order"');
+ expect(html).toContain('href="/settings/medications"');
+ expect(html).toContain('aria-label="Customize medications"');
+ // The in-page order dialog is gone — no dialog trigger remains.
+ expect(html).not.toContain('aria-label="Adjust order"');
});
});
diff --git a/src/app/medications/page.tsx b/src/app/medications/page.tsx
index a0a611642..dcd1a4e54 100644
--- a/src/app/medications/page.tsx
+++ b/src/app/medications/page.tsx
@@ -2,6 +2,7 @@
import { useEffect, useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
+import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useAuth } from "@/hooks/use-auth";
import { useTranslations } from "@/lib/i18n/context";
@@ -15,7 +16,6 @@ import {
MedicationTableSkeleton,
} from "@/components/medications/medication-table";
import { MedicationViewToggle } from "@/components/medications/medication-view-toggle";
-import { MedicationReorderDialog } from "@/components/medications/medication-reorder-dialog";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
@@ -149,16 +149,13 @@ export default function MedicationsPage() {
// two paths: log an intake (incl. a backdated one) against an existing
// medication, or create a new medication (the existing wizard).
const [logIntakeOpen, setLogIntakeOpen] = useState(false);
- // v1.16.10 — manual-order editor (shared by both views).
- const [reorderOpen, setReorderOpen] = useState(false);
// v1.16.10 — the persisted list presentation: cards vs table plus the
// manual medication order, server-side per user
// (`GET`/`PUT /api/medications/layout`). The toggle writes
- // optimistically; the reorder dialog saves explicitly.
- const { layout, isLayoutLoading, setView } = useMedicationListLayout(
- isAuthenticated,
- );
+ // optimistically; the order editor lives at /settings/medications.
+ const { layout, isLayoutLoading, setView } =
+ useMedicationListLayout(isAuthenticated);
useEffect(() => {
if (shouldOpenFromUrl) {
@@ -268,25 +265,27 @@ export default function MedicationsPage() {
{/* v1.16.10 — card ⇄ table view toggle, persisted server-side
- per user; plus the manual-order editor shared by both
- views. The editor opens behind the same Settings2 glyph
- the dashboard and insights headers use for their
- customize entry points, in the same slot (left of the
- add button). It only earns its slot once there is
- something to reorder. */}
+ per user. The Settings2 glyph next to it is the customize
+ shortcut to /settings/medications (view preference + the
+ manual-order editor), exactly like the dashboard and
+ insights headers link to their settings sections, in the
+ same slot (left of the add button) and with the same
+ responsive 44-px mobile tap floor. */}
- {medsArray.length > 1 && (
-
{/* v1.14.0 — the "Add" button is now a choice: log an intake
(incl. a backdated one) against an existing medication, or
create a new medication. v1.12.2 — match the dashboard Add
@@ -324,11 +323,7 @@ export default function MedicationsPage() {
// persisted view (table rows vs card grid) so resolving the data
// never swaps the footprint; while the view preference itself is
// still loading the default cards skeleton stands in.
-
+
{tableView && !isLayoutLoading ? (
) : (
@@ -462,22 +457,6 @@ export default function MedicationsPage() {
date+time that supports backdating. Submits to the existing
per-medication intake route (same slot upsert as a live "Taken"
tap) so the one-row-per-dose-slot invariant holds. */}
- {/* v1.16.10 — manual-order editor. The list is the page's current
- effective order (active block first, inactive after), so the
- dialog opens showing exactly what both views render. */}
- {reorderOpen && (
- ({
- id: m.id,
- name: m.name,
- dose: m.dose,
- active: m.active,
- }))}
- />
- )}
-
{logIntakeOpen && (
,
api: ApiSection,
diff --git a/src/components/medications/__tests__/medication-order-editor.test.tsx b/src/components/medications/__tests__/medication-order-editor.test.tsx
index 29c7486a3..55e71c5c8 100644
--- a/src/components/medications/__tests__/medication-order-editor.test.tsx
+++ b/src/components/medications/__tests__/medication-order-editor.test.tsx
@@ -1,11 +1,14 @@
/**
- * v1.16.10 — reorder dialog mirrors the page's grouping.
+ * v1.16.10 — the inline manual-order editor mirrors the page's grouping.
*
* Both /medications views pin inactive medications after the active
- * block, so the dialog drafts TWO sections (Aktiv / Inaktiv) with a
+ * block, so the editor drafts TWO sections (Aktiv / Inaktiv) with a
* muted heading each: drag and arrows work within a section, and the
* saved order is active ids first, inactive ids after — by
- * construction, not by validation.
+ * construction, not by validation. The editor renders inline in the
+ * Medikamente settings section (`/settings/medications`); it started
+ * life as a dialog on the /medications page and kept its contract when
+ * it moved.
*
* Project convention is SSR-only component tests (`renderToStaticMarkup`)
* plus pure-helper tests for the interactive plumbing an SSR mount
@@ -18,24 +21,6 @@ import { renderToStaticMarkup } from "react-dom/server";
import { I18nProvider } from "@/lib/i18n/context";
-// Radix Dialog portals at runtime; collapse to plain wrappers so the
-// body materialises in static markup (same trick as the sibling suites).
-vi.mock("@/components/ui/dialog", () => {
- const Pass = ({ children }: { children?: React.ReactNode }) => (
-