@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,11 @@
1
+ /**
2
+ * Registration submission detail (club staff)
3
+ * @module atheletebridge/pages/registrations
4
+ *
5
+ * One registration: the participant's answers, the accept / decline review
6
+ * and the payment ledger — record a payment as it arrives, void one recorded
7
+ * in error, or record a refund (BOFF-4135). The ledger panel only renders for
8
+ * staff who can read payments.
9
+ */
10
+ export declare function RegistrationSubmissionPage(): import("react").JSX.Element;
11
+ //# sourceMappingURL=RegistrationSubmissionPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistrationSubmissionPage.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/pages/registrations/RegistrationSubmissionPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuUH,wBAAgB,0BAA0B,gCAkIzC"}
@@ -0,0 +1,411 @@
1
+ import { useAthleteBridge as e } from "../../context/AthleteBridgeContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { StatusBadge as n } from "../../components/StatusBadge.js";
4
+ import { formatDate as r } from "../../utils/formatters.js";
5
+ import { ErrorState as i, LoadingState as a } from "../../components/LoadingState.js";
6
+ import { FormField as o, fieldInputClass as s } from "../../components/form.js";
7
+ import { useRecordRegistrationPayment as c, useRefundRegistrationPayment as l, useRegistrationForm as u, useRegistrationPayments as d, useRegistrationSubmission as f, useReviewRegistration as p, useVoidRegistrationPayment as m } from "../../hooks/useRegistrationApi.js";
8
+ import { formatMoney as h, minorToInput as g, parseMoney as _ } from "../../utils/money.js";
9
+ import { PAYMENT_METHODS as v, paymentMethodLabel as y } from "../../utils/registration.js";
10
+ import { useState as b } from "react";
11
+ import { ArrowLeft as x, Ban as S, Check as C, Loader2 as w, Plus as T, RotateCcw as E, X as D } from "lucide-react";
12
+ import { useParams as O } from "react-router";
13
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
14
+ //#region src/atheletebridge/pages/registrations/RegistrationSubmissionPage.tsx
15
+ var j = "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50", M = "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50", N = (e, t) => e instanceof Error ? e.message : t;
16
+ function P({ submission: e }) {
17
+ let t = p(), [n, i] = b(e.reviewNotes ?? ""), [a, c] = b(null);
18
+ if (e.status === "WITHDRAWN") return /* @__PURE__ */ k("p", {
19
+ className: "text-sm text-text-secondary",
20
+ children: "The family withdrew this registration."
21
+ });
22
+ let l = async (r) => {
23
+ c(null);
24
+ try {
25
+ await t.mutateAsync({
26
+ id: e.id,
27
+ decision: r,
28
+ notes: n.trim() || void 0
29
+ });
30
+ } catch (e) {
31
+ c(N(e, "Could not save the decision."));
32
+ }
33
+ };
34
+ return /* @__PURE__ */ A("div", {
35
+ className: "space-y-3",
36
+ children: [
37
+ /* @__PURE__ */ k(o, {
38
+ label: "Review notes",
39
+ htmlFor: "reviewNotes",
40
+ hint: "Visible to club staff only.",
41
+ children: /* @__PURE__ */ k("textarea", {
42
+ id: "reviewNotes",
43
+ rows: 2,
44
+ className: s,
45
+ value: n,
46
+ onChange: (e) => i(e.target.value)
47
+ })
48
+ }),
49
+ /* @__PURE__ */ A("div", {
50
+ className: "flex flex-wrap gap-2",
51
+ children: [/* @__PURE__ */ A("button", {
52
+ type: "button",
53
+ className: M,
54
+ disabled: t.isPending || e.status === "ACCEPTED",
55
+ onClick: () => void l("ACCEPT"),
56
+ children: [/* @__PURE__ */ k(C, { className: "h-4 w-4" }), " Accept"]
57
+ }), /* @__PURE__ */ A("button", {
58
+ type: "button",
59
+ className: j,
60
+ disabled: t.isPending || e.status === "DECLINED",
61
+ onClick: () => void l("DECLINE"),
62
+ children: [/* @__PURE__ */ k(D, { className: "h-4 w-4" }), " Decline"]
63
+ })]
64
+ }),
65
+ e.reviewedAt && /* @__PURE__ */ A("p", {
66
+ className: "text-xs text-text-secondary",
67
+ children: ["Last reviewed ", r(e.reviewedAt)]
68
+ }),
69
+ a && /* @__PURE__ */ k("p", {
70
+ role: "alert",
71
+ className: "text-sm text-status-error-text",
72
+ children: a
73
+ })
74
+ ]
75
+ });
76
+ }
77
+ function F({ submission: e }) {
78
+ let t = c(), [n, r] = b(g(e.amountOutstanding, e.currency)), [i, a] = b("CASH"), [l, u] = b(""), [d, f] = b(null);
79
+ return /* @__PURE__ */ A("form", {
80
+ onSubmit: async (r) => {
81
+ r.preventDefault(), f(null);
82
+ let a = _(n, e.currency);
83
+ if (a === null || a <= 0) {
84
+ f("Enter the amount received.");
85
+ return;
86
+ }
87
+ try {
88
+ await t.mutateAsync({
89
+ submissionId: e.id,
90
+ amount: a,
91
+ method: i,
92
+ reference: l.trim() || void 0
93
+ }), u("");
94
+ } catch (e) {
95
+ f(N(e, "Could not record the payment."));
96
+ }
97
+ },
98
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-[9rem_12rem_1fr_auto]",
99
+ "aria-label": "Record a payment",
100
+ children: [
101
+ /* @__PURE__ */ k(o, {
102
+ label: `Amount (${e.currency})`,
103
+ htmlFor: "paymentAmount",
104
+ children: /* @__PURE__ */ k("input", {
105
+ id: "paymentAmount",
106
+ inputMode: "decimal",
107
+ className: s,
108
+ value: n,
109
+ onChange: (e) => r(e.target.value)
110
+ })
111
+ }),
112
+ /* @__PURE__ */ k(o, {
113
+ label: "Method",
114
+ htmlFor: "paymentMethod",
115
+ children: /* @__PURE__ */ k("select", {
116
+ id: "paymentMethod",
117
+ className: s,
118
+ value: i,
119
+ onChange: (e) => a(e.target.value),
120
+ children: v.map((e) => /* @__PURE__ */ k("option", {
121
+ value: e,
122
+ children: y(e)
123
+ }, e))
124
+ })
125
+ }),
126
+ /* @__PURE__ */ k(o, {
127
+ label: "Reference",
128
+ htmlFor: "paymentReference",
129
+ children: /* @__PURE__ */ k("input", {
130
+ id: "paymentReference",
131
+ className: s,
132
+ value: l,
133
+ onChange: (e) => u(e.target.value),
134
+ placeholder: "Receipt / bank / cheque no."
135
+ })
136
+ }),
137
+ /* @__PURE__ */ k("div", {
138
+ className: "flex items-end",
139
+ children: /* @__PURE__ */ A("button", {
140
+ type: "submit",
141
+ className: M,
142
+ disabled: t.isPending,
143
+ children: [
144
+ t.isPending ? /* @__PURE__ */ k(w, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ k(T, { className: "h-4 w-4" }),
145
+ " ",
146
+ "Record"
147
+ ]
148
+ })
149
+ }),
150
+ d && /* @__PURE__ */ k("p", {
151
+ role: "alert",
152
+ className: "text-sm text-status-error-text sm:col-span-4",
153
+ children: d
154
+ })
155
+ ]
156
+ });
157
+ }
158
+ function I({ payment: e }) {
159
+ let t = m(), i = l(), [a, o] = b(null), s = e.amount - e.refundedAmount, c = async () => {
160
+ let n = window.prompt("Why is this payment being voided?");
161
+ if (n?.trim()) {
162
+ o(null);
163
+ try {
164
+ await t.mutateAsync({
165
+ id: e.id,
166
+ reason: n.trim()
167
+ });
168
+ } catch (e) {
169
+ o(N(e, "Could not void the payment."));
170
+ }
171
+ }
172
+ }, u = async () => {
173
+ let t = window.prompt(`Refund how much? (up to ${h(s, e.currency)})`, g(s, e.currency));
174
+ if (t === null) return;
175
+ let n = _(t, e.currency);
176
+ if (n === null || n <= 0) {
177
+ o("Enter a valid refund amount.");
178
+ return;
179
+ }
180
+ if (n > s) {
181
+ o(`You can refund at most ${h(s, e.currency)} of this payment.`);
182
+ return;
183
+ }
184
+ let r = window.prompt("Reason for the refund?");
185
+ if (r?.trim()) {
186
+ o(null);
187
+ try {
188
+ await i.mutateAsync({
189
+ id: e.id,
190
+ amount: n,
191
+ reason: r.trim()
192
+ });
193
+ } catch (e) {
194
+ o(N(e, "Could not record the refund."));
195
+ }
196
+ }
197
+ }, d = t.isPending || i.isPending;
198
+ return /* @__PURE__ */ A("li", {
199
+ className: "space-y-1 px-4 py-3",
200
+ "data-testid": "registration-payment",
201
+ children: [/* @__PURE__ */ A("div", {
202
+ className: "flex flex-wrap items-center justify-between gap-3",
203
+ children: [/* @__PURE__ */ A("span", {
204
+ className: "min-w-0",
205
+ children: [
206
+ /* @__PURE__ */ A("span", {
207
+ className: "block text-sm font-medium tabular-nums text-text-primary",
208
+ children: [h(e.amount, e.currency), e.refundedAmount > 0 && /* @__PURE__ */ A("span", {
209
+ className: "ml-2 text-xs text-text-secondary",
210
+ children: ["refunded ", h(e.refundedAmount, e.currency)]
211
+ })]
212
+ }),
213
+ /* @__PURE__ */ A("span", {
214
+ className: "block text-xs text-text-secondary",
215
+ children: [
216
+ y(e.method),
217
+ " · ",
218
+ r(e.receivedAt),
219
+ e.reference ? ` · ${e.reference}` : ""
220
+ ]
221
+ }),
222
+ e.voidReason && /* @__PURE__ */ A("span", {
223
+ className: "block text-xs text-text-secondary",
224
+ children: ["Voided: ", e.voidReason]
225
+ }),
226
+ e.refundReason && /* @__PURE__ */ A("span", {
227
+ className: "block text-xs text-text-secondary",
228
+ children: ["Refund: ", e.refundReason]
229
+ })
230
+ ]
231
+ }), /* @__PURE__ */ A("span", {
232
+ className: "flex items-center gap-2",
233
+ children: [
234
+ /* @__PURE__ */ k(n, { status: e.status }),
235
+ e.status !== "VOIDED" && s > 0 && /* @__PURE__ */ A("button", {
236
+ type: "button",
237
+ className: j,
238
+ disabled: d,
239
+ onClick: () => void u(),
240
+ children: [/* @__PURE__ */ k(E, { className: "h-4 w-4" }), " Refund"]
241
+ }),
242
+ e.status === "RECORDED" && e.refundedAmount === 0 && /* @__PURE__ */ A("button", {
243
+ type: "button",
244
+ className: j,
245
+ disabled: d,
246
+ onClick: () => void c(),
247
+ children: [/* @__PURE__ */ k(S, { className: "h-4 w-4" }), " Void"]
248
+ })
249
+ ]
250
+ })]
251
+ }), a && /* @__PURE__ */ k("p", {
252
+ role: "alert",
253
+ className: "text-sm text-status-error-text",
254
+ children: a
255
+ })]
256
+ });
257
+ }
258
+ function L({ submission: e }) {
259
+ let t = d(e.id);
260
+ return t.isError ? null : /* @__PURE__ */ A("section", {
261
+ className: "space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4",
262
+ "aria-label": "Payments",
263
+ children: [
264
+ /* @__PURE__ */ A("div", {
265
+ className: "flex flex-wrap items-center justify-between gap-3",
266
+ children: [/* @__PURE__ */ k("h2", {
267
+ className: "text-base font-semibold text-text-primary",
268
+ children: "Payments"
269
+ }), /* @__PURE__ */ A("span", {
270
+ className: "text-sm text-text-secondary",
271
+ children: [
272
+ "Paid",
273
+ " ",
274
+ /* @__PURE__ */ k("strong", {
275
+ className: "tabular-nums text-text-primary",
276
+ children: h(e.amountPaid, e.currency)
277
+ }),
278
+ " ",
279
+ "of ",
280
+ h(e.amountDue, e.currency),
281
+ " ·",
282
+ " ",
283
+ /* @__PURE__ */ A("span", {
284
+ "data-testid": "submission-outstanding",
285
+ children: [h(e.amountOutstanding, e.currency), " outstanding"]
286
+ })
287
+ ]
288
+ })]
289
+ }),
290
+ e.amountOutstanding > 0 && e.status !== "WITHDRAWN" && /* @__PURE__ */ k(F, { submission: e }, `${e.id}-${e.amountOutstanding}`),
291
+ t.isLoading ? /* @__PURE__ */ k(a, { label: "Loading payments…" }) : (t.data ?? []).length === 0 ? /* @__PURE__ */ k("p", {
292
+ className: "text-sm text-text-secondary",
293
+ children: "No payments recorded yet."
294
+ }) : /* @__PURE__ */ k("ul", {
295
+ className: "divide-y divide-border-seam rounded-lg border border-border-seam",
296
+ children: (t.data ?? []).map((e) => /* @__PURE__ */ k(I, { payment: e }, e.id))
297
+ })
298
+ ]
299
+ });
300
+ }
301
+ function R() {
302
+ let { id: o, submissionId: s } = O(), { navigateTo: c } = e(), l = f(s), d = u(o);
303
+ if (l.isLoading) return /* @__PURE__ */ k(t, {
304
+ title: "Registration",
305
+ children: /* @__PURE__ */ k(a, { label: "Loading registration…" })
306
+ });
307
+ if (l.isError || !l.data) return /* @__PURE__ */ k(t, {
308
+ title: "Registration",
309
+ children: /* @__PURE__ */ k(i, {
310
+ title: "Registration not found",
311
+ message: "This registration does not exist or you do not have access to it.",
312
+ onRetry: () => c(o ? `/registrations/${o}` : "/registrations")
313
+ })
314
+ });
315
+ let p = l.data, m = d.data?.fields ?? [], g = d.data?.fees ?? [], _ = (e) => m.find((t) => t.key === e)?.label ?? e, v = [...m.map((e) => e.key).filter((e) => e in p.answers), ...Object.keys(p.answers).filter((e) => !m.some((t) => t.key === e))];
316
+ return /* @__PURE__ */ k(t, {
317
+ title: /* @__PURE__ */ A("span", {
318
+ className: "flex flex-wrap items-center gap-3",
319
+ children: [
320
+ p.participantName,
321
+ " ",
322
+ /* @__PURE__ */ k(n, { status: p.status }),
323
+ " ",
324
+ /* @__PURE__ */ k(n, { status: p.paymentStatus })
325
+ ]
326
+ }),
327
+ description: `${p.formTitle} · submitted ${r(p.submittedAt)} · ${p.source === "STAFF_ENTRY" ? "entered by staff" : "via share link"}`,
328
+ actions: /* @__PURE__ */ A("button", {
329
+ type: "button",
330
+ className: j,
331
+ onClick: () => c(`/registrations/${p.formId}`),
332
+ children: [/* @__PURE__ */ k(x, { className: "h-4 w-4" }), " Back to form"]
333
+ }),
334
+ children: /* @__PURE__ */ A("div", {
335
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-[1fr_22rem]",
336
+ children: [/* @__PURE__ */ A("div", {
337
+ className: "space-y-6",
338
+ children: [/* @__PURE__ */ A("section", {
339
+ className: "rounded-lg border border-border-seam bg-bg-surface p-4",
340
+ "aria-label": "Answers",
341
+ children: [
342
+ /* @__PURE__ */ k("h2", {
343
+ className: "mb-3 text-base font-semibold text-text-primary",
344
+ children: "Details"
345
+ }),
346
+ /* @__PURE__ */ A("dl", {
347
+ className: "grid grid-cols-1 gap-x-6 gap-y-3 text-sm sm:grid-cols-2",
348
+ children: [[
349
+ ["Contact", p.contactName],
350
+ ["Email", p.contactEmail],
351
+ ["Phone", p.contactPhone],
352
+ ["Waiver accepted", p.waiverAcceptedAt ? r(p.waiverAcceptedAt) : null]
353
+ ].filter(([, e]) => e).map(([e, t]) => /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
354
+ className: "text-xs text-text-secondary",
355
+ children: e
356
+ }), /* @__PURE__ */ k("dd", {
357
+ className: "text-text-primary",
358
+ children: t
359
+ })] }, e)), v.map((e) => {
360
+ let t = p.answers[e];
361
+ return /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
362
+ className: "text-xs text-text-secondary",
363
+ children: _(e)
364
+ }), /* @__PURE__ */ k("dd", {
365
+ className: "text-text-primary",
366
+ children: typeof t == "boolean" ? t ? "Yes" : "No" : String(t)
367
+ })] }, e);
368
+ })]
369
+ }),
370
+ g.length > 0 && /* @__PURE__ */ A("div", {
371
+ className: "mt-4 border-t border-border-seam pt-3",
372
+ children: [/* @__PURE__ */ k("p", {
373
+ className: "mb-2 text-xs text-text-secondary",
374
+ children: "Fees"
375
+ }), /* @__PURE__ */ k("ul", {
376
+ className: "space-y-1 text-sm",
377
+ children: g.filter((e) => p.selectedFeeIds.includes(e.id)).map((e) => /* @__PURE__ */ A("li", {
378
+ className: "flex justify-between text-text-primary",
379
+ children: [/* @__PURE__ */ k("span", { children: e.name }), /* @__PURE__ */ k("span", {
380
+ className: "tabular-nums",
381
+ children: h(e.amount, p.currency)
382
+ })]
383
+ }, e.id))
384
+ })]
385
+ })
386
+ ]
387
+ }), /* @__PURE__ */ k(L, { submission: p })]
388
+ }), /* @__PURE__ */ A("section", {
389
+ className: "h-fit rounded-lg border border-border-seam bg-bg-surface p-4",
390
+ "aria-label": "Review",
391
+ children: [
392
+ /* @__PURE__ */ k("h2", {
393
+ className: "mb-3 text-base font-semibold text-text-primary",
394
+ children: "Review"
395
+ }),
396
+ /* @__PURE__ */ k(P, { submission: p }, p.id),
397
+ p.status === "ACCEPTED" && d.data?.teamId && /* @__PURE__ */ k("button", {
398
+ type: "button",
399
+ className: `${j} mt-4 w-full justify-center`,
400
+ onClick: () => c(`/teams/${d.data?.teamId}`),
401
+ children: "Open the team roster to add this athlete"
402
+ })
403
+ ]
404
+ })]
405
+ })
406
+ });
407
+ }
408
+ //#endregion
409
+ export { R as RegistrationSubmissionPage };
410
+
411
+ //# sourceMappingURL=RegistrationSubmissionPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistrationSubmissionPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/registrations/RegistrationSubmissionPage.tsx"],"sourcesContent":["/**\n * Registration submission detail (club staff)\n * @module atheletebridge/pages/registrations\n *\n * One registration: the participant's answers, the accept / decline review\n * and the payment ledger — record a payment as it arrives, void one recorded\n * in error, or record a refund (BOFF-4135). The ledger panel only renders for\n * staff who can read payments.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport { ArrowLeft, Ban, Check, Loader2, Plus, RotateCcw, X } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { LoadingState, ErrorState } from '../../components/LoadingState';\nimport { FormField, fieldInputClass } from '../../components/form';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport {\n useRecordRegistrationPayment,\n useRefundRegistrationPayment,\n useRegistrationForm,\n useRegistrationPayments,\n useRegistrationSubmission,\n useReviewRegistration,\n useVoidRegistrationPayment,\n} from '../../hooks/useRegistrationApi';\nimport { formatDate } from '../../utils/formatters';\nimport { formatMoney, minorToInput, parseMoney } from '../../utils/money';\nimport { PAYMENT_METHODS, paymentMethodLabel } from '../../utils/registration';\nimport type {\n AthRegistrationPayment,\n AthRegistrationPaymentMethod,\n AthRegistrationSubmission,\n} from '../../types/registration';\n\nconst secondaryButton =\n 'inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50';\nconst primaryButton =\n 'inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50';\n\nconst errorMessage = (err: unknown, fallback: string) =>\n err instanceof Error ? err.message : fallback;\n\nfunction ReviewPanel({ submission }: { submission: AthRegistrationSubmission }) {\n const review = useReviewRegistration();\n const [notes, setNotes] = useState(submission.reviewNotes ?? '');\n const [error, setError] = useState<string | null>(null);\n if (submission.status === 'WITHDRAWN') {\n return <p className=\"text-sm text-text-secondary\">The family withdrew this registration.</p>;\n }\n const decide = async (decision: 'ACCEPT' | 'DECLINE') => {\n setError(null);\n try {\n await review.mutateAsync({ id: submission.id, decision, notes: notes.trim() || undefined });\n } catch (err) {\n setError(errorMessage(err, 'Could not save the decision.'));\n }\n };\n return (\n <div className=\"space-y-3\">\n <FormField label=\"Review notes\" htmlFor=\"reviewNotes\" hint=\"Visible to club staff only.\">\n <textarea\n id=\"reviewNotes\"\n rows={2}\n className={fieldInputClass}\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n />\n </FormField>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n className={primaryButton}\n disabled={review.isPending || submission.status === 'ACCEPTED'}\n onClick={() => void decide('ACCEPT')}\n >\n <Check className=\"h-4 w-4\" /> Accept\n </button>\n <button\n type=\"button\"\n className={secondaryButton}\n disabled={review.isPending || submission.status === 'DECLINED'}\n onClick={() => void decide('DECLINE')}\n >\n <X className=\"h-4 w-4\" /> Decline\n </button>\n </div>\n {submission.reviewedAt && (\n <p className=\"text-xs text-text-secondary\">\n Last reviewed {formatDate(submission.reviewedAt)}\n </p>\n )}\n {error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error}\n </p>\n )}\n </div>\n );\n}\n\nfunction RecordPaymentForm({ submission }: { submission: AthRegistrationSubmission }) {\n const record = useRecordRegistrationPayment();\n const [amountText, setAmountText] = useState(\n minorToInput(submission.amountOutstanding, submission.currency)\n );\n const [method, setMethod] = useState<AthRegistrationPaymentMethod>('CASH');\n const [reference, setReference] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n const amount = parseMoney(amountText, submission.currency);\n if (amount === null || amount <= 0) {\n setError('Enter the amount received.');\n return;\n }\n try {\n await record.mutateAsync({\n submissionId: submission.id,\n amount,\n method,\n reference: reference.trim() || undefined,\n });\n setReference('');\n } catch (err) {\n setError(errorMessage(err, 'Could not record the payment.'));\n }\n };\n\n return (\n <form\n onSubmit={submit}\n className=\"grid grid-cols-1 gap-3 sm:grid-cols-[9rem_12rem_1fr_auto]\"\n aria-label=\"Record a payment\"\n >\n <FormField label={`Amount (${submission.currency})`} htmlFor=\"paymentAmount\">\n <input\n id=\"paymentAmount\"\n inputMode=\"decimal\"\n className={fieldInputClass}\n value={amountText}\n onChange={(e) => setAmountText(e.target.value)}\n />\n </FormField>\n <FormField label=\"Method\" htmlFor=\"paymentMethod\">\n <select\n id=\"paymentMethod\"\n className={fieldInputClass}\n value={method}\n onChange={(e) => setMethod(e.target.value as AthRegistrationPaymentMethod)}\n >\n {PAYMENT_METHODS.map((value) => (\n <option key={value} value={value}>\n {paymentMethodLabel(value)}\n </option>\n ))}\n </select>\n </FormField>\n <FormField label=\"Reference\" htmlFor=\"paymentReference\">\n <input\n id=\"paymentReference\"\n className={fieldInputClass}\n value={reference}\n onChange={(e) => setReference(e.target.value)}\n placeholder=\"Receipt / bank / cheque no.\"\n />\n </FormField>\n <div className=\"flex items-end\">\n <button type=\"submit\" className={primaryButton} disabled={record.isPending}>\n {record.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Plus className=\"h-4 w-4\" />\n )}{' '}\n Record\n </button>\n </div>\n {error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text sm:col-span-4\">\n {error}\n </p>\n )}\n </form>\n );\n}\n\nfunction PaymentRow({ payment }: { payment: AthRegistrationPayment }) {\n const voidPayment = useVoidRegistrationPayment();\n const refund = useRefundRegistrationPayment();\n const [error, setError] = useState<string | null>(null);\n const remaining = payment.amount - payment.refundedAmount;\n\n const onVoid = async () => {\n const reason = window.prompt('Why is this payment being voided?');\n if (!reason?.trim()) return;\n setError(null);\n try {\n await voidPayment.mutateAsync({ id: payment.id, reason: reason.trim() });\n } catch (err) {\n setError(errorMessage(err, 'Could not void the payment.'));\n }\n };\n\n const onRefund = async () => {\n const amountText = window.prompt(\n `Refund how much? (up to ${formatMoney(remaining, payment.currency)})`,\n minorToInput(remaining, payment.currency)\n );\n if (amountText === null) return;\n const amount = parseMoney(amountText, payment.currency);\n if (amount === null || amount <= 0) {\n setError('Enter a valid refund amount.');\n return;\n }\n if (amount > remaining) {\n setError(\n `You can refund at most ${formatMoney(remaining, payment.currency)} of this payment.`\n );\n return;\n }\n const reason = window.prompt('Reason for the refund?');\n if (!reason?.trim()) return;\n setError(null);\n try {\n await refund.mutateAsync({ id: payment.id, amount, reason: reason.trim() });\n } catch (err) {\n setError(errorMessage(err, 'Could not record the refund.'));\n }\n };\n\n const busy = voidPayment.isPending || refund.isPending;\n return (\n <li className=\"space-y-1 px-4 py-3\" data-testid=\"registration-payment\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium tabular-nums text-text-primary\">\n {formatMoney(payment.amount, payment.currency)}\n {payment.refundedAmount > 0 && (\n <span className=\"ml-2 text-xs text-text-secondary\">\n refunded {formatMoney(payment.refundedAmount, payment.currency)}\n </span>\n )}\n </span>\n <span className=\"block text-xs text-text-secondary\">\n {paymentMethodLabel(payment.method)} · {formatDate(payment.receivedAt)}\n {payment.reference ? ` · ${payment.reference}` : ''}\n </span>\n {payment.voidReason && (\n <span className=\"block text-xs text-text-secondary\">Voided: {payment.voidReason}</span>\n )}\n {payment.refundReason && (\n <span className=\"block text-xs text-text-secondary\">\n Refund: {payment.refundReason}\n </span>\n )}\n </span>\n <span className=\"flex items-center gap-2\">\n <StatusBadge status={payment.status} />\n {payment.status !== 'VOIDED' && remaining > 0 && (\n <button\n type=\"button\"\n className={secondaryButton}\n disabled={busy}\n onClick={() => void onRefund()}\n >\n <RotateCcw className=\"h-4 w-4\" /> Refund\n </button>\n )}\n {payment.status === 'RECORDED' && payment.refundedAmount === 0 && (\n <button\n type=\"button\"\n className={secondaryButton}\n disabled={busy}\n onClick={() => void onVoid()}\n >\n <Ban className=\"h-4 w-4\" /> Void\n </button>\n )}\n </span>\n </div>\n {error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error}\n </p>\n )}\n </li>\n );\n}\n\nfunction PaymentsPanel({ submission }: { submission: AthRegistrationSubmission }) {\n const payments = useRegistrationPayments(submission.id);\n // FORBIDDEN (no payment-ledger access) or any failure: hide the ledger.\n if (payments.isError) return null;\n return (\n <section\n className=\"space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n aria-label=\"Payments\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Payments</h2>\n <span className=\"text-sm text-text-secondary\">\n Paid{' '}\n <strong className=\"tabular-nums text-text-primary\">\n {formatMoney(submission.amountPaid, submission.currency)}\n </strong>{' '}\n of {formatMoney(submission.amountDue, submission.currency)} ·{' '}\n <span data-testid=\"submission-outstanding\">\n {formatMoney(submission.amountOutstanding, submission.currency)} outstanding\n </span>\n </span>\n </div>\n {submission.amountOutstanding > 0 && submission.status !== 'WITHDRAWN' && (\n <RecordPaymentForm\n key={`${submission.id}-${submission.amountOutstanding}`}\n submission={submission}\n />\n )}\n {payments.isLoading ? (\n <LoadingState label=\"Loading payments…\" />\n ) : (payments.data ?? []).length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No payments recorded yet.</p>\n ) : (\n <ul className=\"divide-y divide-border-seam rounded-lg border border-border-seam\">\n {(payments.data ?? []).map((payment) => (\n <PaymentRow key={payment.id} payment={payment} />\n ))}\n </ul>\n )}\n </section>\n );\n}\n\nexport function RegistrationSubmissionPage() {\n const { id: formId, submissionId } = useParams<{ id: string; submissionId: string }>();\n const { navigateTo } = useAthleteBridge();\n const submission = useRegistrationSubmission(submissionId);\n const form = useRegistrationForm(formId);\n\n if (submission.isLoading) {\n return (\n <PageLayout title=\"Registration\">\n <LoadingState label=\"Loading registration…\" />\n </PageLayout>\n );\n }\n if (submission.isError || !submission.data) {\n return (\n <PageLayout title=\"Registration\">\n <ErrorState\n title=\"Registration not found\"\n message=\"This registration does not exist or you do not have access to it.\"\n onRetry={() => navigateTo(formId ? `/registrations/${formId}` : '/registrations')}\n />\n </PageLayout>\n );\n }\n\n const data = submission.data;\n const fields = form.data?.fields ?? [];\n const fees = form.data?.fees ?? [];\n const labelFor = (key: string) => fields.find((field) => field.key === key)?.label ?? key;\n const answerKeys = [\n ...fields.map((field) => field.key).filter((key) => key in data.answers),\n ...Object.keys(data.answers).filter((key) => !fields.some((field) => field.key === key)),\n ];\n\n return (\n <PageLayout\n title={\n <span className=\"flex flex-wrap items-center gap-3\">\n {data.participantName} <StatusBadge status={data.status} />{' '}\n <StatusBadge status={data.paymentStatus} />\n </span>\n }\n description={`${data.formTitle} · submitted ${formatDate(data.submittedAt)} · ${\n data.source === 'STAFF_ENTRY' ? 'entered by staff' : 'via share link'\n }`}\n actions={\n <button\n type=\"button\"\n className={secondaryButton}\n onClick={() => navigateTo(`/registrations/${data.formId}`)}\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back to form\n </button>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-[1fr_22rem]\">\n <div className=\"space-y-6\">\n <section\n className=\"rounded-lg border border-border-seam bg-bg-surface p-4\"\n aria-label=\"Answers\"\n >\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Details</h2>\n <dl className=\"grid grid-cols-1 gap-x-6 gap-y-3 text-sm sm:grid-cols-2\">\n {[\n ['Contact', data.contactName],\n ['Email', data.contactEmail],\n ['Phone', data.contactPhone],\n [\n 'Waiver accepted',\n data.waiverAcceptedAt ? formatDate(data.waiverAcceptedAt) : null,\n ],\n ]\n .filter(([, value]) => value)\n .map(([label, value]) => (\n <div key={label}>\n <dt className=\"text-xs text-text-secondary\">{label}</dt>\n <dd className=\"text-text-primary\">{value}</dd>\n </div>\n ))}\n {answerKeys.map((key) => {\n const value = data.answers[key];\n return (\n <div key={key}>\n <dt className=\"text-xs text-text-secondary\">{labelFor(key)}</dt>\n <dd className=\"text-text-primary\">\n {typeof value === 'boolean' ? (value ? 'Yes' : 'No') : String(value)}\n </dd>\n </div>\n );\n })}\n </dl>\n {fees.length > 0 && (\n <div className=\"mt-4 border-t border-border-seam pt-3\">\n <p className=\"mb-2 text-xs text-text-secondary\">Fees</p>\n <ul className=\"space-y-1 text-sm\">\n {fees\n .filter((fee) => data.selectedFeeIds.includes(fee.id))\n .map((fee) => (\n <li key={fee.id} className=\"flex justify-between text-text-primary\">\n <span>{fee.name}</span>\n <span className=\"tabular-nums\">\n {formatMoney(fee.amount, data.currency)}\n </span>\n </li>\n ))}\n </ul>\n </div>\n )}\n </section>\n <PaymentsPanel submission={data} />\n </div>\n <section\n className=\"h-fit rounded-lg border border-border-seam bg-bg-surface p-4\"\n aria-label=\"Review\"\n >\n <h2 className=\"mb-3 text-base font-semibold text-text-primary\">Review</h2>\n <ReviewPanel key={data.id} submission={data} />\n {data.status === 'ACCEPTED' && form.data?.teamId && (\n <button\n type=\"button\"\n className={`${secondaryButton} mt-4 w-full justify-center`}\n onClick={() => navigateTo(`/teams/${form.data?.teamId}`)}\n >\n Open the team roster to add this athlete\n </button>\n )}\n </section>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}