@burdenoff/microfe-atheletebridge 2026.1103.2 → 2026.1107.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 (25) hide show
  1. package/dist/atheletebridge/components/registration/RegistrationEntryFields.d.ts +6 -0
  2. package/dist/atheletebridge/components/registration/RegistrationEntryFields.d.ts.map +1 -1
  3. package/dist/atheletebridge/components/registration/RegistrationEntryFields.js +23 -11
  4. package/dist/atheletebridge/components/registration/RegistrationEntryFields.js.map +1 -1
  5. package/dist/atheletebridge/components/registration/entryRules.d.ts +2 -0
  6. package/dist/atheletebridge/components/registration/entryRules.d.ts.map +1 -1
  7. package/dist/atheletebridge/components/registration/entryRules.js +2 -1
  8. package/dist/atheletebridge/components/registration/entryRules.js.map +1 -1
  9. package/dist/atheletebridge/hooks/useRegistrationApi.d.ts +2 -2
  10. package/dist/atheletebridge/hooks/useRegistrationApi.d.ts.map +1 -1
  11. package/dist/atheletebridge/hooks/useRegistrationApi.js +1 -1
  12. package/dist/atheletebridge/hooks/useRegistrationApi.js.map +1 -1
  13. package/dist/atheletebridge/pages/registrations/RegisterPage.d.ts.map +1 -1
  14. package/dist/atheletebridge/pages/registrations/RegisterPage.js +4 -2
  15. package/dist/atheletebridge/pages/registrations/RegisterPage.js.map +1 -1
  16. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.d.ts.map +1 -1
  17. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.js +132 -107
  18. package/dist/atheletebridge/pages/registrations/RegistrationSubmissionPage.js.map +1 -1
  19. package/dist/atheletebridge/types/registration.d.ts +11 -0
  20. package/dist/atheletebridge/types/registration.d.ts.map +1 -1
  21. package/dist/atheletebridge/utils/registration.d.ts +19 -0
  22. package/dist/atheletebridge/utils/registration.d.ts.map +1 -1
  23. package/dist/atheletebridge/utils/registration.js +28 -1
  24. package/dist/atheletebridge/utils/registration.js.map +1 -1
  25. package/package.json +1 -1
@@ -9,6 +9,12 @@ interface RegistrationEntryFieldsProps {
9
9
  waiverText: string | null;
10
10
  state: RegistrationEntryState;
11
11
  onChange: (next: RegistrationEntryState) => void;
12
+ /**
13
+ * Offer the "I am the athlete" choice. Only the family share-link flow sets
14
+ * it: there the signed-in registrant can be the athlete, and saying so lets
15
+ * the club add them to the team roster on acceptance (BOFF-10806).
16
+ */
17
+ offerSelfRegistration?: boolean;
12
18
  }
13
19
  export declare const RegistrationEntryFields: FC<RegistrationEntryFieldsProps>;
14
20
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"RegistrationEntryFields.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/components/registration/RegistrationEntryFields.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,KAAK,EAEV,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,sBAAsB,EAAqB,MAAM,cAAc,CAAC;AAyF9E,UAAU,4BAA4B;IACpC,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;CAClD;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,4BAA4B,CAwJpE,CAAC"}
1
+ {"version":3,"file":"RegistrationEntryFields.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/components/registration/RegistrationEntryFields.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,KAAK,EAEV,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,sBAAsB,EAAqB,MAAM,cAAc,CAAC;AAyF9E,UAAU,4BAA4B;IACpC,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACjD;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,4BAA4B,CA0KpE,CAAC"}
@@ -63,11 +63,11 @@ var o = ({ field: n, value: r, onChange: o }) => {
63
63
  hint: n.helpText ?? void 0,
64
64
  children: l
65
65
  });
66
- }, s = ({ fields: s, fees: c, currency: l, waiverText: u, state: d, onChange: f }) => {
67
- let p = (e, t) => f({
66
+ }, s = ({ fields: s, fees: c, currency: l, waiverText: u, state: d, onChange: f, offerSelfRegistration: p = !1 }) => {
67
+ let m = (e, t) => f({
68
68
  ...d,
69
69
  [e]: t
70
- }), m = r(c, d.optionalFeeIds);
70
+ }), h = r(c, d.optionalFeeIds);
71
71
  return /* @__PURE__ */ a("div", {
72
72
  className: "space-y-6",
73
73
  children: [
@@ -88,10 +88,22 @@ var o = ({ field: n, value: r, onChange: o }) => {
88
88
  id: "participantName",
89
89
  className: t,
90
90
  value: d.participantName,
91
- onChange: (e) => p("participantName", e.target.value),
91
+ onChange: (e) => m("participantName", e.target.value),
92
92
  placeholder: "Athlete's full name"
93
93
  })
94
94
  }),
95
+ p && /* @__PURE__ */ a("label", {
96
+ className: "flex items-start gap-2.5 text-sm text-text-primary",
97
+ children: [/* @__PURE__ */ i("input", {
98
+ type: "checkbox",
99
+ checked: d.participantIsRegistrant,
100
+ onChange: (e) => m("participantIsRegistrant", e.target.checked),
101
+ className: "mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]"
102
+ }), /* @__PURE__ */ a("span", { children: ["I am the athlete", /* @__PURE__ */ i("span", {
103
+ className: "block text-xs text-text-secondary",
104
+ children: "Tick this if you are registering yourself, so the club can add you to the team roster when they accept. Leave it clear when registering a child."
105
+ })] })]
106
+ }),
95
107
  /* @__PURE__ */ a("div", {
96
108
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
97
109
  children: [
@@ -103,7 +115,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
103
115
  id: "contactName",
104
116
  className: t,
105
117
  value: d.contactName,
106
- onChange: (e) => p("contactName", e.target.value)
118
+ onChange: (e) => m("contactName", e.target.value)
107
119
  })
108
120
  }),
109
121
  /* @__PURE__ */ i(e, {
@@ -114,7 +126,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
114
126
  type: "email",
115
127
  className: t,
116
128
  value: d.contactEmail,
117
- onChange: (e) => p("contactEmail", e.target.value)
129
+ onChange: (e) => m("contactEmail", e.target.value)
118
130
  })
119
131
  }),
120
132
  /* @__PURE__ */ i(e, {
@@ -125,7 +137,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
125
137
  type: "tel",
126
138
  className: t,
127
139
  value: d.contactPhone,
128
- onChange: (e) => p("contactPhone", e.target.value)
140
+ onChange: (e) => m("contactPhone", e.target.value)
129
141
  })
130
142
  })
131
143
  ]
@@ -142,7 +154,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
142
154
  }), s.map((e) => /* @__PURE__ */ i(o, {
143
155
  field: e,
144
156
  value: d.answers[e.key],
145
- onChange: (t) => p("answers", {
157
+ onChange: (t) => m("answers", {
146
158
  ...d.answers,
147
159
  [e.key]: t
148
160
  })
@@ -168,7 +180,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
168
180
  checked: !t || d.optionalFeeIds.includes(e.id),
169
181
  disabled: !t,
170
182
  "aria-label": `${e.name}${t ? " (optional)" : " (required)"}`,
171
- onChange: (t) => p("optionalFeeIds", t.target.checked ? [...d.optionalFeeIds, e.id] : d.optionalFeeIds.filter((t) => t !== e.id)),
183
+ onChange: (t) => m("optionalFeeIds", t.target.checked ? [...d.optionalFeeIds, e.id] : d.optionalFeeIds.filter((t) => t !== e.id)),
172
184
  className: "mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)] disabled:opacity-60"
173
185
  }), /* @__PURE__ */ a("span", { children: [
174
186
  e.name,
@@ -191,7 +203,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
191
203
  children: [/* @__PURE__ */ i("span", { children: "Total due" }), /* @__PURE__ */ i("span", {
192
204
  className: "tabular-nums",
193
205
  "data-testid": "registration-total",
194
- children: n(m, l)
206
+ children: n(h, l)
195
207
  })]
196
208
  })]
197
209
  })]
