@odla-ai/chapter 0.25.3 → 0.25.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/{chunk-AWBRQH7E.js → chunk-5SWVMJZN.js} +1 -1
- package/dist/chunk-5SWVMJZN.js.map +1 -0
- package/dist/ui/admin/index.d.ts +5 -1
- package/dist/ui/admin/index.js +1 -1
- package/dist/ui/index.js +1 -1
- package/package.json +1 -1
- package/runbooks/adopt-existing.md +39 -0
- package/dist/chunk-AWBRQH7E.js.map +0 -1
package/README.md
CHANGED
|
@@ -493,6 +493,34 @@ The responsive state and data loading belong to `@odla-ai/crm`; the branded
|
|
|
493
493
|
summary, list presentation, record heading, and specialized panels can remain
|
|
494
494
|
host-owned:
|
|
495
495
|
|
|
496
|
+
For an operating site, first preserve the validated workspace whole. A matching
|
|
497
|
+
`people` id or “People” label says where to compose; it does not establish
|
|
498
|
+
feature parity:
|
|
499
|
+
|
|
500
|
+
```tsx
|
|
501
|
+
const workspaces = (defaults) => {
|
|
502
|
+
if (!defaults.some((workspace) => workspace.id === "people")) {
|
|
503
|
+
throw new Error("expected ChapterAdmin people workspace");
|
|
504
|
+
}
|
|
505
|
+
return defaults.map((workspace) =>
|
|
506
|
+
workspace.id === "people"
|
|
507
|
+
? { ...workspace, render: (ctx) => <ExistingPeople context={ctx} /> }
|
|
508
|
+
: workspace
|
|
509
|
+
);
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
<ChapterAdmin chapter={chapter} workspaces={workspaces} />;
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Match the exact `people` id and fail closed if Chapter changes its catalog;
|
|
516
|
+
matching only the displayed label can silently replace the wrong workspace.
|
|
517
|
+
This keeps Chapter's reviewed workspace metadata and surrounding shell while
|
|
518
|
+
the host retains its summaries, exploration model, role signals, record
|
|
519
|
+
operations, and state handling. Replace that adapter incrementally only after
|
|
520
|
+
the corresponding behavior has an executable parity check. A greenfield site
|
|
521
|
+
can begin with Chapter's defaults because there is no operating workspace to
|
|
522
|
+
preserve.
|
|
523
|
+
|
|
496
524
|
```tsx
|
|
497
525
|
const people = collectionSection({
|
|
498
526
|
crm: chapter.crm,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/admin.tsx","../src/ui/chrome.tsx","../src/ui/admin-layout.tsx","../src/ui/admin-brand.tsx","../src/ui/admin-route.ts","../src/ui/admin-workspaces.tsx","../src/ui/admin-availability.tsx","../src/ui/admin-api.ts","../src/ui/admin-billing.tsx","../src/ui/admin-dashboard.tsx","../src/ui/admin-email.tsx","../src/ui/admin-people-workspace.tsx","../src/ui/admin-record-actions.tsx","../src/ui/admin-network.tsx","../src/ui/admin-record-activity.tsx","../src/ui/admin-record-comms.tsx","../src/ui/admin-record-scheduling.tsx","../src/ui/admin-people.tsx","../src/ui/admin-frame.tsx","../src/ui/admin-appearance.ts","../src/ui/admin-auth.ts","../src/ui/admin-defaults.ts","../src/ui/admin-meetings.tsx"],"sourcesContent":["// ChapterAdmin owns auth and operational wiring; sites choose or replace chrome\n// and workspaces without reimplementing the boundary.\nimport type { ComponentChildren } from \"preact\";\nimport { useEffect, useMemo, useRef, useState } from \"preact/hooks\";\nimport { ClerkGate, SignedIn, SignedOut, SignIn, useClerkAuth } from \"@odla-ai/auth-clerk\";\nimport { CrmClient } from \"@odla-ai/crm\";\nimport { S, Gate, AdminShell } from \"./chrome.js\";\nimport { defaultAdminWorkspaces } from \"./admin-workspaces.js\";\nimport { AdminTheme, signInRedirect } from \"./admin-frame.js\";\nimport { useScopedClerkAppearance } from \"./admin-appearance.js\";\nimport {\n DEFAULT_ADMIN_AUTH,\n loadChapterAdminConfig,\n loadChapterAdminUser,\n type ChapterAdminAuthAdapter,\n type ChapterAdminUser,\n} from \"./admin-auth.js\";\nimport type {\n AdminAccountMenuProps,\n AdminChrome,\n AdminRouting,\n AdminSection,\n AdminShellProps,\n AdminWorkspace,\n AdminWorkspaceNavProps,\n Brand,\n} from \"./chrome.js\";\nimport type { Chapter } from \"../types\";\nimport { DEFAULT_CHAPTER_COPY, formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\nexport type {\n AdminSection,\n AdminSectionContext,\n AdminWorkspace,\n AdminRouteState,\n AdminRouteTarget,\n} from \"./chrome.js\";\nexport { loadChapterAdminConfig, loadChapterAdminUser } from \"./admin-auth.js\";\nexport type {\n ChapterAdminAuthAdapter,\n ChapterAdminAuthConfig,\n ChapterAdminAuthLoadContext,\n ChapterAdminUser,\n} from \"./admin-auth.js\";\n\n/** Configuration for the Clerk-gated, brand-scoped Chapter admin console. */\nexport interface ChapterAdminProps {\n chapter?: Chapter;\n /**\n * Replace or transform the standard workspace set. During existing-site\n * adoption, use the transform to preserve a validated host workspace until\n * feature-level parity is proven; matching ids or labels are not parity.\n */\n workspaces?:\n | AdminWorkspace[]\n | ((defaults: readonly AdminWorkspace[]) => AdminWorkspace[]);\n /** @deprecated Use workspaces. */\n sections?: AdminSection[];\n basePath?: string;\n brand?: Brand;\n crmBasePath?: string;\n apiBase?: string;\n /** Default fragment: `/admin/#people/person/record-id/profile`. */\n routing?: AdminRouting;\n /** Default embedded. Standalone adds packaged global chrome. */\n chrome?: AdminChrome;\n renderHeader?: AdminShellProps[\"renderHeader\"];\n renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;\n /** Adapt existing config/current-user endpoints without rewriting auth. */\n auth?: ChapterAdminAuthAdapter;\n}\n\nfunction Authed(props: {\n workspaces: AdminWorkspace[];\n basePath: string;\n brand: Brand;\n crmBasePath: string;\n apiBase: string;\n routing: AdminRouting;\n chrome: AdminChrome;\n auth: ChapterAdminAuthAdapter;\n renderHeader?: AdminShellProps[\"renderHeader\"];\n renderAccountMenu?: AdminShellProps[\"renderAccountMenu\"];\n renderWorkspaceNav?: AdminShellProps[\"renderWorkspaceNav\"];\n}) {\n const copy = useChapterCopy().admin;\n const {\n workspaces,\n basePath,\n brand,\n crmBasePath,\n apiBase,\n routing,\n chrome,\n auth,\n renderHeader,\n renderAccountMenu,\n renderWorkspaceNav,\n } = props;\n const { getToken, signOut } = useClerkAuth();\n const client = useMemo(\n () =>\n new CrmClient({\n basePath: crmBasePath,\n headers: async (): Promise<Record<string, string>> => {\n const token = await getToken();\n return token ? { authorization: `Bearer ${token}` } : {};\n },\n }),\n [getToken, crmBasePath],\n );\n const [state, setState] = useState<{\n status: \"checking\" | \"ok\" | \"denied\";\n email?: string | null;\n user?: ChapterAdminUser;\n }>({ status: \"checking\" });\n\n useEffect(() => {\n let live = true;\n void (async () => {\n try {\n const body = await loadChapterAdminUser(auth, apiBase, getToken);\n const authorized = auth.isAuthorized\n ? auth.isAuthorized(body)\n : body.authorized === true;\n if (live) setState({\n status: authorized ? \"ok\" : \"denied\",\n email: typeof body.email === \"string\" ? body.email : null,\n user: body,\n });\n } catch {\n if (live) setState({ status: \"denied\" });\n }\n })();\n return () => {\n live = false;\n };\n }, [getToken, apiBase, auth]);\n\n if (state.status === \"checking\") return <Gate brand={brand}><p style={S.muted}>{copy.auth.checking}</p></Gate>;\n if (state.status === \"denied\") {\n return (\n <Gate brand={brand}>\n <div className=\"card\" style={S.card}>\n <h2 style={{ marginTop: 0 }}>{copy.auth.notAuthorized}</h2>\n <p style={S.muted}>\n {formatChapterCopy(copy.auth.accountNotAuthorized, {\n account: state.email ?? copy.auth.thisAccount,\n })}\n </p>\n <button className=\"btn secondary\" onClick={() => signOut()}>{copy.auth.signOut}</button>\n </div>\n </Gate>\n );\n }\n return (\n <AdminShell\n workspaces={workspaces}\n basePath={basePath}\n brand={brand}\n client={client}\n getToken={getToken}\n signOut={signOut}\n email={state.email ?? null}\n currentUser={state.user}\n routing={routing}\n chrome={chrome}\n renderHeader={renderHeader}\n renderAccountMenu={renderAccountMenu}\n renderWorkspaceNav={renderWorkspaceNav}\n />\n );\n}\n\n/** Render the complete authenticated admin application from one Chapter config. */\nexport function ChapterAdmin(props: ChapterAdminProps) {\n const copy = props.chapter?.copy ?? DEFAULT_CHAPTER_COPY;\n const defaults = useMemo(\n () => (props.chapter ? defaultAdminWorkspaces(props.chapter) : []),\n [props.chapter],\n );\n const workspaces = useMemo(() => {\n if (typeof props.workspaces === \"function\") return props.workspaces(defaults);\n return props.workspaces ?? props.sections ?? defaults;\n }, [props.workspaces, props.sections, defaults]);\n const basePath = props.basePath ?? \"/admin\";\n const brand = props.brand ?? {\n name: props.chapter?.name ?? copy.admin.shell.adminName,\n badge: props.chapter?.brand.badge,\n wordmark: props.chapter?.brand.wordmark,\n };\n const crmBasePath = props.crmBasePath ?? \"/api/crm\";\n const apiBase = props.apiBase ?? \"\";\n const routing = props.routing ?? \"fragment\";\n const chrome = props.chrome ?? \"embedded\";\n const auth = props.auth ?? DEFAULT_ADMIN_AUTH;\n const redirect = signInRedirect(basePath, workspaces);\n const [publishableKey, setPublishableKey] = useState<string | null | undefined>(undefined);\n\n const scopeRef = useRef<HTMLDivElement>(null);\n const appearance = useScopedClerkAppearance(scopeRef);\n\n useEffect(() => {\n let live = true;\n void loadChapterAdminConfig(auth, apiBase)\n .then((config) =>\n live && setPublishableKey(config.publishableKey ?? null))\n .catch(() => live && setPublishableKey(null));\n return () => {\n live = false;\n };\n }, [apiBase, auth]);\n\n let content: ComponentChildren;\n // A mounted Clerk widget keeps its startup palette, so wait for the scope\n // rather than mounting it against the defaults and re-theming after.\n if (publishableKey === undefined || (publishableKey && !appearance)) {\n content = <Gate brand={brand}><p style={S.muted}>{copy.admin.auth.loading}</p></Gate>;\n } else if (!publishableKey) {\n content = (\n <Gate brand={brand}>\n <div className=\"card\" style={S.card}>\n <h2 style={{ marginTop: 0 }}>{copy.admin.auth.signInNotConfigured}</h2>\n <p style={S.muted}>{copy.admin.auth.missingPublishableKey}</p>\n </div>\n </Gate>\n );\n } else if (workspaces.length === 0) {\n content = <Gate brand={brand}><p style={S.muted}>{copy.admin.auth.noWorkspaces}</p></Gate>;\n } else {\n content = (\n <ClerkGate\n publishableKey={publishableKey}\n appearance={appearance}\n afterSignOutUrl=\"/\"\n >\n <SignedOut>\n <Gate brand={brand} tagline={copy.admin.auth.signInTagline}>\n <SignIn\n routing=\"hash\"\n forceRedirectUrl={redirect}\n signUpForceRedirectUrl={redirect}\n />\n </Gate>\n </SignedOut>\n <SignedIn>\n <Authed\n workspaces={workspaces}\n basePath={basePath}\n brand={brand}\n crmBasePath={crmBasePath}\n apiBase={apiBase}\n routing={routing}\n chrome={chrome}\n auth={auth}\n renderHeader={props.renderHeader}\n renderAccountMenu={props.renderAccountMenu}\n renderWorkspaceNav={props.renderWorkspaceNav}\n />\n </SignedIn>\n </ClerkGate>\n );\n }\n return <AdminTheme chapter={props.chapter} scopeRef={scopeRef}>{content}</AdminTheme>;\n}\n","// Shared workspace contracts, auth gates, and signed-in Chapter admin shell.\nimport type { ComponentChildren } from \"preact\";\nimport { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { Tabs, ThemeScope, TopBar, TopBarLink } from \"@odla-ai/ui/components\";\nimport type { CrmClient } from \"@odla-ai/crm\";\nimport { ThemeWarning } from \"./admin-layout.js\";\nimport { badgeText, brandDisplay, S, type Brand } from \"./admin-brand.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport {\n adminRouteFromUrl,\n adminRouteHref,\n adminSectionFromUrl,\n adminSectionHref,\n type AdminRouteState,\n type AdminRouting,\n} from \"./admin-route.js\";\n\nexport {\n adminRouteFromUrl,\n adminRouteHref,\n adminSectionFromUrl,\n adminSectionHref,\n};\nexport type { AdminRouteState, AdminRouting };\nexport { Gate, S } from \"./admin-brand.js\";\nexport type { Brand } from \"./admin-brand.js\";\n\n/** A workspace id or partial nested route passed to navigation helpers. */\nexport type AdminRouteTarget =\n | string\n | {\n workspaceId?: string;\n viewId?: string | null;\n recordId?: string | null;\n detailTab?: string | null;\n };\n\n/** Context shared by every admin workspace and its nested views. */\nexport interface AdminSectionContext {\n client: CrmClient;\n getToken: () => Promise<string | null>;\n currentUser?: Record<string, unknown>;\n route: AdminRouteState;\n navigate: (target: AdminRouteTarget) => void;\n href: (target: AdminRouteTarget) => string;\n}\n\n/** One top-level admin workspace rendered inside the signed-in shell. */\nexport interface AdminWorkspace {\n id: string;\n label: string;\n /** Canonical nested view used when a workspace is opened without one. */\n defaultViewId?: string;\n /** Optional named @odla-ai/ui accent scoped to this workspace's content. */\n accent?: string;\n render: (ctx: AdminSectionContext) => ComponentChildren;\n}\n\n/** Legacy name for a top-level workspace. @deprecated Use AdminWorkspace. */\nexport type AdminSection = AdminWorkspace;\n/** Built-in shell presentation; embedded preserves site-owned chrome. */\nexport type AdminChrome = \"embedded\" | \"standalone\" | \"editorial\" | \"topbar\" | \"none\";\n\n/** Identity and sign-out services supplied to host-owned account controls. */\nexport interface AdminAccountMenuProps {\n brand: Brand; email: string | null;\n currentUser?: Record<string, unknown>;\n signOut: () => void;\n}\n\n/** Workspace route and navigation services supplied to host-owned navigation. */\nexport interface AdminWorkspaceNavProps {\n workspaces: readonly AdminWorkspace[]; route: AdminRouteState;\n navigate: (target: AdminRouteTarget) => void; href: (target: AdminRouteTarget) => string;\n}\n\nconst mergeRoute = (current: AdminRouteState, target: AdminRouteTarget): AdminRouteState => {\n if (typeof target === \"string\") return { workspaceId: target };\n const changingWorkspace = target.workspaceId != null && target.workspaceId !== current.workspaceId;\n const next: AdminRouteState = changingWorkspace\n ? { workspaceId: target.workspaceId! }\n : { ...current, ...(target.workspaceId ? { workspaceId: target.workspaceId } : {}) };\n for (const key of [\"viewId\", \"recordId\", \"detailTab\"] as const) {\n const value = target[key];\n if (value === null) delete next[key];\n else if (value !== undefined) next[key] = value;\n }\n if (target.viewId !== undefined && target.recordId === undefined) {\n delete next.recordId;\n delete next.detailTab;\n }\n if (target.recordId === null) delete next.detailTab;\n return next;\n};\n\nexport interface AdminShellProps {\n workspaces: AdminWorkspace[]; basePath: string; brand: Brand; client: CrmClient;\n getToken: () => Promise<string | null>;\n signOut: () => void; email: string | null;\n currentUser?: Record<string, unknown>;\n routing?: AdminRouting;\n chrome?: AdminChrome;\n renderHeader?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;\n}\n\nexport function AdminShell({\n workspaces,\n basePath,\n brand,\n client,\n getToken,\n signOut,\n email,\n currentUser,\n routing = \"fragment\",\n chrome = \"embedded\",\n renderHeader,\n renderAccountMenu,\n renderWorkspaceNav,\n}: AdminShellProps) {\n const copy = useChapterCopy().admin;\n const normalizeRoute = useCallback((candidate: AdminRouteState): AdminRouteState => {\n if (candidate.viewId) return candidate;\n const workspace = workspaces.find((item) => item.id === candidate.workspaceId);\n return workspace?.defaultViewId\n ? { ...candidate, viewId: workspace.defaultViewId }\n : candidate;\n }, [workspaces]);\n const routeFromLocation = useCallback(() => {\n if (typeof window === \"undefined\") {\n return normalizeRoute({ workspaceId: workspaces[0]?.id ?? \"\" });\n }\n return normalizeRoute(\n adminRouteFromUrl(new URL(window.location.href), basePath, workspaces.map((workspace) => workspace.id)),\n );\n }, [workspaces, basePath, normalizeRoute]);\n const [route, setRoute] = useState<AdminRouteState>(routeFromLocation);\n const href = useCallback(\n (target: AdminRouteTarget) => {\n const next = normalizeRoute(mergeRoute(route, target));\n if (typeof window === \"undefined\") {\n return `#${[\n next.workspaceId,\n next.viewId,\n next.recordId,\n next.detailTab,\n ].filter((part): part is string => Boolean(part)).map(encodeURIComponent).join(\"/\")}`;\n }\n return adminRouteHref(new URL(window.location.href), basePath, next, routing);\n },\n [route, basePath, routing, normalizeRoute],\n );\n const navigate = useCallback(\n (target: AdminRouteTarget) => {\n const next = normalizeRoute(mergeRoute(route, target));\n if (typeof window !== \"undefined\") {\n window.history.pushState(null, \"\", adminRouteHref(new URL(window.location.href), basePath, next, routing));\n }\n setRoute(next);\n },\n [route, basePath, routing, normalizeRoute],\n );\n\n useEffect(() => {\n const sync = () => setRoute(routeFromLocation());\n window.addEventListener(\"popstate\", sync);\n window.addEventListener(\"hashchange\", sync);\n return () => {\n window.removeEventListener(\"popstate\", sync);\n window.removeEventListener(\"hashchange\", sync);\n };\n }, [routeFromLocation]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const canonical = adminRouteHref(new URL(window.location.href), basePath, route, routing);\n const actual = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n if (canonical !== actual) window.history.replaceState(null, \"\", canonical);\n // Canonicalize only initial/inbound state; route changes already own history.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const context: AdminSectionContext = {\n client,\n getToken,\n ...(currentUser ? { currentUser } : {}),\n route,\n navigate,\n href,\n };\n const active = workspaces.find((workspace) => workspace.id === route.workspaceId) ?? workspaces[0];\n const accountProps: AdminAccountMenuProps = {\n brand,\n email,\n ...(currentUser ? { currentUser } : {}),\n signOut,\n };\n const identity = renderAccountMenu?.(accountProps) ?? (\n <>\n <span style={{ ...S.role, color: \"inherit\", borderColor: \"currentColor\", background: \"transparent\" }}>{copy.shell.adminRole}</span>\n {email ? <span style={{ opacity: 0.72, fontSize: 12 }}>{email}</span> : null}\n <button className=\"btn secondary mini\" onClick={signOut}>{copy.auth.signOut}</button>\n </>\n );\n const activeContent = active?.render(context);\n const workspaceContent = active?.accent\n ? <ThemeScope accent={active.accent}>{activeContent}</ThemeScope>\n : activeContent;\n\n if (chrome === \"topbar\") {\n return (\n <>\n <TopBar>\n <a className=\"topbar-brand\" href=\"/\"><span style={S.badgeSm}>{badgeText(brand)}</span>{brandDisplay(brand)}</a>\n <nav className=\"topbar-nav\" aria-label={copy.shell.navigationLabel}>\n {workspaces.map((workspace) => (\n <TopBarLink key={workspace.id} active={workspace.id === route.workspaceId} onClick={() => navigate(workspace.id)}>\n {workspace.label}\n </TopBarLink>\n ))}\n </nav>\n <span className=\"topbar-spacer\" />\n <div className=\"topbar-actions\">{identity}</div>\n </TopBar>\n <main className=\"shell-main\" style={S.main}><ThemeWarning />{workspaceContent}</main>\n </>\n );\n }\n\n const header = renderHeader\n ? renderHeader(accountProps)\n : chrome === \"standalone\" || chrome === \"editorial\" ? (\n <header style={S.masthead}>\n <a href=\"/\" style={S.mastheadBrand}><span style={S.badgeSm}>{badgeText(brand)}</span>{brandDisplay(brand)}</a>\n <span style={{ opacity: 0.68 }}>{copy.shell.adminConsole}</span>\n <span style={{ flex: 1 }} />\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>{identity}</div>\n </header>\n ) : null;\n return (\n <>\n {header}\n <main className=\"shell-main\" style={S.main}>\n <ThemeWarning />\n {renderWorkspaceNav ? (\n <>\n <div style={S.workspaceTabs}>\n {renderWorkspaceNav({ workspaces, route, navigate, href })}\n </div>\n {workspaceContent}\n </>\n ) : (\n <Tabs\n style={S.workspaceTabs}\n ariaLabel={copy.shell.navigationLabel}\n value={route.workspaceId}\n mount=\"active\"\n onValueChange={(workspaceId) =>\n setRoute(normalizeRoute({ workspaceId }))}\n items={workspaces.map((workspace) => ({\n value: workspace.id,\n label: workspace.label,\n href: href(workspace.id),\n panel: workspace.id === route.workspaceId\n ? (workspace.accent\n ? <ThemeScope accent={workspace.accent}>{workspace.render(context)}</ThemeScope>\n : workspace.render(context))\n : null,\n }))}\n />\n )}\n </main>\n </>\n );\n}\n","// Shared layout for the admin sections, so every section is a centered column of\n// odla-ui `.panel` cards with consistent width and spacing — the container the\n// chrome expects sections to own. No invented classes: `.panel`/`.muted` are\n// odla-ui's, and the width/gap is inline so it works without a per-site stylesheet.\nimport type { ComponentChildren, JSX } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\n\nconst PAGE: JSX.CSSProperties = {\n maxWidth: \"var(--ui-content-width, 1120px)\",\n margin: \"0 auto\",\n padding: \"var(--chapter-admin-page-padding, 28px 20px 64px)\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 20,\n};\nconst HEAD: JSX.CSSProperties = { display: \"flex\", alignItems: \"baseline\", justifyContent: \"space-between\", gap: 16, flexWrap: \"wrap\" };\n\n/** The centered content column every admin section renders into. */\nexport function AdminPage({ children }: { children: ComponentChildren }) {\n return <div style={PAGE}>{children}</div>;\n}\n\n/** An odla-ui `.panel` card with an optional heading + trailing actions. */\nexport function Panel({ title, actions, children }: { title?: ComponentChildren; actions?: ComponentChildren; children: ComponentChildren }) {\n return (\n <section className=\"panel\" style={{ display: \"flex\", flexDirection: \"column\", gap: 14 }}>\n {title || actions ? (\n <header style={HEAD}>\n {title ? <h2 style={{ margin: 0, fontSize: 18 }}>{title}</h2> : <span />}\n {actions ? <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>{actions}</div> : null}\n </header>\n ) : null}\n {children}\n </section>\n );\n}\n\n// odla-ui components read their colors from `--ui-*` design tokens whose VALUES\n// come from the theme layer (e.g. @odla-ai/ui/themes/paper/tokens.css + ui.css),\n// NOT from @odla-ai/ui/index.css. Loading only index.css (or a theme whose remap\n// has no primitives behind it) leaves tokens like `--ui-surface` undefined, and\n// the whole console renders transparent/broken — silently. This probes a real\n// `.panel` background and, if it's transparent, says so LOUDLY instead.\nfunction themeLooksMissing(): boolean {\n if (typeof document === \"undefined\") return false;\n const probe = document.createElement(\"div\");\n probe.className = \"panel\";\n probe.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none\";\n document.body.appendChild(probe);\n const bg = getComputedStyle(probe).backgroundColor;\n probe.remove();\n return !bg || bg === \"transparent\" || bg === \"rgba(0, 0, 0, 0)\";\n}\n\n/** A loud banner when the odla-ui theme token layer is missing. */\nexport function ThemeWarning() {\n const [missing, setMissing] = useState(false);\n useEffect(() => setMissing(themeLooksMissing()), []);\n if (!missing) return null;\n return (\n <div\n role=\"alert\"\n style={{ background: \"#7f1d1d\", color: \"#fff\", padding: \"12px 20px\", fontSize: 14, lineHeight: 1.5, textAlign: \"center\" }}\n >\n <strong>odla-ui theme tokens are missing.</strong> The console reads colors from a theme layer, not{\" \"}\n <code>@odla-ai/ui/index.css</code> alone. Import a theme before it — e.g.{\" \"}\n <code>@odla-ai/ui/themes/paper/tokens.css</code> and <code>@odla-ai/ui/themes/paper/ui.css</code> — then{\" \"}\n <code>@odla-ai/ui/index.css</code>. See the @odla-ai/chapter README (“Theme tokens”).\n </div>\n );\n}\n\n/** A centered status line for loading / empty / error states. */\nexport function AdminNote({ children }: { children: ComponentChildren }) {\n return (\n <AdminPage>\n <section className=\"panel\">\n <p className=\"muted\" style={{ margin: 0 }}>{children}</p>\n </section>\n </AdminPage>\n );\n}\n","import type { ComponentChildren, JSX } from \"preact\";\n\nexport type Brand = { name: string; badge?: string; wordmark?: ComponentChildren };\n\nexport const badgeText = (brand: Brand): string =>\n brand.badge ?? brand.name.slice(0, 3).toUpperCase();\n\nexport const brandDisplay = (brand: Brand): ComponentChildren => {\n const display = brand.wordmark ?? brand.name;\n if (typeof display !== \"string\" || !display.includes(\"&\")) return display;\n return (\n <span>\n {display.split(\"&\").map((part, index, all) => (\n <span key={`${part}:${index}`}>\n {part}\n {index < all.length - 1 ? <span className=\"mk-amp\">&</span> : null}\n </span>\n ))}\n </span>\n );\n};\n\nexport const S: Record<string, JSX.CSSProperties> = {\n gate: {\n minHeight: \"100vh\",\n display: \"grid\",\n placeItems: \"center\",\n padding: 24,\n background:\n \"radial-gradient(900px 480px at 50% -8%, var(--ui-accent-soft), transparent 70%),\" +\n \" radial-gradient(700px 500px at 110% 10%, var(--ui-good-soft), transparent 60%)\",\n },\n gateInner: { width: \"100%\", maxWidth: 400, display: \"flex\", flexDirection: \"column\", alignItems: \"center\" },\n brandBox: { textAlign: \"center\", marginBottom: 22 },\n badge: {\n width: 52, height: 52, margin: \"0 auto 14px\", display: \"grid\", placeItems: \"center\",\n fontSize: 15, fontWeight: 700, color: \"var(--ui-on-accent)\",\n background: \"linear-gradient(135deg, var(--ui-accent), var(--ui-accent-strong))\",\n borderRadius: 14, boxShadow: \"0 10px 28px var(--ui-accent-soft)\",\n },\n badgeSm: {\n width: 30, height: 30, display: \"grid\", placeItems: \"center\", fontSize: 10,\n fontWeight: 700, color: \"var(--ui-on-accent)\", background: \"var(--ui-accent)\",\n borderRadius: 8, marginRight: 10,\n },\n h1: { margin: 0, fontSize: 28, letterSpacing: \"-0.02em\", fontWeight: 700 },\n muted: { color: \"var(--ui-text-muted)\" },\n role: {\n fontFamily: \"var(--ui-font-mono)\", fontSize: 11, textTransform: \"uppercase\",\n letterSpacing: \"0.04em\", padding: \"2px 8px\", borderRadius: 999,\n background: \"var(--ui-accent-soft)\", border: \"1px solid var(--ui-accent)\",\n color: \"var(--ui-accent-strong)\",\n },\n main: { minHeight: \"calc(100vh - 61px)\", background: \"var(--ui-bg)\" },\n card: { width: \"100%\", textAlign: \"center\" },\n masthead: {\n display: \"flex\", alignItems: \"center\", gap: 16, flexWrap: \"wrap\",\n padding: \"18px max(20px, calc((100% - 1120px) / 2))\",\n color: \"var(--ui-bg)\", background: \"var(--ui-text)\",\n },\n mastheadBrand: {\n display: \"inline-flex\", alignItems: \"center\", color: \"inherit\",\n fontFamily: \"var(--ui-font-display)\", fontSize: 22, textDecoration: \"none\",\n },\n workspaceTabs: {\n maxWidth: \"var(--ui-content-width, 1160px)\",\n margin: \"0 auto\",\n padding: \"var(--chapter-admin-workspace-padding, 18px 20px 0)\",\n },\n};\n\nexport function Gate(props: { brand: Brand; tagline?: string; children: ComponentChildren }) {\n const { brand, tagline, children } = props;\n return (\n <div style={S.gate}>\n <div style={S.gateInner}>\n <div style={S.brandBox}>\n <div style={S.badge}>{badgeText(brand)}</div>\n <h1 style={S.h1}>{brandDisplay(brand)}</h1>\n {tagline ? <p style={{ ...S.muted, margin: \"8px 0 0\", fontSize: 14 }}>{tagline}</p> : null}\n </div>\n {children}\n </div>\n </div>\n );\n}\n","/** Typed URL state for the admin's nested in-page workspaces. */\nexport interface AdminRouteState {\n workspaceId: string;\n viewId?: string;\n recordId?: string;\n detailTab?: string;\n}\n\n/** URL encoding used for admin workspace state. */\nexport type AdminRouting = \"fragment\" | \"query\" | \"path\";\nexport type AdminRouteAliases = Readonly<Record<string, AdminRouteState>>;\n\nconst DEFAULT_ALIASES: AdminRouteAliases = {\n billing: { workspaceId: \"dashboard\", viewId: \"billing\" },\n meetings: { workspaceId: \"dashboard\" },\n calls: { workspaceId: \"dashboard\" },\n availability: { workspaceId: \"settings\", viewId: \"calendar\" },\n calendar: { workspaceId: \"settings\", viewId: \"calendar\" },\n email: { workspaceId: \"settings\", viewId: \"email\" },\n};\n\nconst cleanBase = (basePath: string): string =>\n basePath.length > 1 ? basePath.replace(/\\/+$/, \"\") : basePath;\n\nconst decode = (segment: string | undefined): string | undefined => {\n if (!segment) return undefined;\n try {\n return decodeURIComponent(segment);\n } catch {\n return undefined;\n }\n};\n\nconst fromParts = (parts: readonly string[]): AdminRouteState | null => {\n const workspaceId = decode(parts[0]);\n if (!workspaceId) return null;\n const viewId = decode(parts[1]);\n const recordId = decode(parts[2]);\n const detailTab = decode(parts[3]);\n return {\n workspaceId,\n ...(viewId ? { viewId } : {}),\n ...(recordId ? { recordId } : {}),\n ...(detailTab ? { detailTab } : {}),\n };\n};\n\nconst resolve = (\n candidate: AdminRouteState | null,\n workspaceIds: readonly string[],\n aliases: AdminRouteAliases,\n): AdminRouteState | null => {\n if (!candidate) return null;\n if (workspaceIds.includes(candidate.workspaceId)) return candidate;\n const alias = aliases[candidate.workspaceId] ?? DEFAULT_ALIASES[candidate.workspaceId];\n return alias && workspaceIds.includes(alias.workspaceId) ? alias : null;\n};\n\n/** Read canonical fragments first, then inbound query and legacy path links. */\nexport function adminRouteFromUrl(\n url: URL,\n basePath: string,\n workspaceIds: readonly string[],\n aliases: AdminRouteAliases = {},\n): AdminRouteState {\n const fallback = { workspaceId: workspaceIds[0] ?? \"\" };\n const hashParts = url.hash.replace(/^#\\/?/, \"\").split(\"/\").filter(Boolean);\n const fromHash = resolve(fromParts(hashParts), workspaceIds, aliases);\n if (fromHash) return fromHash;\n\n const tab = url.searchParams.get(\"tab\");\n const fromQuery = resolve(\n tab\n ? {\n workspaceId: tab,\n ...(url.searchParams.get(\"view\") ? { viewId: url.searchParams.get(\"view\")! } : {}),\n ...(url.searchParams.get(\"record\") ? { recordId: url.searchParams.get(\"record\")! } : {}),\n ...(url.searchParams.get(\"detail\") ? { detailTab: url.searchParams.get(\"detail\")! } : {}),\n }\n : null,\n workspaceIds,\n aliases,\n );\n if (fromQuery) return fromQuery;\n\n const base = cleanBase(basePath);\n const rest = url.pathname.startsWith(base) ? url.pathname.slice(base.length).replace(/^\\//, \"\") : \"\";\n return resolve(fromParts(rest.split(\"/\").filter(Boolean)), workspaceIds, aliases) ?? fallback;\n}\n\nconst encodedParts = (route: AdminRouteState): string[] =>\n [route.workspaceId, route.viewId, route.recordId, route.detailTab]\n .filter((part): part is string => Boolean(part))\n .map(encodeURIComponent);\n\n/** Build a stable URL for one admin state. Fragment routing is the default. */\nexport function adminRouteHref(\n current: URL,\n basePath: string,\n route: AdminRouteState,\n routing: AdminRouting = \"fragment\",\n): string {\n const next = new URL(current);\n const base = cleanBase(basePath);\n const mountPaths = new Set([base, `${base}/`, `${base}/index.html`]);\n if (!mountPaths.has(next.pathname)) next.pathname = `${base}/`;\n for (const key of [\"tab\", \"view\", \"record\", \"detail\"]) next.searchParams.delete(key);\n\n if (routing === \"fragment\") {\n next.hash = encodedParts(route).join(\"/\");\n } else if (routing === \"query\") {\n next.hash = \"\";\n next.searchParams.set(\"tab\", route.workspaceId);\n if (route.viewId) next.searchParams.set(\"view\", route.viewId);\n if (route.recordId) next.searchParams.set(\"record\", route.recordId);\n if (route.detailTab) next.searchParams.set(\"detail\", route.detailTab);\n } else {\n next.hash = \"\";\n next.pathname = `${base}/${encodeURIComponent(route.workspaceId)}`;\n if (route.viewId) next.searchParams.set(\"view\", route.viewId);\n if (route.recordId) next.searchParams.set(\"record\", route.recordId);\n if (route.detailTab) next.searchParams.set(\"detail\", route.detailTab);\n }\n return `${next.pathname}${next.search}${next.hash}`;\n}\n\n/** Backwards-compatible section helpers over the workspace router. */\nexport function adminSectionFromUrl(url: URL, basePath: string, sectionIds: readonly string[]): string {\n return adminRouteFromUrl(url, basePath, sectionIds).workspaceId;\n}\n\n/** Build a compatibility URL for a top-level admin section. */\nexport function adminSectionHref(\n current: URL,\n basePath: string,\n id: string,\n routing: AdminRouting = \"fragment\",\n): string {\n return adminRouteHref(current, basePath, { workspaceId: id }, routing);\n}\n","import { Tabs } from \"@odla-ai/ui/components\";\nimport type { Chapter } from \"../types.js\";\nimport { availabilitySection } from \"./admin-availability.js\";\nimport { billingSection } from \"./admin-billing.js\";\nimport { dashboardSection } from \"./admin-dashboard.js\";\nimport { emailSection } from \"./admin-email.js\";\nimport { collectionSection } from \"./admin-people.js\";\nimport type { AdminSectionContext, AdminWorkspace } from \"./chrome.js\";\n\nexport const adminViewContext = (\n ctx: AdminSectionContext,\n viewId: string,\n active: boolean,\n): AdminSectionContext => {\n const route = {\n workspaceId: ctx.route.workspaceId,\n viewId,\n ...(active && ctx.route.recordId ? { recordId: ctx.route.recordId } : {}),\n ...(active && ctx.route.detailTab ? { detailTab: ctx.route.detailTab } : {}),\n };\n const targetFromView = (target: Parameters<AdminSectionContext[\"navigate\"]>[0]) => {\n if (typeof target === \"string\") return target;\n if (target.workspaceId && target.workspaceId !== route.workspaceId) return target;\n if (target.viewId && target.viewId !== route.viewId) return target;\n return { ...route, ...target };\n };\n return {\n ...ctx,\n route,\n navigate: (target) => ctx.navigate(targetFromView(target)),\n href: (target) => ctx.href(targetFromView(target)),\n };\n};\n\nfunction DashboardWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const copy = chapter.copy.admin;\n const active = ctx.route.viewId === \"billing\" ? \"billing\" : \"overview\";\n const overview = dashboardSection({ id: \"overview\", label: copy.workspaces.overview });\n const billing = billingSection({ label: copy.workspaces.billing });\n return (\n <Tabs\n ariaLabel={copy.workspaces.dashboardViewsLabel}\n value={active}\n mount=\"active\"\n items={[\n {\n value: \"overview\",\n label: copy.workspaces.overview,\n href: ctx.href({ viewId: \"overview\", recordId: null, detailTab: null }),\n panel: overview.render(adminViewContext(ctx, \"overview\", active === \"overview\")),\n },\n {\n value: \"billing\",\n label: copy.workspaces.billing,\n href: ctx.href({ viewId: \"billing\", recordId: null, detailTab: null }),\n panel: billing.render(adminViewContext(ctx, \"billing\", active === \"billing\")),\n },\n ]}\n />\n );\n}\n\nfunction SettingsWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const copy = chapter.copy.admin;\n const active = ctx.route.viewId === \"email\" ? \"email\" : \"calendar\";\n const calendar = availabilitySection({ id: \"calendar\", label: copy.workspaces.calendar });\n const email = emailSection({ label: copy.workspaces.email });\n return (\n <Tabs\n ariaLabel={copy.workspaces.settingsViewsLabel}\n value={active}\n mount=\"active\"\n items={[\n {\n value: \"calendar\",\n label: copy.workspaces.calendar,\n href: ctx.href({ viewId: \"calendar\", recordId: null, detailTab: null }),\n panel: calendar.render(adminViewContext(ctx, \"calendar\", active === \"calendar\")),\n },\n {\n value: \"email\",\n label: copy.workspaces.email,\n href: ctx.href({ viewId: \"email\", recordId: null, detailTab: null }),\n panel: email.render(adminViewContext(ctx, \"email\", active === \"email\")),\n },\n ]}\n />\n );\n}\n\nfunction PeopleWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const types = Object.entries(chapter.crm.config.types);\n const fallback = types[0]?.[0] ?? \"person\";\n const active = types.some(([type]) => type === ctx.route.viewId) ? ctx.route.viewId! : fallback;\n const networkSharing = chapter.network.targets.length > 0;\n return (\n <Tabs\n ariaLabel={chapter.copy.admin.workspaces.collectionsLabel}\n value={active}\n variant=\"pill\"\n mount=\"active\"\n items={types.map(([type, def]) => {\n const section = collectionSection({\n crm: chapter.crm,\n type,\n lifecycle: chapter.mode === \"chapter\" && type === \"person\",\n roles: chapter.auth.ladder,\n networkSharing,\n });\n return {\n value: type,\n label: def.labelPlural ?? def.label,\n href: ctx.href({ viewId: type, recordId: null, detailTab: null }),\n panel: section.render(adminViewContext(ctx, type, active === type)),\n };\n })}\n />\n );\n}\n\n/** Default follower grammar: three workspaces with nested operational views. */\nexport function defaultAdminWorkspaces(chapter: Chapter): AdminWorkspace[] {\n const copy = chapter.copy.admin;\n const people: AdminWorkspace = {\n id: \"people\",\n label: copy.workspaces.people,\n defaultViewId: Object.keys(chapter.crm.config.types)[0] ?? \"person\",\n render: (ctx) => <PeopleWorkspace chapter={chapter} ctx={ctx} />,\n };\n if (chapter.mode === \"hub\") return [people];\n return [\n {\n id: \"dashboard\",\n label: copy.workspaces.dashboard,\n defaultViewId: \"overview\",\n render: (ctx) => <DashboardWorkspace chapter={chapter} ctx={ctx} />,\n },\n people,\n {\n id: \"settings\",\n label: copy.workspaces.settings,\n defaultViewId: \"calendar\",\n render: (ctx) => <SettingsWorkspace chapter={chapter} ctx={ctx} />,\n },\n ];\n}\n","// Availability section: the owner-editable booking rules from GET/PUT\n// /api/admin/scheduling, as an odla-ui form. The PUT returns field-keyed\n// validation messages, surfaced inline on each Field.\nimport { useState } from \"preact/hooks\";\nimport { Button, Checkbox, Field, Input } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Scheduling {\n slotMinutes: number;\n days: number[];\n startHour: number;\n endHour: number;\n timezone: string;\n minNoticeHours: number;\n windowDays: number;\n summaryTemplate: string;\n}\nfunction AvailabilityBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.availability;\n const { data, loading, error, refresh } = useAdminResource<{ scheduling: Scheduling }>(ctx.getToken, \"/api/admin/scheduling\");\n const [draft, setDraft] = useState<Scheduling | null>(null);\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n const cfg = draft ?? data?.scheduling ?? null;\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !cfg) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const edit = (patch: Partial<Scheduling>) => setDraft({ ...cfg, ...patch });\n const toggleDay = (d: number) => edit({ days: cfg.days.includes(d) ? cfg.days.filter((x) => x !== d) : [...cfg.days, d].sort() });\n const num = (v: string, fallback: number) => (Number.isFinite(Number(v)) ? Number(v) : fallback);\n\n const save = async () => {\n setBusy(true);\n setNote(null);\n setErrors({});\n const token = await ctx.getToken();\n try {\n const r = await fetch(\"/api/admin/scheduling\", { method: \"PUT\", headers: { authorization: `Bearer ${token ?? \"\"}`, \"content-type\": \"application/json\" }, body: JSON.stringify(cfg) });\n const body = (await r.json().catch(() => ({}))) as { error?: string; errors?: Record<string, string> };\n if (!r.ok) {\n setErrors(body.errors ?? {});\n setNote(body.error ?? `save failed (${r.status})`);\n return;\n }\n setDraft(null);\n refresh();\n setNote(copy.saved);\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n }\n };\n\n const numField = (key: keyof Scheduling, label: string) => (\n <Field label={label} error={errors[key]}>\n <Input type=\"number\" value={cfg[key] as number} onInput={(e) => edit({ [key]: num((e.target as HTMLInputElement).value, cfg[key] as number) } as Partial<Scheduling>)} />\n </Field>\n );\n\n return (\n <AdminPage>\n <Panel title={copy.title} actions={note ? <span className=\"muted\">{note}</span> : undefined}>\n <Field label={copy.days} error={errors.days}>\n <div style={{ display: \"flex\", gap: 14, flexWrap: \"wrap\" }}>\n {copy.dayLabels.map((d, i) => (\n <Checkbox key={d} label={d} checked={cfg.days.includes(i)} onChange={() => toggleDay(i)} />\n ))}\n </div>\n </Field>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fit, minmax(180px, 1fr))\", gap: 14 }}>\n {numField(\"startHour\", copy.startHour)}\n {numField(\"endHour\", copy.endHour)}\n {numField(\"slotMinutes\", copy.slotMinutes)}\n {numField(\"minNoticeHours\", copy.minNoticeHours)}\n {numField(\"windowDays\", copy.windowDays)}\n <Field label={copy.timezone} error={errors.timezone}>\n <Input value={cfg.timezone} onInput={(e) => edit({ timezone: (e.target as HTMLInputElement).value })} />\n </Field>\n </div>\n <Field label={copy.summaryTemplate} error={errors.summaryTemplate}>\n <Input value={cfg.summaryTemplate} onInput={(e) => edit({ summaryTemplate: (e.target as HTMLInputElement).value })} />\n </Field>\n <div><Button disabled={!draft || busy} onClick={() => void save()}>{copy.save}</Button></div>\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link availabilitySection}. */\nexport interface AvailabilitySectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Availability admin section: the booking-rules editor over\n * `GET/PUT /api/admin/scheduling`, with field-keyed validation surfaced inline. */\nexport function availabilitySection(options: AvailabilitySectionOptions = {}): AdminSection {\n const { id = \"availability\", label = \"Availability\" } = options;\n return { id, label, render: (ctx) => <AvailabilityBody ctx={ctx} /> };\n}\n","// Token-bound access to the /api/admin/* routes for the console sections. Every\n// section fetches with the signed-in admin's bearer token (from ChapterAdmin's\n// getToken) — the worker gates each route with verifyUser + isAdmin, so the UI\n// carries no privilege of its own.\nimport { useCallback, useEffect, useState } from \"preact/hooks\";\n\n/** Fetch a JSON `/api/admin/*` route with the admin bearer token. Throws on a\n * non-2xx (the body's `error`, else the status). */\nexport async function adminFetch<T = unknown>(\n getToken: () => Promise<string | null>,\n path: string,\n init?: RequestInit,\n): Promise<T> {\n const token = await getToken();\n const headers = new Headers(init?.headers);\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n if (init?.body) headers.set(\"content-type\", \"application/json\");\n const res = await fetch(path, { ...init, headers });\n const body = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw new Error(typeof body.error === \"string\" ? body.error : `request failed (${res.status})`);\n return body as T;\n}\n\n/** The state of one admin resource load. */\nexport interface AdminResource<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n /** Re-fetch (e.g. after a mutation). */\n refresh: () => void;\n}\n\n/** Load a `/api/admin/*` GET route into Preact state, re-fetching on `refresh()`\n * or when `path` changes. */\nexport function useAdminResource<T = unknown>(getToken: () => Promise<string | null>, path: string): AdminResource<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [nonce, setNonce] = useState(0);\n\n useEffect(() => {\n let live = true;\n setLoading(true);\n setError(null);\n adminFetch<T>(getToken, path)\n .then((d) => live && setData(d))\n .catch((e: unknown) => live && setError(e instanceof Error ? e.message : String(e)))\n .finally(() => live && setLoading(false));\n return () => {\n live = false;\n };\n }, [getToken, path, nonce]);\n\n const refresh = useCallback(() => setNonce((n) => n + 1), []);\n return { data, loading, error, refresh };\n}\n","// Billing section: applications joined with live Stripe subscription state from\n// GET /api/admin/billing, rendered with odla-ui StatBand + DataTable. Degrades to\n// a note when billingReady:false, and surfaces the route's `truncated` flag.\nimport { DataTable, StatBand } from \"@odla-ai/ui/components\";\nimport type { DataTableColumn, StatCell } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport type { ChapterCopy } from \"../copy.js\";\n\ninterface BillingRow {\n id: string;\n name: string;\n email: string;\n applicationStatus: string;\n subscriptionStatus: string | null;\n cancelAtPeriodEnd: boolean;\n amountCents: number;\n interval: string;\n renewalAt: number | null;\n}\ninterface BillingData {\n billingReady: boolean;\n testMode?: boolean;\n truncated?: boolean;\n rows: BillingRow[];\n summary: { activeCount: number; annualizedCents: number; renewingSoonCount: number; pastDueCount: number; canceledCount: number; refundedCount: number } | null;\n}\n\nconst money = (cents: number): string => `$${(cents / 100).toLocaleString()}`;\nconst date = (t: number | null): string => (t ? new Date(t).toLocaleDateString([], { dateStyle: \"medium\" }) : \"—\");\n\nconst columns = (\n copy: ChapterCopy[\"admin\"][\"billing\"],\n): readonly DataTableColumn<BillingRow>[] => [\n { key: \"name\", header: copy.name, cell: (r) => r.name, sortAs: \"string\" },\n { key: \"email\", header: copy.email, cell: (r) => r.email },\n { key: \"applicationStatus\", header: copy.application, cell: (r) => r.applicationStatus },\n { key: \"subscriptionStatus\", header: copy.subscription, cell: (r) => (r.subscriptionStatus ? `${r.subscriptionStatus}${r.cancelAtPeriodEnd ? ` · ${copy.cancelling}` : \"\"}` : \"—\") },\n { key: \"amountCents\", header: copy.amount, cell: (r) => `${money(r.amountCents)}/${r.interval === \"month\" ? \"mo\" : \"yr\"}`, sortAs: \"number\", sortValue: (r) => r.amountCents },\n { key: \"renewalAt\", header: copy.renews, cell: (r) => date(r.renewalAt), sortAs: \"number\", sortValue: (r) => r.renewalAt ?? 0 },\n];\n\nfunction BillingBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.billing;\n const { data, loading, error } = useAdminResource<BillingData>(ctx.getToken, \"/api/admin/billing\");\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n if (!data.billingReady) return <AdminNote>{copy.notConfigured}</AdminNote>;\n\n const s = data.summary;\n const stats: StatCell[] = s\n ? [\n { value: s.activeCount, label: copy.active },\n { value: money(s.annualizedCents), label: copy.annualized },\n { value: s.renewingSoonCount, label: copy.renewingSoon },\n { value: s.pastDueCount, label: copy.pastDue },\n ]\n : [];\n\n return (\n <AdminPage>\n {s ? <StatBand stats={stats} /> : null}\n <Panel title={copy.subscriptions} actions={data.testMode ? <span className=\"badge\">{copy.testMode}</span> : undefined}>\n {data.truncated ? <p className=\"badge\">{copy.truncated}</p> : null}\n <DataTable rows={data.rows} columns={columns(copy)} rowKey={(r) => r.id} />\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link billingSection}. */\nexport interface BillingSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Billing admin section over `GET /api/admin/billing`. Renders a\n * \"not configured\" note when the group has no Stripe key vaulted. */\nexport function billingSection(options: BillingSectionOptions = {}): AdminSection {\n const { id = \"billing\", label = \"Billing\" } = options;\n return { id, label, render: (ctx) => <BillingBody ctx={ctx} /> };\n}\n","// Operational overview powered by the MetricWidget and StepPipeline primitives.\nimport { MetricWidget, StepPipeline } from \"@odla-ai/ui/components\";\nimport type { MetricData, PipelineStep } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport { formatChapterCopy } from \"../copy.js\";\n\ninterface DashboardData {\n applications: { total: number; last7: number; last30: number };\n applicationsSeries: MetricData;\n pipeline: Record<string, number>;\n pipelineDelta: Record<string, number>;\n calls: { upcoming: number; needsAttention: number };\n agenda: Array<{\n id: string;\n startAt: number;\n name: string;\n email: string | null;\n drift: string;\n meetUrl: string | null;\n htmlLink?: string | null;\n }>;\n timezone: string;\n revenue: {\n billingReady: boolean;\n activeCount?: number;\n annualRunRateCents?: number;\n testMode?: boolean;\n };\n revenueSeries: MetricData | null;\n membersSeries: MetricData | null;\n}\n\nconst number = (value: number): string => Math.round(value).toLocaleString();\nconst money = (cents: number): string => `$${Math.round(cents / 100).toLocaleString()}`;\nconst when = (time: number): string =>\n new Date(time).toLocaleString([], { dateStyle: \"medium\", timeStyle: \"short\" });\n\nfunction DashboardBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.dashboard;\n const { data, loading, error } = useAdminResource<DashboardData>(\n ctx.getToken,\n \"/api/admin/dashboard\",\n );\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const pipelineSteps: PipelineStep[] = Object.entries(data.pipeline)\n .filter(([stage]) => ![\"declined\", \"refunded\"].includes(stage))\n .map(([stage, count]) => ({\n icon: <span style={{ fontSize: 22, fontWeight: 700 }}>{count}</span>,\n title: stage.replaceAll(\"_\", \" \"),\n description: data.pipelineDelta[stage]\n ? formatChapterCopy(copy.thisWeek, { count: data.pipelineDelta[stage] })\n : copy.noChange,\n }));\n const exceptions = [\"declined\", \"refunded\"]\n .filter((stage) => stage in data.pipeline)\n .map((stage) => `${stage} ${data.pipeline[stage]}`)\n .join(\" · \");\n\n return (\n <AdminPage>\n <Panel\n title={\n <>\n {copy.upcomingCalls}{\" \"}\n <span className=\"muted\" style={{ fontWeight: 400 }}>· {data.timezone}</span>\n </>\n }\n actions={\n data.calls.needsAttention\n ? <span className=\"badge\">{formatChapterCopy(copy.callsNeedAttention, { count: data.calls.needsAttention })}</span>\n : undefined\n }\n >\n {data.agenda.length === 0 ? (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.noUpcomingCalls}</p>\n ) : (\n <ul style={{ listStyle: \"none\", margin: 0, padding: 0, display: \"grid\", gap: 10 }}>\n {data.agenda.map((meeting) => (\n <li key={meeting.id} style={{ display: \"flex\", alignItems: \"center\", gap: 12, flexWrap: \"wrap\" }}>\n <strong style={{ minWidth: 170 }}>{when(meeting.startAt)}</strong>\n <span style={{ flex: 1 }}>{meeting.name}{meeting.email ? ` · ${meeting.email}` : \"\"}</span>\n {meeting.drift && meeting.drift !== \"none\" ? <span className=\"badge\">{copy.drift}</span> : null}\n {meeting.htmlLink ? <a href={meeting.htmlLink} target=\"_blank\" rel=\"noreferrer\">{copy.open}</a> : null}\n {meeting.meetUrl ? <a href={meeting.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.meet}</a> : null}\n </li>\n ))}\n </ul>\n )}\n </Panel>\n\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fit, minmax(280px, 1fr))\", gap: 18 }}>\n <MetricWidget label={copy.applications} data={data.applicationsSeries} format={number} />\n {data.membersSeries ? (\n <MetricWidget label={copy.newMembers} data={data.membersSeries} format={number} />\n ) : (\n <Panel title={copy.newMembers}><p className=\"muted\">{copy.newMembersUnavailable}</p></Panel>\n )}\n </div>\n\n {data.revenueSeries && data.revenue.billingReady ? (\n <div>\n <MetricWidget\n label={copy.revenueAdded}\n data={data.revenueSeries}\n format={money}\n size=\"large\"\n />\n <p className=\"muted\">\n {copy.activeMemberships}: {data.revenue.activeCount ?? 0} · {copy.annualRunRate}:{\" \"}\n {money(data.revenue.annualRunRateCents ?? 0)}\n {data.revenue.testMode ? ` · ${copy.testMode}` : \"\"}\n </p>\n </div>\n ) : (\n <Panel title={copy.revenue}><p className=\"muted\">{copy.revenueUnavailable}</p></Panel>\n )}\n\n <Panel title={copy.pipeline}>\n <StepPipeline ariaLabel={copy.pipelineLabel} steps={pipelineSteps} />\n {exceptions ? <p className=\"muted\" style={{ margin: 0 }}>{exceptions}</p> : null}\n </Panel>\n </AdminPage>\n );\n}\n\n/** Labels and ids for a composed dashboard workspace entry. */\nexport interface DashboardSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the operational dashboard workspace over `/api/admin/dashboard`. */\nexport function dashboardSection(options: DashboardSectionOptions = {}): AdminSection {\n const { id = \"dashboard\", label = \"Dashboard\" } = options;\n return { id, label, render: (ctx) => <DashboardBody ctx={ctx} /> };\n}\n","// Email section: the owner-editable email config (templates + addresses) from\n// GET/PUT /api/admin/group/email, the send audit from GET /api/admin/email/log,\n// and a POST /api/admin/email/test button. Built from odla-ui form primitives.\nimport { useState } from \"preact/hooks\";\nimport { Button, Checkbox, DataTable, Field, Input, Textarea } from \"@odla-ai/ui/components\";\nimport type { DataTableColumn } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport { formatChapterCopy, type ChapterCopy } from \"../copy.js\";\n\ninterface Template { subject: string; text: string; enabled: boolean }\ninterface EmailConfig {\n emailTemplates: Record<string, Template>;\n replyTo: string;\n notificationEmail: string;\n debugEmail: string;\n commitmentText: string;\n normsText: string;\n transport: string;\n fromEmail: string | null;\n envName: string;\n}\ninterface LogRow { id: string; template: string; to: string; subject: string; transport: string; redirected: boolean; error: string | null; sentAt: number }\n\nconst logColumns = (\n copy: ChapterCopy[\"admin\"][\"email\"],\n): readonly DataTableColumn<LogRow>[] => [\n { key: \"sentAt\", header: copy.sentColumn, cell: (r) => new Date(r.sentAt).toLocaleString(), sortAs: \"number\", sortValue: (r) => r.sentAt },\n { key: \"template\", header: copy.templateColumn, cell: (r) => r.template },\n { key: \"to\", header: copy.toColumn, cell: (r) => r.to },\n { key: \"status\", header: copy.statusColumn, cell: (r) => (r.error ? <span className=\"badge\">{copy.failed}</span> : r.redirected ? <span className=\"badge\">{copy.redirected}</span> : copy.delivered) },\n];\n\nfunction EmailBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.email;\n const cfg = useAdminResource<EmailConfig>(ctx.getToken, \"/api/admin/group/email\");\n const log = useAdminResource<{ sends: LogRow[] }>(ctx.getToken, \"/api/admin/email/log\");\n const [draft, setDraft] = useState<EmailConfig | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n\n const data = draft ?? cfg.data;\n if (cfg.loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (cfg.error || !data) return <AdminNote>{copy.loadFailed}{cfg.error ? `: ${cfg.error}` : \"\"}.</AdminNote>;\n\n const edit = (patch: Partial<EmailConfig>) => setDraft({ ...data, ...patch });\n const editTemplate = (key: string, patch: Partial<Template>) =>\n edit({ emailTemplates: { ...data.emailTemplates, [key]: { ...data.emailTemplates[key], ...patch } as Template } });\n\n const run = async (key: string, fn: () => Promise<void>) => {\n setBusy(key);\n setNote(null);\n try {\n await fn();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const save = () =>\n run(\"save\", async () => {\n await adminFetch(ctx.getToken, \"/api/admin/group/email\", { method: \"PUT\", body: JSON.stringify(data) });\n setDraft(null);\n cfg.refresh();\n setNote(copy.saved);\n });\n const test = (template: string) =>\n run(`test:${template}`, async () => {\n const r = await adminFetch<{ ok: boolean; to: string; redirected: boolean }>(ctx.getToken, \"/api/admin/email/test\", { method: \"POST\", body: JSON.stringify({ template }) });\n setNote(r.ok\n ? formatChapterCopy(copy.sent, {\n template,\n address: r.to,\n redirected: r.redirected ? ` (${copy.redirected})` : \"\",\n })\n : copy.testFailed);\n log.refresh();\n });\n\n return (\n <AdminPage>\n <Panel\n title={copy.delivery}\n actions={<span className=\"muted\">{data.envName} · {data.transport}{data.fromEmail ? ` · ${data.fromEmail}` : \"\"}</span>}\n >\n <Field label={copy.notificationAddress}><Input value={data.notificationEmail} onInput={(e) => edit({ notificationEmail: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.replyTo}><Input value={data.replyTo} onInput={(e) => edit({ replyTo: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.debugInbox} hint={copy.debugInboxHint}><Input value={data.debugEmail} onInput={(e) => edit({ debugEmail: (e.target as HTMLInputElement).value })} /></Field>\n </Panel>\n\n {Object.entries(data.emailTemplates).map(([key, t]) => (\n <Panel key={key} title={key} actions={<Button variant=\"secondary\" mini disabled={busy === `test:${key}`} onClick={() => void test(key)}>{copy.sendTest}</Button>}>\n <Checkbox label={copy.enabled} checked={t.enabled} onChange={(e) => editTemplate(key, { enabled: (e.target as HTMLInputElement).checked })} />\n <Field label={copy.subject}><Input value={t.subject} onInput={(e) => editTemplate(key, { subject: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.body}><Textarea prose rows={5} value={t.text} onInput={(e) => editTemplate(key, { text: (e.target as HTMLTextAreaElement).value })} /></Field>\n </Panel>\n ))}\n\n <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n <Button disabled={!draft || busy === \"save\"} onClick={() => void save()}>{copy.save}</Button>\n {note ? <span className=\"muted\">{note}</span> : null}\n </div>\n\n <Panel title={copy.sendLog}>\n <DataTable rows={log.data?.sends ?? []} columns={logColumns(copy)} rowKey={(r) => r.id} />\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link emailSection}. */\nexport interface EmailSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Email admin section: template + address editor over\n * `GET/PUT /api/admin/group/email`, the send log, and per-template test sends. */\nexport function emailSection(options: EmailSectionOptions = {}): AdminSection {\n const { id = \"email\", label = \"Email\" } = options;\n return { id, label, render: (ctx) => <EmailBody ctx={ctx} /> };\n}\n","import { BillingCard, CrmWorkspace } from \"@odla-ai/crm/ui\";\nimport type {\n CrmLifecycleAdapter,\n CrmWorkspaceMasterContext,\n CrmWorkspaceRecordContext,\n RecordPanelTab,\n} from \"@odla-ai/crm/ui\";\nimport type { Crm, CrmClient, CrmRecord } from \"@odla-ai/crm\";\nimport type { ComponentChildren } from \"preact\";\nimport type { AdminSectionContext } from \"./chrome.js\";\nimport { adminFetch } from \"./admin-api.js\";\nimport { RecordActions } from \"./admin-record-actions.js\";\nimport { NetworkShareActions } from \"./admin-network.js\";\nimport { RecordActivityPanel } from \"./admin-record-activity.js\";\nimport { RecordCommsHistory, RecordCommsPanel } from \"./admin-record-comms.js\";\nimport { RecordSchedulingPanel } from \"./admin-record-scheduling.js\";\nimport { AdminPage } from \"./admin-layout.js\";\nimport { DEFAULT_CHAPTER_COPY, type ChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\n/** Application-authoritative stage transitions used by Chapter collections. */\nexport function applicationLifecycleAdapter(\n ctx: Pick<AdminSectionContext, \"getToken\">,\n copy: ChapterCopy[\"admin\"][\"records\"] = DEFAULT_CHAPTER_COPY.admin.records,\n): CrmLifecycleAdapter {\n return {\n transitionStage: async ({ record, to }) => {\n const applicationId =\n typeof record.fields?.applicationId === \"string\"\n ? record.fields.applicationId\n : null;\n if (!applicationId) {\n throw new Error(copy.workflowMissing);\n }\n const path = `/api/admin/applications/${encodeURIComponent(applicationId)}`;\n if (to === \"approved\") {\n await adminFetch(ctx.getToken, `${path}/approve`, { method: \"POST\" });\n } else if (to === \"refunded\") {\n await adminFetch(ctx.getToken, `${path}/refund`, { method: \"POST\" });\n } else {\n await adminFetch(ctx.getToken, path, {\n method: \"PATCH\",\n body: JSON.stringify({ status: to }),\n });\n }\n },\n };\n}\n\nexport interface PeopleBodyProps {\n crm: Crm;\n client: CrmClient;\n type: string;\n ctx: AdminSectionContext;\n roles: readonly string[];\n lifecycle: boolean;\n networkSharing: boolean;\n collapseClosedDetail: boolean;\n lifecycleAdapter?:\n | CrmLifecycleAdapter\n | ((ctx: AdminSectionContext) => CrmLifecycleAdapter);\n requireLifecycleAdapter?: boolean;\n renderSummary?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderMaster?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderDetailHeader?: (\n context: CrmWorkspaceRecordContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderEmptyDetail?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n hrefForRecord?: (record: CrmRecord, ctx: AdminSectionContext) => string;\n extendRecordTabs?: (\n tabs: readonly RecordPanelTab[],\n context: CrmWorkspaceRecordContext,\n ) => readonly RecordPanelTab[];\n}\n\nexport function PeopleBody(props: PeopleBodyProps) {\n const copy = useChapterCopy().admin.records;\n const {\n crm, client, type, ctx, roles, lifecycle, networkSharing,\n collapseClosedDetail, lifecycleAdapter, requireLifecycleAdapter, renderSummary, renderMaster,\n renderDetailHeader, renderEmptyDetail, hrefForRecord, extendRecordTabs,\n } = props;\n const def = crm.type(type);\n const recordId = ctx.route?.recordId ?? null;\n const builtInLifecycle = lifecycle\n ? applicationLifecycleAdapter(ctx, copy)\n : undefined;\n const resolvedLifecycle =\n typeof lifecycleAdapter === \"function\"\n ? lifecycleAdapter(ctx)\n : lifecycleAdapter ?? builtInLifecycle;\n // Both imports are the same runtime class, but their declarations contain a\n // private field that makes TypeScript treat the public UI copy nominally.\n const workspaceClient = client as unknown as Parameters<typeof CrmWorkspace>[0][\"client\"];\n return (\n <AdminPage>\n <CrmWorkspace\n crm={crm}\n client={workspaceClient}\n type={type}\n recordId={recordId}\n detailTab={ctx.route?.detailTab}\n defaultDetailTab=\"profile\"\n onRecordIdChange={(id) => ctx.navigate({ recordId: id, detailTab: null })}\n hrefForRecord={(record) =>\n hrefForRecord?.(record, ctx) ??\n ctx.href({ recordId: record.id, detailTab: \"profile\" })}\n hrefForList={ctx.href({ recordId: null, detailTab: null })}\n hrefForDetailTab={(detailTab) => ctx.href({ detailTab })}\n collapseClosedDetail={collapseClosedDetail}\n lifecycle={resolvedLifecycle}\n requireLifecycleAdapter={requireLifecycleAdapter ?? lifecycle}\n renderSummary={renderSummary\n ? (context) => renderSummary(context, ctx)\n : undefined}\n renderMaster={renderMaster\n ? (context) => renderMaster(context, ctx)\n : undefined}\n renderDetailHeader={renderDetailHeader\n ? (context) => renderDetailHeader(context, ctx)\n : undefined}\n renderEmptyDetail={renderEmptyDetail\n ? (context) => renderEmptyDetail(context, ctx)\n : undefined}\n extendRecordTabs={(base, context): readonly RecordPanelTab[] => {\n const record = context.detail.record;\n const applicationId =\n typeof record.fields?.applicationId === \"string\"\n ? String(record.fields.applicationId)\n : null;\n const byId = new Map(base.map((tab) => [tab.id, tab]));\n const tabs: RecordPanelTab[] = [];\n const add = (id: string) => {\n const tab = byId.get(id);\n if (tab) tabs.push(tab);\n };\n add(\"stage\");\n add(\"profile\");\n if (def.facets?.email !== false) {\n tabs.push({\n id: \"comms\",\n label: copy.comms,\n panel: <RecordCommsPanel client={client} recordId={record.id} getToken={ctx.getToken} />,\n });\n tabs.push({\n id: \"history\",\n label: copy.commsHistory,\n panel: <RecordCommsHistory client={client} recordId={record.id} />,\n });\n }\n if (lifecycle) {\n tabs.push({\n id: \"scheduling\",\n label: copy.scheduling,\n panel: <RecordSchedulingPanel getToken={ctx.getToken} applicationId={applicationId} />,\n });\n tabs.push({ id: \"billing\", label: copy.billing, panel: <BillingCard record={record} /> });\n } else {\n add(\"billing\");\n }\n tabs.push({\n id: \"notes\",\n label: copy.notes,\n panel: <RecordActivityPanel client={client} recordId={record.id} />,\n });\n add(\"connections\");\n if (lifecycle) {\n tabs.push({\n id: \"access\",\n label: copy.access,\n panel: (\n <RecordActions\n getToken={ctx.getToken}\n record={record}\n roles={roles}\n onChanged={() => {\n context.refreshRecord();\n context.refreshList();\n }}\n />\n ),\n visible: () => ctx.currentUser?.superAdmin === true,\n });\n }\n if (networkSharing) {\n tabs.push({\n id: \"sharing\",\n label: copy.sharing,\n panel: <NetworkShareActions recordId={record.id} recordType={record.type} getToken={ctx.getToken} />,\n });\n }\n return extendRecordTabs?.(tabs, context) ?? tabs;\n }}\n />\n </AdminPage>\n );\n}\n","// The lifecycle action panel shown beside an open person record: role change\n// (POST /api/admin/people/role), approve (POST /api/admin/applications/:id/\n// approve) and refund (POST .../refund). Each control appears only when the\n// record carries what it needs — a linked Clerk account for role, an\n// applicationId for approve/refund. Built from odla-ui Field/Select/Button.\nimport { useEffect, useState } from \"preact/hooks\";\nimport { Button, Field, Select } from \"@odla-ai/ui/components\";\nimport { adminFetch } from \"./admin-api.js\";\nimport type { CrmRecord } from \"@odla-ai/crm\";\nimport { formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Access {\n role: string;\n superAdmin: boolean;\n}\n\n/** Props for {@link RecordActions}. */\nexport interface RecordActionsProps {\n getToken: () => Promise<string | null>;\n record: CrmRecord;\n /** The role ladder offered by the role selector. Default provisional→admin. */\n roles: readonly string[];\n /** Called after any action mutates state, so the caller can refresh. */\n onChanged: () => void;\n}\n\n/** The role/approve/refund controls for one person record. Renders only the\n * actions the record supports. */\nexport function RecordActions({ getToken, record, roles, onChanged }: RecordActionsProps) {\n const copy = useChapterCopy().admin.records;\n const userId = typeof record.clerkUserId === \"string\" ? record.clerkUserId : null;\n const applicationId = typeof record.fields?.applicationId === \"string\" ? (record.fields.applicationId as string) : null;\n const [access, setAccess] = useState<Access | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n\n useEffect(() => {\n if (!userId) {\n setAccess(null);\n return;\n }\n let live = true;\n adminFetch<Access>(getToken, `/api/admin/people/access?userId=${encodeURIComponent(userId)}`)\n .then((a) => live && setAccess(a))\n .catch(() => live && setAccess(null));\n return () => {\n live = false;\n };\n }, [getToken, userId]);\n\n const act = async (key: string, run: () => Promise<unknown>, ok: string) => {\n setBusy(key);\n setNote(null);\n try {\n await run();\n setNote(ok);\n onChanged();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const setRole = (role: string) =>\n act(\"role\", () => adminFetch(getToken, \"/api/admin/people/role\", { method: \"POST\", body: JSON.stringify({ userId, role }) }), formatChapterCopy(copy.roleSet, { role }));\n const approve = () =>\n act(\"approve\", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/approve`, { method: \"POST\" }), copy.approved);\n const refund = () =>\n act(\"refund\", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/refund`, { method: \"POST\" }), copy.refunded);\n\n if (!userId && !applicationId) return null;\n return (\n <section className=\"panel\" style={{ display: \"flex\", flexDirection: \"column\", gap: 14, marginTop: 16 }}>\n <h3 style={{ margin: 0, fontSize: 16 }}>{copy.lifecycle}</h3>\n {userId ? (\n <Field label={copy.role} hint={access?.superAdmin ? copy.superAdminHint : undefined}>\n <Select\n value={access?.role ?? \"\"}\n disabled={busy === \"role\" || access?.superAdmin}\n options={roles.map((r) => ({ value: r, label: r }))}\n onChange={(e) => void setRole((e.target as HTMLSelectElement).value)}\n />\n </Field>\n ) : (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.noAccount}</p>\n )}\n {applicationId ? (\n <div style={{ display: \"flex\", gap: 8 }}>\n <Button variant=\"secondary\" mini disabled={busy === \"approve\"} onClick={() => void approve()}>{copy.approve}</Button>\n <Button variant=\"danger\" mini disabled={busy === \"refund\"} onClick={() => void refund()}>{copy.refund}</Button>\n </div>\n ) : null}\n {note ? <p className=\"muted\" style={{ margin: 0 }}>{note}</p> : null}\n </section>\n );\n}\n","// Leader-side \"share to follower\" action. It is intentionally record-local:\n// the operator opens the person/business/deal they already reviewed, chooses a\n// configured follower, and sees an explicit delivery result.\nimport { useState } from \"preact/hooks\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Target {\n id: string;\n name: string;\n url: string;\n types: string[];\n}\n\ninterface TargetResponse {\n targets: Target[];\n}\n\ninterface PushResponse {\n ok: boolean;\n results: Array<{ id: string; name: string; ok: boolean; error?: string }>;\n}\n\n/** Props for {@link NetworkShareActions}. */\nexport interface NetworkShareActionsProps {\n recordId: string;\n recordType: string;\n getToken: () => Promise<string | null>;\n}\n\n/** Render follower delivery buttons when this chapter configured network\n * targets. Targets with an explicit type allowlist hide incompatible records. */\nexport function NetworkShareActions(props: NetworkShareActionsProps) {\n const copy = useChapterCopy().admin.network;\n const { recordId, recordType, getToken } = props;\n const targets = useAdminResource<TargetResponse>(getToken, \"/api/admin/network/targets\");\n const [busy, setBusy] = useState<string | null>(null);\n const [message, setMessage] = useState<string | null>(null);\n const compatible = (targets.data?.targets ?? []).filter((target) => target.types.includes(recordType));\n\n if (targets.loading || targets.error || compatible.length === 0) return null;\n\n const push = async (target: Target) => {\n setBusy(target.id);\n setMessage(null);\n try {\n const result = await adminFetch<PushResponse>(getToken, \"/api/admin/network/push\", {\n method: \"POST\",\n body: JSON.stringify({ recordId, targetIds: [target.id] }),\n });\n const delivery = result.results[0];\n setMessage(delivery?.ok\n ? formatChapterCopy(copy.shared, { target: target.name })\n : delivery?.error ?? formatChapterCopy(copy.shareFailed, { target: target.name }));\n } catch (err) {\n setMessage(err instanceof Error ? err.message : copy.deliveryFailed);\n } finally {\n setBusy(null);\n }\n };\n\n return (\n <section className=\"panel\" style={{ marginTop: 14, display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 16 }}>{copy.title}</h3>\n <p className=\"muted\" style={{ margin: \"4px 0 0\", fontSize: 13 }}>\n {copy.allowlistDescription}\n </p>\n </div>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n {compatible.map((target) => (\n <button className=\"btn secondary mini\" disabled={busy !== null} onClick={() => void push(target)} key={target.id}>\n {busy === target.id\n ? copy.sharing\n : formatChapterCopy(copy.shareWith, { target: target.name })}\n </button>\n ))}\n </div>\n {message ? <p role=\"status\" style={{ margin: 0, fontSize: 13 }}>{message}</p> : null}\n </section>\n );\n}\n","import { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { ActivityFeed } from \"@odla-ai/crm/ui\";\nimport type { CrmActivity, CrmClient } from \"@odla-ai/crm\";\n\n/** Notes and follow-ups for one CRM record. */\nexport function RecordActivityPanel(props: {\n client: CrmClient;\n recordId: string;\n}) {\n const { client, recordId } = props;\n const [activities, setActivities] = useState<CrmActivity[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const load = useCallback(async () => {\n try {\n const result = await client.listActivities(recordId, { limit: 100 });\n setActivities(result.activities);\n setError(null);\n } catch (failure) {\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n }, [client, recordId]);\n useEffect(() => void load(), [load]);\n const run = async (action: () => Promise<unknown>) => {\n setBusy(true);\n try {\n await action();\n await load();\n } finally {\n setBusy(false);\n }\n };\n if (error) return <p role=\"alert\" className=\"muted\">{error}</p>;\n return (\n <ActivityFeed\n activities={activities}\n busy={busy}\n onAddNote={(body) => void run(() => client.addActivity(recordId, { kind: \"note\", body }))}\n onAddTask={(task) => void run(() => client.addActivity(recordId, { kind: \"task\", ...task }))}\n onToggleTask={(activity, done) =>\n void run(() => client.updateTask(activity.id, { status: done ? \"done\" : \"open\" }))}\n />\n );\n}\n","import { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { Button, Field, Select } from \"@odla-ai/ui/components\";\nimport type { CrmClient } from \"@odla-ai/crm\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface EmailConfig {\n emailTemplates: Record<string, { enabled: boolean; subject: string }>;\n}\n\n/** Template send action for one record. */\nexport function RecordCommsPanel(props: {\n client: CrmClient;\n recordId: string;\n getToken: () => Promise<string | null>;\n}) {\n const copy = useChapterCopy().admin.records;\n const { client, recordId, getToken } = props;\n const config = useAdminResource<EmailConfig>(getToken, \"/api/admin/group/email\");\n const templates = Object.entries(config.data?.emailTemplates ?? {}).filter(([, value]) => value.enabled);\n const [template, setTemplate] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n const send = async () => {\n if (!template) return;\n setBusy(true);\n setNote(null);\n try {\n const result = await client.sendEmail(recordId, { templateId: template });\n setNote(result.sent ? copy.messageSent : result.reason ?? copy.messageNotSent);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setBusy(false);\n }\n };\n if (config.loading) return <p className=\"muted\">{copy.loadingTemplates}</p>;\n if (config.error) return <p role=\"alert\" className=\"muted\">{config.error}</p>;\n return (\n <div style={{ display: \"grid\", gap: 14, maxWidth: 560 }}>\n <Field label={copy.template}>\n <Select\n value={template}\n onChange={(event) => setTemplate(event.currentTarget.value)}\n options={[\n { value: \"\", label: copy.chooseTemplate },\n ...templates.map(([id, value]) => ({ value: id, label: value.subject || id })),\n ]}\n />\n </Field>\n <div><Button disabled={!template || busy} onClick={() => void send()}>{busy ? copy.sending : copy.send}</Button></div>\n {note ? <p role=\"status\" className=\"muted\">{note}</p> : null}\n </div>\n );\n}\n\n/** Audited send history for one record. */\nexport function RecordCommsHistory(props: { client: CrmClient; recordId: string }) {\n const copy = useChapterCopy().admin.records;\n const { client, recordId } = props;\n const [rows, setRows] = useState<Record<string, unknown>[]>([]);\n const [error, setError] = useState<string | null>(null);\n const load = useCallback(async () => {\n try {\n const result = await client.emailLog({ recordId, limit: 100 });\n setRows(result.log);\n setError(null);\n } catch (failure) {\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n }, [client, recordId]);\n useEffect(() => void load(), [load]);\n if (error) return <p role=\"alert\" className=\"muted\">{error}</p>;\n if (rows.length === 0) return <p className=\"muted\">{copy.noMessages}</p>;\n return (\n <ul style={{ listStyle: \"none\", padding: 0, margin: 0, display: \"grid\", gap: 10 }}>\n {rows.map((row, index) => (\n <li className=\"panel\" key={String(row[\"id\"] ?? index)}>\n <strong>{String(row[\"templateId\"] ?? row[\"template\"] ?? copy.message)}</strong>\n <div className=\"muted\">\n {row[\"to\"] ? String(row[\"to\"]) : \"\"}\n {row[\"sentAt\"] ? ` · ${new Date(Number(row[\"sentAt\"])).toLocaleString()}` : \"\"}\n </div>\n </li>\n ))}\n </ul>\n );\n}\n","import { useState } from \"preact/hooks\";\nimport { Button } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Meeting {\n id: string;\n applicationId: string;\n startAt: number;\n status: string;\n meetUrl?: string | null;\n htmlLink?: string | null;\n}\n\n/** Meetings and reschedule/cancel actions for one application-backed record. */\nexport function RecordSchedulingPanel(props: {\n getToken: () => Promise<string | null>;\n applicationId: string | null;\n}) {\n const copy = useChapterCopy().admin.records;\n const { getToken, applicationId } = props;\n const resource = useAdminResource<{ meetings: Meeting[]; timezone: string }>(\n getToken,\n \"/api/admin/meetings?all=1\",\n );\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n const meetings = (resource.data?.meetings ?? []).filter((meeting) => meeting.applicationId === applicationId);\n const run = async (meeting: Meeting, action: \"cancel\" | \"reschedule\") => {\n let body: string | undefined;\n if (action === \"reschedule\") {\n const input = globalThis.prompt?.(copy.newStartPrompt);\n if (!input) return;\n const startAt = Date.parse(input);\n if (!Number.isFinite(startAt)) {\n setNote(copy.parseFailed);\n return;\n }\n body = JSON.stringify({ startAt });\n } else if (!globalThis.confirm?.(copy.cancelConfirm)) {\n return;\n }\n setBusy(meeting.id);\n try {\n await adminFetch(getToken, `/api/admin/meetings/${meeting.id}/${action}`, { method: \"POST\", body });\n resource.refresh();\n setNote(action === \"cancel\" ? copy.callCancelled : copy.callRescheduled);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setBusy(null);\n }\n };\n if (!applicationId) return <p className=\"muted\">{copy.noApplication}</p>;\n if (resource.loading) return <p className=\"muted\">{copy.loadingMeetings}</p>;\n if (resource.error) return <p role=\"alert\" className=\"muted\">{resource.error}</p>;\n if (meetings.length === 0) return <p className=\"muted\">{copy.noMeetings}</p>;\n return (\n <div style={{ display: \"grid\", gap: 12 }}>\n {meetings.map((meeting) => (\n <section className=\"panel\" key={meeting.id}>\n <strong>{new Date(meeting.startAt).toLocaleString()}</strong>\n <p className=\"muted\">{meeting.status} · {resource.data?.timezone}</p>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\" }}>\n {meeting.meetUrl ? <a href={meeting.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.joinMeeting}</a> : null}\n {meeting.htmlLink ? <a href={meeting.htmlLink} target=\"_blank\" rel=\"noreferrer\">{copy.openCalendar}</a> : null}\n {meeting.status === \"scheduled\" ? (\n <>\n <Button variant=\"secondary\" mini disabled={busy === meeting.id} onClick={() => void run(meeting, \"reschedule\")}>{copy.reschedule}</Button>\n <Button variant=\"danger\" mini disabled={busy === meeting.id} onClick={() => void run(meeting, \"cancel\")}>{copy.cancel}</Button>\n </>\n ) : null}\n </div>\n </section>\n ))}\n {note ? <p role=\"status\" className=\"muted\">{note}</p> : null}\n </div>\n );\n}\n","// Config-driven CRM workspace with record-local operational tabs.\nimport type {\n CrmLifecycleAdapter,\n CrmWorkspaceMasterContext,\n CrmWorkspaceRecordContext,\n RecordPanelTab,\n} from \"@odla-ai/crm/ui\";\nimport type { Crm, CrmRecord } from \"@odla-ai/crm\";\nimport type { ComponentChildren } from \"preact\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { PeopleBody } from \"./admin-people-workspace.js\";\n\nexport { applicationLifecycleAdapter } from \"./admin-people-workspace.js\";\n\nconst DEFAULT_ROLES = [\"provisional\", \"member\", \"admin\"] as const;\n\n/** Configuration for the person-collection compatibility preset. */\nexport interface PeopleSectionOptions {\n crm: Crm;\n id?: string;\n label?: string;\n type?: string;\n}\n\n/** Configuration for one CRM collection and its application-specific tabs. */\nexport interface CollectionSectionOptions {\n crm: Crm;\n type: string;\n id?: string;\n label?: string;\n lifecycle?: boolean;\n roles?: readonly string[];\n networkSharing?: boolean;\n /** Give the collection list the full workspace width until a record opens. */\n collapseClosedDetail?: boolean;\n lifecycleAdapter?: (\n | CrmLifecycleAdapter\n | ((ctx: AdminSectionContext) => CrmLifecycleAdapter)\n );\n requireLifecycleAdapter?: boolean;\n renderSummary?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderMaster?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderDetailHeader?: (\n context: CrmWorkspaceRecordContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderEmptyDetail?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n hrefForRecord?: (record: CrmRecord, ctx: AdminSectionContext) => string;\n extendRecordTabs?: (\n tabs: readonly RecordPanelTab[],\n context: CrmWorkspaceRecordContext,\n ) => readonly RecordPanelTab[];\n}\n\n/** Build one CRM collection as an admin workspace. */\nexport function collectionSection(options: CollectionSectionOptions): AdminSection {\n const { crm, type } = options;\n let fallbackLabel = type;\n try {\n fallbackLabel = crm.type(type).labelPlural ?? crm.type(type).label ?? type;\n } catch {\n // The route will surface an unknown configured type.\n }\n const {\n id = type,\n label = fallbackLabel,\n lifecycle = type === \"person\",\n roles = DEFAULT_ROLES,\n networkSharing = false,\n collapseClosedDetail = true,\n lifecycleAdapter,\n requireLifecycleAdapter,\n renderSummary,\n renderMaster,\n renderDetailHeader,\n renderEmptyDetail,\n hrefForRecord,\n extendRecordTabs,\n } = options;\n return {\n id,\n label,\n render: (ctx) => (\n <PeopleBody\n crm={crm}\n client={ctx.client}\n type={type}\n ctx={ctx}\n roles={roles}\n lifecycle={lifecycle}\n networkSharing={networkSharing}\n collapseClosedDetail={collapseClosedDetail}\n lifecycleAdapter={lifecycleAdapter}\n requireLifecycleAdapter={requireLifecycleAdapter}\n renderSummary={renderSummary}\n renderMaster={renderMaster}\n renderDetailHeader={renderDetailHeader}\n renderEmptyDetail={renderEmptyDetail}\n hrefForRecord={hrefForRecord}\n extendRecordTabs={extendRecordTabs}\n />\n ),\n };\n}\n\n/** Person-collection preset. */\nexport function peopleSection(options: PeopleSectionOptions & {\n roles?: readonly string[];\n networkSharing?: boolean;\n collapseClosedDetail?: boolean;\n lifecycleAdapter?: CollectionSectionOptions[\"lifecycleAdapter\"];\n requireLifecycleAdapter?: boolean;\n renderSummary?: CollectionSectionOptions[\"renderSummary\"];\n renderMaster?: CollectionSectionOptions[\"renderMaster\"];\n renderDetailHeader?: CollectionSectionOptions[\"renderDetailHeader\"];\n renderEmptyDetail?: CollectionSectionOptions[\"renderEmptyDetail\"];\n hrefForRecord?: CollectionSectionOptions[\"hrefForRecord\"];\n extendRecordTabs?: CollectionSectionOptions[\"extendRecordTabs\"];\n}): AdminSection {\n const {\n crm,\n id = \"people\",\n label = \"People\",\n type = \"person\",\n roles,\n networkSharing,\n collapseClosedDetail,\n lifecycleAdapter,\n requireLifecycleAdapter,\n renderSummary,\n renderMaster,\n renderDetailHeader,\n renderEmptyDetail,\n hrefForRecord,\n extendRecordTabs,\n } = options;\n return collectionSection({\n crm,\n type,\n id,\n label,\n ...(roles ? { roles } : {}),\n ...(networkSharing != null ? { networkSharing } : {}),\n ...(collapseClosedDetail != null ? { collapseClosedDetail } : {}),\n ...(lifecycleAdapter ? { lifecycleAdapter } : {}),\n ...(requireLifecycleAdapter != null ? { requireLifecycleAdapter } : {}),\n ...(renderSummary ? { renderSummary } : {}),\n ...(renderMaster ? { renderMaster } : {}),\n ...(renderDetailHeader ? { renderDetailHeader } : {}),\n ...(renderEmptyDetail ? { renderEmptyDetail } : {}),\n ...(hrefForRecord ? { hrefForRecord } : {}),\n ...(extendRecordTabs ? { extendRecordTabs } : {}),\n });\n}\n","import { ThemeScope } from \"@odla-ai/ui/components\";\nimport type { ComponentChildren, Ref } from \"preact\";\nimport type { Chapter } from \"../types.js\";\nimport { adminRouteFromUrl, adminRouteHref } from \"./admin-route.js\";\nimport type { AdminWorkspace } from \"./chrome.js\";\nimport { BrandStyle } from \"./brand-style.js\";\nimport { ChapterCopyProvider } from \"./copy-context.js\";\n\nexport function AdminTheme(props: {\n chapter?: Chapter;\n children: ComponentChildren;\n /** The theme scope element. Vendor widgets that read `--ui-*` off a live\n * element (Clerk's appearance bridge) must read THIS one, not the document\n * root, or an admin brand silently falls back to the host page's palette. */\n scopeRef?: Ref<HTMLDivElement>;\n}) {\n const brand = props.chapter?.brand;\n return (\n <ChapterCopyProvider copy={props.chapter?.copy}>\n <ThemeScope\n ref={props.scopeRef}\n data-chapter-admin=\"\"\n theme={brand?.theme}\n accent={brand?.accent}\n colorScheme={brand?.colorScheme ?? \"light\"}\n >\n <BrandStyle brand={brand} selector=\"[data-chapter-admin]\" />\n {props.children}\n </ThemeScope>\n </ChapterCopyProvider>\n );\n}\n\nexport function signInRedirect(\n basePath: string,\n workspaces: readonly AdminWorkspace[],\n): string {\n if (typeof window === \"undefined\") return basePath;\n const current = new URL(window.location.href);\n const inbound = adminRouteFromUrl(\n current,\n basePath,\n workspaces.map((workspace) => workspace.id),\n );\n const workspace = workspaces.find((item) => item.id === inbound.workspaceId);\n const route = inbound.viewId || !workspace?.defaultViewId\n ? inbound\n : { ...inbound, viewId: workspace.defaultViewId };\n // Clerk owns the hash while signed out. Preserve requested admin state in\n // its return query, then let AdminShell canonicalize after authentication.\n return adminRouteHref(current, basePath, route, \"query\");\n}\n","// Bridging the admin theme's tokens into Clerk's appearance contract.\nimport type { RefObject } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport { clerkAppearanceFromTokens } from \"@odla-ai/auth-clerk\";\n\ntype ClerkAppearance = ReturnType<typeof clerkAppearanceFromTokens>;\n\n/**\n * Read the Clerk appearance from the admin theme scope rather than the document\n * root.\n *\n * `clerkAppearanceFromTokens()` defaults to `document.documentElement`, but the\n * brand tokens are written scoped to `[data-chapter-admin]` so an admin brand\n * cannot recolor the host page or vendor sign-in UI. Reading the root would\n * therefore theme the widget from whatever the HOST page happens to define —\n * on a page with no `--ui-*` at root, @odla-ai/ui's dark-mode defaults win and\n * the sign-in card renders dark while the console beneath it is light.\n *\n * The scope is an ancestor rendered in the same pass, so it can only be\n * measured after mount. Returns `undefined` until then; callers should hold the\n * widget back rather than mount it against the defaults, because a mounted\n * Clerk widget keeps its startup palette.\n */\nexport function useScopedClerkAppearance(\n scope: RefObject<HTMLElement | null>,\n): ClerkAppearance | undefined {\n const [appearance, setAppearance] = useState<ClerkAppearance>();\n useEffect(() => {\n setAppearance(clerkAppearanceFromTokens(scope.current ?? undefined));\n }, [scope]);\n return appearance;\n}\n","/** Normalized public auth configuration consumed by the Clerk gate. */\nexport interface ChapterAdminAuthConfig {\n publishableKey: string | null;\n}\n\n/** Normalized current-user data retained for workspace visibility decisions. */\nexport interface ChapterAdminUser extends Record<string, unknown> {\n authorized?: boolean;\n email?: string | null;\n}\n\n/** Inputs supplied to custom admin configuration and current-user loaders. */\nexport interface ChapterAdminAuthLoadContext {\n apiBase: string;\n getToken?: () => Promise<string | null>;\n}\n\n/** Existing-site adapter for auth endpoint names and response shapes. */\nexport interface ChapterAdminAuthAdapter {\n configPath?: string;\n currentUserPath?: string;\n loadConfig?: (\n context: ChapterAdminAuthLoadContext,\n ) => Promise<ChapterAdminAuthConfig>;\n loadCurrentUser?: (\n context: Required<ChapterAdminAuthLoadContext>,\n ) => Promise<ChapterAdminUser>;\n mapConfig?: (body: Record<string, unknown>) => ChapterAdminAuthConfig;\n mapCurrentUser?: (body: Record<string, unknown>) => ChapterAdminUser;\n isAuthorized?: (user: ChapterAdminUser) => boolean;\n}\n\nconst apiUrl = (apiBase: string, path: string): string =>\n `${apiBase.replace(/\\/+$/, \"\")}/${path.replace(/^\\/+/, \"\")}`;\n\nexport const DEFAULT_ADMIN_AUTH: ChapterAdminAuthAdapter = {};\n\n/** Load and normalize the public authentication configuration. */\nexport async function loadChapterAdminConfig(\n adapter: ChapterAdminAuthAdapter,\n apiBase: string,\n): Promise<ChapterAdminAuthConfig> {\n if (adapter.loadConfig) return adapter.loadConfig({ apiBase });\n const response = await fetch(apiUrl(apiBase, adapter.configPath ?? \"/api/config\"));\n const body = (await response.json()) as Record<string, unknown>;\n if (adapter.mapConfig) return adapter.mapConfig(body);\n return {\n publishableKey:\n typeof body.clerkPublishableKey === \"string\"\n ? body.clerkPublishableKey\n : null,\n };\n}\n\n/** Load and normalize the authenticated user used by admin workspaces. */\nexport async function loadChapterAdminUser(\n adapter: ChapterAdminAuthAdapter,\n apiBase: string,\n getToken: () => Promise<string | null>,\n): Promise<ChapterAdminUser> {\n if (adapter.loadCurrentUser) {\n return adapter.loadCurrentUser({ apiBase, getToken });\n }\n const token = await getToken();\n const response = await fetch(apiUrl(apiBase, adapter.currentUserPath ?? \"/api/me\"), {\n headers: token ? { authorization: `Bearer ${token}` } : {},\n });\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n return adapter.mapCurrentUser?.(body) ?? body;\n}\n","// Compatibility entry for the workspace-based default console.\nimport type { Chapter } from \"../types\";\nimport type { AdminSection } from \"./chrome.js\";\nimport { defaultAdminWorkspaces } from \"./admin-workspaces.js\";\n\n/** Legacy default catalog. @deprecated Use defaultAdminWorkspaces. */\nexport function defaultAdminSections(chapter: Chapter): AdminSection[] {\n return defaultAdminWorkspaces(chapter);\n}\n\nexport { defaultAdminWorkspaces };\n","// Meetings section: the reconciled agenda from GET /api/admin/meetings, with the\n// reschedule and cancel actions wired to POST /api/admin/meetings/:id/{...}.\n// Built from odla-ui .panel + Button; drift against live Google state is flagged.\nimport { useState } from \"preact/hooks\";\nimport { Button } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface MeetingRow {\n id: string;\n startAt: number;\n endAt: number;\n status: string;\n drift: string;\n meetUrl: string | null;\n applicant: { name: string; email: string; status: string } | null;\n}\n\nconst when = (t: number): string => new Date(t).toLocaleString([], { dateStyle: \"medium\", timeStyle: \"short\" });\n\nfunction MeetingsBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.meetings;\n const { data, loading, error, refresh } = useAdminResource<{ meetings: MeetingRow[]; timezone: string }>(ctx.getToken, \"/api/admin/meetings?all=1\");\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const run = async (id: string, fn: () => Promise<void>) => {\n setBusy(id);\n setNote(null);\n try {\n await fn();\n refresh();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const cancel = (id: string) => {\n if (!globalThis.confirm?.(copy.cancelConfirm)) return;\n void run(id, () => adminFetch(ctx.getToken, `/api/admin/meetings/${id}/cancel`, { method: \"POST\" }));\n };\n const reschedule = (id: string) => {\n const input = globalThis.prompt?.(copy.newStartPrompt);\n if (!input) return;\n const startAt = Date.parse(input);\n if (!Number.isFinite(startAt)) {\n setNote(copy.parseFailed);\n return;\n }\n void run(id, () => adminFetch(ctx.getToken, `/api/admin/meetings/${id}/reschedule`, { method: \"POST\", body: JSON.stringify({ startAt }) }));\n };\n\n return (\n <AdminPage>\n <Panel title={<>{copy.agenda} <span className=\"muted\" style={{ fontWeight: 400 }}>· {data.timezone}</span></>} actions={note ? <span className=\"muted\">{note}</span> : undefined}>\n {data.meetings.length === 0 ? (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.empty}</p>\n ) : (\n <ul style={{ listStyle: \"none\", margin: 0, padding: 0, display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {data.meetings.map((m) => (\n <li key={m.id} style={{ display: \"flex\", alignItems: \"center\", gap: 12, flexWrap: \"wrap\", opacity: m.status === \"cancelled\" ? 0.55 : 1 }}>\n <strong style={{ minWidth: 170 }}>{when(m.startAt)}</strong>\n <span style={{ flex: 1 }}>{m.applicant ? `${m.applicant.name} · ${m.applicant.email}` : copy.unknown}</span>\n <span className=\"badge\">{m.status}</span>\n {m.drift && m.drift !== \"none\" ? <span className=\"badge\">{copy.drift}: {m.drift}</span> : null}\n {m.meetUrl ? <a href={m.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.meet}</a> : null}\n {m.status === \"scheduled\" ? (\n <>\n <Button variant=\"secondary\" mini disabled={busy === m.id} onClick={() => reschedule(m.id)}>{copy.reschedule}</Button>\n <Button variant=\"danger\" mini disabled={busy === m.id} onClick={() => cancel(m.id)}>{copy.cancel}</Button>\n </>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link meetingsSection}. */\nexport interface MeetingsSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Meetings admin section: the reconciled agenda over\n * `GET /api/admin/meetings`, with reschedule/cancel actions. */\nexport function meetingsSection(options: MeetingsSectionOptions = {}): AdminSection {\n const { id = \"meetings\", label = \"Meetings\" } = options;\n return { id, label, render: (ctx) => <MeetingsBody ctx={ctx} /> };\n}\n"],"mappings":"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","names":["useEffect","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","useState","useEffect","jsxs","jsx","Tabs","useState","useCallback","useEffect","useState","jsx","jsxs","useState","jsx","jsxs","Fragment","jsx","jsxs","money","useState","Button","Checkbox","DataTable","Field","Input","jsx","jsxs","useState","Field","Input","Button","Checkbox","DataTable","useEffect","useState","Button","Field","jsx","jsxs","useState","useEffect","Field","Button","useState","jsx","jsxs","useState","useCallback","useEffect","useState","jsx","useCallback","useEffect","useState","Button","Field","Select","jsx","jsxs","useState","Field","Select","Button","useCallback","useEffect","useState","Button","Fragment","jsx","jsxs","useState","Button","jsx","jsx","jsx","Tabs","ThemeScope","jsx","jsxs","ThemeScope","workspace","useEffect","useState","jsx","jsxs","useState","useEffect","useState","Button","Fragment","jsx","jsxs","when","useState","Button"]}
|
package/dist/ui/admin/index.d.ts
CHANGED
|
@@ -122,7 +122,11 @@ interface AdminShellProps {
|
|
|
122
122
|
/** Configuration for the Clerk-gated, brand-scoped Chapter admin console. */
|
|
123
123
|
interface ChapterAdminProps {
|
|
124
124
|
chapter?: Chapter;
|
|
125
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* Replace or transform the standard workspace set. During existing-site
|
|
127
|
+
* adoption, use the transform to preserve a validated host workspace until
|
|
128
|
+
* feature-level parity is proven; matching ids or labels are not parity.
|
|
129
|
+
*/
|
|
126
130
|
workspaces?: AdminWorkspace[] | ((defaults: readonly AdminWorkspace[]) => AdminWorkspace[]);
|
|
127
131
|
/** @deprecated Use workspaces. */
|
|
128
132
|
sections?: AdminSection[];
|
package/dist/ui/admin/index.js
CHANGED
package/dist/ui/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/chapter",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.5",
|
|
4
4
|
"description": "A leader/follower foundation for branded membership sites: shared CRM, admin, auth, payments, booking, and explicit record delivery from one defineChapter config.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://odla.ai/docs/packages/chapter",
|
|
@@ -412,6 +412,14 @@ provider-idempotency contract.
|
|
|
412
412
|
Render the Chapter component beside the current implementation in a dev-only
|
|
413
413
|
fixture. Compare markup/behavior and the Phase 0 screenshots before deletion.
|
|
414
414
|
|
|
415
|
+
Before replacing any existing admin workspace, build a feature-level matrix.
|
|
416
|
+
Top-level labels and route ids are inventory keys, not parity evidence. For each
|
|
417
|
+
workspace record summaries, search/filter/sort/pagination, selection and deep
|
|
418
|
+
links, roles and permission signals, record tabs, mutations and provider side
|
|
419
|
+
effects, and loading/empty/error/unauthorized/keyboard/responsive states.
|
|
420
|
+
Classify every row as packaged-equivalent, composed through a documented seam,
|
|
421
|
+
an explicit PM-approved delta, or blocked.
|
|
422
|
+
|
|
415
423
|
- Import the existing public theme plus its `scope.css`,
|
|
416
424
|
`@odla-ai/ui/index.css`, and `@odla-ai/crm/ui.css` before host CSS.
|
|
417
425
|
- Map the legacy semantic design roles into `brand.tokens` and `tokensDark`;
|
|
@@ -441,6 +449,14 @@ fixture. Compare markup/behavior and the Phase 0 screenshots before deletion.
|
|
|
441
449
|
heading, and specialized panels with `collectionSection`'s `renderSummary`,
|
|
442
450
|
`renderMaster`, `renderDetailHeader`, and record-tab slots. These slots
|
|
443
451
|
customize content; they do not fix pane geometry.
|
|
452
|
+
- The safe first cutover for a validated custom workspace is a `workspaces`
|
|
453
|
+
transform that matches its exact default id, spreads the default metadata,
|
|
454
|
+
and replaces only `render` with the existing component. Fail closed if the
|
|
455
|
+
expected id disappears. Keep an integration test proving the host component
|
|
456
|
+
and representative summary, exploration, role, and operation affordances
|
|
457
|
+
render. Migrate those behaviors into `collectionSection` or `peopleSection`
|
|
458
|
+
slots incrementally; delete the old component only after every matrix row and
|
|
459
|
+
the deployed journey pass.
|
|
444
460
|
- Operational usability is not pixel parity with a cramped legacy admin. At
|
|
445
461
|
desktop widths, the unselected People collection must use the full workspace
|
|
446
462
|
width; after a record opens it becomes master/detail. This is the
|
|
@@ -473,6 +489,9 @@ At 390, 768, 1280, and 1440 pixels in every theme, compare:
|
|
|
473
489
|
- at 1280 and 1440, every unselected collection table uses the full content
|
|
474
490
|
width: no empty detail pane and no wide table squeezed into a narrow rail;
|
|
475
491
|
after selection, both master and detail remain usable;
|
|
492
|
+
- record the CSS-pixel bounding boxes for the accepted outer workspace, master,
|
|
493
|
+
and detail at desktop widths. Compare those measurements with the frozen
|
|
494
|
+
baseline; static markup and component identity cannot prove geometry;
|
|
476
495
|
- no clipped labels, card text escape, accidental document scroll, or
|
|
477
496
|
horizontal overflow;
|
|
478
497
|
- loading, empty, error, unauthorized, 404, and reduced-motion states.
|
|
@@ -586,6 +605,26 @@ Run the real journey:
|
|
|
586
605
|
`doctor`, unit tests, build, CLI smoke, a login page, and a human-looking admin
|
|
587
606
|
screen are necessary but not sufficient.
|
|
588
607
|
|
|
608
|
+
### Close the source-to-deployment loop
|
|
609
|
+
|
|
610
|
+
A commit, pushed branch, or merged pull request does not change a running
|
|
611
|
+
website. After every change that affects a route, workspace, asset, provider
|
|
612
|
+
binding, or acceptance result:
|
|
613
|
+
|
|
614
|
+
1. identify the exact reviewed commit and intended deployment target;
|
|
615
|
+
2. build and deploy that commit with the repository's reviewed dev command;
|
|
616
|
+
3. capture the deploy command, direct origin, immutable Worker/deployment
|
|
617
|
+
version, and source commit in PM;
|
|
618
|
+
4. reload the direct deployed origin and assert distinctive behavior from the
|
|
619
|
+
acceptance matrix—not merely a shared label or route;
|
|
620
|
+
5. measure the deployed viewport geometry and exercise the affected journey;
|
|
621
|
+
6. leave the bug/task open if the intended commit was not deployed or the live
|
|
622
|
+
assertion was not observed.
|
|
623
|
+
|
|
624
|
+
Do not report “fixed”, “ready for handoff”, or a passing phase from source-only
|
|
625
|
+
tests. If CI is expected to deploy a branch or merge automatically, verify the
|
|
626
|
+
actual completed deployment and version rather than assuming the trigger ran.
|
|
627
|
+
|
|
589
628
|
Before filing a route bug from deployed evidence, prove that the probed
|
|
590
629
|
deployment runs the intended commit/version. Repeat the request against the
|
|
591
630
|
direct candidate origin and the public domain with a unique non-secret query
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/admin.tsx","../src/ui/chrome.tsx","../src/ui/admin-layout.tsx","../src/ui/admin-brand.tsx","../src/ui/admin-route.ts","../src/ui/admin-workspaces.tsx","../src/ui/admin-availability.tsx","../src/ui/admin-api.ts","../src/ui/admin-billing.tsx","../src/ui/admin-dashboard.tsx","../src/ui/admin-email.tsx","../src/ui/admin-people-workspace.tsx","../src/ui/admin-record-actions.tsx","../src/ui/admin-network.tsx","../src/ui/admin-record-activity.tsx","../src/ui/admin-record-comms.tsx","../src/ui/admin-record-scheduling.tsx","../src/ui/admin-people.tsx","../src/ui/admin-frame.tsx","../src/ui/admin-appearance.ts","../src/ui/admin-auth.ts","../src/ui/admin-defaults.ts","../src/ui/admin-meetings.tsx"],"sourcesContent":["// ChapterAdmin owns auth and operational wiring; sites choose or replace chrome\n// and workspaces without reimplementing the boundary.\nimport type { ComponentChildren } from \"preact\";\nimport { useEffect, useMemo, useRef, useState } from \"preact/hooks\";\nimport { ClerkGate, SignedIn, SignedOut, SignIn, useClerkAuth } from \"@odla-ai/auth-clerk\";\nimport { CrmClient } from \"@odla-ai/crm\";\nimport { S, Gate, AdminShell } from \"./chrome.js\";\nimport { defaultAdminWorkspaces } from \"./admin-workspaces.js\";\nimport { AdminTheme, signInRedirect } from \"./admin-frame.js\";\nimport { useScopedClerkAppearance } from \"./admin-appearance.js\";\nimport {\n DEFAULT_ADMIN_AUTH,\n loadChapterAdminConfig,\n loadChapterAdminUser,\n type ChapterAdminAuthAdapter,\n type ChapterAdminUser,\n} from \"./admin-auth.js\";\nimport type {\n AdminAccountMenuProps,\n AdminChrome,\n AdminRouting,\n AdminSection,\n AdminShellProps,\n AdminWorkspace,\n AdminWorkspaceNavProps,\n Brand,\n} from \"./chrome.js\";\nimport type { Chapter } from \"../types\";\nimport { DEFAULT_CHAPTER_COPY, formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\nexport type {\n AdminSection,\n AdminSectionContext,\n AdminWorkspace,\n AdminRouteState,\n AdminRouteTarget,\n} from \"./chrome.js\";\nexport { loadChapterAdminConfig, loadChapterAdminUser } from \"./admin-auth.js\";\nexport type {\n ChapterAdminAuthAdapter,\n ChapterAdminAuthConfig,\n ChapterAdminAuthLoadContext,\n ChapterAdminUser,\n} from \"./admin-auth.js\";\n\n/** Configuration for the Clerk-gated, brand-scoped Chapter admin console. */\nexport interface ChapterAdminProps {\n chapter?: Chapter;\n /** Replace or transform the standard workspace set. */\n workspaces?:\n | AdminWorkspace[]\n | ((defaults: readonly AdminWorkspace[]) => AdminWorkspace[]);\n /** @deprecated Use workspaces. */\n sections?: AdminSection[];\n basePath?: string;\n brand?: Brand;\n crmBasePath?: string;\n apiBase?: string;\n /** Default fragment: `/admin/#people/person/record-id/profile`. */\n routing?: AdminRouting;\n /** Default embedded. Standalone adds packaged global chrome. */\n chrome?: AdminChrome;\n renderHeader?: AdminShellProps[\"renderHeader\"];\n renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;\n /** Adapt existing config/current-user endpoints without rewriting auth. */\n auth?: ChapterAdminAuthAdapter;\n}\n\nfunction Authed(props: {\n workspaces: AdminWorkspace[];\n basePath: string;\n brand: Brand;\n crmBasePath: string;\n apiBase: string;\n routing: AdminRouting;\n chrome: AdminChrome;\n auth: ChapterAdminAuthAdapter;\n renderHeader?: AdminShellProps[\"renderHeader\"];\n renderAccountMenu?: AdminShellProps[\"renderAccountMenu\"];\n renderWorkspaceNav?: AdminShellProps[\"renderWorkspaceNav\"];\n}) {\n const copy = useChapterCopy().admin;\n const {\n workspaces,\n basePath,\n brand,\n crmBasePath,\n apiBase,\n routing,\n chrome,\n auth,\n renderHeader,\n renderAccountMenu,\n renderWorkspaceNav,\n } = props;\n const { getToken, signOut } = useClerkAuth();\n const client = useMemo(\n () =>\n new CrmClient({\n basePath: crmBasePath,\n headers: async (): Promise<Record<string, string>> => {\n const token = await getToken();\n return token ? { authorization: `Bearer ${token}` } : {};\n },\n }),\n [getToken, crmBasePath],\n );\n const [state, setState] = useState<{\n status: \"checking\" | \"ok\" | \"denied\";\n email?: string | null;\n user?: ChapterAdminUser;\n }>({ status: \"checking\" });\n\n useEffect(() => {\n let live = true;\n void (async () => {\n try {\n const body = await loadChapterAdminUser(auth, apiBase, getToken);\n const authorized = auth.isAuthorized\n ? auth.isAuthorized(body)\n : body.authorized === true;\n if (live) setState({\n status: authorized ? \"ok\" : \"denied\",\n email: typeof body.email === \"string\" ? body.email : null,\n user: body,\n });\n } catch {\n if (live) setState({ status: \"denied\" });\n }\n })();\n return () => {\n live = false;\n };\n }, [getToken, apiBase, auth]);\n\n if (state.status === \"checking\") return <Gate brand={brand}><p style={S.muted}>{copy.auth.checking}</p></Gate>;\n if (state.status === \"denied\") {\n return (\n <Gate brand={brand}>\n <div className=\"card\" style={S.card}>\n <h2 style={{ marginTop: 0 }}>{copy.auth.notAuthorized}</h2>\n <p style={S.muted}>\n {formatChapterCopy(copy.auth.accountNotAuthorized, {\n account: state.email ?? copy.auth.thisAccount,\n })}\n </p>\n <button className=\"btn secondary\" onClick={() => signOut()}>{copy.auth.signOut}</button>\n </div>\n </Gate>\n );\n }\n return (\n <AdminShell\n workspaces={workspaces}\n basePath={basePath}\n brand={brand}\n client={client}\n getToken={getToken}\n signOut={signOut}\n email={state.email ?? null}\n currentUser={state.user}\n routing={routing}\n chrome={chrome}\n renderHeader={renderHeader}\n renderAccountMenu={renderAccountMenu}\n renderWorkspaceNav={renderWorkspaceNav}\n />\n );\n}\n\n/** Render the complete authenticated admin application from one Chapter config. */\nexport function ChapterAdmin(props: ChapterAdminProps) {\n const copy = props.chapter?.copy ?? DEFAULT_CHAPTER_COPY;\n const defaults = useMemo(\n () => (props.chapter ? defaultAdminWorkspaces(props.chapter) : []),\n [props.chapter],\n );\n const workspaces = useMemo(() => {\n if (typeof props.workspaces === \"function\") return props.workspaces(defaults);\n return props.workspaces ?? props.sections ?? defaults;\n }, [props.workspaces, props.sections, defaults]);\n const basePath = props.basePath ?? \"/admin\";\n const brand = props.brand ?? {\n name: props.chapter?.name ?? copy.admin.shell.adminName,\n badge: props.chapter?.brand.badge,\n wordmark: props.chapter?.brand.wordmark,\n };\n const crmBasePath = props.crmBasePath ?? \"/api/crm\";\n const apiBase = props.apiBase ?? \"\";\n const routing = props.routing ?? \"fragment\";\n const chrome = props.chrome ?? \"embedded\";\n const auth = props.auth ?? DEFAULT_ADMIN_AUTH;\n const redirect = signInRedirect(basePath, workspaces);\n const [publishableKey, setPublishableKey] = useState<string | null | undefined>(undefined);\n\n const scopeRef = useRef<HTMLDivElement>(null);\n const appearance = useScopedClerkAppearance(scopeRef);\n\n useEffect(() => {\n let live = true;\n void loadChapterAdminConfig(auth, apiBase)\n .then((config) =>\n live && setPublishableKey(config.publishableKey ?? null))\n .catch(() => live && setPublishableKey(null));\n return () => {\n live = false;\n };\n }, [apiBase, auth]);\n\n let content: ComponentChildren;\n // A mounted Clerk widget keeps its startup palette, so wait for the scope\n // rather than mounting it against the defaults and re-theming after.\n if (publishableKey === undefined || (publishableKey && !appearance)) {\n content = <Gate brand={brand}><p style={S.muted}>{copy.admin.auth.loading}</p></Gate>;\n } else if (!publishableKey) {\n content = (\n <Gate brand={brand}>\n <div className=\"card\" style={S.card}>\n <h2 style={{ marginTop: 0 }}>{copy.admin.auth.signInNotConfigured}</h2>\n <p style={S.muted}>{copy.admin.auth.missingPublishableKey}</p>\n </div>\n </Gate>\n );\n } else if (workspaces.length === 0) {\n content = <Gate brand={brand}><p style={S.muted}>{copy.admin.auth.noWorkspaces}</p></Gate>;\n } else {\n content = (\n <ClerkGate\n publishableKey={publishableKey}\n appearance={appearance}\n afterSignOutUrl=\"/\"\n >\n <SignedOut>\n <Gate brand={brand} tagline={copy.admin.auth.signInTagline}>\n <SignIn\n routing=\"hash\"\n forceRedirectUrl={redirect}\n signUpForceRedirectUrl={redirect}\n />\n </Gate>\n </SignedOut>\n <SignedIn>\n <Authed\n workspaces={workspaces}\n basePath={basePath}\n brand={brand}\n crmBasePath={crmBasePath}\n apiBase={apiBase}\n routing={routing}\n chrome={chrome}\n auth={auth}\n renderHeader={props.renderHeader}\n renderAccountMenu={props.renderAccountMenu}\n renderWorkspaceNav={props.renderWorkspaceNav}\n />\n </SignedIn>\n </ClerkGate>\n );\n }\n return <AdminTheme chapter={props.chapter} scopeRef={scopeRef}>{content}</AdminTheme>;\n}\n","// Shared workspace contracts, auth gates, and signed-in Chapter admin shell.\nimport type { ComponentChildren } from \"preact\";\nimport { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { Tabs, ThemeScope, TopBar, TopBarLink } from \"@odla-ai/ui/components\";\nimport type { CrmClient } from \"@odla-ai/crm\";\nimport { ThemeWarning } from \"./admin-layout.js\";\nimport { badgeText, brandDisplay, S, type Brand } from \"./admin-brand.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport {\n adminRouteFromUrl,\n adminRouteHref,\n adminSectionFromUrl,\n adminSectionHref,\n type AdminRouteState,\n type AdminRouting,\n} from \"./admin-route.js\";\n\nexport {\n adminRouteFromUrl,\n adminRouteHref,\n adminSectionFromUrl,\n adminSectionHref,\n};\nexport type { AdminRouteState, AdminRouting };\nexport { Gate, S } from \"./admin-brand.js\";\nexport type { Brand } from \"./admin-brand.js\";\n\n/** A workspace id or partial nested route passed to navigation helpers. */\nexport type AdminRouteTarget =\n | string\n | {\n workspaceId?: string;\n viewId?: string | null;\n recordId?: string | null;\n detailTab?: string | null;\n };\n\n/** Context shared by every admin workspace and its nested views. */\nexport interface AdminSectionContext {\n client: CrmClient;\n getToken: () => Promise<string | null>;\n currentUser?: Record<string, unknown>;\n route: AdminRouteState;\n navigate: (target: AdminRouteTarget) => void;\n href: (target: AdminRouteTarget) => string;\n}\n\n/** One top-level admin workspace rendered inside the signed-in shell. */\nexport interface AdminWorkspace {\n id: string;\n label: string;\n /** Canonical nested view used when a workspace is opened without one. */\n defaultViewId?: string;\n /** Optional named @odla-ai/ui accent scoped to this workspace's content. */\n accent?: string;\n render: (ctx: AdminSectionContext) => ComponentChildren;\n}\n\n/** Legacy name for a top-level workspace. @deprecated Use AdminWorkspace. */\nexport type AdminSection = AdminWorkspace;\n/** Built-in shell presentation; embedded preserves site-owned chrome. */\nexport type AdminChrome = \"embedded\" | \"standalone\" | \"editorial\" | \"topbar\" | \"none\";\n\n/** Identity and sign-out services supplied to host-owned account controls. */\nexport interface AdminAccountMenuProps {\n brand: Brand; email: string | null;\n currentUser?: Record<string, unknown>;\n signOut: () => void;\n}\n\n/** Workspace route and navigation services supplied to host-owned navigation. */\nexport interface AdminWorkspaceNavProps {\n workspaces: readonly AdminWorkspace[]; route: AdminRouteState;\n navigate: (target: AdminRouteTarget) => void; href: (target: AdminRouteTarget) => string;\n}\n\nconst mergeRoute = (current: AdminRouteState, target: AdminRouteTarget): AdminRouteState => {\n if (typeof target === \"string\") return { workspaceId: target };\n const changingWorkspace = target.workspaceId != null && target.workspaceId !== current.workspaceId;\n const next: AdminRouteState = changingWorkspace\n ? { workspaceId: target.workspaceId! }\n : { ...current, ...(target.workspaceId ? { workspaceId: target.workspaceId } : {}) };\n for (const key of [\"viewId\", \"recordId\", \"detailTab\"] as const) {\n const value = target[key];\n if (value === null) delete next[key];\n else if (value !== undefined) next[key] = value;\n }\n if (target.viewId !== undefined && target.recordId === undefined) {\n delete next.recordId;\n delete next.detailTab;\n }\n if (target.recordId === null) delete next.detailTab;\n return next;\n};\n\nexport interface AdminShellProps {\n workspaces: AdminWorkspace[]; basePath: string; brand: Brand; client: CrmClient;\n getToken: () => Promise<string | null>;\n signOut: () => void; email: string | null;\n currentUser?: Record<string, unknown>;\n routing?: AdminRouting;\n chrome?: AdminChrome;\n renderHeader?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;\n renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;\n}\n\nexport function AdminShell({\n workspaces,\n basePath,\n brand,\n client,\n getToken,\n signOut,\n email,\n currentUser,\n routing = \"fragment\",\n chrome = \"embedded\",\n renderHeader,\n renderAccountMenu,\n renderWorkspaceNav,\n}: AdminShellProps) {\n const copy = useChapterCopy().admin;\n const normalizeRoute = useCallback((candidate: AdminRouteState): AdminRouteState => {\n if (candidate.viewId) return candidate;\n const workspace = workspaces.find((item) => item.id === candidate.workspaceId);\n return workspace?.defaultViewId\n ? { ...candidate, viewId: workspace.defaultViewId }\n : candidate;\n }, [workspaces]);\n const routeFromLocation = useCallback(() => {\n if (typeof window === \"undefined\") {\n return normalizeRoute({ workspaceId: workspaces[0]?.id ?? \"\" });\n }\n return normalizeRoute(\n adminRouteFromUrl(new URL(window.location.href), basePath, workspaces.map((workspace) => workspace.id)),\n );\n }, [workspaces, basePath, normalizeRoute]);\n const [route, setRoute] = useState<AdminRouteState>(routeFromLocation);\n const href = useCallback(\n (target: AdminRouteTarget) => {\n const next = normalizeRoute(mergeRoute(route, target));\n if (typeof window === \"undefined\") {\n return `#${[\n next.workspaceId,\n next.viewId,\n next.recordId,\n next.detailTab,\n ].filter((part): part is string => Boolean(part)).map(encodeURIComponent).join(\"/\")}`;\n }\n return adminRouteHref(new URL(window.location.href), basePath, next, routing);\n },\n [route, basePath, routing, normalizeRoute],\n );\n const navigate = useCallback(\n (target: AdminRouteTarget) => {\n const next = normalizeRoute(mergeRoute(route, target));\n if (typeof window !== \"undefined\") {\n window.history.pushState(null, \"\", adminRouteHref(new URL(window.location.href), basePath, next, routing));\n }\n setRoute(next);\n },\n [route, basePath, routing, normalizeRoute],\n );\n\n useEffect(() => {\n const sync = () => setRoute(routeFromLocation());\n window.addEventListener(\"popstate\", sync);\n window.addEventListener(\"hashchange\", sync);\n return () => {\n window.removeEventListener(\"popstate\", sync);\n window.removeEventListener(\"hashchange\", sync);\n };\n }, [routeFromLocation]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const canonical = adminRouteHref(new URL(window.location.href), basePath, route, routing);\n const actual = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n if (canonical !== actual) window.history.replaceState(null, \"\", canonical);\n // Canonicalize only initial/inbound state; route changes already own history.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const context: AdminSectionContext = {\n client,\n getToken,\n ...(currentUser ? { currentUser } : {}),\n route,\n navigate,\n href,\n };\n const active = workspaces.find((workspace) => workspace.id === route.workspaceId) ?? workspaces[0];\n const accountProps: AdminAccountMenuProps = {\n brand,\n email,\n ...(currentUser ? { currentUser } : {}),\n signOut,\n };\n const identity = renderAccountMenu?.(accountProps) ?? (\n <>\n <span style={{ ...S.role, color: \"inherit\", borderColor: \"currentColor\", background: \"transparent\" }}>{copy.shell.adminRole}</span>\n {email ? <span style={{ opacity: 0.72, fontSize: 12 }}>{email}</span> : null}\n <button className=\"btn secondary mini\" onClick={signOut}>{copy.auth.signOut}</button>\n </>\n );\n const activeContent = active?.render(context);\n const workspaceContent = active?.accent\n ? <ThemeScope accent={active.accent}>{activeContent}</ThemeScope>\n : activeContent;\n\n if (chrome === \"topbar\") {\n return (\n <>\n <TopBar>\n <a className=\"topbar-brand\" href=\"/\"><span style={S.badgeSm}>{badgeText(brand)}</span>{brandDisplay(brand)}</a>\n <nav className=\"topbar-nav\" aria-label={copy.shell.navigationLabel}>\n {workspaces.map((workspace) => (\n <TopBarLink key={workspace.id} active={workspace.id === route.workspaceId} onClick={() => navigate(workspace.id)}>\n {workspace.label}\n </TopBarLink>\n ))}\n </nav>\n <span className=\"topbar-spacer\" />\n <div className=\"topbar-actions\">{identity}</div>\n </TopBar>\n <main className=\"shell-main\" style={S.main}><ThemeWarning />{workspaceContent}</main>\n </>\n );\n }\n\n const header = renderHeader\n ? renderHeader(accountProps)\n : chrome === \"standalone\" || chrome === \"editorial\" ? (\n <header style={S.masthead}>\n <a href=\"/\" style={S.mastheadBrand}><span style={S.badgeSm}>{badgeText(brand)}</span>{brandDisplay(brand)}</a>\n <span style={{ opacity: 0.68 }}>{copy.shell.adminConsole}</span>\n <span style={{ flex: 1 }} />\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>{identity}</div>\n </header>\n ) : null;\n return (\n <>\n {header}\n <main className=\"shell-main\" style={S.main}>\n <ThemeWarning />\n {renderWorkspaceNav ? (\n <>\n <div style={S.workspaceTabs}>\n {renderWorkspaceNav({ workspaces, route, navigate, href })}\n </div>\n {workspaceContent}\n </>\n ) : (\n <Tabs\n style={S.workspaceTabs}\n ariaLabel={copy.shell.navigationLabel}\n value={route.workspaceId}\n mount=\"active\"\n onValueChange={(workspaceId) =>\n setRoute(normalizeRoute({ workspaceId }))}\n items={workspaces.map((workspace) => ({\n value: workspace.id,\n label: workspace.label,\n href: href(workspace.id),\n panel: workspace.id === route.workspaceId\n ? (workspace.accent\n ? <ThemeScope accent={workspace.accent}>{workspace.render(context)}</ThemeScope>\n : workspace.render(context))\n : null,\n }))}\n />\n )}\n </main>\n </>\n );\n}\n","// Shared layout for the admin sections, so every section is a centered column of\n// odla-ui `.panel` cards with consistent width and spacing — the container the\n// chrome expects sections to own. No invented classes: `.panel`/`.muted` are\n// odla-ui's, and the width/gap is inline so it works without a per-site stylesheet.\nimport type { ComponentChildren, JSX } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\n\nconst PAGE: JSX.CSSProperties = {\n maxWidth: \"var(--ui-content-width, 1120px)\",\n margin: \"0 auto\",\n padding: \"var(--chapter-admin-page-padding, 28px 20px 64px)\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 20,\n};\nconst HEAD: JSX.CSSProperties = { display: \"flex\", alignItems: \"baseline\", justifyContent: \"space-between\", gap: 16, flexWrap: \"wrap\" };\n\n/** The centered content column every admin section renders into. */\nexport function AdminPage({ children }: { children: ComponentChildren }) {\n return <div style={PAGE}>{children}</div>;\n}\n\n/** An odla-ui `.panel` card with an optional heading + trailing actions. */\nexport function Panel({ title, actions, children }: { title?: ComponentChildren; actions?: ComponentChildren; children: ComponentChildren }) {\n return (\n <section className=\"panel\" style={{ display: \"flex\", flexDirection: \"column\", gap: 14 }}>\n {title || actions ? (\n <header style={HEAD}>\n {title ? <h2 style={{ margin: 0, fontSize: 18 }}>{title}</h2> : <span />}\n {actions ? <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>{actions}</div> : null}\n </header>\n ) : null}\n {children}\n </section>\n );\n}\n\n// odla-ui components read their colors from `--ui-*` design tokens whose VALUES\n// come from the theme layer (e.g. @odla-ai/ui/themes/paper/tokens.css + ui.css),\n// NOT from @odla-ai/ui/index.css. Loading only index.css (or a theme whose remap\n// has no primitives behind it) leaves tokens like `--ui-surface` undefined, and\n// the whole console renders transparent/broken — silently. This probes a real\n// `.panel` background and, if it's transparent, says so LOUDLY instead.\nfunction themeLooksMissing(): boolean {\n if (typeof document === \"undefined\") return false;\n const probe = document.createElement(\"div\");\n probe.className = \"panel\";\n probe.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none\";\n document.body.appendChild(probe);\n const bg = getComputedStyle(probe).backgroundColor;\n probe.remove();\n return !bg || bg === \"transparent\" || bg === \"rgba(0, 0, 0, 0)\";\n}\n\n/** A loud banner when the odla-ui theme token layer is missing. */\nexport function ThemeWarning() {\n const [missing, setMissing] = useState(false);\n useEffect(() => setMissing(themeLooksMissing()), []);\n if (!missing) return null;\n return (\n <div\n role=\"alert\"\n style={{ background: \"#7f1d1d\", color: \"#fff\", padding: \"12px 20px\", fontSize: 14, lineHeight: 1.5, textAlign: \"center\" }}\n >\n <strong>odla-ui theme tokens are missing.</strong> The console reads colors from a theme layer, not{\" \"}\n <code>@odla-ai/ui/index.css</code> alone. Import a theme before it — e.g.{\" \"}\n <code>@odla-ai/ui/themes/paper/tokens.css</code> and <code>@odla-ai/ui/themes/paper/ui.css</code> — then{\" \"}\n <code>@odla-ai/ui/index.css</code>. See the @odla-ai/chapter README (“Theme tokens”).\n </div>\n );\n}\n\n/** A centered status line for loading / empty / error states. */\nexport function AdminNote({ children }: { children: ComponentChildren }) {\n return (\n <AdminPage>\n <section className=\"panel\">\n <p className=\"muted\" style={{ margin: 0 }}>{children}</p>\n </section>\n </AdminPage>\n );\n}\n","import type { ComponentChildren, JSX } from \"preact\";\n\nexport type Brand = { name: string; badge?: string; wordmark?: ComponentChildren };\n\nexport const badgeText = (brand: Brand): string =>\n brand.badge ?? brand.name.slice(0, 3).toUpperCase();\n\nexport const brandDisplay = (brand: Brand): ComponentChildren => {\n const display = brand.wordmark ?? brand.name;\n if (typeof display !== \"string\" || !display.includes(\"&\")) return display;\n return (\n <span>\n {display.split(\"&\").map((part, index, all) => (\n <span key={`${part}:${index}`}>\n {part}\n {index < all.length - 1 ? <span className=\"mk-amp\">&</span> : null}\n </span>\n ))}\n </span>\n );\n};\n\nexport const S: Record<string, JSX.CSSProperties> = {\n gate: {\n minHeight: \"100vh\",\n display: \"grid\",\n placeItems: \"center\",\n padding: 24,\n background:\n \"radial-gradient(900px 480px at 50% -8%, var(--ui-accent-soft), transparent 70%),\" +\n \" radial-gradient(700px 500px at 110% 10%, var(--ui-good-soft), transparent 60%)\",\n },\n gateInner: { width: \"100%\", maxWidth: 400, display: \"flex\", flexDirection: \"column\", alignItems: \"center\" },\n brandBox: { textAlign: \"center\", marginBottom: 22 },\n badge: {\n width: 52, height: 52, margin: \"0 auto 14px\", display: \"grid\", placeItems: \"center\",\n fontSize: 15, fontWeight: 700, color: \"var(--ui-on-accent)\",\n background: \"linear-gradient(135deg, var(--ui-accent), var(--ui-accent-strong))\",\n borderRadius: 14, boxShadow: \"0 10px 28px var(--ui-accent-soft)\",\n },\n badgeSm: {\n width: 30, height: 30, display: \"grid\", placeItems: \"center\", fontSize: 10,\n fontWeight: 700, color: \"var(--ui-on-accent)\", background: \"var(--ui-accent)\",\n borderRadius: 8, marginRight: 10,\n },\n h1: { margin: 0, fontSize: 28, letterSpacing: \"-0.02em\", fontWeight: 700 },\n muted: { color: \"var(--ui-text-muted)\" },\n role: {\n fontFamily: \"var(--ui-font-mono)\", fontSize: 11, textTransform: \"uppercase\",\n letterSpacing: \"0.04em\", padding: \"2px 8px\", borderRadius: 999,\n background: \"var(--ui-accent-soft)\", border: \"1px solid var(--ui-accent)\",\n color: \"var(--ui-accent-strong)\",\n },\n main: { minHeight: \"calc(100vh - 61px)\", background: \"var(--ui-bg)\" },\n card: { width: \"100%\", textAlign: \"center\" },\n masthead: {\n display: \"flex\", alignItems: \"center\", gap: 16, flexWrap: \"wrap\",\n padding: \"18px max(20px, calc((100% - 1120px) / 2))\",\n color: \"var(--ui-bg)\", background: \"var(--ui-text)\",\n },\n mastheadBrand: {\n display: \"inline-flex\", alignItems: \"center\", color: \"inherit\",\n fontFamily: \"var(--ui-font-display)\", fontSize: 22, textDecoration: \"none\",\n },\n workspaceTabs: {\n maxWidth: \"var(--ui-content-width, 1160px)\",\n margin: \"0 auto\",\n padding: \"var(--chapter-admin-workspace-padding, 18px 20px 0)\",\n },\n};\n\nexport function Gate(props: { brand: Brand; tagline?: string; children: ComponentChildren }) {\n const { brand, tagline, children } = props;\n return (\n <div style={S.gate}>\n <div style={S.gateInner}>\n <div style={S.brandBox}>\n <div style={S.badge}>{badgeText(brand)}</div>\n <h1 style={S.h1}>{brandDisplay(brand)}</h1>\n {tagline ? <p style={{ ...S.muted, margin: \"8px 0 0\", fontSize: 14 }}>{tagline}</p> : null}\n </div>\n {children}\n </div>\n </div>\n );\n}\n","/** Typed URL state for the admin's nested in-page workspaces. */\nexport interface AdminRouteState {\n workspaceId: string;\n viewId?: string;\n recordId?: string;\n detailTab?: string;\n}\n\n/** URL encoding used for admin workspace state. */\nexport type AdminRouting = \"fragment\" | \"query\" | \"path\";\nexport type AdminRouteAliases = Readonly<Record<string, AdminRouteState>>;\n\nconst DEFAULT_ALIASES: AdminRouteAliases = {\n billing: { workspaceId: \"dashboard\", viewId: \"billing\" },\n meetings: { workspaceId: \"dashboard\" },\n calls: { workspaceId: \"dashboard\" },\n availability: { workspaceId: \"settings\", viewId: \"calendar\" },\n calendar: { workspaceId: \"settings\", viewId: \"calendar\" },\n email: { workspaceId: \"settings\", viewId: \"email\" },\n};\n\nconst cleanBase = (basePath: string): string =>\n basePath.length > 1 ? basePath.replace(/\\/+$/, \"\") : basePath;\n\nconst decode = (segment: string | undefined): string | undefined => {\n if (!segment) return undefined;\n try {\n return decodeURIComponent(segment);\n } catch {\n return undefined;\n }\n};\n\nconst fromParts = (parts: readonly string[]): AdminRouteState | null => {\n const workspaceId = decode(parts[0]);\n if (!workspaceId) return null;\n const viewId = decode(parts[1]);\n const recordId = decode(parts[2]);\n const detailTab = decode(parts[3]);\n return {\n workspaceId,\n ...(viewId ? { viewId } : {}),\n ...(recordId ? { recordId } : {}),\n ...(detailTab ? { detailTab } : {}),\n };\n};\n\nconst resolve = (\n candidate: AdminRouteState | null,\n workspaceIds: readonly string[],\n aliases: AdminRouteAliases,\n): AdminRouteState | null => {\n if (!candidate) return null;\n if (workspaceIds.includes(candidate.workspaceId)) return candidate;\n const alias = aliases[candidate.workspaceId] ?? DEFAULT_ALIASES[candidate.workspaceId];\n return alias && workspaceIds.includes(alias.workspaceId) ? alias : null;\n};\n\n/** Read canonical fragments first, then inbound query and legacy path links. */\nexport function adminRouteFromUrl(\n url: URL,\n basePath: string,\n workspaceIds: readonly string[],\n aliases: AdminRouteAliases = {},\n): AdminRouteState {\n const fallback = { workspaceId: workspaceIds[0] ?? \"\" };\n const hashParts = url.hash.replace(/^#\\/?/, \"\").split(\"/\").filter(Boolean);\n const fromHash = resolve(fromParts(hashParts), workspaceIds, aliases);\n if (fromHash) return fromHash;\n\n const tab = url.searchParams.get(\"tab\");\n const fromQuery = resolve(\n tab\n ? {\n workspaceId: tab,\n ...(url.searchParams.get(\"view\") ? { viewId: url.searchParams.get(\"view\")! } : {}),\n ...(url.searchParams.get(\"record\") ? { recordId: url.searchParams.get(\"record\")! } : {}),\n ...(url.searchParams.get(\"detail\") ? { detailTab: url.searchParams.get(\"detail\")! } : {}),\n }\n : null,\n workspaceIds,\n aliases,\n );\n if (fromQuery) return fromQuery;\n\n const base = cleanBase(basePath);\n const rest = url.pathname.startsWith(base) ? url.pathname.slice(base.length).replace(/^\\//, \"\") : \"\";\n return resolve(fromParts(rest.split(\"/\").filter(Boolean)), workspaceIds, aliases) ?? fallback;\n}\n\nconst encodedParts = (route: AdminRouteState): string[] =>\n [route.workspaceId, route.viewId, route.recordId, route.detailTab]\n .filter((part): part is string => Boolean(part))\n .map(encodeURIComponent);\n\n/** Build a stable URL for one admin state. Fragment routing is the default. */\nexport function adminRouteHref(\n current: URL,\n basePath: string,\n route: AdminRouteState,\n routing: AdminRouting = \"fragment\",\n): string {\n const next = new URL(current);\n const base = cleanBase(basePath);\n const mountPaths = new Set([base, `${base}/`, `${base}/index.html`]);\n if (!mountPaths.has(next.pathname)) next.pathname = `${base}/`;\n for (const key of [\"tab\", \"view\", \"record\", \"detail\"]) next.searchParams.delete(key);\n\n if (routing === \"fragment\") {\n next.hash = encodedParts(route).join(\"/\");\n } else if (routing === \"query\") {\n next.hash = \"\";\n next.searchParams.set(\"tab\", route.workspaceId);\n if (route.viewId) next.searchParams.set(\"view\", route.viewId);\n if (route.recordId) next.searchParams.set(\"record\", route.recordId);\n if (route.detailTab) next.searchParams.set(\"detail\", route.detailTab);\n } else {\n next.hash = \"\";\n next.pathname = `${base}/${encodeURIComponent(route.workspaceId)}`;\n if (route.viewId) next.searchParams.set(\"view\", route.viewId);\n if (route.recordId) next.searchParams.set(\"record\", route.recordId);\n if (route.detailTab) next.searchParams.set(\"detail\", route.detailTab);\n }\n return `${next.pathname}${next.search}${next.hash}`;\n}\n\n/** Backwards-compatible section helpers over the workspace router. */\nexport function adminSectionFromUrl(url: URL, basePath: string, sectionIds: readonly string[]): string {\n return adminRouteFromUrl(url, basePath, sectionIds).workspaceId;\n}\n\n/** Build a compatibility URL for a top-level admin section. */\nexport function adminSectionHref(\n current: URL,\n basePath: string,\n id: string,\n routing: AdminRouting = \"fragment\",\n): string {\n return adminRouteHref(current, basePath, { workspaceId: id }, routing);\n}\n","import { Tabs } from \"@odla-ai/ui/components\";\nimport type { Chapter } from \"../types.js\";\nimport { availabilitySection } from \"./admin-availability.js\";\nimport { billingSection } from \"./admin-billing.js\";\nimport { dashboardSection } from \"./admin-dashboard.js\";\nimport { emailSection } from \"./admin-email.js\";\nimport { collectionSection } from \"./admin-people.js\";\nimport type { AdminSectionContext, AdminWorkspace } from \"./chrome.js\";\n\nexport const adminViewContext = (\n ctx: AdminSectionContext,\n viewId: string,\n active: boolean,\n): AdminSectionContext => {\n const route = {\n workspaceId: ctx.route.workspaceId,\n viewId,\n ...(active && ctx.route.recordId ? { recordId: ctx.route.recordId } : {}),\n ...(active && ctx.route.detailTab ? { detailTab: ctx.route.detailTab } : {}),\n };\n const targetFromView = (target: Parameters<AdminSectionContext[\"navigate\"]>[0]) => {\n if (typeof target === \"string\") return target;\n if (target.workspaceId && target.workspaceId !== route.workspaceId) return target;\n if (target.viewId && target.viewId !== route.viewId) return target;\n return { ...route, ...target };\n };\n return {\n ...ctx,\n route,\n navigate: (target) => ctx.navigate(targetFromView(target)),\n href: (target) => ctx.href(targetFromView(target)),\n };\n};\n\nfunction DashboardWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const copy = chapter.copy.admin;\n const active = ctx.route.viewId === \"billing\" ? \"billing\" : \"overview\";\n const overview = dashboardSection({ id: \"overview\", label: copy.workspaces.overview });\n const billing = billingSection({ label: copy.workspaces.billing });\n return (\n <Tabs\n ariaLabel={copy.workspaces.dashboardViewsLabel}\n value={active}\n mount=\"active\"\n items={[\n {\n value: \"overview\",\n label: copy.workspaces.overview,\n href: ctx.href({ viewId: \"overview\", recordId: null, detailTab: null }),\n panel: overview.render(adminViewContext(ctx, \"overview\", active === \"overview\")),\n },\n {\n value: \"billing\",\n label: copy.workspaces.billing,\n href: ctx.href({ viewId: \"billing\", recordId: null, detailTab: null }),\n panel: billing.render(adminViewContext(ctx, \"billing\", active === \"billing\")),\n },\n ]}\n />\n );\n}\n\nfunction SettingsWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const copy = chapter.copy.admin;\n const active = ctx.route.viewId === \"email\" ? \"email\" : \"calendar\";\n const calendar = availabilitySection({ id: \"calendar\", label: copy.workspaces.calendar });\n const email = emailSection({ label: copy.workspaces.email });\n return (\n <Tabs\n ariaLabel={copy.workspaces.settingsViewsLabel}\n value={active}\n mount=\"active\"\n items={[\n {\n value: \"calendar\",\n label: copy.workspaces.calendar,\n href: ctx.href({ viewId: \"calendar\", recordId: null, detailTab: null }),\n panel: calendar.render(adminViewContext(ctx, \"calendar\", active === \"calendar\")),\n },\n {\n value: \"email\",\n label: copy.workspaces.email,\n href: ctx.href({ viewId: \"email\", recordId: null, detailTab: null }),\n panel: email.render(adminViewContext(ctx, \"email\", active === \"email\")),\n },\n ]}\n />\n );\n}\n\nfunction PeopleWorkspace({ chapter, ctx }: { chapter: Chapter; ctx: AdminSectionContext }) {\n const types = Object.entries(chapter.crm.config.types);\n const fallback = types[0]?.[0] ?? \"person\";\n const active = types.some(([type]) => type === ctx.route.viewId) ? ctx.route.viewId! : fallback;\n const networkSharing = chapter.network.targets.length > 0;\n return (\n <Tabs\n ariaLabel={chapter.copy.admin.workspaces.collectionsLabel}\n value={active}\n variant=\"pill\"\n mount=\"active\"\n items={types.map(([type, def]) => {\n const section = collectionSection({\n crm: chapter.crm,\n type,\n lifecycle: chapter.mode === \"chapter\" && type === \"person\",\n roles: chapter.auth.ladder,\n networkSharing,\n });\n return {\n value: type,\n label: def.labelPlural ?? def.label,\n href: ctx.href({ viewId: type, recordId: null, detailTab: null }),\n panel: section.render(adminViewContext(ctx, type, active === type)),\n };\n })}\n />\n );\n}\n\n/** Default follower grammar: three workspaces with nested operational views. */\nexport function defaultAdminWorkspaces(chapter: Chapter): AdminWorkspace[] {\n const copy = chapter.copy.admin;\n const people: AdminWorkspace = {\n id: \"people\",\n label: copy.workspaces.people,\n defaultViewId: Object.keys(chapter.crm.config.types)[0] ?? \"person\",\n render: (ctx) => <PeopleWorkspace chapter={chapter} ctx={ctx} />,\n };\n if (chapter.mode === \"hub\") return [people];\n return [\n {\n id: \"dashboard\",\n label: copy.workspaces.dashboard,\n defaultViewId: \"overview\",\n render: (ctx) => <DashboardWorkspace chapter={chapter} ctx={ctx} />,\n },\n people,\n {\n id: \"settings\",\n label: copy.workspaces.settings,\n defaultViewId: \"calendar\",\n render: (ctx) => <SettingsWorkspace chapter={chapter} ctx={ctx} />,\n },\n ];\n}\n","// Availability section: the owner-editable booking rules from GET/PUT\n// /api/admin/scheduling, as an odla-ui form. The PUT returns field-keyed\n// validation messages, surfaced inline on each Field.\nimport { useState } from \"preact/hooks\";\nimport { Button, Checkbox, Field, Input } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Scheduling {\n slotMinutes: number;\n days: number[];\n startHour: number;\n endHour: number;\n timezone: string;\n minNoticeHours: number;\n windowDays: number;\n summaryTemplate: string;\n}\nfunction AvailabilityBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.availability;\n const { data, loading, error, refresh } = useAdminResource<{ scheduling: Scheduling }>(ctx.getToken, \"/api/admin/scheduling\");\n const [draft, setDraft] = useState<Scheduling | null>(null);\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n const cfg = draft ?? data?.scheduling ?? null;\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !cfg) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const edit = (patch: Partial<Scheduling>) => setDraft({ ...cfg, ...patch });\n const toggleDay = (d: number) => edit({ days: cfg.days.includes(d) ? cfg.days.filter((x) => x !== d) : [...cfg.days, d].sort() });\n const num = (v: string, fallback: number) => (Number.isFinite(Number(v)) ? Number(v) : fallback);\n\n const save = async () => {\n setBusy(true);\n setNote(null);\n setErrors({});\n const token = await ctx.getToken();\n try {\n const r = await fetch(\"/api/admin/scheduling\", { method: \"PUT\", headers: { authorization: `Bearer ${token ?? \"\"}`, \"content-type\": \"application/json\" }, body: JSON.stringify(cfg) });\n const body = (await r.json().catch(() => ({}))) as { error?: string; errors?: Record<string, string> };\n if (!r.ok) {\n setErrors(body.errors ?? {});\n setNote(body.error ?? `save failed (${r.status})`);\n return;\n }\n setDraft(null);\n refresh();\n setNote(copy.saved);\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n }\n };\n\n const numField = (key: keyof Scheduling, label: string) => (\n <Field label={label} error={errors[key]}>\n <Input type=\"number\" value={cfg[key] as number} onInput={(e) => edit({ [key]: num((e.target as HTMLInputElement).value, cfg[key] as number) } as Partial<Scheduling>)} />\n </Field>\n );\n\n return (\n <AdminPage>\n <Panel title={copy.title} actions={note ? <span className=\"muted\">{note}</span> : undefined}>\n <Field label={copy.days} error={errors.days}>\n <div style={{ display: \"flex\", gap: 14, flexWrap: \"wrap\" }}>\n {copy.dayLabels.map((d, i) => (\n <Checkbox key={d} label={d} checked={cfg.days.includes(i)} onChange={() => toggleDay(i)} />\n ))}\n </div>\n </Field>\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fit, minmax(180px, 1fr))\", gap: 14 }}>\n {numField(\"startHour\", copy.startHour)}\n {numField(\"endHour\", copy.endHour)}\n {numField(\"slotMinutes\", copy.slotMinutes)}\n {numField(\"minNoticeHours\", copy.minNoticeHours)}\n {numField(\"windowDays\", copy.windowDays)}\n <Field label={copy.timezone} error={errors.timezone}>\n <Input value={cfg.timezone} onInput={(e) => edit({ timezone: (e.target as HTMLInputElement).value })} />\n </Field>\n </div>\n <Field label={copy.summaryTemplate} error={errors.summaryTemplate}>\n <Input value={cfg.summaryTemplate} onInput={(e) => edit({ summaryTemplate: (e.target as HTMLInputElement).value })} />\n </Field>\n <div><Button disabled={!draft || busy} onClick={() => void save()}>{copy.save}</Button></div>\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link availabilitySection}. */\nexport interface AvailabilitySectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Availability admin section: the booking-rules editor over\n * `GET/PUT /api/admin/scheduling`, with field-keyed validation surfaced inline. */\nexport function availabilitySection(options: AvailabilitySectionOptions = {}): AdminSection {\n const { id = \"availability\", label = \"Availability\" } = options;\n return { id, label, render: (ctx) => <AvailabilityBody ctx={ctx} /> };\n}\n","// Token-bound access to the /api/admin/* routes for the console sections. Every\n// section fetches with the signed-in admin's bearer token (from ChapterAdmin's\n// getToken) — the worker gates each route with verifyUser + isAdmin, so the UI\n// carries no privilege of its own.\nimport { useCallback, useEffect, useState } from \"preact/hooks\";\n\n/** Fetch a JSON `/api/admin/*` route with the admin bearer token. Throws on a\n * non-2xx (the body's `error`, else the status). */\nexport async function adminFetch<T = unknown>(\n getToken: () => Promise<string | null>,\n path: string,\n init?: RequestInit,\n): Promise<T> {\n const token = await getToken();\n const headers = new Headers(init?.headers);\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n if (init?.body) headers.set(\"content-type\", \"application/json\");\n const res = await fetch(path, { ...init, headers });\n const body = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) throw new Error(typeof body.error === \"string\" ? body.error : `request failed (${res.status})`);\n return body as T;\n}\n\n/** The state of one admin resource load. */\nexport interface AdminResource<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n /** Re-fetch (e.g. after a mutation). */\n refresh: () => void;\n}\n\n/** Load a `/api/admin/*` GET route into Preact state, re-fetching on `refresh()`\n * or when `path` changes. */\nexport function useAdminResource<T = unknown>(getToken: () => Promise<string | null>, path: string): AdminResource<T> {\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [nonce, setNonce] = useState(0);\n\n useEffect(() => {\n let live = true;\n setLoading(true);\n setError(null);\n adminFetch<T>(getToken, path)\n .then((d) => live && setData(d))\n .catch((e: unknown) => live && setError(e instanceof Error ? e.message : String(e)))\n .finally(() => live && setLoading(false));\n return () => {\n live = false;\n };\n }, [getToken, path, nonce]);\n\n const refresh = useCallback(() => setNonce((n) => n + 1), []);\n return { data, loading, error, refresh };\n}\n","// Billing section: applications joined with live Stripe subscription state from\n// GET /api/admin/billing, rendered with odla-ui StatBand + DataTable. Degrades to\n// a note when billingReady:false, and surfaces the route's `truncated` flag.\nimport { DataTable, StatBand } from \"@odla-ai/ui/components\";\nimport type { DataTableColumn, StatCell } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport type { ChapterCopy } from \"../copy.js\";\n\ninterface BillingRow {\n id: string;\n name: string;\n email: string;\n applicationStatus: string;\n subscriptionStatus: string | null;\n cancelAtPeriodEnd: boolean;\n amountCents: number;\n interval: string;\n renewalAt: number | null;\n}\ninterface BillingData {\n billingReady: boolean;\n testMode?: boolean;\n truncated?: boolean;\n rows: BillingRow[];\n summary: { activeCount: number; annualizedCents: number; renewingSoonCount: number; pastDueCount: number; canceledCount: number; refundedCount: number } | null;\n}\n\nconst money = (cents: number): string => `$${(cents / 100).toLocaleString()}`;\nconst date = (t: number | null): string => (t ? new Date(t).toLocaleDateString([], { dateStyle: \"medium\" }) : \"—\");\n\nconst columns = (\n copy: ChapterCopy[\"admin\"][\"billing\"],\n): readonly DataTableColumn<BillingRow>[] => [\n { key: \"name\", header: copy.name, cell: (r) => r.name, sortAs: \"string\" },\n { key: \"email\", header: copy.email, cell: (r) => r.email },\n { key: \"applicationStatus\", header: copy.application, cell: (r) => r.applicationStatus },\n { key: \"subscriptionStatus\", header: copy.subscription, cell: (r) => (r.subscriptionStatus ? `${r.subscriptionStatus}${r.cancelAtPeriodEnd ? ` · ${copy.cancelling}` : \"\"}` : \"—\") },\n { key: \"amountCents\", header: copy.amount, cell: (r) => `${money(r.amountCents)}/${r.interval === \"month\" ? \"mo\" : \"yr\"}`, sortAs: \"number\", sortValue: (r) => r.amountCents },\n { key: \"renewalAt\", header: copy.renews, cell: (r) => date(r.renewalAt), sortAs: \"number\", sortValue: (r) => r.renewalAt ?? 0 },\n];\n\nfunction BillingBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.billing;\n const { data, loading, error } = useAdminResource<BillingData>(ctx.getToken, \"/api/admin/billing\");\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n if (!data.billingReady) return <AdminNote>{copy.notConfigured}</AdminNote>;\n\n const s = data.summary;\n const stats: StatCell[] = s\n ? [\n { value: s.activeCount, label: copy.active },\n { value: money(s.annualizedCents), label: copy.annualized },\n { value: s.renewingSoonCount, label: copy.renewingSoon },\n { value: s.pastDueCount, label: copy.pastDue },\n ]\n : [];\n\n return (\n <AdminPage>\n {s ? <StatBand stats={stats} /> : null}\n <Panel title={copy.subscriptions} actions={data.testMode ? <span className=\"badge\">{copy.testMode}</span> : undefined}>\n {data.truncated ? <p className=\"badge\">{copy.truncated}</p> : null}\n <DataTable rows={data.rows} columns={columns(copy)} rowKey={(r) => r.id} />\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link billingSection}. */\nexport interface BillingSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Billing admin section over `GET /api/admin/billing`. Renders a\n * \"not configured\" note when the group has no Stripe key vaulted. */\nexport function billingSection(options: BillingSectionOptions = {}): AdminSection {\n const { id = \"billing\", label = \"Billing\" } = options;\n return { id, label, render: (ctx) => <BillingBody ctx={ctx} /> };\n}\n","// Operational overview powered by the MetricWidget and StepPipeline primitives.\nimport { MetricWidget, StepPipeline } from \"@odla-ai/ui/components\";\nimport type { MetricData, PipelineStep } from \"@odla-ai/ui/components\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport { formatChapterCopy } from \"../copy.js\";\n\ninterface DashboardData {\n applications: { total: number; last7: number; last30: number };\n applicationsSeries: MetricData;\n pipeline: Record<string, number>;\n pipelineDelta: Record<string, number>;\n calls: { upcoming: number; needsAttention: number };\n agenda: Array<{\n id: string;\n startAt: number;\n name: string;\n email: string | null;\n drift: string;\n meetUrl: string | null;\n htmlLink?: string | null;\n }>;\n timezone: string;\n revenue: {\n billingReady: boolean;\n activeCount?: number;\n annualRunRateCents?: number;\n testMode?: boolean;\n };\n revenueSeries: MetricData | null;\n membersSeries: MetricData | null;\n}\n\nconst number = (value: number): string => Math.round(value).toLocaleString();\nconst money = (cents: number): string => `$${Math.round(cents / 100).toLocaleString()}`;\nconst when = (time: number): string =>\n new Date(time).toLocaleString([], { dateStyle: \"medium\", timeStyle: \"short\" });\n\nfunction DashboardBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.dashboard;\n const { data, loading, error } = useAdminResource<DashboardData>(\n ctx.getToken,\n \"/api/admin/dashboard\",\n );\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const pipelineSteps: PipelineStep[] = Object.entries(data.pipeline)\n .filter(([stage]) => ![\"declined\", \"refunded\"].includes(stage))\n .map(([stage, count]) => ({\n icon: <span style={{ fontSize: 22, fontWeight: 700 }}>{count}</span>,\n title: stage.replaceAll(\"_\", \" \"),\n description: data.pipelineDelta[stage]\n ? formatChapterCopy(copy.thisWeek, { count: data.pipelineDelta[stage] })\n : copy.noChange,\n }));\n const exceptions = [\"declined\", \"refunded\"]\n .filter((stage) => stage in data.pipeline)\n .map((stage) => `${stage} ${data.pipeline[stage]}`)\n .join(\" · \");\n\n return (\n <AdminPage>\n <Panel\n title={\n <>\n {copy.upcomingCalls}{\" \"}\n <span className=\"muted\" style={{ fontWeight: 400 }}>· {data.timezone}</span>\n </>\n }\n actions={\n data.calls.needsAttention\n ? <span className=\"badge\">{formatChapterCopy(copy.callsNeedAttention, { count: data.calls.needsAttention })}</span>\n : undefined\n }\n >\n {data.agenda.length === 0 ? (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.noUpcomingCalls}</p>\n ) : (\n <ul style={{ listStyle: \"none\", margin: 0, padding: 0, display: \"grid\", gap: 10 }}>\n {data.agenda.map((meeting) => (\n <li key={meeting.id} style={{ display: \"flex\", alignItems: \"center\", gap: 12, flexWrap: \"wrap\" }}>\n <strong style={{ minWidth: 170 }}>{when(meeting.startAt)}</strong>\n <span style={{ flex: 1 }}>{meeting.name}{meeting.email ? ` · ${meeting.email}` : \"\"}</span>\n {meeting.drift && meeting.drift !== \"none\" ? <span className=\"badge\">{copy.drift}</span> : null}\n {meeting.htmlLink ? <a href={meeting.htmlLink} target=\"_blank\" rel=\"noreferrer\">{copy.open}</a> : null}\n {meeting.meetUrl ? <a href={meeting.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.meet}</a> : null}\n </li>\n ))}\n </ul>\n )}\n </Panel>\n\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fit, minmax(280px, 1fr))\", gap: 18 }}>\n <MetricWidget label={copy.applications} data={data.applicationsSeries} format={number} />\n {data.membersSeries ? (\n <MetricWidget label={copy.newMembers} data={data.membersSeries} format={number} />\n ) : (\n <Panel title={copy.newMembers}><p className=\"muted\">{copy.newMembersUnavailable}</p></Panel>\n )}\n </div>\n\n {data.revenueSeries && data.revenue.billingReady ? (\n <div>\n <MetricWidget\n label={copy.revenueAdded}\n data={data.revenueSeries}\n format={money}\n size=\"large\"\n />\n <p className=\"muted\">\n {copy.activeMemberships}: {data.revenue.activeCount ?? 0} · {copy.annualRunRate}:{\" \"}\n {money(data.revenue.annualRunRateCents ?? 0)}\n {data.revenue.testMode ? ` · ${copy.testMode}` : \"\"}\n </p>\n </div>\n ) : (\n <Panel title={copy.revenue}><p className=\"muted\">{copy.revenueUnavailable}</p></Panel>\n )}\n\n <Panel title={copy.pipeline}>\n <StepPipeline ariaLabel={copy.pipelineLabel} steps={pipelineSteps} />\n {exceptions ? <p className=\"muted\" style={{ margin: 0 }}>{exceptions}</p> : null}\n </Panel>\n </AdminPage>\n );\n}\n\n/** Labels and ids for a composed dashboard workspace entry. */\nexport interface DashboardSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the operational dashboard workspace over `/api/admin/dashboard`. */\nexport function dashboardSection(options: DashboardSectionOptions = {}): AdminSection {\n const { id = \"dashboard\", label = \"Dashboard\" } = options;\n return { id, label, render: (ctx) => <DashboardBody ctx={ctx} /> };\n}\n","// Email section: the owner-editable email config (templates + addresses) from\n// GET/PUT /api/admin/group/email, the send audit from GET /api/admin/email/log,\n// and a POST /api/admin/email/test button. Built from odla-ui form primitives.\nimport { useState } from \"preact/hooks\";\nimport { Button, Checkbox, DataTable, Field, Input, Textarea } from \"@odla-ai/ui/components\";\nimport type { DataTableColumn } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\nimport { formatChapterCopy, type ChapterCopy } from \"../copy.js\";\n\ninterface Template { subject: string; text: string; enabled: boolean }\ninterface EmailConfig {\n emailTemplates: Record<string, Template>;\n replyTo: string;\n notificationEmail: string;\n debugEmail: string;\n commitmentText: string;\n normsText: string;\n transport: string;\n fromEmail: string | null;\n envName: string;\n}\ninterface LogRow { id: string; template: string; to: string; subject: string; transport: string; redirected: boolean; error: string | null; sentAt: number }\n\nconst logColumns = (\n copy: ChapterCopy[\"admin\"][\"email\"],\n): readonly DataTableColumn<LogRow>[] => [\n { key: \"sentAt\", header: copy.sentColumn, cell: (r) => new Date(r.sentAt).toLocaleString(), sortAs: \"number\", sortValue: (r) => r.sentAt },\n { key: \"template\", header: copy.templateColumn, cell: (r) => r.template },\n { key: \"to\", header: copy.toColumn, cell: (r) => r.to },\n { key: \"status\", header: copy.statusColumn, cell: (r) => (r.error ? <span className=\"badge\">{copy.failed}</span> : r.redirected ? <span className=\"badge\">{copy.redirected}</span> : copy.delivered) },\n];\n\nfunction EmailBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.email;\n const cfg = useAdminResource<EmailConfig>(ctx.getToken, \"/api/admin/group/email\");\n const log = useAdminResource<{ sends: LogRow[] }>(ctx.getToken, \"/api/admin/email/log\");\n const [draft, setDraft] = useState<EmailConfig | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n\n const data = draft ?? cfg.data;\n if (cfg.loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (cfg.error || !data) return <AdminNote>{copy.loadFailed}{cfg.error ? `: ${cfg.error}` : \"\"}.</AdminNote>;\n\n const edit = (patch: Partial<EmailConfig>) => setDraft({ ...data, ...patch });\n const editTemplate = (key: string, patch: Partial<Template>) =>\n edit({ emailTemplates: { ...data.emailTemplates, [key]: { ...data.emailTemplates[key], ...patch } as Template } });\n\n const run = async (key: string, fn: () => Promise<void>) => {\n setBusy(key);\n setNote(null);\n try {\n await fn();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const save = () =>\n run(\"save\", async () => {\n await adminFetch(ctx.getToken, \"/api/admin/group/email\", { method: \"PUT\", body: JSON.stringify(data) });\n setDraft(null);\n cfg.refresh();\n setNote(copy.saved);\n });\n const test = (template: string) =>\n run(`test:${template}`, async () => {\n const r = await adminFetch<{ ok: boolean; to: string; redirected: boolean }>(ctx.getToken, \"/api/admin/email/test\", { method: \"POST\", body: JSON.stringify({ template }) });\n setNote(r.ok\n ? formatChapterCopy(copy.sent, {\n template,\n address: r.to,\n redirected: r.redirected ? ` (${copy.redirected})` : \"\",\n })\n : copy.testFailed);\n log.refresh();\n });\n\n return (\n <AdminPage>\n <Panel\n title={copy.delivery}\n actions={<span className=\"muted\">{data.envName} · {data.transport}{data.fromEmail ? ` · ${data.fromEmail}` : \"\"}</span>}\n >\n <Field label={copy.notificationAddress}><Input value={data.notificationEmail} onInput={(e) => edit({ notificationEmail: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.replyTo}><Input value={data.replyTo} onInput={(e) => edit({ replyTo: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.debugInbox} hint={copy.debugInboxHint}><Input value={data.debugEmail} onInput={(e) => edit({ debugEmail: (e.target as HTMLInputElement).value })} /></Field>\n </Panel>\n\n {Object.entries(data.emailTemplates).map(([key, t]) => (\n <Panel key={key} title={key} actions={<Button variant=\"secondary\" mini disabled={busy === `test:${key}`} onClick={() => void test(key)}>{copy.sendTest}</Button>}>\n <Checkbox label={copy.enabled} checked={t.enabled} onChange={(e) => editTemplate(key, { enabled: (e.target as HTMLInputElement).checked })} />\n <Field label={copy.subject}><Input value={t.subject} onInput={(e) => editTemplate(key, { subject: (e.target as HTMLInputElement).value })} /></Field>\n <Field label={copy.body}><Textarea prose rows={5} value={t.text} onInput={(e) => editTemplate(key, { text: (e.target as HTMLTextAreaElement).value })} /></Field>\n </Panel>\n ))}\n\n <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n <Button disabled={!draft || busy === \"save\"} onClick={() => void save()}>{copy.save}</Button>\n {note ? <span className=\"muted\">{note}</span> : null}\n </div>\n\n <Panel title={copy.sendLog}>\n <DataTable rows={log.data?.sends ?? []} columns={logColumns(copy)} rowKey={(r) => r.id} />\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link emailSection}. */\nexport interface EmailSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Email admin section: template + address editor over\n * `GET/PUT /api/admin/group/email`, the send log, and per-template test sends. */\nexport function emailSection(options: EmailSectionOptions = {}): AdminSection {\n const { id = \"email\", label = \"Email\" } = options;\n return { id, label, render: (ctx) => <EmailBody ctx={ctx} /> };\n}\n","import { BillingCard, CrmWorkspace } from \"@odla-ai/crm/ui\";\nimport type {\n CrmLifecycleAdapter,\n CrmWorkspaceMasterContext,\n CrmWorkspaceRecordContext,\n RecordPanelTab,\n} from \"@odla-ai/crm/ui\";\nimport type { Crm, CrmClient, CrmRecord } from \"@odla-ai/crm\";\nimport type { ComponentChildren } from \"preact\";\nimport type { AdminSectionContext } from \"./chrome.js\";\nimport { adminFetch } from \"./admin-api.js\";\nimport { RecordActions } from \"./admin-record-actions.js\";\nimport { NetworkShareActions } from \"./admin-network.js\";\nimport { RecordActivityPanel } from \"./admin-record-activity.js\";\nimport { RecordCommsHistory, RecordCommsPanel } from \"./admin-record-comms.js\";\nimport { RecordSchedulingPanel } from \"./admin-record-scheduling.js\";\nimport { AdminPage } from \"./admin-layout.js\";\nimport { DEFAULT_CHAPTER_COPY, type ChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\n/** Application-authoritative stage transitions used by Chapter collections. */\nexport function applicationLifecycleAdapter(\n ctx: Pick<AdminSectionContext, \"getToken\">,\n copy: ChapterCopy[\"admin\"][\"records\"] = DEFAULT_CHAPTER_COPY.admin.records,\n): CrmLifecycleAdapter {\n return {\n transitionStage: async ({ record, to }) => {\n const applicationId =\n typeof record.fields?.applicationId === \"string\"\n ? record.fields.applicationId\n : null;\n if (!applicationId) {\n throw new Error(copy.workflowMissing);\n }\n const path = `/api/admin/applications/${encodeURIComponent(applicationId)}`;\n if (to === \"approved\") {\n await adminFetch(ctx.getToken, `${path}/approve`, { method: \"POST\" });\n } else if (to === \"refunded\") {\n await adminFetch(ctx.getToken, `${path}/refund`, { method: \"POST\" });\n } else {\n await adminFetch(ctx.getToken, path, {\n method: \"PATCH\",\n body: JSON.stringify({ status: to }),\n });\n }\n },\n };\n}\n\nexport interface PeopleBodyProps {\n crm: Crm;\n client: CrmClient;\n type: string;\n ctx: AdminSectionContext;\n roles: readonly string[];\n lifecycle: boolean;\n networkSharing: boolean;\n collapseClosedDetail: boolean;\n lifecycleAdapter?:\n | CrmLifecycleAdapter\n | ((ctx: AdminSectionContext) => CrmLifecycleAdapter);\n requireLifecycleAdapter?: boolean;\n renderSummary?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderMaster?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderDetailHeader?: (\n context: CrmWorkspaceRecordContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderEmptyDetail?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n hrefForRecord?: (record: CrmRecord, ctx: AdminSectionContext) => string;\n extendRecordTabs?: (\n tabs: readonly RecordPanelTab[],\n context: CrmWorkspaceRecordContext,\n ) => readonly RecordPanelTab[];\n}\n\nexport function PeopleBody(props: PeopleBodyProps) {\n const copy = useChapterCopy().admin.records;\n const {\n crm, client, type, ctx, roles, lifecycle, networkSharing,\n collapseClosedDetail, lifecycleAdapter, requireLifecycleAdapter, renderSummary, renderMaster,\n renderDetailHeader, renderEmptyDetail, hrefForRecord, extendRecordTabs,\n } = props;\n const def = crm.type(type);\n const recordId = ctx.route?.recordId ?? null;\n const builtInLifecycle = lifecycle\n ? applicationLifecycleAdapter(ctx, copy)\n : undefined;\n const resolvedLifecycle =\n typeof lifecycleAdapter === \"function\"\n ? lifecycleAdapter(ctx)\n : lifecycleAdapter ?? builtInLifecycle;\n // Both imports are the same runtime class, but their declarations contain a\n // private field that makes TypeScript treat the public UI copy nominally.\n const workspaceClient = client as unknown as Parameters<typeof CrmWorkspace>[0][\"client\"];\n return (\n <AdminPage>\n <CrmWorkspace\n crm={crm}\n client={workspaceClient}\n type={type}\n recordId={recordId}\n detailTab={ctx.route?.detailTab}\n defaultDetailTab=\"profile\"\n onRecordIdChange={(id) => ctx.navigate({ recordId: id, detailTab: null })}\n hrefForRecord={(record) =>\n hrefForRecord?.(record, ctx) ??\n ctx.href({ recordId: record.id, detailTab: \"profile\" })}\n hrefForList={ctx.href({ recordId: null, detailTab: null })}\n hrefForDetailTab={(detailTab) => ctx.href({ detailTab })}\n collapseClosedDetail={collapseClosedDetail}\n lifecycle={resolvedLifecycle}\n requireLifecycleAdapter={requireLifecycleAdapter ?? lifecycle}\n renderSummary={renderSummary\n ? (context) => renderSummary(context, ctx)\n : undefined}\n renderMaster={renderMaster\n ? (context) => renderMaster(context, ctx)\n : undefined}\n renderDetailHeader={renderDetailHeader\n ? (context) => renderDetailHeader(context, ctx)\n : undefined}\n renderEmptyDetail={renderEmptyDetail\n ? (context) => renderEmptyDetail(context, ctx)\n : undefined}\n extendRecordTabs={(base, context): readonly RecordPanelTab[] => {\n const record = context.detail.record;\n const applicationId =\n typeof record.fields?.applicationId === \"string\"\n ? String(record.fields.applicationId)\n : null;\n const byId = new Map(base.map((tab) => [tab.id, tab]));\n const tabs: RecordPanelTab[] = [];\n const add = (id: string) => {\n const tab = byId.get(id);\n if (tab) tabs.push(tab);\n };\n add(\"stage\");\n add(\"profile\");\n if (def.facets?.email !== false) {\n tabs.push({\n id: \"comms\",\n label: copy.comms,\n panel: <RecordCommsPanel client={client} recordId={record.id} getToken={ctx.getToken} />,\n });\n tabs.push({\n id: \"history\",\n label: copy.commsHistory,\n panel: <RecordCommsHistory client={client} recordId={record.id} />,\n });\n }\n if (lifecycle) {\n tabs.push({\n id: \"scheduling\",\n label: copy.scheduling,\n panel: <RecordSchedulingPanel getToken={ctx.getToken} applicationId={applicationId} />,\n });\n tabs.push({ id: \"billing\", label: copy.billing, panel: <BillingCard record={record} /> });\n } else {\n add(\"billing\");\n }\n tabs.push({\n id: \"notes\",\n label: copy.notes,\n panel: <RecordActivityPanel client={client} recordId={record.id} />,\n });\n add(\"connections\");\n if (lifecycle) {\n tabs.push({\n id: \"access\",\n label: copy.access,\n panel: (\n <RecordActions\n getToken={ctx.getToken}\n record={record}\n roles={roles}\n onChanged={() => {\n context.refreshRecord();\n context.refreshList();\n }}\n />\n ),\n visible: () => ctx.currentUser?.superAdmin === true,\n });\n }\n if (networkSharing) {\n tabs.push({\n id: \"sharing\",\n label: copy.sharing,\n panel: <NetworkShareActions recordId={record.id} recordType={record.type} getToken={ctx.getToken} />,\n });\n }\n return extendRecordTabs?.(tabs, context) ?? tabs;\n }}\n />\n </AdminPage>\n );\n}\n","// The lifecycle action panel shown beside an open person record: role change\n// (POST /api/admin/people/role), approve (POST /api/admin/applications/:id/\n// approve) and refund (POST .../refund). Each control appears only when the\n// record carries what it needs — a linked Clerk account for role, an\n// applicationId for approve/refund. Built from odla-ui Field/Select/Button.\nimport { useEffect, useState } from \"preact/hooks\";\nimport { Button, Field, Select } from \"@odla-ai/ui/components\";\nimport { adminFetch } from \"./admin-api.js\";\nimport type { CrmRecord } from \"@odla-ai/crm\";\nimport { formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Access {\n role: string;\n superAdmin: boolean;\n}\n\n/** Props for {@link RecordActions}. */\nexport interface RecordActionsProps {\n getToken: () => Promise<string | null>;\n record: CrmRecord;\n /** The role ladder offered by the role selector. Default provisional→admin. */\n roles: readonly string[];\n /** Called after any action mutates state, so the caller can refresh. */\n onChanged: () => void;\n}\n\n/** The role/approve/refund controls for one person record. Renders only the\n * actions the record supports. */\nexport function RecordActions({ getToken, record, roles, onChanged }: RecordActionsProps) {\n const copy = useChapterCopy().admin.records;\n const userId = typeof record.clerkUserId === \"string\" ? record.clerkUserId : null;\n const applicationId = typeof record.fields?.applicationId === \"string\" ? (record.fields.applicationId as string) : null;\n const [access, setAccess] = useState<Access | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n\n useEffect(() => {\n if (!userId) {\n setAccess(null);\n return;\n }\n let live = true;\n adminFetch<Access>(getToken, `/api/admin/people/access?userId=${encodeURIComponent(userId)}`)\n .then((a) => live && setAccess(a))\n .catch(() => live && setAccess(null));\n return () => {\n live = false;\n };\n }, [getToken, userId]);\n\n const act = async (key: string, run: () => Promise<unknown>, ok: string) => {\n setBusy(key);\n setNote(null);\n try {\n await run();\n setNote(ok);\n onChanged();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const setRole = (role: string) =>\n act(\"role\", () => adminFetch(getToken, \"/api/admin/people/role\", { method: \"POST\", body: JSON.stringify({ userId, role }) }), formatChapterCopy(copy.roleSet, { role }));\n const approve = () =>\n act(\"approve\", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/approve`, { method: \"POST\" }), copy.approved);\n const refund = () =>\n act(\"refund\", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/refund`, { method: \"POST\" }), copy.refunded);\n\n if (!userId && !applicationId) return null;\n return (\n <section className=\"panel\" style={{ display: \"flex\", flexDirection: \"column\", gap: 14, marginTop: 16 }}>\n <h3 style={{ margin: 0, fontSize: 16 }}>{copy.lifecycle}</h3>\n {userId ? (\n <Field label={copy.role} hint={access?.superAdmin ? copy.superAdminHint : undefined}>\n <Select\n value={access?.role ?? \"\"}\n disabled={busy === \"role\" || access?.superAdmin}\n options={roles.map((r) => ({ value: r, label: r }))}\n onChange={(e) => void setRole((e.target as HTMLSelectElement).value)}\n />\n </Field>\n ) : (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.noAccount}</p>\n )}\n {applicationId ? (\n <div style={{ display: \"flex\", gap: 8 }}>\n <Button variant=\"secondary\" mini disabled={busy === \"approve\"} onClick={() => void approve()}>{copy.approve}</Button>\n <Button variant=\"danger\" mini disabled={busy === \"refund\"} onClick={() => void refund()}>{copy.refund}</Button>\n </div>\n ) : null}\n {note ? <p className=\"muted\" style={{ margin: 0 }}>{note}</p> : null}\n </section>\n );\n}\n","// Leader-side \"share to follower\" action. It is intentionally record-local:\n// the operator opens the person/business/deal they already reviewed, chooses a\n// configured follower, and sees an explicit delivery result.\nimport { useState } from \"preact/hooks\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { formatChapterCopy } from \"../copy.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Target {\n id: string;\n name: string;\n url: string;\n types: string[];\n}\n\ninterface TargetResponse {\n targets: Target[];\n}\n\ninterface PushResponse {\n ok: boolean;\n results: Array<{ id: string; name: string; ok: boolean; error?: string }>;\n}\n\n/** Props for {@link NetworkShareActions}. */\nexport interface NetworkShareActionsProps {\n recordId: string;\n recordType: string;\n getToken: () => Promise<string | null>;\n}\n\n/** Render follower delivery buttons when this chapter configured network\n * targets. Targets with an explicit type allowlist hide incompatible records. */\nexport function NetworkShareActions(props: NetworkShareActionsProps) {\n const copy = useChapterCopy().admin.network;\n const { recordId, recordType, getToken } = props;\n const targets = useAdminResource<TargetResponse>(getToken, \"/api/admin/network/targets\");\n const [busy, setBusy] = useState<string | null>(null);\n const [message, setMessage] = useState<string | null>(null);\n const compatible = (targets.data?.targets ?? []).filter((target) => target.types.includes(recordType));\n\n if (targets.loading || targets.error || compatible.length === 0) return null;\n\n const push = async (target: Target) => {\n setBusy(target.id);\n setMessage(null);\n try {\n const result = await adminFetch<PushResponse>(getToken, \"/api/admin/network/push\", {\n method: \"POST\",\n body: JSON.stringify({ recordId, targetIds: [target.id] }),\n });\n const delivery = result.results[0];\n setMessage(delivery?.ok\n ? formatChapterCopy(copy.shared, { target: target.name })\n : delivery?.error ?? formatChapterCopy(copy.shareFailed, { target: target.name }));\n } catch (err) {\n setMessage(err instanceof Error ? err.message : copy.deliveryFailed);\n } finally {\n setBusy(null);\n }\n };\n\n return (\n <section className=\"panel\" style={{ marginTop: 14, display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 16 }}>{copy.title}</h3>\n <p className=\"muted\" style={{ margin: \"4px 0 0\", fontSize: 13 }}>\n {copy.allowlistDescription}\n </p>\n </div>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n {compatible.map((target) => (\n <button className=\"btn secondary mini\" disabled={busy !== null} onClick={() => void push(target)} key={target.id}>\n {busy === target.id\n ? copy.sharing\n : formatChapterCopy(copy.shareWith, { target: target.name })}\n </button>\n ))}\n </div>\n {message ? <p role=\"status\" style={{ margin: 0, fontSize: 13 }}>{message}</p> : null}\n </section>\n );\n}\n","import { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { ActivityFeed } from \"@odla-ai/crm/ui\";\nimport type { CrmActivity, CrmClient } from \"@odla-ai/crm\";\n\n/** Notes and follow-ups for one CRM record. */\nexport function RecordActivityPanel(props: {\n client: CrmClient;\n recordId: string;\n}) {\n const { client, recordId } = props;\n const [activities, setActivities] = useState<CrmActivity[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const load = useCallback(async () => {\n try {\n const result = await client.listActivities(recordId, { limit: 100 });\n setActivities(result.activities);\n setError(null);\n } catch (failure) {\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n }, [client, recordId]);\n useEffect(() => void load(), [load]);\n const run = async (action: () => Promise<unknown>) => {\n setBusy(true);\n try {\n await action();\n await load();\n } finally {\n setBusy(false);\n }\n };\n if (error) return <p role=\"alert\" className=\"muted\">{error}</p>;\n return (\n <ActivityFeed\n activities={activities}\n busy={busy}\n onAddNote={(body) => void run(() => client.addActivity(recordId, { kind: \"note\", body }))}\n onAddTask={(task) => void run(() => client.addActivity(recordId, { kind: \"task\", ...task }))}\n onToggleTask={(activity, done) =>\n void run(() => client.updateTask(activity.id, { status: done ? \"done\" : \"open\" }))}\n />\n );\n}\n","import { useCallback, useEffect, useState } from \"preact/hooks\";\nimport { Button, Field, Select } from \"@odla-ai/ui/components\";\nimport type { CrmClient } from \"@odla-ai/crm\";\nimport { useAdminResource } from \"./admin-api.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface EmailConfig {\n emailTemplates: Record<string, { enabled: boolean; subject: string }>;\n}\n\n/** Template send action for one record. */\nexport function RecordCommsPanel(props: {\n client: CrmClient;\n recordId: string;\n getToken: () => Promise<string | null>;\n}) {\n const copy = useChapterCopy().admin.records;\n const { client, recordId, getToken } = props;\n const config = useAdminResource<EmailConfig>(getToken, \"/api/admin/group/email\");\n const templates = Object.entries(config.data?.emailTemplates ?? {}).filter(([, value]) => value.enabled);\n const [template, setTemplate] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n const send = async () => {\n if (!template) return;\n setBusy(true);\n setNote(null);\n try {\n const result = await client.sendEmail(recordId, { templateId: template });\n setNote(result.sent ? copy.messageSent : result.reason ?? copy.messageNotSent);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setBusy(false);\n }\n };\n if (config.loading) return <p className=\"muted\">{copy.loadingTemplates}</p>;\n if (config.error) return <p role=\"alert\" className=\"muted\">{config.error}</p>;\n return (\n <div style={{ display: \"grid\", gap: 14, maxWidth: 560 }}>\n <Field label={copy.template}>\n <Select\n value={template}\n onChange={(event) => setTemplate(event.currentTarget.value)}\n options={[\n { value: \"\", label: copy.chooseTemplate },\n ...templates.map(([id, value]) => ({ value: id, label: value.subject || id })),\n ]}\n />\n </Field>\n <div><Button disabled={!template || busy} onClick={() => void send()}>{busy ? copy.sending : copy.send}</Button></div>\n {note ? <p role=\"status\" className=\"muted\">{note}</p> : null}\n </div>\n );\n}\n\n/** Audited send history for one record. */\nexport function RecordCommsHistory(props: { client: CrmClient; recordId: string }) {\n const copy = useChapterCopy().admin.records;\n const { client, recordId } = props;\n const [rows, setRows] = useState<Record<string, unknown>[]>([]);\n const [error, setError] = useState<string | null>(null);\n const load = useCallback(async () => {\n try {\n const result = await client.emailLog({ recordId, limit: 100 });\n setRows(result.log);\n setError(null);\n } catch (failure) {\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n }, [client, recordId]);\n useEffect(() => void load(), [load]);\n if (error) return <p role=\"alert\" className=\"muted\">{error}</p>;\n if (rows.length === 0) return <p className=\"muted\">{copy.noMessages}</p>;\n return (\n <ul style={{ listStyle: \"none\", padding: 0, margin: 0, display: \"grid\", gap: 10 }}>\n {rows.map((row, index) => (\n <li className=\"panel\" key={String(row[\"id\"] ?? index)}>\n <strong>{String(row[\"templateId\"] ?? row[\"template\"] ?? copy.message)}</strong>\n <div className=\"muted\">\n {row[\"to\"] ? String(row[\"to\"]) : \"\"}\n {row[\"sentAt\"] ? ` · ${new Date(Number(row[\"sentAt\"])).toLocaleString()}` : \"\"}\n </div>\n </li>\n ))}\n </ul>\n );\n}\n","import { useState } from \"preact/hooks\";\nimport { Button } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface Meeting {\n id: string;\n applicationId: string;\n startAt: number;\n status: string;\n meetUrl?: string | null;\n htmlLink?: string | null;\n}\n\n/** Meetings and reschedule/cancel actions for one application-backed record. */\nexport function RecordSchedulingPanel(props: {\n getToken: () => Promise<string | null>;\n applicationId: string | null;\n}) {\n const copy = useChapterCopy().admin.records;\n const { getToken, applicationId } = props;\n const resource = useAdminResource<{ meetings: Meeting[]; timezone: string }>(\n getToken,\n \"/api/admin/meetings?all=1\",\n );\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n const meetings = (resource.data?.meetings ?? []).filter((meeting) => meeting.applicationId === applicationId);\n const run = async (meeting: Meeting, action: \"cancel\" | \"reschedule\") => {\n let body: string | undefined;\n if (action === \"reschedule\") {\n const input = globalThis.prompt?.(copy.newStartPrompt);\n if (!input) return;\n const startAt = Date.parse(input);\n if (!Number.isFinite(startAt)) {\n setNote(copy.parseFailed);\n return;\n }\n body = JSON.stringify({ startAt });\n } else if (!globalThis.confirm?.(copy.cancelConfirm)) {\n return;\n }\n setBusy(meeting.id);\n try {\n await adminFetch(getToken, `/api/admin/meetings/${meeting.id}/${action}`, { method: \"POST\", body });\n resource.refresh();\n setNote(action === \"cancel\" ? copy.callCancelled : copy.callRescheduled);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setBusy(null);\n }\n };\n if (!applicationId) return <p className=\"muted\">{copy.noApplication}</p>;\n if (resource.loading) return <p className=\"muted\">{copy.loadingMeetings}</p>;\n if (resource.error) return <p role=\"alert\" className=\"muted\">{resource.error}</p>;\n if (meetings.length === 0) return <p className=\"muted\">{copy.noMeetings}</p>;\n return (\n <div style={{ display: \"grid\", gap: 12 }}>\n {meetings.map((meeting) => (\n <section className=\"panel\" key={meeting.id}>\n <strong>{new Date(meeting.startAt).toLocaleString()}</strong>\n <p className=\"muted\">{meeting.status} · {resource.data?.timezone}</p>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\" }}>\n {meeting.meetUrl ? <a href={meeting.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.joinMeeting}</a> : null}\n {meeting.htmlLink ? <a href={meeting.htmlLink} target=\"_blank\" rel=\"noreferrer\">{copy.openCalendar}</a> : null}\n {meeting.status === \"scheduled\" ? (\n <>\n <Button variant=\"secondary\" mini disabled={busy === meeting.id} onClick={() => void run(meeting, \"reschedule\")}>{copy.reschedule}</Button>\n <Button variant=\"danger\" mini disabled={busy === meeting.id} onClick={() => void run(meeting, \"cancel\")}>{copy.cancel}</Button>\n </>\n ) : null}\n </div>\n </section>\n ))}\n {note ? <p role=\"status\" className=\"muted\">{note}</p> : null}\n </div>\n );\n}\n","// Config-driven CRM workspace with record-local operational tabs.\nimport type {\n CrmLifecycleAdapter,\n CrmWorkspaceMasterContext,\n CrmWorkspaceRecordContext,\n RecordPanelTab,\n} from \"@odla-ai/crm/ui\";\nimport type { Crm, CrmRecord } from \"@odla-ai/crm\";\nimport type { ComponentChildren } from \"preact\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { PeopleBody } from \"./admin-people-workspace.js\";\n\nexport { applicationLifecycleAdapter } from \"./admin-people-workspace.js\";\n\nconst DEFAULT_ROLES = [\"provisional\", \"member\", \"admin\"] as const;\n\n/** Configuration for the person-collection compatibility preset. */\nexport interface PeopleSectionOptions {\n crm: Crm;\n id?: string;\n label?: string;\n type?: string;\n}\n\n/** Configuration for one CRM collection and its application-specific tabs. */\nexport interface CollectionSectionOptions {\n crm: Crm;\n type: string;\n id?: string;\n label?: string;\n lifecycle?: boolean;\n roles?: readonly string[];\n networkSharing?: boolean;\n /** Give the collection list the full workspace width until a record opens. */\n collapseClosedDetail?: boolean;\n lifecycleAdapter?: (\n | CrmLifecycleAdapter\n | ((ctx: AdminSectionContext) => CrmLifecycleAdapter)\n );\n requireLifecycleAdapter?: boolean;\n renderSummary?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderMaster?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderDetailHeader?: (\n context: CrmWorkspaceRecordContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n renderEmptyDetail?: (\n context: CrmWorkspaceMasterContext,\n ctx: AdminSectionContext,\n ) => ComponentChildren;\n hrefForRecord?: (record: CrmRecord, ctx: AdminSectionContext) => string;\n extendRecordTabs?: (\n tabs: readonly RecordPanelTab[],\n context: CrmWorkspaceRecordContext,\n ) => readonly RecordPanelTab[];\n}\n\n/** Build one CRM collection as an admin workspace. */\nexport function collectionSection(options: CollectionSectionOptions): AdminSection {\n const { crm, type } = options;\n let fallbackLabel = type;\n try {\n fallbackLabel = crm.type(type).labelPlural ?? crm.type(type).label ?? type;\n } catch {\n // The route will surface an unknown configured type.\n }\n const {\n id = type,\n label = fallbackLabel,\n lifecycle = type === \"person\",\n roles = DEFAULT_ROLES,\n networkSharing = false,\n collapseClosedDetail = true,\n lifecycleAdapter,\n requireLifecycleAdapter,\n renderSummary,\n renderMaster,\n renderDetailHeader,\n renderEmptyDetail,\n hrefForRecord,\n extendRecordTabs,\n } = options;\n return {\n id,\n label,\n render: (ctx) => (\n <PeopleBody\n crm={crm}\n client={ctx.client}\n type={type}\n ctx={ctx}\n roles={roles}\n lifecycle={lifecycle}\n networkSharing={networkSharing}\n collapseClosedDetail={collapseClosedDetail}\n lifecycleAdapter={lifecycleAdapter}\n requireLifecycleAdapter={requireLifecycleAdapter}\n renderSummary={renderSummary}\n renderMaster={renderMaster}\n renderDetailHeader={renderDetailHeader}\n renderEmptyDetail={renderEmptyDetail}\n hrefForRecord={hrefForRecord}\n extendRecordTabs={extendRecordTabs}\n />\n ),\n };\n}\n\n/** Person-collection preset. */\nexport function peopleSection(options: PeopleSectionOptions & {\n roles?: readonly string[];\n networkSharing?: boolean;\n collapseClosedDetail?: boolean;\n lifecycleAdapter?: CollectionSectionOptions[\"lifecycleAdapter\"];\n requireLifecycleAdapter?: boolean;\n renderSummary?: CollectionSectionOptions[\"renderSummary\"];\n renderMaster?: CollectionSectionOptions[\"renderMaster\"];\n renderDetailHeader?: CollectionSectionOptions[\"renderDetailHeader\"];\n renderEmptyDetail?: CollectionSectionOptions[\"renderEmptyDetail\"];\n hrefForRecord?: CollectionSectionOptions[\"hrefForRecord\"];\n extendRecordTabs?: CollectionSectionOptions[\"extendRecordTabs\"];\n}): AdminSection {\n const {\n crm,\n id = \"people\",\n label = \"People\",\n type = \"person\",\n roles,\n networkSharing,\n collapseClosedDetail,\n lifecycleAdapter,\n requireLifecycleAdapter,\n renderSummary,\n renderMaster,\n renderDetailHeader,\n renderEmptyDetail,\n hrefForRecord,\n extendRecordTabs,\n } = options;\n return collectionSection({\n crm,\n type,\n id,\n label,\n ...(roles ? { roles } : {}),\n ...(networkSharing != null ? { networkSharing } : {}),\n ...(collapseClosedDetail != null ? { collapseClosedDetail } : {}),\n ...(lifecycleAdapter ? { lifecycleAdapter } : {}),\n ...(requireLifecycleAdapter != null ? { requireLifecycleAdapter } : {}),\n ...(renderSummary ? { renderSummary } : {}),\n ...(renderMaster ? { renderMaster } : {}),\n ...(renderDetailHeader ? { renderDetailHeader } : {}),\n ...(renderEmptyDetail ? { renderEmptyDetail } : {}),\n ...(hrefForRecord ? { hrefForRecord } : {}),\n ...(extendRecordTabs ? { extendRecordTabs } : {}),\n });\n}\n","import { ThemeScope } from \"@odla-ai/ui/components\";\nimport type { ComponentChildren, Ref } from \"preact\";\nimport type { Chapter } from \"../types.js\";\nimport { adminRouteFromUrl, adminRouteHref } from \"./admin-route.js\";\nimport type { AdminWorkspace } from \"./chrome.js\";\nimport { BrandStyle } from \"./brand-style.js\";\nimport { ChapterCopyProvider } from \"./copy-context.js\";\n\nexport function AdminTheme(props: {\n chapter?: Chapter;\n children: ComponentChildren;\n /** The theme scope element. Vendor widgets that read `--ui-*` off a live\n * element (Clerk's appearance bridge) must read THIS one, not the document\n * root, or an admin brand silently falls back to the host page's palette. */\n scopeRef?: Ref<HTMLDivElement>;\n}) {\n const brand = props.chapter?.brand;\n return (\n <ChapterCopyProvider copy={props.chapter?.copy}>\n <ThemeScope\n ref={props.scopeRef}\n data-chapter-admin=\"\"\n theme={brand?.theme}\n accent={brand?.accent}\n colorScheme={brand?.colorScheme ?? \"light\"}\n >\n <BrandStyle brand={brand} selector=\"[data-chapter-admin]\" />\n {props.children}\n </ThemeScope>\n </ChapterCopyProvider>\n );\n}\n\nexport function signInRedirect(\n basePath: string,\n workspaces: readonly AdminWorkspace[],\n): string {\n if (typeof window === \"undefined\") return basePath;\n const current = new URL(window.location.href);\n const inbound = adminRouteFromUrl(\n current,\n basePath,\n workspaces.map((workspace) => workspace.id),\n );\n const workspace = workspaces.find((item) => item.id === inbound.workspaceId);\n const route = inbound.viewId || !workspace?.defaultViewId\n ? inbound\n : { ...inbound, viewId: workspace.defaultViewId };\n // Clerk owns the hash while signed out. Preserve requested admin state in\n // its return query, then let AdminShell canonicalize after authentication.\n return adminRouteHref(current, basePath, route, \"query\");\n}\n","// Bridging the admin theme's tokens into Clerk's appearance contract.\nimport type { RefObject } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport { clerkAppearanceFromTokens } from \"@odla-ai/auth-clerk\";\n\ntype ClerkAppearance = ReturnType<typeof clerkAppearanceFromTokens>;\n\n/**\n * Read the Clerk appearance from the admin theme scope rather than the document\n * root.\n *\n * `clerkAppearanceFromTokens()` defaults to `document.documentElement`, but the\n * brand tokens are written scoped to `[data-chapter-admin]` so an admin brand\n * cannot recolor the host page or vendor sign-in UI. Reading the root would\n * therefore theme the widget from whatever the HOST page happens to define —\n * on a page with no `--ui-*` at root, @odla-ai/ui's dark-mode defaults win and\n * the sign-in card renders dark while the console beneath it is light.\n *\n * The scope is an ancestor rendered in the same pass, so it can only be\n * measured after mount. Returns `undefined` until then; callers should hold the\n * widget back rather than mount it against the defaults, because a mounted\n * Clerk widget keeps its startup palette.\n */\nexport function useScopedClerkAppearance(\n scope: RefObject<HTMLElement | null>,\n): ClerkAppearance | undefined {\n const [appearance, setAppearance] = useState<ClerkAppearance>();\n useEffect(() => {\n setAppearance(clerkAppearanceFromTokens(scope.current ?? undefined));\n }, [scope]);\n return appearance;\n}\n","/** Normalized public auth configuration consumed by the Clerk gate. */\nexport interface ChapterAdminAuthConfig {\n publishableKey: string | null;\n}\n\n/** Normalized current-user data retained for workspace visibility decisions. */\nexport interface ChapterAdminUser extends Record<string, unknown> {\n authorized?: boolean;\n email?: string | null;\n}\n\n/** Inputs supplied to custom admin configuration and current-user loaders. */\nexport interface ChapterAdminAuthLoadContext {\n apiBase: string;\n getToken?: () => Promise<string | null>;\n}\n\n/** Existing-site adapter for auth endpoint names and response shapes. */\nexport interface ChapterAdminAuthAdapter {\n configPath?: string;\n currentUserPath?: string;\n loadConfig?: (\n context: ChapterAdminAuthLoadContext,\n ) => Promise<ChapterAdminAuthConfig>;\n loadCurrentUser?: (\n context: Required<ChapterAdminAuthLoadContext>,\n ) => Promise<ChapterAdminUser>;\n mapConfig?: (body: Record<string, unknown>) => ChapterAdminAuthConfig;\n mapCurrentUser?: (body: Record<string, unknown>) => ChapterAdminUser;\n isAuthorized?: (user: ChapterAdminUser) => boolean;\n}\n\nconst apiUrl = (apiBase: string, path: string): string =>\n `${apiBase.replace(/\\/+$/, \"\")}/${path.replace(/^\\/+/, \"\")}`;\n\nexport const DEFAULT_ADMIN_AUTH: ChapterAdminAuthAdapter = {};\n\n/** Load and normalize the public authentication configuration. */\nexport async function loadChapterAdminConfig(\n adapter: ChapterAdminAuthAdapter,\n apiBase: string,\n): Promise<ChapterAdminAuthConfig> {\n if (adapter.loadConfig) return adapter.loadConfig({ apiBase });\n const response = await fetch(apiUrl(apiBase, adapter.configPath ?? \"/api/config\"));\n const body = (await response.json()) as Record<string, unknown>;\n if (adapter.mapConfig) return adapter.mapConfig(body);\n return {\n publishableKey:\n typeof body.clerkPublishableKey === \"string\"\n ? body.clerkPublishableKey\n : null,\n };\n}\n\n/** Load and normalize the authenticated user used by admin workspaces. */\nexport async function loadChapterAdminUser(\n adapter: ChapterAdminAuthAdapter,\n apiBase: string,\n getToken: () => Promise<string | null>,\n): Promise<ChapterAdminUser> {\n if (adapter.loadCurrentUser) {\n return adapter.loadCurrentUser({ apiBase, getToken });\n }\n const token = await getToken();\n const response = await fetch(apiUrl(apiBase, adapter.currentUserPath ?? \"/api/me\"), {\n headers: token ? { authorization: `Bearer ${token}` } : {},\n });\n const body = (await response.json().catch(() => ({}))) as Record<string, unknown>;\n return adapter.mapCurrentUser?.(body) ?? body;\n}\n","// Compatibility entry for the workspace-based default console.\nimport type { Chapter } from \"../types\";\nimport type { AdminSection } from \"./chrome.js\";\nimport { defaultAdminWorkspaces } from \"./admin-workspaces.js\";\n\n/** Legacy default catalog. @deprecated Use defaultAdminWorkspaces. */\nexport function defaultAdminSections(chapter: Chapter): AdminSection[] {\n return defaultAdminWorkspaces(chapter);\n}\n\nexport { defaultAdminWorkspaces };\n","// Meetings section: the reconciled agenda from GET /api/admin/meetings, with the\n// reschedule and cancel actions wired to POST /api/admin/meetings/:id/{...}.\n// Built from odla-ui .panel + Button; drift against live Google state is flagged.\nimport { useState } from \"preact/hooks\";\nimport { Button } from \"@odla-ai/ui/components\";\nimport { adminFetch, useAdminResource } from \"./admin-api.js\";\nimport { AdminPage, AdminNote, Panel } from \"./admin-layout.js\";\nimport type { AdminSection, AdminSectionContext } from \"./chrome.js\";\nimport { useChapterCopy } from \"./copy-context.js\";\n\ninterface MeetingRow {\n id: string;\n startAt: number;\n endAt: number;\n status: string;\n drift: string;\n meetUrl: string | null;\n applicant: { name: string; email: string; status: string } | null;\n}\n\nconst when = (t: number): string => new Date(t).toLocaleString([], { dateStyle: \"medium\", timeStyle: \"short\" });\n\nfunction MeetingsBody({ ctx }: { ctx: AdminSectionContext }) {\n const copy = useChapterCopy().admin.meetings;\n const { data, loading, error, refresh } = useAdminResource<{ meetings: MeetingRow[]; timezone: string }>(ctx.getToken, \"/api/admin/meetings?all=1\");\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n if (loading) return <AdminNote>{copy.loading}</AdminNote>;\n if (error || !data) return <AdminNote>{copy.loadFailed}{error ? `: ${error}` : \"\"}.</AdminNote>;\n\n const run = async (id: string, fn: () => Promise<void>) => {\n setBusy(id);\n setNote(null);\n try {\n await fn();\n refresh();\n } catch (e) {\n setNote(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(null);\n }\n };\n const cancel = (id: string) => {\n if (!globalThis.confirm?.(copy.cancelConfirm)) return;\n void run(id, () => adminFetch(ctx.getToken, `/api/admin/meetings/${id}/cancel`, { method: \"POST\" }));\n };\n const reschedule = (id: string) => {\n const input = globalThis.prompt?.(copy.newStartPrompt);\n if (!input) return;\n const startAt = Date.parse(input);\n if (!Number.isFinite(startAt)) {\n setNote(copy.parseFailed);\n return;\n }\n void run(id, () => adminFetch(ctx.getToken, `/api/admin/meetings/${id}/reschedule`, { method: \"POST\", body: JSON.stringify({ startAt }) }));\n };\n\n return (\n <AdminPage>\n <Panel title={<>{copy.agenda} <span className=\"muted\" style={{ fontWeight: 400 }}>· {data.timezone}</span></>} actions={note ? <span className=\"muted\">{note}</span> : undefined}>\n {data.meetings.length === 0 ? (\n <p className=\"muted\" style={{ margin: 0 }}>{copy.empty}</p>\n ) : (\n <ul style={{ listStyle: \"none\", margin: 0, padding: 0, display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {data.meetings.map((m) => (\n <li key={m.id} style={{ display: \"flex\", alignItems: \"center\", gap: 12, flexWrap: \"wrap\", opacity: m.status === \"cancelled\" ? 0.55 : 1 }}>\n <strong style={{ minWidth: 170 }}>{when(m.startAt)}</strong>\n <span style={{ flex: 1 }}>{m.applicant ? `${m.applicant.name} · ${m.applicant.email}` : copy.unknown}</span>\n <span className=\"badge\">{m.status}</span>\n {m.drift && m.drift !== \"none\" ? <span className=\"badge\">{copy.drift}: {m.drift}</span> : null}\n {m.meetUrl ? <a href={m.meetUrl} target=\"_blank\" rel=\"noreferrer\">{copy.meet}</a> : null}\n {m.status === \"scheduled\" ? (\n <>\n <Button variant=\"secondary\" mini disabled={busy === m.id} onClick={() => reschedule(m.id)}>{copy.reschedule}</Button>\n <Button variant=\"danger\" mini disabled={busy === m.id} onClick={() => cancel(m.id)}>{copy.cancel}</Button>\n </>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n </Panel>\n </AdminPage>\n );\n}\n\n/** Options for {@link meetingsSection}. */\nexport interface MeetingsSectionOptions {\n id?: string;\n label?: string;\n}\n\n/** Build the Meetings admin section: the reconciled agenda over\n * `GET /api/admin/meetings`, with reschedule/cancel actions. */\nexport function meetingsSection(options: MeetingsSectionOptions = {}): AdminSection {\n const { id = \"meetings\", label = \"Meetings\" } = options;\n return { id, label, render: (ctx) => <MeetingsBody ctx={ctx} /> };\n}\n"],"mappings":"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","names":["useEffect","useState","useEffect","useState","jsx","jsxs","jsx","jsxs","useState","useEffect","jsxs","jsx","Tabs","useState","useCallback","useEffect","useState","jsx","jsxs","useState","jsx","jsxs","Fragment","jsx","jsxs","money","useState","Button","Checkbox","DataTable","Field","Input","jsx","jsxs","useState","Field","Input","Button","Checkbox","DataTable","useEffect","useState","Button","Field","jsx","jsxs","useState","useEffect","Field","Button","useState","jsx","jsxs","useState","useCallback","useEffect","useState","jsx","useCallback","useEffect","useState","Button","Field","Select","jsx","jsxs","useState","Field","Select","Button","useCallback","useEffect","useState","Button","Fragment","jsx","jsxs","useState","Button","jsx","jsx","jsx","Tabs","ThemeScope","jsx","jsxs","ThemeScope","workspace","useEffect","useState","jsx","jsxs","useState","useEffect","useState","Button","Fragment","jsx","jsxs","when","useState","Button"]}
|