@odla-ai/chapter 0.61.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/dist/{chunk-PKVHXKGJ.js → chunk-7CVP6VSO.js} +59 -1
- package/dist/chunk-7CVP6VSO.js.map +1 -0
- package/dist/{chunk-24L7FANC.js → chunk-MUUBATZJ.js} +899 -708
- package/dist/chunk-MUUBATZJ.js.map +1 -0
- package/dist/{chunk-RTJKUOFE.js → chunk-ZIYK3OV2.js} +869 -239
- package/dist/chunk-ZIYK3OV2.js.map +1 -0
- package/dist/copy-context-BJUkVUjE.d.ts +364 -0
- package/dist/index.cjs +3839 -3225
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +387 -84
- package/dist/index.d.ts +387 -84
- package/dist/index.js +3842 -3228
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +672 -3
- package/dist/ui/admin/index.js +2 -2
- package/dist/ui/index.d.ts +3 -2
- package/dist/ui/index.js +49 -3
- package/dist/ui/member/index.d.ts +254 -3
- package/dist/ui/member/index.js +48 -2
- package/dist/worker/index.cjs +1495 -376
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +221 -81
- package/dist/worker/index.d.ts +221 -81
- package/dist/worker/index.js +1493 -374
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-24L7FANC.js.map +0 -1
- package/dist/chunk-PKVHXKGJ.js.map +0 -1
- package/dist/chunk-RTJKUOFE.js.map +0 -1
- package/dist/copy-context-nsw2DwSK.d.ts +0 -899
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DEFAULT_JOIN_COPY,
|
|
3
3
|
formatChapterCopy,
|
|
4
4
|
useChapterCopy
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7CVP6VSO.js";
|
|
6
6
|
import {
|
|
7
7
|
collectFormFields
|
|
8
8
|
} from "./chunk-IVXVECKR.js";
|
|
@@ -867,7 +867,7 @@ function MemberRestart(props) {
|
|
|
867
867
|
}
|
|
868
868
|
|
|
869
869
|
// src/ui/members.tsx
|
|
870
|
-
import { useEffect as
|
|
870
|
+
import { useEffect as useEffect8, useState as useState15 } from "preact/hooks";
|
|
871
871
|
|
|
872
872
|
// src/ui/reschedule.tsx
|
|
873
873
|
import { useState as useState8 } from "preact/hooks";
|
|
@@ -1316,7 +1316,8 @@ function MemberContentArea(props) {
|
|
|
1316
1316
|
list.push(page);
|
|
1317
1317
|
result.set(page.navigation.section, list);
|
|
1318
1318
|
}
|
|
1319
|
-
|
|
1319
|
+
const declared = data?.sections ?? [...result.keys()].map((id) => ({ id, label: id }));
|
|
1320
|
+
return declared.filter((section) => result.has(section.id)).map((section) => [section.label ?? "", result.get(section.id)]);
|
|
1320
1321
|
}, [data]);
|
|
1321
1322
|
if (error) return /* @__PURE__ */ jsxs15("p", { className: "meeting-note", role: "alert", children: [
|
|
1322
1323
|
"Member pages could not be loaded: ",
|
|
@@ -1327,8 +1328,8 @@ function MemberContentArea(props) {
|
|
|
1327
1328
|
const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
|
|
1328
1329
|
const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
|
|
1329
1330
|
return /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content", "data-member-content": true, children: [
|
|
1330
|
-
/* @__PURE__ */ jsx16("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs15("section", { className: "chapter-member-content-section", children: [
|
|
1331
|
-
/* @__PURE__ */ jsx16("h2", { children: section }),
|
|
1331
|
+
/* @__PURE__ */ jsx16("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages], index) => /* @__PURE__ */ jsxs15("section", { className: "chapter-member-content-section", children: [
|
|
1332
|
+
section ? /* @__PURE__ */ jsx16("h2", { children: section }) : null,
|
|
1332
1333
|
/* @__PURE__ */ jsx16("ul", { children: pages.map((page) => /* @__PURE__ */ jsx16("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx16(
|
|
1333
1334
|
"button",
|
|
1334
1335
|
{
|
|
@@ -1338,7 +1339,7 @@ function MemberContentArea(props) {
|
|
|
1338
1339
|
children: pageLabel(page)
|
|
1339
1340
|
}
|
|
1340
1341
|
) }, page.id)) })
|
|
1341
|
-
] }, section)) }),
|
|
1342
|
+
] }, `${index}:${section}`)) }),
|
|
1342
1343
|
/* @__PURE__ */ jsxs15("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
|
|
1343
1344
|
/* @__PURE__ */ jsxs15("header", { children: [
|
|
1344
1345
|
/* @__PURE__ */ jsxs15("div", { className: "card-label", children: [
|
|
@@ -1349,7 +1350,7 @@ function MemberContentArea(props) {
|
|
|
1349
1350
|
/* @__PURE__ */ jsx16("h1", { children: selected.title }),
|
|
1350
1351
|
selected.summary ? /* @__PURE__ */ jsx16("p", { children: selected.summary }) : null
|
|
1351
1352
|
] }),
|
|
1352
|
-
selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content-locked", children: [
|
|
1353
|
+
selected.access === "allowed" && selected.kind === "feature" ? /* @__PURE__ */ jsx16(Fragment4, { children: props.renderFeature?.(selected) ?? null }) : selected.access === "allowed" && selected.kind === "placeholder" ? /* @__PURE__ */ jsx16(MemberPlaceholderBody, { page: selected }) : selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content-locked", children: [
|
|
1353
1354
|
selected.teaserMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx16("p", { children: "This page is not included in your current membership." }),
|
|
1354
1355
|
selected.upsell ? /* @__PURE__ */ jsxs15("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
|
|
1355
1356
|
/* @__PURE__ */ jsx16("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
|
|
@@ -1361,14 +1362,598 @@ function MemberContentArea(props) {
|
|
|
1361
1362
|
] })
|
|
1362
1363
|
] });
|
|
1363
1364
|
}
|
|
1365
|
+
var placeholderBadge = (page) => page.placeholder?.badge ?? (page.placeholder?.availableYear ? `Coming in ${page.placeholder.availableYear}` : "Coming soon");
|
|
1366
|
+
function MemberPlaceholderBody({ page }) {
|
|
1367
|
+
return /* @__PURE__ */ jsxs15("div", { className: "chapter-member-placeholder", "data-placeholder": true, children: [
|
|
1368
|
+
/* @__PURE__ */ jsx16("span", { className: "pill", children: placeholderBadge(page) }),
|
|
1369
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: page.bodyMarkdown }) : null,
|
|
1370
|
+
page.placeholder?.actionLabel ? /* @__PURE__ */ jsx16("button", { className: "btn", type: "button", disabled: true, children: page.placeholder.actionLabel }) : null
|
|
1371
|
+
] });
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// src/ui/member-portal.tsx
|
|
1375
|
+
import { useEffect as useEffect7, useMemo as useMemo3, useState as useState14 } from "preact/hooks";
|
|
1376
|
+
|
|
1377
|
+
// src/ui/member-portal-nav.tsx
|
|
1378
|
+
import { ThemeScope } from "@odla-ai/ui/components";
|
|
1379
|
+
|
|
1380
|
+
// src/ui/member-portal-icons.tsx
|
|
1381
|
+
import { jsx as jsx17 } from "preact/jsx-runtime";
|
|
1382
|
+
var PATHS = {
|
|
1383
|
+
home: ["M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z"],
|
|
1384
|
+
course: ["M22 10 12 5 2 10l10 5 10-5z", "M6 12v5c3 2 9 2 12 0v-5"],
|
|
1385
|
+
library: ["M4 19.5V4.5A1.5 1.5 0 0 1 5.5 3H20v18H5.5A1.5 1.5 0 0 1 4 19.5z", "M8 7h8"],
|
|
1386
|
+
deals: ["M3 17l6-6 4 4 8-8", "M14 7h7v7"],
|
|
1387
|
+
training: ["M9 11l3 3 8-8", "M20 12v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9"],
|
|
1388
|
+
events: ["M5 4h14a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z", "M16 2v4M8 2v4M3 10h18"],
|
|
1389
|
+
members: ["M9 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8z", "M2 21a7 7 0 0 1 14 0", "M16 4a4 4 0 0 1 0 8", "M22 21a7 7 0 0 0-4-6.3"],
|
|
1390
|
+
share: ["M12 3v12", "m7 8 5-5 5 5", "M5 14v5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5"],
|
|
1391
|
+
profile: ["M12 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8z", "M4 21a8 8 0 0 1 16 0"],
|
|
1392
|
+
document: ["M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z", "M14 3v6h6", "M8 13h8M8 17h5"],
|
|
1393
|
+
calendar: ["M5 4h14a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z", "M16 2v4M8 2v4M3 10h18"],
|
|
1394
|
+
chat: ["M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12z"],
|
|
1395
|
+
star: ["m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3l-5.6 2.9 1.1-6.2L3 9.6l6.2-.9z"],
|
|
1396
|
+
lock: ["M6 11h12a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2z", "M8 11V7a4 4 0 0 1 8 0v4"],
|
|
1397
|
+
menu: ["M4 7h16M4 12h16M4 17h16"],
|
|
1398
|
+
close: ["M6 6l12 12M18 6 6 18"]
|
|
1399
|
+
};
|
|
1400
|
+
function PortalIcon({ name, size = 18, label }) {
|
|
1401
|
+
return /* @__PURE__ */ jsx17(
|
|
1402
|
+
"svg",
|
|
1403
|
+
{
|
|
1404
|
+
width: size,
|
|
1405
|
+
height: size,
|
|
1406
|
+
viewBox: "0 0 24 24",
|
|
1407
|
+
fill: "none",
|
|
1408
|
+
stroke: "currentColor",
|
|
1409
|
+
"stroke-width": "1.8",
|
|
1410
|
+
"stroke-linecap": "round",
|
|
1411
|
+
"stroke-linejoin": "round",
|
|
1412
|
+
"aria-hidden": label ? void 0 : "true",
|
|
1413
|
+
"aria-label": label,
|
|
1414
|
+
role: label ? "img" : void 0,
|
|
1415
|
+
focusable: "false",
|
|
1416
|
+
children: PATHS[name].map((d) => /* @__PURE__ */ jsx17("path", { d }, d))
|
|
1417
|
+
}
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
// src/ui/member-portal-routing.ts
|
|
1422
|
+
var PROFILE_SEGMENT = "profile";
|
|
1423
|
+
var trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
|
|
1424
|
+
function routeFromLocation(location, routing) {
|
|
1425
|
+
let segment = "";
|
|
1426
|
+
if (routing.mode === "hash") segment = trimSlashes(decodeURIComponent(location.hash.replace(/^#/, "")));
|
|
1427
|
+
else {
|
|
1428
|
+
const base = `/${trimSlashes(routing.basePath)}`;
|
|
1429
|
+
const path = location.pathname;
|
|
1430
|
+
if (path === base || path.startsWith(`${base}/`)) segment = trimSlashes(decodeURIComponent(path.slice(base.length)));
|
|
1431
|
+
}
|
|
1432
|
+
if (!segment) return { kind: "home" };
|
|
1433
|
+
if (segment === PROFILE_SEGMENT) return { kind: "profile" };
|
|
1434
|
+
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(segment) ? { kind: "page", slug: segment } : { kind: "home" };
|
|
1435
|
+
}
|
|
1436
|
+
function hrefFor(route, routing) {
|
|
1437
|
+
const base = `/${trimSlashes(routing.basePath)}`.replace(/^\/$/, "");
|
|
1438
|
+
const segment = route.kind === "home" ? "" : route.kind === "profile" ? PROFILE_SEGMENT : route.slug;
|
|
1439
|
+
if (routing.mode === "hash") return segment ? `${base}/#${segment}` : `${base}/`;
|
|
1440
|
+
return segment ? `${base}/${segment}` : `${base}/`;
|
|
1441
|
+
}
|
|
1442
|
+
var sameRoute = (a, b) => a.kind === b.kind && (a.kind !== "page" || a.slug === b.slug);
|
|
1443
|
+
|
|
1444
|
+
// src/ui/member-portal-nav.tsx
|
|
1445
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
1446
|
+
function PortalAvatar({ me, className }) {
|
|
1447
|
+
return /* @__PURE__ */ jsx18("span", { className: `chapter-portal-avatar${className ? ` ${className}` : ""}`, children: me.photoUrl ? /* @__PURE__ */ jsx18("img", { src: me.photoUrl, alt: "" }) : me.initials });
|
|
1448
|
+
}
|
|
1449
|
+
function navTag(page, copy) {
|
|
1450
|
+
if (page.access === "locked") return { kind: "lock", text: copy.shell.locked };
|
|
1451
|
+
if (page.navigation.tag === "new") return { kind: "new", text: copy.pages.tagNew };
|
|
1452
|
+
if (page.kind === "placeholder") {
|
|
1453
|
+
const year = page.placeholder?.availableYear;
|
|
1454
|
+
return { kind: "soon", text: year ? String(year) : copy.pages.tagSoon };
|
|
1455
|
+
}
|
|
1456
|
+
return null;
|
|
1457
|
+
}
|
|
1458
|
+
function Groups({ content, route, copy, onNavigate }) {
|
|
1459
|
+
const sections = content.sections ?? [...new Set(content.pages.map((page) => page.navigation.section))].map((id) => ({ id, label: id }));
|
|
1460
|
+
const item = (target, icon, label, tag) => /* @__PURE__ */ jsxs16("button", { type: "button", className: "chapter-portal-nav-item", "aria-current": sameRoute(route, target) ? "page" : void 0, onClick: () => onNavigate(target), children: [
|
|
1461
|
+
/* @__PURE__ */ jsx18(PortalIcon, { name: icon }),
|
|
1462
|
+
/* @__PURE__ */ jsx18("span", { children: label }),
|
|
1463
|
+
tag?.kind === "lock" ? /* @__PURE__ */ jsx18("span", { className: "chapter-portal-tag", "data-tag": "lock", title: tag.text, children: /* @__PURE__ */ jsx18(PortalIcon, { name: "lock", size: 12, label: tag.text }) }) : tag ? /* @__PURE__ */ jsx18("span", { className: "chapter-portal-tag", "data-tag": tag.kind, children: tag.text }) : null
|
|
1464
|
+
] });
|
|
1465
|
+
return /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
1466
|
+
/* @__PURE__ */ jsx18("div", { children: item({ kind: "home" }, "home", copy.shell.home) }),
|
|
1467
|
+
sections.map((section) => {
|
|
1468
|
+
const pages = content.pages.filter((page) => page.navigation.section === section.id && !page.navigation.parentId);
|
|
1469
|
+
if (!pages.length) return null;
|
|
1470
|
+
return /* @__PURE__ */ jsxs16("div", { children: [
|
|
1471
|
+
section.label ? /* @__PURE__ */ jsx18("div", { className: "chapter-portal-group-label", children: section.label }) : null,
|
|
1472
|
+
pages.map((page) => /* @__PURE__ */ jsx18("div", { children: item({ kind: "page", slug: page.slug }, page.navigation.icon ?? "document", page.title, navTag(page, copy)) }, page.id))
|
|
1473
|
+
] }, section.id);
|
|
1474
|
+
})
|
|
1475
|
+
] });
|
|
1476
|
+
}
|
|
1477
|
+
function Account(props) {
|
|
1478
|
+
const { me, email, route, copy, adminHref, onNavigate, onSignOut } = props;
|
|
1479
|
+
return /* @__PURE__ */ jsxs16("div", { className: "chapter-portal-account", children: [
|
|
1480
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", className: "chapter-portal-nav-item", "aria-current": route.kind === "profile" ? "page" : void 0, onClick: () => onNavigate({ kind: "profile" }), children: [
|
|
1481
|
+
/* @__PURE__ */ jsx18(PortalAvatar, { me }),
|
|
1482
|
+
/* @__PURE__ */ jsx18("span", { children: copy.shell.yourProfile })
|
|
1483
|
+
] }),
|
|
1484
|
+
/* @__PURE__ */ jsx18("div", { children: copy.shell.signedInAs }),
|
|
1485
|
+
/* @__PURE__ */ jsx18("div", { children: email }),
|
|
1486
|
+
/* @__PURE__ */ jsxs16("div", { style: { marginTop: ".5rem", display: "flex", gap: "1rem", flexWrap: "wrap" }, children: [
|
|
1487
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: "chapter-portal-link", onClick: onSignOut, children: copy.shell.signOut }),
|
|
1488
|
+
adminHref ? /* @__PURE__ */ jsx18("a", { href: adminHref, children: copy.shell.adminConsole }) : null
|
|
1489
|
+
] })
|
|
1490
|
+
] });
|
|
1491
|
+
}
|
|
1492
|
+
function PortalNav(props) {
|
|
1493
|
+
const island = props.sidebarTokens ? void 0 : "ui-invert";
|
|
1494
|
+
return /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
1495
|
+
/* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-side ${island ?? ""}`, role: "complementary", "aria-label": props.copy.shell.navLabel, children: [
|
|
1496
|
+
/* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
|
|
1497
|
+
/* @__PURE__ */ jsx18(Groups, { ...props }),
|
|
1498
|
+
/* @__PURE__ */ jsx18(Account, { ...props })
|
|
1499
|
+
] }),
|
|
1500
|
+
/* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-mobile ${island ?? ""}`, children: [
|
|
1501
|
+
/* @__PURE__ */ jsxs16("div", { className: "chapter-portal-mobile-bar", children: [
|
|
1502
|
+
/* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
|
|
1503
|
+
/* @__PURE__ */ jsx18(
|
|
1504
|
+
"button",
|
|
1505
|
+
{
|
|
1506
|
+
type: "button",
|
|
1507
|
+
className: "chapter-portal-burger",
|
|
1508
|
+
"aria-expanded": props.menuOpen,
|
|
1509
|
+
"aria-label": props.menuOpen ? props.copy.shell.closeMenu : props.copy.shell.openMenu,
|
|
1510
|
+
onClick: props.onToggleMenu,
|
|
1511
|
+
children: /* @__PURE__ */ jsx18(PortalIcon, { name: props.menuOpen ? "close" : "menu", size: 22 })
|
|
1512
|
+
}
|
|
1513
|
+
)
|
|
1514
|
+
] }),
|
|
1515
|
+
props.menuOpen ? /* @__PURE__ */ jsxs16("nav", { className: "chapter-portal-mobile-menu", "aria-label": props.copy.shell.navLabel, children: [
|
|
1516
|
+
/* @__PURE__ */ jsx18(Groups, { ...props }),
|
|
1517
|
+
/* @__PURE__ */ jsx18(Account, { ...props })
|
|
1518
|
+
] }) : null
|
|
1519
|
+
] })
|
|
1520
|
+
] });
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// src/ui/member-portal-pages.tsx
|
|
1524
|
+
import { Markdown as Markdown2 } from "@odla-ai/ui/components";
|
|
1525
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
1526
|
+
var upsellOf = (page, ctx) => {
|
|
1527
|
+
const tierName = page.upsell?.tierName;
|
|
1528
|
+
const href = page.upsell && ctx.upsellHref ? ctx.upsellHref(page.upsell.tierId, page) : void 0;
|
|
1529
|
+
return { tierName, href, cta: page.upsell?.ctaLabel ?? ctx.copy.pages.upgrade };
|
|
1530
|
+
};
|
|
1531
|
+
function LockedPill({ page, ctx }) {
|
|
1532
|
+
const { tierName } = upsellOf(page, ctx);
|
|
1533
|
+
return /* @__PURE__ */ jsxs17("span", { className: "chapter-portal-pill", children: [
|
|
1534
|
+
/* @__PURE__ */ jsx19(PortalIcon, { name: "lock", size: 12 }),
|
|
1535
|
+
tierName ? formatChapterCopy(ctx.copy.pages.includedWith, { tierName }) : ctx.copy.shell.locked
|
|
1536
|
+
] });
|
|
1537
|
+
}
|
|
1538
|
+
function UpgradeLink({ page, ctx, variant }) {
|
|
1539
|
+
const { href, cta } = upsellOf(page, ctx);
|
|
1540
|
+
return href ? /* @__PURE__ */ jsx19("a", { className: "chapter-portal-btn", "data-variant": variant, href, target: "_blank", rel: "noopener", children: cta }) : null;
|
|
1541
|
+
}
|
|
1542
|
+
function LockedScreen({ page, ctx }) {
|
|
1543
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-access": "locked", children: [
|
|
1544
|
+
/* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
|
|
1545
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1546
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1547
|
+
page.teaserMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.teaserMarkdown }) : null,
|
|
1548
|
+
page.upsell?.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.upsell.bodyMarkdown }) : null,
|
|
1549
|
+
/* @__PURE__ */ jsx19("div", { className: "chapter-portal-btns", style: { justifyContent: "center", marginTop: "1.25rem" }, children: /* @__PURE__ */ jsx19(UpgradeLink, { page, ctx }) })
|
|
1550
|
+
] });
|
|
1551
|
+
}
|
|
1552
|
+
function PlaceholderScreen({ page }) {
|
|
1553
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-placeholder": true, children: [
|
|
1554
|
+
/* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", children: placeholderBadge(page) }),
|
|
1555
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1556
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1557
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null,
|
|
1558
|
+
page.placeholder?.actionLabel ? /* @__PURE__ */ jsx19("div", { className: "chapter-portal-btns", style: { justifyContent: "center", marginTop: "1.25rem" }, children: /* @__PURE__ */ jsx19("button", { className: "chapter-portal-btn", type: "button", disabled: true, children: page.placeholder.actionLabel }) }) : null
|
|
1559
|
+
] });
|
|
1560
|
+
}
|
|
1561
|
+
function PortalPage({ page, ctx, features }) {
|
|
1562
|
+
if (page.access === "locked") return /* @__PURE__ */ jsx19(LockedScreen, { page, ctx });
|
|
1563
|
+
if (page.kind === "placeholder") return /* @__PURE__ */ jsx19(PlaceholderScreen, { page });
|
|
1564
|
+
if (page.kind === "feature" && page.feature) {
|
|
1565
|
+
const feature = features[page.feature.name];
|
|
1566
|
+
if (feature) return /* @__PURE__ */ jsx19(Fragment6, { children: feature.page(page, ctx) });
|
|
1567
|
+
}
|
|
1568
|
+
return /* @__PURE__ */ jsxs17("article", { className: "chapter-portal-card", children: [
|
|
1569
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1570
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1571
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null
|
|
1572
|
+
] });
|
|
1573
|
+
}
|
|
1574
|
+
function PortalTile({ page, ctx }) {
|
|
1575
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-tile", "data-access": page.access, children: [
|
|
1576
|
+
/* @__PURE__ */ jsx19(PortalIcon, { name: page.navigation.icon ?? "document", size: 22 }),
|
|
1577
|
+
/* @__PURE__ */ jsx19("h3", { children: page.title }),
|
|
1578
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1579
|
+
page.access === "locked" ? /* @__PURE__ */ jsx19(LockedPill, { page, ctx }) : /* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", style: { alignSelf: "flex-start" }, children: placeholderBadge(page) })
|
|
1580
|
+
] });
|
|
1581
|
+
}
|
|
1582
|
+
function DefaultHome({ ctx, features, slots }) {
|
|
1583
|
+
const panels = ctx.content.pages.filter((page) => page.kind === "feature" && page.feature && features[page.feature.name]?.home);
|
|
1584
|
+
const soon = ctx.content.pages.filter((page) => page.kind === "placeholder");
|
|
1585
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-stack", children: [
|
|
1586
|
+
slots.top?.(ctx) ?? null,
|
|
1587
|
+
panels.map((page) => {
|
|
1588
|
+
const panel = features[page.feature.name].home(page, ctx);
|
|
1589
|
+
if (page.access !== "locked") return /* @__PURE__ */ jsx19("div", { children: panel }, page.id);
|
|
1590
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-locked-wrap", style: { position: "relative" }, children: [
|
|
1591
|
+
/* @__PURE__ */ jsx19("div", { "aria-hidden": "true", inert: true, style: { opacity: 0.35, filter: "grayscale(1)", pointerEvents: "none" }, children: panel }),
|
|
1592
|
+
/* @__PURE__ */ jsx19("div", { style: { position: "absolute", inset: 0, display: "grid", placeItems: "center", padding: "1rem" }, children: /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card", style: { maxWidth: "26rem", textAlign: "center" }, children: [
|
|
1593
|
+
/* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
|
|
1594
|
+
/* @__PURE__ */ jsx19("h3", { children: page.title }),
|
|
1595
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1596
|
+
/* @__PURE__ */ jsx19(UpgradeLink, { page, ctx })
|
|
1597
|
+
] }) })
|
|
1598
|
+
] }, page.id);
|
|
1599
|
+
}),
|
|
1600
|
+
slots.middle?.(ctx) ?? null,
|
|
1601
|
+
soon.length ? /* @__PURE__ */ jsxs17("section", { children: [
|
|
1602
|
+
/* @__PURE__ */ jsx19("h2", { style: { fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400 }, children: ctx.copy.pages.comingToPortal }),
|
|
1603
|
+
/* @__PURE__ */ jsx19("div", { className: "chapter-portal-tiles", children: soon.map((page) => /* @__PURE__ */ jsx19("div", { children: slots.tile?.(page, ctx) ?? /* @__PURE__ */ jsx19(PortalTile, { page, ctx }) }, page.id)) })
|
|
1604
|
+
] }) : null
|
|
1605
|
+
] });
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
// src/ui/member-profile-page.tsx
|
|
1609
|
+
import { useEffect as useEffect6, useState as useState13 } from "preact/hooks";
|
|
1610
|
+
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
1611
|
+
var memberMonth = (at) => new Date(at).toLocaleString("en-US", { month: "long", year: "numeric", timeZone: "UTC" });
|
|
1612
|
+
var startingPrompts = (view) => view.profile.prompts.length ? view.profile.prompts : view.promptChoices.slice(0, view.maxPrompts).map((prompt) => ({ prompt, answer: "" }));
|
|
1613
|
+
function choosePrompt(prompts, prompt, max) {
|
|
1614
|
+
if (prompts.some((entry) => entry.prompt === prompt) || max === 0) return prompts;
|
|
1615
|
+
return prompts.length < max ? [...prompts, { prompt, answer: "" }] : [...prompts.slice(0, max - 1), { prompt, answer: "" }];
|
|
1616
|
+
}
|
|
1617
|
+
async function resizePhoto(file) {
|
|
1618
|
+
const bitmap = await createImageBitmap(file);
|
|
1619
|
+
const side = Math.min(bitmap.width, bitmap.height);
|
|
1620
|
+
const canvas = document.createElement("canvas");
|
|
1621
|
+
canvas.width = canvas.height = 400;
|
|
1622
|
+
canvas.getContext("2d").drawImage(bitmap, (bitmap.width - side) / 2, (bitmap.height - side) / 2, side, side, 0, 0, 400, 400);
|
|
1623
|
+
return new Promise((resolve, reject) => canvas.toBlob((blob) => blob ? resolve(blob) : reject(new Error("encode failed")), "image/jpeg", 0.9));
|
|
1624
|
+
}
|
|
1625
|
+
function MemberProfilePage({ ctx, middle, extras }) {
|
|
1626
|
+
const copy = ctx.copy.profile;
|
|
1627
|
+
const [view, setView] = useState13(null);
|
|
1628
|
+
const [draft, setDraft] = useState13(null);
|
|
1629
|
+
const [status, setStatus] = useState13(null);
|
|
1630
|
+
const [busy, setBusy] = useState13(false);
|
|
1631
|
+
const load = async () => {
|
|
1632
|
+
try {
|
|
1633
|
+
setView(await ctx.api("/api/member/profile"));
|
|
1634
|
+
} catch {
|
|
1635
|
+
setStatus(ctx.copy.shell.loadFailed);
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
useEffect6(() => {
|
|
1639
|
+
void load();
|
|
1640
|
+
}, []);
|
|
1641
|
+
if (!view) return /* @__PURE__ */ jsx20("p", { children: status ?? ctx.copy.shell.loading });
|
|
1642
|
+
const prompts = draft?.prompts ?? startingPrompts(view);
|
|
1643
|
+
const edit = () => setDraft({
|
|
1644
|
+
preferredName: view.profile.preferredName ?? ctx.me.displayName,
|
|
1645
|
+
location: view.profile.location ?? "",
|
|
1646
|
+
introducedByText: view.profile.introducedByText ?? "",
|
|
1647
|
+
prompts: startingPrompts(view)
|
|
1648
|
+
});
|
|
1649
|
+
const save = async () => {
|
|
1650
|
+
if (!draft) return;
|
|
1651
|
+
setBusy(true);
|
|
1652
|
+
try {
|
|
1653
|
+
const next = await ctx.api("/api/member/profile", { method: "PUT", headers: { "content-type": "application/json" }, body: JSON.stringify({
|
|
1654
|
+
expectedRevision: view.revision,
|
|
1655
|
+
preferredName: draft.preferredName,
|
|
1656
|
+
location: draft.location,
|
|
1657
|
+
introducedByText: draft.introducedByText,
|
|
1658
|
+
prompts: draft.prompts
|
|
1659
|
+
}) });
|
|
1660
|
+
setView(next);
|
|
1661
|
+
setDraft(null);
|
|
1662
|
+
setStatus(copy.saved);
|
|
1663
|
+
await ctx.reloadMe();
|
|
1664
|
+
} catch (error) {
|
|
1665
|
+
setStatus(String(error).includes("409") ? copy.conflict : copy.saveFailed);
|
|
1666
|
+
} finally {
|
|
1667
|
+
setBusy(false);
|
|
1668
|
+
}
|
|
1669
|
+
};
|
|
1670
|
+
const upload = async (file) => {
|
|
1671
|
+
if (!file) return;
|
|
1672
|
+
setBusy(true);
|
|
1673
|
+
setStatus(copy.photoUploading);
|
|
1674
|
+
try {
|
|
1675
|
+
if (file.size > 10 * 1024 * 1024) throw new Error("too large");
|
|
1676
|
+
await ctx.api("/api/member/profile/photo", { method: "POST", headers: { "content-type": "image/jpeg" }, body: await resizePhoto(file) });
|
|
1677
|
+
setStatus(null);
|
|
1678
|
+
await ctx.reloadMe();
|
|
1679
|
+
} catch {
|
|
1680
|
+
setStatus(copy.photoFailed);
|
|
1681
|
+
} finally {
|
|
1682
|
+
setBusy(false);
|
|
1683
|
+
}
|
|
1684
|
+
};
|
|
1685
|
+
const remaining = view.promptChoices.filter((choice) => !prompts.some((entry) => entry.prompt === choice));
|
|
1686
|
+
return /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-stack", "data-portal-profile": true, children: [
|
|
1687
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", style: { display: "flex", gap: "1.25rem", alignItems: "center", flexWrap: "wrap" }, children: [
|
|
1688
|
+
/* @__PURE__ */ jsxs18("div", { style: { textAlign: "center" }, children: [
|
|
1689
|
+
/* @__PURE__ */ jsx20(PortalAvatar, { me: ctx.me, className: "chapter-portal-profile-photo" }),
|
|
1690
|
+
view.photos ? /* @__PURE__ */ jsxs18("label", { className: "chapter-portal-btn", "data-variant": "ghost", style: { marginTop: ".6rem", padding: ".35rem .8rem", fontSize: ".78rem" }, children: [
|
|
1691
|
+
ctx.me.photoUrl ? copy.changePhoto : copy.uploadPhoto,
|
|
1692
|
+
/* @__PURE__ */ jsx20("input", { type: "file", accept: "image/jpeg,image/png", hidden: true, disabled: busy, onChange: (event) => void upload(event.currentTarget.files?.[0]) })
|
|
1693
|
+
] }) : null
|
|
1694
|
+
] }),
|
|
1695
|
+
/* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: "12rem" }, children: [
|
|
1696
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: copy.eyebrow }),
|
|
1697
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1698
|
+
"input",
|
|
1699
|
+
{
|
|
1700
|
+
"aria-label": copy.namePlaceholder,
|
|
1701
|
+
placeholder: copy.namePlaceholder,
|
|
1702
|
+
value: draft.preferredName,
|
|
1703
|
+
maxLength: 80,
|
|
1704
|
+
onInput: (event) => setDraft({ ...draft, preferredName: event.currentTarget.value })
|
|
1705
|
+
}
|
|
1706
|
+
) : /* @__PURE__ */ jsx20("h2", { style: { margin: ".2rem 0" }, children: ctx.me.displayName }),
|
|
1707
|
+
/* @__PURE__ */ jsxs18("p", { style: { margin: 0, color: "var(--ui-text-muted)" }, children: [
|
|
1708
|
+
ctx.me.tier && ctx.me.memberSince ? formatChapterCopy(copy.memberSince, { tierName: ctx.me.tier.name, month: memberMonth(ctx.me.memberSince) }) : null,
|
|
1709
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1710
|
+
"input",
|
|
1711
|
+
{
|
|
1712
|
+
"aria-label": copy.locationPlaceholder,
|
|
1713
|
+
placeholder: copy.locationPlaceholder,
|
|
1714
|
+
value: draft.location,
|
|
1715
|
+
maxLength: 80,
|
|
1716
|
+
onInput: (event) => setDraft({ ...draft, location: event.currentTarget.value })
|
|
1717
|
+
}
|
|
1718
|
+
) : ctx.me.location ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
|
|
1719
|
+
" \xB7 ",
|
|
1720
|
+
ctx.me.location
|
|
1721
|
+
] }) : null
|
|
1722
|
+
] })
|
|
1723
|
+
] }),
|
|
1724
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-btns", children: [
|
|
1725
|
+
draft ? /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", disabled: busy, onClick: () => void save(), children: busy ? copy.saving : copy.saveProfile }) : /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", onClick: edit, children: copy.editProfile }),
|
|
1726
|
+
draft ? /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", disabled: busy, onClick: () => setDraft(null), children: copy.cancel }) : null
|
|
1727
|
+
] })
|
|
1728
|
+
] }),
|
|
1729
|
+
status ? /* @__PURE__ */ jsx20("p", { role: "status", children: status }) : null,
|
|
1730
|
+
view.maxPrompts > 0 && view.promptChoices.length ? /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1731
|
+
/* @__PURE__ */ jsx20("h2", { children: copy.promptsTitle }),
|
|
1732
|
+
/* @__PURE__ */ jsx20("p", { style: { color: "var(--ui-text-muted)" }, children: formatChapterCopy(copy.promptsNote, { count: String(view.maxPrompts) }) }),
|
|
1733
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-tiles", children: prompts.map((entry, index) => /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1734
|
+
/* @__PURE__ */ jsx20("q", { children: entry.prompt }),
|
|
1735
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1736
|
+
"textarea",
|
|
1737
|
+
{
|
|
1738
|
+
"aria-label": entry.prompt,
|
|
1739
|
+
maxLength: 280,
|
|
1740
|
+
rows: 3,
|
|
1741
|
+
value: entry.answer,
|
|
1742
|
+
onInput: (event) => setDraft({ ...draft, prompts: draft.prompts.map((p, i) => i === index ? { ...p, answer: event.currentTarget.value } : p) })
|
|
1743
|
+
}
|
|
1744
|
+
) : /* @__PURE__ */ jsx20("p", { children: entry.answer || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.answerEmpty }) })
|
|
1745
|
+
] }, entry.prompt)) }),
|
|
1746
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-btns", style: { marginTop: "1rem" }, children: remaining.map((choice) => /* @__PURE__ */ jsx20(
|
|
1747
|
+
"button",
|
|
1748
|
+
{
|
|
1749
|
+
type: "button",
|
|
1750
|
+
className: "chapter-portal-pill",
|
|
1751
|
+
style: { cursor: "pointer", background: "transparent" },
|
|
1752
|
+
onClick: () => {
|
|
1753
|
+
const base = draft ?? { preferredName: view.profile.preferredName ?? ctx.me.displayName, location: view.profile.location ?? "", introducedByText: view.profile.introducedByText ?? "", prompts };
|
|
1754
|
+
setDraft({ ...base, prompts: choosePrompt(base.prompts, choice, view.maxPrompts) });
|
|
1755
|
+
},
|
|
1756
|
+
children: formatChapterCopy(copy.addPrompt, { prompt: choice })
|
|
1757
|
+
},
|
|
1758
|
+
choice
|
|
1759
|
+
)) })
|
|
1760
|
+
] }) : null,
|
|
1761
|
+
middle,
|
|
1762
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1763
|
+
/* @__PURE__ */ jsx20("h2", { children: copy.howYouFoundUs }),
|
|
1764
|
+
view.referredBy ? /* @__PURE__ */ jsxs18("p", { children: [
|
|
1765
|
+
/* @__PURE__ */ jsx20("strong", { children: copy.referredBy }),
|
|
1766
|
+
" \xB7 ",
|
|
1767
|
+
/* @__PURE__ */ jsx20("strong", { children: view.referredBy.name }),
|
|
1768
|
+
" ",
|
|
1769
|
+
/* @__PURE__ */ jsxs18("span", { style: { color: "var(--ui-text-muted)" }, children: [
|
|
1770
|
+
"\xB7 ",
|
|
1771
|
+
copy.referredByNote
|
|
1772
|
+
] })
|
|
1773
|
+
] }) : null,
|
|
1774
|
+
/* @__PURE__ */ jsxs18("label", { style: { display: "block" }, children: [
|
|
1775
|
+
/* @__PURE__ */ jsx20("span", { children: copy.introducedBy }),
|
|
1776
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1777
|
+
"input",
|
|
1778
|
+
{
|
|
1779
|
+
placeholder: copy.introducedByPlaceholder,
|
|
1780
|
+
value: draft.introducedByText,
|
|
1781
|
+
maxLength: 120,
|
|
1782
|
+
onInput: (event) => setDraft({ ...draft, introducedByText: event.currentTarget.value })
|
|
1783
|
+
}
|
|
1784
|
+
) : /* @__PURE__ */ jsx20("p", { children: view.profile.introducedByText || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.introducedByPlaceholder }) })
|
|
1785
|
+
] })
|
|
1786
|
+
] }),
|
|
1787
|
+
extras
|
|
1788
|
+
] });
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// src/ui/member-portal-styles.ts
|
|
1792
|
+
var MEMBER_PORTAL_CSS = `
|
|
1793
|
+
.chapter-portal{display:grid;grid-template-columns:clamp(232px,22vw,272px) minmax(0,1fr);min-height:100vh;background:var(--ui-bg,#f4efe6);color:var(--ui-text,#2f3e34);font-family:var(--ui-font-sans,inherit);line-height:1.55;overflow-x:clip}
|
|
1794
|
+
.chapter-portal *,.chapter-portal *::before,.chapter-portal *::after{box-sizing:border-box}
|
|
1795
|
+
.chapter-portal-side{position:sticky;top:0;height:100vh;overflow-y:auto;display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem 1rem;background:var(--ui-surface,#2f3e34);color:var(--ui-text,#fbf8f2)}
|
|
1796
|
+
.chapter-portal-brand{display:flex;align-items:center;gap:.65rem;padding:0 .5rem;font-family:var(--ui-font-display,inherit);font-size:1.35rem;line-height:1.1;white-space:nowrap}
|
|
1797
|
+
.chapter-portal-brand :where(img,svg){width:30px;height:30px;flex:none}
|
|
1798
|
+
.chapter-portal-group-label{padding:0 .75rem;margin-bottom:.35rem;font-size:.68rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-text-muted,#b8c4bb)}
|
|
1799
|
+
.chapter-portal-nav-item{display:flex;align-items:center;gap:.7rem;width:100%;padding:.55rem .75rem;border:0;border-radius:var(--ui-radius-sm,8px);background:transparent;color:inherit;font:inherit;font-size:.95rem;text-align:left;text-decoration:none;cursor:pointer}
|
|
1800
|
+
.chapter-portal-nav-item:hover{background:color-mix(in srgb,var(--ui-text,#fff) 8%,transparent)}
|
|
1801
|
+
.chapter-portal-nav-item[aria-current=page]{background:color-mix(in srgb,var(--ui-text,#fff) 14%,transparent);font-weight:600}
|
|
1802
|
+
.chapter-portal-nav-item>span:first-of-type{flex:1;min-width:0}
|
|
1803
|
+
.chapter-portal-tag{border:1px solid var(--ui-border,rgba(255,255,255,.2));border-radius:999px;padding:.05rem .5rem;font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ui-text-muted,#b8c4bb)}
|
|
1804
|
+
.chapter-portal-tag[data-tag=new]{border-color:transparent;background:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
|
|
1805
|
+
.chapter-portal-account{margin-top:auto;padding:.75rem;border-top:1px solid var(--ui-border,rgba(255,255,255,.15));font-size:.85rem;color:var(--ui-text-muted,#b8c4bb);overflow-wrap:anywhere}
|
|
1806
|
+
.chapter-portal-account .chapter-portal-nav-item{margin:0 -.75rem .75rem;width:calc(100% + 1.5rem);color:var(--ui-text,#fff)}
|
|
1807
|
+
.chapter-portal-account button.chapter-portal-link,.chapter-portal-account a{display:inline;padding:0;border:0;background:none;color:var(--ui-text,#fff);font:inherit;text-decoration:underline;cursor:pointer}
|
|
1808
|
+
.chapter-portal-avatar{display:inline-grid;place-items:center;flex:none;width:28px;height:28px;border-radius:50%;overflow:hidden;background:var(--ui-accent-soft,rgba(124,184,63,.2));color:var(--ui-text,inherit);font-size:.72rem;font-weight:700;letter-spacing:.04em}
|
|
1809
|
+
.chapter-portal-avatar img{width:100%;height:100%;object-fit:cover}
|
|
1810
|
+
.chapter-portal-main{min-width:0;padding:clamp(1rem,3vw,2.5rem);display:flex;flex-direction:column;gap:1.5rem}
|
|
1811
|
+
.chapter-portal-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
|
|
1812
|
+
.chapter-portal-top h1{margin:0;font-family:var(--ui-font-display,inherit);font-weight:400;font-size:clamp(1.8rem,4vw,2.4rem);line-height:1.1}
|
|
1813
|
+
.chapter-portal-back{padding:0;border:0;background:none;color:var(--ui-text,inherit);font:inherit;font-weight:600;cursor:pointer}
|
|
1814
|
+
.chapter-portal-top-right{display:flex;align-items:center;gap:.75rem;margin-left:auto}
|
|
1815
|
+
.chapter-portal-pill{display:inline-flex;align-items:center;gap:.35rem;border:1px solid var(--ui-border,#e2dccf);border-radius:999px;padding:.2rem .7rem;font-size:.66rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ui-text-muted,#7e8e84);white-space:nowrap}
|
|
1816
|
+
.chapter-portal-me{padding:0;border:0;background:none;cursor:pointer;border-radius:50%}
|
|
1817
|
+
.chapter-portal-me .chapter-portal-avatar{width:40px;height:40px;font-size:.85rem}
|
|
1818
|
+
.chapter-portal-card{background:var(--ui-surface,#fbf8f2);border:1px solid var(--ui-border,#e2dccf);border-radius:var(--ui-radius-lg,14px);padding:clamp(1.1rem,3vw,1.6rem);min-width:0}
|
|
1819
|
+
.chapter-portal-card h2{margin:.4rem 0 .5rem;font-family:var(--ui-font-display,inherit);font-weight:400;font-size:1.6rem;line-height:1.15}
|
|
1820
|
+
.chapter-portal-stack{display:flex;flex-direction:column;gap:1.25rem}
|
|
1821
|
+
.chapter-portal-soon{text-align:center;padding:clamp(2rem,6vw,3.5rem) 1.5rem}
|
|
1822
|
+
.chapter-portal-soon p{max-width:36rem;margin:.5rem auto 0;color:var(--ui-text-muted,#7e8e84)}
|
|
1823
|
+
.chapter-portal-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:1rem}
|
|
1824
|
+
.chapter-portal-tile{display:flex;flex-direction:column;gap:.5rem}
|
|
1825
|
+
.chapter-portal-tile h3{margin:0;font-size:1.05rem}
|
|
1826
|
+
.chapter-portal-tile p{margin:0;color:var(--ui-text-muted,#7e8e84);font-size:.92rem;flex:1}
|
|
1827
|
+
.chapter-portal-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:42px;padding:.6rem 1.2rem;border:1px solid var(--ui-text,#2f3e34);border-radius:999px;background:var(--ui-text,#2f3e34);color:var(--ui-bg,#fbf8f2);font:inherit;font-size:.92rem;font-weight:600;text-decoration:none;cursor:pointer}
|
|
1828
|
+
.chapter-portal-btn[data-variant=ghost]{background:transparent;color:var(--ui-text,#2f3e34)}
|
|
1829
|
+
.chapter-portal-btn[data-variant=accent]{background:var(--ui-accent,#7cb83f);border-color:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
|
|
1830
|
+
.chapter-portal-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
1831
|
+
.chapter-portal-btns{display:flex;flex-wrap:wrap;gap:.6rem}
|
|
1832
|
+
.chapter-portal :where(button,a,input,textarea,select):focus-visible{outline:3px solid var(--ui-focus,var(--ui-accent,#7cb83f));outline-offset:2px}
|
|
1833
|
+
.chapter-portal-mobile{display:none}
|
|
1834
|
+
@media (max-width:860px){
|
|
1835
|
+
.chapter-portal{grid-template-columns:minmax(0,1fr)}
|
|
1836
|
+
.chapter-portal-side{display:none}
|
|
1837
|
+
.chapter-portal-mobile{display:block;margin:calc(-1*clamp(1rem,3vw,2.5rem)) calc(-1*clamp(1rem,3vw,2.5rem)) 0;background:var(--ui-surface,#2f3e34);color:var(--ui-text,#fbf8f2)}
|
|
1838
|
+
.chapter-portal-mobile-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.8rem 1rem}
|
|
1839
|
+
.chapter-portal-burger{display:inline-grid;place-items:center;width:44px;height:44px;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer}
|
|
1840
|
+
.chapter-portal-mobile-menu{display:flex;flex-direction:column;gap:1rem;padding:0 1rem 1.25rem}
|
|
1841
|
+
.chapter-portal-mobile .chapter-portal-brand{font-size:1.15rem;padding:0}
|
|
1842
|
+
}
|
|
1843
|
+
`;
|
|
1844
|
+
|
|
1845
|
+
// src/ui/member-portal-features.tsx
|
|
1846
|
+
var PACKAGED_PORTAL_FEATURES = {};
|
|
1847
|
+
|
|
1848
|
+
// src/ui/member-portal.tsx
|
|
1849
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
1850
|
+
var EMPTY = { pages: [], sections: [], viewer: { tierId: null, admin: false }, revisions: { parent: null, chapter: null } };
|
|
1851
|
+
function MemberPortal(props) {
|
|
1852
|
+
const inherited = useChapterCopy();
|
|
1853
|
+
const copy = props.copy ?? inherited.portal;
|
|
1854
|
+
const routing = { mode: props.routing?.mode ?? "hash", basePath: props.routing?.basePath ?? "/members" };
|
|
1855
|
+
const [content, setContent] = useState14(props.initialContent ?? null);
|
|
1856
|
+
const [route, setRoute] = useState14(props.initialRoute ?? { kind: "home" });
|
|
1857
|
+
const [menuOpen, setMenuOpen] = useState14(false);
|
|
1858
|
+
useEffect7(() => {
|
|
1859
|
+
if (props.initialContent) return;
|
|
1860
|
+
let live = true;
|
|
1861
|
+
void props.api("/api/member-content").then((value) => live && setContent(value)).catch(() => live && setContent(EMPTY));
|
|
1862
|
+
return () => {
|
|
1863
|
+
live = false;
|
|
1864
|
+
};
|
|
1865
|
+
}, [props.api, props.initialContent]);
|
|
1866
|
+
useEffect7(() => {
|
|
1867
|
+
if (typeof window === "undefined" || props.initialRoute) return;
|
|
1868
|
+
const sync = () => setRoute(routeFromLocation(window.location, routing));
|
|
1869
|
+
sync();
|
|
1870
|
+
window.addEventListener("popstate", sync);
|
|
1871
|
+
window.addEventListener("hashchange", sync);
|
|
1872
|
+
return () => {
|
|
1873
|
+
window.removeEventListener("popstate", sync);
|
|
1874
|
+
window.removeEventListener("hashchange", sync);
|
|
1875
|
+
};
|
|
1876
|
+
}, [routing.mode, routing.basePath]);
|
|
1877
|
+
const navigate = (next) => {
|
|
1878
|
+
setRoute(next);
|
|
1879
|
+
setMenuOpen(false);
|
|
1880
|
+
if (typeof window !== "undefined") {
|
|
1881
|
+
window.history.pushState(null, "", hrefFor(next, routing));
|
|
1882
|
+
window.scrollTo?.(0, 0);
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
const features = useMemo3(() => ({ ...PACKAGED_PORTAL_FEATURES, ...props.features }), [props.features]);
|
|
1886
|
+
if (!content) return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal", children: [
|
|
1887
|
+
/* @__PURE__ */ jsx21("style", { children: MEMBER_PORTAL_CSS }),
|
|
1888
|
+
/* @__PURE__ */ jsx21("p", { children: copy.shell.loading })
|
|
1889
|
+
] });
|
|
1890
|
+
const ctx = {
|
|
1891
|
+
api: props.api,
|
|
1892
|
+
me: props.me.portal,
|
|
1893
|
+
email: props.me.email,
|
|
1894
|
+
content,
|
|
1895
|
+
copy,
|
|
1896
|
+
navigate,
|
|
1897
|
+
hrefFor: (target) => hrefFor(target, routing),
|
|
1898
|
+
upsellHref: props.upsellHref,
|
|
1899
|
+
reloadMe: props.reloadMe ?? (async () => {
|
|
1900
|
+
})
|
|
1901
|
+
};
|
|
1902
|
+
const page = route.kind === "page" ? content.pages.find((candidate) => candidate.slug === route.slug) : void 0;
|
|
1903
|
+
const slots = typeof props.home === "function" ? {} : props.home ?? {};
|
|
1904
|
+
const home = /* @__PURE__ */ jsx21(DefaultHome, { ctx, features, slots });
|
|
1905
|
+
const body = route.kind === "home" ? typeof props.home === "function" ? props.home(ctx, home) : home : route.kind === "profile" ? /* @__PURE__ */ jsx21(MemberProfilePage, { ctx, middle: props.profile?.middle?.(ctx), extras: props.profile?.extras }) : page ? /* @__PURE__ */ jsx21(PortalPage, { page, ctx, features }) : /* @__PURE__ */ jsx21("div", { className: "chapter-portal-card", children: copy.shell.notFound });
|
|
1906
|
+
const admin = props.me.authorized || props.me.superAdmin ? props.adminHref ?? "/admin/" : void 0;
|
|
1907
|
+
return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal", "data-member-portal": true, "data-route": route.kind, children: [
|
|
1908
|
+
/* @__PURE__ */ jsx21("style", { children: MEMBER_PORTAL_CSS }),
|
|
1909
|
+
/* @__PURE__ */ jsx21(
|
|
1910
|
+
PortalNav,
|
|
1911
|
+
{
|
|
1912
|
+
content,
|
|
1913
|
+
me: ctx.me,
|
|
1914
|
+
email: props.me.email,
|
|
1915
|
+
route,
|
|
1916
|
+
copy,
|
|
1917
|
+
adminHref: admin,
|
|
1918
|
+
onNavigate: navigate,
|
|
1919
|
+
onSignOut: props.signOut,
|
|
1920
|
+
brand: props.brand,
|
|
1921
|
+
sidebarTokens: props.sidebarTokens,
|
|
1922
|
+
menuOpen,
|
|
1923
|
+
onToggleMenu: () => setMenuOpen(!menuOpen)
|
|
1924
|
+
}
|
|
1925
|
+
),
|
|
1926
|
+
/* @__PURE__ */ jsxs19("main", { className: "chapter-portal-main", children: [
|
|
1927
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-top", children: [
|
|
1928
|
+
route.kind === "home" ? /* @__PURE__ */ jsx21("h1", { children: copy.shell.welcomeBack }) : /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-back", onClick: () => navigate({ kind: "home" }), children: copy.shell.backHome }),
|
|
1929
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-top-right", children: [
|
|
1930
|
+
ctx.me.tier ? /* @__PURE__ */ jsx21("span", { className: "chapter-portal-pill", children: ctx.me.tier.name }) : null,
|
|
1931
|
+
/* @__PURE__ */ jsx21(
|
|
1932
|
+
"button",
|
|
1933
|
+
{
|
|
1934
|
+
type: "button",
|
|
1935
|
+
className: "chapter-portal-me",
|
|
1936
|
+
"aria-label": copy.shell.yourProfile,
|
|
1937
|
+
title: copy.shell.yourProfile,
|
|
1938
|
+
"aria-current": route.kind === "profile" ? "page" : void 0,
|
|
1939
|
+
onClick: () => navigate({ kind: "profile" }),
|
|
1940
|
+
children: /* @__PURE__ */ jsx21(PortalAvatar, { me: ctx.me })
|
|
1941
|
+
}
|
|
1942
|
+
)
|
|
1943
|
+
] })
|
|
1944
|
+
] }),
|
|
1945
|
+
body
|
|
1946
|
+
] })
|
|
1947
|
+
] });
|
|
1948
|
+
}
|
|
1364
1949
|
|
|
1365
1950
|
// src/ui/members.tsx
|
|
1366
|
-
import { Fragment as
|
|
1951
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
1367
1952
|
function card(copy, kicker, body) {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1953
|
+
return /* @__PURE__ */ jsxs20("div", { className: "card", children: [
|
|
1954
|
+
/* @__PURE__ */ jsx22("div", { className: "card-label", children: copy.provisional.cardLabel }),
|
|
1955
|
+
/* @__PURE__ */ jsxs20("div", { className: "meeting-block", children: [
|
|
1956
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-kicker", children: kicker }),
|
|
1372
1957
|
body
|
|
1373
1958
|
] })
|
|
1374
1959
|
] });
|
|
@@ -1379,29 +1964,32 @@ function ProvisionalCard(props) {
|
|
|
1379
1964
|
return card(
|
|
1380
1965
|
copy,
|
|
1381
1966
|
copy.provisional.applicationNeeded,
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1967
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
1968
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
|
|
1969
|
+
/* @__PURE__ */ jsx22("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
|
|
1385
1970
|
] })
|
|
1386
1971
|
);
|
|
1387
1972
|
}
|
|
1973
|
+
if (application.status === "declined") {
|
|
1974
|
+
return card(copy, copy.provisional.declined, /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.declinedBody }));
|
|
1975
|
+
}
|
|
1388
1976
|
if (application.status === "refunded") {
|
|
1389
1977
|
return card(
|
|
1390
1978
|
copy,
|
|
1391
1979
|
copy.provisional.refunded,
|
|
1392
|
-
/* @__PURE__ */
|
|
1980
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.refundedBody })
|
|
1393
1981
|
);
|
|
1394
1982
|
}
|
|
1395
|
-
const membership = application.paid ? /* @__PURE__ */
|
|
1983
|
+
const membership = application.paid ? /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
|
|
1396
1984
|
if (application.meetingAt) {
|
|
1397
1985
|
return card(
|
|
1398
1986
|
copy,
|
|
1399
1987
|
copy.provisional.introductionCall,
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
application.meetUrl ? /* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
1988
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
1989
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
|
|
1990
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
|
|
1991
|
+
application.meetUrl ? /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: /* @__PURE__ */ jsx22("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
|
|
1992
|
+
/* @__PURE__ */ jsx22(
|
|
1405
1993
|
Rescheduler,
|
|
1406
1994
|
{
|
|
1407
1995
|
api,
|
|
@@ -1418,9 +2006,9 @@ function ProvisionalCard(props) {
|
|
|
1418
2006
|
return card(
|
|
1419
2007
|
copy,
|
|
1420
2008
|
copy.provisional.bookCall,
|
|
1421
|
-
/* @__PURE__ */
|
|
1422
|
-
/* @__PURE__ */
|
|
1423
|
-
/* @__PURE__ */
|
|
2009
|
+
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
2010
|
+
/* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
|
|
2011
|
+
/* @__PURE__ */ jsx22(
|
|
1424
2012
|
Rescheduler,
|
|
1425
2013
|
{
|
|
1426
2014
|
api,
|
|
@@ -1447,8 +2035,8 @@ function MembersArea(props) {
|
|
|
1447
2035
|
renderProvisional
|
|
1448
2036
|
} = props;
|
|
1449
2037
|
const copy = props.copy ?? inheritedCopy.members;
|
|
1450
|
-
const [me, setMe] =
|
|
1451
|
-
const [error, setError] =
|
|
2038
|
+
const [me, setMe] = useState15(null);
|
|
2039
|
+
const [error, setError] = useState15(false);
|
|
1452
2040
|
const reload = async () => {
|
|
1453
2041
|
try {
|
|
1454
2042
|
setMe(await api("/api/me"));
|
|
@@ -1456,25 +2044,44 @@ function MembersArea(props) {
|
|
|
1456
2044
|
setError(true);
|
|
1457
2045
|
}
|
|
1458
2046
|
};
|
|
1459
|
-
|
|
2047
|
+
useEffect8(() => {
|
|
1460
2048
|
void reload();
|
|
1461
2049
|
}, []);
|
|
1462
|
-
if (error) return /* @__PURE__ */
|
|
1463
|
-
if (!me) return /* @__PURE__ */
|
|
2050
|
+
if (error) return /* @__PURE__ */ jsx22("p", { className: "meeting-note", children: copy.loadFailed });
|
|
2051
|
+
if (!me) return /* @__PURE__ */ jsx22("p", { className: "meeting-note", children: inheritedCopy.common.loading });
|
|
2052
|
+
if (props.portal && me.memberAccess === true && me.portal) {
|
|
2053
|
+
const gifts = /* @__PURE__ */ jsx22(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment });
|
|
2054
|
+
return /* @__PURE__ */ jsx22(
|
|
2055
|
+
MemberPortal,
|
|
2056
|
+
{
|
|
2057
|
+
...props.portal,
|
|
2058
|
+
api,
|
|
2059
|
+
me: { ...me, portal: me.portal },
|
|
2060
|
+
signOut,
|
|
2061
|
+
reloadMe: reload,
|
|
2062
|
+
adminHref: props.portal.adminHref ?? adminHref,
|
|
2063
|
+
profile: { ...props.portal.profile, extras: /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
2064
|
+
props.portal.profile?.extras,
|
|
2065
|
+
gifts,
|
|
2066
|
+
me.namedSeatsEnabled ? /* @__PURE__ */ jsx22(NamedSeatPurchase, { api }) : null
|
|
2067
|
+
] }) }
|
|
2068
|
+
}
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
1464
2071
|
const role = me.role || "provisional";
|
|
1465
|
-
return /* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1467
|
-
/* @__PURE__ */
|
|
1468
|
-
/* @__PURE__ */
|
|
1469
|
-
/* @__PURE__ */
|
|
2072
|
+
return /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
2073
|
+
/* @__PURE__ */ jsxs20("div", { className: "card", children: [
|
|
2074
|
+
/* @__PURE__ */ jsxs20("div", { className: "member-row", children: [
|
|
2075
|
+
/* @__PURE__ */ jsx22("span", { className: "member-email", children: me.email }),
|
|
2076
|
+
/* @__PURE__ */ jsx22("span", { className: "role-badge " + role, children: role })
|
|
1470
2077
|
] }),
|
|
1471
|
-
/* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
me.authorized || me.superAdmin ? /* @__PURE__ */
|
|
2078
|
+
/* @__PURE__ */ jsxs20("div", { className: "account-actions", children: [
|
|
2079
|
+
/* @__PURE__ */ jsx22("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
|
|
2080
|
+
me.authorized || me.superAdmin ? /* @__PURE__ */ jsx22("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
|
|
1474
2081
|
] })
|
|
1475
2082
|
] }),
|
|
1476
|
-
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */
|
|
1477
|
-
const defaultContent = /* @__PURE__ */
|
|
2083
|
+
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx22(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
|
|
2084
|
+
const defaultContent = /* @__PURE__ */ jsx22(
|
|
1478
2085
|
ProvisionalCard,
|
|
1479
2086
|
{
|
|
1480
2087
|
api,
|
|
@@ -1491,27 +2098,27 @@ function MembersArea(props) {
|
|
|
1491
2098
|
reload,
|
|
1492
2099
|
defaultContent
|
|
1493
2100
|
}) ?? defaultContent;
|
|
1494
|
-
})() : memberContent ?? (memberPages ? /* @__PURE__ */
|
|
2101
|
+
})() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx22(
|
|
1495
2102
|
MemberContentArea,
|
|
1496
2103
|
{
|
|
1497
2104
|
api,
|
|
1498
2105
|
...memberPages === true ? {} : memberPages
|
|
1499
2106
|
}
|
|
1500
|
-
) : /* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
me.namedSeatsEnabled ? /* @__PURE__ */
|
|
2107
|
+
) : /* @__PURE__ */ jsx22("div", { className: "card", children: /* @__PURE__ */ jsx22("div", { className: "card-label", children: copy.full.welcome }) })),
|
|
2108
|
+
/* @__PURE__ */ jsx22(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
|
|
2109
|
+
me.namedSeatsEnabled ? /* @__PURE__ */ jsx22(NamedSeatPurchase, { api }) : null
|
|
1503
2110
|
] });
|
|
1504
2111
|
}
|
|
1505
2112
|
|
|
1506
2113
|
// src/ui/join.tsx
|
|
1507
|
-
import { useEffect as
|
|
2114
|
+
import { useEffect as useEffect13, useRef as useRef8, useState as useState23 } from "preact/hooks";
|
|
1508
2115
|
|
|
1509
2116
|
// src/ui/join-booking.tsx
|
|
1510
|
-
import { useEffect as
|
|
1511
|
-
import { jsx as
|
|
2117
|
+
import { useEffect as useEffect9, useRef as useRef6, useState as useState16 } from "preact/hooks";
|
|
2118
|
+
import { jsx as jsx23, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
1512
2119
|
function useJoinSlotsPreload(active) {
|
|
1513
2120
|
const preload = useRef6(null);
|
|
1514
|
-
|
|
2121
|
+
useEffect9(() => {
|
|
1515
2122
|
if (!active || preload.current) return;
|
|
1516
2123
|
preload.current = Promise.resolve().then(() => fetch("/api/schedule/slots"));
|
|
1517
2124
|
preload.current.catch(() => {
|
|
@@ -1522,11 +2129,11 @@ function useJoinSlotsPreload(active) {
|
|
|
1522
2129
|
}
|
|
1523
2130
|
function JoinBooking(props) {
|
|
1524
2131
|
const { applicationId, copy, onBooked, simulation } = props;
|
|
1525
|
-
const [state, setState] =
|
|
1526
|
-
const [msg, setMsg] =
|
|
1527
|
-
const [busy, setBusy] =
|
|
1528
|
-
const [day2, setDay] =
|
|
1529
|
-
const [selected, setSelected] =
|
|
2132
|
+
const [state, setState] = useState16(null);
|
|
2133
|
+
const [msg, setMsg] = useState16(null);
|
|
2134
|
+
const [busy, setBusy] = useState16(false);
|
|
2135
|
+
const [day2, setDay] = useState16(null);
|
|
2136
|
+
const [selected, setSelected] = useState16(null);
|
|
1530
2137
|
const load = async (preloaded) => {
|
|
1531
2138
|
setMsg(null);
|
|
1532
2139
|
try {
|
|
@@ -1551,7 +2158,7 @@ function JoinBooking(props) {
|
|
|
1551
2158
|
setMsg(copy.loadFailed);
|
|
1552
2159
|
}
|
|
1553
2160
|
};
|
|
1554
|
-
|
|
2161
|
+
useEffect9(() => {
|
|
1555
2162
|
void load(props.preload);
|
|
1556
2163
|
}, [simulation]);
|
|
1557
2164
|
const book = async () => {
|
|
@@ -1583,17 +2190,17 @@ function JoinBooking(props) {
|
|
|
1583
2190
|
setBusy(false);
|
|
1584
2191
|
}
|
|
1585
2192
|
};
|
|
1586
|
-
if (!state) return /* @__PURE__ */
|
|
2193
|
+
if (!state) return /* @__PURE__ */ jsx23("p", { className: "slots-status", children: msg ?? copy.loading });
|
|
1587
2194
|
const hint = !day2 ? copy.pickDate ?? DEFAULT_JOIN_COPY.booking.pickDate : !selected ? copy.pickTime ?? DEFAULT_JOIN_COPY.booking.pickTime : null;
|
|
1588
|
-
return /* @__PURE__ */
|
|
1589
|
-
/* @__PURE__ */
|
|
1590
|
-
/* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
hint ? /* @__PURE__ */
|
|
1594
|
-
msg ? /* @__PURE__ */
|
|
2195
|
+
return /* @__PURE__ */ jsxs21("div", { className: "join-book", children: [
|
|
2196
|
+
/* @__PURE__ */ jsx23("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
|
|
2197
|
+
/* @__PURE__ */ jsx23("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
|
|
2198
|
+
/* @__PURE__ */ jsxs21("div", { className: "slot-confirm", children: [
|
|
2199
|
+
/* @__PURE__ */ jsx23("button", { className: "submit-btn", type: "button", disabled: busy || !selected, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
|
|
2200
|
+
hint ? /* @__PURE__ */ jsx23("p", { className: "slot-hint", role: "status", children: hint }) : null,
|
|
2201
|
+
msg ? /* @__PURE__ */ jsx23("p", { className: "step2-note", role: "alert", children: msg }) : null
|
|
1595
2202
|
] }),
|
|
1596
|
-
/* @__PURE__ */
|
|
2203
|
+
/* @__PURE__ */ jsx23(
|
|
1597
2204
|
SlotPicker,
|
|
1598
2205
|
{
|
|
1599
2206
|
slots: state.slots,
|
|
@@ -1611,21 +2218,21 @@ function JoinBooking(props) {
|
|
|
1611
2218
|
}
|
|
1612
2219
|
|
|
1613
2220
|
// src/ui/join-accepted.tsx
|
|
1614
|
-
import { jsx as
|
|
2221
|
+
import { jsx as jsx24, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
1615
2222
|
function JoinAccepted(props) {
|
|
1616
|
-
return /* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
1618
|
-
/* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
2223
|
+
return /* @__PURE__ */ jsxs22("div", { className: "join-done card", children: [
|
|
2224
|
+
/* @__PURE__ */ jsx24("div", { className: "card-label", children: props.copy.accepted.label }),
|
|
2225
|
+
/* @__PURE__ */ jsx24("p", { className: "meeting-note", children: props.copy.accepted.body }),
|
|
2226
|
+
/* @__PURE__ */ jsx24("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
|
|
1620
2227
|
] });
|
|
1621
2228
|
}
|
|
1622
2229
|
|
|
1623
2230
|
// src/ui/gift-claim-card.tsx
|
|
1624
|
-
import { useState as
|
|
1625
|
-
import { Fragment as
|
|
2231
|
+
import { useState as useState17 } from "preact/hooks";
|
|
2232
|
+
import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
1626
2233
|
function GiftClaimCard(props) {
|
|
1627
|
-
const [code, setCode] =
|
|
1628
|
-
const [error, setError] =
|
|
2234
|
+
const [code, setCode] = useState17(props.initialCode ?? "");
|
|
2235
|
+
const [error, setError] = useState17(false);
|
|
1629
2236
|
const rotate = async () => {
|
|
1630
2237
|
if (!props.claimId) return;
|
|
1631
2238
|
setError(false);
|
|
@@ -1638,15 +2245,15 @@ function GiftClaimCard(props) {
|
|
|
1638
2245
|
if (response.ok && body.code) setCode(body.code);
|
|
1639
2246
|
else setError(true);
|
|
1640
2247
|
};
|
|
1641
|
-
return /* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
code ? /* @__PURE__ */
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
2248
|
+
return /* @__PURE__ */ jsxs23("div", { className: "join-done card", children: [
|
|
2249
|
+
/* @__PURE__ */ jsx25("div", { className: "card-label", children: props.copy.label }),
|
|
2250
|
+
/* @__PURE__ */ jsx25("p", { className: "meeting-note", children: props.copy.body }),
|
|
2251
|
+
code ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
|
|
2252
|
+
/* @__PURE__ */ jsx25("output", { className: "gift-code", children: code }),
|
|
2253
|
+
/* @__PURE__ */ jsx25("p", { children: props.copy.save })
|
|
1647
2254
|
] }) : null,
|
|
1648
|
-
!code && props.claimId ? /* @__PURE__ */
|
|
1649
|
-
error ? /* @__PURE__ */
|
|
2255
|
+
!code && props.claimId ? /* @__PURE__ */ jsx25("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
|
|
2256
|
+
error ? /* @__PURE__ */ jsx25("p", { role: "alert", children: props.copy.rotateFailed }) : null
|
|
1650
2257
|
] });
|
|
1651
2258
|
}
|
|
1652
2259
|
|
|
@@ -1654,11 +2261,11 @@ function GiftClaimCard(props) {
|
|
|
1654
2261
|
import { useRef as useRef7 } from "preact/hooks";
|
|
1655
2262
|
|
|
1656
2263
|
// src/ui/join-tiers.tsx
|
|
1657
|
-
import { useState as
|
|
1658
|
-
import { Fragment as
|
|
2264
|
+
import { useState as useState18 } from "preact/hooks";
|
|
2265
|
+
import { Fragment as Fragment10, jsx as jsx26, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
1659
2266
|
var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
|
|
1660
2267
|
function useTierSelection(tiers, initialTierId) {
|
|
1661
|
-
const [selectedTierId, setSelectedTierId] =
|
|
2268
|
+
const [selectedTierId, setSelectedTierId] = useState18(() => {
|
|
1662
2269
|
const preset = tiers.find((tier) => tier.id === initialTierId);
|
|
1663
2270
|
if (preset) return preset.id;
|
|
1664
2271
|
return tiers.length === 1 ? tiers[0].id : null;
|
|
@@ -1673,10 +2280,10 @@ function useTierSelection(tiers, initialTierId) {
|
|
|
1673
2280
|
};
|
|
1674
2281
|
}
|
|
1675
2282
|
function TierPlaceholder(context) {
|
|
1676
|
-
return /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
context.tiers.map((tier) => /* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
2283
|
+
return /* @__PURE__ */ jsxs24("fieldset", { "data-chapter-placeholder": "tiers", children: [
|
|
2284
|
+
/* @__PURE__ */ jsx26("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
|
|
2285
|
+
context.tiers.map((tier) => /* @__PURE__ */ jsxs24("label", { children: [
|
|
2286
|
+
/* @__PURE__ */ jsx26(
|
|
1680
2287
|
"input",
|
|
1681
2288
|
{
|
|
1682
2289
|
type: "radio",
|
|
@@ -1687,13 +2294,13 @@ function TierPlaceholder(context) {
|
|
|
1687
2294
|
}
|
|
1688
2295
|
),
|
|
1689
2296
|
tier.name,
|
|
1690
|
-
tier.founding ? /* @__PURE__ */
|
|
2297
|
+
tier.founding ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
1691
2298
|
" \u2014 ",
|
|
1692
2299
|
joinTierMoney(tier.founding.dueTodayCents),
|
|
1693
2300
|
" founding member rate (list ",
|
|
1694
2301
|
joinTierMoney(tier.priceCents),
|
|
1695
2302
|
")"
|
|
1696
|
-
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */
|
|
2303
|
+
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
1697
2304
|
" \u2014 ",
|
|
1698
2305
|
joinTierMoney(tier.priceCents)
|
|
1699
2306
|
] })
|
|
@@ -1705,12 +2312,12 @@ function tierNeedsPayment(selected, paymentsReady) {
|
|
|
1705
2312
|
}
|
|
1706
2313
|
|
|
1707
2314
|
// src/ui/join-application-form.tsx
|
|
1708
|
-
import { jsx as
|
|
2315
|
+
import { jsx as jsx27, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
1709
2316
|
function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
|
|
1710
2317
|
const form = useRef7(null);
|
|
1711
2318
|
const ready = useFormReadiness(form);
|
|
1712
2319
|
const disabled = submitting || props.submitDisabled === true || !ready || !validJoinRecipient(props.payment?.initialNamedSeat);
|
|
1713
|
-
return /* @__PURE__ */
|
|
2320
|
+
return /* @__PURE__ */ jsxs25("form", { ref: form, className: "join-form", onSubmit: (event) => {
|
|
1714
2321
|
if (!isFormReady(event.currentTarget)) {
|
|
1715
2322
|
event.preventDefault();
|
|
1716
2323
|
event.currentTarget.reportValidity();
|
|
@@ -1718,15 +2325,15 @@ function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelec
|
|
|
1718
2325
|
}
|
|
1719
2326
|
void submit(event);
|
|
1720
2327
|
}, children: [
|
|
1721
|
-
!requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
2328
|
+
!requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs25("fieldset", { children: [
|
|
2329
|
+
/* @__PURE__ */ jsx27("legend", { children: copy.gift.optionsLabel }),
|
|
2330
|
+
/* @__PURE__ */ jsx27("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
|
|
2331
|
+
/* @__PURE__ */ jsx27(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
|
|
1725
2332
|
] }) : null,
|
|
1726
2333
|
!requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
|
|
1727
2334
|
typeof props.children === "function" ? props.children({ invitation }) : props.children,
|
|
1728
|
-
error ? /* @__PURE__ */
|
|
1729
|
-
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */
|
|
2335
|
+
error ? /* @__PURE__ */ jsx27("p", { className: "join-error", role: "alert", children: error }) : null,
|
|
2336
|
+
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx27(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
|
|
1730
2337
|
] });
|
|
1731
2338
|
}
|
|
1732
2339
|
|
|
@@ -1751,8 +2358,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
|
|
|
1751
2358
|
|
|
1752
2359
|
// src/ui/gift-code-redeemer.tsx
|
|
1753
2360
|
import { InlineActionField } from "@odla-ai/ui/components";
|
|
1754
|
-
import { useState as
|
|
1755
|
-
import { Fragment as
|
|
2361
|
+
import { useState as useState19 } from "preact/hooks";
|
|
2362
|
+
import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
1756
2363
|
var GIFT_CODE_REDEEMER_CSS = `
|
|
1757
2364
|
.gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
|
|
1758
2365
|
.gift-code-redeemer .inline-action-field-label{display:block;color:var(--ui-text-muted,#66777f);font-size:var(--ui-text-xs,.72rem);font-weight:var(--ui-weight-strong,700);letter-spacing:var(--ui-tracking-caps,.08em);text-transform:uppercase}
|
|
@@ -1767,10 +2374,10 @@ var GIFT_CODE_REDEEMER_CSS = `
|
|
|
1767
2374
|
@container (max-width:26rem){.gift-code-redeemer .inline-action-field-row{grid-template-columns:minmax(0,1fr)}.gift-code-redeemer .inline-action-field-action{width:100%}}
|
|
1768
2375
|
`;
|
|
1769
2376
|
function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
1770
|
-
const [code, setCode] =
|
|
1771
|
-
const [loading, setLoading] =
|
|
1772
|
-
const [message, setMessage] =
|
|
1773
|
-
const [messageTone, setMessageTone] =
|
|
2377
|
+
const [code, setCode] = useState19("");
|
|
2378
|
+
const [loading, setLoading] = useState19(false);
|
|
2379
|
+
const [message, setMessage] = useState19("");
|
|
2380
|
+
const [messageTone, setMessageTone] = useState19("neutral");
|
|
1774
2381
|
const normalizedCode = code.trim();
|
|
1775
2382
|
const redeem = async () => {
|
|
1776
2383
|
if (!normalizedCode || loading) return;
|
|
@@ -1797,9 +2404,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
|
1797
2404
|
setLoading(false);
|
|
1798
2405
|
}
|
|
1799
2406
|
};
|
|
1800
|
-
return /* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
2407
|
+
return /* @__PURE__ */ jsxs26(Fragment11, { children: [
|
|
2408
|
+
/* @__PURE__ */ jsx28("style", { children: GIFT_CODE_REDEEMER_CSS }),
|
|
2409
|
+
/* @__PURE__ */ jsx28(
|
|
1803
2410
|
InlineActionField,
|
|
1804
2411
|
{
|
|
1805
2412
|
id,
|
|
@@ -1855,12 +2462,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
|
|
|
1855
2462
|
}
|
|
1856
2463
|
|
|
1857
2464
|
// src/ui/join-gift-claim.tsx
|
|
1858
|
-
import { jsx as
|
|
2465
|
+
import { jsx as jsx29, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
1859
2466
|
function JoinGiftClaim(props) {
|
|
1860
|
-
return /* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
1862
|
-
/* @__PURE__ */
|
|
1863
|
-
/* @__PURE__ */
|
|
2467
|
+
return /* @__PURE__ */ jsxs27("section", { className: "join-gift-claim card", children: [
|
|
2468
|
+
/* @__PURE__ */ jsx29("div", { className: "card-label", children: props.copy.claimTitle }),
|
|
2469
|
+
/* @__PURE__ */ jsx29("p", { children: props.copy.claimBody }),
|
|
2470
|
+
/* @__PURE__ */ jsx29(
|
|
1864
2471
|
GiftCodeRedeemer,
|
|
1865
2472
|
{
|
|
1866
2473
|
api: props.api,
|
|
@@ -1884,21 +2491,21 @@ function JoinGiftClaim(props) {
|
|
|
1884
2491
|
}
|
|
1885
2492
|
|
|
1886
2493
|
// src/ui/join-named-seat.tsx
|
|
1887
|
-
import { useState as
|
|
1888
|
-
import { jsx as
|
|
2494
|
+
import { useState as useState20 } from "preact/hooks";
|
|
2495
|
+
import { jsx as jsx30, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
1889
2496
|
function JoinNamedSeat(props) {
|
|
1890
2497
|
const seatId = props.seatId ?? "";
|
|
1891
2498
|
const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
|
|
1892
|
-
const [accepted, setAccepted] =
|
|
1893
|
-
return /* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1895
|
-
/* @__PURE__ */
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
/* @__PURE__ */
|
|
1898
|
-
/* @__PURE__ */
|
|
2499
|
+
const [accepted, setAccepted] = useState20(false), [busy, setBusy] = useState20(false), [error, setError] = useState20("");
|
|
2500
|
+
return /* @__PURE__ */ jsxs28("section", { className: "join-named-seat card", children: [
|
|
2501
|
+
/* @__PURE__ */ jsx30("h2", { children: copy.title }),
|
|
2502
|
+
/* @__PURE__ */ jsx30("p", { children: copy.body }),
|
|
2503
|
+
/* @__PURE__ */ jsxs28("label", { className: "journey-consent", children: [
|
|
2504
|
+
/* @__PURE__ */ jsx30("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
|
|
2505
|
+
/* @__PURE__ */ jsx30("span", { children: copy.consent })
|
|
1899
2506
|
] }),
|
|
1900
|
-
error ? /* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
2507
|
+
error ? /* @__PURE__ */ jsx30("p", { role: "alert", children: error }) : null,
|
|
2508
|
+
/* @__PURE__ */ jsx30("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
|
|
1902
2509
|
setBusy(true);
|
|
1903
2510
|
setError("");
|
|
1904
2511
|
try {
|
|
@@ -1918,13 +2525,13 @@ function JoinNamedSeat(props) {
|
|
|
1918
2525
|
}
|
|
1919
2526
|
|
|
1920
2527
|
// src/ui/join-invitation.tsx
|
|
1921
|
-
import { useEffect as
|
|
1922
|
-
import { jsx as
|
|
2528
|
+
import { useEffect as useEffect10, useState as useState21 } from "preact/hooks";
|
|
2529
|
+
import { jsx as jsx31, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
1923
2530
|
function useJoinInvitation(seatId, api, fallback) {
|
|
1924
|
-
const [invitation, setInvitation] =
|
|
1925
|
-
const [error, setError] =
|
|
1926
|
-
const [revision, setRevision] =
|
|
1927
|
-
|
|
2531
|
+
const [invitation, setInvitation] = useState21(null);
|
|
2532
|
+
const [error, setError] = useState21("");
|
|
2533
|
+
const [revision, setRevision] = useState21(0);
|
|
2534
|
+
useEffect10(() => {
|
|
1928
2535
|
let live = true;
|
|
1929
2536
|
setInvitation(null);
|
|
1930
2537
|
setError("");
|
|
@@ -1946,9 +2553,9 @@ function useJoinInvitation(seatId, api, fallback) {
|
|
|
1946
2553
|
return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
|
|
1947
2554
|
}
|
|
1948
2555
|
function JoinInvitationNotice(props) {
|
|
1949
|
-
return /* @__PURE__ */
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
/* @__PURE__ */
|
|
2556
|
+
return /* @__PURE__ */ jsxs29("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
|
|
2557
|
+
/* @__PURE__ */ jsx31("p", { children: /* @__PURE__ */ jsx31("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
|
|
2558
|
+
/* @__PURE__ */ jsx31("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
|
|
1952
2559
|
] });
|
|
1953
2560
|
}
|
|
1954
2561
|
|
|
@@ -1963,9 +2570,9 @@ function joinSimulationPayment(simulation, priceCents) {
|
|
|
1963
2570
|
}
|
|
1964
2571
|
|
|
1965
2572
|
// src/ui/join-pending.ts
|
|
1966
|
-
import { useEffect as
|
|
2573
|
+
import { useEffect as useEffect11 } from "preact/hooks";
|
|
1967
2574
|
function useJoinPending(state, loadResume, setState) {
|
|
1968
|
-
|
|
2575
|
+
useEffect11(() => {
|
|
1969
2576
|
if (state.step !== "paymentPending") return;
|
|
1970
2577
|
let live = true;
|
|
1971
2578
|
let timer;
|
|
@@ -1988,16 +2595,16 @@ function useJoinPending(state, loadResume, setState) {
|
|
|
1988
2595
|
}
|
|
1989
2596
|
|
|
1990
2597
|
// src/ui/payment-receipt.tsx
|
|
1991
|
-
import { useEffect as
|
|
1992
|
-
import { Fragment as
|
|
2598
|
+
import { useEffect as useEffect12, useState as useState22 } from "preact/hooks";
|
|
2599
|
+
import { Fragment as Fragment12, jsx as jsx32, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
1993
2600
|
function PaymentReceiptCard({ applicationId }) {
|
|
1994
|
-
const [receipt, setReceipt] =
|
|
1995
|
-
const [error, setError] =
|
|
1996
|
-
const [revision, setRevision] =
|
|
1997
|
-
const [emailState, setEmailState] =
|
|
1998
|
-
const [previewEmail, setPreviewEmail] =
|
|
2601
|
+
const [receipt, setReceipt] = useState22(null);
|
|
2602
|
+
const [error, setError] = useState22("");
|
|
2603
|
+
const [revision, setRevision] = useState22(0);
|
|
2604
|
+
const [emailState, setEmailState] = useState22("idle");
|
|
2605
|
+
const [previewEmail, setPreviewEmail] = useState22(false);
|
|
1999
2606
|
const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
|
|
2000
|
-
|
|
2607
|
+
useEffect12(() => {
|
|
2001
2608
|
let live = true, timer;
|
|
2002
2609
|
setReceipt(null);
|
|
2003
2610
|
setError("");
|
|
@@ -2023,9 +2630,9 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
2023
2630
|
if (timer) clearTimeout(timer);
|
|
2024
2631
|
};
|
|
2025
2632
|
}, [endpoint, revision]);
|
|
2026
|
-
if (!receipt) return error ? /* @__PURE__ */
|
|
2027
|
-
/* @__PURE__ */
|
|
2028
|
-
/* @__PURE__ */
|
|
2633
|
+
if (!receipt) return error ? /* @__PURE__ */ jsxs30("section", { "aria-label": "Payment receipt", children: [
|
|
2634
|
+
/* @__PURE__ */ jsx32("p", { role: "status", children: error }),
|
|
2635
|
+
/* @__PURE__ */ jsx32("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
|
|
2029
2636
|
] }) : null;
|
|
2030
2637
|
const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
|
|
2031
2638
|
const email = async () => {
|
|
@@ -2042,38 +2649,38 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
2042
2649
|
setError("We could not confirm email delivery. You can print or save your receipt.");
|
|
2043
2650
|
}
|
|
2044
2651
|
};
|
|
2045
|
-
return /* @__PURE__ */
|
|
2046
|
-
/* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
receipt.namedSeat ? /* @__PURE__ */
|
|
2052
|
-
/* @__PURE__ */
|
|
2652
|
+
return /* @__PURE__ */ jsxs30("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
|
|
2653
|
+
/* @__PURE__ */ jsx32("h2", { children: "Payment received" }),
|
|
2654
|
+
/* @__PURE__ */ jsx32("p", { children: receipt.tierName }),
|
|
2655
|
+
/* @__PURE__ */ jsxs30("dl", { className: "journey-summary", children: [
|
|
2656
|
+
/* @__PURE__ */ jsx32("dt", { children: "Membership" }),
|
|
2657
|
+
/* @__PURE__ */ jsx32("dd", { children: money(receipt.membershipCents) }),
|
|
2658
|
+
receipt.namedSeat ? /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
2659
|
+
/* @__PURE__ */ jsxs30("dt", { children: [
|
|
2053
2660
|
"Additional member \u2014 ",
|
|
2054
2661
|
receipt.namedSeat.recipientName
|
|
2055
2662
|
] }),
|
|
2056
|
-
/* @__PURE__ */
|
|
2663
|
+
/* @__PURE__ */ jsxs30("dd", { children: [
|
|
2057
2664
|
receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
|
|
2058
2665
|
money(receipt.namedSeat.amountCents)
|
|
2059
2666
|
] })
|
|
2060
2667
|
] }) : null,
|
|
2061
|
-
/* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
2668
|
+
/* @__PURE__ */ jsx32("dt", { children: "Total paid" }),
|
|
2669
|
+
/* @__PURE__ */ jsx32("dd", { children: money(receipt.totalCents) })
|
|
2063
2670
|
] }),
|
|
2064
|
-
/* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
2671
|
+
/* @__PURE__ */ jsxs30("div", { className: "journey-actions", children: [
|
|
2672
|
+
/* @__PURE__ */ jsx32("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
|
|
2673
|
+
/* @__PURE__ */ jsx32("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
|
|
2067
2674
|
] }),
|
|
2068
|
-
emailState === "sent" ? /* @__PURE__ */
|
|
2069
|
-
error ? /* @__PURE__ */
|
|
2675
|
+
emailState === "sent" ? /* @__PURE__ */ jsx32("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
|
|
2676
|
+
error ? /* @__PURE__ */ jsx32("p", { role: "alert", children: error }) : null
|
|
2070
2677
|
] });
|
|
2071
2678
|
}
|
|
2072
2679
|
|
|
2073
2680
|
// src/ui/join.tsx
|
|
2074
|
-
import { Fragment as
|
|
2681
|
+
import { Fragment as Fragment13, jsx as jsx33, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
2075
2682
|
function JoinIsland(props) {
|
|
2076
|
-
return /* @__PURE__ */
|
|
2683
|
+
return /* @__PURE__ */ jsx33(JourneyFrame, { children: /* @__PURE__ */ jsx33(JoinFlow, { ...props }) });
|
|
2077
2684
|
}
|
|
2078
2685
|
function JoinFlow(props) {
|
|
2079
2686
|
const inheritedCopy = useChapterCopy();
|
|
@@ -2094,16 +2701,16 @@ function JoinFlow(props) {
|
|
|
2094
2701
|
const invitation = invitationState.invitation;
|
|
2095
2702
|
const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
|
|
2096
2703
|
const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
|
|
2097
|
-
const [state, setState] =
|
|
2098
|
-
const [error, setError] =
|
|
2099
|
-
const [submitting, setSubmitting] =
|
|
2100
|
-
const [editingNamedSeat, setEditingNamedSeat] =
|
|
2101
|
-
const [giftOfferId, setGiftOfferId] =
|
|
2704
|
+
const [state, setState] = useState23(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
|
|
2705
|
+
const [error, setError] = useState23(null);
|
|
2706
|
+
const [submitting, setSubmitting] = useState23(false);
|
|
2707
|
+
const [editingNamedSeat, setEditingNamedSeat] = useState23(false);
|
|
2708
|
+
const [giftOfferId, setGiftOfferId] = useState23(props.initialGiftOfferId ?? null);
|
|
2102
2709
|
const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
|
|
2103
2710
|
const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
|
|
2104
2711
|
const submissionId = useRef8(null);
|
|
2105
2712
|
const slotsPreload = useJoinSlotsPreload(!props.simulation && ["payment", "paymentPending"].includes(state.step));
|
|
2106
|
-
|
|
2713
|
+
useEffect13(() => {
|
|
2107
2714
|
if (props.simulation) return;
|
|
2108
2715
|
const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
|
|
2109
2716
|
if (typeof window === "undefined") return Promise.resolve(null);
|
|
@@ -2176,13 +2783,13 @@ function JoinFlow(props) {
|
|
|
2176
2783
|
setSubmitting(false);
|
|
2177
2784
|
}
|
|
2178
2785
|
};
|
|
2179
|
-
if (requestedSeat && !invitation) return /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2182
|
-
invitationState.error ? /* @__PURE__ */
|
|
2786
|
+
if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs31("section", { className: "card", "aria-live": "polite", children: [
|
|
2787
|
+
/* @__PURE__ */ jsx33("h2", { children: seatCopy.title }),
|
|
2788
|
+
/* @__PURE__ */ jsx33("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
|
|
2789
|
+
invitationState.error ? /* @__PURE__ */ jsx33("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
|
|
2183
2790
|
] });
|
|
2184
|
-
const header = /* @__PURE__ */
|
|
2185
|
-
invitation ? /* @__PURE__ */
|
|
2791
|
+
const header = /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2792
|
+
invitation ? /* @__PURE__ */ jsx33(
|
|
2186
2793
|
JoinInvitationNotice,
|
|
2187
2794
|
{
|
|
2188
2795
|
invitation,
|
|
@@ -2197,49 +2804,49 @@ function JoinFlow(props) {
|
|
|
2197
2804
|
..."applicationId" in state ? { applicationId: state.applicationId } : {}
|
|
2198
2805
|
})
|
|
2199
2806
|
] });
|
|
2200
|
-
const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */
|
|
2807
|
+
const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx33(PaymentReceiptCard, { applicationId: state.applicationId }) : null;
|
|
2201
2808
|
if (state.step === "closed") {
|
|
2202
|
-
return /* @__PURE__ */
|
|
2809
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2203
2810
|
header,
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2811
|
+
/* @__PURE__ */ jsxs31("section", { className: "card", "aria-label": "Application closed", children: [
|
|
2812
|
+
/* @__PURE__ */ jsx33("h2", { children: "This application is closed" }),
|
|
2813
|
+
/* @__PURE__ */ jsx33("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
|
|
2814
|
+
/* @__PURE__ */ jsx33("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
2208
2815
|
] })
|
|
2209
2816
|
] });
|
|
2210
2817
|
}
|
|
2211
2818
|
if (state.step === "done") {
|
|
2212
|
-
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2214
|
-
/* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2819
|
+
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs31("div", { className: "join-done card", children: [
|
|
2820
|
+
/* @__PURE__ */ jsx33("div", { className: "card-label", children: copy.done.label }),
|
|
2821
|
+
/* @__PURE__ */ jsx33("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
|
|
2822
|
+
/* @__PURE__ */ jsx33("p", { className: "meeting-note", children: copy.done.calendarInvite }),
|
|
2823
|
+
/* @__PURE__ */ jsx33("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
2217
2824
|
] });
|
|
2218
|
-
return /* @__PURE__ */
|
|
2825
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2219
2826
|
header,
|
|
2220
2827
|
body,
|
|
2221
2828
|
receipt
|
|
2222
2829
|
] });
|
|
2223
2830
|
}
|
|
2224
2831
|
if (state.step === "accepted") {
|
|
2225
|
-
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
2226
|
-
return /* @__PURE__ */
|
|
2832
|
+
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx33(JoinAccepted, { copy, membersHref });
|
|
2833
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2227
2834
|
header,
|
|
2228
2835
|
body,
|
|
2229
2836
|
receipt
|
|
2230
2837
|
] });
|
|
2231
2838
|
}
|
|
2232
2839
|
if (state.step === "gift") {
|
|
2233
|
-
const body = renderGift?.(state) ?? /* @__PURE__ */
|
|
2234
|
-
return /* @__PURE__ */
|
|
2840
|
+
const body = renderGift?.(state) ?? /* @__PURE__ */ jsx33(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
|
|
2841
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2235
2842
|
header,
|
|
2236
2843
|
body
|
|
2237
2844
|
] });
|
|
2238
2845
|
}
|
|
2239
2846
|
if (state.step === "booking") {
|
|
2240
|
-
return /* @__PURE__ */
|
|
2847
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2241
2848
|
header,
|
|
2242
|
-
/* @__PURE__ */
|
|
2849
|
+
/* @__PURE__ */ jsx33(
|
|
2243
2850
|
JoinBooking,
|
|
2244
2851
|
{
|
|
2245
2852
|
applicationId: state.applicationId,
|
|
@@ -2256,9 +2863,9 @@ function JoinFlow(props) {
|
|
|
2256
2863
|
}
|
|
2257
2864
|
if (state.step === "payment") {
|
|
2258
2865
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
|
|
2259
|
-
return /* @__PURE__ */
|
|
2866
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2260
2867
|
header,
|
|
2261
|
-
/* @__PURE__ */
|
|
2868
|
+
/* @__PURE__ */ jsx33(
|
|
2262
2869
|
JoinNamedSeat,
|
|
2263
2870
|
{
|
|
2264
2871
|
api: props.namedSeatClaimApi,
|
|
@@ -2271,9 +2878,9 @@ function JoinFlow(props) {
|
|
|
2271
2878
|
] });
|
|
2272
2879
|
}
|
|
2273
2880
|
const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
|
|
2274
|
-
return /* @__PURE__ */
|
|
2881
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2275
2882
|
header,
|
|
2276
|
-
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */
|
|
2883
|
+
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx33(
|
|
2277
2884
|
JoinGiftClaim,
|
|
2278
2885
|
{
|
|
2279
2886
|
api: props.giftClaimApi,
|
|
@@ -2284,7 +2891,7 @@ function JoinFlow(props) {
|
|
|
2284
2891
|
onError: () => setError(copy.form.unexpectedFailure)
|
|
2285
2892
|
}
|
|
2286
2893
|
) : null,
|
|
2287
|
-
/* @__PURE__ */
|
|
2894
|
+
/* @__PURE__ */ jsx33(
|
|
2288
2895
|
Payment,
|
|
2289
2896
|
{
|
|
2290
2897
|
applicationId: state.applicationId,
|
|
@@ -2312,9 +2919,9 @@ function JoinFlow(props) {
|
|
|
2312
2919
|
}
|
|
2313
2920
|
if (state.step === "paymentPending") {
|
|
2314
2921
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
|
|
2315
|
-
return /* @__PURE__ */
|
|
2922
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2316
2923
|
header,
|
|
2317
|
-
/* @__PURE__ */
|
|
2924
|
+
/* @__PURE__ */ jsx33(
|
|
2318
2925
|
JoinNamedSeat,
|
|
2319
2926
|
{
|
|
2320
2927
|
api: props.namedSeatClaimApi,
|
|
@@ -2326,15 +2933,15 @@ function JoinFlow(props) {
|
|
|
2326
2933
|
)
|
|
2327
2934
|
] });
|
|
2328
2935
|
}
|
|
2329
|
-
return /* @__PURE__ */
|
|
2936
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2330
2937
|
header,
|
|
2331
|
-
/* @__PURE__ */
|
|
2938
|
+
/* @__PURE__ */ jsx33("p", { className: "pay-status", role: "status", children: copy.payment.pending }),
|
|
2332
2939
|
receipt
|
|
2333
2940
|
] });
|
|
2334
2941
|
}
|
|
2335
|
-
return /* @__PURE__ */
|
|
2942
|
+
return /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
2336
2943
|
header,
|
|
2337
|
-
/* @__PURE__ */
|
|
2944
|
+
/* @__PURE__ */ jsx33(
|
|
2338
2945
|
JoinApplicationForm,
|
|
2339
2946
|
{
|
|
2340
2947
|
props,
|
|
@@ -2353,7 +2960,7 @@ function JoinFlow(props) {
|
|
|
2353
2960
|
}
|
|
2354
2961
|
|
|
2355
2962
|
// src/ui/membership-cards.tsx
|
|
2356
|
-
import { Markdown as
|
|
2963
|
+
import { Markdown as Markdown3 } from "@odla-ai/ui/components";
|
|
2357
2964
|
|
|
2358
2965
|
// src/membership-page.ts
|
|
2359
2966
|
var MEMBERSHIP_PAGE_RENDERER = "membership-cards-v1";
|
|
@@ -2524,7 +3131,7 @@ function membershipPageDocument(input, options = {}) {
|
|
|
2524
3131
|
}
|
|
2525
3132
|
|
|
2526
3133
|
// src/ui/membership-cards.tsx
|
|
2527
|
-
import { jsx as
|
|
3134
|
+
import { jsx as jsx34, jsxs as jsxs32 } from "preact/jsx-runtime";
|
|
2528
3135
|
var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
|
|
2529
3136
|
"--ui-membership-grid-gap": "1.4rem",
|
|
2530
3137
|
"--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
|
|
@@ -2593,67 +3200,67 @@ function membershipApplicationHref(applicationPath, tierId) {
|
|
|
2593
3200
|
}
|
|
2594
3201
|
function TierAction(props) {
|
|
2595
3202
|
if (props.mode === "select") {
|
|
2596
|
-
return /* @__PURE__ */
|
|
3203
|
+
return /* @__PURE__ */ jsxs32("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
|
|
2597
3204
|
props.label,
|
|
2598
|
-
/* @__PURE__ */
|
|
3205
|
+
/* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2599
3206
|
] });
|
|
2600
3207
|
}
|
|
2601
3208
|
if (props.mode === "preview") {
|
|
2602
|
-
return /* @__PURE__ */
|
|
3209
|
+
return /* @__PURE__ */ jsxs32("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
|
|
2603
3210
|
props.label,
|
|
2604
|
-
/* @__PURE__ */
|
|
3211
|
+
/* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2605
3212
|
] });
|
|
2606
3213
|
}
|
|
2607
|
-
return /* @__PURE__ */
|
|
3214
|
+
return /* @__PURE__ */ jsxs32("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
|
|
2608
3215
|
props.label,
|
|
2609
|
-
/* @__PURE__ */
|
|
3216
|
+
/* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2610
3217
|
] });
|
|
2611
3218
|
}
|
|
2612
3219
|
function TierCard(props) {
|
|
2613
3220
|
const { tier, presentation } = props;
|
|
2614
3221
|
const summary = presentation.summaryMarkdown ?? tier.blurb;
|
|
2615
3222
|
const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
|
|
2616
|
-
return /* @__PURE__ */
|
|
2617
|
-
presentation.badge ? /* @__PURE__ */
|
|
2618
|
-
/* @__PURE__ */
|
|
2619
|
-
/* @__PURE__ */
|
|
2620
|
-
presentation.capacity ? /* @__PURE__ */
|
|
2621
|
-
/* @__PURE__ */
|
|
2622
|
-
/* @__PURE__ */
|
|
3223
|
+
return /* @__PURE__ */ jsxs32("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
|
|
3224
|
+
presentation.badge ? /* @__PURE__ */ jsx34("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
|
|
3225
|
+
/* @__PURE__ */ jsx34("h3", { className: "chapter-membership-name", children: tier.name }),
|
|
3226
|
+
/* @__PURE__ */ jsxs32("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
|
|
3227
|
+
presentation.capacity ? /* @__PURE__ */ jsxs32("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
|
|
3228
|
+
/* @__PURE__ */ jsx34("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
|
|
3229
|
+
/* @__PURE__ */ jsx34("small", { children: presentation.capacity.label ?? "available" })
|
|
2623
3230
|
] }) : null,
|
|
2624
|
-
/* @__PURE__ */
|
|
2625
|
-
presentation.priceEyebrow ? /* @__PURE__ */
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
tier.founding ? /* @__PURE__ */
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
!tier.free && presentation.billingLabel ? /* @__PURE__ */
|
|
3231
|
+
/* @__PURE__ */ jsxs32("div", { className: "chapter-membership-price-stack", children: [
|
|
3232
|
+
presentation.priceEyebrow ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
|
|
3233
|
+
/* @__PURE__ */ jsxs32("div", { className: "chapter-membership-price-row", children: [
|
|
3234
|
+
tier.founding ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
|
|
3235
|
+
/* @__PURE__ */ jsx34("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
|
|
3236
|
+
!tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
|
|
2630
3237
|
] })
|
|
2631
3238
|
] })
|
|
2632
3239
|
] }),
|
|
2633
|
-
presentation.priceNoteMarkdown ? /* @__PURE__ */
|
|
2634
|
-
summary ? /* @__PURE__ */
|
|
2635
|
-
presentation.benefits?.length ? /* @__PURE__ */
|
|
2636
|
-
/* @__PURE__ */
|
|
2637
|
-
/* @__PURE__ */
|
|
3240
|
+
presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
|
|
3241
|
+
summary ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-summary", source: summary }) : null,
|
|
3242
|
+
presentation.benefits?.length ? /* @__PURE__ */ jsx34("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs32("li", { children: [
|
|
3243
|
+
/* @__PURE__ */ jsx34("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
|
|
3244
|
+
/* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-benefit", source: benefit })
|
|
2638
3245
|
] }, `${tier.id}-benefit-${index}`)) }) : null,
|
|
2639
|
-
presentation.callout ? /* @__PURE__ */
|
|
2640
|
-
presentation.callout.label ? /* @__PURE__ */
|
|
2641
|
-
/* @__PURE__ */
|
|
3246
|
+
presentation.callout ? /* @__PURE__ */ jsxs32("aside", { className: "chapter-membership-callout", children: [
|
|
3247
|
+
presentation.callout.label ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
|
|
3248
|
+
/* @__PURE__ */ jsx34(Markdown3, { source: presentation.callout.bodyMarkdown })
|
|
2642
3249
|
] }) : null,
|
|
2643
|
-
/* @__PURE__ */
|
|
3250
|
+
/* @__PURE__ */ jsx34(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
|
|
2644
3251
|
] });
|
|
2645
3252
|
}
|
|
2646
3253
|
function MembershipCards(props) {
|
|
2647
3254
|
const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
|
|
2648
3255
|
const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
|
|
2649
3256
|
const mode = props.mode ?? "link";
|
|
2650
|
-
return /* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
3257
|
+
return /* @__PURE__ */ jsxs32("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
|
|
3258
|
+
/* @__PURE__ */ jsx34("style", { children: MEMBERSHIP_CARDS_CSS }),
|
|
3259
|
+
/* @__PURE__ */ jsx34("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
|
|
2653
3260
|
const tier = byId.get(presentation.tierId);
|
|
2654
|
-
return /* @__PURE__ */
|
|
3261
|
+
return /* @__PURE__ */ jsx34(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
|
|
2655
3262
|
}) }),
|
|
2656
|
-
document2.footnoteMarkdown ? /* @__PURE__ */
|
|
3263
|
+
document2.footnoteMarkdown ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
|
|
2657
3264
|
] });
|
|
2658
3265
|
}
|
|
2659
3266
|
|
|
@@ -2687,6 +3294,29 @@ export {
|
|
|
2687
3294
|
NamedSeatRecipientLine,
|
|
2688
3295
|
NamedSeatPurchase,
|
|
2689
3296
|
MemberContentArea,
|
|
3297
|
+
placeholderBadge,
|
|
3298
|
+
MemberPlaceholderBody,
|
|
3299
|
+
PortalIcon,
|
|
3300
|
+
PROFILE_SEGMENT,
|
|
3301
|
+
routeFromLocation,
|
|
3302
|
+
hrefFor,
|
|
3303
|
+
sameRoute,
|
|
3304
|
+
PortalAvatar,
|
|
3305
|
+
navTag,
|
|
3306
|
+
PortalNav,
|
|
3307
|
+
LockedPill,
|
|
3308
|
+
UpgradeLink,
|
|
3309
|
+
LockedScreen,
|
|
3310
|
+
PlaceholderScreen,
|
|
3311
|
+
PortalPage,
|
|
3312
|
+
PortalTile,
|
|
3313
|
+
DefaultHome,
|
|
3314
|
+
memberMonth,
|
|
3315
|
+
startingPrompts,
|
|
3316
|
+
choosePrompt,
|
|
3317
|
+
MemberProfilePage,
|
|
3318
|
+
PACKAGED_PORTAL_FEATURES,
|
|
3319
|
+
MemberPortal,
|
|
2690
3320
|
MembersArea,
|
|
2691
3321
|
useTierSelection,
|
|
2692
3322
|
TierPlaceholder,
|
|
@@ -2698,4 +3328,4 @@ export {
|
|
|
2698
3328
|
membershipApplicationHref,
|
|
2699
3329
|
MembershipCards
|
|
2700
3330
|
};
|
|
2701
|
-
//# sourceMappingURL=chunk-
|
|
3331
|
+
//# sourceMappingURL=chunk-ZIYK3OV2.js.map
|