@odla-ai/chapter 0.61.0 → 0.63.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 +185 -0
- package/dist/{chunk-PKVHXKGJ.js → chunk-OXYMVK2O.js} +203 -1
- package/dist/chunk-OXYMVK2O.js.map +1 -0
- package/dist/{chunk-RTJKUOFE.js → chunk-QPFJBHHK.js} +1292 -303
- package/dist/chunk-QPFJBHHK.js.map +1 -0
- package/dist/{chunk-24L7FANC.js → chunk-S6VPJFHL.js} +1173 -708
- package/dist/chunk-S6VPJFHL.js.map +1 -0
- package/dist/copy-context-BNKK7ZDm.d.ts +370 -0
- package/dist/index.cjs +4200 -3240
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +577 -84
- package/dist/index.d.ts +577 -84
- package/dist/index.js +4203 -3243
- 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 +99 -11
- package/dist/ui/member/index.d.ts +426 -3
- package/dist/ui/member/index.js +98 -10
- package/dist/worker/index.cjs +3999 -2061
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +227 -81
- package/dist/worker/index.d.ts +227 -81
- package/dist/worker/index.js +4013 -2075
- 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
|
@@ -1,69 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_JOIN_COPY,
|
|
3
|
+
dayLabel,
|
|
4
|
+
fmtDate,
|
|
5
|
+
fmtMoney,
|
|
3
6
|
formatChapterCopy,
|
|
7
|
+
fullLabel,
|
|
8
|
+
groupSlotsByDay,
|
|
9
|
+
timeLabel,
|
|
4
10
|
useChapterCopy
|
|
5
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-OXYMVK2O.js";
|
|
6
12
|
import {
|
|
7
13
|
collectFormFields
|
|
8
14
|
} from "./chunk-IVXVECKR.js";
|
|
9
15
|
|
|
10
16
|
// src/ui/slot-picker.tsx
|
|
11
17
|
import { useMemo, useState } from "preact/hooks";
|
|
12
|
-
|
|
13
|
-
// src/ui/datetime.ts
|
|
14
|
-
function tzShort(tz) {
|
|
15
|
-
try {
|
|
16
|
-
const parts = new Intl.DateTimeFormat(void 0, { timeZone: tz, timeZoneName: "short" }).formatToParts(
|
|
17
|
-
/* @__PURE__ */ new Date()
|
|
18
|
-
);
|
|
19
|
-
return parts.find((p) => p.type === "timeZoneName")?.value ?? tz;
|
|
20
|
-
} catch {
|
|
21
|
-
return tz;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function dayKey(ms, tz) {
|
|
25
|
-
return new Date(ms).toLocaleDateString("en-CA", { timeZone: tz });
|
|
26
|
-
}
|
|
27
|
-
function dayLabel(ms, tz) {
|
|
28
|
-
return new Date(ms).toLocaleDateString(void 0, { timeZone: tz, weekday: "short", month: "short", day: "numeric" });
|
|
29
|
-
}
|
|
30
|
-
function timeLabel(ms, tz) {
|
|
31
|
-
return new Date(ms).toLocaleTimeString(void 0, {
|
|
32
|
-
timeZone: tz,
|
|
33
|
-
hour: "numeric",
|
|
34
|
-
minute: "2-digit",
|
|
35
|
-
timeZoneName: "short"
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
function fullLabel(ms, tz) {
|
|
39
|
-
return new Date(ms).toLocaleString(void 0, {
|
|
40
|
-
timeZone: tz,
|
|
41
|
-
weekday: "long",
|
|
42
|
-
month: "long",
|
|
43
|
-
day: "numeric",
|
|
44
|
-
hour: "numeric",
|
|
45
|
-
minute: "2-digit",
|
|
46
|
-
timeZoneName: "short"
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
function fmtMoney(cents) {
|
|
50
|
-
return "$" + Math.round(cents / 100).toLocaleString();
|
|
51
|
-
}
|
|
52
|
-
function fmtDate(ms) {
|
|
53
|
-
return new Date(ms).toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
|
|
54
|
-
}
|
|
55
|
-
function groupSlotsByDay(slots, tz) {
|
|
56
|
-
const byDay = /* @__PURE__ */ new Map();
|
|
57
|
-
for (const s of slots) {
|
|
58
|
-
const k = dayKey(s.startAt, tz);
|
|
59
|
-
const bucket = byDay.get(k);
|
|
60
|
-
if (bucket) bucket.push(s);
|
|
61
|
-
else byDay.set(k, [s]);
|
|
62
|
-
}
|
|
63
|
-
return byDay;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/ui/slot-picker.tsx
|
|
67
18
|
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
68
19
|
var DEFAULT_CLASSES = {
|
|
69
20
|
days: "slot-days",
|
|
@@ -867,7 +818,7 @@ function MemberRestart(props) {
|
|
|
867
818
|
}
|
|
868
819
|
|
|
869
820
|
// src/ui/members.tsx
|
|
870
|
-
import { useEffect as
|
|
821
|
+
import { useEffect as useEffect11, useState as useState18 } from "preact/hooks";
|
|
871
822
|
|
|
872
823
|
// src/ui/reschedule.tsx
|
|
873
824
|
import { useState as useState8 } from "preact/hooks";
|
|
@@ -1316,7 +1267,8 @@ function MemberContentArea(props) {
|
|
|
1316
1267
|
list.push(page);
|
|
1317
1268
|
result.set(page.navigation.section, list);
|
|
1318
1269
|
}
|
|
1319
|
-
|
|
1270
|
+
const declared = data?.sections ?? [...result.keys()].map((id) => ({ id, label: id }));
|
|
1271
|
+
return declared.filter((section) => result.has(section.id)).map((section) => [section.label ?? "", result.get(section.id)]);
|
|
1320
1272
|
}, [data]);
|
|
1321
1273
|
if (error) return /* @__PURE__ */ jsxs15("p", { className: "meeting-note", role: "alert", children: [
|
|
1322
1274
|
"Member pages could not be loaded: ",
|
|
@@ -1327,8 +1279,8 @@ function MemberContentArea(props) {
|
|
|
1327
1279
|
const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
|
|
1328
1280
|
const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
|
|
1329
1281
|
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 }),
|
|
1282
|
+
/* @__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: [
|
|
1283
|
+
section ? /* @__PURE__ */ jsx16("h2", { children: section }) : null,
|
|
1332
1284
|
/* @__PURE__ */ jsx16("ul", { children: pages.map((page) => /* @__PURE__ */ jsx16("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx16(
|
|
1333
1285
|
"button",
|
|
1334
1286
|
{
|
|
@@ -1338,7 +1290,7 @@ function MemberContentArea(props) {
|
|
|
1338
1290
|
children: pageLabel(page)
|
|
1339
1291
|
}
|
|
1340
1292
|
) }, page.id)) })
|
|
1341
|
-
] }, section)) }),
|
|
1293
|
+
] }, `${index}:${section}`)) }),
|
|
1342
1294
|
/* @__PURE__ */ jsxs15("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
|
|
1343
1295
|
/* @__PURE__ */ jsxs15("header", { children: [
|
|
1344
1296
|
/* @__PURE__ */ jsxs15("div", { className: "card-label", children: [
|
|
@@ -1349,7 +1301,7 @@ function MemberContentArea(props) {
|
|
|
1349
1301
|
/* @__PURE__ */ jsx16("h1", { children: selected.title }),
|
|
1350
1302
|
selected.summary ? /* @__PURE__ */ jsx16("p", { children: selected.summary }) : null
|
|
1351
1303
|
] }),
|
|
1352
|
-
selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content-locked", children: [
|
|
1304
|
+
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
1305
|
selected.teaserMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx16("p", { children: "This page is not included in your current membership." }),
|
|
1354
1306
|
selected.upsell ? /* @__PURE__ */ jsxs15("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
|
|
1355
1307
|
/* @__PURE__ */ jsx16("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
|
|
@@ -1361,14 +1313,986 @@ function MemberContentArea(props) {
|
|
|
1361
1313
|
] })
|
|
1362
1314
|
] });
|
|
1363
1315
|
}
|
|
1316
|
+
var placeholderBadge = (page) => page.placeholder?.badge ?? (page.placeholder?.availableYear ? `Coming in ${page.placeholder.availableYear}` : "Coming soon");
|
|
1317
|
+
function MemberPlaceholderBody({ page }) {
|
|
1318
|
+
return /* @__PURE__ */ jsxs15("div", { className: "chapter-member-placeholder", "data-placeholder": true, children: [
|
|
1319
|
+
/* @__PURE__ */ jsx16("div", { className: "card-label", children: placeholderBadge(page) }),
|
|
1320
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: page.bodyMarkdown }) : null,
|
|
1321
|
+
page.placeholder?.actionLabel ? /* @__PURE__ */ jsx16("button", { className: "btn secondary", type: "button", disabled: true, children: page.placeholder.actionLabel }) : null
|
|
1322
|
+
] });
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// src/ui/member-portal.tsx
|
|
1326
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useState as useState17 } from "preact/hooks";
|
|
1327
|
+
|
|
1328
|
+
// src/ui/member-portal-nav.tsx
|
|
1329
|
+
import { ThemeScope } from "@odla-ai/ui/components";
|
|
1330
|
+
|
|
1331
|
+
// src/ui/member-portal-icons.tsx
|
|
1332
|
+
import { jsx as jsx17 } from "preact/jsx-runtime";
|
|
1333
|
+
var PATHS = {
|
|
1334
|
+
home: ["M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z"],
|
|
1335
|
+
course: ["M22 10 12 5 2 10l10 5 10-5z", "M6 12v5c3 2 9 2 12 0v-5"],
|
|
1336
|
+
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"],
|
|
1337
|
+
deals: ["M3 17l6-6 4 4 8-8", "M14 7h7v7"],
|
|
1338
|
+
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"],
|
|
1339
|
+
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"],
|
|
1340
|
+
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"],
|
|
1341
|
+
share: ["M12 3v12", "m7 8 5-5 5 5", "M5 14v5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5"],
|
|
1342
|
+
profile: ["M12 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8z", "M4 21a8 8 0 0 1 16 0"],
|
|
1343
|
+
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"],
|
|
1344
|
+
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"],
|
|
1345
|
+
chat: ["M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12z"],
|
|
1346
|
+
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"],
|
|
1347
|
+
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"],
|
|
1348
|
+
menu: ["M4 7h16M4 12h16M4 17h16"],
|
|
1349
|
+
close: ["M6 6l12 12M18 6 6 18"]
|
|
1350
|
+
};
|
|
1351
|
+
function PortalIcon({ name, size = 18, label }) {
|
|
1352
|
+
return /* @__PURE__ */ jsx17(
|
|
1353
|
+
"svg",
|
|
1354
|
+
{
|
|
1355
|
+
width: size,
|
|
1356
|
+
height: size,
|
|
1357
|
+
viewBox: "0 0 24 24",
|
|
1358
|
+
fill: "none",
|
|
1359
|
+
stroke: "currentColor",
|
|
1360
|
+
"stroke-width": "1.8",
|
|
1361
|
+
"stroke-linecap": "round",
|
|
1362
|
+
"stroke-linejoin": "round",
|
|
1363
|
+
"aria-hidden": label ? void 0 : "true",
|
|
1364
|
+
"aria-label": label,
|
|
1365
|
+
role: label ? "img" : void 0,
|
|
1366
|
+
focusable: "false",
|
|
1367
|
+
children: PATHS[name].map((d) => /* @__PURE__ */ jsx17("path", { d }, d))
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
// src/ui/member-portal-routing.ts
|
|
1373
|
+
var PROFILE_SEGMENT = "profile";
|
|
1374
|
+
var trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
|
|
1375
|
+
function routeFromLocation(location2, routing) {
|
|
1376
|
+
let segment = "";
|
|
1377
|
+
if (routing.mode === "hash") segment = trimSlashes(decodeURIComponent(location2.hash.replace(/^#/, "")));
|
|
1378
|
+
else {
|
|
1379
|
+
const base = `/${trimSlashes(routing.basePath)}`;
|
|
1380
|
+
const path = location2.pathname;
|
|
1381
|
+
if (path === base || path.startsWith(`${base}/`)) segment = trimSlashes(decodeURIComponent(path.slice(base.length)));
|
|
1382
|
+
}
|
|
1383
|
+
if (!segment) return { kind: "home" };
|
|
1384
|
+
if (segment === PROFILE_SEGMENT) return { kind: "profile" };
|
|
1385
|
+
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(segment) ? { kind: "page", slug: segment } : { kind: "home" };
|
|
1386
|
+
}
|
|
1387
|
+
function hrefFor(route, routing) {
|
|
1388
|
+
const base = `/${trimSlashes(routing.basePath)}`.replace(/^\/$/, "");
|
|
1389
|
+
const segment = route.kind === "home" ? "" : route.kind === "profile" ? PROFILE_SEGMENT : route.slug;
|
|
1390
|
+
if (routing.mode === "hash") return segment ? `${base}/#${segment}` : `${base}/`;
|
|
1391
|
+
return segment ? `${base}/${segment}` : `${base}/`;
|
|
1392
|
+
}
|
|
1393
|
+
var sameRoute = (a, b) => a.kind === b.kind && (a.kind !== "page" || a.slug === b.slug);
|
|
1394
|
+
|
|
1395
|
+
// src/ui/member-portal-nav.tsx
|
|
1396
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
1397
|
+
function PortalAvatar({ me, className }) {
|
|
1398
|
+
return /* @__PURE__ */ jsx18("span", { className: `chapter-portal-avatar${className ? ` ${className}` : ""}`, children: me.photoUrl ? /* @__PURE__ */ jsx18("img", { src: me.photoUrl, alt: "" }) : me.initials });
|
|
1399
|
+
}
|
|
1400
|
+
function navTag(page, copy) {
|
|
1401
|
+
if (page.access === "locked") return { kind: "lock", text: copy.shell.locked };
|
|
1402
|
+
if (page.navigation.tag === "new") return { kind: "new", text: copy.pages.tagNew };
|
|
1403
|
+
if (page.kind === "placeholder") {
|
|
1404
|
+
const year = page.placeholder?.availableYear;
|
|
1405
|
+
return { kind: "soon", text: year ? String(year) : copy.pages.tagSoon };
|
|
1406
|
+
}
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
function Groups({ content, route, copy, onNavigate }) {
|
|
1410
|
+
const sections = content.sections ?? [...new Set(content.pages.map((page) => page.navigation.section))].map((id) => ({ id, label: id }));
|
|
1411
|
+
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: [
|
|
1412
|
+
/* @__PURE__ */ jsx18(PortalIcon, { name: icon }),
|
|
1413
|
+
/* @__PURE__ */ jsx18("span", { children: label }),
|
|
1414
|
+
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
|
|
1415
|
+
] });
|
|
1416
|
+
return /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
1417
|
+
/* @__PURE__ */ jsx18("div", { children: item({ kind: "home" }, "home", copy.shell.home) }),
|
|
1418
|
+
sections.map((section) => {
|
|
1419
|
+
const pages = content.pages.filter((page) => page.navigation.section === section.id && !page.navigation.parentId);
|
|
1420
|
+
if (!pages.length) return null;
|
|
1421
|
+
return /* @__PURE__ */ jsxs16("div", { children: [
|
|
1422
|
+
section.label ? /* @__PURE__ */ jsx18("div", { className: "chapter-portal-group-label", children: section.label }) : null,
|
|
1423
|
+
pages.map((page) => /* @__PURE__ */ jsx18("div", { children: item({ kind: "page", slug: page.slug }, page.navigation.icon ?? "document", page.title, navTag(page, copy)) }, page.id))
|
|
1424
|
+
] }, section.id);
|
|
1425
|
+
})
|
|
1426
|
+
] });
|
|
1427
|
+
}
|
|
1428
|
+
function Account(props) {
|
|
1429
|
+
const { me, email, route, copy, adminHref, onNavigate, onSignOut } = props;
|
|
1430
|
+
return /* @__PURE__ */ jsxs16("div", { className: "chapter-portal-account", children: [
|
|
1431
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", className: "chapter-portal-nav-item", "aria-current": route.kind === "profile" ? "page" : void 0, onClick: () => onNavigate({ kind: "profile" }), children: [
|
|
1432
|
+
/* @__PURE__ */ jsx18(PortalAvatar, { me }),
|
|
1433
|
+
/* @__PURE__ */ jsx18("span", { children: copy.shell.yourProfile })
|
|
1434
|
+
] }),
|
|
1435
|
+
/* @__PURE__ */ jsx18("div", { children: copy.shell.signedInAs }),
|
|
1436
|
+
/* @__PURE__ */ jsx18("div", { children: email }),
|
|
1437
|
+
/* @__PURE__ */ jsxs16("div", { style: { marginTop: ".5rem", display: "flex", gap: "1rem", flexWrap: "wrap" }, children: [
|
|
1438
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: "chapter-portal-link", onClick: onSignOut, children: copy.shell.signOut }),
|
|
1439
|
+
adminHref ? /* @__PURE__ */ jsx18("a", { href: adminHref, children: copy.shell.adminConsole }) : null
|
|
1440
|
+
] })
|
|
1441
|
+
] });
|
|
1442
|
+
}
|
|
1443
|
+
function PortalNav(props) {
|
|
1444
|
+
const island = props.sidebarTokens ? void 0 : "ui-invert";
|
|
1445
|
+
return /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
1446
|
+
/* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-side ${island ?? ""}`, role: "complementary", "aria-label": props.copy.shell.navLabel, children: [
|
|
1447
|
+
/* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
|
|
1448
|
+
/* @__PURE__ */ jsx18(Groups, { ...props }),
|
|
1449
|
+
/* @__PURE__ */ jsx18(Account, { ...props })
|
|
1450
|
+
] }),
|
|
1451
|
+
/* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-mobile ${island ?? ""}`, children: [
|
|
1452
|
+
/* @__PURE__ */ jsxs16("div", { className: "chapter-portal-mobile-bar", children: [
|
|
1453
|
+
/* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
|
|
1454
|
+
/* @__PURE__ */ jsx18(
|
|
1455
|
+
"button",
|
|
1456
|
+
{
|
|
1457
|
+
type: "button",
|
|
1458
|
+
className: "chapter-portal-burger",
|
|
1459
|
+
"aria-expanded": props.menuOpen,
|
|
1460
|
+
"aria-label": props.menuOpen ? props.copy.shell.closeMenu : props.copy.shell.openMenu,
|
|
1461
|
+
onClick: props.onToggleMenu,
|
|
1462
|
+
children: /* @__PURE__ */ jsx18(PortalIcon, { name: props.menuOpen ? "close" : "menu", size: 22 })
|
|
1463
|
+
}
|
|
1464
|
+
)
|
|
1465
|
+
] }),
|
|
1466
|
+
props.menuOpen ? /* @__PURE__ */ jsxs16("nav", { className: "chapter-portal-mobile-menu", "aria-label": props.copy.shell.navLabel, children: [
|
|
1467
|
+
/* @__PURE__ */ jsx18(Groups, { ...props }),
|
|
1468
|
+
/* @__PURE__ */ jsx18(Account, { ...props })
|
|
1469
|
+
] }) : null
|
|
1470
|
+
] })
|
|
1471
|
+
] });
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// src/ui/member-portal-pages.tsx
|
|
1475
|
+
import { Markdown as Markdown2 } from "@odla-ai/ui/components";
|
|
1476
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
1477
|
+
var upsellOf = (page, ctx) => {
|
|
1478
|
+
const tierName = page.upsell?.tierName;
|
|
1479
|
+
const tierId = page.upsell?.tierId ?? (page.audience.kind === "tiers" ? page.audience.tierIds[0] : void 0);
|
|
1480
|
+
const href = tierId && ctx.upsellHref ? ctx.upsellHref(tierId, page) : void 0;
|
|
1481
|
+
return { tierName, href, cta: page.upsell?.ctaLabel ?? ctx.copy.pages.upgrade };
|
|
1482
|
+
};
|
|
1483
|
+
function LockedPill({ page, ctx }) {
|
|
1484
|
+
const { tierName } = upsellOf(page, ctx);
|
|
1485
|
+
return /* @__PURE__ */ jsxs17("span", { className: "chapter-portal-pill", children: [
|
|
1486
|
+
/* @__PURE__ */ jsx19(PortalIcon, { name: "lock", size: 12 }),
|
|
1487
|
+
tierName ? formatChapterCopy(ctx.copy.pages.includedWith, { tierName }) : ctx.copy.shell.locked
|
|
1488
|
+
] });
|
|
1489
|
+
}
|
|
1490
|
+
function UpgradeLink({ page, ctx, variant }) {
|
|
1491
|
+
const { href, cta } = upsellOf(page, ctx);
|
|
1492
|
+
return href ? /* @__PURE__ */ jsx19("a", { className: "chapter-portal-btn", "data-variant": variant, href, target: "_blank", rel: "noopener", children: cta }) : null;
|
|
1493
|
+
}
|
|
1494
|
+
function LockedScreen({ page, ctx }) {
|
|
1495
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-access": "locked", children: [
|
|
1496
|
+
/* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
|
|
1497
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1498
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1499
|
+
page.teaserMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.teaserMarkdown }) : null,
|
|
1500
|
+
page.upsell?.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.upsell.bodyMarkdown }) : null,
|
|
1501
|
+
/* @__PURE__ */ jsx19("div", { className: "chapter-portal-btns", style: { justifyContent: "center", marginTop: "1.25rem" }, children: /* @__PURE__ */ jsx19(UpgradeLink, { page, ctx }) })
|
|
1502
|
+
] });
|
|
1503
|
+
}
|
|
1504
|
+
function PlaceholderScreen({ page }) {
|
|
1505
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-placeholder": true, children: [
|
|
1506
|
+
/* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", children: placeholderBadge(page) }),
|
|
1507
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1508
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1509
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null,
|
|
1510
|
+
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
|
|
1511
|
+
] });
|
|
1512
|
+
}
|
|
1513
|
+
function PortalPage({ page, ctx, features }) {
|
|
1514
|
+
if (page.access === "locked") return /* @__PURE__ */ jsx19(LockedScreen, { page, ctx });
|
|
1515
|
+
if (page.kind === "placeholder") return /* @__PURE__ */ jsx19(PlaceholderScreen, { page });
|
|
1516
|
+
if (page.kind === "feature" && page.feature) {
|
|
1517
|
+
const feature = features[page.feature.name];
|
|
1518
|
+
if (feature) return /* @__PURE__ */ jsx19(Fragment6, { children: feature.page(page, ctx) });
|
|
1519
|
+
}
|
|
1520
|
+
return /* @__PURE__ */ jsxs17("article", { className: "chapter-portal-card", children: [
|
|
1521
|
+
/* @__PURE__ */ jsx19("h2", { children: page.title }),
|
|
1522
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1523
|
+
page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null
|
|
1524
|
+
] });
|
|
1525
|
+
}
|
|
1526
|
+
function PortalTile({ page, ctx }) {
|
|
1527
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-tile", "data-access": page.access, children: [
|
|
1528
|
+
/* @__PURE__ */ jsx19(PortalIcon, { name: page.navigation.icon ?? "document", size: 22 }),
|
|
1529
|
+
/* @__PURE__ */ jsx19("h3", { children: page.title }),
|
|
1530
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1531
|
+
page.access === "locked" ? /* @__PURE__ */ jsx19(LockedPill, { page, ctx }) : /* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", style: { alignSelf: "flex-start" }, children: placeholderBadge(page) })
|
|
1532
|
+
] });
|
|
1533
|
+
}
|
|
1534
|
+
function DefaultHome({ ctx, features, slots }) {
|
|
1535
|
+
const panels = ctx.content.pages.filter((page) => page.kind === "feature" && page.feature && features[page.feature.name]?.home);
|
|
1536
|
+
const soon = ctx.content.pages.filter((page) => page.kind === "placeholder");
|
|
1537
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-stack", children: [
|
|
1538
|
+
slots.top?.(ctx) ?? null,
|
|
1539
|
+
panels.map((page) => {
|
|
1540
|
+
const panel = features[page.feature.name].home(page, ctx);
|
|
1541
|
+
if (page.access !== "locked") return /* @__PURE__ */ jsx19("div", { children: panel }, page.id);
|
|
1542
|
+
return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-locked-wrap", style: { position: "relative" }, children: [
|
|
1543
|
+
/* @__PURE__ */ jsx19("div", { "aria-hidden": "true", inert: true, style: { opacity: 0.35, filter: "grayscale(1)", pointerEvents: "none" }, children: panel }),
|
|
1544
|
+
/* @__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: [
|
|
1545
|
+
/* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
|
|
1546
|
+
/* @__PURE__ */ jsx19("h3", { children: page.title }),
|
|
1547
|
+
page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
|
|
1548
|
+
/* @__PURE__ */ jsx19(UpgradeLink, { page, ctx })
|
|
1549
|
+
] }) })
|
|
1550
|
+
] }, page.id);
|
|
1551
|
+
}),
|
|
1552
|
+
slots.middle?.(ctx) ?? null,
|
|
1553
|
+
soon.length ? /* @__PURE__ */ jsxs17("section", { children: [
|
|
1554
|
+
/* @__PURE__ */ jsx19("h2", { style: { fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400 }, children: ctx.copy.pages.comingToPortal }),
|
|
1555
|
+
/* @__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)) })
|
|
1556
|
+
] }) : null
|
|
1557
|
+
] });
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
// src/ui/member-profile-page.tsx
|
|
1561
|
+
import { useEffect as useEffect6, useState as useState13 } from "preact/hooks";
|
|
1562
|
+
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
1563
|
+
var memberMonth = (at) => new Date(at).toLocaleString("en-US", { month: "long", year: "numeric", timeZone: "UTC" });
|
|
1564
|
+
var startingPrompts = (view) => view.profile.prompts.length ? view.profile.prompts : view.promptChoices.slice(0, view.maxPrompts).map((prompt) => ({ prompt, answer: "" }));
|
|
1565
|
+
function choosePrompt(prompts, prompt, max) {
|
|
1566
|
+
if (prompts.some((entry) => entry.prompt === prompt) || max === 0) return prompts;
|
|
1567
|
+
return prompts.length < max ? [...prompts, { prompt, answer: "" }] : [...prompts.slice(0, max - 1), { prompt, answer: "" }];
|
|
1568
|
+
}
|
|
1569
|
+
async function resizePhoto(file) {
|
|
1570
|
+
const bitmap = await createImageBitmap(file);
|
|
1571
|
+
const side = Math.min(bitmap.width, bitmap.height);
|
|
1572
|
+
const canvas = document.createElement("canvas");
|
|
1573
|
+
canvas.width = canvas.height = 400;
|
|
1574
|
+
canvas.getContext("2d").drawImage(bitmap, (bitmap.width - side) / 2, (bitmap.height - side) / 2, side, side, 0, 0, 400, 400);
|
|
1575
|
+
return new Promise((resolve, reject) => canvas.toBlob((blob) => blob ? resolve(blob) : reject(new Error("encode failed")), "image/jpeg", 0.9));
|
|
1576
|
+
}
|
|
1577
|
+
function MemberProfilePage({ ctx, middle, extras }) {
|
|
1578
|
+
const copy = ctx.copy.profile;
|
|
1579
|
+
const [view, setView] = useState13(null);
|
|
1580
|
+
const [draft, setDraft] = useState13(null);
|
|
1581
|
+
const [status, setStatus] = useState13(null);
|
|
1582
|
+
const [busy, setBusy] = useState13(false);
|
|
1583
|
+
const load = async () => {
|
|
1584
|
+
try {
|
|
1585
|
+
setView(await ctx.api("/api/member/profile"));
|
|
1586
|
+
} catch {
|
|
1587
|
+
setStatus(ctx.copy.shell.loadFailed);
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
useEffect6(() => {
|
|
1591
|
+
void load();
|
|
1592
|
+
}, []);
|
|
1593
|
+
if (!view) return /* @__PURE__ */ jsx20("p", { children: status ?? ctx.copy.shell.loading });
|
|
1594
|
+
const prompts = draft?.prompts ?? startingPrompts(view);
|
|
1595
|
+
const edit = () => setDraft({
|
|
1596
|
+
preferredName: view.profile.preferredName ?? ctx.me.displayName,
|
|
1597
|
+
location: view.profile.location ?? "",
|
|
1598
|
+
introducedByText: view.profile.introducedByText ?? "",
|
|
1599
|
+
prompts: startingPrompts(view)
|
|
1600
|
+
});
|
|
1601
|
+
const save = async () => {
|
|
1602
|
+
if (!draft) return;
|
|
1603
|
+
setBusy(true);
|
|
1604
|
+
try {
|
|
1605
|
+
const next = await ctx.api("/api/member/profile", { method: "PUT", headers: { "content-type": "application/json" }, body: JSON.stringify({
|
|
1606
|
+
expectedRevision: view.revision,
|
|
1607
|
+
preferredName: draft.preferredName,
|
|
1608
|
+
location: draft.location,
|
|
1609
|
+
introducedByText: draft.introducedByText,
|
|
1610
|
+
prompts: draft.prompts
|
|
1611
|
+
}) });
|
|
1612
|
+
setView(next);
|
|
1613
|
+
setDraft(null);
|
|
1614
|
+
setStatus(copy.saved);
|
|
1615
|
+
await ctx.reloadMe();
|
|
1616
|
+
} catch (error) {
|
|
1617
|
+
setStatus(String(error).includes("409") ? copy.conflict : copy.saveFailed);
|
|
1618
|
+
} finally {
|
|
1619
|
+
setBusy(false);
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
const upload = async (file) => {
|
|
1623
|
+
if (!file) return;
|
|
1624
|
+
setBusy(true);
|
|
1625
|
+
setStatus(copy.photoUploading);
|
|
1626
|
+
try {
|
|
1627
|
+
if (file.size > 10 * 1024 * 1024) throw new Error("too large");
|
|
1628
|
+
await ctx.api("/api/member/profile/photo", { method: "POST", headers: { "content-type": "image/jpeg" }, body: await resizePhoto(file) });
|
|
1629
|
+
setStatus(null);
|
|
1630
|
+
await ctx.reloadMe();
|
|
1631
|
+
} catch {
|
|
1632
|
+
setStatus(copy.photoFailed);
|
|
1633
|
+
} finally {
|
|
1634
|
+
setBusy(false);
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
const remaining = view.promptChoices.filter((choice) => !prompts.some((entry) => entry.prompt === choice));
|
|
1638
|
+
return /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-stack", "data-portal-profile": true, children: [
|
|
1639
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", style: { display: "flex", gap: "1.25rem", alignItems: "center", flexWrap: "wrap" }, children: [
|
|
1640
|
+
/* @__PURE__ */ jsxs18("div", { style: { textAlign: "center" }, children: [
|
|
1641
|
+
/* @__PURE__ */ jsx20(PortalAvatar, { me: ctx.me, className: "chapter-portal-profile-photo" }),
|
|
1642
|
+
view.photos ? /* @__PURE__ */ jsxs18("label", { className: "chapter-portal-btn", "data-variant": "ghost", style: { marginTop: ".6rem", padding: ".35rem .8rem", fontSize: ".78rem" }, children: [
|
|
1643
|
+
ctx.me.photoUrl ? copy.changePhoto : copy.uploadPhoto,
|
|
1644
|
+
/* @__PURE__ */ jsx20("input", { type: "file", accept: "image/jpeg,image/png", hidden: true, disabled: busy, onChange: (event) => void upload(event.currentTarget.files?.[0]) })
|
|
1645
|
+
] }) : null
|
|
1646
|
+
] }),
|
|
1647
|
+
/* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: "12rem" }, children: [
|
|
1648
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: copy.eyebrow }),
|
|
1649
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1650
|
+
"input",
|
|
1651
|
+
{
|
|
1652
|
+
"aria-label": copy.namePlaceholder,
|
|
1653
|
+
placeholder: copy.namePlaceholder,
|
|
1654
|
+
value: draft.preferredName,
|
|
1655
|
+
maxLength: 80,
|
|
1656
|
+
onInput: (event) => setDraft({ ...draft, preferredName: event.currentTarget.value })
|
|
1657
|
+
}
|
|
1658
|
+
) : /* @__PURE__ */ jsx20("h2", { style: { margin: ".2rem 0" }, children: ctx.me.displayName }),
|
|
1659
|
+
/* @__PURE__ */ jsxs18("p", { style: { margin: 0, color: "var(--ui-text-muted)" }, children: [
|
|
1660
|
+
ctx.me.tier && ctx.me.memberSince ? formatChapterCopy(copy.memberSince, { tierName: ctx.me.tier.name, month: memberMonth(ctx.me.memberSince) }) : null,
|
|
1661
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1662
|
+
"input",
|
|
1663
|
+
{
|
|
1664
|
+
"aria-label": copy.locationPlaceholder,
|
|
1665
|
+
placeholder: copy.locationPlaceholder,
|
|
1666
|
+
value: draft.location,
|
|
1667
|
+
maxLength: 80,
|
|
1668
|
+
onInput: (event) => setDraft({ ...draft, location: event.currentTarget.value })
|
|
1669
|
+
}
|
|
1670
|
+
) : ctx.me.location ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
|
|
1671
|
+
" \xB7 ",
|
|
1672
|
+
ctx.me.location
|
|
1673
|
+
] }) : null
|
|
1674
|
+
] })
|
|
1675
|
+
] }),
|
|
1676
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-btns", children: [
|
|
1677
|
+
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 }),
|
|
1678
|
+
draft ? /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", disabled: busy, onClick: () => setDraft(null), children: copy.cancel }) : null
|
|
1679
|
+
] })
|
|
1680
|
+
] }),
|
|
1681
|
+
status ? /* @__PURE__ */ jsx20("p", { role: "status", children: status }) : null,
|
|
1682
|
+
view.maxPrompts > 0 && view.promptChoices.length ? /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1683
|
+
/* @__PURE__ */ jsx20("h2", { children: copy.promptsTitle }),
|
|
1684
|
+
/* @__PURE__ */ jsx20("p", { style: { color: "var(--ui-text-muted)" }, children: formatChapterCopy(copy.promptsNote, { count: String(view.maxPrompts) }) }),
|
|
1685
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-tiles", children: prompts.map((entry, index) => /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx20("q", { children: entry.prompt }),
|
|
1687
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1688
|
+
"textarea",
|
|
1689
|
+
{
|
|
1690
|
+
"aria-label": entry.prompt,
|
|
1691
|
+
maxLength: 280,
|
|
1692
|
+
rows: 3,
|
|
1693
|
+
value: entry.answer,
|
|
1694
|
+
onInput: (event) => setDraft({ ...draft, prompts: draft.prompts.map((p, i) => i === index ? { ...p, answer: event.currentTarget.value } : p) })
|
|
1695
|
+
}
|
|
1696
|
+
) : /* @__PURE__ */ jsx20("p", { children: entry.answer || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.answerEmpty }) })
|
|
1697
|
+
] }, entry.prompt)) }),
|
|
1698
|
+
/* @__PURE__ */ jsx20("div", { className: "chapter-portal-btns", style: { marginTop: "1rem" }, children: remaining.map((choice) => /* @__PURE__ */ jsx20(
|
|
1699
|
+
"button",
|
|
1700
|
+
{
|
|
1701
|
+
type: "button",
|
|
1702
|
+
className: "chapter-portal-pill",
|
|
1703
|
+
style: { cursor: "pointer", background: "transparent" },
|
|
1704
|
+
onClick: () => {
|
|
1705
|
+
const base = draft ?? { preferredName: view.profile.preferredName ?? ctx.me.displayName, location: view.profile.location ?? "", introducedByText: view.profile.introducedByText ?? "", prompts };
|
|
1706
|
+
setDraft({ ...base, prompts: choosePrompt(base.prompts, choice, view.maxPrompts) });
|
|
1707
|
+
},
|
|
1708
|
+
children: formatChapterCopy(copy.addPrompt, { prompt: choice })
|
|
1709
|
+
},
|
|
1710
|
+
choice
|
|
1711
|
+
)) })
|
|
1712
|
+
] }) : null,
|
|
1713
|
+
middle,
|
|
1714
|
+
/* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
|
|
1715
|
+
/* @__PURE__ */ jsx20("h2", { children: copy.howYouFoundUs }),
|
|
1716
|
+
view.referredBy ? /* @__PURE__ */ jsxs18("p", { children: [
|
|
1717
|
+
/* @__PURE__ */ jsx20("strong", { children: copy.referredBy }),
|
|
1718
|
+
" \xB7 ",
|
|
1719
|
+
/* @__PURE__ */ jsx20("strong", { children: view.referredBy.name }),
|
|
1720
|
+
" ",
|
|
1721
|
+
/* @__PURE__ */ jsxs18("span", { style: { color: "var(--ui-text-muted)" }, children: [
|
|
1722
|
+
"\xB7 ",
|
|
1723
|
+
copy.referredByNote
|
|
1724
|
+
] })
|
|
1725
|
+
] }) : null,
|
|
1726
|
+
/* @__PURE__ */ jsxs18("label", { style: { display: "block" }, children: [
|
|
1727
|
+
/* @__PURE__ */ jsx20("span", { children: copy.introducedBy }),
|
|
1728
|
+
draft ? /* @__PURE__ */ jsx20(
|
|
1729
|
+
"input",
|
|
1730
|
+
{
|
|
1731
|
+
placeholder: copy.introducedByPlaceholder,
|
|
1732
|
+
value: draft.introducedByText,
|
|
1733
|
+
maxLength: 120,
|
|
1734
|
+
onInput: (event) => setDraft({ ...draft, introducedByText: event.currentTarget.value })
|
|
1735
|
+
}
|
|
1736
|
+
) : /* @__PURE__ */ jsx20("p", { children: view.profile.introducedByText || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.introducedByPlaceholder }) })
|
|
1737
|
+
] })
|
|
1738
|
+
] }),
|
|
1739
|
+
extras
|
|
1740
|
+
] });
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// src/ui/member-portal-styles.ts
|
|
1744
|
+
var MEMBER_PORTAL_CSS = `
|
|
1745
|
+
.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}
|
|
1746
|
+
.chapter-portal *,.chapter-portal *::before,.chapter-portal *::after{box-sizing:border-box}
|
|
1747
|
+
.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)}
|
|
1748
|
+
.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}
|
|
1749
|
+
.chapter-portal-brand :where(img,svg){width:30px;height:30px;flex:none}
|
|
1750
|
+
.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)}
|
|
1751
|
+
.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}
|
|
1752
|
+
.chapter-portal-nav-item:hover{background:color-mix(in srgb,var(--ui-text,#fff) 8%,transparent)}
|
|
1753
|
+
.chapter-portal-nav-item[aria-current=page]{background:color-mix(in srgb,var(--ui-text,#fff) 14%,transparent);font-weight:600}
|
|
1754
|
+
.chapter-portal-nav-item>span:first-of-type{flex:1;min-width:0}
|
|
1755
|
+
.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)}
|
|
1756
|
+
.chapter-portal-tag[data-tag=new]{border-color:transparent;background:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
|
|
1757
|
+
.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}
|
|
1758
|
+
.chapter-portal-account .chapter-portal-nav-item{margin:0 -.75rem .75rem;width:calc(100% + 1.5rem);color:var(--ui-text,#fff)}
|
|
1759
|
+
.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}
|
|
1760
|
+
.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}
|
|
1761
|
+
.chapter-portal-avatar img{width:100%;height:100%;object-fit:cover}
|
|
1762
|
+
.chapter-portal-avatar.chapter-portal-profile-photo{width:96px;height:96px;font-size:1.6rem}
|
|
1763
|
+
.chapter-portal-locked-wrap{position:relative}
|
|
1764
|
+
.chapter-portal-main{min-width:0;padding:clamp(1rem,3vw,2.5rem);display:flex;flex-direction:column;gap:1.5rem}
|
|
1765
|
+
.chapter-portal-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
|
|
1766
|
+
.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}
|
|
1767
|
+
.chapter-portal-back{padding:0;border:0;background:none;color:var(--ui-text,inherit);font:inherit;font-weight:600;cursor:pointer}
|
|
1768
|
+
.chapter-portal-top-right{display:flex;align-items:center;gap:.75rem;margin-left:auto}
|
|
1769
|
+
.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}
|
|
1770
|
+
.chapter-portal-me{padding:0;border:0;background:none;cursor:pointer;border-radius:50%}
|
|
1771
|
+
.chapter-portal-me .chapter-portal-avatar{width:40px;height:40px;font-size:.85rem}
|
|
1772
|
+
.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}
|
|
1773
|
+
.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}
|
|
1774
|
+
.chapter-portal-stack{display:flex;flex-direction:column;gap:1.25rem}
|
|
1775
|
+
.chapter-portal-soon{text-align:center;padding:clamp(2rem,6vw,3.5rem) 1.5rem}
|
|
1776
|
+
.chapter-portal-soon p{max-width:36rem;margin:.5rem auto 0;color:var(--ui-text-muted,#7e8e84)}
|
|
1777
|
+
.chapter-portal-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:1rem}
|
|
1778
|
+
.chapter-portal-tile{display:flex;flex-direction:column;gap:.5rem}
|
|
1779
|
+
.chapter-portal-tile h3{margin:0;font-size:1.05rem}
|
|
1780
|
+
.chapter-portal-tile p{margin:0;color:var(--ui-text-muted,#7e8e84);font-size:.92rem;flex:1}
|
|
1781
|
+
.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}
|
|
1782
|
+
.chapter-portal-btn[data-variant=ghost]{background:transparent;color:var(--ui-text,#2f3e34)}
|
|
1783
|
+
.chapter-portal-btn[data-variant=accent]{background:var(--ui-accent,#7cb83f);border-color:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
|
|
1784
|
+
.chapter-portal-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
1785
|
+
.chapter-portal-btns{display:flex;flex-wrap:wrap;gap:.6rem}
|
|
1786
|
+
.chapter-portal :where(button,a,input,textarea,select):focus-visible{outline:3px solid var(--ui-focus,var(--ui-accent,#7cb83f));outline-offset:2px}
|
|
1787
|
+
.chapter-portal-modal-back{position:fixed;inset:0;z-index:50;display:grid;place-items:center;padding:1rem;background:color-mix(in srgb,var(--ui-text,#2f3e34) 45%,transparent)}
|
|
1788
|
+
.chapter-portal-modal{position:relative;width:min(100%,46rem);max-height:90vh;overflow:auto}
|
|
1789
|
+
.chapter-portal-modal-x{position:absolute;top:.75rem;right:.75rem;width:40px;height:40px;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}
|
|
1790
|
+
.chapter-portal-link-box{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;margin:.75rem 0;padding:.5rem .5rem .5rem 1rem;border:1px solid var(--ui-border,#e2dccf);border-radius:999px;background:var(--ui-bg,#f4efe6)}
|
|
1791
|
+
.chapter-portal-link-box code{overflow-wrap:anywhere;font-size:.9rem}
|
|
1792
|
+
.chapter-portal-tally{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.75rem}
|
|
1793
|
+
.chapter-portal-tally[data-tiles="2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
|
|
1794
|
+
.chapter-portal-tally>div{display:flex;flex-direction:column;padding:.9rem;border:1px solid var(--ui-border,#e2dccf);border-radius:var(--ui-radius-sm,10px)}
|
|
1795
|
+
.chapter-portal-tally b{font-family:var(--ui-font-numeral,var(--ui-font-display,inherit));font-size:1.8rem;font-weight:400}
|
|
1796
|
+
.chapter-portal-tally span{font-size:.8rem;color:var(--ui-text-muted,#7e8e84)}
|
|
1797
|
+
.chapter-portal-fallback{margin-top:1rem;padding:1rem;border:1px dashed var(--ui-border-strong,#aeb9b5);border-radius:var(--ui-radius-sm,10px)}
|
|
1798
|
+
.chapter-portal-material{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;padding:.35rem 0;list-style:none}
|
|
1799
|
+
.chapter-portal-material small{color:var(--ui-text-muted,#7e8e84)}
|
|
1800
|
+
.chapter-portal-material a{margin-left:auto}
|
|
1801
|
+
.chapter-portal details{border-top:1px solid var(--ui-border,#e2dccf);padding:.75rem 0}
|
|
1802
|
+
.chapter-portal summary{cursor:pointer}
|
|
1803
|
+
.chapter-portal dl{display:grid;grid-template-columns:auto 1fr;gap:.3rem 1rem;margin:.75rem 0}
|
|
1804
|
+
.chapter-portal dt{color:var(--ui-text-muted,#7e8e84)}
|
|
1805
|
+
.chapter-portal dd{margin:0}
|
|
1806
|
+
.chapter-portal-mobile{display:none}
|
|
1807
|
+
@media (max-width:860px){
|
|
1808
|
+
.chapter-portal{grid-template-columns:minmax(0,1fr)}
|
|
1809
|
+
.chapter-portal-side{display:none}
|
|
1810
|
+
.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)}
|
|
1811
|
+
.chapter-portal-mobile-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.8rem 1rem}
|
|
1812
|
+
.chapter-portal-burger{display:inline-grid;place-items:center;width:44px;height:44px;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer}
|
|
1813
|
+
.chapter-portal-mobile-menu{display:flex;flex-direction:column;gap:1rem;padding:0 1rem 1.25rem}
|
|
1814
|
+
.chapter-portal-mobile .chapter-portal-brand{font-size:1.15rem;padding:0}
|
|
1815
|
+
.chapter-portal-modal-back{place-items:end stretch;padding:0}
|
|
1816
|
+
.chapter-portal-modal{width:100%;border-radius:var(--ui-radius-lg,14px) var(--ui-radius-lg,14px) 0 0}
|
|
1817
|
+
}
|
|
1818
|
+
`;
|
|
1819
|
+
|
|
1820
|
+
// src/ui/member-course-page.tsx
|
|
1821
|
+
import { useEffect as useEffect7, useState as useState14 } from "preact/hooks";
|
|
1822
|
+
import { Markdown as Markdown3 } from "@odla-ai/ui/components";
|
|
1823
|
+
import { Fragment as Fragment8, jsx as jsx21, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
1824
|
+
function useCourse(ctx, courseId) {
|
|
1825
|
+
const [view, setView] = useState14(null);
|
|
1826
|
+
const [error, setError] = useState14(null);
|
|
1827
|
+
const [busy, setBusy] = useState14(false);
|
|
1828
|
+
useEffect7(() => {
|
|
1829
|
+
if (!courseId) return;
|
|
1830
|
+
let live = true;
|
|
1831
|
+
void ctx.api(`/api/member/courses/${encodeURIComponent(courseId)}`).then((v) => live && setView(v)).catch(() => live && setError(ctx.copy.course.failed));
|
|
1832
|
+
return () => {
|
|
1833
|
+
live = false;
|
|
1834
|
+
};
|
|
1835
|
+
}, [courseId]);
|
|
1836
|
+
const act = async (action) => {
|
|
1837
|
+
setBusy(true);
|
|
1838
|
+
setError(null);
|
|
1839
|
+
try {
|
|
1840
|
+
setView(await ctx.api(`/api/member/courses/${encodeURIComponent(courseId)}/${action}`, { method: "POST" }));
|
|
1841
|
+
} catch {
|
|
1842
|
+
setError(ctx.copy.course.failed);
|
|
1843
|
+
} finally {
|
|
1844
|
+
setBusy(false);
|
|
1845
|
+
}
|
|
1846
|
+
};
|
|
1847
|
+
return { view, error, busy, act };
|
|
1848
|
+
}
|
|
1849
|
+
function seatLine(view, copy) {
|
|
1850
|
+
if (view.enrollment?.status === "enrolled") return copy.invitesOnWay;
|
|
1851
|
+
if (view.enrollment?.status === "waitlisted") return formatChapterCopy(copy.onWaitlist, { position: String(view.enrollment.waitlistPosition ?? "") });
|
|
1852
|
+
if (view.course.status === "closed") return copy.closed;
|
|
1853
|
+
return formatChapterCopy(copy.seatsOpen, { left: String(view.course.seatsLeft), capacity: String(view.course.capacity) });
|
|
1854
|
+
}
|
|
1855
|
+
function SeatActions({ ctx, course, details }) {
|
|
1856
|
+
const copy = ctx.copy.course;
|
|
1857
|
+
const view = course.view;
|
|
1858
|
+
const status = view.enrollment?.status;
|
|
1859
|
+
const confirmThen = (action) => {
|
|
1860
|
+
if (window.confirm(copy.confirmGiveUp)) void course.act(action);
|
|
1861
|
+
};
|
|
1862
|
+
return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-btns", children: [
|
|
1863
|
+
status === "enrolled" ? /* @__PURE__ */ jsx21("span", { className: "chapter-portal-pill", children: copy.youreIn }) : null,
|
|
1864
|
+
status === "enrolled" && view.meetUrl ? /* @__PURE__ */ jsx21("a", { className: "chapter-portal-btn", href: view.meetUrl, target: "_blank", rel: "noopener", children: copy.openMeet }) : null,
|
|
1865
|
+
status === "enrolled" ? /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", disabled: course.busy, onClick: () => confirmThen("withdraw"), children: copy.giveUp }) : null,
|
|
1866
|
+
status === "waitlisted" ? /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", disabled: course.busy, onClick: () => void course.act("withdraw"), children: copy.leaveWaitlist }) : null,
|
|
1867
|
+
!status && view.course.status !== "closed" ? /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-btn", disabled: course.busy, onClick: () => void course.act("enroll"), children: view.course.status === "full" ? copy.joinWaitlist : copy.reserve }) : null,
|
|
1868
|
+
details ? /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", onClick: details, children: status === "enrolled" ? copy.courseDetails : copy.seeDetails }) : null
|
|
1869
|
+
] });
|
|
1870
|
+
}
|
|
1871
|
+
var MaterialItem = ({ item, kind, ctx, enrolled }) => /* @__PURE__ */ jsxs19("li", { className: "chapter-portal-material", children: [
|
|
1872
|
+
kind ? /* @__PURE__ */ jsx21("span", { className: "chapter-portal-pill", children: ctx.copy.course[kind] }) : null,
|
|
1873
|
+
/* @__PURE__ */ jsxs19("span", { children: [
|
|
1874
|
+
item.label,
|
|
1875
|
+
item.meta ? /* @__PURE__ */ jsxs19("small", { children: [
|
|
1876
|
+
" \xB7 ",
|
|
1877
|
+
item.meta
|
|
1878
|
+
] }) : null
|
|
1879
|
+
] }),
|
|
1880
|
+
enrolled && item.url ? /* @__PURE__ */ jsx21("a", { href: item.url, target: "_blank", rel: "noopener", children: ctx.copy.course.open }) : null
|
|
1881
|
+
] });
|
|
1882
|
+
function CoursePage({ page, ctx }) {
|
|
1883
|
+
const course = useCourse(ctx, page.feature?.ref);
|
|
1884
|
+
const copy = ctx.copy.course;
|
|
1885
|
+
if (!course.view) return /* @__PURE__ */ jsx21("p", { children: course.error ?? ctx.copy.shell.loading });
|
|
1886
|
+
const { course: c } = course.view;
|
|
1887
|
+
const enrolled = course.view.enrollment?.status === "enrolled";
|
|
1888
|
+
return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-stack", "data-course-page": true, children: [
|
|
1889
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card ui-invert", style: { display: "grid", gap: "1.25rem", gridTemplateColumns: "repeat(auto-fit,minmax(min(100%,18rem),1fr))" }, children: [
|
|
1890
|
+
/* @__PURE__ */ jsxs19("div", { children: [
|
|
1891
|
+
/* @__PURE__ */ jsx21("h1", { style: { fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400, margin: 0 }, children: c.title }),
|
|
1892
|
+
c.content.basedOn ? /* @__PURE__ */ jsx21("p", { style: { fontStyle: "italic" }, children: c.content.basedOn }) : null,
|
|
1893
|
+
c.content.short ? /* @__PURE__ */ jsx21("p", { children: c.content.short }) : null
|
|
1894
|
+
] }),
|
|
1895
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", "data-seat-box": true, children: [
|
|
1896
|
+
!course.view.enrollment ? /* @__PURE__ */ jsx21("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: copy.reserveYourSeat }) : null,
|
|
1897
|
+
/* @__PURE__ */ jsxs19("dl", { children: [
|
|
1898
|
+
c.content.when ? /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
1899
|
+
/* @__PURE__ */ jsx21("dt", { children: copy.when }),
|
|
1900
|
+
/* @__PURE__ */ jsx21("dd", { children: c.content.when })
|
|
1901
|
+
] }) : null,
|
|
1902
|
+
c.content.dates ?? c.content.start ? /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
1903
|
+
/* @__PURE__ */ jsx21("dt", { children: copy.dates }),
|
|
1904
|
+
/* @__PURE__ */ jsx21("dd", { children: c.content.dates ?? c.content.start })
|
|
1905
|
+
] }) : null,
|
|
1906
|
+
/* @__PURE__ */ jsx21("dt", { children: copy.where }),
|
|
1907
|
+
/* @__PURE__ */ jsx21("dd", { children: copy.googleMeet }),
|
|
1908
|
+
/* @__PURE__ */ jsx21("dt", { children: copy.seats }),
|
|
1909
|
+
/* @__PURE__ */ jsx21("dd", { children: seatLine(course.view, copy) })
|
|
1910
|
+
] }),
|
|
1911
|
+
/* @__PURE__ */ jsx21(SeatActions, { ctx, course }),
|
|
1912
|
+
!course.view.enrollment ? /* @__PURE__ */ jsx21("p", { style: { color: "var(--ui-text-muted)" }, children: copy.inviteEvery }) : null,
|
|
1913
|
+
course.error ? /* @__PURE__ */ jsx21("p", { role: "alert", children: course.error }) : null
|
|
1914
|
+
] })
|
|
1915
|
+
] }),
|
|
1916
|
+
c.guides.length ? /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", children: [
|
|
1917
|
+
/* @__PURE__ */ jsx21("h2", { children: copy.guidesTitle }),
|
|
1918
|
+
/* @__PURE__ */ jsx21("div", { className: "chapter-portal-tiles", children: c.guides.map((guide) => /* @__PURE__ */ jsxs19("div", { children: [
|
|
1919
|
+
guide.photoUrl ? /* @__PURE__ */ jsx21("img", { src: guide.photoUrl, alt: guide.name, style: { width: 72, height: 72, borderRadius: "50%", objectFit: "cover" } }) : null,
|
|
1920
|
+
/* @__PURE__ */ jsx21("h3", { children: guide.name }),
|
|
1921
|
+
guide.role ? /* @__PURE__ */ jsx21("div", { style: { color: "var(--ui-text-muted)" }, children: guide.role }) : null,
|
|
1922
|
+
guide.bio ? /* @__PURE__ */ jsx21("p", { children: guide.bio }) : null
|
|
1923
|
+
] }, guide.name)) })
|
|
1924
|
+
] }) : null,
|
|
1925
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", "data-sessions": true, children: [
|
|
1926
|
+
/* @__PURE__ */ jsx21("h2", { children: copy.sessionsTitle }),
|
|
1927
|
+
/* @__PURE__ */ jsx21("p", { style: { color: "var(--ui-text-muted)" }, children: enrolled ? copy.materialsOpen : copy.materialsLocked }),
|
|
1928
|
+
c.sessions.map((session, index) => /* @__PURE__ */ jsxs19("details", { open: enrolled && index === 0, children: [
|
|
1929
|
+
/* @__PURE__ */ jsxs19("summary", { children: [
|
|
1930
|
+
/* @__PURE__ */ jsx21("strong", { children: session.date }),
|
|
1931
|
+
" \xB7 ",
|
|
1932
|
+
session.topic,
|
|
1933
|
+
session.materials.length ? /* @__PURE__ */ jsxs19("small", { children: [
|
|
1934
|
+
" \xB7 ",
|
|
1935
|
+
formatChapterCopy(copy.items, { count: String(session.materials.length) })
|
|
1936
|
+
] }) : null
|
|
1937
|
+
] }),
|
|
1938
|
+
session.description ? /* @__PURE__ */ jsx21("p", { children: session.description }) : null,
|
|
1939
|
+
/* @__PURE__ */ jsx21("ul", { children: session.materials.map((item) => /* @__PURE__ */ jsx21(MaterialItem, { item, kind: item.kind, ctx, enrolled }, item.label)) })
|
|
1940
|
+
] }, session.startsAt))
|
|
1941
|
+
] }),
|
|
1942
|
+
/* @__PURE__ */ jsxs19("div", { className: "chapter-portal-tiles", children: [
|
|
1943
|
+
c.content.outcomes?.length ? /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx21("h2", { children: copy.outcomesTitle }),
|
|
1945
|
+
/* @__PURE__ */ jsx21("ul", { children: c.content.outcomes.map((o) => /* @__PURE__ */ jsx21("li", { children: o }, o)) })
|
|
1946
|
+
] }) : null,
|
|
1947
|
+
c.toolkit.length || c.content.time ? /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", children: [
|
|
1948
|
+
/* @__PURE__ */ jsx21("h2", { children: copy.toolkitTitle }),
|
|
1949
|
+
/* @__PURE__ */ jsx21("ul", { children: c.toolkit.map((item) => /* @__PURE__ */ jsx21(MaterialItem, { item, ctx, enrolled }, item.label)) }),
|
|
1950
|
+
c.content.time ? /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
1951
|
+
/* @__PURE__ */ jsx21("h2", { children: copy.timeTitle }),
|
|
1952
|
+
/* @__PURE__ */ jsx21("p", { children: c.content.time })
|
|
1953
|
+
] }) : null
|
|
1954
|
+
] }) : null
|
|
1955
|
+
] }),
|
|
1956
|
+
c.content.partnerMarkdown ? /* @__PURE__ */ jsx21("div", { className: "chapter-portal-card", children: /* @__PURE__ */ jsx21(Markdown3, { source: c.content.partnerMarkdown }) }) : null
|
|
1957
|
+
] });
|
|
1958
|
+
}
|
|
1959
|
+
function CourseHomePanel({ page, ctx }) {
|
|
1960
|
+
const locked = page.access === "locked";
|
|
1961
|
+
const course = useCourse(ctx, locked ? void 0 : page.feature?.ref);
|
|
1962
|
+
const view = course.view;
|
|
1963
|
+
return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-card", "data-course-panel": true, children: [
|
|
1964
|
+
/* @__PURE__ */ jsx21("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: ctx.copy.course.eyebrow }),
|
|
1965
|
+
/* @__PURE__ */ jsx21("h2", { children: view?.course.title ?? page.title }),
|
|
1966
|
+
view?.course.content.basedOn ? /* @__PURE__ */ jsx21("p", { style: { fontStyle: "italic" }, children: view.course.content.basedOn }) : null,
|
|
1967
|
+
/* @__PURE__ */ jsx21("p", { children: view?.course.content.short ?? page.summary }),
|
|
1968
|
+
view ? /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
1969
|
+
/* @__PURE__ */ jsx21("p", { children: [view.course.content.when, view.course.content.start].filter(Boolean).join(" \xB7 ") }),
|
|
1970
|
+
/* @__PURE__ */ jsx21("p", { children: /* @__PURE__ */ jsx21("strong", { children: seatLine(view, ctx.copy.course) }) }),
|
|
1971
|
+
/* @__PURE__ */ jsx21(SeatActions, { ctx, course, details: () => ctx.navigate({ kind: "page", slug: page.slug }) })
|
|
1972
|
+
] }) : null
|
|
1973
|
+
] });
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
// src/ui/member-share-page.tsx
|
|
1977
|
+
import { useEffect as useEffect9, useState as useState16 } from "preact/hooks";
|
|
1978
|
+
|
|
1979
|
+
// src/ui/member-share.ts
|
|
1980
|
+
import { useEffect as useEffect8, useState as useState15 } from "preact/hooks";
|
|
1981
|
+
var articleFor = (word) => /^[aeiou]/i.test(word.trim()) ? "an" : "a";
|
|
1982
|
+
function shareVars(me, referrals) {
|
|
1983
|
+
const tierName = me.tier?.name ?? "";
|
|
1984
|
+
return {
|
|
1985
|
+
tierName,
|
|
1986
|
+
article: articleFor(tierName),
|
|
1987
|
+
inviteUrl: referrals?.link ?? "",
|
|
1988
|
+
firstName: me.firstName ?? me.displayName.split(/\s+/)[0] ?? "",
|
|
1989
|
+
location: me.location ?? "",
|
|
1990
|
+
credit: referrals?.credit ? fmtMoney(referrals.credit.perFriendCents).replace(/\.00$/, "") : ""
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
var fill = (template, vars) => formatChapterCopy(template, vars);
|
|
1994
|
+
var linkedinShareUrl = (post, link) => `https://www.linkedin.com/feed/?shareActive=true&text=${encodeURIComponent(`${post}
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
${link}`).replace(/'/g, "%27")}`;
|
|
1998
|
+
var mailtoHref = (subject, body) => `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
1999
|
+
var smsHref = (body, ios) => `${ios ? "sms:&body=" : "sms:?body="}${encodeURIComponent(body)}`;
|
|
2000
|
+
var isIOS = (nav) => /iPad|iPhone|iPod/.test(nav.userAgent) || nav.platform === "MacIntel" && (nav.maxTouchPoints ?? 0) > 1;
|
|
2001
|
+
function useMemberReferrals(api) {
|
|
2002
|
+
const [state, setState] = useState15({ data: null, failed: false });
|
|
2003
|
+
useEffect8(() => {
|
|
2004
|
+
let live = true;
|
|
2005
|
+
void api("/api/member/referrals").then((data) => live && setState({ data, failed: false })).catch(() => live && setState({ data: null, failed: true }));
|
|
2006
|
+
return () => {
|
|
2007
|
+
live = false;
|
|
2008
|
+
};
|
|
2009
|
+
}, [api]);
|
|
2010
|
+
return state;
|
|
2011
|
+
}
|
|
2012
|
+
async function copyText(text, copy) {
|
|
2013
|
+
try {
|
|
2014
|
+
await navigator.clipboard.writeText(text);
|
|
2015
|
+
return copy.copied;
|
|
2016
|
+
} catch {
|
|
2017
|
+
return copy.copyBlocked;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
// src/ui/member-share-page.tsx
|
|
2022
|
+
import { Fragment as Fragment9, jsx as jsx22, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
2023
|
+
function CopyButton({ text, label, ctx, variant }) {
|
|
2024
|
+
const [shown, setShown] = useState16(label);
|
|
2025
|
+
return /* @__PURE__ */ jsx22("button", { type: "button", className: "chapter-portal-btn", "data-variant": variant, onClick: () => void copyText(text, ctx.copy.share).then((result) => {
|
|
2026
|
+
setShown(result);
|
|
2027
|
+
setTimeout(() => setShown(label), 2e3);
|
|
2028
|
+
}), children: shown });
|
|
2029
|
+
}
|
|
2030
|
+
function HowDialog({ ctx, vars, onClose, example }) {
|
|
2031
|
+
const copy = ctx.copy.share;
|
|
2032
|
+
useEffect9(() => {
|
|
2033
|
+
const onKey = (event) => {
|
|
2034
|
+
if (event.key === "Escape") onClose();
|
|
2035
|
+
};
|
|
2036
|
+
document.addEventListener("keydown", onKey);
|
|
2037
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
2038
|
+
}, []);
|
|
2039
|
+
return /* @__PURE__ */ jsx22("div", { className: "chapter-portal-modal-back", "data-portal-dialog": true, onClick: (event) => {
|
|
2040
|
+
if (event.target === event.currentTarget) onClose();
|
|
2041
|
+
}, children: /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-modal chapter-portal-card", role: "dialog", "aria-modal": "true", "aria-labelledby": "chapter-portal-how-title", children: [
|
|
2042
|
+
/* @__PURE__ */ jsx22("button", { type: "button", className: "chapter-portal-modal-x", "aria-label": copy.close, onClick: onClose, children: /* @__PURE__ */ jsx22(PortalIcon, { name: "close", size: 20 }) }),
|
|
2043
|
+
/* @__PURE__ */ jsx22("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: copy.stepsEyebrow }),
|
|
2044
|
+
/* @__PURE__ */ jsx22("h2", { id: "chapter-portal-how-title", children: copy.officialTitle }),
|
|
2045
|
+
/* @__PURE__ */ jsx22("ol", { children: copy.steps.map((step) => /* @__PURE__ */ jsx22("li", { children: fill(step, vars) }, step)) }),
|
|
2046
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-btns", children: [
|
|
2047
|
+
/* @__PURE__ */ jsx22("a", { className: "chapter-portal-btn", href: "https://www.linkedin.com/in/me/", target: "_blank", rel: "noopener", children: copy.openLinkedIn }),
|
|
2048
|
+
/* @__PURE__ */ jsx22(CopyButton, { text: fill(copy.linkedinDescription, vars), label: copy.copyDescription, ctx, variant: "ghost" })
|
|
2049
|
+
] }),
|
|
2050
|
+
example
|
|
2051
|
+
] }) });
|
|
2052
|
+
}
|
|
2053
|
+
function OfficialCard({ ctx, referrals, example }) {
|
|
2054
|
+
const [open, setOpen] = useState16(false);
|
|
2055
|
+
const copy = ctx.copy.share;
|
|
2056
|
+
return /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-card", "data-official": true, children: [
|
|
2057
|
+
/* @__PURE__ */ jsx22("h2", { children: copy.officialTitle }),
|
|
2058
|
+
/* @__PURE__ */ jsx22("p", { children: copy.officialBody }),
|
|
2059
|
+
/* @__PURE__ */ jsx22("button", { type: "button", className: "chapter-portal-btn", onClick: () => setOpen(true), children: copy.showMeHow }),
|
|
2060
|
+
open ? /* @__PURE__ */ jsx22(HowDialog, { ctx, vars: shareVars(ctx.me, referrals), onClose: () => setOpen(false), example }) : null
|
|
2061
|
+
] });
|
|
2062
|
+
}
|
|
2063
|
+
function PostCard({ ctx, referrals }) {
|
|
2064
|
+
const copy = ctx.copy.share;
|
|
2065
|
+
const vars = shareVars(ctx.me, referrals);
|
|
2066
|
+
const post = fill(copy.linkedinPost, vars);
|
|
2067
|
+
return /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-card", "data-post": true, children: [
|
|
2068
|
+
/* @__PURE__ */ jsx22("h2", { children: copy.postTitle }),
|
|
2069
|
+
/* @__PURE__ */ jsx22("p", { children: copy.postBody }),
|
|
2070
|
+
/* @__PURE__ */ jsx22("a", { className: "chapter-portal-btn", href: linkedinShareUrl(post, vars.inviteUrl), target: "_blank", rel: "noopener", children: copy.shareOnLinkedIn }),
|
|
2071
|
+
/* @__PURE__ */ jsxs20("details", { children: [
|
|
2072
|
+
/* @__PURE__ */ jsx22("summary", { children: copy.previewPost }),
|
|
2073
|
+
/* @__PURE__ */ jsx22("p", { children: post }),
|
|
2074
|
+
/* @__PURE__ */ jsx22("p", { children: vars.inviteUrl })
|
|
2075
|
+
] })
|
|
2076
|
+
] });
|
|
2077
|
+
}
|
|
2078
|
+
function InviteLinkCard({ ctx, referrals }) {
|
|
2079
|
+
const copy = ctx.copy.share;
|
|
2080
|
+
const vars = shareVars(ctx.me, referrals);
|
|
2081
|
+
const [fallback, setFallback] = useState16(null);
|
|
2082
|
+
const ios = typeof navigator !== "undefined" && isIOS(navigator);
|
|
2083
|
+
const email = fill(copy.emailBody, vars), text = fill(copy.textBody, vars);
|
|
2084
|
+
const tryOpen = (kind) => setTimeout(() => {
|
|
2085
|
+
if (!document.hidden) setFallback(kind);
|
|
2086
|
+
}, 900);
|
|
2087
|
+
return /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-card", "data-invite-link": true, children: [
|
|
2088
|
+
/* @__PURE__ */ jsx22("h2", { children: copy.linkTitle }),
|
|
2089
|
+
/* @__PURE__ */ jsxs20("p", { children: [
|
|
2090
|
+
copy.linkBody,
|
|
2091
|
+
referrals?.credit ? /* @__PURE__ */ jsxs20(Fragment9, { children: [
|
|
2092
|
+
" ",
|
|
2093
|
+
/* @__PURE__ */ jsx22("strong", { children: fill(copy.linkCredit, vars) })
|
|
2094
|
+
] }) : null
|
|
2095
|
+
] }),
|
|
2096
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-link-box", children: [
|
|
2097
|
+
/* @__PURE__ */ jsx22("code", { children: referrals ? referrals.link.replace(/^https?:\/\//, "") : "\u2026" }),
|
|
2098
|
+
referrals ? /* @__PURE__ */ jsx22(CopyButton, { text: referrals.link, label: copy.copyLink, ctx }) : null
|
|
2099
|
+
] }),
|
|
2100
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-btns", children: [
|
|
2101
|
+
/* @__PURE__ */ jsx22("a", { className: "chapter-portal-btn", "data-variant": "ghost", href: mailtoHref(copy.emailSubject, email), onClick: () => tryOpen("email"), children: copy.emailInvite }),
|
|
2102
|
+
/* @__PURE__ */ jsx22("a", { className: "chapter-portal-btn", "data-variant": "ghost", href: smsHref(text, ios), onClick: () => tryOpen("text"), children: copy.textInvite })
|
|
2103
|
+
] }),
|
|
2104
|
+
fallback ? /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-fallback", "data-fallback": fallback, children: [
|
|
2105
|
+
/* @__PURE__ */ jsx22("p", { children: fallback === "email" ? copy.fallbackEmail : copy.fallbackText }),
|
|
2106
|
+
/* @__PURE__ */ jsx22("pre", { style: { whiteSpace: "pre-wrap" }, children: fallback === "email" ? `${copy.emailSubject}
|
|
2107
|
+
|
|
2108
|
+
${email}` : text }),
|
|
2109
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-btns", children: [
|
|
2110
|
+
/* @__PURE__ */ jsx22(CopyButton, { text: fallback === "email" ? email : text, label: copy.copyMessage, ctx }),
|
|
2111
|
+
/* @__PURE__ */ jsx22("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", onClick: () => setFallback(null), children: copy.close })
|
|
2112
|
+
] })
|
|
2113
|
+
] }) : null,
|
|
2114
|
+
/* @__PURE__ */ jsx22("p", { style: { color: "var(--ui-text-muted)" }, children: copy.inviteNote })
|
|
2115
|
+
] });
|
|
2116
|
+
}
|
|
2117
|
+
function ReferralsCard({ ctx, referrals }) {
|
|
2118
|
+
const copy = ctx.copy.share;
|
|
2119
|
+
if (!referrals) return null;
|
|
2120
|
+
const vars = shareVars(ctx.me, referrals);
|
|
2121
|
+
const tile = (value, label) => /* @__PURE__ */ jsxs20("div", { children: [
|
|
2122
|
+
/* @__PURE__ */ jsx22("b", { children: value }),
|
|
2123
|
+
/* @__PURE__ */ jsx22("span", { children: label })
|
|
2124
|
+
] });
|
|
2125
|
+
return /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-card", "data-referrals": true, children: [
|
|
2126
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-top", children: [
|
|
2127
|
+
/* @__PURE__ */ jsx22("h2", { children: copy.referralsTitle }),
|
|
2128
|
+
/* @__PURE__ */ jsx22("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", onClick: () => {
|
|
2129
|
+
const share = ctx.content.pages.find((page) => page.kind === "feature" && page.feature?.name === "share");
|
|
2130
|
+
if (share) ctx.navigate({ kind: "page", slug: share.slug });
|
|
2131
|
+
}, children: copy.inviteFriend })
|
|
2132
|
+
] }),
|
|
2133
|
+
/* @__PURE__ */ jsxs20("p", { children: [
|
|
2134
|
+
copy.referralsBody,
|
|
2135
|
+
referrals.credit ? /* @__PURE__ */ jsxs20(Fragment9, { children: [
|
|
2136
|
+
" ",
|
|
2137
|
+
fill(copy.referralsCredit, vars)
|
|
2138
|
+
] }) : null
|
|
2139
|
+
] }),
|
|
2140
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-tally", "data-tiles": referrals.credit ? 3 : 2, children: [
|
|
2141
|
+
tile(String(referrals.joined.count), copy.joined),
|
|
2142
|
+
tile(String(referrals.inProcess), copy.inProcess),
|
|
2143
|
+
referrals.credit ? tile(fmtMoney(referrals.credit.offNextYearCents).replace(/\.00$/, ""), copy.offNextYear) : null
|
|
2144
|
+
] }),
|
|
2145
|
+
referrals.joined.names.length ? /* @__PURE__ */ jsx22("p", { children: fill(copy.joinedWith, { names: referrals.joined.names.join(", ") }) }) : null
|
|
2146
|
+
] });
|
|
2147
|
+
}
|
|
2148
|
+
function SharePage({ page, ctx, example }) {
|
|
2149
|
+
const { data } = useMemberReferrals(ctx.api);
|
|
2150
|
+
return /* @__PURE__ */ jsxs20("div", { className: "chapter-portal-stack", "data-share-page": true, children: [
|
|
2151
|
+
/* @__PURE__ */ jsxs20("div", { children: [
|
|
2152
|
+
/* @__PURE__ */ jsx22("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: ctx.copy.share.eyebrow }),
|
|
2153
|
+
/* @__PURE__ */ jsx22("h1", { style: { margin: ".3rem 0", fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400 }, children: page.title }),
|
|
2154
|
+
/* @__PURE__ */ jsx22("p", { style: { maxWidth: "40rem", color: "var(--ui-text-muted)" }, children: page.summary ?? ctx.copy.share.intro })
|
|
2155
|
+
] }),
|
|
2156
|
+
/* @__PURE__ */ jsx22(OfficialCard, { ctx, referrals: data, example }),
|
|
2157
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-tiles", children: [
|
|
2158
|
+
/* @__PURE__ */ jsx22(PostCard, { ctx, referrals: data }),
|
|
2159
|
+
/* @__PURE__ */ jsx22(InviteLinkCard, { ctx, referrals: data })
|
|
2160
|
+
] })
|
|
2161
|
+
] });
|
|
2162
|
+
}
|
|
2163
|
+
function ShareHome({ ctx }) {
|
|
2164
|
+
const { data } = useMemberReferrals(ctx.api);
|
|
2165
|
+
return /* @__PURE__ */ jsxs20("section", { className: "chapter-portal-stack", "data-share-home": true, children: [
|
|
2166
|
+
/* @__PURE__ */ jsx22("h2", { style: { fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400, margin: 0 }, children: ctx.copy.share.eyebrow }),
|
|
2167
|
+
/* @__PURE__ */ jsx22(OfficialCard, { ctx, referrals: data }),
|
|
2168
|
+
/* @__PURE__ */ jsxs20("div", { className: "chapter-portal-tiles", children: [
|
|
2169
|
+
/* @__PURE__ */ jsx22(PostCard, { ctx, referrals: data }),
|
|
2170
|
+
/* @__PURE__ */ jsx22(InviteLinkCard, { ctx, referrals: data })
|
|
2171
|
+
] })
|
|
2172
|
+
] });
|
|
2173
|
+
}
|
|
2174
|
+
function ProfileReferrals({ ctx }) {
|
|
2175
|
+
const { data } = useMemberReferrals(ctx.api);
|
|
2176
|
+
return /* @__PURE__ */ jsx22(ReferralsCard, { ctx, referrals: data });
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
// src/ui/member-portal-features.tsx
|
|
2180
|
+
import { jsx as jsx23 } from "preact/jsx-runtime";
|
|
2181
|
+
var PACKAGED_PORTAL_FEATURES = {
|
|
2182
|
+
course: { page: (page, ctx) => /* @__PURE__ */ jsx23(CoursePage, { page, ctx }), home: (page, ctx) => /* @__PURE__ */ jsx23(CourseHomePanel, { page, ctx }) },
|
|
2183
|
+
share: { page: (page, ctx) => /* @__PURE__ */ jsx23(SharePage, { page, ctx }), home: (_page, ctx) => /* @__PURE__ */ jsx23(ShareHome, { ctx }) }
|
|
2184
|
+
};
|
|
2185
|
+
|
|
2186
|
+
// src/ui/member-portal.tsx
|
|
2187
|
+
import { jsx as jsx24, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
2188
|
+
var EMPTY = { pages: [], sections: [], viewer: { tierId: null, admin: false }, revisions: { parent: null, chapter: null } };
|
|
2189
|
+
function MemberPortal(props) {
|
|
2190
|
+
const inherited = useChapterCopy();
|
|
2191
|
+
const copy = props.copy ?? inherited.portal;
|
|
2192
|
+
const routing = { mode: props.routing?.mode ?? "hash", basePath: props.routing?.basePath ?? "/members" };
|
|
2193
|
+
const [content, setContent] = useState17(props.initialContent ?? null);
|
|
2194
|
+
const [route, setRoute] = useState17(props.initialRoute ?? { kind: "home" });
|
|
2195
|
+
const [menuOpen, setMenuOpen] = useState17(false);
|
|
2196
|
+
useEffect10(() => {
|
|
2197
|
+
if (props.initialContent) return;
|
|
2198
|
+
let live = true;
|
|
2199
|
+
void props.api("/api/member-content").then((value) => live && setContent(value)).catch(() => live && setContent(EMPTY));
|
|
2200
|
+
return () => {
|
|
2201
|
+
live = false;
|
|
2202
|
+
};
|
|
2203
|
+
}, [props.api, props.initialContent]);
|
|
2204
|
+
useEffect10(() => {
|
|
2205
|
+
if (typeof window === "undefined" || props.initialRoute) return;
|
|
2206
|
+
const sync = () => setRoute(routeFromLocation(window.location, routing));
|
|
2207
|
+
sync();
|
|
2208
|
+
window.addEventListener("popstate", sync);
|
|
2209
|
+
window.addEventListener("hashchange", sync);
|
|
2210
|
+
return () => {
|
|
2211
|
+
window.removeEventListener("popstate", sync);
|
|
2212
|
+
window.removeEventListener("hashchange", sync);
|
|
2213
|
+
};
|
|
2214
|
+
}, [routing.mode, routing.basePath]);
|
|
2215
|
+
const navigate = (next) => {
|
|
2216
|
+
setRoute(next);
|
|
2217
|
+
setMenuOpen(false);
|
|
2218
|
+
if (typeof window !== "undefined") {
|
|
2219
|
+
window.history.pushState(null, "", hrefFor(next, routing));
|
|
2220
|
+
window.scrollTo?.(0, 0);
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
const features = useMemo3(() => ({ ...PACKAGED_PORTAL_FEATURES, ...props.features }), [props.features]);
|
|
2224
|
+
if (!content) return /* @__PURE__ */ jsxs21("div", { className: "chapter-portal", children: [
|
|
2225
|
+
/* @__PURE__ */ jsx24("style", { children: MEMBER_PORTAL_CSS }),
|
|
2226
|
+
/* @__PURE__ */ jsx24("p", { children: copy.shell.loading })
|
|
2227
|
+
] });
|
|
2228
|
+
const ctx = {
|
|
2229
|
+
api: props.api,
|
|
2230
|
+
me: props.me.portal,
|
|
2231
|
+
email: props.me.email,
|
|
2232
|
+
content,
|
|
2233
|
+
copy,
|
|
2234
|
+
navigate,
|
|
2235
|
+
hrefFor: (target) => hrefFor(target, routing),
|
|
2236
|
+
upsellHref: props.upsellHref,
|
|
2237
|
+
reloadMe: props.reloadMe ?? (async () => {
|
|
2238
|
+
})
|
|
2239
|
+
};
|
|
2240
|
+
const page = route.kind === "page" ? content.pages.find((candidate) => candidate.slug === route.slug) : void 0;
|
|
2241
|
+
const slots = typeof props.home === "function" ? {} : props.home ?? {};
|
|
2242
|
+
const shareAllowed = content.pages.some((candidate) => candidate.kind === "feature" && candidate.feature?.name === "share" && candidate.access === "allowed");
|
|
2243
|
+
const home = /* @__PURE__ */ jsx24(DefaultHome, { ctx, features, slots });
|
|
2244
|
+
const body = route.kind === "home" ? typeof props.home === "function" ? props.home(ctx, home) : home : route.kind === "profile" ? /* @__PURE__ */ jsx24(MemberProfilePage, { ctx, middle: props.profile?.middle ? props.profile.middle(ctx) : shareAllowed ? /* @__PURE__ */ jsx24(ProfileReferrals, { ctx }) : null, extras: props.profile?.extras }) : page ? /* @__PURE__ */ jsx24(PortalPage, { page, ctx, features }) : /* @__PURE__ */ jsx24("div", { className: "chapter-portal-card", children: copy.shell.notFound });
|
|
2245
|
+
const admin = props.me.authorized || props.me.superAdmin ? props.adminHref ?? "/admin/" : void 0;
|
|
2246
|
+
return /* @__PURE__ */ jsxs21("div", { className: "chapter-portal", "data-member-portal": true, "data-route": route.kind, children: [
|
|
2247
|
+
/* @__PURE__ */ jsx24("style", { children: MEMBER_PORTAL_CSS }),
|
|
2248
|
+
/* @__PURE__ */ jsx24(
|
|
2249
|
+
PortalNav,
|
|
2250
|
+
{
|
|
2251
|
+
content,
|
|
2252
|
+
me: ctx.me,
|
|
2253
|
+
email: props.me.email,
|
|
2254
|
+
route,
|
|
2255
|
+
copy,
|
|
2256
|
+
adminHref: admin,
|
|
2257
|
+
onNavigate: navigate,
|
|
2258
|
+
onSignOut: props.signOut,
|
|
2259
|
+
brand: props.brand,
|
|
2260
|
+
sidebarTokens: props.sidebarTokens,
|
|
2261
|
+
menuOpen,
|
|
2262
|
+
onToggleMenu: () => setMenuOpen(!menuOpen)
|
|
2263
|
+
}
|
|
2264
|
+
),
|
|
2265
|
+
/* @__PURE__ */ jsxs21("main", { className: "chapter-portal-main", children: [
|
|
2266
|
+
/* @__PURE__ */ jsxs21("div", { className: "chapter-portal-top", children: [
|
|
2267
|
+
route.kind === "home" ? /* @__PURE__ */ jsx24("h1", { children: copy.shell.welcomeBack }) : /* @__PURE__ */ jsx24("button", { type: "button", className: "chapter-portal-back", onClick: () => navigate({ kind: "home" }), children: copy.shell.backHome }),
|
|
2268
|
+
/* @__PURE__ */ jsxs21("div", { className: "chapter-portal-top-right", children: [
|
|
2269
|
+
ctx.me.tier ? /* @__PURE__ */ jsx24("span", { className: "chapter-portal-pill", children: ctx.me.tier.name }) : null,
|
|
2270
|
+
/* @__PURE__ */ jsx24(
|
|
2271
|
+
"button",
|
|
2272
|
+
{
|
|
2273
|
+
type: "button",
|
|
2274
|
+
className: "chapter-portal-me",
|
|
2275
|
+
"aria-label": copy.shell.yourProfile,
|
|
2276
|
+
title: copy.shell.yourProfile,
|
|
2277
|
+
"aria-current": route.kind === "profile" ? "page" : void 0,
|
|
2278
|
+
onClick: () => navigate({ kind: "profile" }),
|
|
2279
|
+
children: /* @__PURE__ */ jsx24(PortalAvatar, { me: ctx.me })
|
|
2280
|
+
}
|
|
2281
|
+
)
|
|
2282
|
+
] })
|
|
2283
|
+
] }),
|
|
2284
|
+
body
|
|
2285
|
+
] })
|
|
2286
|
+
] });
|
|
2287
|
+
}
|
|
1364
2288
|
|
|
1365
2289
|
// src/ui/members.tsx
|
|
1366
|
-
import { Fragment as
|
|
2290
|
+
import { Fragment as Fragment10, jsx as jsx25, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
1367
2291
|
function card(copy, kicker, body) {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
2292
|
+
return /* @__PURE__ */ jsxs22("div", { className: "card", children: [
|
|
2293
|
+
/* @__PURE__ */ jsx25("div", { className: "card-label", children: copy.provisional.cardLabel }),
|
|
2294
|
+
/* @__PURE__ */ jsxs22("div", { className: "meeting-block", children: [
|
|
2295
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-kicker", children: kicker }),
|
|
1372
2296
|
body
|
|
1373
2297
|
] })
|
|
1374
2298
|
] });
|
|
@@ -1379,29 +2303,32 @@ function ProvisionalCard(props) {
|
|
|
1379
2303
|
return card(
|
|
1380
2304
|
copy,
|
|
1381
2305
|
copy.provisional.applicationNeeded,
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
2306
|
+
/* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
2307
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
|
|
2308
|
+
/* @__PURE__ */ jsx25("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
|
|
1385
2309
|
] })
|
|
1386
2310
|
);
|
|
1387
2311
|
}
|
|
2312
|
+
if (application.status === "declined") {
|
|
2313
|
+
return card(copy, copy.provisional.declined, /* @__PURE__ */ jsx25("div", { className: "meeting-note", children: copy.provisional.declinedBody }));
|
|
2314
|
+
}
|
|
1388
2315
|
if (application.status === "refunded") {
|
|
1389
2316
|
return card(
|
|
1390
2317
|
copy,
|
|
1391
2318
|
copy.provisional.refunded,
|
|
1392
|
-
/* @__PURE__ */
|
|
2319
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-note", children: copy.provisional.refundedBody })
|
|
1393
2320
|
);
|
|
1394
2321
|
}
|
|
1395
|
-
const membership = application.paid ? /* @__PURE__ */
|
|
2322
|
+
const membership = application.paid ? /* @__PURE__ */ jsx25("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
|
|
1396
2323
|
if (application.meetingAt) {
|
|
1397
2324
|
return card(
|
|
1398
2325
|
copy,
|
|
1399
2326
|
copy.provisional.introductionCall,
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
application.meetUrl ? /* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
2327
|
+
/* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
2328
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
|
|
2329
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
|
|
2330
|
+
application.meetUrl ? /* @__PURE__ */ jsx25("div", { className: "meeting-note", children: /* @__PURE__ */ jsx25("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
|
|
2331
|
+
/* @__PURE__ */ jsx25(
|
|
1405
2332
|
Rescheduler,
|
|
1406
2333
|
{
|
|
1407
2334
|
api,
|
|
@@ -1418,9 +2345,9 @@ function ProvisionalCard(props) {
|
|
|
1418
2345
|
return card(
|
|
1419
2346
|
copy,
|
|
1420
2347
|
copy.provisional.bookCall,
|
|
1421
|
-
/* @__PURE__ */
|
|
1422
|
-
/* @__PURE__ */
|
|
1423
|
-
/* @__PURE__ */
|
|
2348
|
+
/* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
2349
|
+
/* @__PURE__ */ jsx25("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
|
|
2350
|
+
/* @__PURE__ */ jsx25(
|
|
1424
2351
|
Rescheduler,
|
|
1425
2352
|
{
|
|
1426
2353
|
api,
|
|
@@ -1447,8 +2374,8 @@ function MembersArea(props) {
|
|
|
1447
2374
|
renderProvisional
|
|
1448
2375
|
} = props;
|
|
1449
2376
|
const copy = props.copy ?? inheritedCopy.members;
|
|
1450
|
-
const [me, setMe] =
|
|
1451
|
-
const [error, setError] =
|
|
2377
|
+
const [me, setMe] = useState18(null);
|
|
2378
|
+
const [error, setError] = useState18(false);
|
|
1452
2379
|
const reload = async () => {
|
|
1453
2380
|
try {
|
|
1454
2381
|
setMe(await api("/api/me"));
|
|
@@ -1456,25 +2383,44 @@ function MembersArea(props) {
|
|
|
1456
2383
|
setError(true);
|
|
1457
2384
|
}
|
|
1458
2385
|
};
|
|
1459
|
-
|
|
2386
|
+
useEffect11(() => {
|
|
1460
2387
|
void reload();
|
|
1461
2388
|
}, []);
|
|
1462
|
-
if (error) return /* @__PURE__ */
|
|
1463
|
-
if (!me) return /* @__PURE__ */
|
|
2389
|
+
if (error) return /* @__PURE__ */ jsx25("p", { className: "meeting-note", children: copy.loadFailed });
|
|
2390
|
+
if (!me) return /* @__PURE__ */ jsx25("p", { className: "meeting-note", children: inheritedCopy.common.loading });
|
|
2391
|
+
if (props.portal && me.memberAccess === true && me.portal) {
|
|
2392
|
+
const gifts = /* @__PURE__ */ jsx25(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment });
|
|
2393
|
+
return /* @__PURE__ */ jsx25(
|
|
2394
|
+
MemberPortal,
|
|
2395
|
+
{
|
|
2396
|
+
...props.portal,
|
|
2397
|
+
api,
|
|
2398
|
+
me: { ...me, portal: me.portal },
|
|
2399
|
+
signOut,
|
|
2400
|
+
reloadMe: reload,
|
|
2401
|
+
adminHref: props.portal.adminHref ?? adminHref,
|
|
2402
|
+
profile: { ...props.portal.profile, extras: /* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
2403
|
+
props.portal.profile?.extras,
|
|
2404
|
+
gifts,
|
|
2405
|
+
me.namedSeatsEnabled ? /* @__PURE__ */ jsx25(NamedSeatPurchase, { api }) : null
|
|
2406
|
+
] }) }
|
|
2407
|
+
}
|
|
2408
|
+
);
|
|
2409
|
+
}
|
|
1464
2410
|
const role = me.role || "provisional";
|
|
1465
|
-
return /* @__PURE__ */
|
|
1466
|
-
/* @__PURE__ */
|
|
1467
|
-
/* @__PURE__ */
|
|
1468
|
-
/* @__PURE__ */
|
|
1469
|
-
/* @__PURE__ */
|
|
2411
|
+
return /* @__PURE__ */ jsxs22(Fragment10, { children: [
|
|
2412
|
+
/* @__PURE__ */ jsxs22("div", { className: "card", children: [
|
|
2413
|
+
/* @__PURE__ */ jsxs22("div", { className: "member-row", children: [
|
|
2414
|
+
/* @__PURE__ */ jsx25("span", { className: "member-email", children: me.email }),
|
|
2415
|
+
/* @__PURE__ */ jsx25("span", { className: "role-badge " + role, children: role })
|
|
1470
2416
|
] }),
|
|
1471
|
-
/* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
me.authorized || me.superAdmin ? /* @__PURE__ */
|
|
2417
|
+
/* @__PURE__ */ jsxs22("div", { className: "account-actions", children: [
|
|
2418
|
+
/* @__PURE__ */ jsx25("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
|
|
2419
|
+
me.authorized || me.superAdmin ? /* @__PURE__ */ jsx25("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
|
|
1474
2420
|
] })
|
|
1475
2421
|
] }),
|
|
1476
|
-
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */
|
|
1477
|
-
const defaultContent = /* @__PURE__ */
|
|
2422
|
+
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx25(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
|
|
2423
|
+
const defaultContent = /* @__PURE__ */ jsx25(
|
|
1478
2424
|
ProvisionalCard,
|
|
1479
2425
|
{
|
|
1480
2426
|
api,
|
|
@@ -1491,27 +2437,34 @@ function MembersArea(props) {
|
|
|
1491
2437
|
reload,
|
|
1492
2438
|
defaultContent
|
|
1493
2439
|
}) ?? defaultContent;
|
|
1494
|
-
})() : memberContent ?? (memberPages ? /* @__PURE__ */
|
|
2440
|
+
})() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx25(
|
|
1495
2441
|
MemberContentArea,
|
|
1496
2442
|
{
|
|
1497
2443
|
api,
|
|
1498
2444
|
...memberPages === true ? {} : memberPages
|
|
1499
2445
|
}
|
|
1500
|
-
) : /* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
me.namedSeatsEnabled ? /* @__PURE__ */
|
|
2446
|
+
) : /* @__PURE__ */ jsx25("div", { className: "card", children: /* @__PURE__ */ jsx25("div", { className: "card-label", children: copy.full.welcome }) })),
|
|
2447
|
+
/* @__PURE__ */ jsx25(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
|
|
2448
|
+
me.namedSeatsEnabled ? /* @__PURE__ */ jsx25(NamedSeatPurchase, { api }) : null
|
|
1503
2449
|
] });
|
|
1504
2450
|
}
|
|
1505
2451
|
|
|
2452
|
+
// src/ui/join-referral.ts
|
|
2453
|
+
var CODE = /^[23456789abcdefghjkmnpqrstuvwxyz]{5,8}$/;
|
|
2454
|
+
function referralFromLocation(search = typeof location === "undefined" ? "" : location.search) {
|
|
2455
|
+
const code = new URLSearchParams(search).get("ref")?.trim().toLowerCase() ?? "";
|
|
2456
|
+
return CODE.test(code) ? { referralCode: code } : {};
|
|
2457
|
+
}
|
|
2458
|
+
|
|
1506
2459
|
// src/ui/join.tsx
|
|
1507
|
-
import { useEffect as
|
|
2460
|
+
import { useEffect as useEffect16, useRef as useRef8, useState as useState26 } from "preact/hooks";
|
|
1508
2461
|
|
|
1509
2462
|
// src/ui/join-booking.tsx
|
|
1510
|
-
import { useEffect as
|
|
1511
|
-
import { jsx as
|
|
2463
|
+
import { useEffect as useEffect12, useRef as useRef6, useState as useState19 } from "preact/hooks";
|
|
2464
|
+
import { jsx as jsx26, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
1512
2465
|
function useJoinSlotsPreload(active) {
|
|
1513
2466
|
const preload = useRef6(null);
|
|
1514
|
-
|
|
2467
|
+
useEffect12(() => {
|
|
1515
2468
|
if (!active || preload.current) return;
|
|
1516
2469
|
preload.current = Promise.resolve().then(() => fetch("/api/schedule/slots"));
|
|
1517
2470
|
preload.current.catch(() => {
|
|
@@ -1522,11 +2475,11 @@ function useJoinSlotsPreload(active) {
|
|
|
1522
2475
|
}
|
|
1523
2476
|
function JoinBooking(props) {
|
|
1524
2477
|
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] =
|
|
2478
|
+
const [state, setState] = useState19(null);
|
|
2479
|
+
const [msg, setMsg] = useState19(null);
|
|
2480
|
+
const [busy, setBusy] = useState19(false);
|
|
2481
|
+
const [day2, setDay] = useState19(null);
|
|
2482
|
+
const [selected, setSelected] = useState19(null);
|
|
1530
2483
|
const load = async (preloaded) => {
|
|
1531
2484
|
setMsg(null);
|
|
1532
2485
|
try {
|
|
@@ -1551,7 +2504,7 @@ function JoinBooking(props) {
|
|
|
1551
2504
|
setMsg(copy.loadFailed);
|
|
1552
2505
|
}
|
|
1553
2506
|
};
|
|
1554
|
-
|
|
2507
|
+
useEffect12(() => {
|
|
1555
2508
|
void load(props.preload);
|
|
1556
2509
|
}, [simulation]);
|
|
1557
2510
|
const book = async () => {
|
|
@@ -1583,17 +2536,17 @@ function JoinBooking(props) {
|
|
|
1583
2536
|
setBusy(false);
|
|
1584
2537
|
}
|
|
1585
2538
|
};
|
|
1586
|
-
if (!state) return /* @__PURE__ */
|
|
2539
|
+
if (!state) return /* @__PURE__ */ jsx26("p", { className: "slots-status", children: msg ?? copy.loading });
|
|
1587
2540
|
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__ */
|
|
2541
|
+
return /* @__PURE__ */ jsxs23("div", { className: "join-book", children: [
|
|
2542
|
+
/* @__PURE__ */ jsx26("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
|
|
2543
|
+
/* @__PURE__ */ jsx26("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
|
|
2544
|
+
/* @__PURE__ */ jsxs23("div", { className: "slot-confirm", children: [
|
|
2545
|
+
/* @__PURE__ */ jsx26("button", { className: "submit-btn", type: "button", disabled: busy || !selected, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
|
|
2546
|
+
hint ? /* @__PURE__ */ jsx26("p", { className: "slot-hint", role: "status", children: hint }) : null,
|
|
2547
|
+
msg ? /* @__PURE__ */ jsx26("p", { className: "step2-note", role: "alert", children: msg }) : null
|
|
1595
2548
|
] }),
|
|
1596
|
-
/* @__PURE__ */
|
|
2549
|
+
/* @__PURE__ */ jsx26(
|
|
1597
2550
|
SlotPicker,
|
|
1598
2551
|
{
|
|
1599
2552
|
slots: state.slots,
|
|
@@ -1611,21 +2564,21 @@ function JoinBooking(props) {
|
|
|
1611
2564
|
}
|
|
1612
2565
|
|
|
1613
2566
|
// src/ui/join-accepted.tsx
|
|
1614
|
-
import { jsx as
|
|
2567
|
+
import { jsx as jsx27, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
1615
2568
|
function JoinAccepted(props) {
|
|
1616
|
-
return /* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
1618
|
-
/* @__PURE__ */
|
|
1619
|
-
/* @__PURE__ */
|
|
2569
|
+
return /* @__PURE__ */ jsxs24("div", { className: "join-done card", children: [
|
|
2570
|
+
/* @__PURE__ */ jsx27("div", { className: "card-label", children: props.copy.accepted.label }),
|
|
2571
|
+
/* @__PURE__ */ jsx27("p", { className: "meeting-note", children: props.copy.accepted.body }),
|
|
2572
|
+
/* @__PURE__ */ jsx27("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
|
|
1620
2573
|
] });
|
|
1621
2574
|
}
|
|
1622
2575
|
|
|
1623
2576
|
// src/ui/gift-claim-card.tsx
|
|
1624
|
-
import { useState as
|
|
1625
|
-
import { Fragment as
|
|
2577
|
+
import { useState as useState20 } from "preact/hooks";
|
|
2578
|
+
import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
1626
2579
|
function GiftClaimCard(props) {
|
|
1627
|
-
const [code, setCode] =
|
|
1628
|
-
const [error, setError] =
|
|
2580
|
+
const [code, setCode] = useState20(props.initialCode ?? "");
|
|
2581
|
+
const [error, setError] = useState20(false);
|
|
1629
2582
|
const rotate = async () => {
|
|
1630
2583
|
if (!props.claimId) return;
|
|
1631
2584
|
setError(false);
|
|
@@ -1638,15 +2591,15 @@ function GiftClaimCard(props) {
|
|
|
1638
2591
|
if (response.ok && body.code) setCode(body.code);
|
|
1639
2592
|
else setError(true);
|
|
1640
2593
|
};
|
|
1641
|
-
return /* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
1644
|
-
code ? /* @__PURE__ */
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
2594
|
+
return /* @__PURE__ */ jsxs25("div", { className: "join-done card", children: [
|
|
2595
|
+
/* @__PURE__ */ jsx28("div", { className: "card-label", children: props.copy.label }),
|
|
2596
|
+
/* @__PURE__ */ jsx28("p", { className: "meeting-note", children: props.copy.body }),
|
|
2597
|
+
code ? /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
2598
|
+
/* @__PURE__ */ jsx28("output", { className: "gift-code", children: code }),
|
|
2599
|
+
/* @__PURE__ */ jsx28("p", { children: props.copy.save })
|
|
1647
2600
|
] }) : null,
|
|
1648
|
-
!code && props.claimId ? /* @__PURE__ */
|
|
1649
|
-
error ? /* @__PURE__ */
|
|
2601
|
+
!code && props.claimId ? /* @__PURE__ */ jsx28("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
|
|
2602
|
+
error ? /* @__PURE__ */ jsx28("p", { role: "alert", children: props.copy.rotateFailed }) : null
|
|
1650
2603
|
] });
|
|
1651
2604
|
}
|
|
1652
2605
|
|
|
@@ -1654,11 +2607,11 @@ function GiftClaimCard(props) {
|
|
|
1654
2607
|
import { useRef as useRef7 } from "preact/hooks";
|
|
1655
2608
|
|
|
1656
2609
|
// src/ui/join-tiers.tsx
|
|
1657
|
-
import { useState as
|
|
1658
|
-
import { Fragment as
|
|
2610
|
+
import { useState as useState21 } from "preact/hooks";
|
|
2611
|
+
import { Fragment as Fragment12, jsx as jsx29, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
1659
2612
|
var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
|
|
1660
2613
|
function useTierSelection(tiers, initialTierId) {
|
|
1661
|
-
const [selectedTierId, setSelectedTierId] =
|
|
2614
|
+
const [selectedTierId, setSelectedTierId] = useState21(() => {
|
|
1662
2615
|
const preset = tiers.find((tier) => tier.id === initialTierId);
|
|
1663
2616
|
if (preset) return preset.id;
|
|
1664
2617
|
return tiers.length === 1 ? tiers[0].id : null;
|
|
@@ -1673,10 +2626,10 @@ function useTierSelection(tiers, initialTierId) {
|
|
|
1673
2626
|
};
|
|
1674
2627
|
}
|
|
1675
2628
|
function TierPlaceholder(context) {
|
|
1676
|
-
return /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
context.tiers.map((tier) => /* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
2629
|
+
return /* @__PURE__ */ jsxs26("fieldset", { "data-chapter-placeholder": "tiers", children: [
|
|
2630
|
+
/* @__PURE__ */ jsx29("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
|
|
2631
|
+
context.tiers.map((tier) => /* @__PURE__ */ jsxs26("label", { children: [
|
|
2632
|
+
/* @__PURE__ */ jsx29(
|
|
1680
2633
|
"input",
|
|
1681
2634
|
{
|
|
1682
2635
|
type: "radio",
|
|
@@ -1687,13 +2640,13 @@ function TierPlaceholder(context) {
|
|
|
1687
2640
|
}
|
|
1688
2641
|
),
|
|
1689
2642
|
tier.name,
|
|
1690
|
-
tier.founding ? /* @__PURE__ */
|
|
2643
|
+
tier.founding ? /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
1691
2644
|
" \u2014 ",
|
|
1692
2645
|
joinTierMoney(tier.founding.dueTodayCents),
|
|
1693
2646
|
" founding member rate (list ",
|
|
1694
2647
|
joinTierMoney(tier.priceCents),
|
|
1695
2648
|
")"
|
|
1696
|
-
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */
|
|
2649
|
+
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs26(Fragment12, { children: [
|
|
1697
2650
|
" \u2014 ",
|
|
1698
2651
|
joinTierMoney(tier.priceCents)
|
|
1699
2652
|
] })
|
|
@@ -1705,12 +2658,12 @@ function tierNeedsPayment(selected, paymentsReady) {
|
|
|
1705
2658
|
}
|
|
1706
2659
|
|
|
1707
2660
|
// src/ui/join-application-form.tsx
|
|
1708
|
-
import { jsx as
|
|
2661
|
+
import { jsx as jsx30, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
1709
2662
|
function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
|
|
1710
2663
|
const form = useRef7(null);
|
|
1711
2664
|
const ready = useFormReadiness(form);
|
|
1712
2665
|
const disabled = submitting || props.submitDisabled === true || !ready || !validJoinRecipient(props.payment?.initialNamedSeat);
|
|
1713
|
-
return /* @__PURE__ */
|
|
2666
|
+
return /* @__PURE__ */ jsxs27("form", { ref: form, className: "join-form", onSubmit: (event) => {
|
|
1714
2667
|
if (!isFormReady(event.currentTarget)) {
|
|
1715
2668
|
event.preventDefault();
|
|
1716
2669
|
event.currentTarget.reportValidity();
|
|
@@ -1718,15 +2671,15 @@ function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelec
|
|
|
1718
2671
|
}
|
|
1719
2672
|
void submit(event);
|
|
1720
2673
|
}, children: [
|
|
1721
|
-
!requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
2674
|
+
!requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs27("fieldset", { children: [
|
|
2675
|
+
/* @__PURE__ */ jsx30("legend", { children: copy.gift.optionsLabel }),
|
|
2676
|
+
/* @__PURE__ */ jsx30("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
|
|
2677
|
+
/* @__PURE__ */ jsx30(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
|
|
1725
2678
|
] }) : null,
|
|
1726
2679
|
!requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
|
|
1727
2680
|
typeof props.children === "function" ? props.children({ invitation }) : props.children,
|
|
1728
|
-
error ? /* @__PURE__ */
|
|
1729
|
-
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */
|
|
2681
|
+
error ? /* @__PURE__ */ jsx30("p", { className: "join-error", role: "alert", children: error }) : null,
|
|
2682
|
+
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx30(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
|
|
1730
2683
|
] });
|
|
1731
2684
|
}
|
|
1732
2685
|
|
|
@@ -1751,8 +2704,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
|
|
|
1751
2704
|
|
|
1752
2705
|
// src/ui/gift-code-redeemer.tsx
|
|
1753
2706
|
import { InlineActionField } from "@odla-ai/ui/components";
|
|
1754
|
-
import { useState as
|
|
1755
|
-
import { Fragment as
|
|
2707
|
+
import { useState as useState22 } from "preact/hooks";
|
|
2708
|
+
import { Fragment as Fragment13, jsx as jsx31, jsxs as jsxs28 } from "preact/jsx-runtime";
|
|
1756
2709
|
var GIFT_CODE_REDEEMER_CSS = `
|
|
1757
2710
|
.gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
|
|
1758
2711
|
.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 +2720,10 @@ var GIFT_CODE_REDEEMER_CSS = `
|
|
|
1767
2720
|
@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
2721
|
`;
|
|
1769
2722
|
function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
1770
|
-
const [code, setCode] =
|
|
1771
|
-
const [loading, setLoading] =
|
|
1772
|
-
const [message, setMessage] =
|
|
1773
|
-
const [messageTone, setMessageTone] =
|
|
2723
|
+
const [code, setCode] = useState22("");
|
|
2724
|
+
const [loading, setLoading] = useState22(false);
|
|
2725
|
+
const [message, setMessage] = useState22("");
|
|
2726
|
+
const [messageTone, setMessageTone] = useState22("neutral");
|
|
1774
2727
|
const normalizedCode = code.trim();
|
|
1775
2728
|
const redeem = async () => {
|
|
1776
2729
|
if (!normalizedCode || loading) return;
|
|
@@ -1797,9 +2750,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
|
1797
2750
|
setLoading(false);
|
|
1798
2751
|
}
|
|
1799
2752
|
};
|
|
1800
|
-
return /* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
2753
|
+
return /* @__PURE__ */ jsxs28(Fragment13, { children: [
|
|
2754
|
+
/* @__PURE__ */ jsx31("style", { children: GIFT_CODE_REDEEMER_CSS }),
|
|
2755
|
+
/* @__PURE__ */ jsx31(
|
|
1803
2756
|
InlineActionField,
|
|
1804
2757
|
{
|
|
1805
2758
|
id,
|
|
@@ -1855,12 +2808,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
|
|
|
1855
2808
|
}
|
|
1856
2809
|
|
|
1857
2810
|
// src/ui/join-gift-claim.tsx
|
|
1858
|
-
import { jsx as
|
|
2811
|
+
import { jsx as jsx32, jsxs as jsxs29 } from "preact/jsx-runtime";
|
|
1859
2812
|
function JoinGiftClaim(props) {
|
|
1860
|
-
return /* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
1862
|
-
/* @__PURE__ */
|
|
1863
|
-
/* @__PURE__ */
|
|
2813
|
+
return /* @__PURE__ */ jsxs29("section", { className: "join-gift-claim card", children: [
|
|
2814
|
+
/* @__PURE__ */ jsx32("div", { className: "card-label", children: props.copy.claimTitle }),
|
|
2815
|
+
/* @__PURE__ */ jsx32("p", { children: props.copy.claimBody }),
|
|
2816
|
+
/* @__PURE__ */ jsx32(
|
|
1864
2817
|
GiftCodeRedeemer,
|
|
1865
2818
|
{
|
|
1866
2819
|
api: props.api,
|
|
@@ -1884,21 +2837,21 @@ function JoinGiftClaim(props) {
|
|
|
1884
2837
|
}
|
|
1885
2838
|
|
|
1886
2839
|
// src/ui/join-named-seat.tsx
|
|
1887
|
-
import { useState as
|
|
1888
|
-
import { jsx as
|
|
2840
|
+
import { useState as useState23 } from "preact/hooks";
|
|
2841
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "preact/jsx-runtime";
|
|
1889
2842
|
function JoinNamedSeat(props) {
|
|
1890
2843
|
const seatId = props.seatId ?? "";
|
|
1891
2844
|
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__ */
|
|
2845
|
+
const [accepted, setAccepted] = useState23(false), [busy, setBusy] = useState23(false), [error, setError] = useState23("");
|
|
2846
|
+
return /* @__PURE__ */ jsxs30("section", { className: "join-named-seat card", children: [
|
|
2847
|
+
/* @__PURE__ */ jsx33("h2", { children: copy.title }),
|
|
2848
|
+
/* @__PURE__ */ jsx33("p", { children: copy.body }),
|
|
2849
|
+
/* @__PURE__ */ jsxs30("label", { className: "journey-consent", children: [
|
|
2850
|
+
/* @__PURE__ */ jsx33("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
|
|
2851
|
+
/* @__PURE__ */ jsx33("span", { children: copy.consent })
|
|
1899
2852
|
] }),
|
|
1900
|
-
error ? /* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
2853
|
+
error ? /* @__PURE__ */ jsx33("p", { role: "alert", children: error }) : null,
|
|
2854
|
+
/* @__PURE__ */ jsx33("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
|
|
1902
2855
|
setBusy(true);
|
|
1903
2856
|
setError("");
|
|
1904
2857
|
try {
|
|
@@ -1918,13 +2871,13 @@ function JoinNamedSeat(props) {
|
|
|
1918
2871
|
}
|
|
1919
2872
|
|
|
1920
2873
|
// src/ui/join-invitation.tsx
|
|
1921
|
-
import { useEffect as
|
|
1922
|
-
import { jsx as
|
|
2874
|
+
import { useEffect as useEffect13, useState as useState24 } from "preact/hooks";
|
|
2875
|
+
import { jsx as jsx34, jsxs as jsxs31 } from "preact/jsx-runtime";
|
|
1923
2876
|
function useJoinInvitation(seatId, api, fallback) {
|
|
1924
|
-
const [invitation, setInvitation] =
|
|
1925
|
-
const [error, setError] =
|
|
1926
|
-
const [revision, setRevision] =
|
|
1927
|
-
|
|
2877
|
+
const [invitation, setInvitation] = useState24(null);
|
|
2878
|
+
const [error, setError] = useState24("");
|
|
2879
|
+
const [revision, setRevision] = useState24(0);
|
|
2880
|
+
useEffect13(() => {
|
|
1928
2881
|
let live = true;
|
|
1929
2882
|
setInvitation(null);
|
|
1930
2883
|
setError("");
|
|
@@ -1946,9 +2899,9 @@ function useJoinInvitation(seatId, api, fallback) {
|
|
|
1946
2899
|
return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
|
|
1947
2900
|
}
|
|
1948
2901
|
function JoinInvitationNotice(props) {
|
|
1949
|
-
return /* @__PURE__ */
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
/* @__PURE__ */
|
|
2902
|
+
return /* @__PURE__ */ jsxs31("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
|
|
2903
|
+
/* @__PURE__ */ jsx34("p", { children: /* @__PURE__ */ jsx34("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
|
|
2904
|
+
/* @__PURE__ */ jsx34("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
|
|
1952
2905
|
] });
|
|
1953
2906
|
}
|
|
1954
2907
|
|
|
@@ -1963,9 +2916,9 @@ function joinSimulationPayment(simulation, priceCents) {
|
|
|
1963
2916
|
}
|
|
1964
2917
|
|
|
1965
2918
|
// src/ui/join-pending.ts
|
|
1966
|
-
import { useEffect as
|
|
2919
|
+
import { useEffect as useEffect14 } from "preact/hooks";
|
|
1967
2920
|
function useJoinPending(state, loadResume, setState) {
|
|
1968
|
-
|
|
2921
|
+
useEffect14(() => {
|
|
1969
2922
|
if (state.step !== "paymentPending") return;
|
|
1970
2923
|
let live = true;
|
|
1971
2924
|
let timer;
|
|
@@ -1988,16 +2941,16 @@ function useJoinPending(state, loadResume, setState) {
|
|
|
1988
2941
|
}
|
|
1989
2942
|
|
|
1990
2943
|
// src/ui/payment-receipt.tsx
|
|
1991
|
-
import { useEffect as
|
|
1992
|
-
import { Fragment as
|
|
2944
|
+
import { useEffect as useEffect15, useState as useState25 } from "preact/hooks";
|
|
2945
|
+
import { Fragment as Fragment14, jsx as jsx35, jsxs as jsxs32 } from "preact/jsx-runtime";
|
|
1993
2946
|
function PaymentReceiptCard({ applicationId }) {
|
|
1994
|
-
const [receipt, setReceipt] =
|
|
1995
|
-
const [error, setError] =
|
|
1996
|
-
const [revision, setRevision] =
|
|
1997
|
-
const [emailState, setEmailState] =
|
|
1998
|
-
const [previewEmail, setPreviewEmail] =
|
|
2947
|
+
const [receipt, setReceipt] = useState25(null);
|
|
2948
|
+
const [error, setError] = useState25("");
|
|
2949
|
+
const [revision, setRevision] = useState25(0);
|
|
2950
|
+
const [emailState, setEmailState] = useState25("idle");
|
|
2951
|
+
const [previewEmail, setPreviewEmail] = useState25(false);
|
|
1999
2952
|
const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
|
|
2000
|
-
|
|
2953
|
+
useEffect15(() => {
|
|
2001
2954
|
let live = true, timer;
|
|
2002
2955
|
setReceipt(null);
|
|
2003
2956
|
setError("");
|
|
@@ -2023,9 +2976,9 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
2023
2976
|
if (timer) clearTimeout(timer);
|
|
2024
2977
|
};
|
|
2025
2978
|
}, [endpoint, revision]);
|
|
2026
|
-
if (!receipt) return error ? /* @__PURE__ */
|
|
2027
|
-
/* @__PURE__ */
|
|
2028
|
-
/* @__PURE__ */
|
|
2979
|
+
if (!receipt) return error ? /* @__PURE__ */ jsxs32("section", { "aria-label": "Payment receipt", children: [
|
|
2980
|
+
/* @__PURE__ */ jsx35("p", { role: "status", children: error }),
|
|
2981
|
+
/* @__PURE__ */ jsx35("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
|
|
2029
2982
|
] }) : null;
|
|
2030
2983
|
const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
|
|
2031
2984
|
const email = async () => {
|
|
@@ -2042,38 +2995,38 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
2042
2995
|
setError("We could not confirm email delivery. You can print or save your receipt.");
|
|
2043
2996
|
}
|
|
2044
2997
|
};
|
|
2045
|
-
return /* @__PURE__ */
|
|
2046
|
-
/* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
receipt.namedSeat ? /* @__PURE__ */
|
|
2052
|
-
/* @__PURE__ */
|
|
2998
|
+
return /* @__PURE__ */ jsxs32("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
|
|
2999
|
+
/* @__PURE__ */ jsx35("h2", { children: "Payment received" }),
|
|
3000
|
+
/* @__PURE__ */ jsx35("p", { children: receipt.tierName }),
|
|
3001
|
+
/* @__PURE__ */ jsxs32("dl", { className: "journey-summary", children: [
|
|
3002
|
+
/* @__PURE__ */ jsx35("dt", { children: "Membership" }),
|
|
3003
|
+
/* @__PURE__ */ jsx35("dd", { children: money(receipt.membershipCents) }),
|
|
3004
|
+
receipt.namedSeat ? /* @__PURE__ */ jsxs32(Fragment14, { children: [
|
|
3005
|
+
/* @__PURE__ */ jsxs32("dt", { children: [
|
|
2053
3006
|
"Additional member \u2014 ",
|
|
2054
3007
|
receipt.namedSeat.recipientName
|
|
2055
3008
|
] }),
|
|
2056
|
-
/* @__PURE__ */
|
|
3009
|
+
/* @__PURE__ */ jsxs32("dd", { children: [
|
|
2057
3010
|
receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
|
|
2058
3011
|
money(receipt.namedSeat.amountCents)
|
|
2059
3012
|
] })
|
|
2060
3013
|
] }) : null,
|
|
2061
|
-
/* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
3014
|
+
/* @__PURE__ */ jsx35("dt", { children: "Total paid" }),
|
|
3015
|
+
/* @__PURE__ */ jsx35("dd", { children: money(receipt.totalCents) })
|
|
2063
3016
|
] }),
|
|
2064
|
-
/* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
3017
|
+
/* @__PURE__ */ jsxs32("div", { className: "journey-actions", children: [
|
|
3018
|
+
/* @__PURE__ */ jsx35("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
|
|
3019
|
+
/* @__PURE__ */ jsx35("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
|
|
2067
3020
|
] }),
|
|
2068
|
-
emailState === "sent" ? /* @__PURE__ */
|
|
2069
|
-
error ? /* @__PURE__ */
|
|
3021
|
+
emailState === "sent" ? /* @__PURE__ */ jsx35("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
|
|
3022
|
+
error ? /* @__PURE__ */ jsx35("p", { role: "alert", children: error }) : null
|
|
2070
3023
|
] });
|
|
2071
3024
|
}
|
|
2072
3025
|
|
|
2073
3026
|
// src/ui/join.tsx
|
|
2074
|
-
import { Fragment as
|
|
3027
|
+
import { Fragment as Fragment15, jsx as jsx36, jsxs as jsxs33 } from "preact/jsx-runtime";
|
|
2075
3028
|
function JoinIsland(props) {
|
|
2076
|
-
return /* @__PURE__ */
|
|
3029
|
+
return /* @__PURE__ */ jsx36(JourneyFrame, { children: /* @__PURE__ */ jsx36(JoinFlow, { ...props }) });
|
|
2077
3030
|
}
|
|
2078
3031
|
function JoinFlow(props) {
|
|
2079
3032
|
const inheritedCopy = useChapterCopy();
|
|
@@ -2094,16 +3047,16 @@ function JoinFlow(props) {
|
|
|
2094
3047
|
const invitation = invitationState.invitation;
|
|
2095
3048
|
const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
|
|
2096
3049
|
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] =
|
|
3050
|
+
const [state, setState] = useState26(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
|
|
3051
|
+
const [error, setError] = useState26(null);
|
|
3052
|
+
const [submitting, setSubmitting] = useState26(false);
|
|
3053
|
+
const [editingNamedSeat, setEditingNamedSeat] = useState26(false);
|
|
3054
|
+
const [giftOfferId, setGiftOfferId] = useState26(props.initialGiftOfferId ?? null);
|
|
2102
3055
|
const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
|
|
2103
3056
|
const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
|
|
2104
3057
|
const submissionId = useRef8(null);
|
|
2105
3058
|
const slotsPreload = useJoinSlotsPreload(!props.simulation && ["payment", "paymentPending"].includes(state.step));
|
|
2106
|
-
|
|
3059
|
+
useEffect16(() => {
|
|
2107
3060
|
if (props.simulation) return;
|
|
2108
3061
|
const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
|
|
2109
3062
|
if (typeof window === "undefined") return Promise.resolve(null);
|
|
@@ -2132,7 +3085,7 @@ function JoinFlow(props) {
|
|
|
2132
3085
|
setError(null);
|
|
2133
3086
|
try {
|
|
2134
3087
|
const fields = collectFormFields(new FormData(e.currentTarget));
|
|
2135
|
-
fields
|
|
3088
|
+
Object.assign(fields, { submissionId: submissionId.current ??= crypto.randomUUID() }, invitation ? {} : referralFromLocation());
|
|
2136
3089
|
if (invitation) {
|
|
2137
3090
|
fields.namedSeatId = invitation.seatId;
|
|
2138
3091
|
fields.tierId = invitation.skuId;
|
|
@@ -2176,13 +3129,13 @@ function JoinFlow(props) {
|
|
|
2176
3129
|
setSubmitting(false);
|
|
2177
3130
|
}
|
|
2178
3131
|
};
|
|
2179
|
-
if (requestedSeat && !invitation) return /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2182
|
-
invitationState.error ? /* @__PURE__ */
|
|
3132
|
+
if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs33("section", { className: "card", "aria-live": "polite", children: [
|
|
3133
|
+
/* @__PURE__ */ jsx36("h2", { children: seatCopy.title }),
|
|
3134
|
+
/* @__PURE__ */ jsx36("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
|
|
3135
|
+
invitationState.error ? /* @__PURE__ */ jsx36("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
|
|
2183
3136
|
] });
|
|
2184
|
-
const header = /* @__PURE__ */
|
|
2185
|
-
invitation ? /* @__PURE__ */
|
|
3137
|
+
const header = /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
3138
|
+
invitation ? /* @__PURE__ */ jsx36(
|
|
2186
3139
|
JoinInvitationNotice,
|
|
2187
3140
|
{
|
|
2188
3141
|
invitation,
|
|
@@ -2197,49 +3150,49 @@ function JoinFlow(props) {
|
|
|
2197
3150
|
..."applicationId" in state ? { applicationId: state.applicationId } : {}
|
|
2198
3151
|
})
|
|
2199
3152
|
] });
|
|
2200
|
-
const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */
|
|
3153
|
+
const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx36(PaymentReceiptCard, { applicationId: state.applicationId }) : null;
|
|
2201
3154
|
if (state.step === "closed") {
|
|
2202
|
-
return /* @__PURE__ */
|
|
3155
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2203
3156
|
header,
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
3157
|
+
/* @__PURE__ */ jsxs33("section", { className: "card", "aria-label": "Application closed", children: [
|
|
3158
|
+
/* @__PURE__ */ jsx36("h2", { children: "This application is closed" }),
|
|
3159
|
+
/* @__PURE__ */ jsx36("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
|
|
3160
|
+
/* @__PURE__ */ jsx36("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
2208
3161
|
] })
|
|
2209
3162
|
] });
|
|
2210
3163
|
}
|
|
2211
3164
|
if (state.step === "done") {
|
|
2212
|
-
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2214
|
-
/* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
3165
|
+
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs33("div", { className: "join-done card", children: [
|
|
3166
|
+
/* @__PURE__ */ jsx36("div", { className: "card-label", children: copy.done.label }),
|
|
3167
|
+
/* @__PURE__ */ jsx36("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
|
|
3168
|
+
/* @__PURE__ */ jsx36("p", { className: "meeting-note", children: copy.done.calendarInvite }),
|
|
3169
|
+
/* @__PURE__ */ jsx36("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
2217
3170
|
] });
|
|
2218
|
-
return /* @__PURE__ */
|
|
3171
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2219
3172
|
header,
|
|
2220
3173
|
body,
|
|
2221
3174
|
receipt
|
|
2222
3175
|
] });
|
|
2223
3176
|
}
|
|
2224
3177
|
if (state.step === "accepted") {
|
|
2225
|
-
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
2226
|
-
return /* @__PURE__ */
|
|
3178
|
+
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx36(JoinAccepted, { copy, membersHref });
|
|
3179
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2227
3180
|
header,
|
|
2228
3181
|
body,
|
|
2229
3182
|
receipt
|
|
2230
3183
|
] });
|
|
2231
3184
|
}
|
|
2232
3185
|
if (state.step === "gift") {
|
|
2233
|
-
const body = renderGift?.(state) ?? /* @__PURE__ */
|
|
2234
|
-
return /* @__PURE__ */
|
|
3186
|
+
const body = renderGift?.(state) ?? /* @__PURE__ */ jsx36(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
|
|
3187
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2235
3188
|
header,
|
|
2236
3189
|
body
|
|
2237
3190
|
] });
|
|
2238
3191
|
}
|
|
2239
3192
|
if (state.step === "booking") {
|
|
2240
|
-
return /* @__PURE__ */
|
|
3193
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2241
3194
|
header,
|
|
2242
|
-
/* @__PURE__ */
|
|
3195
|
+
/* @__PURE__ */ jsx36(
|
|
2243
3196
|
JoinBooking,
|
|
2244
3197
|
{
|
|
2245
3198
|
applicationId: state.applicationId,
|
|
@@ -2256,9 +3209,9 @@ function JoinFlow(props) {
|
|
|
2256
3209
|
}
|
|
2257
3210
|
if (state.step === "payment") {
|
|
2258
3211
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
|
|
2259
|
-
return /* @__PURE__ */
|
|
3212
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2260
3213
|
header,
|
|
2261
|
-
/* @__PURE__ */
|
|
3214
|
+
/* @__PURE__ */ jsx36(
|
|
2262
3215
|
JoinNamedSeat,
|
|
2263
3216
|
{
|
|
2264
3217
|
api: props.namedSeatClaimApi,
|
|
@@ -2271,9 +3224,9 @@ function JoinFlow(props) {
|
|
|
2271
3224
|
] });
|
|
2272
3225
|
}
|
|
2273
3226
|
const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
|
|
2274
|
-
return /* @__PURE__ */
|
|
3227
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2275
3228
|
header,
|
|
2276
|
-
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */
|
|
3229
|
+
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx36(
|
|
2277
3230
|
JoinGiftClaim,
|
|
2278
3231
|
{
|
|
2279
3232
|
api: props.giftClaimApi,
|
|
@@ -2284,7 +3237,7 @@ function JoinFlow(props) {
|
|
|
2284
3237
|
onError: () => setError(copy.form.unexpectedFailure)
|
|
2285
3238
|
}
|
|
2286
3239
|
) : null,
|
|
2287
|
-
/* @__PURE__ */
|
|
3240
|
+
/* @__PURE__ */ jsx36(
|
|
2288
3241
|
Payment,
|
|
2289
3242
|
{
|
|
2290
3243
|
applicationId: state.applicationId,
|
|
@@ -2312,9 +3265,9 @@ function JoinFlow(props) {
|
|
|
2312
3265
|
}
|
|
2313
3266
|
if (state.step === "paymentPending") {
|
|
2314
3267
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
|
|
2315
|
-
return /* @__PURE__ */
|
|
3268
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2316
3269
|
header,
|
|
2317
|
-
/* @__PURE__ */
|
|
3270
|
+
/* @__PURE__ */ jsx36(
|
|
2318
3271
|
JoinNamedSeat,
|
|
2319
3272
|
{
|
|
2320
3273
|
api: props.namedSeatClaimApi,
|
|
@@ -2326,15 +3279,15 @@ function JoinFlow(props) {
|
|
|
2326
3279
|
)
|
|
2327
3280
|
] });
|
|
2328
3281
|
}
|
|
2329
|
-
return /* @__PURE__ */
|
|
3282
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2330
3283
|
header,
|
|
2331
|
-
/* @__PURE__ */
|
|
3284
|
+
/* @__PURE__ */ jsx36("p", { className: "pay-status", role: "status", children: copy.payment.pending }),
|
|
2332
3285
|
receipt
|
|
2333
3286
|
] });
|
|
2334
3287
|
}
|
|
2335
|
-
return /* @__PURE__ */
|
|
3288
|
+
return /* @__PURE__ */ jsxs33(Fragment15, { children: [
|
|
2336
3289
|
header,
|
|
2337
|
-
/* @__PURE__ */
|
|
3290
|
+
/* @__PURE__ */ jsx36(
|
|
2338
3291
|
JoinApplicationForm,
|
|
2339
3292
|
{
|
|
2340
3293
|
props,
|
|
@@ -2353,7 +3306,7 @@ function JoinFlow(props) {
|
|
|
2353
3306
|
}
|
|
2354
3307
|
|
|
2355
3308
|
// src/ui/membership-cards.tsx
|
|
2356
|
-
import { Markdown as
|
|
3309
|
+
import { Markdown as Markdown4 } from "@odla-ai/ui/components";
|
|
2357
3310
|
|
|
2358
3311
|
// src/membership-page.ts
|
|
2359
3312
|
var MEMBERSHIP_PAGE_RENDERER = "membership-cards-v1";
|
|
@@ -2524,7 +3477,7 @@ function membershipPageDocument(input, options = {}) {
|
|
|
2524
3477
|
}
|
|
2525
3478
|
|
|
2526
3479
|
// src/ui/membership-cards.tsx
|
|
2527
|
-
import { jsx as
|
|
3480
|
+
import { jsx as jsx37, jsxs as jsxs34 } from "preact/jsx-runtime";
|
|
2528
3481
|
var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
|
|
2529
3482
|
"--ui-membership-grid-gap": "1.4rem",
|
|
2530
3483
|
"--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
|
|
@@ -2593,79 +3546,71 @@ function membershipApplicationHref(applicationPath, tierId) {
|
|
|
2593
3546
|
}
|
|
2594
3547
|
function TierAction(props) {
|
|
2595
3548
|
if (props.mode === "select") {
|
|
2596
|
-
return /* @__PURE__ */
|
|
3549
|
+
return /* @__PURE__ */ jsxs34("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
|
|
2597
3550
|
props.label,
|
|
2598
|
-
/* @__PURE__ */
|
|
3551
|
+
/* @__PURE__ */ jsx37("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2599
3552
|
] });
|
|
2600
3553
|
}
|
|
2601
3554
|
if (props.mode === "preview") {
|
|
2602
|
-
return /* @__PURE__ */
|
|
3555
|
+
return /* @__PURE__ */ jsxs34("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
|
|
2603
3556
|
props.label,
|
|
2604
|
-
/* @__PURE__ */
|
|
3557
|
+
/* @__PURE__ */ jsx37("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2605
3558
|
] });
|
|
2606
3559
|
}
|
|
2607
|
-
return /* @__PURE__ */
|
|
3560
|
+
return /* @__PURE__ */ jsxs34("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
|
|
2608
3561
|
props.label,
|
|
2609
|
-
/* @__PURE__ */
|
|
3562
|
+
/* @__PURE__ */ jsx37("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2610
3563
|
] });
|
|
2611
3564
|
}
|
|
2612
3565
|
function TierCard(props) {
|
|
2613
3566
|
const { tier, presentation } = props;
|
|
2614
3567
|
const summary = presentation.summaryMarkdown ?? tier.blurb;
|
|
2615
3568
|
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__ */
|
|
3569
|
+
return /* @__PURE__ */ jsxs34("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
|
|
3570
|
+
presentation.badge ? /* @__PURE__ */ jsx37("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
|
|
3571
|
+
/* @__PURE__ */ jsx37("h3", { className: "chapter-membership-name", children: tier.name }),
|
|
3572
|
+
/* @__PURE__ */ jsxs34("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
|
|
3573
|
+
presentation.capacity ? /* @__PURE__ */ jsxs34("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
|
|
3574
|
+
/* @__PURE__ */ jsx37("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
|
|
3575
|
+
/* @__PURE__ */ jsx37("small", { children: presentation.capacity.label ?? "available" })
|
|
2623
3576
|
] }) : null,
|
|
2624
|
-
/* @__PURE__ */
|
|
2625
|
-
presentation.priceEyebrow ? /* @__PURE__ */
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
tier.founding ? /* @__PURE__ */
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
!tier.free && presentation.billingLabel ? /* @__PURE__ */
|
|
3577
|
+
/* @__PURE__ */ jsxs34("div", { className: "chapter-membership-price-stack", children: [
|
|
3578
|
+
presentation.priceEyebrow ? /* @__PURE__ */ jsx37("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx37("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
|
|
3579
|
+
/* @__PURE__ */ jsxs34("div", { className: "chapter-membership-price-row", children: [
|
|
3580
|
+
tier.founding ? /* @__PURE__ */ jsx37("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx37("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
|
|
3581
|
+
/* @__PURE__ */ jsx37("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
|
|
3582
|
+
!tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx37("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
|
|
2630
3583
|
] })
|
|
2631
3584
|
] })
|
|
2632
3585
|
] }),
|
|
2633
|
-
presentation.priceNoteMarkdown ? /* @__PURE__ */
|
|
2634
|
-
summary ? /* @__PURE__ */
|
|
2635
|
-
presentation.benefits?.length ? /* @__PURE__ */
|
|
2636
|
-
/* @__PURE__ */
|
|
2637
|
-
/* @__PURE__ */
|
|
3586
|
+
presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx37(Markdown4, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
|
|
3587
|
+
summary ? /* @__PURE__ */ jsx37(Markdown4, { className: "chapter-membership-summary", source: summary }) : null,
|
|
3588
|
+
presentation.benefits?.length ? /* @__PURE__ */ jsx37("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs34("li", { children: [
|
|
3589
|
+
/* @__PURE__ */ jsx37("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
|
|
3590
|
+
/* @__PURE__ */ jsx37(Markdown4, { className: "chapter-membership-benefit", source: benefit })
|
|
2638
3591
|
] }, `${tier.id}-benefit-${index}`)) }) : null,
|
|
2639
|
-
presentation.callout ? /* @__PURE__ */
|
|
2640
|
-
presentation.callout.label ? /* @__PURE__ */
|
|
2641
|
-
/* @__PURE__ */
|
|
3592
|
+
presentation.callout ? /* @__PURE__ */ jsxs34("aside", { className: "chapter-membership-callout", children: [
|
|
3593
|
+
presentation.callout.label ? /* @__PURE__ */ jsx37("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
|
|
3594
|
+
/* @__PURE__ */ jsx37(Markdown4, { source: presentation.callout.bodyMarkdown })
|
|
2642
3595
|
] }) : null,
|
|
2643
|
-
/* @__PURE__ */
|
|
3596
|
+
/* @__PURE__ */ jsx37(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
|
|
2644
3597
|
] });
|
|
2645
3598
|
}
|
|
2646
3599
|
function MembershipCards(props) {
|
|
2647
3600
|
const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
|
|
2648
3601
|
const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
|
|
2649
3602
|
const mode = props.mode ?? "link";
|
|
2650
|
-
return /* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
3603
|
+
return /* @__PURE__ */ jsxs34("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
|
|
3604
|
+
/* @__PURE__ */ jsx37("style", { children: MEMBERSHIP_CARDS_CSS }),
|
|
3605
|
+
/* @__PURE__ */ jsx37("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
|
|
2653
3606
|
const tier = byId.get(presentation.tierId);
|
|
2654
|
-
return /* @__PURE__ */
|
|
3607
|
+
return /* @__PURE__ */ jsx37(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
|
|
2655
3608
|
}) }),
|
|
2656
|
-
document2.footnoteMarkdown ? /* @__PURE__ */
|
|
3609
|
+
document2.footnoteMarkdown ? /* @__PURE__ */ jsx37(Markdown4, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
|
|
2657
3610
|
] });
|
|
2658
3611
|
}
|
|
2659
3612
|
|
|
2660
3613
|
export {
|
|
2661
|
-
tzShort,
|
|
2662
|
-
dayKey,
|
|
2663
|
-
dayLabel,
|
|
2664
|
-
timeLabel,
|
|
2665
|
-
fullLabel,
|
|
2666
|
-
fmtMoney,
|
|
2667
|
-
fmtDate,
|
|
2668
|
-
groupSlotsByDay,
|
|
2669
3614
|
SlotPicker,
|
|
2670
3615
|
ADDITIONAL_MEMBER_COPY,
|
|
2671
3616
|
additionalMemberSelection,
|
|
@@ -2687,7 +3632,51 @@ export {
|
|
|
2687
3632
|
NamedSeatRecipientLine,
|
|
2688
3633
|
NamedSeatPurchase,
|
|
2689
3634
|
MemberContentArea,
|
|
3635
|
+
placeholderBadge,
|
|
3636
|
+
MemberPlaceholderBody,
|
|
3637
|
+
PortalIcon,
|
|
3638
|
+
PROFILE_SEGMENT,
|
|
3639
|
+
routeFromLocation,
|
|
3640
|
+
hrefFor,
|
|
3641
|
+
sameRoute,
|
|
3642
|
+
PortalAvatar,
|
|
3643
|
+
navTag,
|
|
3644
|
+
PortalNav,
|
|
3645
|
+
LockedPill,
|
|
3646
|
+
UpgradeLink,
|
|
3647
|
+
LockedScreen,
|
|
3648
|
+
PlaceholderScreen,
|
|
3649
|
+
PortalPage,
|
|
3650
|
+
PortalTile,
|
|
3651
|
+
DefaultHome,
|
|
3652
|
+
memberMonth,
|
|
3653
|
+
startingPrompts,
|
|
3654
|
+
choosePrompt,
|
|
3655
|
+
MemberProfilePage,
|
|
3656
|
+
useCourse,
|
|
3657
|
+
seatLine,
|
|
3658
|
+
SeatActions,
|
|
3659
|
+
CoursePage,
|
|
3660
|
+
CourseHomePanel,
|
|
3661
|
+
articleFor,
|
|
3662
|
+
shareVars,
|
|
3663
|
+
linkedinShareUrl,
|
|
3664
|
+
mailtoHref,
|
|
3665
|
+
smsHref,
|
|
3666
|
+
isIOS,
|
|
3667
|
+
useMemberReferrals,
|
|
3668
|
+
CopyButton,
|
|
3669
|
+
OfficialCard,
|
|
3670
|
+
PostCard,
|
|
3671
|
+
InviteLinkCard,
|
|
3672
|
+
ReferralsCard,
|
|
3673
|
+
SharePage,
|
|
3674
|
+
ShareHome,
|
|
3675
|
+
ProfileReferrals,
|
|
3676
|
+
PACKAGED_PORTAL_FEATURES,
|
|
3677
|
+
MemberPortal,
|
|
2690
3678
|
MembersArea,
|
|
3679
|
+
referralFromLocation,
|
|
2691
3680
|
useTierSelection,
|
|
2692
3681
|
TierPlaceholder,
|
|
2693
3682
|
tierNeedsPayment,
|
|
@@ -2698,4 +3687,4 @@ export {
|
|
|
2698
3687
|
membershipApplicationHref,
|
|
2699
3688
|
MembershipCards
|
|
2700
3689
|
};
|
|
2701
|
-
//# sourceMappingURL=chunk-
|
|
3690
|
+
//# sourceMappingURL=chunk-QPFJBHHK.js.map
|