@@ -215,7 +227,7 @@ var o = ({ field: n, value: r, onChange: o }) => {
215
227
  /* @__PURE__ */ i("input", {
216
228
  type: "checkbox",
217
229
  checked: d.waiverAccepted,
218
- onChange: (e) => p("waiverAccepted", e.target.checked),
230
+ onChange: (e) => m("waiverAccepted", e.target.checked),
219
231
  className: "h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]"
220
232
  }),
221
233
  "I have read and accept the waiver",
@@ -1 +1 @@
1
- {"version":3,"file":"RegistrationEntryFields.js","names":[],"sources":["../../../../src/atheletebridge/components/registration/RegistrationEntryFields.tsx"],"sourcesContent":["/**\n * Registration entry fields (BOFF-4135)\n * @module atheletebridge/components/registration\n *\n * Renders a registration form's participant/contact block, its questions, its\n * fees (REQUIRED always included, OPTIONAL opt-in) and its waiver. Shared by\n * the family-facing share-link page and the staff \"record a registration\"\n * page so both collect exactly what the server validates.\n */\n\nimport type { FC } from 'react';\nimport { FormField, fieldInputClass } from '../form';\nimport { formatMoney } from '../../utils/money';\nimport type {\n AthRegistrationAnswerValue,\n AthRegistrationFee,\n AthRegistrationField,\n} from '../../types/registration';\nimport { type RegistrationEntryState, registrationTotal } from './entryRules';\n\ninterface QuestionInputProps {\n field: AthRegistrationField;\n value: AthRegistrationAnswerValue | undefined;\n onChange: (value: AthRegistrationAnswerValue) => void;\n}\n\nconst QuestionInput: FC<QuestionInputProps> = ({ field, value, onChange }) => {\n const id = `q-${field.key}`;\n if (field.fieldType === 'CHECKBOX') {\n return (\n <label className=\"flex items-start gap-2.5 text-sm text-text-primary\" htmlFor={id}>\n <input\n id={id}\n type=\"checkbox\"\n checked={value === true}\n onChange={(e) => onChange(e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]\"\n />\n <span>\n {field.label}\n {field.required && <span className=\"ml-0.5 text-status-error-text\">*</span>}\n {field.helpText && (\n <span className=\"block text-xs text-text-secondary\">{field.helpText}</span>\n )}\n </span>\n </label>\n );\n }\n\n const text = value === undefined ? '' : String(value);\n let control;\n if (field.fieldType === 'LONG_TEXT') {\n control = (\n <textarea\n id={id}\n rows={3}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n } else if (field.fieldType === 'SELECT') {\n control = (\n <select\n id={id}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">Select…</option>\n {field.options.map((option) => (\n <option key={option} value={option}>\n {option}\n </option>\n ))}\n </select>\n );\n } else {\n const inputType: Record<string, string> = {\n EMAIL: 'email',\n PHONE: 'tel',\n NUMBER: 'number',\n DATE: 'date',\n };\n control = (\n <input\n id={id}\n type={inputType[field.fieldType] ?? 'text'}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n }\n\n return (\n <FormField\n label={field.label}\n htmlFor={id}\n required={field.required}\n hint={field.helpText ?? undefined}\n >\n {control}\n </FormField>\n );\n};\n\ninterface RegistrationEntryFieldsProps {\n fields: AthRegistrationField[];\n fees: AthRegistrationFee[];\n currency: string;\n waiverText: string | null;\n state: RegistrationEntryState;\n onChange: (next: RegistrationEntryState) => void;\n}\n\nexport const RegistrationEntryFields: FC<RegistrationEntryFieldsProps> = ({\n fields,\n fees,\n currency,\n waiverText,\n state,\n onChange,\n}) => {\n const set = <K extends keyof RegistrationEntryState>(key: K, value: RegistrationEntryState[K]) =>\n onChange({ ...state, [key]: value });\n const total = registrationTotal(fees, state.optionalFeeIds);\n\n return (\n <div className=\"space-y-6\">\n <section className=\"space-y-4\" aria-labelledby=\"reg-participant\">\n <h2 id=\"reg-participant\" className=\"text-base font-semibold text-text-primary\">\n Participant\n </h2>\n <FormField label=\"Participant name\" htmlFor=\"participantName\" required>\n <input\n id=\"participantName\"\n className={fieldInputClass}\n value={state.participantName}\n onChange={(e) => set('participantName', e.target.value)}\n placeholder=\"Athlete's full name\"\n />\n </FormField>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <FormField\n label=\"Contact name\"\n htmlFor=\"contactName\"\n hint=\"Parent or guardian, if applicable.\"\n >\n <input\n id=\"contactName\"\n className={fieldInputClass}\n value={state.contactName}\n onChange={(e) => set('contactName', e.target.value)}\n />\n </FormField>\n <FormField label=\"Contact email\" htmlFor=\"contactEmail\">\n <input\n id=\"contactEmail\"\n type=\"email\"\n className={fieldInputClass}\n value={state.contactEmail}\n onChange={(e) => set('contactEmail', e.target.value)}\n />\n </FormField>\n <FormField label=\"Contact phone\" htmlFor=\"contactPhone\">\n <input\n id=\"contactPhone\"\n type=\"tel\"\n className={fieldInputClass}\n value={state.contactPhone}\n onChange={(e) => set('contactPhone', e.target.value)}\n />\n </FormField>\n </div>\n </section>\n\n {fields.length > 0 && (\n <section className=\"space-y-4\" aria-labelledby=\"reg-questions\">\n <h2 id=\"reg-questions\" className=\"text-base font-semibold text-text-primary\">\n Questions\n </h2>\n {fields.map((field) => (\n <QuestionInput\n key={field.id}\n field={field}\n value={state.answers[field.key]}\n onChange={(value) => set('answers', { ...state.answers, [field.key]: value })}\n />\n ))}\n </section>\n )}\n\n {fees.length > 0 && (\n <section className=\"space-y-3\" aria-labelledby=\"reg-fees\">\n <h2 id=\"reg-fees\" className=\"text-base font-semibold text-text-primary\">\n Fees\n </h2>\n <ul className=\"divide-y divide-border-seam rounded-lg border border-border-seam\">\n {fees.map((fee) => {\n const optional = fee.feeType === 'OPTIONAL';\n const checked = !optional || state.optionalFeeIds.includes(fee.id);\n return (\n <li key={fee.id} className=\"flex items-center justify-between gap-3 px-4 py-3\">\n <label className=\"flex items-start gap-2.5 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={!optional}\n aria-label={`${fee.name}${optional ? ' (optional)' : ' (required)'}`}\n onChange={(e) =>\n set(\n 'optionalFeeIds',\n e.target.checked\n ? [...state.optionalFeeIds, fee.id]\n : state.optionalFeeIds.filter((feeId) => feeId !== fee.id)\n )\n }\n className=\"mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)] disabled:opacity-60\"\n />\n <span>\n {fee.name}\n <span className=\"ml-1.5 text-xs text-text-secondary\">\n {optional ? 'Optional' : 'Required'}\n </span>\n {fee.description && (\n <span className=\"block text-xs text-text-secondary\">{fee.description}</span>\n )}\n </span>\n </label>\n <span className=\"text-sm font-medium tabular-nums text-text-primary\">\n {formatMoney(fee.amount, currency)}\n </span>\n </li>\n );\n })}\n <li className=\"flex items-center justify-between px-4 py-3 text-sm font-semibold text-text-primary\">\n <span>Total due</span>\n <span className=\"tabular-nums\" data-testid=\"registration-total\">\n {formatMoney(total, currency)}\n </span>\n </li>\n </ul>\n </section>\n )}\n\n {waiverText && (\n <section className=\"space-y-3\" aria-labelledby=\"reg-waiver\">\n <h2 id=\"reg-waiver\" className=\"text-base font-semibold text-text-primary\">\n Waiver\n </h2>\n <p className=\"whitespace-pre-line rounded-lg border border-border-seam bg-bg-sunken p-4 text-sm text-text-secondary\">\n {waiverText}\n </p>\n <label className=\"flex items-center gap-2.5 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={state.waiverAccepted}\n onChange={(e) => set('waiverAccepted', e.target.checked)}\n className=\"h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]\"\n />\n I have read and accept the waiver\n <span className=\"text-status-error-text\">*</span>\n </label>\n </section>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RegistrationEntryFields.js","names":[],"sources":["../../../../src/atheletebridge/components/registration/RegistrationEntryFields.tsx"],"sourcesContent":["/**\n * Registration entry fields (BOFF-4135)\n * @module atheletebridge/components/registration\n *\n * Renders a registration form's participant/contact block, its questions, its\n * fees (REQUIRED always included, OPTIONAL opt-in) and its waiver. Shared by\n * the family-facing share-link page and the staff \"record a registration\"\n * page so both collect exactly what the server validates.\n */\n\nimport type { FC } from 'react';\nimport { FormField, fieldInputClass } from '../form';\nimport { formatMoney } from '../../utils/money';\nimport type {\n AthRegistrationAnswerValue,\n AthRegistrationFee,\n AthRegistrationField,\n} from '../../types/registration';\nimport { type RegistrationEntryState, registrationTotal } from './entryRules';\n\ninterface QuestionInputProps {\n field: AthRegistrationField;\n value: AthRegistrationAnswerValue | undefined;\n onChange: (value: AthRegistrationAnswerValue) => void;\n}\n\nconst QuestionInput: FC<QuestionInputProps> = ({ field, value, onChange }) => {\n const id = `q-${field.key}`;\n if (field.fieldType === 'CHECKBOX') {\n return (\n <label className=\"flex items-start gap-2.5 text-sm text-text-primary\" htmlFor={id}>\n <input\n id={id}\n type=\"checkbox\"\n checked={value === true}\n onChange={(e) => onChange(e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]\"\n />\n <span>\n {field.label}\n {field.required && <span className=\"ml-0.5 text-status-error-text\">*</span>}\n {field.helpText && (\n <span className=\"block text-xs text-text-secondary\">{field.helpText}</span>\n )}\n </span>\n </label>\n );\n }\n\n const text = value === undefined ? '' : String(value);\n let control;\n if (field.fieldType === 'LONG_TEXT') {\n control = (\n <textarea\n id={id}\n rows={3}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n } else if (field.fieldType === 'SELECT') {\n control = (\n <select\n id={id}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n >\n <option value=\"\">Select…</option>\n {field.options.map((option) => (\n <option key={option} value={option}>\n {option}\n </option>\n ))}\n </select>\n );\n } else {\n const inputType: Record<string, string> = {\n EMAIL: 'email',\n PHONE: 'tel',\n NUMBER: 'number',\n DATE: 'date',\n };\n control = (\n <input\n id={id}\n type={inputType[field.fieldType] ?? 'text'}\n className={fieldInputClass}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n }\n\n return (\n <FormField\n label={field.label}\n htmlFor={id}\n required={field.required}\n hint={field.helpText ?? undefined}\n >\n {control}\n </FormField>\n );\n};\n\ninterface RegistrationEntryFieldsProps {\n fields: AthRegistrationField[];\n fees: AthRegistrationFee[];\n currency: string;\n waiverText: string | null;\n state: RegistrationEntryState;\n onChange: (next: RegistrationEntryState) => void;\n /**\n * Offer the \"I am the athlete\" choice. Only the family share-link flow sets\n * it: there the signed-in registrant can be the athlete, and saying so lets\n * the club add them to the team roster on acceptance (BOFF-10806).\n */\n offerSelfRegistration?: boolean;\n}\n\nexport const RegistrationEntryFields: FC<RegistrationEntryFieldsProps> = ({\n fields,\n fees,\n currency,\n waiverText,\n state,\n onChange,\n offerSelfRegistration = false,\n}) => {\n const set = <K extends keyof RegistrationEntryState>(key: K, value: RegistrationEntryState[K]) =>\n onChange({ ...state, [key]: value });\n const total = registrationTotal(fees, state.optionalFeeIds);\n\n return (\n <div className=\"space-y-6\">\n <section className=\"space-y-4\" aria-labelledby=\"reg-participant\">\n <h2 id=\"reg-participant\" className=\"text-base font-semibold text-text-primary\">\n Participant\n </h2>\n <FormField label=\"Participant name\" htmlFor=\"participantName\" required>\n <input\n id=\"participantName\"\n className={fieldInputClass}\n value={state.participantName}\n onChange={(e) => set('participantName', e.target.value)}\n placeholder=\"Athlete's full name\"\n />\n </FormField>\n {offerSelfRegistration && (\n <label className=\"flex items-start gap-2.5 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={state.participantIsRegistrant}\n onChange={(e) => set('participantIsRegistrant', e.target.checked)}\n className=\"mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]\"\n />\n <span>\n I am the athlete\n <span className=\"block text-xs text-text-secondary\">\n Tick this if you are registering yourself, so the club can add you to the team\n roster when they accept. Leave it clear when registering a child.\n </span>\n </span>\n </label>\n )}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <FormField\n label=\"Contact name\"\n htmlFor=\"contactName\"\n hint=\"Parent or guardian, if applicable.\"\n >\n <input\n id=\"contactName\"\n className={fieldInputClass}\n value={state.contactName}\n onChange={(e) => set('contactName', e.target.value)}\n />\n </FormField>\n <FormField label=\"Contact email\" htmlFor=\"contactEmail\">\n <input\n id=\"contactEmail\"\n type=\"email\"\n className={fieldInputClass}\n value={state.contactEmail}\n onChange={(e) => set('contactEmail', e.target.value)}\n />\n </FormField>\n <FormField label=\"Contact phone\" htmlFor=\"contactPhone\">\n <input\n id=\"contactPhone\"\n type=\"tel\"\n className={fieldInputClass}\n value={state.contactPhone}\n onChange={(e) => set('contactPhone', e.target.value)}\n />\n </FormField>\n </div>\n </section>\n\n {fields.length > 0 && (\n <section className=\"space-y-4\" aria-labelledby=\"reg-questions\">\n <h2 id=\"reg-questions\" className=\"text-base font-semibold text-text-primary\">\n Questions\n </h2>\n {fields.map((field) => (\n <QuestionInput\n key={field.id}\n field={field}\n value={state.answers[field.key]}\n onChange={(value) => set('answers', { ...state.answers, [field.key]: value })}\n />\n ))}\n </section>\n )}\n\n {fees.length > 0 && (\n <section className=\"space-y-3\" aria-labelledby=\"reg-fees\">\n <h2 id=\"reg-fees\" className=\"text-base font-semibold text-text-primary\">\n Fees\n </h2>\n <ul className=\"divide-y divide-border-seam rounded-lg border border-border-seam\">\n {fees.map((fee) => {\n const optional = fee.feeType === 'OPTIONAL';\n const checked = !optional || state.optionalFeeIds.includes(fee.id);\n return (\n <li key={fee.id} className=\"flex items-center justify-between gap-3 px-4 py-3\">\n <label className=\"flex items-start gap-2.5 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={!optional}\n aria-label={`${fee.name}${optional ? ' (optional)' : ' (required)'}`}\n onChange={(e) =>\n set(\n 'optionalFeeIds',\n e.target.checked\n ? [...state.optionalFeeIds, fee.id]\n : state.optionalFeeIds.filter((feeId) => feeId !== fee.id)\n )\n }\n className=\"mt-0.5 h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)] disabled:opacity-60\"\n />\n <span>\n {fee.name}\n <span className=\"ml-1.5 text-xs text-text-secondary\">\n {optional ? 'Optional' : 'Required'}\n </span>\n {fee.description && (\n <span className=\"block text-xs text-text-secondary\">{fee.description}</span>\n )}\n </span>\n </label>\n <span className=\"text-sm font-medium tabular-nums text-text-primary\">\n {formatMoney(fee.amount, currency)}\n </span>\n </li>\n );\n })}\n <li className=\"flex items-center justify-between px-4 py-3 text-sm font-semibold text-text-primary\">\n <span>Total due</span>\n <span className=\"tabular-nums\" data-testid=\"registration-total\">\n {formatMoney(total, currency)}\n </span>\n </li>\n </ul>\n </section>\n )}\n\n {waiverText && (\n <section className=\"space-y-3\" aria-labelledby=\"reg-waiver\">\n <h2 id=\"reg-waiver\" className=\"text-base font-semibold text-text-primary\">\n Waiver\n </h2>\n <p className=\"whitespace-pre-line rounded-lg border border-border-seam bg-bg-sunken p-4 text-sm text-text-secondary\">\n {waiverText}\n </p>\n <label className=\"flex items-center gap-2.5 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={state.waiverAccepted}\n onChange={(e) => set('waiverAccepted', e.target.checked)}\n className=\"h-4 w-4 rounded border-border-seam text-action-primary-bg focus:ring-[var(--color-focus-ring)]\"\n />\n I have read and accept the waiver\n <span className=\"text-status-error-text\">*</span>\n </label>\n </section>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -8,6 +8,8 @@ export interface RegistrationEntryState {
8
8
  answers: Record<string, AthRegistrationAnswerValue>;
9
9
  optionalFeeIds: string[];
10
10
  waiverAccepted: boolean;
11
+ /** Self-service only: the signed-in registrant is the athlete (BOFF-10806). */
12
+ participantIsRegistrant: boolean;
11
13
  }
12
14
  export declare const EMPTY_REGISTRATION_ENTRY: RegistrationEntryState;
13
15
  /** Total due for the current fee selection, in minor units. */
@@ -1 +1 @@
1
- {"version":3,"file":"entryRules.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/components/registration/entryRules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACpD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,wBAAwB,EAAE,sBAQtC,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAI9F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,EAAE,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,MAAM,GAAG,IAAI,CAcf;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,GAClD,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAM5C"}
1
+ {"version":3,"file":"entryRules.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/components/registration/entryRules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACpD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,eAAO,MAAM,wBAAwB,EAAE,sBAStC,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAI9F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,EAAE,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,MAAM,GAAG,IAAI,CAcf;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,GAClD,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAM5C"}
@@ -6,7 +6,8 @@ var e = {
6
6
  contactPhone: "",
7
7
  answers: {},
8
8
  optionalFeeIds: [],
9
- waiverAccepted: !1
9
+ waiverAccepted: !1,
10
+ participantIsRegistrant: !1
10
11
  };
11
12
  function t(e, t) {
12
13
  return e.filter((e) => e.feeType === "REQUIRED" || t.includes(e.id)).reduce((e, t) => e + t.amount, 0);
@@ -1 +1 @@
1
- {"version":3,"file":"entryRules.js","names":[],"sources":["../../../../src/atheletebridge/components/registration/entryRules.ts"],"sourcesContent":["/**\n * Pure rules for the registration entry form (BOFF-4135).\n * @module atheletebridge/components/registration\n */\n\nimport type {\n AthRegistrationAnswerValue,\n AthRegistrationFee,\n AthRegistrationField,\n} from '../../types/registration';\n\nexport interface RegistrationEntryState {\n participantName: string;\n contactName: string;\n contactEmail: string;\n contactPhone: string;\n answers: Record<string, AthRegistrationAnswerValue>;\n optionalFeeIds: string[];\n waiverAccepted: boolean;\n}\n\nexport const EMPTY_REGISTRATION_ENTRY: RegistrationEntryState = {\n participantName: '',\n contactName: '',\n contactEmail: '',\n contactPhone: '',\n answers: {},\n optionalFeeIds: [],\n waiverAccepted: false,\n};\n\n/** Total due for the current fee selection, in minor units. */\nexport function registrationTotal(fees: AthRegistrationFee[], optionalFeeIds: string[]): number {\n return fees\n .filter((fee) => fee.feeType === 'REQUIRED' || optionalFeeIds.includes(fee.id))\n .reduce((total, fee) => total + fee.amount, 0);\n}\n\n/**\n * Client-side pre-check mirroring the server's required-answer rule, so the\n * family sees what is missing before a round trip. The server stays the\n * authority on every rule.\n */\nexport function missingRequiredAnswer(\n fields: AthRegistrationField[],\n state: RegistrationEntryState\n): string | null {\n if (!state.participantName.trim()) return 'Participant name';\n for (const field of fields) {\n if (!field.required) continue;\n const value = state.answers[field.key];\n if (\n field.fieldType === 'CHECKBOX'\n ? value !== true\n : value === undefined || String(value).trim() === ''\n ) {\n return field.label;\n }\n }\n return null;\n}\n\n/** Strip blank answers so optional unanswered questions are simply omitted. */\nexport function cleanAnswers(\n answers: Record<string, AthRegistrationAnswerValue>\n): Record<string, AthRegistrationAnswerValue> {\n return Object.fromEntries(\n Object.entries(answers).filter(\n ([, value]) => !(typeof value === 'string' && value.trim() === '')\n )\n );\n}\n"],"mappings":";AAqBA,IAAa,IAAmD;CAC9D,iBAAiB;CACjB,aAAa;CACb,cAAc;CACd,cAAc;CACd,SAAS,CAAC;CACV,gBAAgB,CAAC;CACjB,gBAAgB;AAClB;AAGA,SAAgB,EAAkB,GAA4B,GAAkC;CAC9F,OAAO,EACJ,QAAQ,MAAQ,EAAI,YAAY,cAAc,EAAe,SAAS,EAAI,EAAE,CAAC,EAC7E,QAAQ,GAAO,MAAQ,IAAQ,EAAI,QAAQ,CAAC;AACjD;AAOA,SAAgB,EACd,GACA,GACe;CACf,IAAI,CAAC,EAAM,gBAAgB,KAAK,GAAG,OAAO;CAC1C,KAAK,IAAM,KAAS,GAAQ;EAC1B,IAAI,CAAC,EAAM,UAAU;EACrB,IAAM,IAAQ,EAAM,QAAQ,EAAM;EAClC,IACE,EAAM,cAAc,aAChB,MAAU,KACV,MAAU,KAAA,KAAa,OAAO,CAAK,EAAE,KAAK,MAAM,IAEpD,OAAO,EAAM;CAEjB;CACA,OAAO;AACT;AAGA,SAAgB,EACd,GAC4C;CAC5C,OAAO,OAAO,YACZ,OAAO,QAAQ,CAAO,EAAE,QACrB,GAAG,OAAW,EAAE,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,GACjE,CACF;AACF"}
1
+ {"version":3,"file":"entryRules.js","names":[],"sources":["../../../../src/atheletebridge/components/registration/entryRules.ts"],"sourcesContent":["/**\n * Pure rules for the registration entry form (BOFF-4135).\n * @module atheletebridge/components/registration\n */\n\nimport type {\n AthRegistrationAnswerValue,\n AthRegistrationFee,\n AthRegistrationField,\n} from '../../types/registration';\n\nexport interface RegistrationEntryState {\n participantName: string;\n contactName: string;\n contactEmail: string;\n contactPhone: string;\n answers: Record<string, AthRegistrationAnswerValue>;\n optionalFeeIds: string[];\n waiverAccepted: boolean;\n /** Self-service only: the signed-in registrant is the athlete (BOFF-10806). */\n participantIsRegistrant: boolean;\n}\n\nexport const EMPTY_REGISTRATION_ENTRY: RegistrationEntryState = {\n participantName: '',\n contactName: '',\n contactEmail: '',\n contactPhone: '',\n answers: {},\n optionalFeeIds: [],\n waiverAccepted: false,\n participantIsRegistrant: false,\n};\n\n/** Total due for the current fee selection, in minor units. */\nexport function registrationTotal(fees: AthRegistrationFee[], optionalFeeIds: string[]): number {\n return fees\n .filter((fee) => fee.feeType === 'REQUIRED' || optionalFeeIds.includes(fee.id))\n .reduce((total, fee) => total + fee.amount, 0);\n}\n\n/**\n * Client-side pre-check mirroring the server's required-answer rule, so the\n * family sees what is missing before a round trip. The server stays the\n * authority on every rule.\n */\nexport function missingRequiredAnswer(\n fields: AthRegistrationField[],\n state: RegistrationEntryState\n): string | null {\n if (!state.participantName.trim()) return 'Participant name';\n for (const field of fields) {\n if (!field.required) continue;\n const value = state.answers[field.key];\n if (\n field.fieldType === 'CHECKBOX'\n ? value !== true\n : value === undefined || String(value).trim() === ''\n ) {\n return field.label;\n }\n }\n return null;\n}\n\n/** Strip blank answers so optional unanswered questions are simply omitted. */\nexport function cleanAnswers(\n answers: Record<string, AthRegistrationAnswerValue>\n): Record<string, AthRegistrationAnswerValue> {\n return Object.fromEntries(\n Object.entries(answers).filter(\n ([, value]) => !(typeof value === 'string' && value.trim() === '')\n )\n );\n}\n"],"mappings":";AAuBA,IAAa,IAAmD;CAC9D,iBAAiB;CACjB,aAAa;CACb,cAAc;CACd,cAAc;CACd,SAAS,CAAC;CACV,gBAAgB,CAAC;CACjB,gBAAgB;CAChB,yBAAyB;AAC3B;AAGA,SAAgB,EAAkB,GAA4B,GAAkC;CAC9F,OAAO,EACJ,QAAQ,MAAQ,EAAI,YAAY,cAAc,EAAe,SAAS,EAAI,EAAE,CAAC,EAC7E,QAAQ,GAAO,MAAQ,IAAQ,EAAI,QAAQ,CAAC;AACjD;AAOA,SAAgB,EACd,GACA,GACe;CACf,IAAI,CAAC,EAAM,gBAAgB,KAAK,GAAG,OAAO;CAC1C,KAAK,IAAM,KAAS,GAAQ;EAC1B,IAAI,CAAC,EAAM,UAAU;EACrB,IAAM,IAAQ,EAAM,QAAQ,EAAM;EAClC,IACE,EAAM,cAAc,aAChB,MAAU,KACV,MAAU,KAAA,KAAa,OAAO,CAAK,EAAE,KAAK,MAAM,IAEpD,OAAO,EAAM;CAEjB;CACA,OAAO;AACT;AAGA,SAAgB,EACd,GAC4C;CAC5C,OAAO,OAAO,YACZ,OAAO,QAAQ,CAAO,EAAE,QACrB,GAAG,OAAW,EAAE,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,GACjE,CACF;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { PaginationInput } from '../types';
2
- import { AthCreateRegistrationFormInput, AthMyRegistration, AthMyRegistrationConnection, AthPublicRegistrationForm, AthRecordRegistrationInput, AthRecordRegistrationPaymentInput, AthRegistrationDecision, AthRegistrationEntryInput, AthRegistrationForm, AthRegistrationFormConnection, AthRegistrationFormStatus, AthRegistrationPayment, AthRegistrationPaymentStatus, AthRegistrationPaymentSummary, AthRegistrationSubmission, AthRegistrationSubmissionConnection, AthRegistrationSubmissionStatus, AthUpdateRegistrationFormInput } from '../types/registration';
2
+ import { AthCreateRegistrationFormInput, AthMyRegistration, AthMyRegistrationConnection, AthPublicRegistrationForm, AthRecordRegistrationInput, AthRecordRegistrationPaymentInput, AthRegistrationDecision, AthRegistrationForm, AthRegistrationFormConnection, AthRegistrationFormStatus, AthRegistrationPayment, AthRegistrationPaymentStatus, AthRegistrationPaymentSummary, AthRegistrationSubmission, AthRegistrationSubmissionConnection, AthRegistrationSubmissionStatus, AthSubmitRegistrationInput, AthUpdateRegistrationFormInput } from '../types/registration';
3
3
 
4
4
  export interface RegistrationFormFilters {
5
5
  status?: AthRegistrationFormStatus;
@@ -47,7 +47,7 @@ export declare const useRefundRegistrationPayment: () => import('@tanstack/react
47
47
  export declare const usePublicRegistrationForm: (slug: string | undefined) => import('@tanstack/react-query').UseQueryResult<NoInfer<AthPublicRegistrationForm | null>, Error>;
48
48
  export declare const useSubmitRegistration: () => import('@tanstack/react-query').UseMutationResult<AthMyRegistration, Error, {
49
49
  slug: string;
50
- input: AthRegistrationEntryInput;
50
+ input: AthSubmitRegistrationInput;
51
51
  }, unknown>;
52
52
  export declare const useMyRegistrations: (pagination?: PaginationInput) => import('@tanstack/react-query').UseQueryResult<NoInfer<AthMyRegistrationConnection>, Error>;
53
53
  export declare const useWithdrawMyRegistration: () => import('@tanstack/react-query').UseMutationResult<AthMyRegistration, Error, string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"useRegistrationApi.d.ts","sourceRoot":"","sources":["../../../src/atheletebridge/hooks/useRegistrationApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EACV,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAC3B,yBAAyB,EACzB,0BAA0B,EAC1B,iCAAiC,EACjC,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,EACnB,6BAA6B,EAC7B,yBAAyB,EACzB,sBAAsB,EACtB,4BAA4B,EAC5B,6BAA6B,EAC7B,yBAAyB,EACzB,mCAAmC,EACnC,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,uBAAuB,CAAC;AA6D/B,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,eAAO,MAAM,oBAAoB,GAAI,UAAS,uBAA4B,kGAkBzE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,IAAI,MAAM,GAAG,SAAS,+FAczD,CAAC;AAEF,eAAO,MAAM,yBAAyB,8HAgBrC,CAAC;AAEF,eAAO,MAAM,yBAAyB;QAIM,MAAM;WAAS,8BAA8B;WAYxF,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAW9E,eAAO,MAAM,4BAA4B;QAII,MAAM;YAAU,+BAA+B;WAW3F,CAAC;AAMF,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,+BAA+B,CAAC;IACzC,aAAa,CAAC,EAAE,4BAA4B,CAAC;IAC7C,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,6BAA6B,EACtC,iBAAc,wGAgCf,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,IAAI,MAAM,GAAG,SAAS,qGAkB/D,CAAC;AAEF,eAAO,MAAM,qBAAqB,gIAgBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;QASxB,MAAM;cACA,uBAAuB;YACzB,MAAM;WAanB,CAAC;AAMF,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,GAAG,SAAS,6FAiBvE,CAAC;AAEF,eAAO,MAAM,6BAA6B,GAAI,SAAS,MAAM,kGAoB5D,CAAC;AAEF,eAAO,MAAM,4BAA4B,oIAgBxC,CAAC;AAEF,eAAO,MAAM,0BAA0B;QAIM,MAAM;YAAU,MAAM;WAYlE,CAAC;AAEF,eAAO,MAAM,4BAA4B;QAIY,MAAM;YAAU,MAAM;YAAU,MAAM;WAY1F,CAAC;AAMF,eAAO,MAAM,yBAAyB,GAAI,MAAM,MAAM,GAAG,SAAS,qGAkBjE,CAAC;AAEF,eAAO,MAAM,qBAAqB;UAIc,MAAM;WAAS,yBAAyB;WAYvF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,aAAa,eAAe,gGAkB9D,CAAC;AAEF,eAAO,MAAM,yBAAyB,oGAgBrC,CAAC"}
1
+ {"version":3,"file":"useRegistrationApi.d.ts","sourceRoot":"","sources":["../../../src/atheletebridge/hooks/useRegistrationApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EACV,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAC3B,yBAAyB,EACzB,0BAA0B,EAC1B,iCAAiC,EACjC,uBAAuB,EACvB,mBAAmB,EACnB,6BAA6B,EAC7B,yBAAyB,EACzB,sBAAsB,EACtB,4BAA4B,EAC5B,6BAA6B,EAC7B,yBAAyB,EACzB,mCAAmC,EACnC,+BAA+B,EAC/B,0BAA0B,EAC1B,8BAA8B,EAC/B,MAAM,uBAAuB,CAAC;AA8D/B,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,eAAO,MAAM,oBAAoB,GAAI,UAAS,uBAA4B,kGAkBzE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,IAAI,MAAM,GAAG,SAAS,+FAczD,CAAC;AAEF,eAAO,MAAM,yBAAyB,8HAgBrC,CAAC;AAEF,eAAO,MAAM,yBAAyB;QAIM,MAAM;WAAS,8BAA8B;WAYxF,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAW9E,eAAO,MAAM,4BAA4B;QAII,MAAM;YAAU,+BAA+B;WAW3F,CAAC;AAMF,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,+BAA+B,CAAC;IACzC,aAAa,CAAC,EAAE,4BAA4B,CAAC;IAC7C,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,6BAA6B,EACtC,iBAAc,wGAgCf,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,IAAI,MAAM,GAAG,SAAS,qGAkB/D,CAAC;AAEF,eAAO,MAAM,qBAAqB,gIAgBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;QASxB,MAAM;cACA,uBAAuB;YACzB,MAAM;WAanB,CAAC;AAMF,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,GAAG,SAAS,6FAiBvE,CAAC;AAEF,eAAO,MAAM,6BAA6B,GAAI,SAAS,MAAM,kGAoB5D,CAAC;AAEF,eAAO,MAAM,4BAA4B,oIAgBxC,CAAC;AAEF,eAAO,MAAM,0BAA0B;QAIM,MAAM;YAAU,MAAM;WAYlE,CAAC;AAEF,eAAO,MAAM,4BAA4B;QAIY,MAAM;YAAU,MAAM;YAAU,MAAM;WAY1F,CAAC;AAMF,eAAO,MAAM,yBAAyB,GAAI,MAAM,MAAM,GAAG,SAAS,qGAkBjE,CAAC;AAEF,eAAO,MAAM,qBAAqB;UAIc,MAAM;WAAS,0BAA0B;WAYxF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,aAAa,eAAe,gGAkB9D,CAAC;AAEF,eAAO,MAAM,yBAAyB,oGAgBrC,CAAC"}
@@ -9,7 +9,7 @@ var a = ["atheletebridge", "registration"], o = "id key label fieldType required
9
9
  submissionCount createdAt updatedAt
10
10
  fields { ${o} }
11
11
  fees { ${s} }
12
- `, l = "\n id workspaceId formId formTitle source submittedByUserId participantName\n participantUserId contactName contactEmail contactPhone answers selectedFeeIds\n status paymentStatus amountDue amountPaid amountOutstanding currency\n waiverAcceptedAt reviewNotes reviewedAt submittedAt createdAt updatedAt\n", u = "\n id submissionId amount refundedAmount netAmount currency method status\n reference note receivedAt voidedAt voidReason refundedAt refundReason\n createdBy createdAt\n", d = "\n formId submissionCount acceptedCount notRequiredCount unpaidCount\n partiallyPaidCount paidCount refundedCount\n totals { currency amountDue amountCollected amountRefunded amountOutstanding }\n", f = `
12
+ `, l = "\n id workspaceId formId formTitle source submittedByUserId participantName\n participantUserId contactName contactEmail contactPhone answers selectedFeeIds\n status paymentStatus amountDue amountPaid amountOutstanding currency\n waiverAcceptedAt reviewNotes reviewedAt submittedAt createdAt updatedAt\n participantIsRegistrant rosterOutcome rosterMemberId rosterTeamId rosterTeamName\n", u = "\n id submissionId amount refundedAmount netAmount currency method status\n reference note receivedAt voidedAt voidReason refundedAt refundReason\n createdBy createdAt\n", d = "\n formId submissionCount acceptedCount notRequiredCount unpaidCount\n partiallyPaidCount paidCount refundedCount\n totals { currency amountDue amountCollected amountRefunded amountOutstanding }\n", f = `
13
13
  id slug title description season currency opensAt closesAt waiverText isOpen
14
14
  spotsRemaining
15
15
  fields { ${o} }
@@ -1 +1 @@
1
- {"version":3,"file":"useRegistrationApi.js","names":[],"sources":["../../../src/atheletebridge/hooks/useRegistrationApi.ts"],"sourcesContent":["/**\n * Club registration & payments API hooks (BOFF-4135).\n *\n * react-query wrappers over the `wspace-atheletebridge-svc` registration\n * module, reached through the workspace gateway like every other hook in this\n * package. Staff hooks are gated by `atheletebridge-registration` /\n * `atheletebridge-registration-payment`; the family-facing hooks\n * (`usePublicRegistrationForm`, `useSubmitRegistration`, `useMyRegistrations`,\n * `useWithdrawMyRegistration`) are self-scoped and work for any signed-in user.\n *\n * @module atheletebridge/hooks/registration\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useAthleteBridge } from '../context';\nimport type { PaginationInput } from '../types';\nimport type {\n AthCreateRegistrationFormInput,\n AthMyRegistration,\n AthMyRegistrationConnection,\n AthPublicRegistrationForm,\n AthRecordRegistrationInput,\n AthRecordRegistrationPaymentInput,\n AthRegistrationDecision,\n AthRegistrationEntryInput,\n AthRegistrationForm,\n AthRegistrationFormConnection,\n AthRegistrationFormStatus,\n AthRegistrationPayment,\n AthRegistrationPaymentStatus,\n AthRegistrationPaymentSummary,\n AthRegistrationSubmission,\n AthRegistrationSubmissionConnection,\n AthRegistrationSubmissionStatus,\n AthUpdateRegistrationFormInput,\n} from '../types/registration';\nimport { athQuery } from './useAthleteBridgeApi';\n\n// Workspace-scoped reads put the active workspace right after ROOT: the\n// QueryClient outlives a workspace switch, and one club's registrations or\n// ledger must never be served from cache to another club. Invalidating ROOT\n// still clears every workspace's entries.\nconst ROOT = ['atheletebridge', 'registration'] as const;\n\nconst FIELD_FIELDS = `id key label fieldType required options helpText position`;\nconst FEE_FIELDS = `id name description amount feeType position`;\n\nconst FORM_FIELDS = `\n id workspaceId title description season teamId programId slug status currency\n opensAt closesAt maxSubmissions waiverText publishedAt closedAt isOpen\n submissionCount createdAt updatedAt\n fields { ${FIELD_FIELDS} }\n fees { ${FEE_FIELDS} }\n`;\n\nconst SUBMISSION_FIELDS = `\n id workspaceId formId formTitle source submittedByUserId participantName\n participantUserId contactName contactEmail contactPhone answers selectedFeeIds\n status paymentStatus amountDue amountPaid amountOutstanding currency\n waiverAcceptedAt reviewNotes reviewedAt submittedAt createdAt updatedAt\n`;\n\nconst PAYMENT_FIELDS = `\n id submissionId amount refundedAmount netAmount currency method status\n reference note receivedAt voidedAt voidReason refundedAt refundReason\n createdBy createdAt\n`;\n\nconst SUMMARY_FIELDS = `\n formId submissionCount acceptedCount notRequiredCount unpaidCount\n partiallyPaidCount paidCount refundedCount\n totals { currency amountDue amountCollected amountRefunded amountOutstanding }\n`;\n\nconst PUBLIC_FORM_FIELDS = `\n id slug title description season currency opensAt closesAt waiverText isOpen\n spotsRemaining\n fields { ${FIELD_FIELDS} }\n fees { ${FEE_FIELDS} }\n`;\n\nconst MY_REGISTRATION_FIELDS = `\n id formId formTitle formSlug participantName status paymentStatus amountDue\n amountPaid amountOutstanding currency submittedAt\n`;\n\n/** Every registration read is invalidated together after any write. */\nconst useInvalidateRegistration = () => {\n const queryClient = useQueryClient();\n return () => queryClient.invalidateQueries({ queryKey: ROOT });\n};\n\n// ============================================================================\n// Forms (staff)\n// ============================================================================\n\nexport interface RegistrationFormFilters {\n status?: AthRegistrationFormStatus;\n season?: string;\n pagination?: PaginationInput;\n}\n\nexport const useRegistrationForms = (filters: RegistrationFormFilters = {}) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'forms', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListRegistrationForms: AthRegistrationFormConnection }>(\n `query AthListRegistrationForms($status: AthRegistrationFormStatus, $season: String, $pagination: PaginationInput) {\n athListRegistrationForms(status: $status, season: $season, pagination: $pagination) {\n items { ${FORM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { ...filters },\n apiGatewayUrl\n );\n return result.athListRegistrationForms;\n },\n });\n};\n\nexport const useRegistrationForm = (id: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'form', id],\n queryFn: async () => {\n const result = await athQuery<{ athRegistrationForm: AthRegistrationForm | null }>(\n `query AthRegistrationForm($id: ID!) { athRegistrationForm(id: $id) { ${FORM_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return result.athRegistrationForm;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useCreateRegistrationForm = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthCreateRegistrationFormInput) => {\n const result = await athQuery<{ athCreateRegistrationForm: AthRegistrationForm }>(\n `mutation AthCreateRegistrationForm($input: AthCreateRegistrationFormInput!) {\n athCreateRegistrationForm(input: $input) { ${FORM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athCreateRegistrationForm;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useUpdateRegistrationForm = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AthUpdateRegistrationFormInput }) => {\n const result = await athQuery<{ athUpdateRegistrationForm: AthRegistrationForm }>(\n `mutation AthUpdateRegistrationForm($id: ID!, $input: AthUpdateRegistrationFormInput!) {\n athUpdateRegistrationForm(id: $id, input: $input) { ${FORM_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athUpdateRegistrationForm;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport type RegistrationFormLifecycleAction = 'publish' | 'close' | 'archive';\n\nconst LIFECYCLE_MUTATIONS: Record<\n RegistrationFormLifecycleAction,\n { field: string; selection: string }\n> = {\n publish: { field: 'athPublishRegistrationForm', selection: `{ ${FORM_FIELDS} }` },\n close: { field: 'athCloseRegistrationForm', selection: `{ ${FORM_FIELDS} }` },\n archive: { field: 'athArchiveRegistrationForm', selection: '' },\n};\n\nexport const useRegistrationFormLifecycle = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, action }: { id: string; action: RegistrationFormLifecycleAction }) => {\n const { field, selection } = LIFECYCLE_MUTATIONS[action];\n await athQuery<Record<string, unknown>>(\n `mutation AthRegistrationFormLifecycle($id: ID!) { ${field}(id: $id) ${selection} }`,\n { id },\n apiGatewayUrl\n );\n return action;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Submissions (staff)\n// ============================================================================\n\nexport interface RegistrationSubmissionFilters {\n formId?: string;\n status?: AthRegistrationSubmissionStatus;\n paymentStatus?: AthRegistrationPaymentStatus;\n pagination?: PaginationInput;\n}\n\nexport const useRegistrationSubmissions = (\n filters: RegistrationSubmissionFilters,\n enabled = true\n) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'submissions', filters],\n queryFn: async () => {\n const result = await athQuery<{\n athListRegistrationSubmissions: AthRegistrationSubmissionConnection;\n }>(\n `query AthListRegistrationSubmissions(\n $formId: ID\n $status: AthRegistrationSubmissionStatus\n $paymentStatus: AthRegistrationPaymentStatus\n $pagination: PaginationInput\n ) {\n athListRegistrationSubmissions(\n formId: $formId\n status: $status\n paymentStatus: $paymentStatus\n pagination: $pagination\n ) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { ...filters },\n apiGatewayUrl\n );\n return result.athListRegistrationSubmissions;\n },\n enabled,\n });\n};\n\nexport const useRegistrationSubmission = (id: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'submission', id],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationSubmission: AthRegistrationSubmission | null;\n }>(\n `query AthRegistrationSubmission($id: ID!) {\n athRegistrationSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athRegistrationSubmission;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useRecordRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthRecordRegistrationInput) => {\n const result = await athQuery<{ athRecordRegistration: AthRegistrationSubmission }>(\n `mutation AthRecordRegistration($input: AthRecordRegistrationInput!) {\n athRecordRegistration(input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athRecordRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useReviewRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({\n id,\n decision,\n notes,\n }: {\n id: string;\n decision: AthRegistrationDecision;\n notes?: string;\n }) => {\n const result = await athQuery<{ athReviewRegistrationSubmission: AthRegistrationSubmission }>(\n `mutation AthReviewRegistrationSubmission($id: ID!, $input: AthReviewRegistrationInput!) {\n athReviewRegistrationSubmission(id: $id, input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { id, input: { decision, notes } },\n apiGatewayUrl\n );\n return result.athReviewRegistrationSubmission;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Payments (staff)\n// ============================================================================\n\nexport const useRegistrationPayments = (submissionId: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'payments', submissionId],\n queryFn: async () => {\n const result = await athQuery<{ athListRegistrationPayments: AthRegistrationPayment[] }>(\n `query AthListRegistrationPayments($submissionId: ID!) {\n athListRegistrationPayments(submissionId: $submissionId) { ${PAYMENT_FIELDS} }\n }`,\n { submissionId },\n apiGatewayUrl\n );\n return result.athListRegistrationPayments;\n },\n enabled: Boolean(submissionId),\n retry: false,\n });\n};\n\nexport const useRegistrationPaymentSummary = (formId?: string) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'summary', formId ?? null],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationPaymentSummary: AthRegistrationPaymentSummary;\n }>(\n `query AthRegistrationPaymentSummary($formId: ID) {\n athRegistrationPaymentSummary(formId: $formId) { ${SUMMARY_FIELDS} }\n }`,\n { formId: formId ?? null },\n apiGatewayUrl\n );\n return result.athRegistrationPaymentSummary;\n },\n // A coach can read submissions without the payment ledger; a FORBIDDEN\n // here just hides the money panel, so never retry it.\n retry: false,\n });\n};\n\nexport const useRecordRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthRecordRegistrationPaymentInput) => {\n const result = await athQuery<{ athRecordRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthRecordRegistrationPayment($input: AthRecordRegistrationPaymentInput!) {\n athRecordRegistrationPayment(input: $input) { ${PAYMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athRecordRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useVoidRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, reason }: { id: string; reason: string }) => {\n const result = await athQuery<{ athVoidRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthVoidRegistrationPayment($id: ID!, $reason: String!) {\n athVoidRegistrationPayment(id: $id, reason: $reason) { ${PAYMENT_FIELDS} }\n }`,\n { id, reason },\n apiGatewayUrl\n );\n return result.athVoidRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useRefundRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, amount, reason }: { id: string; amount: number; reason: string }) => {\n const result = await athQuery<{ athRefundRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthRefundRegistrationPayment($id: ID!, $input: AthRefundRegistrationPaymentInput!) {\n athRefundRegistrationPayment(id: $id, input: $input) { ${PAYMENT_FIELDS} }\n }`,\n { id, input: { amount, reason } },\n apiGatewayUrl\n );\n return result.athRefundRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Family-facing (self-scoped)\n// ============================================================================\n\nexport const usePublicRegistrationForm = (slug: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, 'public', slug],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationFormBySlug: AthPublicRegistrationForm | null;\n }>(\n `query AthRegistrationFormBySlug($slug: String!) {\n athRegistrationFormBySlug(slug: $slug) { ${PUBLIC_FORM_FIELDS} }\n }`,\n { slug },\n apiGatewayUrl\n );\n return result.athRegistrationFormBySlug;\n },\n enabled: Boolean(slug),\n });\n};\n\nexport const useSubmitRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ slug, input }: { slug: string; input: AthRegistrationEntryInput }) => {\n const result = await athQuery<{ athSubmitRegistration: AthMyRegistration }>(\n `mutation AthSubmitRegistration($slug: String!, $input: AthSubmitRegistrationInput!) {\n athSubmitRegistration(slug: $slug, input: $input) { ${MY_REGISTRATION_FIELDS} }\n }`,\n { slug, input },\n apiGatewayUrl\n );\n return result.athSubmitRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useMyRegistrations = (pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, 'mine', pagination ?? null],\n queryFn: async () => {\n const result = await athQuery<{ athMyRegistrations: AthMyRegistrationConnection }>(\n `query AthMyRegistrations($pagination: PaginationInput) {\n athMyRegistrations(pagination: $pagination) {\n items { ${MY_REGISTRATION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: pagination ?? null },\n apiGatewayUrl\n );\n return result.athMyRegistrations;\n },\n });\n};\n\nexport const useWithdrawMyRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athWithdrawMyRegistration: AthMyRegistration }>(\n `mutation AthWithdrawMyRegistration($id: ID!) {\n athWithdrawMyRegistration(id: $id) { ${MY_REGISTRATION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athWithdrawMyRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRegistrationApi.js","names":[],"sources":["../../../src/atheletebridge/hooks/useRegistrationApi.ts"],"sourcesContent":["/**\n * Club registration & payments API hooks (BOFF-4135).\n *\n * react-query wrappers over the `wspace-atheletebridge-svc` registration\n * module, reached through the workspace gateway like every other hook in this\n * package. Staff hooks are gated by `atheletebridge-registration` /\n * `atheletebridge-registration-payment`; the family-facing hooks\n * (`usePublicRegistrationForm`, `useSubmitRegistration`, `useMyRegistrations`,\n * `useWithdrawMyRegistration`) are self-scoped and work for any signed-in user.\n *\n * @module atheletebridge/hooks/registration\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useAthleteBridge } from '../context';\nimport type { PaginationInput } from '../types';\nimport type {\n AthCreateRegistrationFormInput,\n AthMyRegistration,\n AthMyRegistrationConnection,\n AthPublicRegistrationForm,\n AthRecordRegistrationInput,\n AthRecordRegistrationPaymentInput,\n AthRegistrationDecision,\n AthRegistrationForm,\n AthRegistrationFormConnection,\n AthRegistrationFormStatus,\n AthRegistrationPayment,\n AthRegistrationPaymentStatus,\n AthRegistrationPaymentSummary,\n AthRegistrationSubmission,\n AthRegistrationSubmissionConnection,\n AthRegistrationSubmissionStatus,\n AthSubmitRegistrationInput,\n AthUpdateRegistrationFormInput,\n} from '../types/registration';\nimport { athQuery } from './useAthleteBridgeApi';\n\n// Workspace-scoped reads put the active workspace right after ROOT: the\n// QueryClient outlives a workspace switch, and one club's registrations or\n// ledger must never be served from cache to another club. Invalidating ROOT\n// still clears every workspace's entries.\nconst ROOT = ['atheletebridge', 'registration'] as const;\n\nconst FIELD_FIELDS = `id key label fieldType required options helpText position`;\nconst FEE_FIELDS = `id name description amount feeType position`;\n\nconst FORM_FIELDS = `\n id workspaceId title description season teamId programId slug status currency\n opensAt closesAt maxSubmissions waiverText publishedAt closedAt isOpen\n submissionCount createdAt updatedAt\n fields { ${FIELD_FIELDS} }\n fees { ${FEE_FIELDS} }\n`;\n\nconst SUBMISSION_FIELDS = `\n id workspaceId formId formTitle source submittedByUserId participantName\n participantUserId contactName contactEmail contactPhone answers selectedFeeIds\n status paymentStatus amountDue amountPaid amountOutstanding currency\n waiverAcceptedAt reviewNotes reviewedAt submittedAt createdAt updatedAt\n participantIsRegistrant rosterOutcome rosterMemberId rosterTeamId rosterTeamName\n`;\n\nconst PAYMENT_FIELDS = `\n id submissionId amount refundedAmount netAmount currency method status\n reference note receivedAt voidedAt voidReason refundedAt refundReason\n createdBy createdAt\n`;\n\nconst SUMMARY_FIELDS = `\n formId submissionCount acceptedCount notRequiredCount unpaidCount\n partiallyPaidCount paidCount refundedCount\n totals { currency amountDue amountCollected amountRefunded amountOutstanding }\n`;\n\nconst PUBLIC_FORM_FIELDS = `\n id slug title description season currency opensAt closesAt waiverText isOpen\n spotsRemaining\n fields { ${FIELD_FIELDS} }\n fees { ${FEE_FIELDS} }\n`;\n\nconst MY_REGISTRATION_FIELDS = `\n id formId formTitle formSlug participantName status paymentStatus amountDue\n amountPaid amountOutstanding currency submittedAt\n`;\n\n/** Every registration read is invalidated together after any write. */\nconst useInvalidateRegistration = () => {\n const queryClient = useQueryClient();\n return () => queryClient.invalidateQueries({ queryKey: ROOT });\n};\n\n// ============================================================================\n// Forms (staff)\n// ============================================================================\n\nexport interface RegistrationFormFilters {\n status?: AthRegistrationFormStatus;\n season?: string;\n pagination?: PaginationInput;\n}\n\nexport const useRegistrationForms = (filters: RegistrationFormFilters = {}) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'forms', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListRegistrationForms: AthRegistrationFormConnection }>(\n `query AthListRegistrationForms($status: AthRegistrationFormStatus, $season: String, $pagination: PaginationInput) {\n athListRegistrationForms(status: $status, season: $season, pagination: $pagination) {\n items { ${FORM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { ...filters },\n apiGatewayUrl\n );\n return result.athListRegistrationForms;\n },\n });\n};\n\nexport const useRegistrationForm = (id: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'form', id],\n queryFn: async () => {\n const result = await athQuery<{ athRegistrationForm: AthRegistrationForm | null }>(\n `query AthRegistrationForm($id: ID!) { athRegistrationForm(id: $id) { ${FORM_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return result.athRegistrationForm;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useCreateRegistrationForm = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthCreateRegistrationFormInput) => {\n const result = await athQuery<{ athCreateRegistrationForm: AthRegistrationForm }>(\n `mutation AthCreateRegistrationForm($input: AthCreateRegistrationFormInput!) {\n athCreateRegistrationForm(input: $input) { ${FORM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athCreateRegistrationForm;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useUpdateRegistrationForm = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AthUpdateRegistrationFormInput }) => {\n const result = await athQuery<{ athUpdateRegistrationForm: AthRegistrationForm }>(\n `mutation AthUpdateRegistrationForm($id: ID!, $input: AthUpdateRegistrationFormInput!) {\n athUpdateRegistrationForm(id: $id, input: $input) { ${FORM_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athUpdateRegistrationForm;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport type RegistrationFormLifecycleAction = 'publish' | 'close' | 'archive';\n\nconst LIFECYCLE_MUTATIONS: Record<\n RegistrationFormLifecycleAction,\n { field: string; selection: string }\n> = {\n publish: { field: 'athPublishRegistrationForm', selection: `{ ${FORM_FIELDS} }` },\n close: { field: 'athCloseRegistrationForm', selection: `{ ${FORM_FIELDS} }` },\n archive: { field: 'athArchiveRegistrationForm', selection: '' },\n};\n\nexport const useRegistrationFormLifecycle = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, action }: { id: string; action: RegistrationFormLifecycleAction }) => {\n const { field, selection } = LIFECYCLE_MUTATIONS[action];\n await athQuery<Record<string, unknown>>(\n `mutation AthRegistrationFormLifecycle($id: ID!) { ${field}(id: $id) ${selection} }`,\n { id },\n apiGatewayUrl\n );\n return action;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Submissions (staff)\n// ============================================================================\n\nexport interface RegistrationSubmissionFilters {\n formId?: string;\n status?: AthRegistrationSubmissionStatus;\n paymentStatus?: AthRegistrationPaymentStatus;\n pagination?: PaginationInput;\n}\n\nexport const useRegistrationSubmissions = (\n filters: RegistrationSubmissionFilters,\n enabled = true\n) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'submissions', filters],\n queryFn: async () => {\n const result = await athQuery<{\n athListRegistrationSubmissions: AthRegistrationSubmissionConnection;\n }>(\n `query AthListRegistrationSubmissions(\n $formId: ID\n $status: AthRegistrationSubmissionStatus\n $paymentStatus: AthRegistrationPaymentStatus\n $pagination: PaginationInput\n ) {\n athListRegistrationSubmissions(\n formId: $formId\n status: $status\n paymentStatus: $paymentStatus\n pagination: $pagination\n ) {\n items { ${SUBMISSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { ...filters },\n apiGatewayUrl\n );\n return result.athListRegistrationSubmissions;\n },\n enabled,\n });\n};\n\nexport const useRegistrationSubmission = (id: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'submission', id],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationSubmission: AthRegistrationSubmission | null;\n }>(\n `query AthRegistrationSubmission($id: ID!) {\n athRegistrationSubmission(id: $id) { ${SUBMISSION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athRegistrationSubmission;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useRecordRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthRecordRegistrationInput) => {\n const result = await athQuery<{ athRecordRegistration: AthRegistrationSubmission }>(\n `mutation AthRecordRegistration($input: AthRecordRegistrationInput!) {\n athRecordRegistration(input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athRecordRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useReviewRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({\n id,\n decision,\n notes,\n }: {\n id: string;\n decision: AthRegistrationDecision;\n notes?: string;\n }) => {\n const result = await athQuery<{ athReviewRegistrationSubmission: AthRegistrationSubmission }>(\n `mutation AthReviewRegistrationSubmission($id: ID!, $input: AthReviewRegistrationInput!) {\n athReviewRegistrationSubmission(id: $id, input: $input) { ${SUBMISSION_FIELDS} }\n }`,\n { id, input: { decision, notes } },\n apiGatewayUrl\n );\n return result.athReviewRegistrationSubmission;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Payments (staff)\n// ============================================================================\n\nexport const useRegistrationPayments = (submissionId: string | undefined) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'payments', submissionId],\n queryFn: async () => {\n const result = await athQuery<{ athListRegistrationPayments: AthRegistrationPayment[] }>(\n `query AthListRegistrationPayments($submissionId: ID!) {\n athListRegistrationPayments(submissionId: $submissionId) { ${PAYMENT_FIELDS} }\n }`,\n { submissionId },\n apiGatewayUrl\n );\n return result.athListRegistrationPayments;\n },\n enabled: Boolean(submissionId),\n retry: false,\n });\n};\n\nexport const useRegistrationPaymentSummary = (formId?: string) => {\n const { apiGatewayUrl, workspaceId } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, workspaceId ?? null, 'summary', formId ?? null],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationPaymentSummary: AthRegistrationPaymentSummary;\n }>(\n `query AthRegistrationPaymentSummary($formId: ID) {\n athRegistrationPaymentSummary(formId: $formId) { ${SUMMARY_FIELDS} }\n }`,\n { formId: formId ?? null },\n apiGatewayUrl\n );\n return result.athRegistrationPaymentSummary;\n },\n // A coach can read submissions without the payment ledger; a FORBIDDEN\n // here just hides the money panel, so never retry it.\n retry: false,\n });\n};\n\nexport const useRecordRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (input: AthRecordRegistrationPaymentInput) => {\n const result = await athQuery<{ athRecordRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthRecordRegistrationPayment($input: AthRecordRegistrationPaymentInput!) {\n athRecordRegistrationPayment(input: $input) { ${PAYMENT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athRecordRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useVoidRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, reason }: { id: string; reason: string }) => {\n const result = await athQuery<{ athVoidRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthVoidRegistrationPayment($id: ID!, $reason: String!) {\n athVoidRegistrationPayment(id: $id, reason: $reason) { ${PAYMENT_FIELDS} }\n }`,\n { id, reason },\n apiGatewayUrl\n );\n return result.athVoidRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useRefundRegistrationPayment = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ id, amount, reason }: { id: string; amount: number; reason: string }) => {\n const result = await athQuery<{ athRefundRegistrationPayment: AthRegistrationPayment }>(\n `mutation AthRefundRegistrationPayment($id: ID!, $input: AthRefundRegistrationPaymentInput!) {\n athRefundRegistrationPayment(id: $id, input: $input) { ${PAYMENT_FIELDS} }\n }`,\n { id, input: { amount, reason } },\n apiGatewayUrl\n );\n return result.athRefundRegistrationPayment;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\n// ============================================================================\n// Family-facing (self-scoped)\n// ============================================================================\n\nexport const usePublicRegistrationForm = (slug: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, 'public', slug],\n queryFn: async () => {\n const result = await athQuery<{\n athRegistrationFormBySlug: AthPublicRegistrationForm | null;\n }>(\n `query AthRegistrationFormBySlug($slug: String!) {\n athRegistrationFormBySlug(slug: $slug) { ${PUBLIC_FORM_FIELDS} }\n }`,\n { slug },\n apiGatewayUrl\n );\n return result.athRegistrationFormBySlug;\n },\n enabled: Boolean(slug),\n });\n};\n\nexport const useSubmitRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async ({ slug, input }: { slug: string; input: AthSubmitRegistrationInput }) => {\n const result = await athQuery<{ athSubmitRegistration: AthMyRegistration }>(\n `mutation AthSubmitRegistration($slug: String!, $input: AthSubmitRegistrationInput!) {\n athSubmitRegistration(slug: $slug, input: $input) { ${MY_REGISTRATION_FIELDS} }\n }`,\n { slug, input },\n apiGatewayUrl\n );\n return result.athSubmitRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n\nexport const useMyRegistrations = (pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: [...ROOT, 'mine', pagination ?? null],\n queryFn: async () => {\n const result = await athQuery<{ athMyRegistrations: AthMyRegistrationConnection }>(\n `query AthMyRegistrations($pagination: PaginationInput) {\n athMyRegistrations(pagination: $pagination) {\n items { ${MY_REGISTRATION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: pagination ?? null },\n apiGatewayUrl\n );\n return result.athMyRegistrations;\n },\n });\n};\n\nexport const useWithdrawMyRegistration = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n const invalidate = useInvalidateRegistration();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athWithdrawMyRegistration: AthMyRegistration }>(\n `mutation AthWithdrawMyRegistration($id: ID!) {\n athWithdrawMyRegistration(id: $id) { ${MY_REGISTRATION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athWithdrawMyRegistration;\n },\n onSuccess: () => void invalidate(),\n });\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RegisterPage.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/pages/registrations/RegisterPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,wBAAgB,YAAY,gCAgK3B"}
1
+ {"version":3,"file":"RegisterPage.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/pages/registrations/RegisterPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,wBAAgB,YAAY,gCAkK3B"}
@@ -95,7 +95,8 @@ function S() {
95
95
  contactPhone: E.contactPhone.trim() || void 0,
96
96
  answers: d(E.answers),
97
97
  selectedFeeIds: E.optionalFeeIds,
98
- waiverAccepted: E.waiverAccepted
98
+ waiverAccepted: E.waiverAccepted,
99
+ participantIsRegistrant: E.participantIsRegistrant
99
100
  }
100
101
  }));
101
102
  } catch (e) {
@@ -124,7 +125,8 @@ function S() {
124
125
  currency: M.currency,
125
126
  waiverText: M.waiverText,
126
127
  state: E,
127
- onChange: D
128
+ onChange: D,
129
+ offerSelfRegistration: !0
128
130
  }),
129
131
  O && /* @__PURE__ */ b("p", {
130
132
  role: "alert",
@@ -1 +1 @@
1
- {"version":3,"file":"RegisterPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/registrations/RegisterPage.tsx"],"sourcesContent":["/**\n * Family registration (share link)\n * @module atheletebridge/pages/registrations\n *\n * Opened from a club's share link (`/register/:slug`). Any signed-in user —\n * typically a parent who is not a member of the club's workspace — can fill\n * in a published form; the registration is filed with the club and tracked\n * under \"My registrations\" (BOFF-4135).\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport { CheckCircle2, ClipboardX, Loader2, Send } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/LoadingState';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { RegistrationEntryFields } from '../../components/registration/RegistrationEntryFields';\nimport {\n EMPTY_REGISTRATION_ENTRY,\n type RegistrationEntryState,\n cleanAnswers,\n missingRequiredAnswer,\n} from '../../components/registration/entryRules';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { usePublicRegistrationForm, useSubmitRegistration } from '../../hooks/useRegistrationApi';\nimport { formatDate } from '../../utils/formatters';\nimport { formatMoney } from '../../utils/money';\nimport type { AthMyRegistration } from '../../types/registration';\n\nexport function RegisterPage() {\n const { slug } = useParams<{ slug: string }>();\n const { navigateTo } = useAthleteBridge();\n const form = usePublicRegistrationForm(slug);\n const submit = useSubmitRegistration();\n const [state, setState] = useState<RegistrationEntryState>(EMPTY_REGISTRATION_ENTRY);\n const [error, setError] = useState<string | null>(null);\n const [receipt, setReceipt] = useState<AthMyRegistration | null>(null);\n\n if (form.isLoading) {\n return (\n <PageLayout title=\"Registration\">\n <LoadingState label=\"Loading registration form…\" />\n </PageLayout>\n );\n }\n if (form.isError) {\n return (\n <PageLayout title=\"Registration\">\n <ErrorState onRetry={() => void form.refetch()} />\n </PageLayout>\n );\n }\n if (!form.data || !slug) {\n return (\n <PageLayout title=\"Registration\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<ClipboardX className=\"h-10 w-10\" />}\n title=\"This registration link is not available\"\n description=\"The club may not have published it yet, or the link is incorrect. Check the link with the club.\"\n />\n </PageLayout>\n );\n }\n const data = form.data;\n\n if (receipt) {\n return (\n <PageLayout title={data.title}>\n <div\n className=\"max-w-xl space-y-4 rounded-lg border border-border-seam bg-bg-surface p-6\"\n data-testid=\"registration-receipt\"\n >\n <p className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <CheckCircle2 className=\"h-6 w-6 text-status-success-text\" /> Registration received\n </p>\n <p className=\"text-sm text-text-secondary\">\n {receipt.participantName} is registered for {receipt.formTitle}. The club will review it\n {receipt.amountDue > 0 ? ' and confirm payment details with you' : ''}.\n </p>\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n <StatusBadge status={receipt.status} />\n <StatusBadge status={receipt.paymentStatus} />\n {receipt.amountDue > 0 && (\n <span className=\"tabular-nums text-text-primary\">\n {formatMoney(receipt.amountOutstanding, receipt.currency)} due\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/my-registrations')}\n 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\"\n >\n View my registrations\n </button>\n </div>\n </PageLayout>\n );\n }\n\n const onSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n const missing = missingRequiredAnswer(data.fields, state);\n if (missing) {\n setError(`Please answer \"${missing}\".`);\n return;\n }\n if (data.waiverText && !state.waiverAccepted) {\n setError('Please accept the waiver to register.');\n return;\n }\n try {\n const result = await submit.mutateAsync({\n slug,\n input: {\n participantName: state.participantName.trim(),\n contactName: state.contactName.trim() || undefined,\n contactEmail: state.contactEmail.trim() || undefined,\n contactPhone: state.contactPhone.trim() || undefined,\n answers: cleanAnswers(state.answers),\n selectedFeeIds: state.optionalFeeIds,\n waiverAccepted: state.waiverAccepted,\n },\n });\n setReceipt(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not submit the registration.');\n }\n };\n\n const subtitle = [\n data.season,\n data.closesAt ? `Closes ${formatDate(data.closesAt)}` : null,\n data.spotsRemaining != null ? `${data.spotsRemaining} places left` : null,\n ]\n .filter(Boolean)\n .join(' · ');\n\n return (\n <PageLayout title={data.title} description={subtitle || undefined}>\n <div className=\"max-w-2xl space-y-6\">\n {data.description && (\n <p className=\"whitespace-pre-line text-sm text-text-secondary\">{data.description}</p>\n )}\n {!data.isOpen ? (\n <p\n role=\"status\"\n className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text\"\n >\n This form is not accepting registrations right now\n {data.opensAt && new Date(data.opensAt) > new Date()\n ? ` — it opens ${formatDate(data.opensAt)}`\n : ''}\n .\n </p>\n ) : (\n <form onSubmit={onSubmit} className=\"space-y-6\">\n <RegistrationEntryFields\n fields={data.fields}\n fees={data.fees}\n currency={data.currency}\n waiverText={data.waiverText}\n state={state}\n onChange={setState}\n />\n {error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error}\n </p>\n )}\n <button\n type=\"submit\"\n disabled={submit.isPending}\n 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\"\n >\n {submit.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}{' '}\n Submit registration\n </button>\n </form>\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"RegisterPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/registrations/RegisterPage.tsx"],"sourcesContent":["/**\n * Family registration (share link)\n * @module atheletebridge/pages/registrations\n *\n * Opened from a club's share link (`/register/:slug`). Any signed-in user —\n * typically a parent who is not a member of the club's workspace — can fill\n * in a published form; the registration is filed with the club and tracked\n * under \"My registrations\" (BOFF-4135).\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport { CheckCircle2, ClipboardX, Loader2, Send } from 'lucide-react';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/LoadingState';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { RegistrationEntryFields } from '../../components/registration/RegistrationEntryFields';\nimport {\n EMPTY_REGISTRATION_ENTRY,\n type RegistrationEntryState,\n cleanAnswers,\n missingRequiredAnswer,\n} from '../../components/registration/entryRules';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { usePublicRegistrationForm, useSubmitRegistration } from '../../hooks/useRegistrationApi';\nimport { formatDate } from '../../utils/formatters';\nimport { formatMoney } from '../../utils/money';\nimport type { AthMyRegistration } from '../../types/registration';\n\nexport function RegisterPage() {\n const { slug } = useParams<{ slug: string }>();\n const { navigateTo } = useAthleteBridge();\n const form = usePublicRegistrationForm(slug);\n const submit = useSubmitRegistration();\n const [state, setState] = useState<RegistrationEntryState>(EMPTY_REGISTRATION_ENTRY);\n const [error, setError] = useState<string | null>(null);\n const [receipt, setReceipt] = useState<AthMyRegistration | null>(null);\n\n if (form.isLoading) {\n return (\n <PageLayout title=\"Registration\">\n <LoadingState label=\"Loading registration form…\" />\n </PageLayout>\n );\n }\n if (form.isError) {\n return (\n <PageLayout title=\"Registration\">\n <ErrorState onRetry={() => void form.refetch()} />\n </PageLayout>\n );\n }\n if (!form.data || !slug) {\n return (\n <PageLayout title=\"Registration\">\n <EmptyState\n illustration=\"empty-data\"\n icon={<ClipboardX className=\"h-10 w-10\" />}\n title=\"This registration link is not available\"\n description=\"The club may not have published it yet, or the link is incorrect. Check the link with the club.\"\n />\n </PageLayout>\n );\n }\n const data = form.data;\n\n if (receipt) {\n return (\n <PageLayout title={data.title}>\n <div\n className=\"max-w-xl space-y-4 rounded-lg border border-border-seam bg-bg-surface p-6\"\n data-testid=\"registration-receipt\"\n >\n <p className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <CheckCircle2 className=\"h-6 w-6 text-status-success-text\" /> Registration received\n </p>\n <p className=\"text-sm text-text-secondary\">\n {receipt.participantName} is registered for {receipt.formTitle}. The club will review it\n {receipt.amountDue > 0 ? ' and confirm payment details with you' : ''}.\n </p>\n <div className=\"flex flex-wrap items-center gap-2 text-sm\">\n <StatusBadge status={receipt.status} />\n <StatusBadge status={receipt.paymentStatus} />\n {receipt.amountDue > 0 && (\n <span className=\"tabular-nums text-text-primary\">\n {formatMoney(receipt.amountOutstanding, receipt.currency)} due\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/my-registrations')}\n 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\"\n >\n View my registrations\n </button>\n </div>\n </PageLayout>\n );\n }\n\n const onSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n const missing = missingRequiredAnswer(data.fields, state);\n if (missing) {\n setError(`Please answer \"${missing}\".`);\n return;\n }\n if (data.waiverText && !state.waiverAccepted) {\n setError('Please accept the waiver to register.');\n return;\n }\n try {\n const result = await submit.mutateAsync({\n slug,\n input: {\n participantName: state.participantName.trim(),\n contactName: state.contactName.trim() || undefined,\n contactEmail: state.contactEmail.trim() || undefined,\n contactPhone: state.contactPhone.trim() || undefined,\n answers: cleanAnswers(state.answers),\n selectedFeeIds: state.optionalFeeIds,\n waiverAccepted: state.waiverAccepted,\n participantIsRegistrant: state.participantIsRegistrant,\n },\n });\n setReceipt(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not submit the registration.');\n }\n };\n\n const subtitle = [\n data.season,\n data.closesAt ? `Closes ${formatDate(data.closesAt)}` : null,\n data.spotsRemaining != null ? `${data.spotsRemaining} places left` : null,\n ]\n .filter(Boolean)\n .join(' · ');\n\n return (\n <PageLayout title={data.title} description={subtitle || undefined}>\n <div className=\"max-w-2xl space-y-6\">\n {data.description && (\n <p className=\"whitespace-pre-line text-sm text-text-secondary\">{data.description}</p>\n )}\n {!data.isOpen ? (\n <p\n role=\"status\"\n className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text\"\n >\n This form is not accepting registrations right now\n {data.opensAt && new Date(data.opensAt) > new Date()\n ? ` — it opens ${formatDate(data.opensAt)}`\n : ''}\n .\n </p>\n ) : (\n <form onSubmit={onSubmit} className=\"space-y-6\">\n <RegistrationEntryFields\n fields={data.fields}\n fees={data.fees}\n currency={data.currency}\n waiverText={data.waiverText}\n state={state}\n onChange={setState}\n offerSelfRegistration\n />\n {error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error}\n </p>\n )}\n <button\n type=\"submit\"\n disabled={submit.isPending}\n 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\"\n >\n {submit.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}{' '}\n Submit registration\n </button>\n </form>\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RegistrationSubmissionPage.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/pages/registrations/RegistrationSubmissionPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuUH,wBAAgB,0BAA0B,gCAkIzC"}
1
+ {"version":3,"file":"RegistrationSubmissionPage.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/pages/registrations/RegistrationSubmissionPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuYH,wBAAgB,0BAA0B,gCA0HzC"}