mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
Settings now reads as nine groups: Account, Tracking, Arrangement, Notifications, Health profile, AI, Connections, Data and System. On a phone one button names the current section and opens the grouped list, replacing the strip of every section. What moved, every old address still working: - Sessions, trusted devices and security activity sit under Security; the privacy page anchors forward there. - Notifications holds every reminder kind: the Coach nudges and the checkup reminder switches joined, and a card names the reminders set where their subject lives (dose times, cycle reminders). - Arrangement holds order and view only. Mood tags, the labs biomarker catalog and on-device text recognition, and the injection sites live on module pages under /settings/modules/<id>, linked from each Modules row and from the module's own wrench. /settings/layout/mood redirects. - The timezone saves on change in the Display card, with a one-tap offer of the device zone. - Screening hints sit beside the life circumstances they come from. - System gains Preview features with the Topics switch. Duplicates: the Coach and MCP pages show their state and link to the one switch in Modules (turning MCP off keeps tokens), the Coach overlay shows the provider and model with a link to Settings > AI instead of a second set of selects, and the privacy page drops its copy of the export links. A guard walks every historical /settings address through the redirects and every forwarded anchor to a page that renders.
71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Old deep links into cards that moved to another Settings page.
|
|
*
|
|
* A path that moved is a server redirect (`next.config.ts`), but a card that
|
|
* moved while its page stayed cannot be: the `#anchor` never reaches the
|
|
* server. Bookmarks, cross-links in older notifications and the docs point at
|
|
* `/settings/privacy#sessions` and the like, so the shell forwards a known
|
|
* anchor on a known page to the card's new home, once, on arrival.
|
|
*
|
|
* `SETTINGS_ANCHOR_FORWARDS` is also read by the legacy-routes guard, which
|
|
* proves every target lands on a page that exists.
|
|
*/
|
|
|
|
import { useEffect } from "react";
|
|
import { usePathname, useRouter } from "next/navigation";
|
|
|
|
export const SETTINGS_ANCHOR_FORWARDS: Readonly<
|
|
Record<string, Readonly<Record<string, string>>>
|
|
> = {
|
|
// v1.44 — sessions, trusted devices and the security activity joined the
|
|
// other sign-in controls under Security; the duplicate export card left.
|
|
"/settings/privacy": {
|
|
sessions: "/settings/security#sessions",
|
|
"trusted-devices": "/settings/security#trusted-devices",
|
|
"security-activity": "/settings/security#security-activity",
|
|
"your-data-export": "/settings/export",
|
|
},
|
|
// v1.44 — the proactive nudges are a reminder and live with the others.
|
|
"/settings/coach": {
|
|
"coach-nudge": "/settings/notifications#coach-nudge",
|
|
},
|
|
// v1.44 — Arrangement holds order and view only; each module's own
|
|
// settings moved to its page under Modules.
|
|
"/settings/layout/labs": {
|
|
"labs-local-ocr": "/settings/modules/labs#labs-local-ocr",
|
|
"labs-biomarkers": "/settings/modules/labs#labs-biomarkers",
|
|
},
|
|
"/settings/layout/medications": {
|
|
"injection-sites": "/settings/modules/medications#injection-sites",
|
|
},
|
|
"/settings/layout/vorsorge": {
|
|
"screening-hints": "/settings/anamnesis#screening-hints",
|
|
"vorsorge-reminders": "/settings/notifications#vorsorge-reminders",
|
|
},
|
|
};
|
|
|
|
/** Where an anchor on a page now lives, or null when it did not move. */
|
|
export function forwardedAnchorTarget(
|
|
pathname: string,
|
|
hash: string,
|
|
): string | null {
|
|
const anchor = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
if (!anchor) return null;
|
|
return SETTINGS_ANCHOR_FORWARDS[pathname]?.[anchor] ?? null;
|
|
}
|
|
|
|
export function SettingsAnchorForward() {
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
|
|
useEffect(() => {
|
|
if (!pathname) return;
|
|
const target = forwardedAnchorTarget(pathname, window.location.hash);
|
|
if (target) router.replace(target);
|
|
}, [pathname, router]);
|
|
|
|
return null;
|
|
}
|