@odla-ai/chapter 0.56.0 → 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-IQZWCG42.js → chunk-E7CB5K2D.js} +745 -490
- 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 +115 -1
- package/dist/ui/member/index.js +11 -1
- package/package.json +1 -1
- package/dist/chunk-IQZWCG42.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,79 +470,93 @@ 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
|
|
|
498
|
+
// src/ui/checkout-seat-review.tsx
|
|
499
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
500
|
+
function CheckoutSeatReview({ quote, label, locked, onEdit }) {
|
|
501
|
+
if (!quote.namedSeat) return null;
|
|
502
|
+
return /* @__PURE__ */ jsxs6("section", { className: "checkout-seat-review", "aria-label": label, children: [
|
|
503
|
+
/* @__PURE__ */ jsx7("h3", { children: label }),
|
|
504
|
+
/* @__PURE__ */ jsxs6("p", { children: [
|
|
505
|
+
quote.namedSeat.recipientName,
|
|
506
|
+
/* @__PURE__ */ jsx7("br", {}),
|
|
507
|
+
quote.namedSeat.recipientEmail
|
|
508
|
+
] }),
|
|
509
|
+
!locked ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: onEdit, children: "Edit details" }) : null
|
|
510
|
+
] });
|
|
511
|
+
}
|
|
512
|
+
|
|
353
513
|
// src/ui/membership-payment-step.tsx
|
|
354
|
-
import { Fragment as
|
|
514
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
355
515
|
function MembershipPaymentStep(props) {
|
|
516
|
+
const renderEditor = props.renderNamedSeatEditor ?? (props.additionalMember ? (context) => /* @__PURE__ */ jsx8(AdditionalMemberEditor, { ...props.additionalMember, ...context }) : void 0);
|
|
356
517
|
const inherited = useChapterCopy();
|
|
357
518
|
const copy = props.copy ?? inherited.join.payment;
|
|
358
|
-
const [quote, setQuote] =
|
|
359
|
-
const [locked, setLocked] =
|
|
360
|
-
const [prefillConsumed, setPrefillConsumed] =
|
|
361
|
-
const [error, setError] =
|
|
362
|
-
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);
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
props.onNamedSeatEditingChange?.(Boolean(renderEditor && editing && !locked && quote));
|
|
526
|
+
}, [editing, locked, Boolean(quote), Boolean(renderEditor)]);
|
|
363
527
|
useEffect(() => {
|
|
364
528
|
let live = true;
|
|
365
529
|
setQuote(null);
|
|
366
530
|
setError(false);
|
|
367
531
|
void fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, { method: "POST", cache: "no-store" }).then(async (response) => {
|
|
368
532
|
if (!response.ok) throw new Error("quote unavailable");
|
|
369
|
-
|
|
533
|
+
let value = await response.json();
|
|
370
534
|
value.checkoutStarted = response.headers.get("x-chapter-checkout-started") === "true";
|
|
371
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");
|
|
536
|
+
if (!live) return;
|
|
537
|
+
if (renderEditor && props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer) {
|
|
538
|
+
const saved = await fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, {
|
|
539
|
+
method: "POST",
|
|
540
|
+
cache: "no-store",
|
|
541
|
+
headers: { "content-type": "application/json" },
|
|
542
|
+
body: JSON.stringify({ namedSeat: props.initialNamedSeat })
|
|
543
|
+
});
|
|
544
|
+
if (!saved.ok) {
|
|
545
|
+
if (saved.status === 409) {
|
|
546
|
+
if (live) setRevision((current) => current + 1);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
if (live) {
|
|
550
|
+
setQuote(value);
|
|
551
|
+
setEditing(true);
|
|
552
|
+
setError(true);
|
|
553
|
+
}
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
value = await saved.json();
|
|
557
|
+
if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest) || !value.namedSeat) throw new Error("invalid quote");
|
|
558
|
+
if (live) setPrefillConsumed(true);
|
|
559
|
+
}
|
|
372
560
|
if (live) {
|
|
373
561
|
setQuote(value);
|
|
374
562
|
setLocked(Boolean(value.checkoutStarted));
|
|
@@ -385,10 +573,10 @@ function MembershipPaymentStep(props) {
|
|
|
385
573
|
setQuote(null);
|
|
386
574
|
setRevision((value) => value + 1);
|
|
387
575
|
};
|
|
388
|
-
if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */
|
|
389
|
-
props.merchantDisclosureText ? /* @__PURE__ */
|
|
390
|
-
/* @__PURE__ */
|
|
391
|
-
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
|
|
392
580
|
] });
|
|
393
581
|
const startCheckout = async () => {
|
|
394
582
|
setLocked(true);
|
|
@@ -424,10 +612,33 @@ function MembershipPaymentStep(props) {
|
|
|
424
612
|
if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest)) throw new Error(copy.setupFailed);
|
|
425
613
|
setQuote(value);
|
|
426
614
|
setEditing(false);
|
|
615
|
+
setError(false);
|
|
427
616
|
setPrefillConsumed(true);
|
|
428
617
|
};
|
|
429
|
-
|
|
430
|
-
|
|
618
|
+
const pickLater = !quote.namedSeat && quote.seatOffer?.amountCents === 0;
|
|
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({
|
|
622
|
+
selection: quote.namedSeat ?? (!prefillConsumed ? props.initialNamedSeat : void 0) ?? null,
|
|
623
|
+
offer: { ...quote.seatOffer, currency: quote.currency, interval: quote.interval },
|
|
624
|
+
save: changeSeat,
|
|
625
|
+
cancel: () => {
|
|
626
|
+
setEditing(false);
|
|
627
|
+
setError(false);
|
|
628
|
+
setPrefillConsumed(true);
|
|
629
|
+
}
|
|
630
|
+
})
|
|
631
|
+
] });
|
|
632
|
+
return /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
633
|
+
renderEditor ? /* @__PURE__ */ jsx8(
|
|
634
|
+
CheckoutSeatReview,
|
|
635
|
+
{
|
|
636
|
+
quote,
|
|
637
|
+
label: props.namedSeatLabel ?? "Additional member",
|
|
638
|
+
locked,
|
|
639
|
+
onEdit: () => setEditing(true)
|
|
640
|
+
}
|
|
641
|
+
) : quote.seatOffer ? /* @__PURE__ */ jsx8(
|
|
431
642
|
CheckoutSeatChoice,
|
|
432
643
|
{
|
|
433
644
|
quote,
|
|
@@ -438,47 +649,52 @@ function MembershipPaymentStep(props) {
|
|
|
438
649
|
},
|
|
439
650
|
quote.digest
|
|
440
651
|
) : null,
|
|
441
|
-
/* @__PURE__ */
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
-
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,
|
|
444
655
|
props.renderPriceLines ? props.renderPriceLines({
|
|
445
656
|
...quote.lineItems,
|
|
446
657
|
...quote.founding ? { founding: quote.founding } : {},
|
|
658
|
+
...pickLater ? { namedSeatPickLater: true } : {},
|
|
447
659
|
...quote.presentation ? { presentation: quote.presentation } : {}
|
|
448
|
-
}) : /* @__PURE__ */
|
|
449
|
-
quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
-
/* @__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: [
|
|
452
664
|
amount(quote.lineItems.standardCents),
|
|
453
665
|
" per ",
|
|
454
666
|
quote.interval
|
|
455
667
|
] }),
|
|
456
|
-
/* @__PURE__ */
|
|
457
|
-
/* @__PURE__ */
|
|
668
|
+
/* @__PURE__ */ jsx8("dt", { children: copy.yourRate }),
|
|
669
|
+
/* @__PURE__ */ jsxs7("dd", { children: [
|
|
458
670
|
amount(quote.lineItems.dueTodayCents - (quote.lineItems.namedSeatCents ?? 0)),
|
|
459
671
|
" per ",
|
|
460
672
|
quote.interval
|
|
461
673
|
] })
|
|
462
|
-
] }) : /* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
464
|
-
/* @__PURE__ */
|
|
674
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
675
|
+
/* @__PURE__ */ jsx8("dt", { children: "Membership price" }),
|
|
676
|
+
/* @__PURE__ */ jsxs7("dd", { children: [
|
|
465
677
|
amount(quote.lineItems.standardCents),
|
|
466
678
|
" per ",
|
|
467
679
|
quote.interval
|
|
468
680
|
] }),
|
|
469
|
-
quote.lineItems.discountCents > 0 ? /* @__PURE__ */
|
|
470
|
-
/* @__PURE__ */
|
|
471
|
-
/* @__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) })
|
|
472
684
|
] }) : null
|
|
473
685
|
] }),
|
|
474
|
-
quote.namedSeat ? /* @__PURE__ */
|
|
475
|
-
/* @__PURE__ */
|
|
476
|
-
/* @__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) })
|
|
689
|
+
] }) : null,
|
|
690
|
+
pickLater ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
691
|
+
/* @__PURE__ */ jsx8("dt", { children: "Additional member" }),
|
|
692
|
+
/* @__PURE__ */ jsx8("dd", { children: "Pick later" })
|
|
477
693
|
] }) : null,
|
|
478
|
-
/* @__PURE__ */
|
|
479
|
-
/* @__PURE__ */
|
|
694
|
+
/* @__PURE__ */ jsx8("dt", { children: "Due today" }),
|
|
695
|
+
/* @__PURE__ */ jsx8("dd", { children: amount(quote.lineItems.dueTodayCents) })
|
|
480
696
|
] }),
|
|
481
|
-
quote.namedSeat ? /* @__PURE__ */
|
|
697
|
+
quote.namedSeat && !renderEditor ? /* @__PURE__ */ jsxs7("p", { children: [
|
|
482
698
|
"For ",
|
|
483
699
|
quote.namedSeat.recipientName,
|
|
484
700
|
" \xB7 ",
|
|
@@ -486,8 +702,8 @@ function MembershipPaymentStep(props) {
|
|
|
486
702
|
".",
|
|
487
703
|
props.renderPriceLines ? ` Additional member: ${quote.lineItems.namedSeatCents === 0 ? "included" : amount(quote.lineItems.namedSeatCents)} in the total above.` : ""
|
|
488
704
|
] }) : null,
|
|
489
|
-
quote.commercial ? /* @__PURE__ */
|
|
490
|
-
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: [
|
|
491
707
|
"First renewal: ",
|
|
492
708
|
new Intl.DateTimeFormat("en-US", {
|
|
493
709
|
dateStyle: "long",
|
|
@@ -495,19 +711,23 @@ function MembershipPaymentStep(props) {
|
|
|
495
711
|
}).format(quote.commercial.initialTermEndsAt),
|
|
496
712
|
"."
|
|
497
713
|
] }) : null,
|
|
498
|
-
/* @__PURE__ */
|
|
714
|
+
/* @__PURE__ */ jsxs7("p", { children: [
|
|
499
715
|
"Renews automatically at ",
|
|
500
716
|
amount(quote.commercial.renewalCents),
|
|
501
717
|
" per ",
|
|
502
718
|
quote.interval,
|
|
503
719
|
" unless canceled before renewal."
|
|
504
720
|
] }),
|
|
505
|
-
quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */
|
|
506
|
-
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
|
|
507
723
|
] }) : null,
|
|
508
|
-
quote.trustCopy ? /* @__PURE__ */
|
|
724
|
+
quote.trustCopy ? /* @__PURE__ */ jsx8("p", { className: "pay-trust", children: quote.trustCopy }) : null
|
|
509
725
|
] }),
|
|
510
|
-
|
|
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." })
|
|
729
|
+
] }) : null,
|
|
730
|
+
!editing ? /* @__PURE__ */ jsx8(
|
|
511
731
|
PaymentStep,
|
|
512
732
|
{
|
|
513
733
|
...props,
|
|
@@ -518,12 +738,12 @@ function MembershipPaymentStep(props) {
|
|
|
518
738
|
startCheckout
|
|
519
739
|
},
|
|
520
740
|
quote.digest
|
|
521
|
-
) : /* @__PURE__ */
|
|
741
|
+
) : /* @__PURE__ */ jsx8("p", { role: "status", children: "Save your member selection to continue to payment." })
|
|
522
742
|
] });
|
|
523
743
|
}
|
|
524
744
|
|
|
525
745
|
// src/ui/journey-frame.tsx
|
|
526
|
-
import { jsx as
|
|
746
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
527
747
|
var styles = `
|
|
528
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}
|
|
529
749
|
.chapter-journey *{box-sizing:border-box}
|
|
@@ -531,7 +751,7 @@ var styles = `
|
|
|
531
751
|
.chapter-journey :where(h2,h3){font-family:var(--ui-font-display,inherit);line-height:1.2;letter-spacing:-.025em;text-transform:none}
|
|
532
752
|
.chapter-journey h2{font-size:clamp(1.6rem,3vw,2.15rem)}
|
|
533
753
|
.chapter-journey h3{font-size:1.3rem}
|
|
534
|
-
.chapter-journey :where(.card,.join-form,.payment-quote,.join-book){padding:clamp(1.25rem,4vw,2.4rem);border:1px solid var(--ui-border,#dfe3df);border-radius:var(--ui-radius-lg,16px);background:var(--ui-surface,#fff);margin-block:1.2rem}
|
|
754
|
+
.chapter-journey :where(.card,.join-form,.payment-quote,.join-book,.checkout-seat-review){padding:clamp(1.25rem,4vw,2.4rem);border:1px solid var(--ui-border,#dfe3df);border-radius:var(--ui-radius-lg,16px);background:var(--ui-surface,#fff);margin-block:1.2rem}
|
|
535
755
|
.chapter-journey :where(.card-label,.journey-eyebrow){font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ui-text-muted,#536360);margin-bottom:.7rem;font-weight:600}
|
|
536
756
|
.chapter-journey :where(form,.journey-fields){display:grid;gap:1.25rem}
|
|
537
757
|
.chapter-journey :where(label){display:block;font-size:.95rem;font-weight:500;letter-spacing:normal;text-transform:none;line-height:1.55}
|
|
@@ -545,6 +765,14 @@ var styles = `
|
|
|
545
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)}
|
|
546
766
|
.chapter-journey :is(.slot-time,.slot-day)[aria-pressed=true]{background:var(--ui-accent,#285c50);color:var(--ui-on-accent,#fff)}
|
|
547
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}}
|
|
548
776
|
.chapter-journey :where(.compliance-box,.journey-note){padding:1.2rem;background:var(--ui-surface-2,#f3f5f2);border-radius:10px;margin-block:1.2rem}
|
|
549
777
|
.chapter-journey :where(.compliance-box p:last-child,.journey-note p:last-child,.card p:last-child){margin-bottom:0}
|
|
550
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}
|
|
@@ -555,24 +783,26 @@ var styles = `
|
|
|
555
783
|
.chapter-journey :where(.pay-status,.meeting-note,.slots-status){color:var(--ui-text-muted,#536360)}
|
|
556
784
|
.chapter-journey .journey-actions{display:flex;gap:.75rem;flex-wrap:wrap;margin-top:1.25rem}
|
|
557
785
|
.chapter-journey fieldset{min-width:0;border:0;padding:0;margin:0}
|
|
786
|
+
.chapter-journey .checkout-seat-terms{margin-block:1rem}
|
|
787
|
+
.chapter-journey .checkout-seat-terms summary{cursor:pointer}
|
|
558
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}}
|
|
559
789
|
`;
|
|
560
790
|
function JourneyFrame({ children }) {
|
|
561
|
-
return /* @__PURE__ */
|
|
562
|
-
/* @__PURE__ */
|
|
791
|
+
return /* @__PURE__ */ jsxs8("div", { className: "chapter-journey", children: [
|
|
792
|
+
/* @__PURE__ */ jsx9("style", { children: styles }),
|
|
563
793
|
children
|
|
564
794
|
] });
|
|
565
795
|
}
|
|
566
796
|
|
|
567
797
|
// src/ui/member-restart.tsx
|
|
568
|
-
import { jsx as
|
|
798
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
569
799
|
function MemberRestart(props) {
|
|
570
|
-
const [id, setId] =
|
|
571
|
-
const [busy, setBusy] =
|
|
572
|
-
const [error, setError] =
|
|
573
|
-
const [paid, setPaid] =
|
|
574
|
-
const [checking, setChecking] =
|
|
575
|
-
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);
|
|
576
806
|
useEffect2(() => {
|
|
577
807
|
if (!paid) return;
|
|
578
808
|
let live = true, timer, attempt = 0;
|
|
@@ -610,40 +840,40 @@ function MemberRestart(props) {
|
|
|
610
840
|
setBusy(false);
|
|
611
841
|
}
|
|
612
842
|
};
|
|
613
|
-
return /* @__PURE__ */
|
|
614
|
-
/* @__PURE__ */
|
|
615
|
-
/* @__PURE__ */
|
|
616
|
-
/* @__PURE__ */
|
|
617
|
-
/* @__PURE__ */
|
|
618
|
-
/* @__PURE__ */
|
|
619
|
-
/* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
621
|
-
/* @__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 })
|
|
622
852
|
] }),
|
|
623
|
-
paid ? /* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
626
|
-
!checking ? /* @__PURE__ */
|
|
627
|
-
] }) : id ? /* @__PURE__ */
|
|
628
|
-
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
|
|
629
859
|
] }) });
|
|
630
860
|
}
|
|
631
861
|
|
|
632
862
|
// src/ui/members.tsx
|
|
633
|
-
import { useEffect as useEffect6, useState as
|
|
863
|
+
import { useEffect as useEffect6, useState as useState12 } from "preact/hooks";
|
|
634
864
|
|
|
635
865
|
// src/ui/reschedule.tsx
|
|
636
|
-
import { useState as
|
|
637
|
-
import { jsx as
|
|
866
|
+
import { useState as useState8 } from "preact/hooks";
|
|
867
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "preact/jsx-runtime";
|
|
638
868
|
function Rescheduler(props) {
|
|
639
869
|
const inheritedCopy = useChapterCopy();
|
|
640
870
|
const copy = props.copy ?? inheritedCopy.members.reschedule;
|
|
641
871
|
const { api, applicationId, timezone, onRescheduled, label = copy.changeTime } = props;
|
|
642
|
-
const [open, setOpen] =
|
|
643
|
-
const [slots, setSlots] =
|
|
644
|
-
const [tz, setTz] =
|
|
645
|
-
const [busy, setBusy] =
|
|
646
|
-
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);
|
|
647
877
|
const start = async () => {
|
|
648
878
|
setOpen(true);
|
|
649
879
|
setSlots(null);
|
|
@@ -676,7 +906,7 @@ function Rescheduler(props) {
|
|
|
676
906
|
}
|
|
677
907
|
};
|
|
678
908
|
if (!open) {
|
|
679
|
-
return /* @__PURE__ */
|
|
909
|
+
return /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: /* @__PURE__ */ jsx11(
|
|
680
910
|
"a",
|
|
681
911
|
{
|
|
682
912
|
href: "#",
|
|
@@ -688,8 +918,8 @@ function Rescheduler(props) {
|
|
|
688
918
|
}
|
|
689
919
|
) });
|
|
690
920
|
}
|
|
691
|
-
return /* @__PURE__ */
|
|
692
|
-
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(
|
|
693
923
|
SlotPicker,
|
|
694
924
|
{
|
|
695
925
|
slots,
|
|
@@ -698,9 +928,9 @@ function Rescheduler(props) {
|
|
|
698
928
|
onPick: (s) => void pick(s)
|
|
699
929
|
}
|
|
700
930
|
),
|
|
701
|
-
busy ? /* @__PURE__ */
|
|
702
|
-
msg && slots && slots.length > 0 ? /* @__PURE__ */
|
|
703
|
-
/* @__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(
|
|
704
934
|
"a",
|
|
705
935
|
{
|
|
706
936
|
href: "#",
|
|
@@ -715,32 +945,32 @@ function Rescheduler(props) {
|
|
|
715
945
|
}
|
|
716
946
|
|
|
717
947
|
// src/ui/member-gifts.tsx
|
|
718
|
-
import { useEffect as useEffect3, useRef as
|
|
948
|
+
import { useEffect as useEffect3, useRef as useRef5, useState as useState9 } from "preact/hooks";
|
|
719
949
|
|
|
720
950
|
// src/ui/gift-offer-cards.tsx
|
|
721
|
-
import { jsx as
|
|
951
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "preact/jsx-runtime";
|
|
722
952
|
var price = (cents, currency) => currency === "usd" ? fmtMoney(cents) : new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(cents / 100);
|
|
723
953
|
function GiftOfferCards(props) {
|
|
724
954
|
const mode = props.mode ?? "preview";
|
|
725
|
-
return /* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
/* @__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: [
|
|
729
959
|
price(offer.priceCents, offer.currency),
|
|
730
960
|
offer.billingMode === "subscription" ? " recurring" : ""
|
|
731
961
|
] }),
|
|
732
|
-
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 })
|
|
733
963
|
] }, offer.id)) });
|
|
734
964
|
}
|
|
735
965
|
|
|
736
966
|
// src/ui/member-gifts.tsx
|
|
737
|
-
import { jsx as
|
|
967
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "preact/jsx-runtime";
|
|
738
968
|
function GiftPurchases(props) {
|
|
739
|
-
const [data, setData] =
|
|
740
|
-
const [selected, setSelected] =
|
|
741
|
-
const [code, setCode] =
|
|
742
|
-
const [message, setMessage] =
|
|
743
|
-
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());
|
|
744
974
|
const load = async () => setData(await props.api("/api/gifts"));
|
|
745
975
|
useEffect3(() => {
|
|
746
976
|
void load().catch(() => setData({ offers: [], claims: [] }));
|
|
@@ -757,16 +987,16 @@ function GiftPurchases(props) {
|
|
|
757
987
|
if (!data) return null;
|
|
758
988
|
if (data.offers.length === 0 && data.claims.length === 0) return null;
|
|
759
989
|
const offer = data.offers.find((item) => item.id === selected);
|
|
760
|
-
return /* @__PURE__ */
|
|
761
|
-
data.offers.length ? /* @__PURE__ */
|
|
762
|
-
/* @__PURE__ */
|
|
763
|
-
/* @__PURE__ */
|
|
764
|
-
/* @__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) => {
|
|
765
995
|
setSelected(id);
|
|
766
996
|
setCode("");
|
|
767
997
|
purchaseId.current = crypto.randomUUID();
|
|
768
998
|
} }),
|
|
769
|
-
offer ? /* @__PURE__ */
|
|
999
|
+
offer ? /* @__PURE__ */ jsx13(
|
|
770
1000
|
PaymentStep,
|
|
771
1001
|
{
|
|
772
1002
|
applicationId: purchaseId.current,
|
|
@@ -786,27 +1016,27 @@ function GiftPurchases(props) {
|
|
|
786
1016
|
}
|
|
787
1017
|
}
|
|
788
1018
|
) : null,
|
|
789
|
-
code ? /* @__PURE__ */
|
|
790
|
-
/* @__PURE__ */
|
|
791
|
-
/* @__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 })
|
|
792
1022
|
] }) : null
|
|
793
1023
|
] }) : null,
|
|
794
|
-
/* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
data.claims.length ? data.claims.map((claim) => /* @__PURE__ */
|
|
797
|
-
/* @__PURE__ */
|
|
798
|
-
/* @__PURE__ */
|
|
799
|
-
claim.status === "pending" ? /* @__PURE__ */
|
|
800
|
-
] }, claim.id)) : /* @__PURE__ */
|
|
801
|
-
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
|
|
802
1032
|
] })
|
|
803
1033
|
] });
|
|
804
1034
|
}
|
|
805
1035
|
var MemberGifts = GiftPurchases;
|
|
806
1036
|
|
|
807
1037
|
// src/ui/member-named-seat.tsx
|
|
808
|
-
import { useEffect as useEffect4, useState as
|
|
809
|
-
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";
|
|
810
1040
|
var NAMED_SEAT_RECIPIENT_WORDS = {
|
|
811
1041
|
payment_pending: "payment in progress",
|
|
812
1042
|
invited: "invited, waiting for them to accept",
|
|
@@ -819,7 +1049,7 @@ var NAMED_SEAT_RECIPIENT_WORDS = {
|
|
|
819
1049
|
var day = (at) => new Date(at).toLocaleDateString("en-US", { timeZone: "UTC" });
|
|
820
1050
|
function NamedSeatRecipientLine({ seat }) {
|
|
821
1051
|
const words = NAMED_SEAT_RECIPIENT_WORDS[seat.recipientState] ?? seat.status.replaceAll("_", " ");
|
|
822
|
-
return /* @__PURE__ */
|
|
1052
|
+
return /* @__PURE__ */ jsxs13("p", { className: "member-named-seat-recipient", children: [
|
|
823
1053
|
seat.recipientName,
|
|
824
1054
|
" \xB7 ",
|
|
825
1055
|
seat.recipientEmail,
|
|
@@ -829,9 +1059,9 @@ function NamedSeatRecipientLine({ seat }) {
|
|
|
829
1059
|
] });
|
|
830
1060
|
}
|
|
831
1061
|
function NamedSeatPurchase({ api }) {
|
|
832
|
-
const [data, setData] =
|
|
833
|
-
const [name, setName] =
|
|
834
|
-
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);
|
|
835
1065
|
const load = async () => {
|
|
836
1066
|
try {
|
|
837
1067
|
const value = await api("/api/named-seat");
|
|
@@ -868,13 +1098,13 @@ function NamedSeatPurchase({ api }) {
|
|
|
868
1098
|
}
|
|
869
1099
|
};
|
|
870
1100
|
const money = data ? new Intl.NumberFormat("en-US", { style: "currency", currency: data.currency }).format(data.amountCents / 100) : "";
|
|
871
|
-
return /* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
error ? /* @__PURE__ */
|
|
874
|
-
data ? /* @__PURE__ */
|
|
875
|
-
data.seat ? /* @__PURE__ */
|
|
876
|
-
data.eligible ? /* @__PURE__ */
|
|
877
|
-
/* @__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: [
|
|
878
1108
|
data.included ? "Included with your membership at no charge." : `${money} paid in full now.`,
|
|
879
1109
|
" This seat ",
|
|
880
1110
|
data.autoRenew ? "renews with your primary membership" : "ends with your primary membership",
|
|
@@ -885,39 +1115,39 @@ function NamedSeatPurchase({ api }) {
|
|
|
885
1115
|
" ",
|
|
886
1116
|
"It belongs to one named person and cannot be reassigned."
|
|
887
1117
|
] }),
|
|
888
|
-
/* @__PURE__ */
|
|
889
|
-
!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) => {
|
|
890
1120
|
event.preventDefault();
|
|
891
1121
|
setReviewing(true);
|
|
892
1122
|
setTerms(false);
|
|
893
1123
|
}, children: [
|
|
894
|
-
/* @__PURE__ */
|
|
1124
|
+
/* @__PURE__ */ jsxs13("label", { children: [
|
|
895
1125
|
"Recipient name",
|
|
896
|
-
/* @__PURE__ */
|
|
1126
|
+
/* @__PURE__ */ jsx14("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
|
|
897
1127
|
] }),
|
|
898
|
-
/* @__PURE__ */
|
|
1128
|
+
/* @__PURE__ */ jsxs13("label", { children: [
|
|
899
1129
|
"Recipient email",
|
|
900
|
-
/* @__PURE__ */
|
|
1130
|
+
/* @__PURE__ */ jsx14("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
|
|
901
1131
|
] }),
|
|
902
|
-
/* @__PURE__ */
|
|
903
|
-
] }) : /* @__PURE__ */
|
|
904
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsx14("button", { className: "btn primary", type: "submit", children: "Review named seat" })
|
|
1133
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment3, { children: [
|
|
1134
|
+
/* @__PURE__ */ jsxs13("p", { children: [
|
|
905
1135
|
"For ",
|
|
906
1136
|
name,
|
|
907
1137
|
" \xB7 ",
|
|
908
1138
|
email
|
|
909
1139
|
] }),
|
|
910
|
-
/* @__PURE__ */
|
|
1140
|
+
/* @__PURE__ */ jsx14("button", { className: "btn secondary", type: "button", onClick: () => {
|
|
911
1141
|
setReviewing(false);
|
|
912
1142
|
setTerms(false);
|
|
913
1143
|
void load();
|
|
914
1144
|
}, children: "Back to recipient" }),
|
|
915
|
-
/* @__PURE__ */
|
|
916
|
-
/* @__PURE__ */
|
|
917
|
-
/* @__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." })
|
|
918
1148
|
] }),
|
|
919
|
-
terms && data.included ? /* @__PURE__ */
|
|
920
|
-
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(
|
|
921
1151
|
PaymentStep,
|
|
922
1152
|
{
|
|
923
1153
|
applicationId: data.membershipId,
|
|
@@ -932,17 +1162,17 @@ function NamedSeatPurchase({ api }) {
|
|
|
932
1162
|
}
|
|
933
1163
|
) : null
|
|
934
1164
|
] })
|
|
935
|
-
] }) : !data.seat ? /* @__PURE__ */
|
|
936
|
-
pending ? /* @__PURE__ */
|
|
937
|
-
] }) : !error ? /* @__PURE__ */
|
|
938
|
-
/* @__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" })
|
|
939
1169
|
] }) });
|
|
940
1170
|
}
|
|
941
1171
|
|
|
942
1172
|
// src/ui/member-content.tsx
|
|
943
|
-
import { useEffect as useEffect5, useMemo as useMemo2, useState as
|
|
1173
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState11 } from "preact/hooks";
|
|
944
1174
|
import { Markdown } from "@odla-ai/ui/components";
|
|
945
|
-
import { Fragment as
|
|
1175
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs14 } from "preact/jsx-runtime";
|
|
946
1176
|
var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
|
|
947
1177
|
function MemberContentArea(props) {
|
|
948
1178
|
const {
|
|
@@ -950,12 +1180,12 @@ function MemberContentArea(props) {
|
|
|
950
1180
|
path = "/api/member-content",
|
|
951
1181
|
upsellHref,
|
|
952
1182
|
onUpsell,
|
|
953
|
-
loadingContent = /* @__PURE__ */
|
|
954
|
-
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." })
|
|
955
1185
|
} = props;
|
|
956
|
-
const [data, setData] =
|
|
957
|
-
const [error, setError] =
|
|
958
|
-
const [selectedId, setSelectedId] =
|
|
1186
|
+
const [data, setData] = useState11(props.initialData ?? null);
|
|
1187
|
+
const [error, setError] = useState11(null);
|
|
1188
|
+
const [selectedId, setSelectedId] = useState11(
|
|
959
1189
|
props.initialPageId ?? props.initialData?.pages[0]?.id ?? ""
|
|
960
1190
|
);
|
|
961
1191
|
useEffect5(() => {
|
|
@@ -980,18 +1210,18 @@ function MemberContentArea(props) {
|
|
|
980
1210
|
}
|
|
981
1211
|
return [...result.entries()];
|
|
982
1212
|
}, [data]);
|
|
983
|
-
if (error) return /* @__PURE__ */
|
|
1213
|
+
if (error) return /* @__PURE__ */ jsxs14("p", { className: "meeting-note", role: "alert", children: [
|
|
984
1214
|
"Member pages could not be loaded: ",
|
|
985
1215
|
error
|
|
986
1216
|
] });
|
|
987
|
-
if (!data) return /* @__PURE__ */
|
|
988
|
-
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 });
|
|
989
1219
|
const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
|
|
990
1220
|
const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
|
|
991
|
-
return /* @__PURE__ */
|
|
992
|
-
/* @__PURE__ */
|
|
993
|
-
/* @__PURE__ */
|
|
994
|
-
/* @__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(
|
|
995
1225
|
"button",
|
|
996
1226
|
{
|
|
997
1227
|
type: "button",
|
|
@@ -1001,23 +1231,23 @@ function MemberContentArea(props) {
|
|
|
1001
1231
|
}
|
|
1002
1232
|
) }, page.id)) })
|
|
1003
1233
|
] }, section)) }),
|
|
1004
|
-
/* @__PURE__ */
|
|
1005
|
-
/* @__PURE__ */
|
|
1006
|
-
/* @__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: [
|
|
1007
1237
|
selected.source.type === "parent" ? "Parent" : "Chapter",
|
|
1008
1238
|
" \xB7 ",
|
|
1009
1239
|
selected.access
|
|
1010
1240
|
] }),
|
|
1011
|
-
/* @__PURE__ */
|
|
1012
|
-
selected.summary ? /* @__PURE__ */
|
|
1241
|
+
/* @__PURE__ */ jsx15("h1", { children: selected.title }),
|
|
1242
|
+
selected.summary ? /* @__PURE__ */ jsx15("p", { children: selected.summary }) : null
|
|
1013
1243
|
] }),
|
|
1014
|
-
selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */
|
|
1015
|
-
selected.teaserMarkdown ? /* @__PURE__ */
|
|
1016
|
-
selected.upsell ? /* @__PURE__ */
|
|
1017
|
-
/* @__PURE__ */
|
|
1018
|
-
/* @__PURE__ */
|
|
1019
|
-
selected.upsell.bodyMarkdown ? /* @__PURE__ */
|
|
1020
|
-
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
|
|
1021
1251
|
] }) : null
|
|
1022
1252
|
] })
|
|
1023
1253
|
] })
|
|
@@ -1025,12 +1255,12 @@ function MemberContentArea(props) {
|
|
|
1025
1255
|
}
|
|
1026
1256
|
|
|
1027
1257
|
// src/ui/members.tsx
|
|
1028
|
-
import { Fragment as
|
|
1258
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs15 } from "preact/jsx-runtime";
|
|
1029
1259
|
function card(copy, kicker, body) {
|
|
1030
|
-
return /* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
1033
|
-
/* @__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 }),
|
|
1034
1264
|
body
|
|
1035
1265
|
] })
|
|
1036
1266
|
] });
|
|
@@ -1041,9 +1271,9 @@ function ProvisionalCard(props) {
|
|
|
1041
1271
|
return card(
|
|
1042
1272
|
copy,
|
|
1043
1273
|
copy.provisional.applicationNeeded,
|
|
1044
|
-
/* @__PURE__ */
|
|
1045
|
-
/* @__PURE__ */
|
|
1046
|
-
/* @__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 })
|
|
1047
1277
|
] })
|
|
1048
1278
|
);
|
|
1049
1279
|
}
|
|
@@ -1051,19 +1281,19 @@ function ProvisionalCard(props) {
|
|
|
1051
1281
|
return card(
|
|
1052
1282
|
copy,
|
|
1053
1283
|
copy.provisional.refunded,
|
|
1054
|
-
/* @__PURE__ */
|
|
1284
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.refundedBody })
|
|
1055
1285
|
);
|
|
1056
1286
|
}
|
|
1057
|
-
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;
|
|
1058
1288
|
if (application.meetingAt) {
|
|
1059
1289
|
return card(
|
|
1060
1290
|
copy,
|
|
1061
1291
|
copy.provisional.introductionCall,
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
application.meetUrl ? /* @__PURE__ */
|
|
1066
|
-
/* @__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(
|
|
1067
1297
|
Rescheduler,
|
|
1068
1298
|
{
|
|
1069
1299
|
api,
|
|
@@ -1080,9 +1310,9 @@ function ProvisionalCard(props) {
|
|
|
1080
1310
|
return card(
|
|
1081
1311
|
copy,
|
|
1082
1312
|
copy.provisional.bookCall,
|
|
1083
|
-
/* @__PURE__ */
|
|
1084
|
-
/* @__PURE__ */
|
|
1085
|
-
/* @__PURE__ */
|
|
1313
|
+
/* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
1314
|
+
/* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
|
|
1315
|
+
/* @__PURE__ */ jsx16(
|
|
1086
1316
|
Rescheduler,
|
|
1087
1317
|
{
|
|
1088
1318
|
api,
|
|
@@ -1109,8 +1339,8 @@ function MembersArea(props) {
|
|
|
1109
1339
|
renderProvisional
|
|
1110
1340
|
} = props;
|
|
1111
1341
|
const copy = props.copy ?? inheritedCopy.members;
|
|
1112
|
-
const [me, setMe] =
|
|
1113
|
-
const [error, setError] =
|
|
1342
|
+
const [me, setMe] = useState12(null);
|
|
1343
|
+
const [error, setError] = useState12(false);
|
|
1114
1344
|
const reload = async () => {
|
|
1115
1345
|
try {
|
|
1116
1346
|
setMe(await api("/api/me"));
|
|
@@ -1121,22 +1351,22 @@ function MembersArea(props) {
|
|
|
1121
1351
|
useEffect6(() => {
|
|
1122
1352
|
void reload();
|
|
1123
1353
|
}, []);
|
|
1124
|
-
if (error) return /* @__PURE__ */
|
|
1125
|
-
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 });
|
|
1126
1356
|
const role = me.role || "provisional";
|
|
1127
|
-
return /* @__PURE__ */
|
|
1128
|
-
/* @__PURE__ */
|
|
1129
|
-
/* @__PURE__ */
|
|
1130
|
-
/* @__PURE__ */
|
|
1131
|
-
/* @__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 })
|
|
1132
1362
|
] }),
|
|
1133
|
-
/* @__PURE__ */
|
|
1134
|
-
/* @__PURE__ */
|
|
1135
|
-
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
|
|
1136
1366
|
] })
|
|
1137
1367
|
] }),
|
|
1138
|
-
me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */
|
|
1139
|
-
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(
|
|
1140
1370
|
ProvisionalCard,
|
|
1141
1371
|
{
|
|
1142
1372
|
api,
|
|
@@ -1153,30 +1383,30 @@ function MembersArea(props) {
|
|
|
1153
1383
|
reload,
|
|
1154
1384
|
defaultContent
|
|
1155
1385
|
}) ?? defaultContent;
|
|
1156
|
-
})() : memberContent ?? (memberPages ? /* @__PURE__ */
|
|
1386
|
+
})() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx16(
|
|
1157
1387
|
MemberContentArea,
|
|
1158
1388
|
{
|
|
1159
1389
|
api,
|
|
1160
1390
|
...memberPages === true ? {} : memberPages
|
|
1161
1391
|
}
|
|
1162
|
-
) : /* @__PURE__ */
|
|
1163
|
-
/* @__PURE__ */
|
|
1164
|
-
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
|
|
1165
1395
|
] });
|
|
1166
1396
|
}
|
|
1167
1397
|
|
|
1168
1398
|
// src/ui/join.tsx
|
|
1169
|
-
import { useEffect as useEffect11, useRef as
|
|
1399
|
+
import { useEffect as useEffect11, useRef as useRef7, useState as useState20 } from "preact/hooks";
|
|
1170
1400
|
|
|
1171
1401
|
// src/ui/join-booking.tsx
|
|
1172
|
-
import { useEffect as useEffect7, useState as
|
|
1173
|
-
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";
|
|
1174
1404
|
function JoinBooking(props) {
|
|
1175
1405
|
const { applicationId, copy, onBooked, simulation } = props;
|
|
1176
|
-
const [state, setState] =
|
|
1177
|
-
const [msg, setMsg] =
|
|
1178
|
-
const [busy, setBusy] =
|
|
1179
|
-
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);
|
|
1180
1410
|
const load = async () => {
|
|
1181
1411
|
setMsg(null);
|
|
1182
1412
|
try {
|
|
@@ -1233,11 +1463,11 @@ function JoinBooking(props) {
|
|
|
1233
1463
|
setBusy(false);
|
|
1234
1464
|
}
|
|
1235
1465
|
};
|
|
1236
|
-
if (!state) return /* @__PURE__ */
|
|
1237
|
-
return /* @__PURE__ */
|
|
1238
|
-
/* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
/* @__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(
|
|
1241
1471
|
SlotPicker,
|
|
1242
1472
|
{
|
|
1243
1473
|
slots: state.slots,
|
|
@@ -1247,29 +1477,29 @@ function JoinBooking(props) {
|
|
|
1247
1477
|
onDayChange: () => setSelected(null)
|
|
1248
1478
|
}
|
|
1249
1479
|
),
|
|
1250
|
-
/* @__PURE__ */
|
|
1251
|
-
/* @__PURE__ */
|
|
1252
|
-
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
|
|
1253
1483
|
] })
|
|
1254
1484
|
] });
|
|
1255
1485
|
}
|
|
1256
1486
|
|
|
1257
1487
|
// src/ui/join-accepted.tsx
|
|
1258
|
-
import { jsx as
|
|
1488
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "preact/jsx-runtime";
|
|
1259
1489
|
function JoinAccepted(props) {
|
|
1260
|
-
return /* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
1262
|
-
/* @__PURE__ */
|
|
1263
|
-
/* @__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 })
|
|
1264
1494
|
] });
|
|
1265
1495
|
}
|
|
1266
1496
|
|
|
1267
1497
|
// src/ui/gift-claim-card.tsx
|
|
1268
|
-
import { useState as
|
|
1269
|
-
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";
|
|
1270
1500
|
function GiftClaimCard(props) {
|
|
1271
|
-
const [code, setCode] =
|
|
1272
|
-
const [error, setError] =
|
|
1501
|
+
const [code, setCode] = useState14(props.initialCode ?? "");
|
|
1502
|
+
const [error, setError] = useState14(false);
|
|
1273
1503
|
const rotate = async () => {
|
|
1274
1504
|
if (!props.claimId) return;
|
|
1275
1505
|
setError(false);
|
|
@@ -1282,24 +1512,27 @@ function GiftClaimCard(props) {
|
|
|
1282
1512
|
if (response.ok && body.code) setCode(body.code);
|
|
1283
1513
|
else setError(true);
|
|
1284
1514
|
};
|
|
1285
|
-
return /* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
code ? /* @__PURE__ */
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__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 })
|
|
1291
1521
|
] }) : null,
|
|
1292
|
-
!code && props.claimId ? /* @__PURE__ */
|
|
1293
|
-
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
|
|
1294
1524
|
] });
|
|
1295
1525
|
}
|
|
1296
1526
|
|
|
1527
|
+
// src/ui/join-application-form.tsx
|
|
1528
|
+
import { useRef as useRef6 } from "preact/hooks";
|
|
1529
|
+
|
|
1297
1530
|
// src/ui/join-tiers.tsx
|
|
1298
|
-
import { useState as
|
|
1299
|
-
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";
|
|
1300
1533
|
var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
|
|
1301
1534
|
function useTierSelection(tiers, initialTierId) {
|
|
1302
|
-
const [selectedTierId, setSelectedTierId] =
|
|
1535
|
+
const [selectedTierId, setSelectedTierId] = useState15(() => {
|
|
1303
1536
|
const preset = tiers.find((tier) => tier.id === initialTierId);
|
|
1304
1537
|
if (preset) return preset.id;
|
|
1305
1538
|
return tiers.length === 1 ? tiers[0].id : null;
|
|
@@ -1314,10 +1547,10 @@ function useTierSelection(tiers, initialTierId) {
|
|
|
1314
1547
|
};
|
|
1315
1548
|
}
|
|
1316
1549
|
function TierPlaceholder(context) {
|
|
1317
|
-
return /* @__PURE__ */
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
context.tiers.map((tier) => /* @__PURE__ */
|
|
1320
|
-
/* @__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(
|
|
1321
1554
|
"input",
|
|
1322
1555
|
{
|
|
1323
1556
|
type: "radio",
|
|
@@ -1328,13 +1561,13 @@ function TierPlaceholder(context) {
|
|
|
1328
1561
|
}
|
|
1329
1562
|
),
|
|
1330
1563
|
tier.name,
|
|
1331
|
-
tier.founding ? /* @__PURE__ */
|
|
1564
|
+
tier.founding ? /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
1332
1565
|
" \u2014 ",
|
|
1333
1566
|
joinTierMoney(tier.founding.dueTodayCents),
|
|
1334
1567
|
" founding member rate (list ",
|
|
1335
1568
|
joinTierMoney(tier.priceCents),
|
|
1336
1569
|
")"
|
|
1337
|
-
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */
|
|
1570
|
+
] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
1338
1571
|
" \u2014 ",
|
|
1339
1572
|
joinTierMoney(tier.priceCents)
|
|
1340
1573
|
] })
|
|
@@ -1346,19 +1579,28 @@ function tierNeedsPayment(selected, paymentsReady) {
|
|
|
1346
1579
|
}
|
|
1347
1580
|
|
|
1348
1581
|
// src/ui/join-application-form.tsx
|
|
1349
|
-
import { jsx as
|
|
1582
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "preact/jsx-runtime";
|
|
1350
1583
|
function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
|
|
1351
|
-
const
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
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 })
|
|
1357
1599
|
] }) : null,
|
|
1358
1600
|
!requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
|
|
1359
1601
|
typeof props.children === "function" ? props.children({ invitation }) : props.children,
|
|
1360
|
-
error ? /* @__PURE__ */
|
|
1361
|
-
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 })
|
|
1362
1604
|
] });
|
|
1363
1605
|
}
|
|
1364
1606
|
|
|
@@ -1383,8 +1625,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
|
|
|
1383
1625
|
|
|
1384
1626
|
// src/ui/gift-code-redeemer.tsx
|
|
1385
1627
|
import { InlineActionField } from "@odla-ai/ui/components";
|
|
1386
|
-
import { useState as
|
|
1387
|
-
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";
|
|
1388
1630
|
var GIFT_CODE_REDEEMER_CSS = `
|
|
1389
1631
|
.gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
|
|
1390
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}
|
|
@@ -1399,10 +1641,10 @@ var GIFT_CODE_REDEEMER_CSS = `
|
|
|
1399
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%}}
|
|
1400
1642
|
`;
|
|
1401
1643
|
function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
1402
|
-
const [code, setCode] =
|
|
1403
|
-
const [loading, setLoading] =
|
|
1404
|
-
const [message, setMessage] =
|
|
1405
|
-
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");
|
|
1406
1648
|
const normalizedCode = code.trim();
|
|
1407
1649
|
const redeem = async () => {
|
|
1408
1650
|
if (!normalizedCode || loading) return;
|
|
@@ -1429,9 +1671,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
|
|
|
1429
1671
|
setLoading(false);
|
|
1430
1672
|
}
|
|
1431
1673
|
};
|
|
1432
|
-
return /* @__PURE__ */
|
|
1433
|
-
/* @__PURE__ */
|
|
1434
|
-
/* @__PURE__ */
|
|
1674
|
+
return /* @__PURE__ */ jsxs21(Fragment8, { children: [
|
|
1675
|
+
/* @__PURE__ */ jsx22("style", { children: GIFT_CODE_REDEEMER_CSS }),
|
|
1676
|
+
/* @__PURE__ */ jsx22(
|
|
1435
1677
|
InlineActionField,
|
|
1436
1678
|
{
|
|
1437
1679
|
id,
|
|
@@ -1487,12 +1729,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
|
|
|
1487
1729
|
}
|
|
1488
1730
|
|
|
1489
1731
|
// src/ui/join-gift-claim.tsx
|
|
1490
|
-
import { jsx as
|
|
1732
|
+
import { jsx as jsx23, jsxs as jsxs22 } from "preact/jsx-runtime";
|
|
1491
1733
|
function JoinGiftClaim(props) {
|
|
1492
|
-
return /* @__PURE__ */
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
/* @__PURE__ */
|
|
1495
|
-
/* @__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(
|
|
1496
1738
|
GiftCodeRedeemer,
|
|
1497
1739
|
{
|
|
1498
1740
|
api: props.api,
|
|
@@ -1516,21 +1758,21 @@ function JoinGiftClaim(props) {
|
|
|
1516
1758
|
}
|
|
1517
1759
|
|
|
1518
1760
|
// src/ui/join-named-seat.tsx
|
|
1519
|
-
import { useState as
|
|
1520
|
-
import { jsx as
|
|
1761
|
+
import { useState as useState17 } from "preact/hooks";
|
|
1762
|
+
import { jsx as jsx24, jsxs as jsxs23 } from "preact/jsx-runtime";
|
|
1521
1763
|
function JoinNamedSeat(props) {
|
|
1522
1764
|
const seatId = props.seatId ?? "";
|
|
1523
1765
|
const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
|
|
1524
|
-
const [accepted, setAccepted] =
|
|
1525
|
-
return /* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
1527
|
-
/* @__PURE__ */
|
|
1528
|
-
/* @__PURE__ */
|
|
1529
|
-
/* @__PURE__ */
|
|
1530
|
-
/* @__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 })
|
|
1531
1773
|
] }),
|
|
1532
|
-
error ? /* @__PURE__ */
|
|
1533
|
-
/* @__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 () => {
|
|
1534
1776
|
setBusy(true);
|
|
1535
1777
|
setError("");
|
|
1536
1778
|
try {
|
|
@@ -1550,12 +1792,12 @@ function JoinNamedSeat(props) {
|
|
|
1550
1792
|
}
|
|
1551
1793
|
|
|
1552
1794
|
// src/ui/join-invitation.tsx
|
|
1553
|
-
import { useEffect as useEffect8, useState as
|
|
1554
|
-
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";
|
|
1555
1797
|
function useJoinInvitation(seatId, api, fallback) {
|
|
1556
|
-
const [invitation, setInvitation] =
|
|
1557
|
-
const [error, setError] =
|
|
1558
|
-
const [revision, setRevision] =
|
|
1798
|
+
const [invitation, setInvitation] = useState18(null);
|
|
1799
|
+
const [error, setError] = useState18("");
|
|
1800
|
+
const [revision, setRevision] = useState18(0);
|
|
1559
1801
|
useEffect8(() => {
|
|
1560
1802
|
let live = true;
|
|
1561
1803
|
setInvitation(null);
|
|
@@ -1578,12 +1820,22 @@ function useJoinInvitation(seatId, api, fallback) {
|
|
|
1578
1820
|
return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
|
|
1579
1821
|
}
|
|
1580
1822
|
function JoinInvitationNotice(props) {
|
|
1581
|
-
return /* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__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 }) })
|
|
1584
1826
|
] });
|
|
1585
1827
|
}
|
|
1586
1828
|
|
|
1829
|
+
// src/ui/join-simulation.ts
|
|
1830
|
+
function joinSimulationPayment(simulation, priceCents) {
|
|
1831
|
+
if (!simulation) return void 0;
|
|
1832
|
+
return simulation.payment ?? { lineItems: {
|
|
1833
|
+
standardCents: priceCents,
|
|
1834
|
+
discountCents: 0,
|
|
1835
|
+
dueTodayCents: priceCents
|
|
1836
|
+
} };
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1587
1839
|
// src/ui/join-pending.ts
|
|
1588
1840
|
import { useEffect as useEffect9 } from "preact/hooks";
|
|
1589
1841
|
function useJoinPending(state, loadResume, setState) {
|
|
@@ -1610,14 +1862,14 @@ function useJoinPending(state, loadResume, setState) {
|
|
|
1610
1862
|
}
|
|
1611
1863
|
|
|
1612
1864
|
// src/ui/payment-receipt.tsx
|
|
1613
|
-
import { useEffect as useEffect10, useState as
|
|
1614
|
-
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";
|
|
1615
1867
|
function PaymentReceiptCard({ applicationId }) {
|
|
1616
|
-
const [receipt, setReceipt] =
|
|
1617
|
-
const [error, setError] =
|
|
1618
|
-
const [revision, setRevision] =
|
|
1619
|
-
const [emailState, setEmailState] =
|
|
1620
|
-
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);
|
|
1621
1873
|
const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
|
|
1622
1874
|
useEffect10(() => {
|
|
1623
1875
|
let live = true, timer;
|
|
@@ -1645,9 +1897,9 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
1645
1897
|
if (timer) clearTimeout(timer);
|
|
1646
1898
|
};
|
|
1647
1899
|
}, [endpoint, revision]);
|
|
1648
|
-
if (!receipt) return error ? /* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__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" })
|
|
1651
1903
|
] }) : null;
|
|
1652
1904
|
const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
|
|
1653
1905
|
const email = async () => {
|
|
@@ -1664,38 +1916,38 @@ function PaymentReceiptCard({ applicationId }) {
|
|
|
1664
1916
|
setError("We could not confirm email delivery. You can print or save your receipt.");
|
|
1665
1917
|
}
|
|
1666
1918
|
};
|
|
1667
|
-
return /* @__PURE__ */
|
|
1668
|
-
/* @__PURE__ */
|
|
1669
|
-
/* @__PURE__ */
|
|
1670
|
-
/* @__PURE__ */
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
1673
|
-
receipt.namedSeat ? /* @__PURE__ */
|
|
1674
|
-
/* @__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: [
|
|
1675
1927
|
"Additional member \u2014 ",
|
|
1676
1928
|
receipt.namedSeat.recipientName
|
|
1677
1929
|
] }),
|
|
1678
|
-
/* @__PURE__ */
|
|
1930
|
+
/* @__PURE__ */ jsxs25("dd", { children: [
|
|
1679
1931
|
receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
|
|
1680
1932
|
money(receipt.namedSeat.amountCents)
|
|
1681
1933
|
] })
|
|
1682
1934
|
] }) : null,
|
|
1683
|
-
/* @__PURE__ */
|
|
1684
|
-
/* @__PURE__ */
|
|
1935
|
+
/* @__PURE__ */ jsx26("dt", { children: "Total paid" }),
|
|
1936
|
+
/* @__PURE__ */ jsx26("dd", { children: money(receipt.totalCents) })
|
|
1685
1937
|
] }),
|
|
1686
|
-
/* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
/* @__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" })
|
|
1689
1941
|
] }),
|
|
1690
|
-
emailState === "sent" ? /* @__PURE__ */
|
|
1691
|
-
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
|
|
1692
1944
|
] });
|
|
1693
1945
|
}
|
|
1694
1946
|
|
|
1695
1947
|
// src/ui/join.tsx
|
|
1696
|
-
import { Fragment as
|
|
1948
|
+
import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs26 } from "preact/jsx-runtime";
|
|
1697
1949
|
function JoinIsland(props) {
|
|
1698
|
-
return /* @__PURE__ */
|
|
1950
|
+
return /* @__PURE__ */ jsx27(JourneyFrame, { children: /* @__PURE__ */ jsx27(JoinFlow, { ...props }) });
|
|
1699
1951
|
}
|
|
1700
1952
|
function JoinFlow(props) {
|
|
1701
1953
|
const inheritedCopy = useChapterCopy();
|
|
@@ -1716,19 +1968,14 @@ function JoinFlow(props) {
|
|
|
1716
1968
|
const invitation = invitationState.invitation;
|
|
1717
1969
|
const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
|
|
1718
1970
|
const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
|
|
1719
|
-
const [state, setState] =
|
|
1720
|
-
const [error, setError] =
|
|
1721
|
-
const [submitting, setSubmitting] =
|
|
1722
|
-
const [
|
|
1723
|
-
const
|
|
1724
|
-
|
|
1725
|
-
standardCents: selectedTier?.priceCents ?? 0,
|
|
1726
|
-
discountCents: 0,
|
|
1727
|
-
dueTodayCents: selectedTier?.priceCents ?? 0
|
|
1728
|
-
}
|
|
1729
|
-
} : void 0;
|
|
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);
|
|
1976
|
+
const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
|
|
1730
1977
|
const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
|
|
1731
|
-
const submissionId =
|
|
1978
|
+
const submissionId = useRef7(null);
|
|
1732
1979
|
useEffect11(() => {
|
|
1733
1980
|
if (props.simulation) return;
|
|
1734
1981
|
const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
|
|
@@ -1750,6 +1997,10 @@ function JoinFlow(props) {
|
|
|
1750
1997
|
const submit = async (e) => {
|
|
1751
1998
|
e.preventDefault();
|
|
1752
1999
|
if (submitting || props.submitDisabled === true || requestedSeat && !invitation) return;
|
|
2000
|
+
if (!validJoinRecipient(props.payment?.initialNamedSeat)) {
|
|
2001
|
+
setError("Enter your family member's full name and valid email before continuing.");
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
1753
2004
|
setSubmitting(true);
|
|
1754
2005
|
setError(null);
|
|
1755
2006
|
try {
|
|
@@ -1798,13 +2049,13 @@ function JoinFlow(props) {
|
|
|
1798
2049
|
setSubmitting(false);
|
|
1799
2050
|
}
|
|
1800
2051
|
};
|
|
1801
|
-
if (requestedSeat && !invitation) return /* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
1803
|
-
/* @__PURE__ */
|
|
1804
|
-
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
|
|
1805
2056
|
] });
|
|
1806
|
-
const header = /* @__PURE__ */
|
|
1807
|
-
invitation ? /* @__PURE__ */
|
|
2057
|
+
const header = /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
2058
|
+
invitation ? /* @__PURE__ */ jsx27(
|
|
1808
2059
|
JoinInvitationNotice,
|
|
1809
2060
|
{
|
|
1810
2061
|
invitation,
|
|
@@ -1814,51 +2065,52 @@ function JoinFlow(props) {
|
|
|
1814
2065
|
) : null,
|
|
1815
2066
|
renderStepHeader?.({
|
|
1816
2067
|
state,
|
|
2068
|
+
editingNamedSeat: state.step === "payment" && editingNamedSeat,
|
|
1817
2069
|
...invitation ? { invitation } : {},
|
|
1818
2070
|
..."applicationId" in state ? { applicationId: state.applicationId } : {}
|
|
1819
2071
|
}),
|
|
1820
|
-
!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
|
|
1821
2073
|
] });
|
|
1822
2074
|
if (state.step === "closed") {
|
|
1823
|
-
return /* @__PURE__ */
|
|
2075
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1824
2076
|
header,
|
|
1825
|
-
/* @__PURE__ */
|
|
1826
|
-
/* @__PURE__ */
|
|
1827
|
-
/* @__PURE__ */
|
|
1828
|
-
/* @__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 })
|
|
1829
2081
|
] })
|
|
1830
2082
|
] });
|
|
1831
2083
|
}
|
|
1832
2084
|
if (state.step === "done") {
|
|
1833
|
-
const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
1834
|
-
/* @__PURE__ */
|
|
1835
|
-
/* @__PURE__ */
|
|
1836
|
-
/* @__PURE__ */
|
|
1837
|
-
/* @__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 })
|
|
1838
2090
|
] });
|
|
1839
|
-
return /* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1840
2092
|
header,
|
|
1841
2093
|
body
|
|
1842
2094
|
] });
|
|
1843
2095
|
}
|
|
1844
2096
|
if (state.step === "accepted") {
|
|
1845
|
-
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */
|
|
1846
|
-
return /* @__PURE__ */
|
|
2097
|
+
const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx27(JoinAccepted, { copy, membersHref });
|
|
2098
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1847
2099
|
header,
|
|
1848
2100
|
body
|
|
1849
2101
|
] });
|
|
1850
2102
|
}
|
|
1851
2103
|
if (state.step === "gift") {
|
|
1852
|
-
const body = renderGift?.(state) ?? /* @__PURE__ */
|
|
1853
|
-
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: [
|
|
1854
2106
|
header,
|
|
1855
2107
|
body
|
|
1856
2108
|
] });
|
|
1857
2109
|
}
|
|
1858
2110
|
if (state.step === "booking") {
|
|
1859
|
-
return /* @__PURE__ */
|
|
2111
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1860
2112
|
header,
|
|
1861
|
-
/* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsx27(
|
|
1862
2114
|
JoinBooking,
|
|
1863
2115
|
{
|
|
1864
2116
|
applicationId: state.applicationId,
|
|
@@ -1873,9 +2125,9 @@ function JoinFlow(props) {
|
|
|
1873
2125
|
}
|
|
1874
2126
|
if (state.step === "payment") {
|
|
1875
2127
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
|
|
1876
|
-
return /* @__PURE__ */
|
|
2128
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1877
2129
|
header,
|
|
1878
|
-
/* @__PURE__ */
|
|
2130
|
+
/* @__PURE__ */ jsx27(
|
|
1879
2131
|
JoinNamedSeat,
|
|
1880
2132
|
{
|
|
1881
2133
|
api: props.namedSeatClaimApi,
|
|
@@ -1888,9 +2140,9 @@ function JoinFlow(props) {
|
|
|
1888
2140
|
] });
|
|
1889
2141
|
}
|
|
1890
2142
|
const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
|
|
1891
|
-
return /* @__PURE__ */
|
|
2143
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1892
2144
|
header,
|
|
1893
|
-
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */
|
|
2145
|
+
props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx27(
|
|
1894
2146
|
JoinGiftClaim,
|
|
1895
2147
|
{
|
|
1896
2148
|
api: props.giftClaimApi,
|
|
@@ -1901,17 +2153,15 @@ function JoinFlow(props) {
|
|
|
1901
2153
|
onError: () => setError(copy.form.unexpectedFailure)
|
|
1902
2154
|
}
|
|
1903
2155
|
) : null,
|
|
1904
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsx27(
|
|
1905
2157
|
Payment,
|
|
1906
2158
|
{
|
|
1907
2159
|
applicationId: state.applicationId,
|
|
1908
2160
|
refundPolicyText: config.refundPolicyText ?? "",
|
|
1909
2161
|
merchantDisclosureText: config.merchantDisclosureText,
|
|
1910
2162
|
copy: copy.payment,
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
fonts: props.payment?.fonts,
|
|
1914
|
-
renderPriceLines: props.payment?.renderPriceLines,
|
|
2163
|
+
...props.payment,
|
|
2164
|
+
onNamedSeatEditingChange: setEditingNamedSeat,
|
|
1915
2165
|
simulation: simulatedPayment,
|
|
1916
2166
|
onPaid: (result) => {
|
|
1917
2167
|
if (props.simulation) {
|
|
@@ -1931,9 +2181,9 @@ function JoinFlow(props) {
|
|
|
1931
2181
|
}
|
|
1932
2182
|
if (state.step === "paymentPending") {
|
|
1933
2183
|
if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
|
|
1934
|
-
return /* @__PURE__ */
|
|
2184
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1935
2185
|
header,
|
|
1936
|
-
/* @__PURE__ */
|
|
2186
|
+
/* @__PURE__ */ jsx27(
|
|
1937
2187
|
JoinNamedSeat,
|
|
1938
2188
|
{
|
|
1939
2189
|
api: props.namedSeatClaimApi,
|
|
@@ -1945,14 +2195,14 @@ function JoinFlow(props) {
|
|
|
1945
2195
|
)
|
|
1946
2196
|
] });
|
|
1947
2197
|
}
|
|
1948
|
-
return /* @__PURE__ */
|
|
2198
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1949
2199
|
header,
|
|
1950
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ jsx27("p", { className: "pay-status", role: "status", children: copy.payment.pending })
|
|
1951
2201
|
] });
|
|
1952
2202
|
}
|
|
1953
|
-
return /* @__PURE__ */
|
|
2203
|
+
return /* @__PURE__ */ jsxs26(Fragment10, { children: [
|
|
1954
2204
|
header,
|
|
1955
|
-
/* @__PURE__ */
|
|
2205
|
+
/* @__PURE__ */ jsx27(
|
|
1956
2206
|
JoinApplicationForm,
|
|
1957
2207
|
{
|
|
1958
2208
|
props,
|
|
@@ -2142,7 +2392,7 @@ function membershipPageDocument(input, options = {}) {
|
|
|
2142
2392
|
}
|
|
2143
2393
|
|
|
2144
2394
|
// src/ui/membership-cards.tsx
|
|
2145
|
-
import { jsx as
|
|
2395
|
+
import { jsx as jsx28, jsxs as jsxs27 } from "preact/jsx-runtime";
|
|
2146
2396
|
var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
|
|
2147
2397
|
"--ui-membership-grid-gap": "1.4rem",
|
|
2148
2398
|
"--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
|
|
@@ -2211,67 +2461,67 @@ function membershipApplicationHref(applicationPath, tierId) {
|
|
|
2211
2461
|
}
|
|
2212
2462
|
function TierAction(props) {
|
|
2213
2463
|
if (props.mode === "select") {
|
|
2214
|
-
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: [
|
|
2215
2465
|
props.label,
|
|
2216
|
-
/* @__PURE__ */
|
|
2466
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2217
2467
|
] });
|
|
2218
2468
|
}
|
|
2219
2469
|
if (props.mode === "preview") {
|
|
2220
|
-
return /* @__PURE__ */
|
|
2470
|
+
return /* @__PURE__ */ jsxs27("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
|
|
2221
2471
|
props.label,
|
|
2222
|
-
/* @__PURE__ */
|
|
2472
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2223
2473
|
] });
|
|
2224
2474
|
}
|
|
2225
|
-
return /* @__PURE__ */
|
|
2475
|
+
return /* @__PURE__ */ jsxs27("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
|
|
2226
2476
|
props.label,
|
|
2227
|
-
/* @__PURE__ */
|
|
2477
|
+
/* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2228
2478
|
] });
|
|
2229
2479
|
}
|
|
2230
2480
|
function TierCard(props) {
|
|
2231
2481
|
const { tier, presentation } = props;
|
|
2232
2482
|
const summary = presentation.summaryMarkdown ?? tier.blurb;
|
|
2233
2483
|
const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
|
|
2234
|
-
return /* @__PURE__ */
|
|
2235
|
-
presentation.badge ? /* @__PURE__ */
|
|
2236
|
-
/* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
presentation.capacity ? /* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2240
|
-
/* @__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" })
|
|
2241
2491
|
] }) : null,
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
presentation.priceEyebrow ? /* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
tier.founding ? /* @__PURE__ */
|
|
2246
|
-
/* @__PURE__ */
|
|
2247
|
-
!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
|
|
2248
2498
|
] })
|
|
2249
2499
|
] })
|
|
2250
2500
|
] }),
|
|
2251
|
-
presentation.priceNoteMarkdown ? /* @__PURE__ */
|
|
2252
|
-
summary ? /* @__PURE__ */
|
|
2253
|
-
presentation.benefits?.length ? /* @__PURE__ */
|
|
2254
|
-
/* @__PURE__ */
|
|
2255
|
-
/* @__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 })
|
|
2256
2506
|
] }, `${tier.id}-benefit-${index}`)) }) : null,
|
|
2257
|
-
presentation.callout ? /* @__PURE__ */
|
|
2258
|
-
presentation.callout.label ? /* @__PURE__ */
|
|
2259
|
-
/* @__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 })
|
|
2260
2510
|
] }) : null,
|
|
2261
|
-
/* @__PURE__ */
|
|
2511
|
+
/* @__PURE__ */ jsx28(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
|
|
2262
2512
|
] });
|
|
2263
2513
|
}
|
|
2264
2514
|
function MembershipCards(props) {
|
|
2265
2515
|
const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
|
|
2266
2516
|
const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
|
|
2267
2517
|
const mode = props.mode ?? "link";
|
|
2268
|
-
return /* @__PURE__ */
|
|
2269
|
-
/* @__PURE__ */
|
|
2270
|
-
/* @__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) => {
|
|
2271
2521
|
const tier = byId.get(presentation.tierId);
|
|
2272
|
-
return /* @__PURE__ */
|
|
2522
|
+
return /* @__PURE__ */ jsx28(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
|
|
2273
2523
|
}) }),
|
|
2274
|
-
document2.footnoteMarkdown ? /* @__PURE__ */
|
|
2524
|
+
document2.footnoteMarkdown ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
|
|
2275
2525
|
] });
|
|
2276
2526
|
}
|
|
2277
2527
|
|
|
@@ -2285,6 +2535,11 @@ export {
|
|
|
2285
2535
|
fmtDate,
|
|
2286
2536
|
groupSlotsByDay,
|
|
2287
2537
|
SlotPicker,
|
|
2538
|
+
ADDITIONAL_MEMBER_COPY,
|
|
2539
|
+
additionalMemberSelection,
|
|
2540
|
+
AdditionalMemberFields,
|
|
2541
|
+
JoinSubmitButton,
|
|
2542
|
+
AdditionalMemberEditor,
|
|
2288
2543
|
PaymentStep,
|
|
2289
2544
|
JourneyFrame,
|
|
2290
2545
|
MemberRestart,
|
|
@@ -2307,4 +2562,4 @@ export {
|
|
|
2307
2562
|
membershipApplicationHref,
|
|
2308
2563
|
MembershipCards
|
|
2309
2564
|
};
|
|
2310
|
-
//# sourceMappingURL=chunk-
|
|
2565
|
+
//# sourceMappingURL=chunk-E7CB5K2D.js.map
|