@odla-ai/chapter 0.56.1 → 0.56.2
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 +39 -0
- package/dist/{chunk-NK267YQZ.js → chunk-E7CB5K2D.js} +668 -504
- package/dist/chunk-E7CB5K2D.js.map +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +11 -1
- package/dist/ui/member/index.d.ts +83 -1
- package/dist/ui/member/index.js +11 -1
- package/package.json +1 -1
- package/dist/chunk-NK267YQZ.js.map +0 -1
|
@@ -111,14 +111,185 @@ function SlotPicker(props) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
// src/ui/member-restart.tsx
|
|
114
|
-
import { useEffect as useEffect2, useState as
|
|
114
|
+
import { useEffect as useEffect2, useState as useState7 } from "preact/hooks";
|
|
115
|
+
|
|
116
|
+
// src/ui/additional-member-editor.tsx
|
|
117
|
+
import { useRef as useRef2, useState as useState3 } from "preact/hooks";
|
|
118
|
+
|
|
119
|
+
// src/ui/additional-member-fields.tsx
|
|
120
|
+
import { useRef } from "preact/hooks";
|
|
121
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
122
|
+
var ADDITIONAL_MEMBER_COPY = {
|
|
123
|
+
label: "Additional member",
|
|
124
|
+
includedChoice: "Include my additional member at no extra charge.",
|
|
125
|
+
paidChoice: "Add one additional member.",
|
|
126
|
+
includedHint: "Included with your membership at no extra charge.",
|
|
127
|
+
pendingHint: "Your additional-member rate will be confirmed at checkout.",
|
|
128
|
+
editTitle: "Edit additional member details"
|
|
129
|
+
};
|
|
130
|
+
function additionalMemberSelection(value) {
|
|
131
|
+
return value.selected ? { recipientName: value.name.trim(), recipientEmail: value.email.trim() } : null;
|
|
132
|
+
}
|
|
133
|
+
function AdditionalMemberFields({ value, onChange, offer, ...options }) {
|
|
134
|
+
const draft = useRef(value);
|
|
135
|
+
draft.current = value;
|
|
136
|
+
const change = (patch) => {
|
|
137
|
+
draft.current = { ...draft.current, ...patch };
|
|
138
|
+
onChange(draft.current);
|
|
139
|
+
};
|
|
140
|
+
const copy = { ...ADDITIONAL_MEMBER_COPY, ...options.copy };
|
|
141
|
+
const names = { selected: "additionalMemberSelected", name: "additionalMemberName", email: "additionalMemberEmail", ...options.names };
|
|
142
|
+
const price2 = offer && new Intl.NumberFormat("en-US", { style: "currency", currency: offer.currency ?? "USD" }).format(offer.amountCents / 100);
|
|
143
|
+
return /* @__PURE__ */ jsxs2("div", { className: "form-group additional-member-fields", children: [
|
|
144
|
+
/* @__PURE__ */ jsx2("label", { htmlFor: names.selected, children: copy.label }),
|
|
145
|
+
/* @__PURE__ */ jsx2("p", { className: "hint", children: offer?.amountCents === 0 ? copy.includedHint : offer ? `${price2} per ${offer.interval ?? "year"}, paid with your membership.` : copy.pendingHint }),
|
|
146
|
+
/* @__PURE__ */ jsxs2("label", { className: "checkbox-option journey-consent", children: [
|
|
147
|
+
/* @__PURE__ */ jsx2(
|
|
148
|
+
"input",
|
|
149
|
+
{
|
|
150
|
+
type: "checkbox",
|
|
151
|
+
id: names.selected,
|
|
152
|
+
name: names.selected,
|
|
153
|
+
value: "yes",
|
|
154
|
+
checked: value.selected,
|
|
155
|
+
onChange: (event) => change({ selected: event.currentTarget.checked })
|
|
156
|
+
}
|
|
157
|
+
),
|
|
158
|
+
offer?.amountCents === 0 ? copy.includedChoice : copy.paidChoice
|
|
159
|
+
] }),
|
|
160
|
+
value.selected ? /* @__PURE__ */ jsxs2("div", { className: "additional-member-details", children: [
|
|
161
|
+
/* @__PURE__ */ jsxs2("label", { htmlFor: names.name, children: [
|
|
162
|
+
"Full name ",
|
|
163
|
+
/* @__PURE__ */ jsx2("span", { className: "req", "aria-hidden": "true", children: "*" })
|
|
164
|
+
] }),
|
|
165
|
+
/* @__PURE__ */ jsx2(
|
|
166
|
+
"input",
|
|
167
|
+
{
|
|
168
|
+
type: "text",
|
|
169
|
+
id: names.name,
|
|
170
|
+
name: names.name,
|
|
171
|
+
placeholder: "Full name",
|
|
172
|
+
required: true,
|
|
173
|
+
minLength: 2,
|
|
174
|
+
maxLength: 160,
|
|
175
|
+
pattern: ".*\\S.*\\S.*",
|
|
176
|
+
value: value.name,
|
|
177
|
+
onInput: (event) => change({ name: event.currentTarget.value })
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ jsxs2("label", { htmlFor: names.email, children: [
|
|
181
|
+
"Email ",
|
|
182
|
+
/* @__PURE__ */ jsx2("span", { className: "req", "aria-hidden": "true", children: "*" })
|
|
183
|
+
] }),
|
|
184
|
+
/* @__PURE__ */ jsx2(
|
|
185
|
+
"input",
|
|
186
|
+
{
|
|
187
|
+
type: "email",
|
|
188
|
+
id: names.email,
|
|
189
|
+
name: names.email,
|
|
190
|
+
placeholder: "member@example.com",
|
|
191
|
+
required: true,
|
|
192
|
+
pattern: "[^\\s@]+@[^\\s@]+\\.[^\\s@]+",
|
|
193
|
+
maxLength: 254,
|
|
194
|
+
value: value.email,
|
|
195
|
+
onInput: (event) => change({ email: event.currentTarget.value })
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
] }) : null
|
|
199
|
+
] });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/ui/form-readiness.ts
|
|
203
|
+
import { useLayoutEffect, useState as useState2 } from "preact/hooks";
|
|
204
|
+
function isFormReady(form) {
|
|
205
|
+
return Array.from(form.elements).every((element) => {
|
|
206
|
+
const field = element;
|
|
207
|
+
return !field.willValidate || field.validity.valid && (!field.required || field.value.trim().length > 0);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
function useFormReadiness(ref) {
|
|
211
|
+
const [ready, setReady] = useState2(false);
|
|
212
|
+
useLayoutEffect(() => {
|
|
213
|
+
const form = ref.current;
|
|
214
|
+
if (!form) return;
|
|
215
|
+
let live = true;
|
|
216
|
+
const update = () => {
|
|
217
|
+
if (live) setReady(isFormReady(form));
|
|
218
|
+
};
|
|
219
|
+
const afterInput = () => queueMicrotask(update);
|
|
220
|
+
update();
|
|
221
|
+
for (const type of ["input", "change", "focusin", "reset"]) form.addEventListener(type, afterInput);
|
|
222
|
+
const observer = new MutationObserver(afterInput);
|
|
223
|
+
observer.observe(form, {
|
|
224
|
+
childList: true,
|
|
225
|
+
subtree: true,
|
|
226
|
+
attributes: true,
|
|
227
|
+
attributeFilter: ["required", "disabled", "pattern", "minlength", "maxlength", "min", "max", "type"]
|
|
228
|
+
});
|
|
229
|
+
return () => {
|
|
230
|
+
live = false;
|
|
231
|
+
observer.disconnect();
|
|
232
|
+
for (const type of ["input", "change", "focusin", "reset"]) form.removeEventListener(type, afterInput);
|
|
233
|
+
};
|
|
234
|
+
});
|
|
235
|
+
return ready;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/ui/join-submit-button.tsx
|
|
239
|
+
import { jsx as jsx3 } from "preact/jsx-runtime";
|
|
240
|
+
function JoinSubmitButton(props) {
|
|
241
|
+
return /* @__PURE__ */ jsx3("button", { ...props, type: "submit", className: "submit-btn chapter-form-primary" });
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/ui/join-recipient.ts
|
|
245
|
+
function validJoinRecipient(recipient) {
|
|
246
|
+
if (!recipient) return true;
|
|
247
|
+
const name = recipient.recipientName.trim(), email = recipient.recipientEmail.trim();
|
|
248
|
+
return name.length >= 2 && name.length <= 160 && !/[\u0000-\u001f\u007f]/.test(name) && email.length <= 254 && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/ui/additional-member-editor.tsx
|
|
252
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
253
|
+
function AdditionalMemberEditor({ selection, offer, save, cancel, onSaved, ...options }) {
|
|
254
|
+
const [value, setValue] = useState3({ selected: Boolean(selection), name: selection?.recipientName ?? "", email: selection?.recipientEmail ?? "" });
|
|
255
|
+
const [saving, setSaving] = useState3(false), [error, setError] = useState3("");
|
|
256
|
+
const form = useRef2(null), inFlight = useRef2(false);
|
|
257
|
+
const ready = useFormReadiness(form);
|
|
258
|
+
const valid = validJoinRecipient(additionalMemberSelection(value) ?? void 0);
|
|
259
|
+
return /* @__PURE__ */ jsxs3("form", { ref: form, className: "join-form additional-member-editor", onSubmit: async (event) => {
|
|
260
|
+
event.preventDefault();
|
|
261
|
+
if (inFlight.current || !valid || !isFormReady(event.currentTarget)) return;
|
|
262
|
+
inFlight.current = true;
|
|
263
|
+
setSaving(true);
|
|
264
|
+
setError("");
|
|
265
|
+
try {
|
|
266
|
+
await save(additionalMemberSelection(value));
|
|
267
|
+
onSaved?.(value);
|
|
268
|
+
} catch (failure) {
|
|
269
|
+
setError(failure instanceof Error ? failure.message : "Could not save your changes. Try again.");
|
|
270
|
+
} finally {
|
|
271
|
+
inFlight.current = false;
|
|
272
|
+
setSaving(false);
|
|
273
|
+
}
|
|
274
|
+
}, children: [
|
|
275
|
+
/* @__PURE__ */ jsx4("h2", { children: options.copy?.editTitle ?? ADDITIONAL_MEMBER_COPY.editTitle }),
|
|
276
|
+
/* @__PURE__ */ jsxs3("fieldset", { disabled: saving, children: [
|
|
277
|
+
/* @__PURE__ */ jsx4(AdditionalMemberFields, { ...options, value, onChange: setValue, offer }),
|
|
278
|
+
error ? /* @__PURE__ */ jsx4("p", { role: "alert", children: error }) : null,
|
|
279
|
+
/* @__PURE__ */ jsxs3("div", { className: "journey-actions additional-member-actions", children: [
|
|
280
|
+
/* @__PURE__ */ jsx4(JoinSubmitButton, { disabled: saving || !ready || !valid, children: saving ? "Saving\u2026" : "Save details" }),
|
|
281
|
+
/* @__PURE__ */ jsx4("button", { className: "journey-secondary", type: "button", onClick: cancel, children: "Cancel" })
|
|
282
|
+
] })
|
|
283
|
+
] })
|
|
284
|
+
] });
|
|
285
|
+
}
|
|
115
286
|
|
|
116
287
|
// src/ui/membership-payment-step.tsx
|
|
117
|
-
import { useEffect, useState as
|
|
288
|
+
import { useEffect, useState as useState6 } from "preact/hooks";
|
|
118
289
|
|
|
119
290
|
// src/ui/payment-step.tsx
|
|
120
|
-
import { useRef, useState as
|
|
121
|
-
import { jsx as
|
|
291
|
+
import { useRef as useRef3, useState as useState4 } from "preact/hooks";
|
|
292
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
122
293
|
var loader = null;
|
|
123
294
|
function loadStripe() {
|
|
124
295
|
const existing = globalThis.Stripe;
|
|
@@ -152,13 +323,13 @@ function PaymentStep(props) {
|
|
|
152
323
|
simulation
|
|
153
324
|
} = props;
|
|
154
325
|
const copy = props.copy ?? inheritedCopy.join.payment;
|
|
155
|
-
const [status, setStatus] =
|
|
156
|
-
const [error, setError] =
|
|
157
|
-
const [lineItems, setLineItems] =
|
|
158
|
-
const mountRef =
|
|
159
|
-
const stripeRef =
|
|
160
|
-
const elementsRef =
|
|
161
|
-
const completionRef =
|
|
326
|
+
const [status, setStatus] = useState4("idle");
|
|
327
|
+
const [error, setError] = useState4(null);
|
|
328
|
+
const [lineItems, setLineItems] = useState4(null);
|
|
329
|
+
const mountRef = useRef3(null);
|
|
330
|
+
const stripeRef = useRef3(null);
|
|
331
|
+
const elementsRef = useRef3(null);
|
|
332
|
+
const completionRef = useRef3({ gift: false });
|
|
162
333
|
const begin = async () => {
|
|
163
334
|
setStatus("loading");
|
|
164
335
|
setError(null);
|
|
@@ -228,12 +399,12 @@ function PaymentStep(props) {
|
|
|
228
399
|
setStatus("ready");
|
|
229
400
|
}
|
|
230
401
|
};
|
|
231
|
-
return /* @__PURE__ */
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
merchantDisclosureText ? /* @__PURE__ */
|
|
234
|
-
/* @__PURE__ */
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
/* @__PURE__ */
|
|
402
|
+
return /* @__PURE__ */ jsxs4("div", { className: "join-pay", children: [
|
|
403
|
+
/* @__PURE__ */ jsxs4("div", { className: "compliance-box", children: [
|
|
404
|
+
merchantDisclosureText ? /* @__PURE__ */ jsx5("p", { className: "compliance-merchant", children: merchantDisclosureText }) : null,
|
|
405
|
+
/* @__PURE__ */ jsx5("p", { className: "compliance-policy", children: refundPolicyText }),
|
|
406
|
+
/* @__PURE__ */ jsxs4("label", { className: "compliance-check", children: [
|
|
407
|
+
/* @__PURE__ */ jsx5(
|
|
237
408
|
"input",
|
|
238
409
|
{
|
|
239
410
|
type: "checkbox",
|
|
@@ -243,52 +414,55 @@ function PaymentStep(props) {
|
|
|
243
414
|
}
|
|
244
415
|
}
|
|
245
416
|
),
|
|
246
|
-
copy.consent ? /* @__PURE__ */
|
|
417
|
+
copy.consent ? /* @__PURE__ */ jsx5("span", { children: copy.consent }) : null
|
|
247
418
|
] })
|
|
248
419
|
] }),
|
|
249
|
-
status === "loading" ? /* @__PURE__ */
|
|
420
|
+
status === "loading" ? /* @__PURE__ */ jsx5("p", { className: "pay-status", children: copy.preparing }) : null,
|
|
250
421
|
lineItems && renderPriceLines ? renderPriceLines(lineItems) : null,
|
|
251
422
|
children,
|
|
252
|
-
simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */
|
|
253
|
-
/* @__PURE__ */
|
|
254
|
-
/* @__PURE__ */
|
|
423
|
+
simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */ jsxs4("fieldset", { className: "join-pay-simulation", children: [
|
|
424
|
+
/* @__PURE__ */ jsx5("legend", { children: "Payment details" }),
|
|
425
|
+
/* @__PURE__ */ jsxs4("label", { children: [
|
|
255
426
|
"Card number",
|
|
256
|
-
/* @__PURE__ */
|
|
427
|
+
/* @__PURE__ */ jsx5("input", { name: "simulationCardNumber", inputMode: "numeric", autoComplete: "off", defaultValue: "4242 4242 4242 4242" })
|
|
257
428
|
] }),
|
|
258
|
-
/* @__PURE__ */
|
|
429
|
+
/* @__PURE__ */ jsxs4("label", { children: [
|
|
259
430
|
"Expiration",
|
|
260
|
-
/* @__PURE__ */
|
|
431
|
+
/* @__PURE__ */ jsx5("input", { name: "simulationCardExpiry", inputMode: "numeric", autoComplete: "off", defaultValue: "12 / 34" })
|
|
261
432
|
] }),
|
|
262
|
-
/* @__PURE__ */
|
|
433
|
+
/* @__PURE__ */ jsxs4("label", { children: [
|
|
263
434
|
"Security code",
|
|
264
|
-
/* @__PURE__ */
|
|
435
|
+
/* @__PURE__ */ jsx5("input", { name: "simulationCardCvc", inputMode: "numeric", autoComplete: "off", defaultValue: "123" })
|
|
265
436
|
] }),
|
|
266
|
-
/* @__PURE__ */
|
|
437
|
+
/* @__PURE__ */ jsx5("p", { children: "This is a simulation. No card data is sent and no charge is created." })
|
|
267
438
|
] }) : null,
|
|
268
|
-
/* @__PURE__ */
|
|
269
|
-
status === "ready" || status === "confirming" ? /* @__PURE__ */
|
|
270
|
-
error ? /* @__PURE__ */
|
|
439
|
+
/* @__PURE__ */ jsx5("div", { ref: mountRef, hidden: status === "idle" || status === "loading" }),
|
|
440
|
+
status === "ready" || status === "confirming" ? /* @__PURE__ */ jsx5("button", { className: "submit-btn", disabled: status === "confirming", onClick: () => void pay(), children: status === "confirming" ? copy.processing : copy.payAndContinue }) : null,
|
|
441
|
+
error ? /* @__PURE__ */ jsx5("p", { className: "pay-error", children: error }) : null
|
|
271
442
|
] });
|
|
272
443
|
}
|
|
273
444
|
|
|
274
445
|
// src/ui/checkout-seat-choice.tsx
|
|
275
|
-
import { useState as
|
|
276
|
-
import {
|
|
446
|
+
import { useRef as useRef4, useState as useState5 } from "preact/hooks";
|
|
447
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
277
448
|
function CheckoutSeatChoice(props) {
|
|
278
449
|
const saved = props.quote.namedSeat;
|
|
279
|
-
const [selected, setSelected] =
|
|
280
|
-
const [name, setName] =
|
|
281
|
-
const [email, setEmail] =
|
|
282
|
-
const [saving, setSaving] =
|
|
283
|
-
const
|
|
284
|
-
const
|
|
450
|
+
const [selected, setSelected] = useState5(Boolean(saved || props.initial));
|
|
451
|
+
const [name, setName] = useState5(saved?.recipientName ?? props.initial?.recipientName ?? "");
|
|
452
|
+
const [email, setEmail] = useState5(saved?.recipientEmail ?? props.initial?.recipientEmail ?? "");
|
|
453
|
+
const [saving, setSaving] = useState5(false), [error, setError] = useState5("");
|
|
454
|
+
const form = useRef4(null), inFlight = useRef4(false);
|
|
455
|
+
const ready = useFormReadiness(form);
|
|
456
|
+
const valid = validJoinRecipient(selected ? { recipientName: name, recipientEmail: email } : void 0);
|
|
285
457
|
const dirty = selected !== Boolean(saved) || selected && (name !== saved?.recipientName || email !== saved?.recipientEmail);
|
|
286
458
|
const edit = (nextSelected, nextName = name, nextEmail = email) => {
|
|
287
459
|
props.onEditing(nextSelected !== Boolean(saved) || nextSelected && (nextName !== saved?.recipientName || nextEmail !== saved?.recipientEmail));
|
|
288
460
|
setError("");
|
|
289
461
|
};
|
|
290
|
-
return /* @__PURE__ */
|
|
462
|
+
return /* @__PURE__ */ jsx6("section", { className: "checkout-seat-choice", "aria-label": "Additional member", children: /* @__PURE__ */ jsxs5("form", { ref: form, onSubmit: async (event) => {
|
|
291
463
|
event.preventDefault();
|
|
464
|
+
if (props.locked || inFlight.current || !valid || !isFormReady(event.currentTarget)) return;
|
|
465
|
+
inFlight.current = true;
|
|
292
466
|
setSaving(true);
|
|
293
467
|
setError("");
|
|
294
468
|
try {
|
|
@@ -296,88 +470,60 @@ function CheckoutSeatChoice(props) {
|
|
|
296
470
|
} catch (error2) {
|
|
297
471
|
setError(error2 instanceof Error ? error2.message : "Could not save your selection. Try again.");
|
|
298
472
|
} finally {
|
|
473
|
+
inFlight.current = false;
|
|
299
474
|
setSaving(false);
|
|
300
475
|
}
|
|
301
476
|
}, children: [
|
|
302
|
-
/* @__PURE__ */
|
|
303
|
-
/* @__PURE__ */
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
required: true,
|
|
319
|
-
minLength: 2,
|
|
320
|
-
maxLength: 160,
|
|
321
|
-
value: name,
|
|
322
|
-
onInput: (event) => {
|
|
323
|
-
setName(event.currentTarget.value);
|
|
324
|
-
edit(selected, event.currentTarget.value);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
)
|
|
328
|
-
] }),
|
|
329
|
-
/* @__PURE__ */ jsxs3("label", { children: [
|
|
330
|
-
"Email",
|
|
331
|
-
/* @__PURE__ */ jsx3(
|
|
332
|
-
"input",
|
|
333
|
-
{
|
|
334
|
-
required: true,
|
|
335
|
-
type: "email",
|
|
336
|
-
maxLength: 254,
|
|
337
|
-
value: email,
|
|
338
|
-
onInput: (event) => {
|
|
339
|
-
setEmail(event.currentTarget.value);
|
|
340
|
-
edit(selected, name, event.currentTarget.value);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
)
|
|
344
|
-
] }),
|
|
345
|
-
/* @__PURE__ */ jsx3("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
|
|
346
|
-
] }) : /* @__PURE__ */ jsx3("p", { children: "You can add someone from your member page after paying." }),
|
|
347
|
-
dirty ? /* @__PURE__ */ jsx3("button", { type: "submit", disabled: saving, children: saving ? "Saving\u2026" : amount === 0 ? "Save member details" : "Update total" }) : null
|
|
477
|
+
/* @__PURE__ */ jsxs5("fieldset", { disabled: props.locked || saving, children: [
|
|
478
|
+
/* @__PURE__ */ jsx6(
|
|
479
|
+
AdditionalMemberFields,
|
|
480
|
+
{
|
|
481
|
+
value: { selected, name, email },
|
|
482
|
+
offer: { ...props.quote.seatOffer, currency: props.quote.currency, interval: props.quote.interval },
|
|
483
|
+
onChange: (value) => {
|
|
484
|
+
setSelected(value.selected);
|
|
485
|
+
setName(value.name);
|
|
486
|
+
setEmail(value.email);
|
|
487
|
+
edit(value.selected, value.name, value.email);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
),
|
|
491
|
+
selected ? /* @__PURE__ */ jsx6("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." }) : /* @__PURE__ */ jsx6("p", { children: "You can add someone from your member page after paying." }),
|
|
492
|
+
dirty ? /* @__PURE__ */ jsx6(JoinSubmitButton, { disabled: saving || !ready || !valid, children: saving ? "Saving\u2026" : "Save details" }) : null
|
|
348
493
|
] }),
|
|
349
|
-
error ? /* @__PURE__ */
|
|
494
|
+
error ? /* @__PURE__ */ jsx6("p", { role: "alert", children: error }) : null
|
|
350
495
|
] }) });
|
|
351
496
|
}
|
|
352
497
|
|
|
353
498
|
// src/ui/checkout-seat-review.tsx
|
|
354
|
-
import { jsx as
|
|
499
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
355
500
|
function CheckoutSeatReview({ quote, label, locked, onEdit }) {
|
|
356
501
|
if (!quote.namedSeat) return null;
|
|
357
|
-
return /* @__PURE__ */
|
|
358
|
-
/* @__PURE__ */
|
|
359
|
-
/* @__PURE__ */
|
|
502
|
+
return /* @__PURE__ */ jsxs6("section", { className: "checkout-seat-review", "aria-label": label, children: [
|
|
503
|
+
/* @__PURE__ */ jsx7("h3", { children: label }),
|
|
504
|
+
/* @__PURE__ */ jsxs6("p", { children: [
|
|
360
505
|
quote.namedSeat.recipientName,
|
|
361
|
-
/* @__PURE__ */
|
|
506
|
+
/* @__PURE__ */ jsx7("br", {}),
|
|
362
507
|
quote.namedSeat.recipientEmail
|
|
363
508
|
] }),
|
|
364
|
-
!locked ? /* @__PURE__ */
|
|
509
|
+
!locked ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: onEdit, children: "Edit details" }) : null
|
|
365
510
|
] });
|
|
366
511
|
}
|
|
367
512
|
|
|
368
513
|
// src/ui/membership-payment-step.tsx
|
|
369
|
-
import { Fragment as
|
|
514
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
370
515
|
function MembershipPaymentStep(props) {
|
|
516
|
+
const renderEditor = props.renderNamedSeatEditor ?? (props.additionalMember ? (context) => /* @__PURE__ */ jsx8(AdditionalMemberEditor, { ...props.additionalMember, ...context }) : void 0);
|
|
371
517
|
const inherited = useChapterCopy();
|
|
372
518
|
const copy = props.copy ?? inherited.join.payment;
|
|
373
|
-
const [quote, setQuote] =
|
|
374
|
-
const [locked, setLocked] =
|
|
375
|
-
const [prefillConsumed, setPrefillConsumed] =
|
|
376
|
-
const [error, setError] =
|
|
377
|
-
const [revision, setRevision] =
|
|
519
|
+
const [quote, setQuote] = useState6(null);
|
|
520
|
+
const [locked, setLocked] = useState6(false), [editing, setEditing] = useState6(Boolean(props.initialNamedSeat));
|
|
521
|
+
const [prefillConsumed, setPrefillConsumed] = useState6(false);
|
|
522
|
+
const [error, setError] = useState6(false);
|
|
523
|
+
const [revision, setRevision] = useState6(0);
|
|
378
524
|
useEffect(() => {
|
|
379
|
-
props.onNamedSeatEditingChange?.(Boolean(
|
|
380
|
-
}, [editing, locked, Boolean(quote), Boolean(
|
|
525
|
+
props.onNamedSeatEditingChange?.(Boolean(renderEditor && editing && !locked && quote));
|
|
526
|
+
}, [editing, locked, Boolean(quote), Boolean(renderEditor)]);
|
|
381
527
|
useEffect(() => {
|
|
382
528
|
let live = true;
|
|
383
529
|
setQuote(null);
|
|
@@ -388,7 +534,7 @@ function MembershipPaymentStep(props) {
|
|
|
388
534
|
value.checkoutStarted = response.headers.get("x-chapter-checkout-started") === "true";
|
|
389
535
|
if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest) || !/^[a-z]{3}$/.test(value.currency) || !Number.isSafeInteger(value.lineItems?.dueTodayCents) || value.lineItems.dueTodayCents <= 0 || typeof value.refundPolicyText !== "string") throw new Error("invalid quote");
|
|
390
536
|
if (!live) return;
|
|
391
|
-
if (
|
|
537
|
+
if (renderEditor && props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer) {
|
|
392
538
|
const saved = await fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, {
|
|
393
539
|
method: "POST",
|
|
394
540
|
cache: "no-store",
|
|
@@ -427,10 +573,10 @@ function MembershipPaymentStep(props) {
|
|
|
427
573
|
setQuote(null);
|
|
428
574
|
setRevision((value) => value + 1);
|
|
429
575
|
};
|
|
430
|
-
if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */
|
|
431
|
-
props.merchantDisclosureText ? /* @__PURE__ */
|
|
432
|
-
/* @__PURE__ */
|
|
433
|
-
error ? /* @__PURE__ */
|
|
576
|
+
if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */ jsxs7("div", { className: "join-pay", role: "status", children: [
|
|
577
|
+
props.merchantDisclosureText ? /* @__PURE__ */ jsx8("p", { className: "compliance-merchant", children: props.merchantDisclosureText }) : null,
|
|
578
|
+
/* @__PURE__ */ jsx8("p", { children: error ? copy.setupFailed : copy.preparing }),
|
|
579
|
+
error ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: refresh, children: "Reload payment terms" }) : null
|
|
434
580
|
] });
|
|
435
581
|
const startCheckout = async () => {
|
|
436
582
|
setLocked(true);
|
|
@@ -470,9 +616,9 @@ function MembershipPaymentStep(props) {
|
|
|
470
616
|
setPrefillConsumed(true);
|
|
471
617
|
};
|
|
472
618
|
const pickLater = !quote.namedSeat && quote.seatOffer?.amountCents === 0;
|
|
473
|
-
if (
|
|
474
|
-
error ? /* @__PURE__ */
|
|
475
|
-
|
|
619
|
+
if (renderEditor && editing && !locked && quote.seatOffer) return /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
620
|
+
error ? /* @__PURE__ */ jsx8("p", { role: "alert", children: "Enter a different recipient's full name and valid email to continue." }) : null,
|
|
621
|
+
renderEditor({
|
|
476
622
|
selection: quote.namedSeat ?? (!prefillConsumed ? props.initialNamedSeat : void 0) ?? null,
|
|
477
623
|
offer: { ...quote.seatOffer, currency: quote.currency, interval: quote.interval },
|
|
478
624
|
save: changeSeat,
|
|
@@ -483,8 +629,8 @@ function MembershipPaymentStep(props) {
|
|
|
483
629
|
}
|
|
484
630
|
})
|
|
485
631
|
] });
|
|
486
|
-
return /* @__PURE__ */
|
|
487
|
-
|
|
632
|
+
return /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
633
|
+
renderEditor ? /* @__PURE__ */ jsx8(
|
|
488
634
|
CheckoutSeatReview,
|
|
489
635
|
{
|
|
490
636
|
quote,
|
|
@@ -492,7 +638,7 @@ function MembershipPaymentStep(props) {
|
|
|
492
638
|
locked,
|
|
493
639
|
onEdit: () => setEditing(true)
|
|
494
640
|
}
|
|
495
|
-
) : quote.seatOffer ? /* @__PURE__ */
|
|
641
|
+
) : quote.seatOffer ? /* @__PURE__ */ jsx8(
|
|
496
642
|
CheckoutSeatChoice,
|
|
497
643
|
{
|
|
498
644
|
quote,
|
|
@@ -503,52 +649,52 @@ function MembershipPaymentStep(props) {
|
|
|
503
649
|
},
|
|
504
650
|
quote.digest
|
|
505
651
|
) : null,
|
|
506
|
-
/* @__PURE__ */
|
|
507
|
-
/* @__PURE__ */
|
|
508
|
-
quote.founding ? /* @__PURE__ */
|
|
652
|
+
/* @__PURE__ */ jsxs7("section", { className: "payment-quote", "aria-label": "Membership price", children: [
|
|
653
|
+
/* @__PURE__ */ jsx8("h3", { children: quote.tierName }),
|
|
654
|
+
quote.founding ? /* @__PURE__ */ jsx8("p", { className: "payment-founding", role: "note", "aria-label": "Founding member", children: copy.foundingMember }) : null,
|
|
509
655
|
props.renderPriceLines ? props.renderPriceLines({
|
|
510
656
|
...quote.lineItems,
|
|
511
657
|
...quote.founding ? { founding: quote.founding } : {},
|
|
512
658
|
...pickLater ? { namedSeatPickLater: true } : {},
|
|
513
659
|
...quote.presentation ? { presentation: quote.presentation } : {}
|
|
514
|
-
}) : /* @__PURE__ */
|
|
515
|
-
quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */
|
|
516
|
-
/* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */
|
|
660
|
+
}) : /* @__PURE__ */ jsxs7("dl", { children: [
|
|
661
|
+
quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
662
|
+
/* @__PURE__ */ jsx8("dt", { children: copy.standardRate }),
|
|
663
|
+
/* @__PURE__ */ jsxs7("dd", { children: [
|
|
518
664
|
amount(quote.lineItems.standardCents),
|
|
519
665
|
" per ",
|
|
520
666
|
quote.interval
|
|
521
667
|
] }),
|
|
522
|
-
/* @__PURE__ */
|
|
523
|
-
/* @__PURE__ */
|
|
668
|
+
/* @__PURE__ */ jsx8("dt", { children: copy.yourRate }),
|
|
669
|
+
/* @__PURE__ */ jsxs7("dd", { children: [
|
|
524
670
|
amount(quote.lineItems.dueTodayCents - (quote.lineItems.namedSeatCents ?? 0)),
|
|
525
671
|
" per ",
|
|
526
672
|
quote.interval
|
|
527
673
|
] })
|
|
528
|
-
] }) : /* @__PURE__ */
|
|
529
|
-
/* @__PURE__ */
|
|
530
|
-
/* @__PURE__ */
|
|
674
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
675
|
+
/* @__PURE__ */ jsx8("dt", { children: "Membership price" }),
|
|
676
|
+
/* @__PURE__ */ jsxs7("dd", { children: [
|
|
531
677
|
amount(quote.lineItems.standardCents),
|
|
532
678
|
" per ",
|
|
533
679
|
quote.interval
|
|
534
680
|
] }),
|
|
535
|
-
quote.lineItems.discountCents > 0 ? /* @__PURE__ */
|
|
536
|
-
/* @__PURE__ */
|
|
537
|
-
/* @__PURE__ */
|
|
681
|
+
quote.lineItems.discountCents > 0 ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
682
|
+
/* @__PURE__ */ jsx8("dt", { children: quote.founding ? copy.foundingDiscount : "Discount" }),
|
|
683
|
+
/* @__PURE__ */ jsx8("dd", { children: amount(quote.lineItems.discountCents) })
|
|
538
684
|
] }) : null
|
|
539
685
|
] }),
|
|
540
|
-
quote.namedSeat ? /* @__PURE__ */
|
|
541
|
-
/* @__PURE__ */
|
|
542
|
-
/* @__PURE__ */
|
|
686
|
+
quote.namedSeat ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
687
|
+
/* @__PURE__ */ jsx8("dt", { children: "Additional member" }),
|
|
688
|
+
/* @__PURE__ */ jsx8("dd", { children: quote.lineItems.namedSeatCents === 0 ? "Included" : amount(quote.lineItems.namedSeatCents) })
|
|
543
689
|
] }) : null,
|
|
544
|
-
pickLater ? /* @__PURE__ */
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
690
|
+
pickLater ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
691
|
+
/* @__PURE__ */ jsx8("dt", { children: "Additional member" }),
|
|
692
|
+
/* @__PURE__ */ jsx8("dd", { children: "Pick later" })
|
|
547
693
|
] }) : null,
|
|
548
|
-
/* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
694
|
+
/* @__PURE__ */ jsx8("dt", { children: "Due today" }),
|
|
695
|
+
/* @__PURE__ */ jsx8("dd", { children: amount(quote.lineItems.dueTodayCents) })
|
|
550
696
|
] }),
|
|
551
|
-
quote.namedSeat && !
|
|
697
|
+
quote.namedSeat && !renderEditor ? /* @__PURE__ */ jsxs7("p", { children: [
|
|
552
698
|
"For ",
|
|
553
699
|
quote.namedSeat.recipientName,
|
|
554
700
|
" \xB7 ",
|
|
@@ -556,8 +702,8 @@ function MembershipPaymentStep(props) {
|
|
|
556
702
|
".",
|
|
557
703
|
props.renderPriceLines ? ` Additional member: ${quote.lineItems.namedSeatCents === 0 ? "included" : amount(quote.lineItems.namedSeatCents)} in the total above.` : ""
|
|
558
704
|
] }) : null,
|
|
559
|
-
quote.commercial ? /* @__PURE__ */
|
|
560
|
-
quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */
|
|
705
|
+
quote.commercial ? /* @__PURE__ */ jsxs7("div", { role: "note", "aria-label": "Renewal terms", children: [
|
|
706
|
+
quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs7("p", { children: [
|
|
561
707
|
"First renewal: ",
|
|
562
708
|
new Intl.DateTimeFormat("en-US", {
|
|
563
709
|
dateStyle: "long",
|
|
@@ -565,23 +711,23 @@ function MembershipPaymentStep(props) {
|
|
|
565
711
|
}).format(quote.commercial.initialTermEndsAt),
|
|
566
712
|
"."
|
|
567
713
|
] }) : null,
|
|
568
|
-
/* @__PURE__ */
|
|
714
|
+
/* @__PURE__ */ jsxs7("p", { children: [
|
|
569
715
|
"Renews automatically at ",
|
|
570
716
|
amount(quote.commercial.renewalCents),
|
|
571
717
|
" per ",
|
|
572
718
|
quote.interval,
|
|
573
719
|
" unless canceled before renewal."
|
|
574
720
|
] }),
|
|
575
|
-
quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */
|
|
576
|
-
quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */
|
|
721
|
+
quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */ jsx8("p", { children: "The discount applies to your first paid term only." }) : null,
|
|
722
|
+
quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */ jsx8("p", { children: "The discounted rate continues while this membership stays active." }) : null
|
|
577
723
|
] }) : null,
|
|
578
|
-
quote.trustCopy ? /* @__PURE__ */
|
|
724
|
+
quote.trustCopy ? /* @__PURE__ */ jsx8("p", { className: "pay-trust", children: quote.trustCopy }) : null
|
|
579
725
|
] }),
|
|
580
|
-
quote.namedSeat &&
|
|
581
|
-
/* @__PURE__ */
|
|
582
|
-
/* @__PURE__ */
|
|
726
|
+
quote.namedSeat && renderEditor ? /* @__PURE__ */ jsxs7("details", { className: "checkout-seat-terms", children: [
|
|
727
|
+
/* @__PURE__ */ jsx8("summary", { children: "Additional-member terms" }),
|
|
728
|
+
/* @__PURE__ */ jsx8("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
|
|
583
729
|
] }) : null,
|
|
584
|
-
!editing ? /* @__PURE__ */
|
|
730
|
+
!editing ? /* @__PURE__ */ jsx8(
|
|
585
731
|
PaymentStep,
|
|
586
732
|
{
|
|
587
733
|
...props,
|
|
@@ -592,12 +738,12 @@ function MembershipPaymentStep(props) {
|
|
|
592
738
|
startCheckout
|
|
593
739
|
},
|
|
594
740
|
quote.digest
|
|
595
|
-
) : /* @__PURE__ */
|
|
741
|
+
) : /* @__PURE__ */ jsx8("p", { role: "status", children: "Save your member selection to continue to payment." })
|
|
596
742
|
] });
|
|
597
743
|
}
|
|
598
744
|
|
|
599
745
|
// src/ui/journey-frame.tsx
|
|
600
|
-
import { jsx as
|
|
746
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
601
747
|
var styles = `
|
|
602
748
|
.chapter-journey{color:var(--ui-text,#202827);font-family:var(--ui-font-sans,inherit);line-height:1.65;max-width:46rem;margin-inline:auto;min-width:0}
|
|
603
749
|
.chapter-journey *{box-sizing:border-box}
|
|
@@ -619,6 +765,14 @@ var styles = `
|
|
|
619
765
|
.chapter-journey :is(.slot-time,.slot-day):hover{background:var(--ui-surface-2,#f3f5f2);color:var(--ui-text,#202827);border-color:var(--ui-accent,#285c50)}
|
|
620
766
|
.chapter-journey :is(.slot-time,.slot-day)[aria-pressed=true]{background:var(--ui-accent,#285c50);color:var(--ui-on-accent,#fff)}
|
|
621
767
|
.chapter-journey button:disabled{opacity:.55;cursor:default}
|
|
768
|
+
.chapter-journey .chapter-form-primary{background:var(--ui-accent,#285c50);color:var(--ui-on-accent,#fff);width:100%;margin-top:1rem}
|
|
769
|
+
.chapter-journey .chapter-form-primary:hover:not(:disabled){filter:brightness(.92)}
|
|
770
|
+
.chapter-journey .chapter-form-primary:disabled{background:var(--ui-surface-2,#e3e8df);color:var(--ui-text-muted,#687361);opacity:1;cursor:not-allowed;transform:none;filter:none}
|
|
771
|
+
.chapter-journey .additional-member-details{padding:1rem;margin-top:1rem;background:var(--ui-surface-2,#f3f5f2);border:1px solid var(--ui-border,#dfe3df);border-radius:8px}
|
|
772
|
+
.chapter-journey .additional-member-details label:not(:first-child){margin-top:.6rem}
|
|
773
|
+
.chapter-journey .additional-member-actions .chapter-form-primary{width:auto;flex:1;margin-top:0}
|
|
774
|
+
.chapter-journey .additional-member-actions .journey-secondary{min-width:7rem}
|
|
775
|
+
@media(max-width:520px){.chapter-journey .additional-member-actions{flex-direction:column}}
|
|
622
776
|
.chapter-journey :where(.compliance-box,.journey-note){padding:1.2rem;background:var(--ui-surface-2,#f3f5f2);border-radius:10px;margin-block:1.2rem}
|
|
623
777
|
.chapter-journey :where(.compliance-box p:last-child,.journey-note p:last-child,.card p:last-child){margin-bottom:0}
|
|
624
778
|
.chapter-journey .journey-invitation{padding:1.1rem 1.3rem;border-left:3px solid var(--ui-accent,#285c50);background:var(--ui-surface-2,#f3f5f2);border-radius:0 10px 10px 0;margin-block:1rem}
|
|
@@ -634,21 +788,21 @@ var styles = `
|
|
|
634
788
|
@media(max-width:520px){.chapter-journey .journey-actions>*{width:100%}.chapter-journey .journey-summary{grid-template-columns:1fr}.chapter-journey .journey-summary dd{text-align:left}.chapter-journey :where(.card,.join-form,.payment-quote,.join-book){padding:1.25rem}}
|
|
635
789
|
`;
|
|
636
790
|
function JourneyFrame({ children }) {
|
|
637
|
-
return /* @__PURE__ */
|
|
638
|
-
/* @__PURE__ */
|
|
791
|
+
return /* @__PURE__ */ jsxs8("div", { className: "chapter-journey", children: [
|
|
792
|
+
/* @__PURE__ */ jsx9("style", { children: styles }),
|
|
639
793
|
children
|
|
640
794
|
] });
|
|
641
795
|
}
|
|
642
796
|
|
|
643
797
|
// src/ui/member-restart.tsx
|
|
644
|
-
import { jsx as
|
|
798
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
645
799
|
function MemberRestart(props) {
|
|
646
|
-
const [id, setId] =
|
|
647
|
-
const [busy, setBusy] =
|
|
648
|
-
const [error, setError] =
|
|
649
|
-
const [paid, setPaid] =
|
|
650
|
-
const [checking, setChecking] =
|
|
651
|
-
const [revision, setRevision] =
|
|
800
|
+
const [id, setId] = useState7(props.applicationId);
|
|
801
|
+
const [busy, setBusy] = useState7(false);
|
|
802
|
+
const [error, setError] = useState7("");
|
|
803
|
+
const [paid, setPaid] = useState7(false);
|
|
804
|
+
const [checking, setChecking] = useState7(false);
|
|
805
|
+
const [revision, setRevision] = useState7(0);
|
|
652
806
|
useEffect2(() => {
|
|
653
807
|
if (!paid) return;
|
|
654
808
|
let live = true, timer, attempt = 0;
|
|
@@ -686,40 +840,40 @@ function MemberRestart(props) {
|
|
|
686
840
|
setBusy(false);
|
|
687
841
|
}
|
|
688
842
|
};
|
|
689
|
-
return /* @__PURE__ */
|
|
690
|
-
/* @__PURE__ */
|
|
691
|
-
/* @__PURE__ */
|
|
692
|
-
/* @__PURE__ */
|
|
693
|
-
/* @__PURE__ */
|
|
694
|
-
/* @__PURE__ */
|
|
695
|
-
/* @__PURE__ */
|
|
696
|
-
/* @__PURE__ */
|
|
697
|
-
/* @__PURE__ */
|
|
843
|
+
return /* @__PURE__ */ jsx10(JourneyFrame, { children: /* @__PURE__ */ jsxs9("section", { className: "card", "aria-label": "Restart membership", children: [
|
|
844
|
+
/* @__PURE__ */ jsx10("p", { className: "card-label", children: "Welcome back" }),
|
|
845
|
+
/* @__PURE__ */ jsx10("h2", { children: "Restart your membership" }),
|
|
846
|
+
/* @__PURE__ */ jsx10("p", { children: "Your account is ready, and your previous approval still counts. No new application or interview is needed." }),
|
|
847
|
+
/* @__PURE__ */ jsxs9("dl", { className: "journey-summary", children: [
|
|
848
|
+
/* @__PURE__ */ jsx10("dt", { children: "Name" }),
|
|
849
|
+
/* @__PURE__ */ jsx10("dd", { children: [props.application.firstName, props.application.lastName].filter(Boolean).join(" ") }),
|
|
850
|
+
/* @__PURE__ */ jsx10("dt", { children: "Email" }),
|
|
851
|
+
/* @__PURE__ */ jsx10("dd", { children: props.application.email })
|
|
698
852
|
] }),
|
|
699
|
-
paid ? /* @__PURE__ */
|
|
700
|
-
/* @__PURE__ */
|
|
701
|
-
/* @__PURE__ */
|
|
702
|
-
!checking ? /* @__PURE__ */
|
|
703
|
-
] }) : id ? /* @__PURE__ */
|
|
704
|
-
error ? /* @__PURE__ */
|
|
853
|
+
paid ? /* @__PURE__ */ jsxs9("div", { role: "status", children: [
|
|
854
|
+
/* @__PURE__ */ jsx10("h3", { children: "Confirming your membership" }),
|
|
855
|
+
/* @__PURE__ */ jsx10("p", { children: "We\u2019re waiting for payment confirmation. Your membership will open here as soon as it arrives." }),
|
|
856
|
+
!checking ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Check membership" }) : null
|
|
857
|
+
] }) : id ? /* @__PURE__ */ jsx10(MembershipPaymentStep, { applicationId: id, refundPolicyText: "", onPaid: () => setPaid(true) }) : /* @__PURE__ */ jsx10("button", { type: "button", disabled: busy, onClick: () => void start(), children: busy ? "Preparing your membership\u2026" : "Review membership and payment" }),
|
|
858
|
+
error ? /* @__PURE__ */ jsx10("p", { role: "alert", children: error }) : null
|
|
705
859
|
] }) });
|
|
706
860
|
}
|
|
707
861
|
|
|
708
862
|
// src/ui/members.tsx
|
|
709
|
-
import { useEffect as useEffect6, useState as
|
|
863
|
+
import { useEffect as useEffect6, useState as useState12 } from "preact/hooks";
|
|
710
864
|
|
|
711
865
|
// src/ui/reschedule.tsx
|
|
712
|
-
import { useState as
|
|
713
|
-
import { jsx as
|
|
866
|
+
import { useState as useState8 } from "preact/hooks";
|
|
867
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
714
868
|
function Rescheduler(props) {
|
|
715
869
|
const inheritedCopy = useChapterCopy();
|
|
716
870
|
const copy = props.copy ?? inheritedCopy.members.reschedule;
|
|
717
871
|
const { api, applicationId, timezone, onRescheduled, label = copy.changeTime } = props;
|
|
718
|
-
const [open, setOpen] =
|
|
719
|
-
const [slots, setSlots] =
|
|
720
|
-
const [tz, setTz] =
|
|
721
|
-
const [busy, setBusy] =
|
|
722
|
-
const [msg, setMsg] =
|
|
872
|
+
const [open, setOpen] = useState8(false);
|
|
873
|
+
const [slots, setSlots] = useState8(null);
|
|
874
|
+
const [tz, setTz] = useState8(timezone);
|
|
875
|
+
const [busy, setBusy] = useState8(false);
|
|
876
|
+
const [msg, setMsg] = useState8(null);
|
|
723
877
|
const start = async () => {
|
|
724
878
|
setOpen(true);
|
|
725
879
|
setSlots(null);
|
|
@@ -752,7 +906,7 @@ function Rescheduler(props) {
|
|
|
752
906
|
}
|
|
753
907
|
};
|
|
754
908
|
if (!open) {
|
|
755
|
-
return /* @__PURE__ */
|
|
909
|
+
return /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: /* @__PURE__ */ jsx11(
|
|
756
910
|
"a",
|
|
757
911
|
{
|
|
758
912
|
href: "#",
|
|
@@ -764,8 +918,8 @@ function Rescheduler(props) {
|
|
|
764
918
|
}
|
|
765
919
|
) });
|
|
766
920
|
}
|
|
767
|
-
return /* @__PURE__ */
|
|
768
|
-
slots === null ? /* @__PURE__ */
|
|
921
|
+
return /* @__PURE__ */ jsxs10("div", { className: "msched", children: [
|
|
922
|
+
slots === null ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: copy.loading }) : slots.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: msg ?? copy.noTimes }) : /* @__PURE__ */ jsx11(
|
|
769
923
|
SlotPicker,
|
|
770
924
|
{
|
|
771
925
|
slots,
|
|
@@ -774,9 +928,9 @@ function Rescheduler(props) {
|
|
|
774
928
|
onPick: (s) => void pick(s)
|
|
775
929
|
}
|
|
776
930
|
),
|
|
777
|
-
busy ? /* @__PURE__ */
|
|
778
|
-
msg && slots && slots.length > 0 ? /* @__PURE__ */
|
|
779
|
-
/* @__PURE__ */
|
|
931
|
+
busy ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: copy.rescheduling }) : null,
|
|
932
|
+
msg && slots && slots.length > 0 ? /* @__PURE__ */ jsx11("p", { className: "meeting-note error", children: msg }) : null,
|
|
933
|
+
/* @__PURE__ */ jsx11("p", { className: "meeting-note", children: /* @__PURE__ */ jsx11(
|
|
780
934
|
"a",
|
|
781
935
|
{
|
|
782
936
|
href: "#",
|
|
@@ -791,32 +945,32 @@ function Rescheduler(props) {
|
|
|
791
945
|
}
|
|
792
946
|
|
|
793
947
|
// src/ui/member-gifts.tsx
|
|
794
|
-
import { useEffect as useEffect3, useRef as
|
|
948
|
+
import { useEffect as useEffect3, useRef as useRef5, useState as useState9 } from "preact/hooks";
|
|
795
949
|
|
|
796
950
|
// src/ui/gift-offer-cards.tsx
|
|
797
|
-
import { jsx as
|
|
951
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
798
952
|
var price = (cents, currency) => currency === "usd" ? fmtMoney(cents) : new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(cents / 100);
|
|
799
953
|
function GiftOfferCards(props) {
|
|
800
954
|
const mode = props.mode ?? "preview";
|
|
801
|
-
return /* @__PURE__ */
|
|
802
|
-
/* @__PURE__ */
|
|
803
|
-
/* @__PURE__ */
|
|
804
|
-
/* @__PURE__ */
|
|
955
|
+
return /* @__PURE__ */ jsx12("section", { className: "chapter-gift-offers", "aria-label": props.ariaLabel ?? "Gift options", children: props.offers.map((offer) => /* @__PURE__ */ jsxs11("article", { className: "card chapter-gift-offer", "data-offer-id": offer.id, children: [
|
|
956
|
+
/* @__PURE__ */ jsx12("div", { className: "card-label", children: offer.title }),
|
|
957
|
+
/* @__PURE__ */ jsx12("p", { children: offer.description }),
|
|
958
|
+
/* @__PURE__ */ jsxs11("p", { className: "meeting-date", children: [
|
|
805
959
|
price(offer.priceCents, offer.currency),
|
|
806
960
|
offer.billingMode === "subscription" ? " recurring" : ""
|
|
807
961
|
] }),
|
|
808
|
-
mode === "select" ? /* @__PURE__ */
|
|
962
|
+
mode === "select" ? /* @__PURE__ */ jsx12("button", { type: "button", className: "btn secondary", "aria-pressed": props.selectedOfferId === offer.id, onClick: () => props.onSelect?.(offer.id), children: offer.ctaLabel }) : /* @__PURE__ */ jsx12("span", { className: "btn secondary", "aria-disabled": "true", children: offer.ctaLabel })
|
|
809
963
|
] }, offer.id)) });
|
|
810
964
|
}
|
|
811
965
|
|
|
812
966
|
// src/ui/member-gifts.tsx
|
|
813
|
-
import { jsx as
|
|
967
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
814
968
|
function GiftPurchases(props) {
|
|
815
|
-
const [data, setData] =
|
|
816
|
-
const [selected, setSelected] =
|
|
817
|
-
const [code, setCode] =
|
|
818
|
-
const [message, setMessage] =
|
|
819
|
-
const purchaseId =
|
|
969
|
+
const [data, setData] = useState9(null);
|
|
970
|
+
const [selected, setSelected] = useState9(null);
|
|
971
|
+
const [code, setCode] = useState9("");
|
|
972
|
+
const [message, setMessage] = useState9("");
|
|
973
|
+
const purchaseId = useRef5(crypto.randomUUID());
|
|
820
974
|
const load = async () => setData(await props.api("/api/gifts"));
|
|
821
975
|
useEffect3(() => {
|
|
822
976
|
void load().catch(() => setData({ offers: [], claims: [] }));
|
|
@@ -833,16 +987,16 @@ function GiftPurchases(props) {
|
|
|
833
987
|
if (!data) return null;
|
|
834
988
|
if (data.offers.length === 0 && data.claims.length === 0) return null;
|
|
835
989
|
const offer = data.offers.find((item) => item.id === selected);
|
|
836
|
-
return /* @__PURE__ */
|
|
837
|
-
data.offers.length ? /* @__PURE__ */
|
|
838
|
-
/* @__PURE__ */
|
|
839
|
-
/* @__PURE__ */
|
|
840
|
-
/* @__PURE__ */
|
|
990
|
+
return /* @__PURE__ */ jsxs12("section", { className: "member-gifts", children: [
|
|
991
|
+
data.offers.length ? /* @__PURE__ */ jsxs12("div", { className: "card", children: [
|
|
992
|
+
/* @__PURE__ */ jsx13("div", { className: "card-label", children: props.copy.title }),
|
|
993
|
+
/* @__PURE__ */ jsx13("p", { children: props.copy.body }),
|
|
994
|
+
/* @__PURE__ */ jsx13(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
|
|
841
995
|
setSelected(id);
|
|
842
996
|
setCode("");
|
|
843
997
|
purchaseId.current = crypto.randomUUID();
|
|
844
998
|
} }),
|
|
845
|
-
offer ? /* @__PURE__ */
|
|
999
|
+
offer ? /* @__PURE__ */ jsx13(
|
|
846
1000
|
PaymentStep,
|
|
847
1001
|
{
|
|
848
1002
|
applicationId: purchaseId.current,
|
|
@@ -862,27 +1016,27 @@ function GiftPurchases(props) {
|
|
|
862
1016
|
}
|
|
863
1017
|
}
|
|
864
1018
|
) : null,
|
|
865
|
-
code ? /* @__PURE__ */
|
|
866
|
-
/* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
1019
|
+
code ? /* @__PURE__ */ jsxs12("div", { className: "gift-code-once", children: [
|
|
1020
|
+
/* @__PURE__ */ jsx13("output", { children: code }),
|
|
1021
|
+
/* @__PURE__ */ jsx13("p", { children: props.copy.saveCode })
|
|
868
1022
|
] }) : null
|
|
869
1023
|
] }) : null,
|
|
870
|
-
/* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
data.claims.length ? data.claims.map((claim) => /* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
claim.status === "pending" ? /* @__PURE__ */
|
|
876
|
-
] }, claim.id)) : /* @__PURE__ */
|
|
877
|
-
message ? /* @__PURE__ */
|
|
1024
|
+
/* @__PURE__ */ jsxs12("div", { className: "card", children: [
|
|
1025
|
+
/* @__PURE__ */ jsx13("div", { className: "card-label", children: props.copy.purchases }),
|
|
1026
|
+
data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs12("div", { className: "member-row", children: [
|
|
1027
|
+
/* @__PURE__ */ jsx13("span", { children: claim.offerId }),
|
|
1028
|
+
/* @__PURE__ */ jsx13("span", { children: props.copy[claim.status] }),
|
|
1029
|
+
claim.status === "pending" ? /* @__PURE__ */ jsx13("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
|
|
1030
|
+
] }, claim.id)) : /* @__PURE__ */ jsx13("p", { children: props.copy.noPurchases }),
|
|
1031
|
+
message ? /* @__PURE__ */ jsx13("p", { role: "status", children: message }) : null
|
|
878
1032
|
] })
|
|
879
1033
|
] });
|
|
880
1034
|
}
|
|
881
1035
|
var MemberGifts = GiftPurchases;
|
|
882
1036
|
|
|
883
1037
|
// src/ui/member-named-seat.tsx
|
|
884
|
-
import { useEffect as useEffect4, useState as
|
|
885
|
-
import { Fragment as
|
|
1038
|
+
import { useEffect as useEffect4, useState as useState10 } from "preact/hooks";
|
|
1039
|
+
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs13 } from "preact/jsx-runtime";
|
|
886
1040
|
var NAMED_SEAT_RECIPIENT_WORDS = {
|
|
887
1041
|
payment_pending: "payment in progress",
|
|
888
1042
|
invited: "invited, waiting for them to accept",
|
|
@@ -895,7 +1049,7 @@ var NAMED_SEAT_RECIPIENT_WORDS = {
|
|
|
895
1049
|
var day = (at) => new Date(at).toLocaleDateString("en-US", { timeZone: "UTC" });
|
|
896
1050
|
function NamedSeatRecipientLine({ seat }) {
|
|
897
1051
|
const words = NAMED_SEAT_RECIPIENT_WORDS[seat.recipientState] ?? seat.status.replaceAll("_", " ");
|
|
898
|
-
return /* @__PURE__ */
|
|
1052
|
+
return /* @__PURE__ */ jsxs13("p", { className: "member-named-seat-recipient", children: [
|
|
899
1053
|
seat.recipientName,
|
|
900
1054
|
" \xB7 ",
|
|
901
1055
|
seat.recipientEmail,
|
|
@@ -905,9 +1059,9 @@ function NamedSeatRecipientLine({ seat }) {
|
|
|
905
1059
|
] });
|
|
906
1060
|
}
|
|
907
1061
|
function NamedSeatPurchase({ api }) {
|
|
908
|
-
const [data, setData] =
|
|
909
|
-
const [name, setName] =
|
|
910
|
-
const [terms, setTerms] =
|
|
1062
|
+
const [data, setData] = useState10(null), [error, setError] = useState10("");
|
|
1063
|
+
const [name, setName] = useState10(""), [email, setEmail] = useState10(""), [reviewing, setReviewing] = useState10(false);
|
|
1064
|
+
const [terms, setTerms] = useState10(false), [pending, setPending] = useState10(false), [granting, setGranting] = useState10(false);
|
|
911
1065
|
const load = async () => {
|
|
912
1066
|
try {
|
|
913
1067
|
const value = await api("/api/named-seat");
|
|
@@ -944,13 +1098,13 @@ function NamedSeatPurchase({ api }) {
|
|
|
944
1098
|
}
|
|
945
1099
|
};
|
|
946
1100
|
const money = data ? new Intl.NumberFormat("en-US", { style: "currency", currency: data.currency }).format(data.amountCents / 100) : "";
|
|
947
|
-
return /* @__PURE__ */
|
|
948
|
-
/* @__PURE__ */
|
|
949
|
-
error ? /* @__PURE__ */
|
|
950
|
-
data ? /* @__PURE__ */
|
|
951
|
-
data.seat ? /* @__PURE__ */
|
|
952
|
-
data.eligible ? /* @__PURE__ */
|
|
953
|
-
/* @__PURE__ */
|
|
1101
|
+
return /* @__PURE__ */ jsx14(JourneyFrame, { children: /* @__PURE__ */ jsxs13("section", { className: "card member-named-seat", "aria-label": "Named additional seat", children: [
|
|
1102
|
+
/* @__PURE__ */ jsx14("h2", { children: "Named additional seat" }),
|
|
1103
|
+
error ? /* @__PURE__ */ jsx14("p", { role: "alert", children: error }) : null,
|
|
1104
|
+
data ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1105
|
+
data.seat ? /* @__PURE__ */ jsx14(NamedSeatRecipientLine, { seat: data.seat }) : null,
|
|
1106
|
+
data.eligible ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1107
|
+
/* @__PURE__ */ jsxs13("p", { children: [
|
|
954
1108
|
data.included ? "Included with your membership at no charge." : `${money} paid in full now.`,
|
|
955
1109
|
" This seat ",
|
|
956
1110
|
data.autoRenew ? "renews with your primary membership" : "ends with your primary membership",
|
|
@@ -961,39 +1115,39 @@ function NamedSeatPurchase({ api }) {
|
|
|
961
1115
|
" ",
|
|
962
1116
|
"It belongs to one named person and cannot be reassigned."
|
|
963
1117
|
] }),
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
!reviewing ? /* @__PURE__ */
|
|
1118
|
+
/* @__PURE__ */ jsx14("p", { children: "The recipient must accept and complete their own application and any required interview. The seat stays open for them while your membership is paid; it is not refunded automatically. Contact the chapter if you need a refund." }),
|
|
1119
|
+
!reviewing ? /* @__PURE__ */ jsxs13("form", { onSubmit: (event) => {
|
|
966
1120
|
event.preventDefault();
|
|
967
1121
|
setReviewing(true);
|
|
968
1122
|
setTerms(false);
|
|
969
1123
|
}, children: [
|
|
970
|
-
/* @__PURE__ */
|
|
1124
|
+
/* @__PURE__ */ jsxs13("label", { children: [
|
|
971
1125
|
"Recipient name",
|
|
972
|
-
/* @__PURE__ */
|
|
1126
|
+
/* @__PURE__ */ jsx14("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
|
|
973
1127
|
] }),
|
|
974
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsxs13("label", { children: [
|
|
975
1129
|
"Recipient email",
|
|
976
|
-
/* @__PURE__ */
|
|
1130
|
+
/* @__PURE__ */ jsx14("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
|
|
977
1131
|
] }),
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
] }) : /* @__PURE__ */
|
|
980
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsx14("button", { className: "btn primary", type: "submit", children: "Review named seat" })
|
|
1133
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1134
|
+
/* @__PURE__ */ jsxs13("p", { children: [
|
|
981
1135
|
"For ",
|
|
982
1136
|
name,
|
|
983
1137
|
" \xB7 ",
|
|
984
1138
|
email
|
|
985
1139
|
] }),
|
|
986
|
-
/* @__PURE__ */
|
|
1140
|
+
/* @__PURE__ */ jsx14("button", { className: "btn secondary", type: "button", onClick: () => {
|
|
987
1141
|
setReviewing(false);
|
|
988
1142
|
setTerms(false);
|
|
989
1143
|
void load();
|
|
990
1144
|
}, children: "Back to recipient" }),
|
|
991
|
-
/* @__PURE__ */
|
|
992
|
-
/* @__PURE__ */
|
|
993
|
-
/* @__PURE__ */
|
|
1145
|
+
/* @__PURE__ */ jsxs13("label", { className: "journey-consent", children: [
|
|
1146
|
+
/* @__PURE__ */ jsx14("input", { type: "checkbox", checked: terms, onChange: (event) => setTerms(event.currentTarget.checked) }),
|
|
1147
|
+
/* @__PURE__ */ jsx14("span", { children: data.included ? "I agree to the seat terms and the refund policy; the seat is included with my membership and follows its renewal." : data.autoRenew ? "I agree to the full initial payment and automatic renewal with my membership; I can cancel renewal." : "I agree to the full initial payment and the displayed end date, with no automatic renewal while my membership renewal is canceled." })
|
|
994
1148
|
] }),
|
|
995
|
-
terms && data.included ? /* @__PURE__ */
|
|
996
|
-
terms && !data.included ? /* @__PURE__ */
|
|
1149
|
+
terms && data.included ? /* @__PURE__ */ jsx14("button", { className: "btn primary", type: "button", disabled: granting, onClick: () => void grant(), children: granting ? "Sending the invitation\u2026" : "Send the invitation" }) : null,
|
|
1150
|
+
terms && !data.included ? /* @__PURE__ */ jsx14(
|
|
997
1151
|
PaymentStep,
|
|
998
1152
|
{
|
|
999
1153
|
applicationId: data.membershipId,
|
|
@@ -1008,17 +1162,17 @@ function NamedSeatPurchase({ api }) {
|
|
|
1008
1162
|
}
|
|
1009
1163
|
) : null
|
|
1010
1164
|
] })
|
|
1011
|
-
] }) : !data.seat ? /* @__PURE__ */
|
|
1012
|
-
pending ? /* @__PURE__ */
|
|
1013
|
-
] }) : !error ? /* @__PURE__ */
|
|
1014
|
-
/* @__PURE__ */
|
|
1165
|
+
] }) : !data.seat ? /* @__PURE__ */ jsx14("p", { children: data.purchaseWindowed === false ? "An additional seat can be purchased for as long as your membership stays paid." : `Additional seats can be purchased until ${day(data.purchaseEndsAt)}.` }) : null,
|
|
1166
|
+
pending ? /* @__PURE__ */ jsx14("p", { role: "status", children: "Payment confirmation is being reconciled. The recipient\u2019s access begins only after their own acceptance and approval." }) : null
|
|
1167
|
+
] }) : !error ? /* @__PURE__ */ jsx14("p", { children: "Loading your seat terms\u2026" }) : null,
|
|
1168
|
+
/* @__PURE__ */ jsx14("button", { className: "btn secondary", onClick: () => void load(), children: "Refresh seat status" })
|
|
1015
1169
|
] }) });
|
|
1016
1170
|
}
|
|
1017
1171
|
|
|
1018
1172
|
// src/ui/member-content.tsx
|
|
1019
|
-
import { useEffect as useEffect5, useMemo as useMemo2, useState as
|
|
1173
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState11 } from "preact/hooks";
|
|
1020
1174
|
import { Markdown } from "@odla-ai/ui/components";
|
|
1021
|
-
import { Fragment as
|
|
1175
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
1022
1176
|
var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
|
|
1023
1177
|
function MemberContentArea(props) {
|
|
1024
1178
|
const {
|
|
@@ -1026,12 +1180,12 @@ function MemberContentArea(props) {
|
|
|
1026
1180
|
path = "/api/member-content",
|
|
1027
1181
|
upsellHref,
|
|
1028
1182
|
onUpsell,
|
|
1029
|
-
loadingContent = /* @__PURE__ */
|
|
1030
|
-
emptyContent = /* @__PURE__ */
|
|
1183
|
+
loadingContent = /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
|
|
1184
|
+
emptyContent = /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: "No member pages have been published yet." })
|
|
1031
1185
|
} = props;
|
|
1032
|
-
const [data, setData] =
|
|
1033
|
-
const [error, setError] =
|
|
1034
|
-
const [selectedId, setSelectedId] =
|
|
1186
|
+
const [data, setData] = useState11(props.initialData ?? null);
|
|
1187
|
+
const [error, setError] = useState11(null);
|
|
1188
|
+
const [selectedId, setSelectedId] = useState11(
|
|
1035
1189
|
props.initialPageId ?? props.initialData?.pages[0]?.id ?? ""
|
|
1036
1190
|
);
|
|
1037
1191
|
useEffect5(() => {
|
|
@@ -1056,18 +1210,18 @@ function MemberContentArea(props) {
|
|
|
1056
1210
|
}
|
|
1057
1211
|
return [...result.entries()];
|
|
1058
1212
|
}, [data]);
|
|
1059
|
-
if (error) return /* @__PURE__ */
|
|
1213
|
+
if (error) return /* @__PURE__ */ jsxs14("p", { className: "meeting-note", role: "alert", children: [
|
|
1060
1214
|
"Member pages could not be loaded: ",
|
|
1061
1215
|
error
|
|
1062
1216
|
] });
|
|
1063
|
-
if (!data) return /* @__PURE__ */
|
|
1064
|
-
if (data.pages.length === 0) return /* @__PURE__ */
|
|
1217
|
+
if (!data) return /* @__PURE__ */ jsx15(Fragment4, { children: loadingContent });
|
|
1218
|
+
if (data.pages.length === 0) return /* @__PURE__ */ jsx15(Fragment4, { children: emptyContent });
|
|
1065
1219
|
const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
|
|
1066
1220
|
const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
|
|
1067
|
-
return /* @__PURE__ */
|
|
1068
|
-
/* @__PURE__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1221
|
+
return /* @__PURE__ */ jsxs14("div", { className: "chapter-member-content", "data-member-content": true, children: [
|
|
1222
|
+
/* @__PURE__ */ jsx15("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs14("section", { className: "chapter-member-content-section", children: [
|
|
1223
|
+
/* @__PURE__ */ jsx15("h2", { children: section }),
|
|
1224
|
+
/* @__PURE__ */ jsx15("ul", { children: pages.map((page) => /* @__PURE__ */ jsx15("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx15(
|
|
1071
1225
|
"button",
|
|
1072
1226
|
{
|
|
1073
1227
|
type: "button",
|
|
@@ -1077,23 +1231,23 @@ function MemberContentArea(props) {
|
|
|
1077
1231
|
}
|
|
1078
1232
|
) }, page.id)) })
|
|
1079
1233
|
] }, section)) }),
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1234
|
+
/* @__PURE__ */ jsxs14("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
|
|
1235
|
+
/* @__PURE__ */ jsxs14("header", { children: [
|
|
1236
|
+
/* @__PURE__ */ jsxs14("div", { className: "card-label", children: [
|
|
1083
1237
|
selected.source.type === "parent" ? "Parent" : "Chapter",
|
|
1084
1238
|
" \xB7 ",
|
|
1085
1239
|
selected.access
|
|
1086
1240
|
] }),
|
|
1087
|
-
/* @__PURE__ */
|
|
1088
|
-
selected.summary ? /* @__PURE__ */
|
|
1241
|
+
/* @__PURE__ */ jsx15("h1", { children: selected.title }),
|
|
1242
|
+
selected.summary ? /* @__PURE__ */ jsx15("p", { children: selected.summary }) : null
|
|
1089
1243
|
] }),
|
|
1090
|
-
selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */
|
|
1091
|
-
selected.teaserMarkdown ? /* @__PURE__ */
|
|
1092
|
-
selected.upsell ? /* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1095
|
-
selected.upsell.bodyMarkdown ? /* @__PURE__ */
|
|
1096
|
-
href ? /* @__PURE__ */
|
|
1244
|
+
selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs14("div", { className: "chapter-member-content-locked", children: [
|
|
1245
|
+
selected.teaserMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx15("p", { children: "This page is not included in your current membership." }),
|
|
1246
|
+
selected.upsell ? /* @__PURE__ */ jsxs14("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
|
|
1247
|
+
/* @__PURE__ */ jsx15("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
|
|
1248
|
+
/* @__PURE__ */ jsx15("p", { children: fmtMoney(selected.upsell.priceCents) }),
|
|
1249
|
+
selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
|
|
1250
|
+
href ? /* @__PURE__ */ jsx15("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx15("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
|
|
1097
1251
|
] }) : null
|
|
1098
1252
|
] })
|
|
1099
1253
|
] })
|
|
@@ -1101,12 +1255,12 @@ function MemberContentArea(props) {
|
|
|
1101
1255
|
}
|
|
1102
1256
|
|
|
1103
1257
|
// src/ui/members.tsx
|
|
1104
|
-
import { Fragment as
|
|
1258
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
1105
1259
|
function card(copy, kicker, body) {
|
|
1106
|
-
return /* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1109
|
-
/* @__PURE__ */
|
|
1260
|
+
return /* @__PURE__ */ jsxs15("div", { className: "card", children: [
|
|
1261
|
+
/* @__PURE__ */ jsx16("div", { className: "card-label", children: copy.provisional.cardLabel }),
|
|
1262
|
+
/* @__PURE__ */ jsxs15("div", { className: "meeting-block", children: [
|
|
1263
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-kicker", children: kicker }),
|
|
1110
1264
|
body
|
|
1111
1265
|
] })
|
|
1112
1266
|
] });
|
|
@@ -1117,9 +1271,9 @@ function ProvisionalCard(props) {
|
|
|
1117
1271
|
return card(
|
|
1118
1272
|
copy,
|
|
1119
1273
|
copy.provisional.applicationNeeded,
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1274
|
+
/* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
1275
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
|
|
1276
|
+
/* @__PURE__ */ jsx16("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
|
|
1123
1277
|
] })
|
|
1124
1278
|
);
|
|
1125
1279
|
}
|
|
@@ -1127,19 +1281,19 @@ function ProvisionalCard(props) {
|
|
|
1127
1281
|
return card(
|
|
1128
1282
|
copy,
|
|
1129
1283
|
copy.provisional.refunded,
|
|
1130
|
-
/* @__PURE__ */
|
|
1284
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.refundedBody })
|
|
1131
1285
|
);
|
|
1132
1286
|
}
|
|
1133
|
-
const membership = application.paid ? /* @__PURE__ */
|
|
1287
|
+
const membership = application.paid ? /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
|
|
1134
1288
|
if (application.meetingAt) {
|
|
1135
1289
|
return card(
|
|
1136
1290
|
copy,
|
|
1137
1291
|
copy.provisional.introductionCall,
|
|
1138
|
-
/* @__PURE__ */
|
|
1139
|
-
/* @__PURE__ */
|
|
1140
|
-
/* @__PURE__ */
|
|
1141
|
-
application.meetUrl ? /* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */
|
|
1292
|
+
/* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
1293
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
|
|
1294
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
|
|
1295
|
+
application.meetUrl ? /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: /* @__PURE__ */ jsx16("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
|
|
1296
|
+
/* @__PURE__ */ jsx16(
|
|
1143
1297
|
Rescheduler,
|
|
1144
1298
|
{
|
|
1145
1299
|
api,
|
|
@@ -1156,9 +1310,9 @@ function ProvisionalCard(props) {
|
|
|
1156
1310
|
return card(
|
|
1157
1311
|
copy,
|
|
1158
1312
|
copy.provisional.bookCall,
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1161
|
-
/* @__PURE__ */
|
|
1313
|
+
/* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
1314
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
|
|
1315
|
+
/* @__PURE__ */ jsx16(
|
|
1162
1316
|
Rescheduler,
|
|
1163
1317
|
{
|
|
1164
1318
|
api,
|
|
@@ -1185,8 +1339,8 @@ function MembersArea(props) {
|
|
|
1185
1339
|
renderProvisional
|
|
1186
1340
|
} = props;
|
|
1187
1341
|
const copy = props.copy ?? inheritedCopy.members;
|
|
1188
|
-
const [me, setMe] =
|
|
1189
|
-
const [error, setError] =
|
|
1342
|
+
const [me, setMe] = useState12(null);
|
|
1343
|
+
const [error, setError] = useState12(false);
|
|
1190
1344
|
const reload = async () => {
|
|
1191
1345
|
try {
|
|
1192
1346
|
setMe(await api("/api/me"));
|
|
@@ -1197,22 +1351,22 @@ function MembersArea(props) {
|
|
|
1197
1351
|
useEffect6(() => {
|
|
1198
1352
|
void reload();
|
|
1199
1353
|
}, []);
|
|
1200
|
-
if (error) return /* @__PURE__ */
|
|
1201
|
-
if (!me) return /* @__PURE__ */
|
|
1354
|
+
if (error) return /* @__PURE__ */ jsx16("p", { className: "meeting-note", children: copy.loadFailed });
|
|
1355
|
+
if (!me) return /* @__PURE__ */ jsx16("p", { className: "meeting-note", children: inheritedCopy.common.loading });
|
|
1202
1356
|
const role = me.role || "provisional";
|
|
1203
|
-
return /* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1357
|
+
return /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
1358
|
+
/* @__PURE__ */ jsxs15("div", { className: "card", children: [
|
|
1359
|
+
/* @__PURE__ */ jsxs15("div", { className: "member-row", children: [
|
|
1360
|
+
/* @__PURE__ */ jsx16("span", { className: "member-email", children: me.email }),
|
|
1361
|
+
/* @__PURE__ */ jsx16("span", { className: "role-badge " + role, children: role })
|
|
1208
1362
|
] }),
|
|
1209
|
-
/* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
me.authorized || me.superAdmin ? /* @__PURE__ */
|
|
1363
|
+
/* @__PURE__ */ jsxs15("div", { className: "account-actions", children: [
|
|
1364
|
+
/* @__PURE__ */ jsx16("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
|
|
1365
|
+
me.authorized || me.superAdmin ? /* @__PURE__ */ jsx16("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
|
|
1212
1366
|
] })
|
|
1213
1367
|
] }),
|
|
1214
|
-
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */
|
|
1215
|
-
const defaultContent = /* @__PURE__ */
|
|
1368
|
+
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx16(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
|
|
1369
|
+
const defaultContent = /* @__PURE__ */ jsx16(
|
|
1216
1370
|
ProvisionalCard,
|
|
1217
1371
|
{
|
|
1218
1372
|
api,
|
|
@@ -1229,30 +1383,30 @@ function MembersArea(props) {
|
|
|
1229
1383
|
reload,
|
|
1230
1384
|
defaultContent
|
|
1231
1385
|
}) ?? defaultContent;
|
|
1232
|
-
})() : memberContent ?? (memberPages ? /* @__PURE__ */
|
|
1386
|
+
})() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx16(
|
|
1233
1387
|
MemberContentArea,
|
|
1234
1388
|
{
|
|
1235
1389
|
api,
|
|
1236
1390
|
...memberPages === true ? {} : memberPages
|
|
1237
1391
|
}
|
|
1238
|
-
) : /* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
me.namedSeatsEnabled ? /* @__PURE__ */
|
|
1392
|
+
) : /* @__PURE__ */ jsx16("div", { className: "card", children: /* @__PURE__ */ jsx16("div", { className: "card-label", children: copy.full.welcome }) })),
|
|
1393
|
+
/* @__PURE__ */ jsx16(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
|
|
1394
|
+
me.namedSeatsEnabled ? /* @__PURE__ */ jsx16(NamedSeatPurchase, { api }) : null
|
|
1241
1395
|
] });
|
|
1242
1396
|
}
|
|
1243
1397
|
|
|
1244
1398
|
// src/ui/join.tsx
|
|
1245
|
-
import { useEffect as useEffect11, useRef as
|
|
1399
|
+
import { useEffect as useEffect11, useRef as useRef7, useState as useState20 } from "preact/hooks";
|
|
1246
1400
|
|
|
1247
1401
|
// src/ui/join-booking.tsx
|
|
1248
|
-
import { useEffect as useEffect7, useState as
|
|
1249
|
-
import { jsx as
|
|
1402
|
+
import { useEffect as useEffect7, useState as useState13 } from "preact/hooks";
|
|
1403
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "preact/jsx-runtime";
|
|
1250
1404
|
function JoinBooking(props) {
|
|
1251
1405
|
const { applicationId, copy, onBooked, simulation } = props;
|
|
1252
|
-
const [state, setState] =
|
|
1253
|
-
const [msg, setMsg] =
|
|
1254
|
-
const [busy, setBusy] =
|
|
1255
|
-
const [selected, setSelected] =
|
|
1406
|
+
const [state, setState] = useState13(null);
|
|
1407
|
+
const [msg, setMsg] = useState13(null);
|
|
1408
|
+
const [busy, setBusy] = useState13(false);
|
|
1409
|
+
const [selected, setSelected] = useState13(null);
|
|
1256
1410
|
const load = async () => {
|
|
1257
1411
|
setMsg(null);
|
|
1258
1412
|
try {
|
|
@@ -1309,11 +1463,11 @@ function JoinBooking(props) {
|
|
|
1309
1463
|
setBusy(false);
|
|
1310
1464
|
}
|
|
1311
1465
|
};
|
|
1312
|
-
if (!state) return /* @__PURE__ */
|
|
1313
|
-
return /* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1466
|
+
if (!state) return /* @__PURE__ */ jsx17("p", { className: "slots-status", children: msg ?? copy.loading });
|
|
1467
|
+
return /* @__PURE__ */ jsxs16("div", { className: "join-book", children: [
|
|
1468
|
+
/* @__PURE__ */ jsx17("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
|
|
1469
|
+
/* @__PURE__ */ jsx17("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
|
|
1470
|
+
/* @__PURE__ */ jsx17(
|
|
1317
1471
|
SlotPicker,
|
|
1318
1472
|
{
|
|
1319
1473
|
slots: state.slots,
|
|
@@ -1323,29 +1477,29 @@ function JoinBooking(props) {
|
|
|
1323
1477
|
onDayChange: () => setSelected(null)
|
|
1324
1478
|
}
|
|
1325
1479
|
),
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
msg ? /* @__PURE__ */
|
|
1480
|
+
/* @__PURE__ */ jsxs16("div", { className: "slot-confirm", hidden: !selected, children: [
|
|
1481
|
+
/* @__PURE__ */ jsx17("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
|
|
1482
|
+
msg ? /* @__PURE__ */ jsx17("p", { className: "step2-note", children: msg }) : null
|
|
1329
1483
|
] })
|
|
1330
1484
|
] });
|
|
1331
1485
|
}
|
|
1332
1486
|
|
|
1333
1487
|
// src/ui/join-accepted.tsx
|
|
1334
|
-
import { jsx as
|
|
1488
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
1335
1489
|
function JoinAccepted(props) {
|
|
1336
|
-
return /* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1338
|
-
/* @__PURE__ */
|
|
1339
|
-
/* @__PURE__ */
|
|
1490
|
+
return /* @__PURE__ */ jsxs17("div", { className: "join-done card", children: [
|
|
1491
|
+
/* @__PURE__ */ jsx18("div", { className: "card-label", children: props.copy.accepted.label }),
|
|
1492
|
+
/* @__PURE__ */ jsx18("p", { className: "meeting-note", children: props.copy.accepted.body }),
|
|
1493
|
+
/* @__PURE__ */ jsx18("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
|
|
1340
1494
|
] });
|
|
1341
1495
|
}
|
|
1342
1496
|
|
|
1343
1497
|
// src/ui/gift-claim-card.tsx
|
|
1344
|
-
import { useState as
|
|
1345
|
-
import { Fragment as
|
|
1498
|
+
import { useState as useState14 } from "preact/hooks";
|
|
1499
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs18 } from "preact/jsx-runtime";
|
|
1346
1500
|
function GiftClaimCard(props) {
|
|
1347
|
-
const [code, setCode] =
|
|
1348
|
-
const [error, setError] =
|
|
1501
|
+
const [code, setCode] = useState14(props.initialCode ?? "");
|
|
1502
|
+
const [error, setError] = useState14(false);
|
|
1349
1503
|
const rotate = async () => {
|
|
1350
1504
|
if (!props.claimId) return;
|
|
1351
1505
|
setError(false);
|
|
@@ -1358,24 +1512,27 @@ function GiftClaimCard(props) {
|
|
|
1358
1512
|
if (response.ok && body.code) setCode(body.code);
|
|
1359
1513
|
else setError(true);
|
|
1360
1514
|
};
|
|
1361
|
-
return /* @__PURE__ */
|
|
1362
|
-
/* @__PURE__ */
|
|
1363
|
-
/* @__PURE__ */
|
|
1364
|
-
code ? /* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
/* @__PURE__ */
|
|
1515
|
+
return /* @__PURE__ */ jsxs18("div", { className: "join-done card", children: [
|
|
1516
|
+
/* @__PURE__ */ jsx19("div", { className: "card-label", children: props.copy.label }),
|
|
1517
|
+
/* @__PURE__ */ jsx19("p", { className: "meeting-note", children: props.copy.body }),
|
|
1518
|
+
code ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
|
|
1519
|
+
/* @__PURE__ */ jsx19("output", { className: "gift-code", children: code }),
|
|
1520
|
+
/* @__PURE__ */ jsx19("p", { children: props.copy.save })
|
|
1367
1521
|
] }) : null,
|
|
1368
|
-
!code && props.claimId ? /* @__PURE__ */
|
|
1369
|
-
error ? /* @__PURE__ */
|
|
1522
|
+
!code && props.claimId ? /* @__PURE__ */ jsx19("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
|
|
1523
|
+
error ? /* @__PURE__ */ jsx19("p", { role: "alert", children: props.copy.rotateFailed }) : null
|
|
1370
1524
|
] });
|
|
1371
1525
|
}
|
|
1372
1526
|
|
|
1527
|
+
// src/ui/join-application-form.tsx
|
|
1528
|
+
import { useRef as useRef6 } from "preact/hooks";
|
|
1529
|
+
|
|
1373
1530
|
// src/ui/join-tiers.tsx
|
|
1374
|
-
import { useState as
|
|
1375
|
-
import { Fragment as
|
|
1531
|
+
import { useState as useState15 } from "preact/hooks";
|
|
1532
|
+
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs19 } from "preact/jsx-runtime";
|
|
1376
1533
|
var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
|
|
1377
1534
|
function useTierSelection(tiers, initialTierId) {
|
|
1378
|
-
const [selectedTierId, setSelectedTierId] =
|
|
1535
|
+
const [selectedTierId, setSelectedTierId] = useState15(() => {
|
|
1379
1536
|
const preset = tiers.find((tier) => tier.id === initialTierId);
|
|
1380
1537
|
if (preset) return preset.id;
|
|
1381
1538
|
return tiers.length === 1 ? tiers[0].id : null;
|
|
@@ -1390,10 +1547,10 @@ function useTierSelection(tiers, initialTierId) {
|
|
|
1390
1547
|
};
|
|
1391
1548
|
}
|
|
1392
1549
|
function TierPlaceholder(context) {
|
|
1393
|
-
return /* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
context.tiers.map((tier) => /* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1550
|
+
return /* @__PURE__ */ jsxs19("fieldset", { "data-chapter-placeholder": "tiers", children: [
|
|
1551
|
+
/* @__PURE__ */ jsx20("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
|
|
1552
|
+
context.tiers.map((tier) => /* @__PURE__ */ jsxs19("label", { children: [
|
|
1553
|
+
/* @__PURE__ */ jsx20(
|
|
1397
1554
|
"input",
|
|
1398
1555
|
{
|
|
1399
1556
|
type: "radio",
|
|
@@ -1404,13 +1561,13 @@ function TierPlaceholder(context) {
|
|
|
1404
1561
|
}
|
|
1405
1562
|
),
|
|
1406
1563
|
tier.name,
|
|
1407
|
-
tier.founding ? /* @__PURE__ */
|
|
1564
|
+
tier.founding ? /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
1408
1565
|
" \u2014 ",
|
|
1409
1566
|
joinTierMoney(tier.founding.dueTodayCents),
|
|
1410
1567
|
" founding member rate (list ",
|
|
1411
1568
|
joinTierMoney(tier.priceCents),
|
|
1412
1569
|
")"
|
|
1413
|
-
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */
|
|
1570
|
+
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
1414
1571
|
" \u2014 ",
|
|
1415
1572
|
joinTierMoney(tier.priceCents)
|
|
1416
1573
|
] })
|
|
@@ -1422,19 +1579,28 @@ function tierNeedsPayment(selected, paymentsReady) {
|
|
|
1422
1579
|
}
|
|
1423
1580
|
|
|
1424
1581
|
// src/ui/join-application-form.tsx
|
|
1425
|
-
import { jsx as
|
|
1582
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
1426
1583
|
function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1584
|
+
const form = useRef6(null);
|
|
1585
|
+
const ready = useFormReadiness(form);
|
|
1586
|
+
const disabled = submitting || props.submitDisabled === true || !ready || !validJoinRecipient(props.payment?.initialNamedSeat);
|
|
1587
|
+
return /* @__PURE__ */ jsxs20("form", { ref: form, className: "join-form", onSubmit: (event) => {
|
|
1588
|
+
if (!isFormReady(event.currentTarget)) {
|
|
1589
|
+
event.preventDefault();
|
|
1590
|
+
event.currentTarget.reportValidity();
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1593
|
+
void submit(event);
|
|
1594
|
+
}, children: [
|
|
1595
|
+
!requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs20("fieldset", { children: [
|
|
1596
|
+
/* @__PURE__ */ jsx21("legend", { children: copy.gift.optionsLabel }),
|
|
1597
|
+
/* @__PURE__ */ jsx21("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
|
|
1598
|
+
/* @__PURE__ */ jsx21(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
|
|
1433
1599
|
] }) : null,
|
|
1434
1600
|
!requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
|
|
1435
1601
|
typeof props.children === "function" ? props.children({ invitation }) : props.children,
|
|
1436
|
-
error ? /* @__PURE__ */
|
|
1437
|
-
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */
|
|
1602
|
+
error ? /* @__PURE__ */ jsx21("p", { className: "join-error", role: "alert", children: error }) : null,
|
|
1603
|
+
props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx21(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
|
|
1438
1604
|
] });
|
|
1439
1605
|
}
|
|
1440
1606
|
|
|
@@ -1459,8 +1625,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
|
|
|
1459
1625
|
|
|
1460
1626
|
// src/ui/gift-code-redeemer.tsx
|
|
1461
1627
|
import { InlineActionField } from "@odla-ai/ui/components";
|
|
1462
|
-
import { useState as
|
|
1463
|
-
import { Fragment as
|
|
1628
|
+
import { useState as useState16 } from "preact/hooks";
|
|
1629
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs21 } from "preact/jsx-runtime";
|
|
1464
1630
|
var GIFT_CODE_REDEEMER_CSS = `
|
|
1465
1631
|
.gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
|
|
1466
1632
|
.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}
|
|
@@ -1475,10 +1641,10 @@ var GIFT_CODE_REDEEMER_CSS = `
|
|
|
1475
1641
|
@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%}}
|
|
1476
1642
|
`;
|
|
1477
1643
|
function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
1478
|
-
const [code, setCode] =
|
|
1479
|
-
const [loading, setLoading] =
|
|
1480
|
-
const [message, setMessage] =
|
|
1481
|
-
const [messageTone, setMessageTone] =
|
|
1644
|
+
const [code, setCode] = useState16("");
|
|
1645
|
+
const [loading, setLoading] = useState16(false);
|
|
1646
|
+
const [message, setMessage] = useState16("");
|
|
1647
|
+
const [messageTone, setMessageTone] = useState16("neutral");
|
|
1482
1648
|
const normalizedCode = code.trim();
|
|
1483
1649
|
const redeem = async () => {
|
|
1484
1650
|
if (!normalizedCode || loading) return;
|
|
@@ -1505,9 +1671,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
|
1505
1671
|
setLoading(false);
|
|
1506
1672
|
}
|
|
1507
1673
|
};
|
|
1508
|
-
return /* @__PURE__ */
|
|
1509
|
-
/* @__PURE__ */
|
|
1510
|
-
/* @__PURE__ */
|
|
1674
|
+
return /* @__PURE__ */ jsxs21(Fragment8, { children: [
|
|
1675
|
+
/* @__PURE__ */ jsx22("style", { children: GIFT_CODE_REDEEMER_CSS }),
|
|
1676
|
+
/* @__PURE__ */ jsx22(
|
|
1511
1677
|
InlineActionField,
|
|
1512
1678
|
{
|
|
1513
1679
|
id,
|
|
@@ -1563,12 +1729,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
|
|
|
1563
1729
|
}
|
|
1564
1730
|
|
|
1565
1731
|
// src/ui/join-gift-claim.tsx
|
|
1566
|
-
import { jsx as
|
|
1732
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
1567
1733
|
function JoinGiftClaim(props) {
|
|
1568
|
-
return /* @__PURE__ */
|
|
1569
|
-
/* @__PURE__ */
|
|
1570
|
-
/* @__PURE__ */
|
|
1571
|
-
/* @__PURE__ */
|
|
1734
|
+
return /* @__PURE__ */ jsxs22("section", { className: "join-gift-claim card", children: [
|
|
1735
|
+
/* @__PURE__ */ jsx23("div", { className: "card-label", children: props.copy.claimTitle }),
|
|
1736
|
+
/* @__PURE__ */ jsx23("p", { children: props.copy.claimBody }),
|
|
1737
|
+
/* @__PURE__ */ jsx23(
|
|
1572
1738
|
GiftCodeRedeemer,
|
|
1573
1739
|
{
|
|
1574
1740
|
api: props.api,
|
|
@@ -1592,21 +1758,21 @@ function JoinGiftClaim(props) {
|
|
|
1592
1758
|
}
|
|
1593
1759
|
|
|
1594
1760
|
// src/ui/join-named-seat.tsx
|
|
1595
|
-
import { useState as
|
|
1596
|
-
import { jsx as
|
|
1761
|
+
import { useState as useState17 } from "preact/hooks";
|
|
1762
|
+
import { jsx as jsx24, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
1597
1763
|
function JoinNamedSeat(props) {
|
|
1598
1764
|
const seatId = props.seatId ?? "";
|
|
1599
1765
|
const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
|
|
1600
|
-
const [accepted, setAccepted] =
|
|
1601
|
-
return /* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1603
|
-
/* @__PURE__ */
|
|
1604
|
-
/* @__PURE__ */
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1766
|
+
const [accepted, setAccepted] = useState17(false), [busy, setBusy] = useState17(false), [error, setError] = useState17("");
|
|
1767
|
+
return /* @__PURE__ */ jsxs23("section", { className: "join-named-seat card", children: [
|
|
1768
|
+
/* @__PURE__ */ jsx24("h2", { children: copy.title }),
|
|
1769
|
+
/* @__PURE__ */ jsx24("p", { children: copy.body }),
|
|
1770
|
+
/* @__PURE__ */ jsxs23("label", { className: "journey-consent", children: [
|
|
1771
|
+
/* @__PURE__ */ jsx24("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
|
|
1772
|
+
/* @__PURE__ */ jsx24("span", { children: copy.consent })
|
|
1607
1773
|
] }),
|
|
1608
|
-
error ? /* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1774
|
+
error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: error }) : null,
|
|
1775
|
+
/* @__PURE__ */ jsx24("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
|
|
1610
1776
|
setBusy(true);
|
|
1611
1777
|
setError("");
|
|
1612
1778
|
try {
|
|
@@ -1626,12 +1792,12 @@ function JoinNamedSeat(props) {
|
|
|
1626
1792
|
}
|
|
1627
1793
|
|
|
1628
1794
|
// src/ui/join-invitation.tsx
|
|
1629
|
-
import { useEffect as useEffect8, useState as
|
|
1630
|
-
import { jsx as
|
|
1795
|
+
import { useEffect as useEffect8, useState as useState18 } from "preact/hooks";
|
|
1796
|
+
import { jsx as jsx25, jsxs as jsxs24 } from "preact/jsx-runtime";
|
|
1631
1797
|
function useJoinInvitation(seatId, api, fallback) {
|
|
1632
|
-
const [invitation, setInvitation] =
|
|
1633
|
-
const [error, setError] =
|
|
1634
|
-
const [revision, setRevision] =
|
|
1798
|
+
const [invitation, setInvitation] = useState18(null);
|
|
1799
|
+
const [error, setError] = useState18("");
|
|
1800
|
+
const [revision, setRevision] = useState18(0);
|
|
1635
1801
|
useEffect8(() => {
|
|
1636
1802
|
let live = true;
|
|
1637
1803
|
setInvitation(null);
|
|
@@ -1654,9 +1820,9 @@ function useJoinInvitation(seatId, api, fallback) {
|
|
|
1654
1820
|
return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
|
|
1655
1821
|
}
|
|
1656
1822
|
function JoinInvitationNotice(props) {
|
|
1657
|
-
return /* @__PURE__ */
|
|
1658
|
-
/* @__PURE__ */
|
|
1659
|
-
/* @__PURE__ */
|
|
1823
|
+
return /* @__PURE__ */ jsxs24("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
|
|
1824
|
+
/* @__PURE__ */ jsx25("p", { children: /* @__PURE__ */ jsx25("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
|
|
1825
|
+
/* @__PURE__ */ jsx25("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
|
|
1660
1826
|
] });
|
|
1661
1827
|
}
|
|
1662
1828
|
|
|
@@ -1696,14 +1862,14 @@ function useJoinPending(state, loadResume, setState) {
|
|
|
1696
1862
|
}
|
|
1697
1863
|
|
|
1698
1864
|
// src/ui/payment-receipt.tsx
|
|
1699
|
-
import { useEffect as useEffect10, useState as
|
|
1700
|
-
import { Fragment as
|
|
1865
|
+
import { useEffect as useEffect10, useState as useState19 } from "preact/hooks";
|
|
1866
|
+
import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs25 } from "preact/jsx-runtime";
|
|
1701
1867
|
function PaymentReceiptCard({ applicationId }) {
|
|
1702
|
-
const [receipt, setReceipt] =
|
|
1703
|
-
const [error, setError] =
|
|
1704
|
-
const [revision, setRevision] =
|
|
1705
|
-
const [emailState, setEmailState] =
|
|
1706
|
-
const [previewEmail, setPreviewEmail] =
|
|
1868
|
+
const [receipt, setReceipt] = useState19(null);
|
|
1869
|
+
const [error, setError] = useState19("");
|
|
1870
|
+
const [revision, setRevision] = useState19(0);
|
|
1871
|
+
const [emailState, setEmailState] = useState19("idle");
|
|
1872
|
+
const [previewEmail, setPreviewEmail] = useState19(false);
|
|
1707
1873
|
const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
|
|
1708
1874
|
useEffect10(() => {
|
|
1709
1875
|
let live = true, timer;
|
|
@@ -1731,9 +1897,9 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
1731
1897
|
if (timer) clearTimeout(timer);
|
|
1732
1898
|
};
|
|
1733
1899
|
}, [endpoint, revision]);
|
|
1734
|
-
if (!receipt) return error ? /* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1900
|
+
if (!receipt) return error ? /* @__PURE__ */ jsxs25("section", { "aria-label": "Payment receipt", children: [
|
|
1901
|
+
/* @__PURE__ */ jsx26("p", { role: "status", children: error }),
|
|
1902
|
+
/* @__PURE__ */ jsx26("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
|
|
1737
1903
|
] }) : null;
|
|
1738
1904
|
const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
|
|
1739
1905
|
const email = async () => {
|
|
@@ -1750,45 +1916,38 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
1750
1916
|
setError("We could not confirm email delivery. You can print or save your receipt.");
|
|
1751
1917
|
}
|
|
1752
1918
|
};
|
|
1753
|
-
return /* @__PURE__ */
|
|
1754
|
-
/* @__PURE__ */
|
|
1755
|
-
/* @__PURE__ */
|
|
1756
|
-
/* @__PURE__ */
|
|
1757
|
-
/* @__PURE__ */
|
|
1758
|
-
/* @__PURE__ */
|
|
1759
|
-
receipt.namedSeat ? /* @__PURE__ */
|
|
1760
|
-
/* @__PURE__ */
|
|
1919
|
+
return /* @__PURE__ */ jsxs25("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
|
|
1920
|
+
/* @__PURE__ */ jsx26("h2", { children: "Payment received" }),
|
|
1921
|
+
/* @__PURE__ */ jsx26("p", { children: receipt.tierName }),
|
|
1922
|
+
/* @__PURE__ */ jsxs25("dl", { className: "journey-summary", children: [
|
|
1923
|
+
/* @__PURE__ */ jsx26("dt", { children: "Membership" }),
|
|
1924
|
+
/* @__PURE__ */ jsx26("dd", { children: money(receipt.membershipCents) }),
|
|
1925
|
+
receipt.namedSeat ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
|
|
1926
|
+
/* @__PURE__ */ jsxs25("dt", { children: [
|
|
1761
1927
|
"Additional member \u2014 ",
|
|
1762
1928
|
receipt.namedSeat.recipientName
|
|
1763
1929
|
] }),
|
|
1764
|
-
/* @__PURE__ */
|
|
1930
|
+
/* @__PURE__ */ jsxs25("dd", { children: [
|
|
1765
1931
|
receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
|
|
1766
1932
|
money(receipt.namedSeat.amountCents)
|
|
1767
1933
|
] })
|
|
1768
1934
|
] }) : null,
|
|
1769
|
-
/* @__PURE__ */
|
|
1770
|
-
/* @__PURE__ */
|
|
1935
|
+
/* @__PURE__ */ jsx26("dt", { children: "Total paid" }),
|
|
1936
|
+
/* @__PURE__ */ jsx26("dd", { children: money(receipt.totalCents) })
|
|
1771
1937
|
] }),
|
|
1772
|
-
/* @__PURE__ */
|
|
1773
|
-
/* @__PURE__ */
|
|
1774
|
-
/* @__PURE__ */
|
|
1938
|
+
/* @__PURE__ */ jsxs25("div", { className: "journey-actions", children: [
|
|
1939
|
+
/* @__PURE__ */ jsx26("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
|
|
1940
|
+
/* @__PURE__ */ jsx26("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
|
|
1775
1941
|
] }),
|
|
1776
|
-
emailState === "sent" ? /* @__PURE__ */
|
|
1777
|
-
error ? /* @__PURE__ */
|
|
1942
|
+
emailState === "sent" ? /* @__PURE__ */ jsx26("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
|
|
1943
|
+
error ? /* @__PURE__ */ jsx26("p", { role: "alert", children: error }) : null
|
|
1778
1944
|
] });
|
|
1779
1945
|
}
|
|
1780
1946
|
|
|
1781
|
-
// src/ui/join-recipient.ts
|
|
1782
|
-
function validJoinRecipient(recipient) {
|
|
1783
|
-
if (!recipient) return true;
|
|
1784
|
-
const name = recipient.recipientName.trim(), email = recipient.recipientEmail.trim();
|
|
1785
|
-
return name.length >= 2 && name.length <= 160 && !/[\u0000-\u001f\u007f]/.test(name) && email.length <= 254 && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
1947
|
// src/ui/join.tsx
|
|
1789
|
-
import { Fragment as
|
|
1948
|
+
import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
1790
1949
|
function JoinIsland(props) {
|
|
1791
|
-
return /* @__PURE__ */
|
|
1950
|
+
return /* @__PURE__ */ jsx27(JourneyFrame, { children: /* @__PURE__ */ jsx27(JoinFlow, { ...props }) });
|
|
1792
1951
|
}
|
|
1793
1952
|
function JoinFlow(props) {
|
|
1794
1953
|
const inheritedCopy = useChapterCopy();
|
|
@@ -1809,14 +1968,14 @@ function JoinFlow(props) {
|
|
|
1809
1968
|
const invitation = invitationState.invitation;
|
|
1810
1969
|
const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
|
|
1811
1970
|
const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
|
|
1812
|
-
const [state, setState] =
|
|
1813
|
-
const [error, setError] =
|
|
1814
|
-
const [submitting, setSubmitting] =
|
|
1815
|
-
const [editingNamedSeat, setEditingNamedSeat] =
|
|
1816
|
-
const [giftOfferId, setGiftOfferId] =
|
|
1971
|
+
const [state, setState] = useState20(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
|
|
1972
|
+
const [error, setError] = useState20(null);
|
|
1973
|
+
const [submitting, setSubmitting] = useState20(false);
|
|
1974
|
+
const [editingNamedSeat, setEditingNamedSeat] = useState20(false);
|
|
1975
|
+
const [giftOfferId, setGiftOfferId] = useState20(props.initialGiftOfferId ?? null);
|
|
1817
1976
|
const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
|
|
1818
1977
|
const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
|
|
1819
|
-
const submissionId =
|
|
1978
|
+
const submissionId = useRef7(null);
|
|
1820
1979
|
useEffect11(() => {
|
|
1821
1980
|
if (props.simulation) return;
|
|
1822
1981
|
const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
|
|
@@ -1890,13 +2049,13 @@ function JoinFlow(props) {
|
|
|
1890
2049
|
setSubmitting(false);
|
|
1891
2050
|
}
|
|
1892
2051
|
};
|
|
1893
|
-
if (requestedSeat && !invitation) return /* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
1895
|
-
/* @__PURE__ */
|
|
1896
|
-
invitationState.error ? /* @__PURE__ */
|
|
2052
|
+
if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs26("section", { className: "card", "aria-live": "polite", children: [
|
|
2053
|
+
/* @__PURE__ */ jsx27("h2", { children: seatCopy.title }),
|
|
2054
|
+
/* @__PURE__ */ jsx27("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
|
|
2055
|
+
invitationState.error ? /* @__PURE__ */ jsx27("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
|
|
1897
2056
|
] });
|
|
1898
|
-
const header = /* @__PURE__ */
|
|
1899
|
-
invitation ? /* @__PURE__ */
|
|
2057
|
+
const header = /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
2058
|
+
invitation ? /* @__PURE__ */ jsx27(
|
|
1900
2059
|
JoinInvitationNotice,
|
|
1901
2060
|
{
|
|
1902
2061
|
invitation,
|
|
@@ -1910,48 +2069,48 @@ function JoinFlow(props) {
|
|
|
1910
2069
|
...invitation ? { invitation } : {},
|
|
1911
2070
|
..."applicationId" in state ? { applicationId: state.applicationId } : {}
|
|
1912
2071
|
}),
|
|
1913
|
-
!props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */
|
|
2072
|
+
!props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx27(PaymentReceiptCard, { applicationId: state.applicationId }) : null
|
|
1914
2073
|
] });
|
|
1915
2074
|
if (state.step === "closed") {
|
|
1916
|
-
return /* @__PURE__ */
|
|
2075
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1917
2076
|
header,
|
|
1918
|
-
/* @__PURE__ */
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsxs26("section", { className: "card", "aria-label": "Application closed", children: [
|
|
2078
|
+
/* @__PURE__ */ jsx27("h2", { children: "This application is closed" }),
|
|
2079
|
+
/* @__PURE__ */ jsx27("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
|
|
2080
|
+
/* @__PURE__ */ jsx27("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
1922
2081
|
] })
|
|
1923
2082
|
] });
|
|
1924
2083
|
}
|
|
1925
2084
|
if (state.step === "done") {
|
|
1926
|
-
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
1928
|
-
/* @__PURE__ */
|
|
1929
|
-
/* @__PURE__ */
|
|
1930
|
-
/* @__PURE__ */
|
|
2085
|
+
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs26("div", { className: "join-done card", children: [
|
|
2086
|
+
/* @__PURE__ */ jsx27("div", { className: "card-label", children: copy.done.label }),
|
|
2087
|
+
/* @__PURE__ */ jsx27("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
|
|
2088
|
+
/* @__PURE__ */ jsx27("p", { className: "meeting-note", children: copy.done.calendarInvite }),
|
|
2089
|
+
/* @__PURE__ */ jsx27("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
|
|
1931
2090
|
] });
|
|
1932
|
-
return /* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1933
2092
|
header,
|
|
1934
2093
|
body
|
|
1935
2094
|
] });
|
|
1936
2095
|
}
|
|
1937
2096
|
if (state.step === "accepted") {
|
|
1938
|
-
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
1939
|
-
return /* @__PURE__ */
|
|
2097
|
+
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx27(JoinAccepted, { copy, membersHref });
|
|
2098
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1940
2099
|
header,
|
|
1941
2100
|
body
|
|
1942
2101
|
] });
|
|
1943
2102
|
}
|
|
1944
2103
|
if (state.step === "gift") {
|
|
1945
|
-
const body = renderGift?.(state) ?? /* @__PURE__ */
|
|
1946
|
-
return /* @__PURE__ */
|
|
2104
|
+
const body = renderGift?.(state) ?? /* @__PURE__ */ jsx27(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
|
|
2105
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1947
2106
|
header,
|
|
1948
2107
|
body
|
|
1949
2108
|
] });
|
|
1950
2109
|
}
|
|
1951
2110
|
if (state.step === "booking") {
|
|
1952
|
-
return /* @__PURE__ */
|
|
2111
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1953
2112
|
header,
|
|
1954
|
-
/* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsx27(
|
|
1955
2114
|
JoinBooking,
|
|
1956
2115
|
{
|
|
1957
2116
|
applicationId: state.applicationId,
|
|
@@ -1966,9 +2125,9 @@ function JoinFlow(props) {
|
|
|
1966
2125
|
}
|
|
1967
2126
|
if (state.step === "payment") {
|
|
1968
2127
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
|
|
1969
|
-
return /* @__PURE__ */
|
|
2128
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1970
2129
|
header,
|
|
1971
|
-
/* @__PURE__ */
|
|
2130
|
+
/* @__PURE__ */ jsx27(
|
|
1972
2131
|
JoinNamedSeat,
|
|
1973
2132
|
{
|
|
1974
2133
|
api: props.namedSeatClaimApi,
|
|
@@ -1981,9 +2140,9 @@ function JoinFlow(props) {
|
|
|
1981
2140
|
] });
|
|
1982
2141
|
}
|
|
1983
2142
|
const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
|
|
1984
|
-
return /* @__PURE__ */
|
|
2143
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1985
2144
|
header,
|
|
1986
|
-
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */
|
|
2145
|
+
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx27(
|
|
1987
2146
|
JoinGiftClaim,
|
|
1988
2147
|
{
|
|
1989
2148
|
api: props.giftClaimApi,
|
|
@@ -1994,7 +2153,7 @@ function JoinFlow(props) {
|
|
|
1994
2153
|
onError: () => setError(copy.form.unexpectedFailure)
|
|
1995
2154
|
}
|
|
1996
2155
|
) : null,
|
|
1997
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsx27(
|
|
1998
2157
|
Payment,
|
|
1999
2158
|
{
|
|
2000
2159
|
applicationId: state.applicationId,
|
|
@@ -2022,9 +2181,9 @@ function JoinFlow(props) {
|
|
|
2022
2181
|
}
|
|
2023
2182
|
if (state.step === "paymentPending") {
|
|
2024
2183
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
|
|
2025
|
-
return /* @__PURE__ */
|
|
2184
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
2026
2185
|
header,
|
|
2027
|
-
/* @__PURE__ */
|
|
2186
|
+
/* @__PURE__ */ jsx27(
|
|
2028
2187
|
JoinNamedSeat,
|
|
2029
2188
|
{
|
|
2030
2189
|
api: props.namedSeatClaimApi,
|
|
@@ -2036,14 +2195,14 @@ function JoinFlow(props) {
|
|
|
2036
2195
|
)
|
|
2037
2196
|
] });
|
|
2038
2197
|
}
|
|
2039
|
-
return /* @__PURE__ */
|
|
2198
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
2040
2199
|
header,
|
|
2041
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ jsx27("p", { className: "pay-status", role: "status", children: copy.payment.pending })
|
|
2042
2201
|
] });
|
|
2043
2202
|
}
|
|
2044
|
-
return /* @__PURE__ */
|
|
2203
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
2045
2204
|
header,
|
|
2046
|
-
/* @__PURE__ */
|
|
2205
|
+
/* @__PURE__ */ jsx27(
|
|
2047
2206
|
JoinApplicationForm,
|
|
2048
2207
|
{
|
|
2049
2208
|
props,
|
|
@@ -2233,7 +2392,7 @@ function membershipPageDocument(input, options = {}) {
|
|
|
2233
2392
|
}
|
|
2234
2393
|
|
|
2235
2394
|
// src/ui/membership-cards.tsx
|
|
2236
|
-
import { jsx as
|
|
2395
|
+
import { jsx as jsx28, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
2237
2396
|
var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
|
|
2238
2397
|
"--ui-membership-grid-gap": "1.4rem",
|
|
2239
2398
|
"--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
|
|
@@ -2302,67 +2461,67 @@ function membershipApplicationHref(applicationPath, tierId) {
|
|
|
2302
2461
|
}
|
|
2303
2462
|
function TierAction(props) {
|
|
2304
2463
|
if (props.mode === "select") {
|
|
2305
|
-
return /* @__PURE__ */
|
|
2464
|
+
return /* @__PURE__ */ jsxs27("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
|
|
2306
2465
|
props.label,
|
|
2307
|
-
/* @__PURE__ */
|
|
2466
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2308
2467
|
] });
|
|
2309
2468
|
}
|
|
2310
2469
|
if (props.mode === "preview") {
|
|
2311
|
-
return /* @__PURE__ */
|
|
2470
|
+
return /* @__PURE__ */ jsxs27("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
|
|
2312
2471
|
props.label,
|
|
2313
|
-
/* @__PURE__ */
|
|
2472
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2314
2473
|
] });
|
|
2315
2474
|
}
|
|
2316
|
-
return /* @__PURE__ */
|
|
2475
|
+
return /* @__PURE__ */ jsxs27("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
|
|
2317
2476
|
props.label,
|
|
2318
|
-
/* @__PURE__ */
|
|
2477
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2319
2478
|
] });
|
|
2320
2479
|
}
|
|
2321
2480
|
function TierCard(props) {
|
|
2322
2481
|
const { tier, presentation } = props;
|
|
2323
2482
|
const summary = presentation.summaryMarkdown ?? tier.blurb;
|
|
2324
2483
|
const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
|
|
2325
|
-
return /* @__PURE__ */
|
|
2326
|
-
presentation.badge ? /* @__PURE__ */
|
|
2327
|
-
/* @__PURE__ */
|
|
2328
|
-
/* @__PURE__ */
|
|
2329
|
-
presentation.capacity ? /* @__PURE__ */
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
/* @__PURE__ */
|
|
2484
|
+
return /* @__PURE__ */ jsxs27("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
|
|
2485
|
+
presentation.badge ? /* @__PURE__ */ jsx28("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
|
|
2486
|
+
/* @__PURE__ */ jsx28("h3", { className: "chapter-membership-name", children: tier.name }),
|
|
2487
|
+
/* @__PURE__ */ jsxs27("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
|
|
2488
|
+
presentation.capacity ? /* @__PURE__ */ jsxs27("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
|
|
2489
|
+
/* @__PURE__ */ jsx28("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
|
|
2490
|
+
/* @__PURE__ */ jsx28("small", { children: presentation.capacity.label ?? "available" })
|
|
2332
2491
|
] }) : null,
|
|
2333
|
-
/* @__PURE__ */
|
|
2334
|
-
presentation.priceEyebrow ? /* @__PURE__ */
|
|
2335
|
-
/* @__PURE__ */
|
|
2336
|
-
tier.founding ? /* @__PURE__ */
|
|
2337
|
-
/* @__PURE__ */
|
|
2338
|
-
!tier.free && presentation.billingLabel ? /* @__PURE__ */
|
|
2492
|
+
/* @__PURE__ */ jsxs27("div", { className: "chapter-membership-price-stack", children: [
|
|
2493
|
+
presentation.priceEyebrow ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
|
|
2494
|
+
/* @__PURE__ */ jsxs27("div", { className: "chapter-membership-price-row", children: [
|
|
2495
|
+
tier.founding ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
|
|
2496
|
+
/* @__PURE__ */ jsx28("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
|
|
2497
|
+
!tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
|
|
2339
2498
|
] })
|
|
2340
2499
|
] })
|
|
2341
2500
|
] }),
|
|
2342
|
-
presentation.priceNoteMarkdown ? /* @__PURE__ */
|
|
2343
|
-
summary ? /* @__PURE__ */
|
|
2344
|
-
presentation.benefits?.length ? /* @__PURE__ */
|
|
2345
|
-
/* @__PURE__ */
|
|
2346
|
-
/* @__PURE__ */
|
|
2501
|
+
presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
|
|
2502
|
+
summary ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
|
|
2503
|
+
presentation.benefits?.length ? /* @__PURE__ */ jsx28("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs27("li", { children: [
|
|
2504
|
+
/* @__PURE__ */ jsx28("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
|
|
2505
|
+
/* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-benefit", source: benefit })
|
|
2347
2506
|
] }, `${tier.id}-benefit-${index}`)) }) : null,
|
|
2348
|
-
presentation.callout ? /* @__PURE__ */
|
|
2349
|
-
presentation.callout.label ? /* @__PURE__ */
|
|
2350
|
-
/* @__PURE__ */
|
|
2507
|
+
presentation.callout ? /* @__PURE__ */ jsxs27("aside", { className: "chapter-membership-callout", children: [
|
|
2508
|
+
presentation.callout.label ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
|
|
2509
|
+
/* @__PURE__ */ jsx28(Markdown2, { source: presentation.callout.bodyMarkdown })
|
|
2351
2510
|
] }) : null,
|
|
2352
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ jsx28(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
|
|
2353
2512
|
] });
|
|
2354
2513
|
}
|
|
2355
2514
|
function MembershipCards(props) {
|
|
2356
2515
|
const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
|
|
2357
2516
|
const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
|
|
2358
2517
|
const mode = props.mode ?? "link";
|
|
2359
|
-
return /* @__PURE__ */
|
|
2360
|
-
/* @__PURE__ */
|
|
2361
|
-
/* @__PURE__ */
|
|
2518
|
+
return /* @__PURE__ */ jsxs27("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
|
|
2519
|
+
/* @__PURE__ */ jsx28("style", { children: MEMBERSHIP_CARDS_CSS }),
|
|
2520
|
+
/* @__PURE__ */ jsx28("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
|
|
2362
2521
|
const tier = byId.get(presentation.tierId);
|
|
2363
|
-
return /* @__PURE__ */
|
|
2522
|
+
return /* @__PURE__ */ jsx28(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
|
|
2364
2523
|
}) }),
|
|
2365
|
-
document2.footnoteMarkdown ? /* @__PURE__ */
|
|
2524
|
+
document2.footnoteMarkdown ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
|
|
2366
2525
|
] });
|
|
2367
2526
|
}
|
|
2368
2527
|
|
|
@@ -2376,6 +2535,11 @@ export {
|
|
|
2376
2535
|
fmtDate,
|
|
2377
2536
|
groupSlotsByDay,
|
|
2378
2537
|
SlotPicker,
|
|
2538
|
+
ADDITIONAL_MEMBER_COPY,
|
|
2539
|
+
additionalMemberSelection,
|
|
2540
|
+
AdditionalMemberFields,
|
|
2541
|
+
JoinSubmitButton,
|
|
2542
|
+
AdditionalMemberEditor,
|
|
2379
2543
|
PaymentStep,
|
|
2380
2544
|
JourneyFrame,
|
|
2381
2545
|
MemberRestart,
|
|
@@ -2398,4 +2562,4 @@ export {
|
|
|
2398
2562
|
membershipApplicationHref,
|
|
2399
2563
|
MembershipCards
|
|
2400
2564
|
};
|
|
2401
|
-
//# sourceMappingURL=chunk-
|
|
2565
|
+
//# sourceMappingURL=chunk-E7CB5K2D.js.map
|