// A notification email links to `#/go/`. The token is held for this tab across sign-in and // opened once the person is signed in; it grants nothing and names nobody on its own. const SESSION_KEY = 'akashere_notification_link_token'; const GO_PATH = /^#\/go\/([0-9a-f]{64})(?:[/?].*)?$/; export type NotificationDestination = | { kind: 'appointment'; id: string } | { kind: 'task'; id: string } | { kind: 'message'; id: string } | { kind: 'record' } | { kind: 'home' }; export const extractNotificationLinkToken = (hash: string): string | null => GO_PATH.exec(hash ?? '')?.[1] ?? null; export const getNotificationLinkToken = (): string | null => { try { return window.sessionStorage.getItem(SESSION_KEY); } catch { return null; } }; export const clearNotificationLinkToken = (): void => { try { window.sessionStorage.removeItem(SESSION_KEY); } catch { // ignore } }; /** * Hold a `#/go/` link for this tab and take it out of the address bar, so it is not left in * history or on a shared screen. sessionStorage, so it dies with the tab. */ export const captureNotificationLink = ( hash: string = window.location.hash, replaceHash: (hash: string) => void = (next) => window.history.replaceState(null, '', next), ): boolean => { const token = extractNotificationLinkToken(hash); if (!token) return false; try { window.sessionStorage.setItem(SESSION_KEY, token); } catch { // Without storage the link cannot survive sign-in; the portal still opens. } try { replaceHash('#/'); } catch { // ignore } return true; }; /** The route state a destination opens with: a record update opens on the practice it came from. */ export const destinationState = (destination: NotificationDestination, organization?: { id: string }) => destination.kind === 'record' && organization?.id ? { recordPractice: organization.id } : undefined; /** The portal route a destination opens. */ export const destinationPath = (destination: NotificationDestination): string => { switch (destination.kind) { case 'appointment': return '/dashboard/my-appointments'; case 'task': return `/dashboard/home/task/${encodeURIComponent(destination.id)}`; case 'message': return '/dashboard/messages'; case 'record': return '/dashboard/patient'; default: return '/dashboard/home'; } };