Files
HealthLog/src/lib/encounters/visit-links.ts
T
Marc-André Bombeck 0dcafeeb70 fix(visits): open an upcoming appointment where it lives
Visits are the second tab of `/checkups`, and the bare path opens the
first one, the preventive-care list, which never shows an appointment.
Every surface that listed an upcoming appointment linked it there: the
dashboard's next-appointment line, the Today rail item, the Today
overview fact and the appointment's push notification. A tap on the
appointment landed on the list it is not on.

Each now opens the visit itself (`/checkups?visit=<id>`), or the visits
tab (`/checkups?view=visits`) for a line naming several appointments.
The checkups page reads `view` to pick a tab. The rail item stops
borrowing the check-up item's action: it carries its own label
("View appointment") and intent `visit.view`. The appointment push names
its visit through the producer's `metadata.url` override; a check-up's
push keeps the checkups list.

The same mis-route sat on three links that lead to visits without
being upcoming: a condition's visit rows, the address book's back link
and the onboarding and timeline prompts to add a visit.

`visit-link-guard.test.ts` keeps the visit paths in the builder and
counts every bare `/checkups` per file, each with the reason it names
the checkups list.
2026-10-21 12:22:36 +02:00

53 lines
1.9 KiB
TypeScript

/**
* Where a visit lives in the app, spelled once.
*
* Visits have no page of their own: they are the second tab of `/checkups`,
* beside the preventive-care list that opens by default. A bare `/checkups`
* therefore lands on the checkups, which is the wrong half of the page for an
* appointment, and every surface that hand-spelled that path for a visit (the
* dashboard's next-appointment line, the Today rail, the Today overview, the
* appointment's push) sent the person to the list the appointment is not on.
*
* Every link to one visit or to the visits list is built here. The checkups
* page reads both parameters: `visit` opens that visit on the visits tab
* (`src/hooks/use-deep-linked-record.ts`), `view` picks a tab.
* `visit-link-guard.test.ts` refuses a hand-spelled copy elsewhere.
*
* Pure and client-safe: no server imports.
*/
/** The tabs of the checkups page, as the `view` parameter names them. */
export const CHECKUPS_VIEWS = [
"vorsorge",
"visits",
"procedures",
"body-sites",
] as const;
export type CheckupsView = (typeof CHECKUPS_VIEWS)[number];
/** The tab a `view` parameter names, or null for anything else. */
export function parseCheckupsView(
value: string | null | undefined,
): CheckupsView | null {
return (CHECKUPS_VIEWS as readonly string[]).includes(value ?? "")
? (value as CheckupsView)
: null;
}
/** The visits list: the checkups page opened on its visits tab. */
export const VISITS_PATH = "/checkups?view=visits";
/** One visit: the visits tab, scrolled to the visit and opened. */
export function visitPath(id: string): string {
return `/checkups?visit=${encodeURIComponent(id)}`;
}
/**
* Where a group of visits leads: the visit itself when there is one, the
* visits list when several share one line (a day with two appointments).
*/
export function visitsPath(ids: readonly string[]): string {
return ids.length === 1 ? visitPath(ids[0]) : VISITS_PATH;
}