@odla-ai/chapter 0.39.0 → 0.39.1

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.
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-IAWBE5PX.js";
8
8
 
9
9
  // src/ui/admin.tsx
10
- import { useEffect as useEffect10, useMemo as useMemo2, useRef, useState as useState16 } from "preact/hooks";
10
+ import { useEffect as useEffect11, useMemo as useMemo2, useRef, useState as useState17 } from "preact/hooks";
11
11
  import { ClerkGate, SignedIn, SignedOut, SignIn, useClerkAuth } from "@odla-ai/auth-clerk";
12
12
  import { CrmClient } from "@odla-ai/crm";
13
13
 
@@ -438,11 +438,10 @@ function AdminShell({
438
438
  }
439
439
 
440
440
  // src/ui/admin-workspaces.tsx
441
- import { Tabs as Tabs2 } from "@odla-ai/ui/components";
441
+ import { Tabs as Tabs3 } from "@odla-ai/ui/components";
442
442
 
443
- // src/ui/admin-availability.tsx
444
- import { useState as useState4 } from "preact/hooks";
445
- import { Button, Checkbox, Field, Input } from "@odla-ai/ui/components";
443
+ // src/ui/admin-billing.tsx
444
+ import { DataTable, StatBand } from "@odla-ai/ui/components";
446
445
 
447
446
  // src/ui/admin-api.ts
448
447
  import { useCallback as useCallback2, useEffect as useEffect3, useState as useState3 } from "preact/hooks";
@@ -480,70 +479,8 @@ function useAdminResource(getToken, path) {
480
479
  return { data, loading, error, refresh };
481
480
  }
482
481
 
483
- // src/ui/admin-availability.tsx
484
- import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
485
- function AvailabilityBody({ ctx }) {
486
- const copy = useChapterCopy().admin.availability;
487
- const { data, loading, error, refresh } = useAdminResource(ctx.getToken, "/api/admin/scheduling");
488
- const [draft, setDraft] = useState4(null);
489
- const [busy, setBusy] = useState4(false);
490
- const [note, setNote] = useState4(null);
491
- const [errors, setErrors] = useState4({});
492
- const cfg = draft ?? data?.scheduling ?? null;
493
- if (loading) return /* @__PURE__ */ jsx4(AdminNote, { children: copy.loading });
494
- if (error || !cfg) return /* @__PURE__ */ jsxs4(AdminNote, { children: [
495
- copy.loadFailed,
496
- error ? `: ${error}` : "",
497
- "."
498
- ] });
499
- const edit = (patch) => setDraft({ ...cfg, ...patch });
500
- const toggleDay = (d) => edit({ days: cfg.days.includes(d) ? cfg.days.filter((x) => x !== d) : [...cfg.days, d].sort() });
501
- const num = (v, fallback) => Number.isFinite(Number(v)) ? Number(v) : fallback;
502
- const save = async () => {
503
- setBusy(true);
504
- setNote(null);
505
- setErrors({});
506
- const token = await ctx.getToken();
507
- try {
508
- const r = await fetch("/api/admin/scheduling", { method: "PUT", headers: { authorization: `Bearer ${token ?? ""}`, "content-type": "application/json" }, body: JSON.stringify(cfg) });
509
- const body = await r.json().catch(() => ({}));
510
- if (!r.ok) {
511
- setErrors(body.errors ?? {});
512
- setNote(body.error ?? `save failed (${r.status})`);
513
- return;
514
- }
515
- setDraft(null);
516
- refresh();
517
- setNote(copy.saved);
518
- } catch (e) {
519
- setNote(e instanceof Error ? e.message : String(e));
520
- } finally {
521
- setBusy(false);
522
- }
523
- };
524
- const numField = (key, label) => /* @__PURE__ */ jsx4(Field, { label, error: errors[key], children: /* @__PURE__ */ jsx4(Input, { type: "number", value: cfg[key], onInput: (e) => edit({ [key]: num(e.target.value, cfg[key]) }) }) });
525
- return /* @__PURE__ */ jsx4(AdminPage, { children: /* @__PURE__ */ jsxs4(Panel, { title: copy.title, actions: note ? /* @__PURE__ */ jsx4("span", { className: "muted", children: note }) : void 0, children: [
526
- /* @__PURE__ */ jsx4(Field, { label: copy.days, error: errors.days, children: /* @__PURE__ */ jsx4("div", { style: { display: "flex", gap: 14, flexWrap: "wrap" }, children: copy.dayLabels.map((d, i) => /* @__PURE__ */ jsx4(Checkbox, { label: d, checked: cfg.days.includes(i), onChange: () => toggleDay(i) }, d)) }) }),
527
- /* @__PURE__ */ jsxs4("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", gap: 14 }, children: [
528
- numField("startHour", copy.startHour),
529
- numField("endHour", copy.endHour),
530
- numField("slotMinutes", copy.slotMinutes),
531
- numField("minNoticeHours", copy.minNoticeHours),
532
- numField("windowDays", copy.windowDays),
533
- /* @__PURE__ */ jsx4(Field, { label: copy.timezone, error: errors.timezone, children: /* @__PURE__ */ jsx4(Input, { value: cfg.timezone, onInput: (e) => edit({ timezone: e.target.value }) }) })
534
- ] }),
535
- /* @__PURE__ */ jsx4(Field, { label: copy.summaryTemplate, error: errors.summaryTemplate, children: /* @__PURE__ */ jsx4(Input, { value: cfg.summaryTemplate, onInput: (e) => edit({ summaryTemplate: e.target.value }) }) }),
536
- /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(Button, { disabled: !draft || busy, onClick: () => void save(), children: copy.save }) })
537
- ] }) });
538
- }
539
- function availabilitySection(options = {}) {
540
- const { id = "availability", label = "Availability" } = options;
541
- return { id, label, render: (ctx) => /* @__PURE__ */ jsx4(AvailabilityBody, { ctx }) };
542
- }
543
-
544
482
  // src/ui/admin-billing.tsx
545
- import { DataTable, StatBand } from "@odla-ai/ui/components";
546
- import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
483
+ import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
547
484
  var money = (cents) => `$${(cents / 100).toLocaleString()}`;
548
485
  var date = (t) => t ? new Date(t).toLocaleDateString([], { dateStyle: "medium" }) : "\u2014";
