@burdenoff/microfe-atheletebridge 2026.1031.3 → 2026.1102.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/atheletebridge/AthleteBridgeRoot.d.ts.map +1 -1
  2. package/dist/atheletebridge/AthleteBridgeRoot.js +63 -47
  3. package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
  4. package/dist/atheletebridge/AthleteBridgeRoutes.d.ts.map +1 -1
  5. package/dist/atheletebridge/AthleteBridgeRoutes.js +62 -6
  6. package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
  7. package/dist/atheletebridge/components/StatusBadge.d.ts.map +1 -1
  8. package/dist/atheletebridge/components/StatusBadge.js +13 -1
  9. package/dist/atheletebridge/components/StatusBadge.js.map +1 -1
  10. package/dist/atheletebridge/components/registration/PaymentSummaryPanel.d.ts +6 -0
  11. package/dist/atheletebridge/components/registration/PaymentSummaryPanel.d.ts.map +1 -0
  12. package/dist/atheletebridge/components/registration/PaymentSummaryPanel.js +104 -0
  13. package/dist/atheletebridge/components/registration/PaymentSummaryPanel.js.map +1 -0
  14. package/dist/atheletebridge/components/registration/RegistrationEntryFields.d.ts +15 -0
  15. package/dist/atheletebridge/components/registration/RegistrationEntryFields.d.ts.map +1 -0
  16. package/dist/atheletebridge/components/registration/RegistrationEntryFields.js +236 -0
  17. package/dist/atheletebridge/components/registration/RegistrationEntryFields.js.map +1 -0
  18. package/dist/atheletebridge/components/registration/entryRules.d.ts +23 -0
  19. package/dist/atheletebridge/components/registration/entryRules.d.ts.map +1 -0
  20. package/dist/atheletebridge/components/registration/entryRules.js +29 -0
  21. package/dist/atheletebridge/components/registration/entryRules.js.map +1 -0
  22. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts +1 -0
  23. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts.map +1 -1
  24. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +1 -1
  25. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  26. package/dist/atheletebridge/hooks/useRegistrationApi.d.ts +54 -0
  27. package/dist/atheletebridge/hooks/useRegistrationApi.d.ts.map +1 -0
  28. package/dist/atheletebridge/hooks/useRegistrationApi.js +265 -0
  29. package/dist/atheletebridge/hooks/useRegistrationApi.js.map +1 -0
  30. package/dist/atheletebridge/pages/registrations/MyRegistrationsPage.d.ts +10 -0
  31. package/dist/atheletebridge/pages/registrations/MyRegistrationsPage.d.ts.map +1 -0
  32. package/dist/atheletebridge/pages/registrations/MyRegistrationsPage.js +89 -0
  33. package/dist/atheletebridge/pages/registrations/MyRegistrationsPage.js.map +1 -0
  34. package/dist/atheletebridge/pages/registrations/RecordRegistrationPage.d.ts +10 -0
  35. package/dist/atheletebridge/pages/registrations/RecordRegistrationPage.d.ts.map +1 -0
  36. package/dist/atheletebridge/pages/registrations/RecordRegistrationPage.js +94 -0
  37. package/dist/atheletebridge/pages/registrations/RecordRegistrationPage.js.map +1 -0
  38. package/dist/atheletebridge/pages/registrations/RegisterPage.d.ts +11 -0
  39. package/dist/atheletebridge/pages/registrations/RegisterPage.d.ts.map +1 -0
  40. package/dist/atheletebridge/pages/registrations/RegisterPage.js +160 -0
  41. package/dist/atheletebridge/pages/registrations/RegisterPage.js.map +1 -0
  42. package/dist/atheletebridge/pages/registrations/RegistrationFormBuilderPage.d.ts +10 -0
  43. package/dist/atheletebridge/pages/registrations/RegistrationFormBuilderPage.d.ts.map +1 -0
  44. package/dist/atheletebridge/pages/registrations/RegistrationFormBuilderPage.js +602 -0
  45. package/dist/atheletebridge/pages/registrations/RegistrationFormBuilderPage.js.map +1 -0
  46. package/dist/atheletebridge/pages/registrations/RegistrationFormDetailPage.d.ts +9 -0
  47. package/dist/atheletebridge/pages/registrations/RegistrationFormDetailPage.d.ts.map +1 -0
  48. package/dist/atheletebridge/pages/registrations/RegistrationFormDetailPage.js +317 -0
  49. package/dist/atheletebridge/pages/registrations/RegistrationFormDetailPage.js.map +1 -0
  50. package/dist/atheletebridge/pages/registrations/RegistrationFormsListPage.d.ts +9 -0
  51. package/dist/atheletebridge/pages/registrations/RegistrationFormsListPage.d.ts.map +1 -0
  52. package/dist/atheletebridge/pages/registrations/RegistrationFormsListPage.js +127 -0
  53. package/dist/atheletebridge/pages/registrations/RegistrationFormsListPage.js.map +1 -0
  54. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.d.ts +11 -0
  55. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.d.ts.map +1 -0
  56. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.js +411 -0
  57. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.js.map +1 -0
  58. package/dist/atheletebridge/types/registration.d.ts +220 -0
  59. package/dist/atheletebridge/types/registration.d.ts.map +1 -0
  60. package/dist/atheletebridge/utils/money.d.ts +22 -0
  61. package/dist/atheletebridge/utils/money.d.ts.map +1 -0
  62. package/dist/atheletebridge/utils/money.js +38 -0
  63. package/dist/atheletebridge/utils/money.js.map +1 -0
  64. package/dist/atheletebridge/utils/registration.d.ts +17 -0
  65. package/dist/atheletebridge/utils/registration.d.ts.map +1 -0
  66. package/dist/atheletebridge/utils/registration.js +25 -0
  67. package/dist/atheletebridge/utils/registration.js.map +1 -0
  68. package/package.json +1 -1
