import type { ReactNode } from "react"; import { Link, NavLink } from "react-router-dom"; import { ru } from "../content/ru"; import { useDialog } from "../dialog/DialogContext"; import { useSession } from "../session/SessionContext"; import { HotlineCard, useHelp } from "./HelpSheet"; import { Icon, LogoMark, type IconName } from "./Icon"; /* * Shared patient workspace, following the approved doctor dashboard. * phone: content → «Экстренная помощь» block → bottom tab bar (signed in) * desktop: white sidebar | workspace header | content + emergency panel * bare: one centred column on every width (questionnaires) */ const TABS: { to: string; label: string; icon: IconName }[] = [ { to: "/today", label: ru.nav.today, icon: "home" }, { to: "/meds", label: ru.nav.meds, icon: "pill" }, { to: "/doctor", label: ru.nav.doctor, icon: "doctor" }, { to: "/profile", label: ru.nav.profile, icon: "user" }, ]; /** Inline emergency block shown at the bottom of every phone screen (hidden on desktop: the rail has it). */ export function EmergencyBlock() { const { resources, open } = useHelp(); return (
{resources.slice(0, 2).map((r) => ( ))}
); } function Sidebar({ signedIn }: { signedIn: boolean }) { const { open } = useHelp(); const { unread } = useDialog(); return ( ); } function BottomNav() { return ( ); } function Rail({ aside }: { aside?: ReactNode }) { const { resources, open } = useHelp(); return ( ); } function WorkspaceHeader({ signedIn, bare = false }: { signedIn: boolean; bare?: boolean }) { const { session } = useSession(); return (
{bare ? ru.product.name : signedIn ? ru.product.workspace : ru.nav.signIn}
{signedIn && !bare ? ( {session?.displayName || ru.nav.profile} ) : {ru.product.tagline}}
); } export function AppShell({ children, signedIn = true, aside, focus = false, sos = true, bare = false, }: { children: ReactNode; signedIn?: boolean; aside?: ReactNode; /** Focus screens (one question per screen) hide the tab bar on phones, like in the mocks. */ focus?: boolean; /** The crisis screen shows the hotlines itself, so it drops the bottom block. */ sos?: boolean; /** Questionnaires: no sidebar, rail or tab bar — one centred column, so nothing distracts from the answers. */ bare?: boolean; }) { if (bare) return (
{children} {sos && }
); return (
{children} {sos && }
{signedIn && !focus && }
); } export function Notice({ tone = "info", children }: { tone?: "info" | "warn" | "danger" | "ok"; children: ReactNode }) { const icon: IconName = tone === "info" ? "info" : tone === "ok" ? "check" : tone === "danger" ? "x" : "alert"; return (
{children}
); } export function TopBar({ onBack, title, children }: { onBack?: () => void; title?: string; children?: ReactNode }) { return (
{onBack && ( )} {title && {title}} {children}
); }