549
486
  var columns = (copy) => [
@@ -557,13 +494,13 @@ var columns = (copy) => [
557
494
  function BillingBody({ ctx }) {
558
495
  const copy = useChapterCopy().admin.billing;
559
496
  const { data, loading, error } = useAdminResource(ctx.getToken, "/api/admin/billing");
560
- if (loading) return /* @__PURE__ */ jsx5(AdminNote, { children: copy.loading });
561
- if (error || !data) return /* @__PURE__ */ jsxs5(AdminNote, { children: [
497
+ if (loading) return /* @__PURE__ */ jsx4(AdminNote, { children: copy.loading });
498
+ if (error || !data) return /* @__PURE__ */ jsxs4(AdminNote, { children: [
562
499
  copy.loadFailed,
563
500
  error ? `: ${error}` : "",
564
501
  "."
565
502
  ] });
566
- if (!data.billingReady) return /* @__PURE__ */ jsx5(AdminNote, { children: copy.notConfigured });
503
+ if (!data.billingReady) return /* @__PURE__ */ jsx4(AdminNote, { children: copy.notConfigured });
567
504
  const s = data.summary;
568
505
  const stats = s ? [
569
506
  { value: s.activeCount, label: copy.active },
@@ -571,22 +508,22 @@ function BillingBody({ ctx }) {
571
508
  { value: s.renewingSoonCount, label: copy.renewingSoon },
572
509
  { value: s.pastDueCount, label: copy.pastDue }
573
510
  ] : [];
574
- return /* @__PURE__ */ jsxs5(AdminPage, { children: [
575
- s ? /* @__PURE__ */ jsx5(StatBand, { stats }) : null,
576
- /* @__PURE__ */ jsxs5(Panel, { title: copy.subscriptions, actions: data.testMode ? /* @__PURE__ */ jsx5("span", { className: "badge", children: copy.testMode }) : void 0, children: [
577
- data.truncated ? /* @__PURE__ */ jsx5("p", { className: "badge", children: copy.truncated }) : null,
578
- /* @__PURE__ */ jsx5(DataTable, { rows: data.rows, columns: columns(copy), rowKey: (r) => r.id })
511
+ return /* @__PURE__ */ jsxs4(AdminPage, { children: [
512
+ s ? /* @__PURE__ */ jsx4(StatBand, { stats }) : null,
513
+ /* @__PURE__ */ jsxs4(Panel, { title: copy.subscriptions, actions: data.testMode ? /* @__PURE__ */ jsx4("span", { className: "badge", children: copy.testMode }) : void 0, children: [
514
+ data.truncated ? /* @__PURE__ */ jsx4("p", { className: "badge", children: copy.truncated }) : null,
515
+ /* @__PURE__ */ jsx4(DataTable, { rows: data.rows, columns: columns(copy), rowKey: (r) => r.id })
579
516
  ] })
580
517
  ] });
581
518
  }
582
519
  function billingSection(options = {}) {
583
520
  const { id = "billing", label = "Billing" } = options;
584
- return { id, label, render: (ctx) => /* @__PURE__ */ jsx5(BillingBody, { ctx }) };
521
+ return { id, label, render: (ctx) => /* @__PURE__ */ jsx4(BillingBody, { ctx }) };
585
522
  }
586
523
 
587
524
  // src/ui/admin-dashboard.tsx
588
525
  import { MetricWidget, StepPipeline } from "@odla-ai/ui/components";
589
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
526
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
590
527
  var number = (value) => Math.round(value).toLocaleString();
591
528
  var money2 = (cents) => `$${Math.round(cents / 100).toLocaleString()}`;
592
529
  var when = (time) => new Date(time).toLocaleString([], { dateStyle: "medium", timeStyle: "short" });
@@ -596,49 +533,49 @@ function DashboardBody({ ctx }) {
596
533
  ctx.getToken,
597
534
  "/api/admin/dashboard"
598
535
  );
599
- if (loading) return /* @__PURE__ */ jsx6(AdminNote, { children: copy.loading });
600
- if (error || !data) return /* @__PURE__ */ jsxs6(AdminNote, { children: [
536
+ if (loading) return /* @__PURE__ */ jsx5(AdminNote, { children: copy.loading });
537
+ if (error || !data) return /* @__PURE__ */ jsxs5(AdminNote, { children: [
601
538
  copy.loadFailed,
602
539
  error ? `: ${error}` : "",
603
540
  "."
604
541
  ] });
605
542
  const pipelineSteps = Object.entries(data.pipeline).filter(([stage]) => !["declined", "refunded"].includes(stage)).map(([stage, count]) => ({
606
- icon: /* @__PURE__ */ jsx6("span", { style: { fontSize: 22, fontWeight: 700 }, children: count }),
543
+ icon: /* @__PURE__ */ jsx5("span", { style: { fontSize: 22, fontWeight: 700 }, children: count }),
607
544
  title: stage.replaceAll("_", " "),
608
545
  description: data.pipelineDelta[stage] ? formatChapterCopy(copy.thisWeek, { count: data.pipelineDelta[stage] }) : copy.noChange
609
546
  }));
610
547
  const exceptions = ["declined", "refunded"].filter((stage) => stage in data.pipeline).map((stage) => `${stage} ${data.pipeline[stage]}`).join(" \xB7 ");
611
- return /* @__PURE__ */ jsxs6(AdminPage, { children: [
612
- /* @__PURE__ */ jsx6(
548
+ return /* @__PURE__ */ jsxs5(AdminPage, { children: [
549
+ /* @__PURE__ */ jsx5(
613
550
  Panel,
614
551
  {
615
- title: /* @__PURE__ */ jsxs6(Fragment2, { children: [
552
+ title: /* @__PURE__ */ jsxs5(Fragment2, { children: [
616
553
  copy.upcomingCalls,
617
554
  " ",
618
- /* @__PURE__ */ jsxs6("span", { className: "muted", style: { fontWeight: 400 }, children: [
555
+ /* @__PURE__ */ jsxs5("span", { className: "muted", style: { fontWeight: 400 }, children: [
619
556
  "\xB7 ",
620
557
  data.timezone
621
558
  ] })
622
559
  ] }),
623
- actions: data.calls.needsAttention ? /* @__PURE__ */ jsx6("span", { className: "badge", children: formatChapterCopy(copy.callsNeedAttention, { count: data.calls.needsAttention }) }) : void 0,
624
- children: data.agenda.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "muted", style: { margin: 0 }, children: copy.noUpcomingCalls }) : /* @__PURE__ */ jsx6("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 10 }, children: data.agenda.map((meeting) => /* @__PURE__ */ jsxs6("li", { style: { display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }, children: [
625
- /* @__PURE__ */ jsx6("strong", { style: { minWidth: 170 }, children: when(meeting.startAt) }),
626
- /* @__PURE__ */ jsxs6("span", { style: { flex: 1 }, children: [
560
+ actions: data.calls.needsAttention ? /* @__PURE__ */ jsx5("span", { className: "badge", children: formatChapterCopy(copy.callsNeedAttention, { count: data.calls.needsAttention }) }) : void 0,
561
+ children: data.agenda.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "muted", style: { margin: 0 }, children: copy.noUpcomingCalls }) : /* @__PURE__ */ jsx5("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 10 }, children: data.agenda.map((meeting) => /* @__PURE__ */ jsxs5("li", { style: { display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }, children: [
562
+ /* @__PURE__ */ jsx5("strong", { style: { minWidth: 170 }, children: when(meeting.startAt) }),
563
+ /* @__PURE__ */ jsxs5("span", { style: { flex: 1 }, children: [
627
564
  meeting.name,
628
565
  meeting.email ? ` \xB7 ${meeting.email}` : ""
629
566
  ] }),
630
- meeting.drift && meeting.drift !== "none" ? /* @__PURE__ */ jsx6("span", { className: "badge", children: copy.drift }) : null,
631
- meeting.htmlLink ? /* @__PURE__ */ jsx6("a", { href: meeting.htmlLink, target: "_blank", rel: "noreferrer", children: copy.open }) : null,
632
- meeting.meetUrl ? /* @__PURE__ */ jsx6("a", { href: meeting.meetUrl, target: "_blank", rel: "noreferrer", children: copy.meet }) : null
567
+ meeting.drift && meeting.drift !== "none" ? /* @__PURE__ */ jsx5("span", { className: "badge", children: copy.drift }) : null,
568
+ meeting.htmlLink ? /* @__PURE__ */ jsx5("a", { href: meeting.htmlLink, target: "_blank", rel: "noreferrer", children: copy.open }) : null,
569
+ meeting.meetUrl ? /* @__PURE__ */ jsx5("a", { href: meeting.meetUrl, target: "_blank", rel: "noreferrer", children: copy.meet }) : null
633
570
  ] }, meeting.id)) })
634
571
  }
635
572
  ),
636
- /* @__PURE__ */ jsxs6("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: 18 }, children: [
637
- /* @__PURE__ */ jsx6(MetricWidget, { label: copy.applications, data: data.applicationsSeries, format: number }),
638
- data.membersSeries ? /* @__PURE__ */ jsx6(MetricWidget, { label: copy.newMembers, data: data.membersSeries, format: number }) : /* @__PURE__ */ jsx6(Panel, { title: copy.newMembers, children: /* @__PURE__ */ jsx6("p", { className: "muted", children: copy.newMembersUnavailable }) })
573
+ /* @__PURE__ */ jsxs5("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: 18 }, children: [
574
+ /* @__PURE__ */ jsx5(MetricWidget, { label: copy.applications, data: data.applicationsSeries, format: number }),
575
+ data.membersSeries ? /* @__PURE__ */ jsx5(MetricWidget, { label: copy.newMembers, data: data.membersSeries, format: number }) : /* @__PURE__ */ jsx5(Panel, { title: copy.newMembers, children: /* @__PURE__ */ jsx5("p", { className: "muted", children: copy.newMembersUnavailable }) })
639
576
  ] }),
640
- data.revenueSeries && data.revenue.billingReady ? /* @__PURE__ */ jsxs6("div", { children: [
641
- /* @__PURE__ */ jsx6(
577
+ data.revenueSeries && data.revenue.billingReady ? /* @__PURE__ */ jsxs5("div", { children: [
578
+ /* @__PURE__ */ jsx5(
642
579
  MetricWidget,
643
580
  {
644
581
  label: copy.revenueAdded,
@@ -647,7 +584,7 @@ function DashboardBody({ ctx }) {
647
584
  size: "large"
648
585
  }
649
586
  ),
650
- /* @__PURE__ */ jsxs6("p", { className: "muted", children: [
587
+ /* @__PURE__ */ jsxs5("p", { className: "muted", children: [
651
588
  copy.activeMemberships,
652
589
  ": ",
653
590
  data.revenue.activeCount ?? 0,
@@ -658,119 +595,32 @@ function DashboardBody({ ctx }) {
658
595
  money2(data.revenue.annualRunRateCents ?? 0),
659
596
  data.revenue.testMode ? ` \xB7 ${copy.testMode}` : ""
660
597
  ] })
661
- ] }) : /* @__PURE__ */ jsx6(Panel, { title: copy.revenue, children: /* @__PURE__ */ jsx6("p", { className: "muted", children: copy.revenueUnavailable }) }),
662
- /* @__PURE__ */ jsxs6(Panel, { title: copy.pipeline, children: [
663
- /* @__PURE__ */ jsx6(StepPipeline, { ariaLabel: copy.pipelineLabel, steps: pipelineSteps }),
664
- exceptions ? /* @__PURE__ */ jsx6("p", { className: "muted", style: { margin: 0 }, children: exceptions }) : null
598
+ ] }) : /* @__PURE__ */ jsx5(Panel, { title: copy.revenue, children: /* @__PURE__ */ jsx5("p", { className: "muted", children: copy.revenueUnavailable }) }),
599
+ /* @__PURE__ */ jsxs5(Panel, { title: copy.pipeline, children: [
600
+ /* @__PURE__ */ jsx5(StepPipeline, { ariaLabel: copy.pipelineLabel, steps: pipelineSteps }),
601
+ exceptions ? /* @__PURE__ */ jsx5("p", { className: "muted", style: { margin: 0 }, children: exceptions }) : null
665
602
  ] })
666
603
  ] });
667
604
  }
668
605
  function dashboardSection(options = {}) {
669
606
  const { id = "dashboard", label = "Dashboard" } = options;
670
- return { id, label, render: (ctx) => /* @__PURE__ */ jsx6(DashboardBody, { ctx }) };
671
- }
672
-
673
- // src/ui/admin-email.tsx
674
- import { useState as useState5 } from "preact/hooks";
675
- import { Button as Button2, Checkbox as Checkbox2, DataTable as DataTable2, Field as Field2, Input as Input2, Textarea } from "@odla-ai/ui/components";
676
- import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
677
- var logColumns = (copy) => [
678
- { key: "sentAt", header: copy.sentColumn, cell: (r) => new Date(r.sentAt).toLocaleString(), sortAs: "number", sortValue: (r) => r.sentAt },
679
- { key: "template", header: copy.templateColumn, cell: (r) => r.template },
680
- { key: "to", header: copy.toColumn, cell: (r) => r.to },
681
- { key: "status", header: copy.statusColumn, cell: (r) => r.error ? /* @__PURE__ */ jsx7("span", { className: "badge", children: copy.failed }) : r.redirected ? /* @__PURE__ */ jsx7("span", { className: "badge", children: copy.redirected }) : copy.delivered }
682
- ];
683
- function EmailBody({ ctx }) {
684
- const copy = useChapterCopy().admin.email;
685
- const cfg = useAdminResource(ctx.getToken, "/api/admin/group/email");
686
- const log = useAdminResource(ctx.getToken, "/api/admin/email/log");
687
- const [draft, setDraft] = useState5(null);
688
- const [busy, setBusy] = useState5(null);
689
- const [note, setNote] = useState5(null);
690
- const data = draft ?? cfg.data;
691
- if (cfg.loading) return /* @__PURE__ */ jsx7(AdminNote, { children: copy.loading });
692
- if (cfg.error || !data) return /* @__PURE__ */ jsxs7(AdminNote, { children: [
693
- copy.loadFailed,
694
- cfg.error ? `: ${cfg.error}` : "",
695
- "."
696
- ] });
697
- const edit = (patch) => setDraft({ ...data, ...patch });
698
- const editTemplate = (key, patch) => edit({ emailTemplates: { ...data.emailTemplates, [key]: { ...data.emailTemplates[key], ...patch } } });
699
- const run = async (key, fn) => {
700
- setBusy(key);
701
- setNote(null);
702
- try {
703
- await fn();
704
- } catch (e) {
705
- setNote(e instanceof Error ? e.message : String(e));
706
- } finally {
707
- setBusy(null);
708
- }
709
- };
710
- const save = () => run("save", async () => {
711
- await adminFetch(ctx.getToken, "/api/admin/group/email", { method: "PUT", body: JSON.stringify(data) });
712
- setDraft(null);
713
- cfg.refresh();
714
- setNote(copy.saved);
715
- });
716
- const test = (template) => run(`test:${template}`, async () => {
717
- const r = await adminFetch(ctx.getToken, "/api/admin/email/test", { method: "POST", body: JSON.stringify({ template }) });
718
- setNote(r.ok ? formatChapterCopy(copy.sent, {
719
- template,
720
- address: r.to,
721
- redirected: r.redirected ? ` (${copy.redirected})` : ""
722
- }) : copy.testFailed);
723
- log.refresh();
724
- });
725
- return /* @__PURE__ */ jsxs7(AdminPage, { children: [
726
- /* @__PURE__ */ jsxs7(
727
- Panel,
728
- {
729
- title: copy.delivery,
730
- actions: /* @__PURE__ */ jsxs7("span", { className: "muted", children: [
731
- data.envName,
732
- " \xB7 ",
733
- data.transport,
734
- data.fromEmail ? ` \xB7 ${data.fromEmail}` : ""
735
- ] }),
736
- children: [
737
- /* @__PURE__ */ jsx7(Field2, { label: copy.notificationAddress, children: /* @__PURE__ */ jsx7(Input2, { value: data.notificationEmail, onInput: (e) => edit({ notificationEmail: e.target.value }) }) }),
738
- /* @__PURE__ */ jsx7(Field2, { label: copy.replyTo, children: /* @__PURE__ */ jsx7(Input2, { value: data.replyTo, onInput: (e) => edit({ replyTo: e.target.value }) }) }),
739
- /* @__PURE__ */ jsx7(Field2, { label: copy.debugInbox, hint: copy.debugInboxHint, children: /* @__PURE__ */ jsx7(Input2, { value: data.debugEmail, onInput: (e) => edit({ debugEmail: e.target.value }) }) })
740
- ]
741
- }
742
- ),
743
- Object.entries(data.emailTemplates).map(([key, t]) => /* @__PURE__ */ jsxs7(Panel, { title: key, actions: /* @__PURE__ */ jsx7(Button2, { variant: "secondary", mini: true, disabled: busy === `test:${key}`, onClick: () => void test(key), children: copy.sendTest }), children: [
744
- /* @__PURE__ */ jsx7(Checkbox2, { label: copy.enabled, checked: t.enabled, onChange: (e) => editTemplate(key, { enabled: e.target.checked }) }),
745
- /* @__PURE__ */ jsx7(Field2, { label: copy.subject, children: /* @__PURE__ */ jsx7(Input2, { value: t.subject, onInput: (e) => editTemplate(key, { subject: e.target.value }) }) }),
746
- /* @__PURE__ */ jsx7(Field2, { label: copy.body, children: /* @__PURE__ */ jsx7(Textarea, { prose: true, rows: 5, value: t.text, onInput: (e) => editTemplate(key, { text: e.target.value }) }) })
747
- ] }, key)),
748
- /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
749
- /* @__PURE__ */ jsx7(Button2, { disabled: !draft || busy === "save", onClick: () => void save(), children: copy.save }),
750
- note ? /* @__PURE__ */ jsx7("span", { className: "muted", children: note }) : null
751
- ] }),
752
- /* @__PURE__ */ jsx7(Panel, { title: copy.sendLog, children: /* @__PURE__ */ jsx7(DataTable2, { rows: log.data?.sends ?? [], columns: logColumns(copy), rowKey: (r) => r.id }) })
753
- ] });
754
- }
755
- function emailSection(options = {}) {
756
- const { id = "email", label = "Email" } = options;
757
- return { id, label, render: (ctx) => /* @__PURE__ */ jsx7(EmailBody, { ctx }) };
607
+ return { id, label, render: (ctx) => /* @__PURE__ */ jsx5(DashboardBody, { ctx }) };
758
608
  }
759
609
 
760
610
  // src/ui/admin-people-workspace.tsx
761
611
  import { BillingCard, CrmWorkspace } from "@odla-ai/crm/ui";
762
612
 
763
613
  // src/ui/admin-record-actions.tsx
764
- import { useEffect as useEffect4, useState as useState6 } from "preact/hooks";
765
- import { Button as Button3, Field as Field3, Select } from "@odla-ai/ui/components";
766
- import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
614
+ import { useEffect as useEffect4, useState as useState4 } from "preact/hooks";
615
+ import { Button, Field, Select } from "@odla-ai/ui/components";
616
+ import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
767
617
  function RecordActions({ getToken, record, roles, onChanged }) {
768
618
  const copy = useChapterCopy().admin.records;
769
619
  const userId = typeof record.clerkUserId === "string" ? record.clerkUserId : null;
770
620
  const applicationId = typeof record.fields?.applicationId === "string" ? record.fields.applicationId : null;
771
- const [access, setAccess] = useState6(null);
772
- const [busy, setBusy] = useState6(null);
773
- const [note, setNote] = useState6(null);
621
+ const [access, setAccess] = useState4(null);
622
+ const [busy, setBusy] = useState4(null);
623
+ const [note, setNote] = useState4(null);
774
624
  useEffect4(() => {
775
625
  if (!userId) {
776
626
  setAccess(null);
@@ -799,9 +649,9 @@ function RecordActions({ getToken, record, roles, onChanged }) {
799
649
  const approve = () => act("approve", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/approve`, { method: "POST" }), copy.approved);
800
650
  const refund = () => act("refund", () => adminFetch(getToken, `/api/admin/applications/${applicationId}/refund`, { method: "POST" }), copy.refunded);
801
651
  if (!userId && !applicationId) return null;
802
- return /* @__PURE__ */ jsxs8("section", { className: "panel", style: { display: "flex", flexDirection: "column", gap: 14, marginTop: 16 }, children: [
803
- /* @__PURE__ */ jsx8("h3", { style: { margin: 0, fontSize: 16 }, children: copy.lifecycle }),
804
- userId ? /* @__PURE__ */ jsx8(Field3, { label: copy.role, hint: access?.superAdmin ? copy.superAdminHint : void 0, children: /* @__PURE__ */ jsx8(
652
+ return /* @__PURE__ */ jsxs6("section", { className: "panel", style: { display: "flex", flexDirection: "column", gap: 14, marginTop: 16 }, children: [
653
+ /* @__PURE__ */ jsx6("h3", { style: { margin: 0, fontSize: 16 }, children: copy.lifecycle }),
654
+ userId ? /* @__PURE__ */ jsx6(Field, { label: copy.role, hint: access?.superAdmin ? copy.superAdminHint : void 0, children: /* @__PURE__ */ jsx6(
805
655
  Select,
806
656
  {
807
657
  value: access?.role ?? "",
@@ -809,24 +659,24 @@ function RecordActions({ getToken, record, roles, onChanged }) {
809
659
  options: roles.map((r) => ({ value: r, label: r })),
810
660
  onChange: (e) => void setRole(e.target.value)
811
661
  }
812
- ) }) : /* @__PURE__ */ jsx8("p", { className: "muted", style: { margin: 0 }, children: copy.noAccount }),
813
- applicationId ? /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: 8 }, children: [
814
- /* @__PURE__ */ jsx8(Button3, { variant: "secondary", mini: true, disabled: busy === "approve", onClick: () => void approve(), children: copy.approve }),
815
- /* @__PURE__ */ jsx8(Button3, { variant: "danger", mini: true, disabled: busy === "refund", onClick: () => void refund(), children: copy.refund })
662
+ ) }) : /* @__PURE__ */ jsx6("p", { className: "muted", style: { margin: 0 }, children: copy.noAccount }),
663
+ applicationId ? /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8 }, children: [
664
+ /* @__PURE__ */ jsx6(Button, { variant: "secondary", mini: true, disabled: busy === "approve", onClick: () => void approve(), children: copy.approve }),
665
+ /* @__PURE__ */ jsx6(Button, { variant: "danger", mini: true, disabled: busy === "refund", onClick: () => void refund(), children: copy.refund })
816
666
  ] }) : null,
817
- note ? /* @__PURE__ */ jsx8("p", { className: "muted", style: { margin: 0 }, children: note }) : null
667
+ note ? /* @__PURE__ */ jsx6("p", { className: "muted", style: { margin: 0 }, children: note }) : null
818
668
  ] });
819
669
  }
820
670
 
821
671
  // src/ui/admin-network.tsx
822
- import { useState as useState7 } from "preact/hooks";
823
- import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
672
+ import { useState as useState5 } from "preact/hooks";
673
+ import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
824
674
  function NetworkShareActions(props) {
825
675
  const copy = useChapterCopy().admin.network;
826
676
  const { recordId, recordType, getToken } = props;
827
677
  const targets = useAdminResource(getToken, "/api/admin/network/targets");
828
- const [busy, setBusy] = useState7(null);
829
- const [message, setMessage] = useState7(null);
678
+ const [busy, setBusy] = useState5(null);
679
+ const [message, setMessage] = useState5(null);
830
680
  const compatible = (targets.data?.targets ?? []).filter((target) => target.types.includes(recordType));
831
681
  if (targets.loading || targets.error || compatible.length === 0) return null;
832
682
  const push = async (target) => {
@@ -845,26 +695,26 @@ function NetworkShareActions(props) {
845
695
  setBusy(null);
846
696
  }
847
697
  };
848
- return /* @__PURE__ */ jsxs9("section", { className: "panel", style: { marginTop: 14, display: "flex", flexDirection: "column", gap: 10 }, children: [
849
- /* @__PURE__ */ jsxs9("div", { children: [
850
- /* @__PURE__ */ jsx9("h3", { style: { margin: 0, fontSize: 16 }, children: copy.title }),
851
- /* @__PURE__ */ jsx9("p", { className: "muted", style: { margin: "4px 0 0", fontSize: 13 }, children: copy.allowlistDescription })
698
+ return /* @__PURE__ */ jsxs7("section", { className: "panel", style: { marginTop: 14, display: "flex", flexDirection: "column", gap: 10 }, children: [
699
+ /* @__PURE__ */ jsxs7("div", { children: [
700
+ /* @__PURE__ */ jsx7("h3", { style: { margin: 0, fontSize: 16 }, children: copy.title }),
701
+ /* @__PURE__ */ jsx7("p", { className: "muted", style: { margin: "4px 0 0", fontSize: 13 }, children: copy.allowlistDescription })
852
702
  ] }),
853
- /* @__PURE__ */ jsx9("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: compatible.map((target) => /* @__PURE__ */ jsx9("button", { className: "btn secondary mini", disabled: busy !== null, onClick: () => void push(target), children: busy === target.id ? copy.sharing : formatChapterCopy(copy.shareWith, { target: target.name }) }, target.id)) }),
854
- message ? /* @__PURE__ */ jsx9("p", { role: "status", style: { margin: 0, fontSize: 13 }, children: message }) : null
703
+ /* @__PURE__ */ jsx7("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: compatible.map((target) => /* @__PURE__ */ jsx7("button", { className: "btn secondary mini", disabled: busy !== null, onClick: () => void push(target), children: busy === target.id ? copy.sharing : formatChapterCopy(copy.shareWith, { target: target.name }) }, target.id)) }),
704
+ message ? /* @__PURE__ */ jsx7("p", { role: "status", style: { margin: 0, fontSize: 13 }, children: message }) : null
855
705
  ] });
856
706
  }
857
707
 
858
708
  // src/ui/admin-record-activity.tsx
859
- import { useCallback as useCallback3, useEffect as useEffect5, useState as useState8 } from "preact/hooks";
709
+ import { useCallback as useCallback3, useEffect as useEffect5, useState as useState6 } from "preact/hooks";
860
710
  import { ActivityFeed } from "@odla-ai/crm/ui";
861
711
  import { parseCrmDiscussionReference as parseCrmDiscussionReference2 } from "@odla-ai/crm";
862
- import { jsx as jsx10 } from "preact/jsx-runtime";
712
+ import { jsx as jsx8 } from "preact/jsx-runtime";
863
713
  function RecordActivityPanel(props) {
864
714
  const { client, recordId } = props;
865
- const [activities, setActivities] = useState8([]);
866
- const [busy, setBusy] = useState8(false);
867
- const [error, setError] = useState8(null);
715
+ const [activities, setActivities] = useState6([]);
716
+ const [busy, setBusy] = useState6(false);
717
+ const [error, setError] = useState6(null);
868
718
  const reference = typeof window === "undefined" ? null : parseCrmDiscussionReference2(new URL(window.location.href));
869
719
  const focusedActivityId = reference?.kind === "crm:activity" && reference.recordId === recordId ? reference.activityId : void 0;
870
720
  const load = useCallback3(async () => {
@@ -886,8 +736,8 @@ function RecordActivityPanel(props) {
886
736
  setBusy(false);
887
737
  }
888
738
  };
889
- if (error) return /* @__PURE__ */ jsx10("p", { role: "alert", className: "muted", children: error });
890
- return /* @__PURE__ */ jsx10(
739
+ if (error) return /* @__PURE__ */ jsx8("p", { role: "alert", className: "muted", children: error });
740
+ return /* @__PURE__ */ jsx8(
891
741
  ActivityFeed,
892
742
  {
893
743
  activities,
@@ -901,17 +751,17 @@ function RecordActivityPanel(props) {
901
751
  }
902
752
 
903
753
  // src/ui/admin-record-comms.tsx
904
- import { useCallback as useCallback4, useEffect as useEffect6, useState as useState9 } from "preact/hooks";
905
- import { Button as Button4, Field as Field4, Select as Select2 } from "@odla-ai/ui/components";
906
- import { jsx as jsx11, jsxs as jsxs10 } from "preact/jsx-runtime";
754
+ import { useCallback as useCallback4, useEffect as useEffect6, useState as useState7 } from "preact/hooks";
755
+ import { Button as Button2, Field as Field2, Select as Select2 } from "@odla-ai/ui/components";
756
+ import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
907
757
  function RecordCommsPanel(props) {
908
758
  const copy = useChapterCopy().admin.records;
909
759
  const { client, recordId, getToken } = props;
910
760
  const config = useAdminResource(getToken, "/api/admin/group/email");
911
761
  const templates = Object.entries(config.data?.emailTemplates ?? {}).filter(([, value]) => value.enabled);
912
- const [template, setTemplate] = useState9("");
913
- const [busy, setBusy] = useState9(false);
914
- const [note, setNote] = useState9(null);
762
+ const [template, setTemplate] = useState7("");
763
+ const [busy, setBusy] = useState7(false);
764
+ const [note, setNote] = useState7(null);
915
765
  const send = async () => {
916
766
  if (!template) return;
917
767
  setBusy(true);
@@ -925,10 +775,10 @@ function RecordCommsPanel(props) {
925
775
  setBusy(false);
926
776
  }
927
777
  };
928
- if (config.loading) return /* @__PURE__ */ jsx11("p", { className: "muted", children: copy.loadingTemplates });
929
- if (config.error) return /* @__PURE__ */ jsx11("p", { role: "alert", className: "muted", children: config.error });
930
- return /* @__PURE__ */ jsxs10("div", { style: { display: "grid", gap: 14, maxWidth: 560 }, children: [
931
- /* @__PURE__ */ jsx11(Field4, { label: copy.template, children: /* @__PURE__ */ jsx11(
778
+ if (config.loading) return /* @__PURE__ */ jsx9("p", { className: "muted", children: copy.loadingTemplates });
779
+ if (config.error) return /* @__PURE__ */ jsx9("p", { role: "alert", className: "muted", children: config.error });
780
+ return /* @__PURE__ */ jsxs8("div", { style: { display: "grid", gap: 14, maxWidth: 560 }, children: [
781
+ /* @__PURE__ */ jsx9(Field2, { label: copy.template, children: /* @__PURE__ */ jsx9(
932
782
  Select2,
933
783
  {
934
784
  value: template,
@@ -939,15 +789,15 @@ function RecordCommsPanel(props) {
939
789
  ]
940
790
  }
941
791
  ) }),
942
- /* @__PURE__ */ jsx11("div", { children: /* @__PURE__ */ jsx11(Button4, { disabled: !template || busy, onClick: () => void send(), children: busy ? copy.sending : copy.send }) }),
943
- note ? /* @__PURE__ */ jsx11("p", { role: "status", className: "muted", children: note }) : null
792
+ /* @__PURE__ */ jsx9("div", { children: /* @__PURE__ */ jsx9(Button2, { disabled: !template || busy, onClick: () => void send(), children: busy ? copy.sending : copy.send }) }),
793
+ note ? /* @__PURE__ */ jsx9("p", { role: "status", className: "muted", children: note }) : null
944
794
  ] });
945
795
  }
946
796
  function RecordCommsHistory(props) {
947
797
  const copy = useChapterCopy().admin.records;
948
798
  const { client, recordId } = props;
949
- const [rows, setRows] = useState9([]);
950
- const [error, setError] = useState9(null);
799
+ const [rows, setRows] = useState7([]);
800
+ const [error, setError] = useState7(null);
951
801
  const load = useCallback4(async () => {
952
802
  try {
953
803
  const result = await client.emailLog({ recordId, limit: 100 });
@@ -958,11 +808,11 @@ function RecordCommsHistory(props) {
958
808
  }
959
809
  }, [client, recordId]);
960
810
  useEffect6(() => void load(), [load]);
961
- if (error) return /* @__PURE__ */ jsx11("p", { role: "alert", className: "muted", children: error });
962
- if (rows.length === 0) return /* @__PURE__ */ jsx11("p", { className: "muted", children: copy.noMessages });
963
- return /* @__PURE__ */ jsx11("ul", { style: { listStyle: "none", padding: 0, margin: 0, display: "grid", gap: 10 }, children: rows.map((row, index) => /* @__PURE__ */ jsxs10("li", { className: "panel", children: [
964
- /* @__PURE__ */ jsx11("strong", { children: String(row["templateId"] ?? row["template"] ?? copy.message) }),
965
- /* @__PURE__ */ jsxs10("div", { className: "muted", children: [
811
+ if (error) return /* @__PURE__ */ jsx9("p", { role: "alert", className: "muted", children: error });
812
+ if (rows.length === 0) return /* @__PURE__ */ jsx9("p", { className: "muted", children: copy.noMessages });
813
+ return /* @__PURE__ */ jsx9("ul", { style: { listStyle: "none", padding: 0, margin: 0, display: "grid", gap: 10 }, children: rows.map((row, index) => /* @__PURE__ */ jsxs8("li", { className: "panel", children: [
814
+ /* @__PURE__ */ jsx9("strong", { children: String(row["templateId"] ?? row["template"] ?? copy.message) }),
815
+ /* @__PURE__ */ jsxs8("div", { className: "muted", children: [
966
816
  row["to"] ? String(row["to"]) : "",
967
817
  row["sentAt"] ? ` \xB7 ${new Date(Number(row["sentAt"])).toLocaleString()}` : ""
968
818
  ] })
@@ -970,9 +820,9 @@ function RecordCommsHistory(props) {
970
820
  }
971
821
 
972
822
  // src/ui/admin-record-scheduling.tsx
973
- import { useState as useState10 } from "preact/hooks";
974
- import { Button as Button5 } from "@odla-ai/ui/components";
975
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "preact/jsx-runtime";
823
+ import { useState as useState8 } from "preact/hooks";
824
+ import { Button as Button3 } from "@odla-ai/ui/components";
825
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
976
826
  function RecordSchedulingPanel(props) {
977
827
  const copy = useChapterCopy().admin.records;
978
828
  const { getToken, applicationId } = props;
@@ -980,8 +830,8 @@ function RecordSchedulingPanel(props) {
980
830
  getToken,
981
831
  "/api/admin/meetings?all=1"
982
832
  );
983
- const [busy, setBusy] = useState10(null);
984
- const [note, setNote] = useState10(null);
833
+ const [busy, setBusy] = useState8(null);
834
+ const [note, setNote] = useState8(null);
985
835
  const meetings = (resource.data?.meetings ?? []).filter((meeting) => meeting.applicationId === applicationId);
986
836
  const run = async (meeting, action) => {
987
837
  let body;
@@ -1008,33 +858,33 @@ function RecordSchedulingPanel(props) {
1008
858
  setBusy(null);
1009
859
  }
1010
860
  };
1011
- if (!applicationId) return /* @__PURE__ */ jsx12("p", { className: "muted", children: copy.noApplication });
1012
- if (resource.loading) return /* @__PURE__ */ jsx12("p", { className: "muted", children: copy.loadingMeetings });
1013
- if (resource.error) return /* @__PURE__ */ jsx12("p", { role: "alert", className: "muted", children: resource.error });
1014
- if (meetings.length === 0) return /* @__PURE__ */ jsx12("p", { className: "muted", children: copy.noMeetings });
1015
- return /* @__PURE__ */ jsxs11("div", { style: { display: "grid", gap: 12 }, children: [
1016
- meetings.map((meeting) => /* @__PURE__ */ jsxs11("section", { className: "panel", children: [
1017
- /* @__PURE__ */ jsx12("strong", { children: new Date(meeting.startAt).toLocaleString() }),
1018
- /* @__PURE__ */ jsxs11("p", { className: "muted", children: [
861
+ if (!applicationId) return /* @__PURE__ */ jsx10("p", { className: "muted", children: copy.noApplication });
862
+ if (resource.loading) return /* @__PURE__ */ jsx10("p", { className: "muted", children: copy.loadingMeetings });
863
+ if (resource.error) return /* @__PURE__ */ jsx10("p", { role: "alert", className: "muted", children: resource.error });
864
+ if (meetings.length === 0) return /* @__PURE__ */ jsx10("p", { className: "muted", children: copy.noMeetings });
865
+ return /* @__PURE__ */ jsxs9("div", { style: { display: "grid", gap: 12 }, children: [
866
+ meetings.map((meeting) => /* @__PURE__ */ jsxs9("section", { className: "panel", children: [
867
+ /* @__PURE__ */ jsx10("strong", { children: new Date(meeting.startAt).toLocaleString() }),
868
+ /* @__PURE__ */ jsxs9("p", { className: "muted", children: [
1019
869
  meeting.status,
1020
870
  " \xB7 ",
1021
871
  resource.data?.timezone
1022
872
  ] }),
1023
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
1024
- meeting.meetUrl ? /* @__PURE__ */ jsx12("a", { href: meeting.meetUrl, target: "_blank", rel: "noreferrer", children: copy.joinMeeting }) : null,
1025
- meeting.htmlLink ? /* @__PURE__ */ jsx12("a", { href: meeting.htmlLink, target: "_blank", rel: "noreferrer", children: copy.openCalendar }) : null,
1026
- meeting.status === "scheduled" ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
1027
- /* @__PURE__ */ jsx12(Button5, { variant: "secondary", mini: true, disabled: busy === meeting.id, onClick: () => void run(meeting, "reschedule"), children: copy.reschedule }),
1028
- /* @__PURE__ */ jsx12(Button5, { variant: "danger", mini: true, disabled: busy === meeting.id, onClick: () => void run(meeting, "cancel"), children: copy.cancel })
873
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
874
+ meeting.meetUrl ? /* @__PURE__ */ jsx10("a", { href: meeting.meetUrl, target: "_blank", rel: "noreferrer", children: copy.joinMeeting }) : null,
875
+ meeting.htmlLink ? /* @__PURE__ */ jsx10("a", { href: meeting.htmlLink, target: "_blank", rel: "noreferrer", children: copy.openCalendar }) : null,
876
+ meeting.status === "scheduled" ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
877
+ /* @__PURE__ */ jsx10(Button3, { variant: "secondary", mini: true, disabled: busy === meeting.id, onClick: () => void run(meeting, "reschedule"), children: copy.reschedule }),
878
+ /* @__PURE__ */ jsx10(Button3, { variant: "danger", mini: true, disabled: busy === meeting.id, onClick: () => void run(meeting, "cancel"), children: copy.cancel })
1029
879
  ] }) : null
1030
880
  ] })
1031
881
  ] }, meeting.id)),
1032
- note ? /* @__PURE__ */ jsx12("p", { role: "status", className: "muted", children: note }) : null
882
+ note ? /* @__PURE__ */ jsx10("p", { role: "status", className: "muted", children: note }) : null
1033
883
  ] });
1034
884
  }
1035
885
 
1036
886
  // src/ui/admin-people-workspace.tsx
1037
- import { jsx as jsx13 } from "preact/jsx-runtime";
887
+ import { jsx as jsx11 } from "preact/jsx-runtime";
1038
888
  function applicationLifecycleAdapter(ctx, copy = DEFAULT_CHAPTER_COPY.admin.records) {
1039
889
  return {
1040
890
  transitionStage: async ({ record, to }) => {
@@ -1083,7 +933,7 @@ function PeopleBody(props) {
1083
933
  const builtInLifecycle = lifecycle ? applicationLifecycleAdapter(ctx, copy) : void 0;
1084
934
  const resolvedLifecycle = typeof lifecycleAdapter === "function" ? lifecycleAdapter(ctx) : lifecycleAdapter ?? builtInLifecycle;
1085
935
  const workspaceClient = client;
1086
- return /* @__PURE__ */ jsx13(AdminPage, { children: /* @__PURE__ */ jsx13(
936
+ return /* @__PURE__ */ jsx11(AdminPage, { children: /* @__PURE__ */ jsx11(
1087
937
  CrmWorkspace,
1088
938
  {
1089
939
  crm,
@@ -1119,35 +969,35 @@ function PeopleBody(props) {
1119
969
  tabs.push({
1120
970
  id: "comms",
1121
971
  label: copy.comms,
1122
- panel: /* @__PURE__ */ jsx13(RecordCommsPanel, { client, recordId: record.id, getToken: ctx.getToken })
972
+ panel: /* @__PURE__ */ jsx11(RecordCommsPanel, { client, recordId: record.id, getToken: ctx.getToken })
1123
973
  });
1124
974
  tabs.push({
1125
975
  id: "history",
1126
976
  label: copy.commsHistory,
1127
- panel: /* @__PURE__ */ jsx13(RecordCommsHistory, { client, recordId: record.id })
977
+ panel: /* @__PURE__ */ jsx11(RecordCommsHistory, { client, recordId: record.id })
1128
978
  });
1129
979
  }
1130
980
  if (lifecycle) {
1131
981
  tabs.push({
1132
982
  id: "scheduling",
1133
983
  label: copy.scheduling,
1134
- panel: /* @__PURE__ */ jsx13(RecordSchedulingPanel, { getToken: ctx.getToken, applicationId })
984
+ panel: /* @__PURE__ */ jsx11(RecordSchedulingPanel, { getToken: ctx.getToken, applicationId })
1135
985
  });
1136
- tabs.push({ id: "billing", label: copy.billing, panel: /* @__PURE__ */ jsx13(BillingCard, { record }) });
986
+ tabs.push({ id: "billing", label: copy.billing, panel: /* @__PURE__ */ jsx11(BillingCard, { record }) });
1137
987
  } else {
1138
988
  add("billing");
1139
989
  }
1140
990
  tabs.push({
1141
991
  id: "notes",
1142
992
  label: copy.notes,
1143
- panel: /* @__PURE__ */ jsx13(RecordActivityPanel, { client, recordId: record.id })
993
+ panel: /* @__PURE__ */ jsx11(RecordActivityPanel, { client, recordId: record.id })
1144
994
  });
1145
995
  add("connections");
1146
996
  if (lifecycle) {
1147
997
  tabs.push({
1148
998
  id: "access",
1149
999
  label: copy.access,
1150
- panel: /* @__PURE__ */ jsx13(
1000
+ panel: /* @__PURE__ */ jsx11(
1151
1001
  RecordActions,
1152
1002
  {
1153
1003
  getToken: ctx.getToken,
@@ -1166,7 +1016,7 @@ function PeopleBody(props) {
1166
1016
  tabs.push({
1167
1017
  id: "sharing",
1168
1018
  label: copy.sharing,
1169
- panel: /* @__PURE__ */ jsx13(NetworkShareActions, { recordId: record.id, recordType: record.type, getToken: ctx.getToken })
1019
+ panel: /* @__PURE__ */ jsx11(NetworkShareActions, { recordId: record.id, recordType: record.type, getToken: ctx.getToken })
1170
1020
  });
1171
1021
  }
1172
1022
  return extendRecordTabs?.(tabs, context) ?? tabs;
@@ -1176,7 +1026,7 @@ function PeopleBody(props) {
1176
1026
  }
1177
1027
 
1178
1028
  // src/ui/admin-people.tsx
1179
- import { jsx as jsx14 } from "preact/jsx-runtime";
1029
+ import { jsx as jsx12 } from "preact/jsx-runtime";
1180
1030
  var DEFAULT_ROLES = ["provisional", "member", "admin"];
1181
1031
  function collectionSection(options) {
1182
1032
  const { crm, type } = options;
@@ -1206,7 +1056,7 @@ function collectionSection(options) {
1206
1056
  return {
1207
1057
  id,
1208
1058
  label,
1209
- render: (ctx) => /* @__PURE__ */ jsx14(
1059
+ render: (ctx) => /* @__PURE__ */ jsx12(
1210
1060
  PeopleBody,
1211
1061
  {
1212
1062
  crm,
@@ -1274,18 +1124,18 @@ function peopleSection(options) {
1274
1124
 
1275
1125
  // src/ui/admin-network-records.tsx
1276
1126
  import {
1277
- DataTable as DataTable3,
1278
- Field as Field6,
1127
+ DataTable as DataTable2,
1128
+ Field as Field4,
1279
1129
  MasterDetail,
1280
1130
  Pagination,
1281
1131
  Select as Select3
1282
1132
  } from "@odla-ai/ui/components";
1283
- import { useEffect as useEffect7, useMemo, useState as useState12 } from "preact/hooks";
1133
+ import { useEffect as useEffect7, useMemo, useState as useState10 } from "preact/hooks";
1284
1134
 
1285
1135
  // src/ui/admin-network-notes.tsx
1286
- import { Button as Button6, Field as Field5, Textarea as Textarea2 } from "@odla-ai/ui/components";
1287
- import { useState as useState11 } from "preact/hooks";
1288
- import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
1136
+ import { Button as Button4, Field as Field3, Textarea } from "@odla-ai/ui/components";
1137
+ import { useState as useState9 } from "preact/hooks";
1138
+ import { jsx as jsx13, jsxs as jsxs10 } from "preact/jsx-runtime";
1289
1139
  function displayValue(value) {
1290
1140
  if (Array.isArray(value)) return value.join(", ");
1291
1141
  if (value && typeof value === "object") return JSON.stringify(value);
@@ -1300,9 +1150,9 @@ function PrivateNotes(props) {
1300
1150
  });
1301
1151
  const path = `/api/admin/network/notes?${query}`;
1302
1152
  const notes = useAdminResource(ctx.getToken, path);
1303
- const [body, setBody] = useState11("");
1304
- const [busy, setBusy] = useState11(false);
1305
- const [error, setError] = useState11(null);
1153
+ const [body, setBody] = useState9("");
1154
+ const [busy, setBusy] = useState9(false);
1155
+ const [error, setError] = useState9(null);
1306
1156
  const submit = async () => {
1307
1157
  const trimmed = body.trim();
1308
1158
  if (!trimmed) return;
@@ -1321,19 +1171,19 @@ function PrivateNotes(props) {
1321
1171
  setBusy(false);
1322
1172
  }
1323
1173
  };
1324
- return /* @__PURE__ */ jsxs12("section", { style: { display: "grid", gap: 12 }, children: [
1325
- /* @__PURE__ */ jsxs12("h3", { style: { margin: "8px 0 0" }, children: [
1174
+ return /* @__PURE__ */ jsxs10("section", { style: { display: "grid", gap: 12 }, children: [
1175
+ /* @__PURE__ */ jsxs10("h3", { style: { margin: "8px 0 0" }, children: [
1326
1176
  "Private to ",
1327
1177
  leaderName
1328
1178
  ] }),
1329
- /* @__PURE__ */ jsx15(
1330
- Field5,
1179
+ /* @__PURE__ */ jsx13(
1180
+ Field3,
1331
1181
  {
1332
1182
  label: "Add a note",
1333
1183
  hint: `Visible only to ${leaderName} admins. Nothing is written back to the follower.`,
1334
1184
  error,
1335
- children: /* @__PURE__ */ jsx15(
1336
- Textarea2,
1185
+ children: /* @__PURE__ */ jsx13(
1186
+ Textarea,
1337
1187
  {
1338
1188
  rows: 4,
1339
1189
  value: body,
@@ -1343,13 +1193,13 @@ function PrivateNotes(props) {
1343
1193
  )
1344
1194
  }
1345
1195
  ),
1346
- /* @__PURE__ */ jsx15("div", { children: /* @__PURE__ */ jsx15(Button6, { disabled: busy || !body.trim(), onClick: () => void submit(), children: busy ? "Saving\u2026" : "Save note" }) }),
1347
- notes.loading ? /* @__PURE__ */ jsx15("p", { className: "muted", children: "Loading notes\u2026" }) : null,
1348
- notes.error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: notes.error }) : null,
1349
- !notes.loading && !notes.error && (notes.data?.notes.length ?? 0) === 0 ? /* @__PURE__ */ jsx15("p", { className: "muted", children: "No notes yet." }) : null,
1350
- (notes.data?.notes ?? []).map((note) => /* @__PURE__ */ jsxs12("article", { className: "panel", style: { padding: 14 }, children: [
1351
- /* @__PURE__ */ jsx15("p", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: note.body }),
1352
- /* @__PURE__ */ jsxs12("p", { className: "muted", style: { margin: "8px 0 0", fontSize: 12 }, children: [
1196
+ /* @__PURE__ */ jsx13("div", { children: /* @__PURE__ */ jsx13(Button4, { disabled: busy || !body.trim(), onClick: () => void submit(), children: busy ? "Saving\u2026" : "Save note" }) }),
1197
+ notes.loading ? /* @__PURE__ */ jsx13("p", { className: "muted", children: "Loading notes\u2026" }) : null,
1198
+ notes.error ? /* @__PURE__ */ jsx13("p", { role: "alert", children: notes.error }) : null,
1199
+ !notes.loading && !notes.error && (notes.data?.notes.length ?? 0) === 0 ? /* @__PURE__ */ jsx13("p", { className: "muted", children: "No notes yet." }) : null,
1200
+ (notes.data?.notes ?? []).map((note) => /* @__PURE__ */ jsxs10("article", { className: "panel", style: { padding: 14 }, children: [
1201
+ /* @__PURE__ */ jsx13("p", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: note.body }),
1202
+ /* @__PURE__ */ jsxs10("p", { className: "muted", style: { margin: "8px 0 0", fontSize: 12 }, children: [
1353
1203
  note.authorEmail ?? note.authorId,
1354
1204
  " \xB7 ",
1355
1205
  new Date(note.createdAt).toLocaleString()
@@ -1366,9 +1216,9 @@ function SharedNotes(props) {
1366
1216
  });
1367
1217
  const path = `/api/admin/network/shared-notes?${query}`;
1368
1218
  const notes = useAdminResource(ctx.getToken, path);
1369
- const [body, setBody] = useState11("");
1370
- const [busy, setBusy] = useState11(false);
1371
- const [error, setError] = useState11(null);
1219
+ const [body, setBody] = useState9("");
1220
+ const [busy, setBusy] = useState9(false);
1221
+ const [error, setError] = useState9(null);
1372
1222
  const submit = async () => {
1373
1223
  const trimmed = body.trim();
1374
1224
  if (!trimmed) return;
@@ -1387,19 +1237,19 @@ function SharedNotes(props) {
1387
1237
  setBusy(false);
1388
1238
  }
1389
1239
  };
1390
- return /* @__PURE__ */ jsxs12("section", { style: { display: "grid", gap: 12 }, children: [
1391
- /* @__PURE__ */ jsxs12("h3", { style: { margin: "8px 0 0" }, children: [
1240
+ return /* @__PURE__ */ jsxs10("section", { style: { display: "grid", gap: 12 }, children: [
1241
+ /* @__PURE__ */ jsxs10("h3", { style: { margin: "8px 0 0" }, children: [
1392
1242
  "Shared with ",
1393
1243
  targetName
1394
1244
  ] }),
1395
- /* @__PURE__ */ jsx15(
1396
- Field5,
1245
+ /* @__PURE__ */ jsx13(
1246
+ Field3,
1397
1247
  {
1398
1248
  label: "Add a shared note",
1399
1249
  hint: `This is written to the record's Notes feed for ${targetName} admins.`,
1400
1250
  error,
1401
- children: /* @__PURE__ */ jsx15(
1402
- Textarea2,
1251
+ children: /* @__PURE__ */ jsx13(
1252
+ Textarea,
1403
1253
  {
1404
1254
  rows: 4,
1405
1255
  value: body,
@@ -1409,13 +1259,13 @@ function SharedNotes(props) {
1409
1259
  )
1410
1260
  }
1411
1261
  ),
1412
- /* @__PURE__ */ jsx15("div", { children: /* @__PURE__ */ jsx15(Button6, { disabled: busy || !body.trim(), onClick: () => void submit(), children: busy ? "Sharing\u2026" : `Share with ${targetName}` }) }),
1413
- notes.loading ? /* @__PURE__ */ jsx15("p", { className: "muted", children: "Loading shared notes\u2026" }) : null,
1414
- notes.error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: notes.error }) : null,
1415
- !notes.loading && !notes.error && (notes.data?.notes.length ?? 0) === 0 ? /* @__PURE__ */ jsx15("p", { className: "muted", children: "No shared notes yet." }) : null,
1416
- (notes.data?.notes ?? []).map((note) => /* @__PURE__ */ jsxs12("article", { className: "panel", style: { padding: 14 }, children: [
1417
- /* @__PURE__ */ jsx15("p", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: note.body }),
1418
- /* @__PURE__ */ jsxs12("p", { className: "muted", style: { margin: "8px 0 0", fontSize: 12 }, children: [
1262
+ /* @__PURE__ */ jsx13("div", { children: /* @__PURE__ */ jsx13(Button4, { disabled: busy || !body.trim(), onClick: () => void submit(), children: busy ? "Sharing\u2026" : `Share with ${targetName}` }) }),
1263
+ notes.loading ? /* @__PURE__ */ jsx13("p", { className: "muted", children: "Loading shared notes\u2026" }) : null,
1264
+ notes.error ? /* @__PURE__ */ jsx13("p", { role: "alert", children: notes.error }) : null,
1265
+ !notes.loading && !notes.error && (notes.data?.notes.length ?? 0) === 0 ? /* @__PURE__ */ jsx13("p", { className: "muted", children: "No shared notes yet." }) : null,
1266
+ (notes.data?.notes ?? []).map((note) => /* @__PURE__ */ jsxs10("article", { className: "panel", style: { padding: 14 }, children: [
1267
+ /* @__PURE__ */ jsx13("p", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: note.body }),
1268
+ /* @__PURE__ */ jsxs10("p", { className: "muted", style: { margin: "8px 0 0", fontSize: 12 }, children: [
1419
1269
  "Shared with ",
1420
1270
  targetName,
1421
1271
  " \xB7 ",
@@ -1426,23 +1276,23 @@ function SharedNotes(props) {
1426
1276
  }
1427
1277
  function NetworkRecordDetail(props) {
1428
1278
  const { ctx, targetId, targetName, leaderName, sharedEnabled, record } = props;
1429
- return /* @__PURE__ */ jsxs12("div", { style: { display: "grid", gap: 14 }, children: [
1430
- /* @__PURE__ */ jsxs12("header", { children: [
1431
- /* @__PURE__ */ jsx15("h2", { style: { margin: 0 }, children: record.name }),
1432
- record.stage ? /* @__PURE__ */ jsx15("span", { className: "badge", style: { marginTop: 8 }, children: record.stage.replaceAll("_", " ") }) : null
1279
+ return /* @__PURE__ */ jsxs10("div", { style: { display: "grid", gap: 14 }, children: [
1280
+ /* @__PURE__ */ jsxs10("header", { children: [
1281
+ /* @__PURE__ */ jsx13("h2", { style: { margin: 0 }, children: record.name }),
1282
+ record.stage ? /* @__PURE__ */ jsx13("span", { className: "badge", style: { marginTop: 8 }, children: record.stage.replaceAll("_", " ") }) : null
1433
1283
  ] }),
1434
- /* @__PURE__ */ jsxs12("dl", { style: { display: "grid", gridTemplateColumns: "minmax(8rem, auto) 1fr", gap: "8px 16px", margin: 0 }, children: [
1435
- Object.entries(record.fields).map(([name, value]) => /* @__PURE__ */ jsxs12("div", { style: { display: "contents" }, children: [
1436
- /* @__PURE__ */ jsx15("dt", { className: "muted", children: name.replaceAll("_", " ") }),
1437
- /* @__PURE__ */ jsx15("dd", { style: { margin: 0, overflowWrap: "anywhere" }, children: displayValue(value) })
1284
+ /* @__PURE__ */ jsxs10("dl", { style: { display: "grid", gridTemplateColumns: "minmax(8rem, auto) 1fr", gap: "8px 16px", margin: 0 }, children: [
1285
+ Object.entries(record.fields).map(([name, value]) => /* @__PURE__ */ jsxs10("div", { style: { display: "contents" }, children: [
1286
+ /* @__PURE__ */ jsx13("dt", { className: "muted", children: name.replaceAll("_", " ") }),
1287
+ /* @__PURE__ */ jsx13("dd", { style: { margin: 0, overflowWrap: "anywhere" }, children: displayValue(value) })
1438
1288
  ] }, name)),
1439
- /* @__PURE__ */ jsxs12("div", { style: { display: "contents" }, children: [
1440
- /* @__PURE__ */ jsx15("dt", { className: "muted", children: "Updated" }),
1441
- /* @__PURE__ */ jsx15("dd", { style: { margin: 0 }, children: new Date(record.updatedAt).toLocaleString() })
1289
+ /* @__PURE__ */ jsxs10("div", { style: { display: "contents" }, children: [
1290
+ /* @__PURE__ */ jsx13("dt", { className: "muted", children: "Updated" }),
1291
+ /* @__PURE__ */ jsx13("dd", { style: { margin: 0 }, children: new Date(record.updatedAt).toLocaleString() })
1442
1292
  ] })
1443
1293
  ] }),
1444
- /* @__PURE__ */ jsxs12("div", { style: { display: "grid", gap: 22 }, children: [
1445
- /* @__PURE__ */ jsx15(
1294
+ /* @__PURE__ */ jsxs10("div", { style: { display: "grid", gap: 22 }, children: [
1295
+ /* @__PURE__ */ jsx13(
1446
1296
  PrivateNotes,
1447
1297
  {
1448
1298
  ctx,
@@ -1451,7 +1301,7 @@ function NetworkRecordDetail(props) {
1451
1301
  leaderName
1452
1302
  }
1453
1303
  ),
1454
- sharedEnabled ? /* @__PURE__ */ jsx15(
1304
+ sharedEnabled ? /* @__PURE__ */ jsx13(
1455
1305
  SharedNotes,
1456
1306
  {
1457
1307
  ctx,
@@ -1465,11 +1315,11 @@ function NetworkRecordDetail(props) {
1465
1315
  }
1466
1316
 
1467
1317
  // src/ui/admin-network-records.tsx
1468
- import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
1318
+ import { jsx as jsx14, jsxs as jsxs11 } from "preact/jsx-runtime";
1469
1319
  function RecordsExplorer(props) {
1470
1320
  const { ctx, target, type, leaderName } = props;
1471
- const [offset, setOffset] = useState12(0);
1472
- const [search, setSearch] = useState12("");
1321
+ const [offset, setOffset] = useState10(0);
1322
+ const [search, setSearch] = useState10("");
1473
1323
  const query = new URLSearchParams({
1474
1324
  targetId: target.id,
1475
1325
  type,
@@ -1486,12 +1336,12 @@ function RecordsExplorer(props) {
1486
1336
  {
1487
1337
  key: "name",
1488
1338
  header: "Name",
1489
- cell: (record) => /* @__PURE__ */ jsx16("a", { href: ctx.href({ recordId: record.id, detailTab: null }), children: record.name })
1339
+ cell: (record) => /* @__PURE__ */ jsx14("a", { href: ctx.href({ recordId: record.id, detailTab: null }), children: record.name })
1490
1340
  },
1491
1341
  {
1492
1342
  key: "stage",
1493
1343
  header: "Stage",
1494
- cell: (record) => record.stage ? /* @__PURE__ */ jsx16("span", { className: "badge", children: record.stage.replaceAll("_", " ") }) : "\u2014"
1344
+ cell: (record) => record.stage ? /* @__PURE__ */ jsx14("span", { className: "badge", children: record.stage.replaceAll("_", " ") }) : "\u2014"
1495
1345
  },
1496
1346
  {
1497
1347
  key: "updatedAt",
@@ -1499,7 +1349,7 @@ function RecordsExplorer(props) {
1499
1349
  cell: (record) => new Date(record.updatedAt).toLocaleDateString()
1500
1350
  }
1501
1351
  ], [ctx]);
1502
- return /* @__PURE__ */ jsx16(
1352
+ return /* @__PURE__ */ jsx14(
1503
1353
  MasterDetail,
1504
1354
  {
1505
1355
  collapseClosedDetail: true,
@@ -1507,14 +1357,14 @@ function RecordsExplorer(props) {
1507
1357
  detailLabel: "Follower record details, private notes, and shared notes",
1508
1358
  detailOpen: Boolean(selected),
1509
1359
  closeHref: ctx.href({ recordId: null, detailTab: null }),
1510
- master: /* @__PURE__ */ jsxs13("div", { style: { display: "grid", gap: 14, padding: "var(--ui-space-4)" }, children: [
1511
- /* @__PURE__ */ jsxs13("h2", { style: { margin: 0, fontSize: 18 }, children: [
1360
+ master: /* @__PURE__ */ jsxs11("div", { style: { display: "grid", gap: 14, padding: "var(--ui-space-4)" }, children: [
1361
+ /* @__PURE__ */ jsxs11("h2", { style: { margin: 0, fontSize: 18 }, children: [
1512
1362
  target.name,
1513
1363
  " \xB7 ",
1514
1364
  type.replaceAll("_", " ")
1515
1365
  ] }),
1516
- /* @__PURE__ */ jsx16(
1517
- DataTable3,
1366
+ /* @__PURE__ */ jsx14(
1367
+ DataTable2,
1518
1368
  {
1519
1369
  manual: true,
1520
1370
  filterable: true,
@@ -1533,7 +1383,7 @@ function RecordsExplorer(props) {
1533
1383
  ariaLabel: `${target.name} ${type} records`
1534
1384
  }
1535
1385
  ),
1536
- /* @__PURE__ */ jsx16(
1386
+ /* @__PURE__ */ jsx14(
1537
1387
  Pagination,
1538
1388
  {
1539
1389
  offset: page.data?.offset ?? offset,
@@ -1548,7 +1398,7 @@ function RecordsExplorer(props) {
1548
1398
  }
1549
1399
  )
1550
1400
  ] }),
1551
- detail: selected ? /* @__PURE__ */ jsx16(
1401
+ detail: selected ? /* @__PURE__ */ jsx14(
1552
1402
  NetworkRecordDetail,
1553
1403
  {
1554
1404
  ctx,
@@ -1565,8 +1415,8 @@ function RecordsExplorer(props) {
1565
1415
  function NetworkRecordsWorkspace(props) {
1566
1416
  const { chapter, ctx } = props;
1567
1417
  const targets = useAdminResource(ctx.getToken, "/api/admin/network/targets");
1568
- const [targetId, setTargetId] = useState12("");
1569
- const [type, setType] = useState12("");
1418
+ const [targetId, setTargetId] = useState10("");
1419
+ const [type, setType] = useState10("");
1570
1420
  const target = targets.data?.targets.find((candidate) => candidate.id === targetId) ?? targets.data?.targets[0];
1571
1421
  useEffect7(() => {
1572
1422
  if (target && target.id !== targetId) setTargetId(target.id);
@@ -1575,16 +1425,16 @@ function NetworkRecordsWorkspace(props) {
1575
1425
  const first = target?.types[0] ?? "";
1576
1426
  if (target && !target.types.includes(type)) setType(first);
1577
1427
  }, [target, type]);
1578
- if (targets.loading) return /* @__PURE__ */ jsx16(AdminNote, { children: "Loading follower records\u2026" });
1579
- if (targets.error || !targets.data) return /* @__PURE__ */ jsxs13(AdminNote, { children: [
1428
+ if (targets.loading) return /* @__PURE__ */ jsx14(AdminNote, { children: "Loading follower records\u2026" });
1429
+ if (targets.error || !targets.data) return /* @__PURE__ */ jsxs11(AdminNote, { children: [
1580
1430
  "Could not load followers",
1581
1431
  targets.error ? `: ${targets.error}` : "",
1582
1432
  "."
1583
1433
  ] });
1584
- if (!target) return /* @__PURE__ */ jsx16(AdminPage, { children: /* @__PURE__ */ jsx16(Panel, { title: "Follower records", children: /* @__PURE__ */ jsx16("p", { className: "muted", children: "No followers are configured." }) }) });
1585
- return /* @__PURE__ */ jsxs13(AdminPage, { children: [
1586
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 12, flexWrap: "wrap", alignItems: "end" }, children: [
1587
- /* @__PURE__ */ jsx16(Field6, { label: "Chapter", style: { minWidth: 240 }, children: /* @__PURE__ */ jsx16(
1434
+ if (!target) return /* @__PURE__ */ jsx14(AdminPage, { children: /* @__PURE__ */ jsx14(Panel, { title: "Follower records", children: /* @__PURE__ */ jsx14("p", { className: "muted", children: "No followers are configured." }) }) });
1435
+ return /* @__PURE__ */ jsxs11(AdminPage, { children: [
1436
+ /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 12, flexWrap: "wrap", alignItems: "end" }, children: [
1437
+ /* @__PURE__ */ jsx14(Field4, { label: "Chapter", style: { minWidth: 240 }, children: /* @__PURE__ */ jsx14(
1588
1438
  Select3,
1589
1439
  {
1590
1440
  value: target.id,
@@ -1596,7 +1446,7 @@ function NetworkRecordsWorkspace(props) {
1596
1446
  }
1597
1447
  }
1598
1448
  ) }),
1599
- /* @__PURE__ */ jsx16(Field6, { label: "Record type", style: { minWidth: 180 }, children: /* @__PURE__ */ jsx16(
1449
+ /* @__PURE__ */ jsx14(Field4, { label: "Record type", style: { minWidth: 180 }, children: /* @__PURE__ */ jsx14(
1600
1450
  Select3,
1601
1451
  {
1602
1452
  value: type,
@@ -1608,7 +1458,7 @@ function NetworkRecordsWorkspace(props) {
1608
1458
  }
1609
1459
  ) })
1610
1460
  ] }),
1611
- type ? /* @__PURE__ */ jsx16(
1461
+ type ? /* @__PURE__ */ jsx14(
1612
1462
  RecordsExplorer,
1613
1463
  {
1614
1464
  ctx,
@@ -1617,7 +1467,7 @@ function NetworkRecordsWorkspace(props) {
1617
1467
  leaderName: chapter.name
1618
1468
  },
1619
1469
  `${target.id}:${type}`
1620
- ) : /* @__PURE__ */ jsx16(Panel, { children: /* @__PURE__ */ jsx16("p", { className: "muted", children: "This follower has no browsable record types configured." }) })
1470
+ ) : /* @__PURE__ */ jsx14(Panel, { children: /* @__PURE__ */ jsx14("p", { className: "muted", children: "This follower has no browsable record types configured." }) })
1621
1471
  ] });
1622
1472
  }
1623
1473
  function networkRecordsWorkspace(chapter) {
@@ -1625,60 +1475,60 @@ function networkRecordsWorkspace(chapter) {
1625
1475
  id: "network",
1626
1476
  label: chapter.copy.admin.workspaces.network,
1627
1477
  defaultViewId: "records",
1628
- render: (ctx) => /* @__PURE__ */ jsx16(NetworkRecordsWorkspace, { chapter, ctx })
1478
+ render: (ctx) => /* @__PURE__ */ jsx14(NetworkRecordsWorkspace, { chapter, ctx })
1629
1479
  };
1630
1480
  }
1631
1481
 
1632
1482
  // src/ui/admin-portfolio.tsx
1633
1483
  import { StatBand as StatBand2, StepPipeline as StepPipeline2 } from "@odla-ai/ui/components";
1634
- import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
1484
+ import { jsx as jsx15, jsxs as jsxs12 } from "preact/jsx-runtime";
1635
1485
  function LeaderNetworkOverview({ ctx }) {
1636
1486
  const copy = useChapterCopy().admin.network;
1637
1487
  const { data, loading, error } = useAdminResource(
1638
1488
  ctx.getToken,
1639
1489
  "/api/admin/network/rollup"
1640
1490
  );
1641
- if (loading) return /* @__PURE__ */ jsx17(AdminNote, { children: copy.loadingRollup });
1642
- if (error || !data) return /* @__PURE__ */ jsxs14(AdminNote, { children: [
1491
+ if (loading) return /* @__PURE__ */ jsx15(AdminNote, { children: copy.loadingRollup });
1492
+ if (error || !data) return /* @__PURE__ */ jsxs12(AdminNote, { children: [
1643
1493
  copy.loadRollupFailed,
1644
1494
  error ? `: ${error}` : "",
1645
1495
  "."
1646
1496
  ] });
1647
- if (data.configured === 0) return /* @__PURE__ */ jsx17(AdminPage, { children: /* @__PURE__ */ jsx17(Panel, { title: copy.overview, children: /* @__PURE__ */ jsx17("p", { className: "muted", children: copy.noFollowers }) }) });
1497
+ if (data.configured === 0) return /* @__PURE__ */ jsx15(AdminPage, { children: /* @__PURE__ */ jsx15(Panel, { title: copy.overview, children: /* @__PURE__ */ jsx15("p", { className: "muted", children: copy.noFollowers }) }) });
1648
1498
  const stats = [
1649
1499
  { value: data.configured.toLocaleString(), label: copy.configuredFollowers },
1650
1500
  { value: data.available.toLocaleString(), label: copy.reachableFollowers },
1651
1501
  { value: data.totalRecords.toLocaleString(), label: copy.recordsAcrossFollowers }
1652
1502
  ];
1653
1503
  const steps = data.types.map((type) => ({
1654
- icon: /* @__PURE__ */ jsx17("span", { style: { fontSize: 22, fontWeight: 700 }, children: type.total }),
1504
+ icon: /* @__PURE__ */ jsx15("span", { style: { fontSize: 22, fontWeight: 700 }, children: type.total }),
1655
1505
  title: type.type.replaceAll("_", " "),
1656
1506
  description: Object.entries(type.stages).filter(([, count]) => count > 0).map(([stage, count]) => `${stage.replaceAll("_", " ")} ${count}`).join(" \xB7 ") || copy.noRecordTotals
1657
1507
  }));
1658
- return /* @__PURE__ */ jsxs14(AdminPage, { children: [
1659
- /* @__PURE__ */ jsx17(StatBand2, { stats }),
1660
- /* @__PURE__ */ jsx17(Panel, { title: copy.followers, children: /* @__PURE__ */ jsx17("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 10 }, children: data.targets.map((target) => /* @__PURE__ */ jsxs14("li", { style: { display: "flex", gap: 12, alignItems: "baseline", flexWrap: "wrap" }, children: [
1661
- /* @__PURE__ */ jsx17("strong", { style: { minWidth: 180 }, children: target.name }),
1662
- /* @__PURE__ */ jsx17("span", { className: "badge", children: target.available ? copy.available : copy.unavailable }),
1663
- target.error ? /* @__PURE__ */ jsx17("span", { className: "muted", children: target.error }) : null,
1664
- /* @__PURE__ */ jsx17("a", { href: target.url, target: "_blank", rel: "noreferrer", style: { marginLeft: "auto" }, children: target.url })
1508
+ return /* @__PURE__ */ jsxs12(AdminPage, { children: [
1509
+ /* @__PURE__ */ jsx15(StatBand2, { stats }),
1510
+ /* @__PURE__ */ jsx15(Panel, { title: copy.followers, children: /* @__PURE__ */ jsx15("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "grid", gap: 10 }, children: data.targets.map((target) => /* @__PURE__ */ jsxs12("li", { style: { display: "flex", gap: 12, alignItems: "baseline", flexWrap: "wrap" }, children: [
1511
+ /* @__PURE__ */ jsx15("strong", { style: { minWidth: 180 }, children: target.name }),
1512
+ /* @__PURE__ */ jsx15("span", { className: "badge", children: target.available ? copy.available : copy.unavailable }),
1513
+ target.error ? /* @__PURE__ */ jsx15("span", { className: "muted", children: target.error }) : null,
1514
+ /* @__PURE__ */ jsx15("a", { href: target.url, target: "_blank", rel: "noreferrer", style: { marginLeft: "auto" }, children: target.url })
1665
1515
  ] }, target.id)) }) }),
1666
- /* @__PURE__ */ jsx17(Panel, { title: copy.recordTotals, children: steps.length ? /* @__PURE__ */ jsx17(StepPipeline2, { ariaLabel: copy.recordTotals, steps }) : /* @__PURE__ */ jsx17("p", { className: "muted", children: copy.noRecordTotals }) })
1516
+ /* @__PURE__ */ jsx15(Panel, { title: copy.recordTotals, children: steps.length ? /* @__PURE__ */ jsx15(StepPipeline2, { ariaLabel: copy.recordTotals, steps }) : /* @__PURE__ */ jsx15("p", { className: "muted", children: copy.noRecordTotals }) })
1667
1517
  ] });
1668
1518
  }
1669
1519
 
1670
1520
  // src/ui/admin-admission.tsx
1671
- import { useState as useState13 } from "preact/hooks";
1672
- import { jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
1521
+ import { useState as useState11 } from "preact/hooks";
1522
+ import { jsx as jsx16, jsxs as jsxs13 } from "preact/jsx-runtime";
1673
1523
  function AdmissionGrantsWorkspace(props) {
1674
1524
  const copy = useChapterCopy().admin.admission;
1675
1525
  const resource = useAdminResource(props.getToken, "/api/admin/admission-grants");
1676
- const [email, setEmail] = useState13("");
1677
- const [decision, setDecision] = useState13("waive_interview");
1678
- const [note, setNote] = useState13("");
1679
- const [expires, setExpires] = useState13("");
1680
- const [busy, setBusy] = useState13(false);
1681
- const [error, setError] = useState13(null);
1526
+ const [email, setEmail] = useState11("");
1527
+ const [decision, setDecision] = useState11("waive_interview");
1528
+ const [note, setNote] = useState11("");
1529
+ const [expires, setExpires] = useState11("");
1530
+ const [busy, setBusy] = useState11(false);
1531
+ const [error, setError] = useState11(null);
1682
1532
  const submit = async (event) => {
1683
1533
  event.preventDefault();
1684
1534
  setBusy(true);
@@ -1715,48 +1565,48 @@ function AdmissionGrantsWorkspace(props) {
1715
1565
  setBusy(false);
1716
1566
  }
1717
1567
  };
1718
- return /* @__PURE__ */ jsxs15(AdminPage, { children: [
1719
- /* @__PURE__ */ jsxs15(Panel, { title: copy.title, children: [
1720
- /* @__PURE__ */ jsx18("p", { className: "muted", style: { margin: 0 }, children: copy.description }),
1721
- /* @__PURE__ */ jsxs15("form", { onSubmit: (event) => void submit(event), style: { display: "grid", gap: 12, gridTemplateColumns: "minmax(220px,2fr) minmax(180px,1fr) minmax(160px,1fr)" }, children: [
1722
- /* @__PURE__ */ jsxs15("label", { children: [
1568
+ return /* @__PURE__ */ jsxs13(AdminPage, { children: [
1569
+ /* @__PURE__ */ jsxs13(Panel, { title: copy.title, children: [
1570
+ /* @__PURE__ */ jsx16("p", { className: "muted", style: { margin: 0 }, children: copy.description }),
1571
+ /* @__PURE__ */ jsxs13("form", { onSubmit: (event) => void submit(event), style: { display: "grid", gap: 12, gridTemplateColumns: "minmax(220px,2fr) minmax(180px,1fr) minmax(160px,1fr)" }, children: [
1572
+ /* @__PURE__ */ jsxs13("label", { children: [
1723
1573
  copy.email,
1724
- /* @__PURE__ */ jsx18("input", { required: true, type: "email", value: email, onInput: (event) => setEmail(event.currentTarget.value) })
1574
+ /* @__PURE__ */ jsx16("input", { required: true, type: "email", value: email, onInput: (event) => setEmail(event.currentTarget.value) })
1725
1575
  ] }),
1726
- /* @__PURE__ */ jsxs15("label", { children: [
1576
+ /* @__PURE__ */ jsxs13("label", { children: [
1727
1577
  copy.decision,
1728
- /* @__PURE__ */ jsxs15("select", { value: decision, onChange: (event) => setDecision(event.currentTarget.value), children: [
1729
- /* @__PURE__ */ jsx18("option", { value: "waive_interview", children: copy.waive }),
1730
- /* @__PURE__ */ jsx18("option", { value: "require_interview", children: copy.require })
1578
+ /* @__PURE__ */ jsxs13("select", { value: decision, onChange: (event) => setDecision(event.currentTarget.value), children: [
1579
+ /* @__PURE__ */ jsx16("option", { value: "waive_interview", children: copy.waive }),
1580
+ /* @__PURE__ */ jsx16("option", { value: "require_interview", children: copy.require })
1731
1581
  ] })
1732
1582
  ] }),
1733
- /* @__PURE__ */ jsxs15("label", { children: [
1583
+ /* @__PURE__ */ jsxs13("label", { children: [
1734
1584
  copy.expires,
1735
- /* @__PURE__ */ jsx18("input", { type: "date", value: expires, onInput: (event) => setExpires(event.currentTarget.value) })
1585
+ /* @__PURE__ */ jsx16("input", { type: "date", value: expires, onInput: (event) => setExpires(event.currentTarget.value) })
1736
1586
  ] }),
1737
- /* @__PURE__ */ jsxs15("label", { style: { gridColumn: "1 / -1" }, children: [
1587
+ /* @__PURE__ */ jsxs13("label", { style: { gridColumn: "1 / -1" }, children: [
1738
1588
  copy.note,
1739
- /* @__PURE__ */ jsx18("input", { value: note, maxLength: 2e3, onInput: (event) => setNote(event.currentTarget.value) })
1589
+ /* @__PURE__ */ jsx16("input", { value: note, maxLength: 2e3, onInput: (event) => setNote(event.currentTarget.value) })
1740
1590
  ] }),
1741
- /* @__PURE__ */ jsx18("button", { className: "btn secondary", type: "submit", disabled: busy, children: copy.add })
1591
+ /* @__PURE__ */ jsx16("button", { className: "btn secondary", type: "submit", disabled: busy, children: copy.add })
1742
1592
  ] }),
1743
- error ? /* @__PURE__ */ jsx18("p", { role: "alert", children: error }) : null
1593
+ error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: error }) : null
1744
1594
  ] }),
1745
- /* @__PURE__ */ jsxs15(Panel, { title: copy.ledger, children: [
1746
- resource.loading ? /* @__PURE__ */ jsx18("p", { className: "muted", children: copy.loading }) : resource.error ? /* @__PURE__ */ jsx18("p", { role: "alert", children: resource.error }) : null,
1747
- /* @__PURE__ */ jsx18("div", { style: { display: "grid", gap: 10 }, children: (resource.data?.grants ?? []).map((grant) => {
1595
+ /* @__PURE__ */ jsxs13(Panel, { title: copy.ledger, children: [
1596
+ resource.loading ? /* @__PURE__ */ jsx16("p", { className: "muted", children: copy.loading }) : resource.error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: resource.error }) : null,
1597
+ /* @__PURE__ */ jsx16("div", { style: { display: "grid", gap: 10 }, children: (resource.data?.grants ?? []).map((grant) => {
1748
1598
  const state = grant.consumedAt ? copy.consumed : grant.revokedAt || !grant.active ? copy.revoked : grant.expiresAt && grant.expiresAt <= Date.now() ? copy.expired : copy.active;
1749
- return /* @__PURE__ */ jsxs15("article", { className: "card", style: { padding: 14 }, children: [
1750
- /* @__PURE__ */ jsx18("strong", { children: grant.email }),
1599
+ return /* @__PURE__ */ jsxs13("article", { className: "card", style: { padding: 14 }, children: [
1600
+ /* @__PURE__ */ jsx16("strong", { children: grant.email }),
1751
1601
  " \xB7 ",
1752
1602
  grant.decision === "waive_interview" ? copy.waive : copy.require,
1753
- /* @__PURE__ */ jsxs15("p", { className: "muted", style: { margin: "6px 0" }, children: [
1603
+ /* @__PURE__ */ jsxs13("p", { className: "muted", style: { margin: "6px 0" }, children: [
1754
1604
  grant.sourceScope === "local" ? copy.local : copy.parent,
1755
1605
  " \xB7 ",
1756
1606
  state,
1757
1607
  grant.note ? ` \xB7 ${grant.note}` : ""
1758
1608
  ] }),
1759
- grant.sourceScope === "local" && state === copy.active ? /* @__PURE__ */ jsx18("button", { className: "btn secondary mini", disabled: busy, onClick: () => void revoke(grant), children: copy.revoke }) : null
1609
+ grant.sourceScope === "local" && state === copy.active ? /* @__PURE__ */ jsx16("button", { className: "btn secondary mini", disabled: busy, onClick: () => void revoke(grant), children: copy.revoke }) : null
1760
1610
  ] }, grant.id);
1761
1611
  }) })
1762
1612
  ] })
@@ -1767,14 +1617,285 @@ function admissionGrantsWorkspace(label = "Admission") {
1767
1617
  id: "admission",
1768
1618
  label,
1769
1619
  defaultViewId: "grants",
1770
- render: (ctx) => /* @__PURE__ */ jsx18(AdmissionGrantsWorkspace, { getToken: ctx.getToken })
1620
+ render: (ctx) => /* @__PURE__ */ jsx16(AdmissionGrantsWorkspace, { getToken: ctx.getToken })
1771
1621
  };
1772
1622
  }
1773
1623
 
1774
- // src/ui/admin-member-content.tsx
1775
- import { useEffect as useEffect8, useState as useState14 } from "preact/hooks";
1624
+ // src/ui/admin-settings-workspace.tsx
1625
+ import { Tabs as Tabs2 } from "@odla-ai/ui/components";
1626
+
1627
+ // src/ui/admin-availability.tsx
1628
+ import { useState as useState12 } from "preact/hooks";
1629
+ import { Button as Button5, Checkbox, Field as Field5, Input } from "@odla-ai/ui/components";
1630
+ import { jsx as jsx17, jsxs as jsxs14 } from "preact/jsx-runtime";
1631
+ function AvailabilityBody({ ctx }) {
1632
+ const copy = useChapterCopy().admin.availability;
1633
+ const { data, loading, error, refresh } = useAdminResource(ctx.getToken, "/api/admin/scheduling");
1634
+ const [draft, setDraft] = useState12(null);
1635
+ const [busy, setBusy] = useState12(false);
1636
+ const [note, setNote] = useState12(null);
1637
+ const [errors, setErrors] = useState12({});
1638
+ const cfg = draft ?? data?.scheduling ?? null;
1639
+ if (loading) return /* @__PURE__ */ jsx17(AdminNote, { children: copy.loading });
1640
+ if (error || !cfg) return /* @__PURE__ */ jsxs14(AdminNote, { children: [
1641
+ copy.loadFailed,
1642
+ error ? `: ${error}` : "",
1643
+ "."
1644
+ ] });
1645
+ const edit = (patch) => setDraft({ ...cfg, ...patch });
1646
+ const toggleDay = (d) => edit({ days: cfg.days.includes(d) ? cfg.days.filter((x) => x !== d) : [...cfg.days, d].sort() });
1647
+ const num = (v, fallback) => Number.isFinite(Number(v)) ? Number(v) : fallback;
1648
+ const save = async () => {
1649
+ setBusy(true);
1650
+ setNote(null);
1651
+ setErrors({});
1652
+ const token = await ctx.getToken();
1653
+ try {
1654
+ const r = await fetch("/api/admin/scheduling", { method: "PUT", headers: { authorization: `Bearer ${token ?? ""}`, "content-type": "application/json" }, body: JSON.stringify(cfg) });
1655
+ const body = await r.json().catch(() => ({}));
1656
+ if (!r.ok) {
1657
+ setErrors(body.errors ?? {});
1658
+ setNote(body.error ?? `save failed (${r.status})`);
1659
+ return;
1660
+ }
1661
+ setDraft(null);
1662
+ refresh();
1663
+ setNote(copy.saved);
1664
+ } catch (e) {
1665
+ setNote(e instanceof Error ? e.message : String(e));
1666
+ } finally {
1667
+ setBusy(false);
1668
+ }
1669
+ };
1670
+ const numField = (key, label) => /* @__PURE__ */ jsx17(Field5, { label, error: errors[key], children: /* @__PURE__ */ jsx17(Input, { type: "number", value: cfg[key], onInput: (e) => edit({ [key]: num(e.target.value, cfg[key]) }) }) });
1671
+ return /* @__PURE__ */ jsx17(AdminPage, { children: /* @__PURE__ */ jsxs14(Panel, { title: copy.title, actions: note ? /* @__PURE__ */ jsx17("span", { className: "muted", children: note }) : void 0, children: [
1672
+ /* @__PURE__ */ jsx17(Field5, { label: copy.days, error: errors.days, children: /* @__PURE__ */ jsx17("div", { style: { display: "flex", gap: 14, flexWrap: "wrap" }, children: copy.dayLabels.map((d, i) => /* @__PURE__ */ jsx17(Checkbox, { label: d, checked: cfg.days.includes(i), onChange: () => toggleDay(i) }, d)) }) }),
1673
+ /* @__PURE__ */ jsxs14("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", gap: 14 }, children: [
1674
+ numField("startHour", copy.startHour),
1675
+ numField("endHour", copy.endHour),
1676
+ numField("slotMinutes", copy.slotMinutes),
1677
+ numField("minNoticeHours", copy.minNoticeHours),
1678
+ numField("windowDays", copy.windowDays),
1679
+ /* @__PURE__ */ jsx17(Field5, { label: copy.timezone, error: errors.timezone, children: /* @__PURE__ */ jsx17(Input, { value: cfg.timezone, onInput: (e) => edit({ timezone: e.target.value }) }) })
1680
+ ] }),
1681
+ /* @__PURE__ */ jsx17(Field5, { label: copy.summaryTemplate, error: errors.summaryTemplate, children: /* @__PURE__ */ jsx17(Input, { value: cfg.summaryTemplate, onInput: (e) => edit({ summaryTemplate: e.target.value }) }) }),
1682
+ /* @__PURE__ */ jsx17("div", { children: /* @__PURE__ */ jsx17(Button5, { disabled: !draft || busy, onClick: () => void save(), children: copy.save }) })
1683
+ ] }) });
1684
+ }
1685
+ function availabilitySection(options = {}) {
1686
+ const { id = "availability", label = "Availability" } = options;
1687
+ return { id, label, render: (ctx) => /* @__PURE__ */ jsx17(AvailabilityBody, { ctx }) };
1688
+ }
1689
+
1690
+ // src/ui/admin-builder-library.tsx
1691
+ import { useEffect as useEffect8, useState as useState13 } from "preact/hooks";
1692
+ import { jsx as jsx18, jsxs as jsxs15 } from "preact/jsx-runtime";
1693
+ var emptyDraft = () => ({ resources: [] });
1694
+ var scopeLabel = (resource) => resource.scope.kind === "chapter" ? `Only ${resource.scope.chapterId}` : resource.scope.kind === "built_not_found" ? "Only Built Not Found" : "Every chapter";
1695
+ function BuilderLibraryAdmin({ ctx, initialData }) {
1696
+ const resource = useAdminResource(ctx.getToken, "/api/admin/builder-library");
1697
+ const [draft, setDraft] = useState13(JSON.stringify(initialData?.local?.document ?? emptyDraft(), null, 2));
1698
+ const [saveError, setSaveError] = useState13(null);
1699
+ const [saving, setSaving] = useState13(false);
1700
+ useEffect8(() => {
1701
+ if (resource.data) setDraft(JSON.stringify(resource.data.local?.document ?? emptyDraft(), null, 2));
1702
+ }, [resource.data]);
1703
+ const data = initialData ?? resource.data;
1704
+ if (!data && resource.loading) return /* @__PURE__ */ jsx18(AdminPage, { children: /* @__PURE__ */ jsx18(AdminNote, { children: "Loading Builder Library\u2026" }) });
1705
+ if (resource.error || !data) return /* @__PURE__ */ jsx18(AdminPage, { children: /* @__PURE__ */ jsxs15(AdminNote, { children: [
1706
+ "Builder Library could not be loaded: ",
1707
+ resource.error ?? "unknown error"
1708
+ ] }) });
1709
+ const save = async () => {
1710
+ setSaveError(null);
1711
+ let document2;
1712
+ try {
1713
+ document2 = JSON.parse(draft);
1714
+ } catch (error) {
1715
+ setSaveError([`JSON is invalid: ${error instanceof Error ? error.message : String(error)}`]);
1716
+ return;
1717
+ }
1718
+ setSaving(true);
1719
+ try {
1720
+ await adminFetch(ctx.getToken, "/api/admin/builder-library", { method: "PUT", body: JSON.stringify({ expectedRevision: data.local?.revision ?? 0, document: document2 }) });
1721
+ resource.refresh();
1722
+ } catch (error) {
1723
+ const structured = error;
1724
+ setSaveError(structured.errors ?? [error instanceof Error ? error.message : String(error)]);
1725
+ } finally {
1726
+ setSaving(false);
1727
+ }
1728
+ };
1729
+ const promote = async (chapterId, resourceId) => {
1730
+ setSaveError(null);
1731
+ try {
1732
+ await adminFetch(ctx.getToken, "/api/admin/builder-library/promote", { method: "POST", body: JSON.stringify({ chapterId, resourceId, expectedRevision: data.local?.revision ?? 0 }) });
1733
+ resource.refresh();
1734
+ } catch (error) {
1735
+ setSaveError([error instanceof Error ? error.message : String(error)]);
1736
+ }
1737
+ };
1738
+ return /* @__PURE__ */ jsxs15(AdminPage, { children: [
1739
+ /* @__PURE__ */ jsxs15(Panel, { children: [
1740
+ /* @__PURE__ */ jsx18("div", { className: "card-label", children: "Builder Library \xB7 private" }),
1741
+ /* @__PURE__ */ jsx18("h2", { children: "References for the agents building sites" }),
1742
+ /* @__PURE__ */ jsx18("p", { children: "This is not member content. Saving a document, Brand asset reference, link, or inspiration here never publishes it to a member page." }),
1743
+ /* @__PURE__ */ jsxs15("div", { className: "stat-band", children: [
1744
+ /* @__PURE__ */ jsxs15("div", { children: [
1745
+ /* @__PURE__ */ jsx18("strong", { children: data.local?.document.resources.length ?? 0 }),
1746
+ /* @__PURE__ */ jsx18("span", { children: "Local resources" })
1747
+ ] }),
1748
+ /* @__PURE__ */ jsxs15("div", { children: [
1749
+ /* @__PURE__ */ jsx18("strong", { children: data.sources.reduce((count, source) => count + source.document.resources.length, 0) }),
1750
+ /* @__PURE__ */ jsx18("span", { children: "Shared in" })
1751
+ ] }),
1752
+ /* @__PURE__ */ jsxs15("div", { children: [
1753
+ /* @__PURE__ */ jsx18("strong", { children: "3" }),
1754
+ /* @__PURE__ */ jsx18("span", { children: "Scopes only" })
1755
+ ] })
1756
+ ] }),
1757
+ /* @__PURE__ */ jsx18(AdminNote, { children: "Visibility is always one chapter, only Built Not Found, or every chapter. Chapters never see sibling libraries." })
1758
+ ] }),
1759
+ data.sources.map((source) => /* @__PURE__ */ jsxs15(Panel, { children: [
1760
+ /* @__PURE__ */ jsxs15("div", { className: "card-label", children: [
1761
+ data.mode === "hub" ? "Chapter material" : "Global material",
1762
+ " \xB7 read only"
1763
+ ] }),
1764
+ /* @__PURE__ */ jsxs15("h2", { children: [
1765
+ source.sourceId,
1766
+ " \xB7 revision ",
1767
+ source.revision
1768
+ ] }),
1769
+ source.document.resources.length === 0 ? /* @__PURE__ */ jsx18(AdminNote, { children: "No resources delivered." }) : /* @__PURE__ */ jsx18("div", { className: "data-list", children: source.document.resources.map((item) => /* @__PURE__ */ jsxs15("article", { className: "card", children: [
1770
+ /* @__PURE__ */ jsx18("strong", { children: item.title }),
1771
+ /* @__PURE__ */ jsxs15("div", { className: "meeting-note", children: [
1772
+ item.kind,
1773
+ " \xB7 ",
1774
+ item.status,
1775
+ " \xB7 ",
1776
+ scopeLabel(item)
1777
+ ] }),
1778
+ item.summary ? /* @__PURE__ */ jsx18("p", { children: item.summary }) : null,
1779
+ data.mode === "hub" && item.scope.kind === "chapter" ? /* @__PURE__ */ jsx18("button", { className: "btn", type: "button", onClick: () => void promote(source.sourceId, item.id), children: "Make global" }) : null
1780
+ ] }, item.id)) })
1781
+ ] }, source.sourceId)),
1782
+ /* @__PURE__ */ jsxs15(Panel, { children: [
1783
+ /* @__PURE__ */ jsxs15("div", { className: "card-label", children: [
1784
+ data.mode === "hub" ? "Built Not Found" : "This chapter",
1785
+ " \xB7 editable"
1786
+ ] }),
1787
+ /* @__PURE__ */ jsxs15("h2", { children: [
1788
+ "Local library \xB7 revision ",
1789
+ data.local?.revision ?? 0
1790
+ ] }),
1791
+ /* @__PURE__ */ jsx18("p", { className: "meeting-note", children: "Use documents/notes, HTTPS links/inspiration, or canonical Brand book and asset IDs. The server owns revisions, actor history, and timestamps." }),
1792
+ /* @__PURE__ */ jsxs15("label", { className: "field", children: [
1793
+ /* @__PURE__ */ jsx18("span", { children: "Builder resources (JSON)" }),
1794
+ /* @__PURE__ */ jsx18("textarea", { rows: 24, value: draft, disabled: !data.localAuthoring || saving, onInput: (event) => setDraft(event.currentTarget.value), spellcheck: false })
1795
+ ] }),
1796
+ saveError ? /* @__PURE__ */ jsxs15("div", { className: "notice danger", role: "alert", children: [
1797
+ /* @__PURE__ */ jsx18("strong", { children: "Fix these items before saving:" }),
1798
+ /* @__PURE__ */ jsx18("ul", { children: saveError.map((error) => /* @__PURE__ */ jsx18("li", { children: error }, error)) })
1799
+ ] }) : null,
1800
+ /* @__PURE__ */ jsx18("button", { className: "btn primary", type: "button", disabled: !data.localAuthoring || saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save Builder Library" })
1801
+ ] })
1802
+ ] });
1803
+ }
1804
+ function builderLibrarySection() {
1805
+ return { id: "builder-library", label: "Builder Library", render: (ctx) => /* @__PURE__ */ jsx18(BuilderLibraryAdmin, { ctx }) };
1806
+ }
1807
+
1808
+ // src/ui/admin-email.tsx
1809
+ import { useState as useState14 } from "preact/hooks";
1810
+ import { Button as Button6, Checkbox as Checkbox2, DataTable as DataTable3, Field as Field6, Input as Input2, Textarea as Textarea2 } from "@odla-ai/ui/components";
1776
1811
  import { jsx as jsx19, jsxs as jsxs16 } from "preact/jsx-runtime";
1777
- var emptyDraft = () => ({ pages: [], upsellOverrides: [] });
1812
+ var logColumns = (copy) => [
1813
+ { key: "sentAt", header: copy.sentColumn, cell: (r) => new Date(r.sentAt).toLocaleString(), sortAs: "number", sortValue: (r) => r.sentAt },
1814
+ { key: "template", header: copy.templateColumn, cell: (r) => r.template },
1815
+ { key: "to", header: copy.toColumn, cell: (r) => r.to },
1816
+ { key: "status", header: copy.statusColumn, cell: (r) => r.error ? /* @__PURE__ */ jsx19("span", { className: "badge", children: copy.failed }) : r.redirected ? /* @__PURE__ */ jsx19("span", { className: "badge", children: copy.redirected }) : copy.delivered }
1817
+ ];
1818
+ function EmailBody({ ctx }) {
1819
+ const copy = useChapterCopy().admin.email;
1820
+ const cfg = useAdminResource(ctx.getToken, "/api/admin/group/email");
1821
+ const log = useAdminResource(ctx.getToken, "/api/admin/email/log");
1822
+ const [draft, setDraft] = useState14(null);
1823
+ const [busy, setBusy] = useState14(null);
1824
+ const [note, setNote] = useState14(null);
1825
+ const data = draft ?? cfg.data;
1826
+ if (cfg.loading) return /* @__PURE__ */ jsx19(AdminNote, { children: copy.loading });
1827
+ if (cfg.error || !data) return /* @__PURE__ */ jsxs16(AdminNote, { children: [
1828
+ copy.loadFailed,
1829
+ cfg.error ? `: ${cfg.error}` : "",
1830
+ "."
1831
+ ] });
1832
+ const edit = (patch) => setDraft({ ...data, ...patch });
1833
+ const editTemplate = (key, patch) => edit({ emailTemplates: { ...data.emailTemplates, [key]: { ...data.emailTemplates[key], ...patch } } });
1834
+ const run = async (key, fn) => {
1835
+ setBusy(key);
1836
+ setNote(null);
1837
+ try {
1838
+ await fn();
1839
+ } catch (e) {
1840
+ setNote(e instanceof Error ? e.message : String(e));
1841
+ } finally {
1842
+ setBusy(null);
1843
+ }
1844
+ };
1845
+ const save = () => run("save", async () => {
1846
+ await adminFetch(ctx.getToken, "/api/admin/group/email", { method: "PUT", body: JSON.stringify(data) });
1847
+ setDraft(null);
1848
+ cfg.refresh();
1849
+ setNote(copy.saved);
1850
+ });
1851
+ const test = (template) => run(`test:${template}`, async () => {
1852
+ const r = await adminFetch(ctx.getToken, "/api/admin/email/test", { method: "POST", body: JSON.stringify({ template }) });
1853
+ setNote(r.ok ? formatChapterCopy(copy.sent, {
1854
+ template,
1855
+ address: r.to,
1856
+ redirected: r.redirected ? ` (${copy.redirected})` : ""
1857
+ }) : copy.testFailed);
1858
+ log.refresh();
1859
+ });
1860
+ return /* @__PURE__ */ jsxs16(AdminPage, { children: [
1861
+ /* @__PURE__ */ jsxs16(
1862
+ Panel,
1863
+ {
1864
+ title: copy.delivery,
1865
+ actions: /* @__PURE__ */ jsxs16("span", { className: "muted", children: [
1866
+ data.envName,
1867
+ " \xB7 ",
1868
+ data.transport,
1869
+ data.fromEmail ? ` \xB7 ${data.fromEmail}` : ""
1870
+ ] }),
1871
+ children: [
1872
+ /* @__PURE__ */ jsx19(Field6, { label: copy.notificationAddress, children: /* @__PURE__ */ jsx19(Input2, { value: data.notificationEmail, onInput: (e) => edit({ notificationEmail: e.target.value }) }) }),
1873
+ /* @__PURE__ */ jsx19(Field6, { label: copy.replyTo, children: /* @__PURE__ */ jsx19(Input2, { value: data.replyTo, onInput: (e) => edit({ replyTo: e.target.value }) }) }),
1874
+ /* @__PURE__ */ jsx19(Field6, { label: copy.debugInbox, hint: copy.debugInboxHint, children: /* @__PURE__ */ jsx19(Input2, { value: data.debugEmail, onInput: (e) => edit({ debugEmail: e.target.value }) }) })
1875
+ ]
1876
+ }
1877
+ ),
1878
+ Object.entries(data.emailTemplates).map(([key, t]) => /* @__PURE__ */ jsxs16(Panel, { title: key, actions: /* @__PURE__ */ jsx19(Button6, { variant: "secondary", mini: true, disabled: busy === `test:${key}`, onClick: () => void test(key), children: copy.sendTest }), children: [
1879
+ /* @__PURE__ */ jsx19(Checkbox2, { label: copy.enabled, checked: t.enabled, onChange: (e) => editTemplate(key, { enabled: e.target.checked }) }),
1880
+ /* @__PURE__ */ jsx19(Field6, { label: copy.subject, children: /* @__PURE__ */ jsx19(Input2, { value: t.subject, onInput: (e) => editTemplate(key, { subject: e.target.value }) }) }),
1881
+ /* @__PURE__ */ jsx19(Field6, { label: copy.body, children: /* @__PURE__ */ jsx19(Textarea2, { prose: true, rows: 5, value: t.text, onInput: (e) => editTemplate(key, { text: e.target.value }) }) })
1882
+ ] }, key)),
1883
+ /* @__PURE__ */ jsxs16("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
1884
+ /* @__PURE__ */ jsx19(Button6, { disabled: !draft || busy === "save", onClick: () => void save(), children: copy.save }),
1885
+ note ? /* @__PURE__ */ jsx19("span", { className: "muted", children: note }) : null
1886
+ ] }),
1887
+ /* @__PURE__ */ jsx19(Panel, { title: copy.sendLog, children: /* @__PURE__ */ jsx19(DataTable3, { rows: log.data?.sends ?? [], columns: logColumns(copy), rowKey: (r) => r.id }) })
1888
+ ] });
1889
+ }
1890
+ function emailSection(options = {}) {
1891
+ const { id = "email", label = "Email" } = options;
1892
+ return { id, label, render: (ctx) => /* @__PURE__ */ jsx19(EmailBody, { ctx }) };
1893
+ }
1894
+
1895
+ // src/ui/admin-member-content.tsx
1896
+ import { useEffect as useEffect9, useState as useState15 } from "preact/hooks";
1897
+ import { jsx as jsx20, jsxs as jsxs17 } from "preact/jsx-runtime";
1898
+ var emptyDraft2 = () => ({ pages: [], upsellOverrides: [] });
1778
1899
  function accessLabel(page) {
1779
1900
  return page.audience.kind === "all-members" ? "All members" : `Tiers: ${page.audience.tierIds.join(", ")}`;
1780
1901
  }
@@ -1783,17 +1904,17 @@ function MemberContentAdmin({
1783
1904
  initialData
1784
1905
  }) {
1785
1906
  const resource = useAdminResource(ctx.getToken, "/api/admin/member-content");
1786
- const [draft, setDraft] = useState14(JSON.stringify(initialData?.chapter?.document ?? emptyDraft(), null, 2));
1787
- const [saveError, setSaveError] = useState14(null);
1788
- const [saving, setSaving] = useState14(false);
1789
- useEffect8(() => {
1907
+ const [draft, setDraft] = useState15(JSON.stringify(initialData?.chapter?.document ?? emptyDraft2(), null, 2));
1908
+ const [saveError, setSaveError] = useState15(null);
1909
+ const [saving, setSaving] = useState15(false);
1910
+ useEffect9(() => {
1790
1911
  if (!resource.data) return;
1791
- setDraft(JSON.stringify(resource.data.chapter?.document ?? emptyDraft(), null, 2));
1912
+ setDraft(JSON.stringify(resource.data.chapter?.document ?? emptyDraft2(), null, 2));
1792
1913
  }, [resource.data]);
1793
1914
  const loaded = initialData ?? resource.data;
1794
- if (!loaded && resource.loading) return /* @__PURE__ */ jsx19(AdminPage, { children: /* @__PURE__ */ jsx19(AdminNote, { children: "Loading member content\u2026" }) });
1915
+ if (!loaded && resource.loading) return /* @__PURE__ */ jsx20(AdminPage, { children: /* @__PURE__ */ jsx20(AdminNote, { children: "Loading member content\u2026" }) });
1795
1916
  if (resource.error || !loaded) {
1796
- return /* @__PURE__ */ jsx19(AdminPage, { children: /* @__PURE__ */ jsxs16(AdminNote, { children: [
1917
+ return /* @__PURE__ */ jsx20(AdminPage, { children: /* @__PURE__ */ jsxs17(AdminNote, { children: [
1797
1918
  "Member content could not be loaded: ",
1798
1919
  resource.error ?? "unknown error"
1799
1920
  ] }) });
@@ -1824,35 +1945,35 @@ function MemberContentAdmin({
1824
1945
  setSaving(false);
1825
1946
  }
1826
1947
  };
1827
- return /* @__PURE__ */ jsxs16(AdminPage, { children: [
1828
- /* @__PURE__ */ jsxs16(Panel, { children: [
1829
- /* @__PURE__ */ jsx19("div", { className: "card-label", children: "Member content" }),
1830
- /* @__PURE__ */ jsx19("h2", { children: "One catalog, two clear owners" }),
1831
- /* @__PURE__ */ jsx19("p", { children: "Parent pages are inherited and read-only here. Chapter pages and delegated upsells are edited in the local document. Access uses exact tier IDs; no tier order is assumed." }),
1832
- /* @__PURE__ */ jsxs16("div", { className: "stat-band", children: [
1833
- /* @__PURE__ */ jsxs16("div", { children: [
1834
- /* @__PURE__ */ jsx19("strong", { children: inherited.length }),
1835
- /* @__PURE__ */ jsx19("span", { children: "Inherited pages" })
1948
+ return /* @__PURE__ */ jsxs17(AdminPage, { children: [
1949
+ /* @__PURE__ */ jsxs17(Panel, { children: [
1950
+ /* @__PURE__ */ jsx20("div", { className: "card-label", children: "Member content" }),
1951
+ /* @__PURE__ */ jsx20("h2", { children: "One catalog, two clear owners" }),
1952
+ /* @__PURE__ */ jsx20("p", { children: "Parent pages are inherited and read-only here. Chapter pages and delegated upsells are edited in the local document. Access uses exact tier IDs; no tier order is assumed." }),
1953
+ /* @__PURE__ */ jsxs17("div", { className: "stat-band", children: [
1954
+ /* @__PURE__ */ jsxs17("div", { children: [
1955
+ /* @__PURE__ */ jsx20("strong", { children: inherited.length }),
1956
+ /* @__PURE__ */ jsx20("span", { children: "Inherited pages" })
1836
1957
  ] }),
1837
- /* @__PURE__ */ jsxs16("div", { children: [
1838
- /* @__PURE__ */ jsx19("strong", { children: local.length }),
1839
- /* @__PURE__ */ jsx19("span", { children: "Chapter pages" })
1958
+ /* @__PURE__ */ jsxs17("div", { children: [
1959
+ /* @__PURE__ */ jsx20("strong", { children: local.length }),
1960
+ /* @__PURE__ */ jsx20("span", { children: "Chapter pages" })
1840
1961
  ] }),
1841
- /* @__PURE__ */ jsxs16("div", { children: [
1842
- /* @__PURE__ */ jsx19("strong", { children: data.tiers.length }),
1843
- /* @__PURE__ */ jsx19("span", { children: "Declared tiers" })
1962
+ /* @__PURE__ */ jsxs17("div", { children: [
1963
+ /* @__PURE__ */ jsx20("strong", { children: data.tiers.length }),
1964
+ /* @__PURE__ */ jsx20("span", { children: "Declared tiers" })
1844
1965
  ] })
1845
1966
  ] })
1846
1967
  ] }),
1847
- /* @__PURE__ */ jsxs16(Panel, { children: [
1848
- /* @__PURE__ */ jsx19("div", { className: "card-label", children: "Inherited \xB7 read only" }),
1849
- /* @__PURE__ */ jsxs16("h2", { children: [
1968
+ /* @__PURE__ */ jsxs17(Panel, { children: [
1969
+ /* @__PURE__ */ jsx20("div", { className: "card-label", children: "Inherited \xB7 read only" }),
1970
+ /* @__PURE__ */ jsxs17("h2", { children: [
1850
1971
  "Parent pages ",
1851
1972
  data.parent ? `\xB7 revision ${data.parent.revision}` : ""
1852
1973
  ] }),
1853
- inherited.length === 0 ? /* @__PURE__ */ jsx19(AdminNote, { children: "No Parent pages have been delivered." }) : /* @__PURE__ */ jsx19("div", { className: "data-list", "data-member-content-inherited": true, children: inherited.map((page) => /* @__PURE__ */ jsxs16("article", { className: "card", children: [
1854
- /* @__PURE__ */ jsx19("strong", { children: page.title }),
1855
- /* @__PURE__ */ jsxs16("div", { className: "meeting-note", children: [
1974
+ inherited.length === 0 ? /* @__PURE__ */ jsx20(AdminNote, { children: "No Parent pages have been delivered." }) : /* @__PURE__ */ jsx20("div", { className: "data-list", "data-member-content-inherited": true, children: inherited.map((page) => /* @__PURE__ */ jsxs17("article", { className: "card", children: [
1975
+ /* @__PURE__ */ jsx20("strong", { children: page.title }),
1976
+ /* @__PURE__ */ jsxs17("div", { className: "meeting-note", children: [
1856
1977
  "/",
1857
1978
  page.slug,
1858
1979
  " \xB7 ",
@@ -1860,22 +1981,22 @@ function MemberContentAdmin({
1860
1981
  " \xB7 ",
1861
1982
  accessLabel(page)
1862
1983
  ] }),
1863
- /* @__PURE__ */ jsxs16("div", { className: "meeting-note", children: [
1984
+ /* @__PURE__ */ jsxs17("div", { className: "meeting-note", children: [
1864
1985
  "Upsell: ",
1865
1986
  page.upsell ? `${page.upsell.owner} controlled` : "none"
1866
1987
  ] })
1867
1988
  ] }, page.id)) })
1868
1989
  ] }),
1869
- /* @__PURE__ */ jsxs16(Panel, { children: [
1870
- /* @__PURE__ */ jsx19("div", { className: "card-label", children: "Chapter \xB7 editable" }),
1871
- /* @__PURE__ */ jsxs16("h2", { children: [
1990
+ /* @__PURE__ */ jsxs17(Panel, { children: [
1991
+ /* @__PURE__ */ jsx20("div", { className: "card-label", children: "Chapter \xB7 editable" }),
1992
+ /* @__PURE__ */ jsxs17("h2", { children: [
1872
1993
  "Local document \xB7 revision ",
1873
1994
  data.chapter?.revision ?? 0
1874
1995
  ] }),
1875
- /* @__PURE__ */ jsx19("p", { className: "meeting-note", children: "Use the published MemberContentDocument fields. The server supplies schemaVersion, revision, timestamp, and chapter source; unknown fields and undeclared tiers are rejected." }),
1876
- /* @__PURE__ */ jsxs16("label", { className: "field", children: [
1877
- /* @__PURE__ */ jsx19("span", { children: "Pages and delegated upsells (JSON)" }),
1878
- /* @__PURE__ */ jsx19(
1996
+ /* @__PURE__ */ jsx20("p", { className: "meeting-note", children: "Use the published MemberContentDocument fields. The server supplies schemaVersion, revision, timestamp, and chapter source; unknown fields and undeclared tiers are rejected." }),
1997
+ /* @__PURE__ */ jsxs17("label", { className: "field", children: [
1998
+ /* @__PURE__ */ jsx20("span", { children: "Pages and delegated upsells (JSON)" }),
1999
+ /* @__PURE__ */ jsx20(
1879
2000
  "textarea",
1880
2001
  {
1881
2002
  rows: 24,
@@ -1886,12 +2007,12 @@ function MemberContentAdmin({
1886
2007
  }
1887
2008
  )
1888
2009
  ] }),
1889
- saveError ? /* @__PURE__ */ jsxs16("div", { className: "notice danger", role: "alert", children: [
1890
- /* @__PURE__ */ jsx19("strong", { children: "Fix these items before saving:" }),
1891
- /* @__PURE__ */ jsx19("ul", { children: saveError.map((error) => /* @__PURE__ */ jsx19("li", { children: error }, error)) })
2010
+ saveError ? /* @__PURE__ */ jsxs17("div", { className: "notice danger", role: "alert", children: [
2011
+ /* @__PURE__ */ jsx20("strong", { children: "Fix these items before saving:" }),
2012
+ /* @__PURE__ */ jsx20("ul", { children: saveError.map((error) => /* @__PURE__ */ jsx20("li", { children: error }, error)) })
1892
2013
  ] }) : null,
1893
- /* @__PURE__ */ jsx19("button", { className: "btn primary", type: "button", disabled: !data.localAuthoring || saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save chapter content" }),
1894
- !data.localAuthoring ? /* @__PURE__ */ jsx19(AdminNote, { children: "Local authoring is disabled in the checked-in Chapter config." }) : null
2014
+ /* @__PURE__ */ jsx20("button", { className: "btn primary", type: "button", disabled: !data.localAuthoring || saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save chapter content" }),
2015
+ !data.localAuthoring ? /* @__PURE__ */ jsx20(AdminNote, { children: "Local authoring is disabled in the checked-in Chapter config." }) : null
1895
2016
  ] })
1896
2017
  ] });
1897
2018
  }
@@ -1899,12 +2020,48 @@ function memberContentSection() {
1899
2020
  return {
1900
2021
  id: "member-content",
1901
2022
  label: "Member content",
1902
- render: (ctx) => /* @__PURE__ */ jsx19(MemberContentAdmin, { ctx })
2023
+ render: (ctx) => /* @__PURE__ */ jsx20(MemberContentAdmin, { ctx })
1903
2024
  };
1904
2025
  }
1905
2026
 
2027
+ // src/ui/admin-settings-workspace.tsx
2028
+ import { jsx as jsx21 } from "preact/jsx-runtime";
2029
+ var viewContext = (ctx, viewId, active) => {
2030
+ const route = { workspaceId: ctx.route.workspaceId, viewId, ...active && ctx.route.recordId ? { recordId: ctx.route.recordId } : {}, ...active && ctx.route.detailTab ? { detailTab: ctx.route.detailTab } : {} };
2031
+ const targetFromView = (target) => {
2032
+ if (typeof target === "string") return target;
2033
+ if (target.workspaceId && target.workspaceId !== route.workspaceId) return target;
2034
+ if (target.viewId && target.viewId !== route.viewId) return target;
2035
+ return { ...route, ...target };
2036
+ };
2037
+ return { ...ctx, route, navigate: (target) => ctx.navigate(targetFromView(target)), href: (target) => ctx.href(targetFromView(target)) };
2038
+ };
2039
+ function SettingsWorkspace({ chapter, ctx }) {
2040
+ const copy = chapter.copy.admin;
2041
+ const active = ctx.route.viewId === "email" ? "email" : ctx.route.viewId === "builder-library" && chapter.builderLibrary ? "builder-library" : ctx.route.viewId === "member-content" && chapter.memberContent ? "member-content" : "calendar";
2042
+ const calendar = availabilitySection({ id: "calendar", label: copy.workspaces.calendar });
2043
+ const email = emailSection({ label: copy.workspaces.email });
2044
+ const content = memberContentSection();
2045
+ const library = builderLibrarySection();
2046
+ return /* @__PURE__ */ jsx21(Tabs2, { ariaLabel: copy.workspaces.settingsViewsLabel, value: active, mount: "active", items: [
2047
+ { value: "calendar", label: copy.workspaces.calendar, href: ctx.href({ viewId: "calendar", recordId: null, detailTab: null }), panel: calendar.render(viewContext(ctx, "calendar", active === "calendar")) },
2048
+ { value: "email", label: copy.workspaces.email, href: ctx.href({ viewId: "email", recordId: null, detailTab: null }), panel: email.render(viewContext(ctx, "email", active === "email")) },
2049
+ ...chapter.memberContent ? [{ value: "member-content", label: "Member content", href: ctx.href({ viewId: "member-content", recordId: null, detailTab: null }), panel: content.render(viewContext(ctx, "member-content", active === "member-content")) }] : [],
2050
+ ...chapter.builderLibrary ? [{ value: "builder-library", label: "Builder Library", href: ctx.href({ viewId: "builder-library", recordId: null, detailTab: null }), panel: library.render(viewContext(ctx, "builder-library", active === "builder-library")) }] : []
2051
+ ] });
2052
+ }
2053
+ function LeaderSettingsWorkspace({ chapter, ctx }) {
2054
+ const email = emailSection({ label: chapter.copy.admin.workspaces.email });
2055
+ const library = builderLibrarySection();
2056
+ const active = ctx.route.viewId === "builder-library" && chapter.builderLibrary ? "builder-library" : "email";
2057
+ return /* @__PURE__ */ jsx21(Tabs2, { ariaLabel: chapter.copy.admin.workspaces.settingsViewsLabel, value: active, mount: "active", items: [
2058
+ { value: "email", label: chapter.copy.admin.workspaces.email, href: ctx.href({ viewId: "email", recordId: null, detailTab: null }), panel: email.render(viewContext(ctx, "email", active === "email")) },
2059
+ ...chapter.builderLibrary ? [{ value: "builder-library", label: "Builder Library", href: ctx.href({ viewId: "builder-library", recordId: null, detailTab: null }), panel: library.render(viewContext(ctx, "builder-library", active === "builder-library")) }] : []
2060
+ ] });
2061
+ }
2062
+
1906
2063
  // src/ui/admin-workspaces.tsx
1907
- import { jsx as jsx20 } from "preact/jsx-runtime";
2064
+ import { jsx as jsx22 } from "preact/jsx-runtime";
1908
2065
  var adminViewContext = (ctx, viewId, active) => {
1909
2066
  const route = {
1910
2067
  workspaceId: ctx.route.workspaceId,
@@ -1930,8 +2087,8 @@ function DashboardWorkspace({ chapter, ctx }) {
1930
2087
  const active = ctx.route.viewId === "billing" ? "billing" : "overview";
1931
2088
  const overview = dashboardSection({ id: "overview", label: copy.workspaces.overview });
1932
2089
  const billing = billingSection({ label: copy.workspaces.billing });
1933
- return /* @__PURE__ */ jsx20(
1934
- Tabs2,
2090
+ return /* @__PURE__ */ jsx22(
2091
+ Tabs3,
1935
2092
  {
1936
2093
  ariaLabel: copy.workspaces.dashboardViewsLabel,
1937
2094
  value: active,
@@ -1953,48 +2110,13 @@ function DashboardWorkspace({ chapter, ctx }) {
1953
2110
  }
1954
2111
  );
1955
2112
  }
1956
- function SettingsWorkspace({ chapter, ctx }) {
1957
- const copy = chapter.copy.admin;
1958
- const active = ctx.route.viewId === "email" ? "email" : ctx.route.viewId === "member-content" && chapter.memberContent ? "member-content" : "calendar";
1959
- const calendar = availabilitySection({ id: "calendar", label: copy.workspaces.calendar });
1960
- const email = emailSection({ label: copy.workspaces.email });
1961
- const content = memberContentSection();
1962
- return /* @__PURE__ */ jsx20(
1963
- Tabs2,
1964
- {
1965
- ariaLabel: copy.workspaces.settingsViewsLabel,
1966
- value: active,
1967
- mount: "active",
1968
- items: [
1969
- {
1970
- value: "calendar",
1971
- label: copy.workspaces.calendar,
1972
- href: ctx.href({ viewId: "calendar", recordId: null, detailTab: null }),
1973
- panel: calendar.render(adminViewContext(ctx, "calendar", active === "calendar"))
1974
- },
1975
- {
1976
- value: "email",
1977
- label: copy.workspaces.email,
1978
- href: ctx.href({ viewId: "email", recordId: null, detailTab: null }),
1979
- panel: email.render(adminViewContext(ctx, "email", active === "email"))
1980
- },
1981
- ...chapter.memberContent ? [{
1982
- value: "member-content",
1983
- label: "Member content",
1984
- href: ctx.href({ viewId: "member-content", recordId: null, detailTab: null }),
1985
- panel: content.render(adminViewContext(ctx, "member-content", active === "member-content"))
1986
- }] : []
1987
- ]
1988
- }
1989
- );
1990
- }
1991
2113
  function PeopleWorkspace({ chapter, ctx }) {
1992
2114
  const types = Object.entries(chapter.crm.config.types).filter(([, def]) => (def.workspace ?? "people") === "people");
1993
2115
  const fallback = types[0]?.[0] ?? "person";
1994
2116
  const active = types.some(([type]) => type === ctx.route.viewId) ? ctx.route.viewId : fallback;
1995
2117
  const networkSharing = chapter.network.targets.length > 0;
1996
- return /* @__PURE__ */ jsx20(
1997
- Tabs2,
2118
+ return /* @__PURE__ */ jsx22(
2119
+ Tabs3,
1998
2120
  {
1999
2121
  ariaLabel: chapter.copy.admin.workspaces.collectionsLabel,
2000
2122
  value: active,
@@ -2023,9 +2145,9 @@ function PortfolioWorkspace({ chapter, ctx }) {
2023
2145
  const types = Object.entries(chapter.crm.config.types).filter(([, def]) => def.workspace === "portfolio");
2024
2146
  const fallback = types[0]?.[0] ?? "";
2025
2147
  const active = types.some(([type]) => type === ctx.route.viewId) ? ctx.route.viewId : fallback;
2026
- if (!active) return /* @__PURE__ */ jsx20(LeaderNetworkOverview, { ctx });
2027
- return /* @__PURE__ */ jsx20(
2028
- Tabs2,
2148
+ if (!active) return /* @__PURE__ */ jsx22(LeaderNetworkOverview, { ctx });
2149
+ return /* @__PURE__ */ jsx22(
2150
+ Tabs3,
2029
2151
  {
2030
2152
  ariaLabel: copy.workspaces.portfolioViewsLabel,
2031
2153
  value: active,
@@ -2048,8 +2170,8 @@ function PortfolioWorkspace({ chapter, ctx }) {
2048
2170
  );
2049
2171
  }
2050
2172
  function LeaderDashboardWorkspace({ chapter, ctx }) {
2051
- return /* @__PURE__ */ jsx20(
2052
- Tabs2,
2173
+ return /* @__PURE__ */ jsx22(
2174
+ Tabs3,
2053
2175
  {
2054
2176
  ariaLabel: chapter.copy.admin.workspaces.dashboardViewsLabel,
2055
2177
  value: "overview",
@@ -2058,24 +2180,7 @@ function LeaderDashboardWorkspace({ chapter, ctx }) {
2058
2180
  value: "overview",
2059
2181
  label: chapter.copy.admin.workspaces.overview,
2060
2182
  href: ctx.href({ viewId: "overview", recordId: null, detailTab: null }),
2061
- panel: /* @__PURE__ */ jsx20(LeaderNetworkOverview, { ctx: adminViewContext(ctx, "overview", true) })
2062
- }]
2063
- }
2064
- );
2065
- }
2066
- function LeaderSettingsWorkspace({ chapter, ctx }) {
2067
- const email = emailSection({ label: chapter.copy.admin.workspaces.email });
2068
- return /* @__PURE__ */ jsx20(
2069
- Tabs2,
2070
- {
2071
- ariaLabel: chapter.copy.admin.workspaces.settingsViewsLabel,
2072
- value: "email",
2073
- mount: "active",
2074
- items: [{
2075
- value: "email",
2076
- label: chapter.copy.admin.workspaces.email,
2077
- href: ctx.href({ viewId: "email", recordId: null, detailTab: null }),
2078
- panel: email.render(adminViewContext(ctx, "email", true))
2183
+ panel: /* @__PURE__ */ jsx22(LeaderNetworkOverview, { ctx: adminViewContext(ctx, "overview", true) })
2079
2184
  }]
2080
2185
  }
2081
2186
  );
@@ -2086,7 +2191,7 @@ function defaultAdminWorkspaces(chapter) {
2086
2191
  id: "people",
2087
2192
  label: copy.workspaces.people,
2088
2193
  defaultViewId: Object.keys(chapter.crm.config.types)[0] ?? "person",
2089
- render: (ctx) => /* @__PURE__ */ jsx20(PeopleWorkspace, { chapter, ctx })
2194
+ render: (ctx) => /* @__PURE__ */ jsx22(PeopleWorkspace, { chapter, ctx })
2090
2195
  };
2091
2196
  if (chapter.mode === "hub" && chapter.network.targets.length === 0) return [people];
2092
2197
  if (chapter.mode === "hub") {
@@ -2096,7 +2201,7 @@ function defaultAdminWorkspaces(chapter) {
2096
2201
  id: "dashboard",
2097
2202
  label: copy.workspaces.dashboard,
2098
2203
  defaultViewId: "overview",
2099
- render: (ctx) => /* @__PURE__ */ jsx20(LeaderDashboardWorkspace, { chapter, ctx })
2204
+ render: (ctx) => /* @__PURE__ */ jsx22(LeaderDashboardWorkspace, { chapter, ctx })
2100
2205
  },
2101
2206
  networkRecordsWorkspace(chapter),
2102
2207
  people,
@@ -2104,13 +2209,13 @@ function defaultAdminWorkspaces(chapter) {
2104
2209
  id: "portfolio",
2105
2210
  label: copy.workspaces.portfolio,
2106
2211
  defaultViewId: portfolioTypes[0]?.[0],
2107
- render: (ctx) => /* @__PURE__ */ jsx20(PortfolioWorkspace, { chapter, ctx })
2212
+ render: (ctx) => /* @__PURE__ */ jsx22(PortfolioWorkspace, { chapter, ctx })
2108
2213
  },
2109
2214
  {
2110
2215
  id: "settings",
2111
2216
  label: copy.workspaces.settings,
2112
2217
  defaultViewId: "email",
2113
- render: (ctx) => /* @__PURE__ */ jsx20(LeaderSettingsWorkspace, { chapter, ctx })
2218
+ render: (ctx) => /* @__PURE__ */ jsx22(LeaderSettingsWorkspace, { chapter, ctx })
2114
2219
  }
2115
2220
  ];
2116
2221
  }
@@ -2119,7 +2224,7 @@ function defaultAdminWorkspaces(chapter) {
2119
2224
  id: "dashboard",
2120
2225
  label: copy.workspaces.dashboard,
2121
2226
  defaultViewId: "overview",
2122
- render: (ctx) => /* @__PURE__ */ jsx20(DashboardWorkspace, { chapter, ctx })
2227
+ render: (ctx) => /* @__PURE__ */ jsx22(DashboardWorkspace, { chapter, ctx })
2123
2228
  },
2124
2229
  people,
2125
2230
  admissionGrantsWorkspace(copy.workspaces.admission),
@@ -2127,17 +2232,17 @@ function defaultAdminWorkspaces(chapter) {
2127
2232
  id: "settings",
2128
2233
  label: copy.workspaces.settings,
2129
2234
  defaultViewId: "calendar",
2130
- render: (ctx) => /* @__PURE__ */ jsx20(SettingsWorkspace, { chapter, ctx })
2235
+ render: (ctx) => /* @__PURE__ */ jsx22(SettingsWorkspace, { chapter, ctx })
2131
2236
  }
2132
2237
  ];
2133
2238
  }
2134
2239
 
2135
2240
  // src/ui/admin-frame.tsx
2136
2241
  import { ThemeScope as ThemeScope2 } from "@odla-ai/ui/components";
2137
- import { jsx as jsx21, jsxs as jsxs17 } from "preact/jsx-runtime";
2242
+ import { jsx as jsx23, jsxs as jsxs18 } from "preact/jsx-runtime";
2138
2243
  function AdminTheme(props) {
2139
2244
  const brand = props.chapter?.brand;
2140
- return /* @__PURE__ */ jsx21(ChapterCopyProvider, { copy: props.chapter?.copy, children: /* @__PURE__ */ jsxs17(
2245
+ return /* @__PURE__ */ jsx23(ChapterCopyProvider, { copy: props.chapter?.copy, children: /* @__PURE__ */ jsxs18(
2141
2246
  ThemeScope2,
2142
2247
  {
2143
2248
  ref: props.scopeRef,
@@ -2146,7 +2251,7 @@ function AdminTheme(props) {
2146
2251
  accent: brand?.accent,
2147
2252
  colorScheme: brand?.colorScheme ?? "light",
2148
2253
  children: [
2149
- /* @__PURE__ */ jsx21(BrandStyle, { brand, selector: "[data-chapter-admin]" }),
2254
+ /* @__PURE__ */ jsx23(BrandStyle, { brand, selector: "[data-chapter-admin]" }),
2150
2255
  props.children
2151
2256
  ]
2152
2257
  }
@@ -2166,11 +2271,11 @@ function signInRedirect(basePath, workspaces) {
2166
2271
  }
2167
2272
 
2168
2273
  // src/ui/admin-appearance.ts
2169
- import { useEffect as useEffect9, useState as useState15 } from "preact/hooks";
2274
+ import { useEffect as useEffect10, useState as useState16 } from "preact/hooks";
2170
2275
  import { clerkAppearanceFromTokens } from "@odla-ai/auth-clerk";
2171
2276
  function useScopedClerkAppearance(scope) {
2172
- const [appearance, setAppearance] = useState15();
2173
- useEffect9(() => {
2277
+ const [appearance, setAppearance] = useState16();
2278
+ useEffect10(() => {
2174
2279
  setAppearance(clerkAppearanceFromTokens(scope.current ?? void 0));
2175
2280
  }, [scope]);
2176
2281
  return appearance;
@@ -2201,7 +2306,7 @@ async function loadChapterAdminUser(adapter, apiBase, getToken) {
2201
2306
  }
2202
2307
 
2203
2308
  // src/ui/admin.tsx
2204
- import { jsx as jsx22, jsxs as jsxs18 } from "preact/jsx-runtime";
2309
+ import { jsx as jsx24, jsxs as jsxs19 } from "preact/jsx-runtime";
2205
2310
  function Authed(props) {
2206
2311
  const copy = useChapterCopy().admin;
2207
2312
  const {
@@ -2228,8 +2333,8 @@ function Authed(props) {
2228
2333
  }),
2229
2334
  [getToken, crmBasePath]
2230
2335
  );
2231
- const [state, setState] = useState16({ status: "checking" });
2232
- useEffect10(() => {
2336
+ const [state, setState] = useState17({ status: "checking" });
2337
+ useEffect11(() => {
2233
2338
  let live = true;
2234
2339
  void (async () => {
2235
2340
  try {
@@ -2248,17 +2353,17 @@ function Authed(props) {
2248
2353
  live = false;
2249
2354
  };
2250
2355
  }, [getToken, apiBase, auth]);
2251
- if (state.status === "checking") return /* @__PURE__ */ jsx22(Gate, { brand, children: /* @__PURE__ */ jsx22("p", { style: S.muted, children: copy.auth.checking }) });
2356
+ if (state.status === "checking") return /* @__PURE__ */ jsx24(Gate, { brand, children: /* @__PURE__ */ jsx24("p", { style: S.muted, children: copy.auth.checking }) });
2252
2357
  if (state.status === "denied") {
2253
- return /* @__PURE__ */ jsx22(Gate, { brand, children: /* @__PURE__ */ jsxs18("div", { className: "card", style: S.card, children: [
2254
- /* @__PURE__ */ jsx22("h2", { style: { marginTop: 0 }, children: copy.auth.notAuthorized }),
2255
- /* @__PURE__ */ jsx22("p", { style: S.muted, children: formatChapterCopy(copy.auth.accountNotAuthorized, {
2358
+ return /* @__PURE__ */ jsx24(Gate, { brand, children: /* @__PURE__ */ jsxs19("div", { className: "card", style: S.card, children: [
2359
+ /* @__PURE__ */ jsx24("h2", { style: { marginTop: 0 }, children: copy.auth.notAuthorized }),
2360
+ /* @__PURE__ */ jsx24("p", { style: S.muted, children: formatChapterCopy(copy.auth.accountNotAuthorized, {
2256
2361
  account: state.email ?? copy.auth.thisAccount
2257
2362
  }) }),
2258
- /* @__PURE__ */ jsx22("button", { className: "btn secondary", onClick: () => signOut(), children: copy.auth.signOut })
2363
+ /* @__PURE__ */ jsx24("button", { className: "btn secondary", onClick: () => signOut(), children: copy.auth.signOut })
2259
2364
  ] }) });
2260
2365
  }
2261
- return /* @__PURE__ */ jsx22(
2366
+ return /* @__PURE__ */ jsx24(
2262
2367
  AdminShell,
2263
2368
  {
2264
2369
  workspaces,
@@ -2299,10 +2404,10 @@ function ChapterAdmin(props) {
2299
2404
  const chrome = props.chrome ?? "embedded";
2300
2405
  const auth = props.auth ?? DEFAULT_ADMIN_AUTH;
2301
2406
  const redirect = signInRedirect(basePath, workspaces);
2302
- const [publishableKey, setPublishableKey] = useState16(void 0);
2407
+ const [publishableKey, setPublishableKey] = useState17(void 0);
2303
2408
  const scopeRef = useRef(null);
2304
2409
  const appearance = useScopedClerkAppearance(scopeRef);
2305
- useEffect10(() => {
2410
+ useEffect11(() => {
2306
2411
  let live = true;
2307
2412
  void loadChapterAdminConfig(auth, apiBase).then((config) => live && setPublishableKey(config.publishableKey ?? null)).catch(() => live && setPublishableKey(null));
2308
2413
  return () => {
@@ -2311,23 +2416,23 @@ function ChapterAdmin(props) {
2311
2416
  }, [apiBase, auth]);
2312
2417
  let content;
2313
2418
  if (publishableKey === void 0 || publishableKey && !appearance) {
2314
- content = /* @__PURE__ */ jsx22(Gate, { brand, children: /* @__PURE__ */ jsx22("p", { style: S.muted, children: copy.admin.auth.loading }) });
2419
+ content = /* @__PURE__ */ jsx24(Gate, { brand, children: /* @__PURE__ */ jsx24("p", { style: S.muted, children: copy.admin.auth.loading }) });
2315
2420
  } else if (!publishableKey) {
2316
- content = /* @__PURE__ */ jsx22(Gate, { brand, children: /* @__PURE__ */ jsxs18("div", { className: "card", style: S.card, children: [
2317
- /* @__PURE__ */ jsx22("h2", { style: { marginTop: 0 }, children: copy.admin.auth.signInNotConfigured }),
2318
- /* @__PURE__ */ jsx22("p", { style: S.muted, children: copy.admin.auth.missingPublishableKey })
2421
+ content = /* @__PURE__ */ jsx24(Gate, { brand, children: /* @__PURE__ */ jsxs19("div", { className: "card", style: S.card, children: [
2422
+ /* @__PURE__ */ jsx24("h2", { style: { marginTop: 0 }, children: copy.admin.auth.signInNotConfigured }),
2423
+ /* @__PURE__ */ jsx24("p", { style: S.muted, children: copy.admin.auth.missingPublishableKey })
2319
2424
  ] }) });
2320
2425
  } else if (workspaces.length === 0) {
2321
- content = /* @__PURE__ */ jsx22(Gate, { brand, children: /* @__PURE__ */ jsx22("p", { style: S.muted, children: copy.admin.auth.noWorkspaces }) });
2426
+ content = /* @__PURE__ */ jsx24(Gate, { brand, children: /* @__PURE__ */ jsx24("p", { style: S.muted, children: copy.admin.auth.noWorkspaces }) });
2322
2427
  } else {
2323
- content = /* @__PURE__ */ jsxs18(
2428
+ content = /* @__PURE__ */ jsxs19(
2324
2429
  ClerkGate,
2325
2430
  {
2326
2431
  publishableKey,
2327
2432
  appearance,
2328
2433
  afterSignOutUrl: "/",
2329
2434
  children: [
2330
- /* @__PURE__ */ jsx22(SignedOut, { children: /* @__PURE__ */ jsx22(Gate, { brand, tagline: copy.admin.auth.signInTagline, children: /* @__PURE__ */ jsx22(
2435
+ /* @__PURE__ */ jsx24(SignedOut, { children: /* @__PURE__ */ jsx24(Gate, { brand, tagline: copy.admin.auth.signInTagline, children: /* @__PURE__ */ jsx24(
2331
2436
  SignIn,
2332
2437
  {
2333
2438
  routing: "hash",
@@ -2335,7 +2440,7 @@ function ChapterAdmin(props) {
2335
2440
  signUpForceRedirectUrl: redirect
2336
2441
  }
2337
2442
  ) }) }),
2338
- /* @__PURE__ */ jsx22(SignedIn, { children: /* @__PURE__ */ jsx22(
2443
+ /* @__PURE__ */ jsx24(SignedIn, { children: /* @__PURE__ */ jsx24(
2339
2444
  Authed,
2340
2445
  {
2341
2446
  workspaces,
@@ -2355,7 +2460,7 @@ function ChapterAdmin(props) {
2355
2460
  }
2356
2461
  );
2357
2462
  }
2358
- return /* @__PURE__ */ jsx22(AdminTheme, { chapter: props.chapter, scopeRef, children: content });
2463
+ return /* @__PURE__ */ jsx24(AdminTheme, { chapter: props.chapter, scopeRef, children: content });
2359
2464
  }
2360
2465
 
2361
2466
  // src/ui/admin-defaults.ts
@@ -2364,17 +2469,17 @@ function defaultAdminSections(chapter) {
2364
2469
  }
2365
2470
 
2366
2471
  // src/ui/admin-meetings.tsx
2367
- import { useState as useState17 } from "preact/hooks";
2472
+ import { useState as useState18 } from "preact/hooks";
2368
2473
  import { Button as Button7 } from "@odla-ai/ui/components";
2369
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs19 } from "preact/jsx-runtime";
2474
+ import { Fragment as Fragment4, jsx as jsx25, jsxs as jsxs20 } from "preact/jsx-runtime";
2370
2475
  var when2 = (t) => new Date(t).toLocaleString([], { dateStyle: "medium", timeStyle: "short" });
2371
2476
  function MeetingsBody({ ctx }) {
2372
2477
  const copy = useChapterCopy().admin.meetings;
2373
2478
  const { data, loading, error, refresh } = useAdminResource(ctx.getToken, "/api/admin/meetings?all=1");
2374
- const [busy, setBusy] = useState17(null);
2375
- const [note, setNote] = useState17(null);
2376
- if (loading) return /* @__PURE__ */ jsx23(AdminNote, { children: copy.loading });
2377
- if (error || !data) return /* @__PURE__ */ jsxs19(AdminNote, { children: [
2479
+ const [busy, setBusy] = useState18(null);
2480
+ const [note, setNote] = useState18(null);
2481
+ if (loading) return /* @__PURE__ */ jsx25(AdminNote, { children: copy.loading });
2482
+ if (error || !data) return /* @__PURE__ */ jsxs20(AdminNote, { children: [
2378
2483
  copy.loadFailed,
2379
2484
  error ? `: ${error}` : "",
2380
2485
  "."
@@ -2405,32 +2510,32 @@ function MeetingsBody({ ctx }) {
2405
2510
  }
2406
2511
  void run(id, () => adminFetch(ctx.getToken, `/api/admin/meetings/${id}/reschedule`, { method: "POST", body: JSON.stringify({ startAt }) }));
2407
2512
  };
2408
- return /* @__PURE__ */ jsx23(AdminPage, { children: /* @__PURE__ */ jsx23(Panel, { title: /* @__PURE__ */ jsxs19(Fragment4, { children: [
2513
+ return /* @__PURE__ */ jsx25(AdminPage, { children: /* @__PURE__ */ jsx25(Panel, { title: /* @__PURE__ */ jsxs20(Fragment4, { children: [
2409
2514
  copy.agenda,
2410
2515
  " ",
2411
- /* @__PURE__ */ jsxs19("span", { className: "muted", style: { fontWeight: 400 }, children: [
2516
+ /* @__PURE__ */ jsxs20("span", { className: "muted", style: { fontWeight: 400 }, children: [
2412
2517
  "\xB7 ",
2413
2518
  data.timezone
2414
2519
  ] })
2415
- ] }), actions: note ? /* @__PURE__ */ jsx23("span", { className: "muted", children: note }) : void 0, children: data.meetings.length === 0 ? /* @__PURE__ */ jsx23("p", { className: "muted", style: { margin: 0 }, children: copy.empty }) : /* @__PURE__ */ jsx23("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 12 }, children: data.meetings.map((m) => /* @__PURE__ */ jsxs19("li", { style: { display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap", opacity: m.status === "cancelled" ? 0.55 : 1 }, children: [
2416
- /* @__PURE__ */ jsx23("strong", { style: { minWidth: 170 }, children: when2(m.startAt) }),
2417
- /* @__PURE__ */ jsx23("span", { style: { flex: 1 }, children: m.applicant ? `${m.applicant.name} \xB7 ${m.applicant.email}` : copy.unknown }),
2418
- /* @__PURE__ */ jsx23("span", { className: "badge", children: m.status }),
2419
- m.drift && m.drift !== "none" ? /* @__PURE__ */ jsxs19("span", { className: "badge", children: [
2520
+ ] }), actions: note ? /* @__PURE__ */ jsx25("span", { className: "muted", children: note }) : void 0, children: data.meetings.length === 0 ? /* @__PURE__ */ jsx25("p", { className: "muted", style: { margin: 0 }, children: copy.empty }) : /* @__PURE__ */ jsx25("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 12 }, children: data.meetings.map((m) => /* @__PURE__ */ jsxs20("li", { style: { display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap", opacity: m.status === "cancelled" ? 0.55 : 1 }, children: [
2521
+ /* @__PURE__ */ jsx25("strong", { style: { minWidth: 170 }, children: when2(m.startAt) }),
2522
+ /* @__PURE__ */ jsx25("span", { style: { flex: 1 }, children: m.applicant ? `${m.applicant.name} \xB7 ${m.applicant.email}` : copy.unknown }),
2523
+ /* @__PURE__ */ jsx25("span", { className: "badge", children: m.status }),
2524
+ m.drift && m.drift !== "none" ? /* @__PURE__ */ jsxs20("span", { className: "badge", children: [
2420
2525
  copy.drift,
2421
2526
  ": ",
2422
2527
  m.drift
2423
2528
  ] }) : null,
2424
- m.meetUrl ? /* @__PURE__ */ jsx23("a", { href: m.meetUrl, target: "_blank", rel: "noreferrer", children: copy.meet }) : null,
2425
- m.status === "scheduled" ? /* @__PURE__ */ jsxs19(Fragment4, { children: [
2426
- /* @__PURE__ */ jsx23(Button7, { variant: "secondary", mini: true, disabled: busy === m.id, onClick: () => reschedule(m.id), children: copy.reschedule }),
2427
- /* @__PURE__ */ jsx23(Button7, { variant: "danger", mini: true, disabled: busy === m.id, onClick: () => cancel(m.id), children: copy.cancel })
2529
+ m.meetUrl ? /* @__PURE__ */ jsx25("a", { href: m.meetUrl, target: "_blank", rel: "noreferrer", children: copy.meet }) : null,
2530
+ m.status === "scheduled" ? /* @__PURE__ */ jsxs20(Fragment4, { children: [
2531
+ /* @__PURE__ */ jsx25(Button7, { variant: "secondary", mini: true, disabled: busy === m.id, onClick: () => reschedule(m.id), children: copy.reschedule }),
2532
+ /* @__PURE__ */ jsx25(Button7, { variant: "danger", mini: true, disabled: busy === m.id, onClick: () => cancel(m.id), children: copy.cancel })
2428
2533
  ] }) : null
2429
2534
  ] }, m.id)) }) }) });
2430
2535
  }
2431
2536
  function meetingsSection(options = {}) {
2432
2537
  const { id = "meetings", label = "Meetings" } = options;
2433
- return { id, label, render: (ctx) => /* @__PURE__ */ jsx23(MeetingsBody, { ctx }) };
2538
+ return { id, label, render: (ctx) => /* @__PURE__ */ jsx25(MeetingsBody, { ctx }) };
2434
2539
  }
2435
2540
 
2436
2541
  export {
@@ -2444,10 +2549,8 @@ export {
2444
2549
  adminSectionHref,
2445
2550
  adminFetch,
2446
2551
  useAdminResource,
2447
- availabilitySection,
2448
2552
  billingSection,
2449
2553
  dashboardSection,
2450
- emailSection,
2451
2554
  RecordActions,
2452
2555
  NetworkShareActions,
2453
2556
  applicationLifecycleAdapter,
@@ -2458,6 +2561,10 @@ export {
2458
2561
  LeaderNetworkOverview,
2459
2562
  AdmissionGrantsWorkspace,
2460
2563
  admissionGrantsWorkspace,
2564
+ availabilitySection,
2565
+ BuilderLibraryAdmin,
2566
+ builderLibrarySection,
2567
+ emailSection,
2461
2568
  MemberContentAdmin,
2462
2569
  memberContentSection,
2463
2570
  defaultAdminWorkspaces,
@@ -2467,4 +2574,4 @@ export {
2467
2574
  defaultAdminSections,
2468
2575
  meetingsSection
2469
2576
  };
2470
- //# sourceMappingURL=chunk-SI3JHSEX.js.map
2577
+ //# sourceMappingURL=chunk-4K2Q5JBC.js.map