@@ -0,0 +1,602 @@
1
+ import { useAthleteBridge as e } from "../../context/AthleteBridgeContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { ErrorState as n, LoadingState as r } from "../../components/LoadingState.js";
4
+ import { useTeams as i } from "../../hooks/useAthleteBridgeApi.js";
5
+ import { FormField as a, fieldInputClass as o } from "../../components/form.js";
6
+ import { useCreateRegistrationForm as s, useRegistrationForm as c, useUpdateRegistrationForm as l } from "../../hooks/useRegistrationApi.js";
7
+ import { minorToInput as u, parseMoney as d } from "../../utils/money.js";
8
+ import { keyFromLabel as f } from "../../utils/registration.js";
9
+ import { useEffect as p, useRef as m, useState as h } from "react";
10
+ import { ArrowDown as g, ArrowLeft as _, ArrowUp as v, Loader2 as y, Plus as b, Save as x, Trash2 as S } from "lucide-react";
11
+ import { useParams as C } from "react-router";
12
+ import { jsx as w, jsxs as T } from "react/jsx-runtime";
13
+ //#region src/atheletebridge/pages/registrations/RegistrationFormBuilderPage.tsx
14
+ var E = {
15
+ SHORT_TEXT: "Short text",
16
+ LONG_TEXT: "Paragraph",
17
+ EMAIL: "Email",
18
+ PHONE: "Phone",
19
+ NUMBER: "Number",
20
+ DATE: "Date",
21
+ SELECT: "Dropdown",
22
+ CHECKBOX: "Checkbox (yes / consent)"
23
+ }, D = [
24
+ "USD",
25
+ "INR",
26
+ "GBP",
27
+ "EUR",
28
+ "AUD",
29
+ "CAD",
30
+ "SGD",
31
+ "AED"
32
+ ], O = () => `draft-${crypto.randomUUID()}`, k = {
33
+ title: "",
34
+ description: "",
35
+ season: "",
36
+ teamId: "",
37
+ slug: "",
38
+ currency: "USD",
39
+ opensAt: "",
40
+ closesAt: "",
41
+ maxSubmissions: "",
42
+ waiverText: "",
43
+ questions: [],
44
+ fees: []
45
+ };
46
+ function A(e) {
47
+ if (!e) return "";
48
+ let t = new Date(e), n = t.getTimezoneOffset() * 6e4;
49
+ return new Date(t.getTime() - n).toISOString().slice(0, 16);
50
+ }
51
+ function j(e) {
52
+ return e ? new Date(e).toISOString() : void 0;
53
+ }
54
+ function M(e) {
55
+ return {
56
+ title: e.title,
57
+ description: e.description ?? "",
58
+ season: e.season ?? "",
59
+ teamId: e.teamId ?? "",
60
+ slug: e.slug,
61
+ currency: e.currency,
62
+ opensAt: A(e.opensAt),
63
+ closesAt: A(e.closesAt),
64
+ maxSubmissions: e.maxSubmissions == null ? "" : String(e.maxSubmissions),
65
+ waiverText: e.waiverText ?? "",
66
+ questions: e.fields.map((e) => ({
67
+ uid: O(),
68
+ key: e.key,
69
+ label: e.label,
70
+ fieldType: e.fieldType,
71
+ required: e.required,
72
+ optionsText: e.options.join(", "),
73
+ helpText: e.helpText ?? ""
74
+ })),
75
+ fees: e.fees.map((t) => ({
76
+ uid: O(),
77
+ name: t.name,
78
+ amountText: u(t.amount, e.currency),
79
+ feeType: t.feeType,
80
+ description: t.description ?? ""
81
+ }))
82
+ };
83
+ }
84
+ function N(e, t, n) {
85
+ let r = t + n;
86
+ if (r < 0 || r >= e.length) return e;
87
+ let i = [...e], [a] = i.splice(t, 1);
88
+ return a !== void 0 && i.splice(r, 0, a), i;
89
+ }
90
+ var P = "inline-flex h-8 w-8 items-center justify-center rounded-md border border-border-seam text-text-secondary transition-colors hover:bg-bg-sunken disabled:opacity-40";
91
+ function F() {
92
+ let { id: u } = C(), A = !!u, { navigateTo: F } = e(), I = c(u), L = i({ pagination: { limit: 100 } }), R = s(), z = l(), [B, V] = h(k), [H, U] = h(null), W = m(null);
93
+ p(() => {
94
+ A && I.data && W.current !== I.data.id && (W.current = I.data.id, V(M(I.data)));
95
+ }, [A, I.data]);
96
+ let G = A && (I.data?.submissionCount ?? 0) > 0, K = (e, t) => V((n) => ({
97
+ ...n,
98
+ [e]: t
99
+ })), q = (e, t) => K("questions", B.questions.map((n) => n.uid === e ? {
100
+ ...n,
101
+ ...t
102
+ } : n)), J = (e, t) => K("fees", B.fees.map((n) => n.uid === e ? {
103
+ ...n,
104
+ ...t
105
+ } : n)), Y = () => {
106
+ let e = new Set(B.questions.map((e) => e.key).filter(Boolean)), t = [];
107
+ for (let n of B.questions) {
108
+ let r = n.label.trim();
109
+ if (!r) return "Every question needs a label.";
110
+ let i = n.key || f(r, e);
111
+ e.add(i);
112
+ let a = n.optionsText.split(",").map((e) => e.trim()).filter(Boolean);
113
+ if (n.fieldType === "SELECT" && a.length === 0) return `Add at least one option to the dropdown "${r}".`;
114
+ t.push({
115
+ key: i,
116
+ label: r,
117
+ fieldType: n.fieldType,
118
+ required: n.required,
119
+ options: n.fieldType === "SELECT" ? a : void 0,
120
+ helpText: n.helpText.trim() || void 0
121
+ });
122
+ }
123
+ let n = [];
124
+ for (let e of B.fees) {
125
+ let t = e.name.trim();
126
+ if (!t) return "Every fee needs a name.";
127
+ let r = d(e.amountText, B.currency);
128
+ if (r === null) return `Enter a valid amount for "${t}".`;
129
+ n.push({
130
+ name: t,
131
+ amount: r,
132
+ feeType: e.feeType,
133
+ description: e.description.trim() || void 0
134
+ });
135
+ }
136
+ return {
137
+ fields: t,
138
+ fees: n
139
+ };
140
+ }, X = async (e) => {
141
+ if (e.preventDefault(), U(null), !B.title.trim()) {
142
+ U("Give the form a title.");
143
+ return;
144
+ }
145
+ let t = B.maxSubmissions.trim() ? Number.parseInt(B.maxSubmissions, 10) : void 0;
146
+ if (t !== void 0 && (Number.isNaN(t) || t < 1)) {
147
+ U("Capacity must be a positive number.");
148
+ return;
149
+ }
150
+ let n = G ? null : Y();
151
+ if (typeof n == "string") {
152
+ U(n);
153
+ return;
154
+ }
155
+ try {
156
+ A && u ? (await z.mutateAsync({
157
+ id: u,
158
+ input: {
159
+ title: B.title.trim(),
160
+ description: B.description.trim() || null,
161
+ season: B.season.trim() || null,
162
+ teamId: B.teamId || null,
163
+ opensAt: j(B.opensAt) ?? null,
164
+ closesAt: j(B.closesAt) ?? null,
165
+ maxSubmissions: t ?? null,
166
+ waiverText: B.waiverText.trim() || null,
167
+ ...n ? {
168
+ currency: B.currency,
169
+ fields: n.fields,
170
+ fees: n.fees
171
+ } : {}
172
+ }
173
+ }), F(`/registrations/${u}`)) : n && F(`/registrations/${(await R.mutateAsync({
174
+ title: B.title.trim(),
175
+ description: B.description.trim() || void 0,
176
+ season: B.season.trim() || void 0,
177
+ teamId: B.teamId || void 0,
178
+ slug: B.slug.trim() || void 0,
179
+ currency: B.currency,
180
+ opensAt: j(B.opensAt),
181
+ closesAt: j(B.closesAt),
182
+ maxSubmissions: t,
183
+ waiverText: B.waiverText.trim() || void 0,
184
+ fields: n.fields,
185
+ fees: n.fees
186
+ })).id}`);
187
+ } catch (e) {
188
+ U(e instanceof Error ? e.message : "Failed to save the registration form.");
189
+ }
190
+ }, Z = R.isPending || z.isPending, Q = A ? "Edit registration form" : "New registration form";
191
+ return A && I.isLoading ? /* @__PURE__ */ w(t, {
192
+ title: Q,
193
+ children: /* @__PURE__ */ w(r, { label: "Loading registration form…" })
194
+ }) : A && (I.isError || !I.data) ? /* @__PURE__ */ w(t, {
195
+ title: Q,
196
+ children: /* @__PURE__ */ w(n, {
197
+ title: "Registration form not found",
198
+ message: "This form does not exist or you do not have access to it.",
199
+ onRetry: () => F("/registrations")
200
+ })
201
+ }) : /* @__PURE__ */ w(t, {
202
+ title: Q,
203
+ description: "Set the details, the questions families answer and the fees they pay.",
204
+ actions: /* @__PURE__ */ T("button", {
205
+ type: "button",
206
+ onClick: () => F(A && u ? `/registrations/${u}` : "/registrations"),
207
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
208
+ children: [/* @__PURE__ */ w(_, { className: "h-4 w-4" }), " Cancel"]
209
+ }),
210
+ children: /* @__PURE__ */ T("form", {
211
+ onSubmit: X,
212
+ className: "max-w-3xl space-y-8",
213
+ children: [
214
+ /* @__PURE__ */ T("section", {
215
+ className: "space-y-5",
216
+ children: [
217
+ /* @__PURE__ */ w(a, {
218
+ label: "Form title",
219
+ htmlFor: "title",
220
+ required: !0,
221
+ children: /* @__PURE__ */ w("input", {
222
+ id: "title",
223
+ className: o,
224
+ value: B.title,
225
+ onChange: (e) => K("title", e.target.value),
226
+ placeholder: "e.g. U12 Boys — 2026/27 season registration"
227
+ })
228
+ }),
229
+ /* @__PURE__ */ w(a, {
230
+ label: "Description",
231
+ htmlFor: "description",
232
+ children: /* @__PURE__ */ w("textarea", {
233
+ id: "description",
234
+ rows: 3,
235
+ className: o,
236
+ value: B.description,
237
+ onChange: (e) => K("description", e.target.value),
238
+ placeholder: "Who this is for, training days, what is included."
239
+ })
240
+ }),
241
+ /* @__PURE__ */ T("div", {
242
+ className: "grid grid-cols-1 gap-5 sm:grid-cols-3",
243
+ children: [
244
+ /* @__PURE__ */ w(a, {
245
+ label: "Season",
246
+ htmlFor: "season",
247
+ children: /* @__PURE__ */ w("input", {
248
+ id: "season",
249
+ className: o,
250
+ value: B.season,
251
+ onChange: (e) => K("season", e.target.value),
252
+ placeholder: "2026/27"
253
+ })
254
+ }),
255
+ /* @__PURE__ */ w(a, {
256
+ label: "Team",
257
+ htmlFor: "teamId",
258
+ hint: "Optional squad this registers for.",
259
+ children: /* @__PURE__ */ T("select", {
260
+ id: "teamId",
261
+ className: o,
262
+ value: B.teamId,
263
+ onChange: (e) => K("teamId", e.target.value),
264
+ children: [/* @__PURE__ */ w("option", {
265
+ value: "",
266
+ children: "No specific team"
267
+ }), (L.data?.items ?? []).map((e) => /* @__PURE__ */ w("option", {
268
+ value: e.id,
269
+ children: e.name
270
+ }, e.id))]
271
+ })
272
+ }),
273
+ /* @__PURE__ */ w(a, {
274
+ label: "Currency",
275
+ htmlFor: "currency",
276
+ hint: G ? "Locked after the first registration." : void 0,
277
+ children: /* @__PURE__ */ w("select", {
278
+ id: "currency",
279
+ className: o,
280
+ value: B.currency,
281
+ disabled: G,
282
+ onChange: (e) => K("currency", e.target.value),
283
+ children: [...new Set([B.currency, ...D])].map((e) => /* @__PURE__ */ w("option", {
284
+ value: e,
285
+ children: e
286
+ }, e))
287
+ })
288
+ })
289
+ ]
290
+ }),
291
+ /* @__PURE__ */ T("div", {
292
+ className: "grid grid-cols-1 gap-5 sm:grid-cols-3",
293
+ children: [
294
+ /* @__PURE__ */ w(a, {
295
+ label: "Opens",
296
+ htmlFor: "opensAt",
297
+ hint: "Leave empty to open on publish.",
298
+ children: /* @__PURE__ */ w("input", {
299
+ id: "opensAt",
300
+ type: "datetime-local",
301
+ className: o,
302
+ value: B.opensAt,
303
+ onChange: (e) => K("opensAt", e.target.value)
304
+ })
305
+ }),
306
+ /* @__PURE__ */ w(a, {
307
+ label: "Closes",
308
+ htmlFor: "closesAt",
309
+ hint: "Leave empty to close manually.",
310
+ children: /* @__PURE__ */ w("input", {
311
+ id: "closesAt",
312
+ type: "datetime-local",
313
+ className: o,
314
+ value: B.closesAt,
315
+ onChange: (e) => K("closesAt", e.target.value)
316
+ })
317
+ }),
318
+ /* @__PURE__ */ w(a, {
319
+ label: "Capacity",
320
+ htmlFor: "maxSubmissions",
321
+ hint: "Maximum registrations.",
322
+ children: /* @__PURE__ */ w("input", {
323
+ id: "maxSubmissions",
324
+ inputMode: "numeric",
325
+ className: o,
326
+ value: B.maxSubmissions,
327
+ onChange: (e) => K("maxSubmissions", e.target.value),
328
+ placeholder: "Unlimited"
329
+ })
330
+ })
331
+ ]
332
+ }),
333
+ !A && /* @__PURE__ */ w(a, {
334
+ label: "Share-link name",
335
+ htmlFor: "slug",
336
+ hint: "Optional. Lowercase letters, digits and dashes. Generated from the title when empty.",
337
+ children: /* @__PURE__ */ w("input", {
338
+ id: "slug",
339
+ className: o,
340
+ value: B.slug,
341
+ onChange: (e) => K("slug", e.target.value),
342
+ placeholder: "u12-boys-2026"
343
+ })
344
+ })
345
+ ]
346
+ }),
347
+ /* @__PURE__ */ T("section", {
348
+ className: "space-y-3",
349
+ "aria-labelledby": "builder-questions",
350
+ children: [
351
+ /* @__PURE__ */ T("div", {
352
+ className: "flex items-center justify-between",
353
+ children: [/* @__PURE__ */ w("h2", {
354
+ id: "builder-questions",
355
+ className: "text-base font-semibold text-text-primary",
356
+ children: "Questions"
357
+ }), /* @__PURE__ */ T("button", {
358
+ type: "button",
359
+ disabled: G,
360
+ onClick: () => K("questions", [...B.questions, {
361
+ uid: O(),
362
+ key: "",
363
+ label: "",
364
+ fieldType: "SHORT_TEXT",
365
+ required: !1,
366
+ optionsText: "",
367
+ helpText: ""
368
+ }]),
369
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50",
370
+ children: [/* @__PURE__ */ w(b, { className: "h-4 w-4" }), " Add question"]
371
+ })]
372
+ }),
373
+ /* @__PURE__ */ T("p", {
374
+ className: "text-xs text-text-secondary",
375
+ children: ["Participant name and contact details are always collected.", G && " Questions are locked because this form already has registrations."]
376
+ }),
377
+ B.questions.map((e, t) => /* @__PURE__ */ T("div", {
378
+ className: "space-y-3 rounded-lg border border-border-seam bg-bg-surface p-4",
379
+ "data-testid": "builder-question",
380
+ children: [
381
+ /* @__PURE__ */ T("div", {
382
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-[1fr_12rem]",
383
+ children: [/* @__PURE__ */ w(a, {
384
+ label: `Question ${t + 1}`,
385
+ htmlFor: `q-label-${e.uid}`,
386
+ children: /* @__PURE__ */ w("input", {
387
+ id: `q-label-${e.uid}`,
388
+ className: o,
389
+ value: e.label,
390
+ disabled: G,
391
+ onChange: (t) => q(e.uid, { label: t.target.value }),
392
+ placeholder: "e.g. Date of birth"
393
+ })
394
+ }), /* @__PURE__ */ w(a, {
395
+ label: "Answer type",
396
+ htmlFor: `q-type-${e.uid}`,
397
+ children: /* @__PURE__ */ w("select", {
398
+ id: `q-type-${e.uid}`,
399
+ className: o,
400
+ value: e.fieldType,
401
+ disabled: G,
402
+ onChange: (t) => q(e.uid, { fieldType: t.target.value }),
403
+ children: Object.keys(E).map((e) => /* @__PURE__ */ w("option", {
404
+ value: e,
405
+ children: E[e]
406
+ }, e))
407
+ })
408
+ })]
409
+ }),
410
+ e.fieldType === "SELECT" && /* @__PURE__ */ w(a, {
411
+ label: "Options",
412
+ htmlFor: `q-options-${e.uid}`,
413
+ hint: "Comma-separated.",
414
+ children: /* @__PURE__ */ w("input", {
415
+ id: `q-options-${e.uid}`,
416
+ className: o,
417
+ value: e.optionsText,
418
+ disabled: G,
419
+ onChange: (t) => q(e.uid, { optionsText: t.target.value }),
420
+ placeholder: "XS, S, M, L"
421
+ })
422
+ }),
423
+ /* @__PURE__ */ w(a, {
424
+ label: "Help text",
425
+ htmlFor: `q-help-${e.uid}`,
426
+ children: /* @__PURE__ */ w("input", {
427
+ id: `q-help-${e.uid}`,
428
+ className: o,
429
+ value: e.helpText,
430
+ disabled: G,
431
+ onChange: (t) => q(e.uid, { helpText: t.target.value })
432
+ })
433
+ }),
434
+ /* @__PURE__ */ T("div", {
435
+ className: "flex flex-wrap items-center justify-between gap-3",
436
+ children: [/* @__PURE__ */ T("label", {
437
+ className: "flex items-center gap-2 text-sm text-text-primary",
438
+ children: [/* @__PURE__ */ w("input", {
439
+ type: "checkbox",
440
+ checked: e.required,
441
+ disabled: G,
442
+ onChange: (t) => q(e.uid, { required: t.target.checked }),
443
+ className: "h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]"
444
+ }), "Required"]
445
+ }), /* @__PURE__ */ T("span", {
446
+ className: "flex gap-2",
447
+ children: [
448
+ /* @__PURE__ */ w("button", {
449
+ type: "button",
450
+ "aria-label": "Move question up",
451
+ className: P,
452
+ disabled: G || t === 0,
453
+ onClick: () => K("questions", N(B.questions, t, -1)),
454
+ children: /* @__PURE__ */ w(v, { className: "h-4 w-4" })
455
+ }),
456
+ /* @__PURE__ */ w("button", {
457
+ type: "button",
458
+ "aria-label": "Move question down",
459
+ className: P,
460
+ disabled: G || t === B.questions.length - 1,
461
+ onClick: () => K("questions", N(B.questions, t, 1)),
462
+ children: /* @__PURE__ */ w(g, { className: "h-4 w-4" })
463
+ }),
464
+ /* @__PURE__ */ w("button", {
465
+ type: "button",
466
+ "aria-label": "Remove question",
467
+ className: P,
468
+ disabled: G,
469
+ onClick: () => K("questions", B.questions.filter((t) => t.uid !== e.uid)),
470
+ children: /* @__PURE__ */ w(S, { className: "h-4 w-4" })
471
+ })
472
+ ]
473
+ })]
474
+ })
475
+ ]
476
+ }, e.uid))
477
+ ]
478
+ }),
479
+ /* @__PURE__ */ T("section", {
480
+ className: "space-y-3",
481
+ "aria-labelledby": "builder-fees",
482
+ children: [
483
+ /* @__PURE__ */ T("div", {
484
+ className: "flex items-center justify-between",
485
+ children: [/* @__PURE__ */ w("h2", {
486
+ id: "builder-fees",
487
+ className: "text-base font-semibold text-text-primary",
488
+ children: "Fees"
489
+ }), /* @__PURE__ */ T("button", {
490
+ type: "button",
491
+ disabled: G,
492
+ onClick: () => K("fees", [...B.fees, {
493
+ uid: O(),
494
+ name: "",
495
+ amountText: "",
496
+ feeType: "REQUIRED",
497
+ description: ""
498
+ }]),
499
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50",
500
+ children: [/* @__PURE__ */ w(b, { className: "h-4 w-4" }), " Add fee"]
501
+ })]
502
+ }),
503
+ /* @__PURE__ */ w("p", {
504
+ className: "text-xs text-text-secondary",
505
+ children: "Required fees are charged on every registration; optional ones (kit, tournament entry) are opt-in. Payments are recorded by the club office as they arrive."
506
+ }),
507
+ B.fees.map((e) => /* @__PURE__ */ T("div", {
508
+ className: "grid grid-cols-1 gap-3 rounded-lg border border-border-seam bg-bg-surface p-4 sm:grid-cols-[1fr_9rem_9rem_auto]",
509
+ "data-testid": "builder-fee",
510
+ children: [
511
+ /* @__PURE__ */ w(a, {
512
+ label: "Fee name",
513
+ htmlFor: `f-name-${e.uid}`,
514
+ children: /* @__PURE__ */ w("input", {
515
+ id: `f-name-${e.uid}`,
516
+ className: o,
517
+ value: e.name,
518
+ disabled: G,
519
+ onChange: (t) => J(e.uid, { name: t.target.value }),
520
+ placeholder: "Membership"
521
+ })
522
+ }),
523
+ /* @__PURE__ */ w(a, {
524
+ label: `Amount (${B.currency})`,
525
+ htmlFor: `f-amount-${e.uid}`,
526
+ children: /* @__PURE__ */ w("input", {
527
+ id: `f-amount-${e.uid}`,
528
+ inputMode: "decimal",
529
+ className: o,
530
+ value: e.amountText,
531
+ disabled: G,
532
+ onChange: (t) => J(e.uid, { amountText: t.target.value }),
533
+ placeholder: "150.00"
534
+ })
535
+ }),
536
+ /* @__PURE__ */ w(a, {
537
+ label: "Type",
538
+ htmlFor: `f-type-${e.uid}`,
539
+ children: /* @__PURE__ */ T("select", {
540
+ id: `f-type-${e.uid}`,
541
+ className: o,
542
+ value: e.feeType,
543
+ disabled: G,
544
+ onChange: (t) => J(e.uid, { feeType: t.target.value }),
545
+ children: [/* @__PURE__ */ w("option", {
546
+ value: "REQUIRED",
547
+ children: "Required"
548
+ }), /* @__PURE__ */ w("option", {
549
+ value: "OPTIONAL",
550
+ children: "Optional"
551
+ })]
552
+ })
553
+ }),
554
+ /* @__PURE__ */ w("div", {
555
+ className: "flex items-end",
556
+ children: /* @__PURE__ */ w("button", {
557
+ type: "button",
558
+ "aria-label": "Remove fee",
559
+ className: P,
560
+ disabled: G,
561
+ onClick: () => K("fees", B.fees.filter((t) => t.uid !== e.uid)),
562
+ children: /* @__PURE__ */ w(S, { className: "h-4 w-4" })
563
+ })
564
+ })
565
+ ]
566
+ }, e.uid))
567
+ ]
568
+ }),
569
+ /* @__PURE__ */ w("section", { children: /* @__PURE__ */ w(a, {
570
+ label: "Waiver / consent",
571
+ htmlFor: "waiverText",
572
+ hint: "Optional. When set, registrants must accept it to submit.",
573
+ children: /* @__PURE__ */ w("textarea", {
574
+ id: "waiverText",
575
+ rows: 4,
576
+ className: o,
577
+ value: B.waiverText,
578
+ onChange: (e) => K("waiverText", e.target.value)
579
+ })
580
+ }) }),
581
+ H && /* @__PURE__ */ w("p", {
582
+ role: "alert",
583
+ className: "text-sm text-status-error-text",
584
+ children: H
585
+ }),
586
+ /* @__PURE__ */ w("div", {
587
+ className: "pt-2",
588
+ children: /* @__PURE__ */ T("button", {
589
+ type: "submit",
590
+ disabled: Z,
591
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-60",
592
+ children: [Z ? /* @__PURE__ */ w(y, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ w(x, { className: "h-4 w-4" }), A ? "Save changes" : "Create form"]
593
+ })
594
+ })
595
+ ]
596
+ })
597
+ });
598
+ }
599
+ //#endregion
600
+ export { F as RegistrationFormBuilderPage };
601
+
602
+ //# sourceMappingURL=RegistrationFormBuilderPage.js.map