@burdenoff/microfe-atheletebridge 2026.629.1 → 2026.705.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/atheletebridge/AthleteBridgeRoot.js +45 -37
  2. package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
  3. package/dist/atheletebridge/AthleteBridgeRoutes.js +10 -6
  4. package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
  5. package/dist/atheletebridge/components/AthleteSelect.js +66 -0
  6. package/dist/atheletebridge/components/AthleteSelect.js.map +1 -0
  7. package/dist/atheletebridge/components/DrillVideoLink.js +28 -0
  8. package/dist/atheletebridge/components/DrillVideoLink.js.map +1 -0
  9. package/dist/atheletebridge/components/MetricsCard.js +20 -46
  10. package/dist/atheletebridge/components/MetricsCard.js.map +1 -1
  11. package/dist/atheletebridge/components/UserSearchSelect.js +129 -0
  12. package/dist/atheletebridge/components/UserSearchSelect.js.map +1 -0
  13. package/dist/atheletebridge/components/domain.js +10 -1
  14. package/dist/atheletebridge/components/domain.js.map +1 -1
  15. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +313 -180
  16. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  17. package/dist/atheletebridge/pages/DashboardPage.js +77 -69
  18. package/dist/atheletebridge/pages/DashboardPage.js.map +1 -1
  19. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +4 -4
  20. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -1
  21. package/dist/atheletebridge/pages/performance/PerformancePage.js +496 -0
  22. package/dist/atheletebridge/pages/performance/PerformancePage.js.map +1 -0
  23. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +176 -142
  24. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -1
  25. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +86 -85
  26. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -1
  27. package/dist/atheletebridge/pages/sessions/SessionFormPage.js +92 -98
  28. package/dist/atheletebridge/pages/sessions/SessionFormPage.js.map +1 -1
  29. package/dist/atheletebridge/pages/teams/TeamDetailPage.js +132 -137
  30. package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -1
  31. package/dist/atheletebridge/utils/formatters.js +2 -25
  32. package/dist/atheletebridge/utils/formatters.js.map +1 -1
  33. package/dist/atheletebridge/utils/url.js +17 -0
  34. package/dist/atheletebridge/utils/url.js.map +1 -0
  35. package/dist/index.js +4 -4
  36. package/package.json +5 -5
@@ -7,19 +7,20 @@ import { EmptyState as o } from "../../components/EmptyState.js";
7
7
  import { ErrorState as s, LoadingState as c } from "../../components/LoadingState.js";
8
8
  import { useAddMember as l, useArchiveTeam as u, useRemoveMember as d, useTeam as f } from "../../hooks/useAthleteBridgeApi.js";
9
9
  import { FormField as p, fieldInputClass as m } from "../../components/form.js";
10
- import { useState as h } from "react";
11
- import { Archive as g, ArrowLeft as _, CalendarDays as v, Edit as y, Loader2 as b, MapPin as x, Plus as S, Trash2 as C, UserPlus as w } from "lucide-react";
12
- import { useParams as T } from "react-router-dom";
13
- import { jsx as E, jsxs as D } from "react/jsx-runtime";
14
- import { EmphasisPanel as O, GlassCard as k, ResponsiveDialog as A, ResponsiveDialogContent as j, ResponsiveDialogFooter as M, ResponsiveDialogHeader as N, ResponsiveDialogTitle as P } from "@burdenoff/fe-libs/ui";
10
+ import { UserSearchSelect as h } from "../../components/UserSearchSelect.js";
11
+ import { useState as g } from "react";
12
+ import { Archive as _, ArrowLeft as v, CalendarDays as y, Edit as b, Loader2 as x, MapPin as S, Plus as C, Trash2 as w, UserPlus as T } from "lucide-react";
13
+ import { useParams as E } from "react-router-dom";
14
+ import { jsx as D, jsxs as O } from "react/jsx-runtime";
15
+ import { EmphasisPanel as k, GlassCard as A, ResponsiveDialog as j, ResponsiveDialogContent as M, ResponsiveDialogFooter as N, ResponsiveDialogHeader as P, ResponsiveDialogTitle as F } from "@burdenoff/fe-libs/ui";
15
16
  //#region src/atheletebridge/pages/teams/TeamDetailPage.tsx
16
- var F = Object.keys(r), I = [
17
+ var I = Object.keys(r), L = [
17
18
  "TRIAL",
18
19
  "ACTIVE",
19
20
  "INJURED",
20
21
  "SUSPENDED",
21
22
  "RELEASED"
22
- ], L = {
23
+ ], R = {
23
24
  userId: "",
24
25
  displayName: "",
25
26
  role: "PLAYER",
@@ -27,48 +28,48 @@ var F = Object.keys(r), I = [
27
28
  position: "",
28
29
  jerseyNumber: ""
29
30
  };
30
- function R() {
31
- let { id: R } = T(), { navigateTo: z } = e(), B = f(R), V = u(), H = l(), U = d(R), [W, G] = h(!1), [K, q] = h(L), [J, Y] = h(null);
32
- if (B.isLoading) return /* @__PURE__ */ E(t, {
31
+ function z() {
32
+ let { id: z } = E(), { navigateTo: B } = e(), V = f(z), H = u(), U = l(), W = d(z), [G, K] = g(!1), [q, J] = g(R), [Y, X] = g(null);
33
+ if (V.isLoading) return /* @__PURE__ */ D(t, {
33
34
  title: "Team",
34
- children: /* @__PURE__ */ E(c, { label: "Loading team…" })
35
+ children: /* @__PURE__ */ D(c, { label: "Loading team…" })
35
36
  });
36
- if (B.isError || !B.data) return /* @__PURE__ */ E(t, {
37
+ if (V.isError || !V.data) return /* @__PURE__ */ D(t, {
37
38
  title: "Team",
38
- children: /* @__PURE__ */ E(s, {
39
+ children: /* @__PURE__ */ D(s, {
39
40
  title: "Team not found",
40
41
  message: "This team does not exist or you do not have access to it.",
41
- onRetry: () => z("/teams")
42
+ onRetry: () => B("/teams")
42
43
  })
43
44
  });
44
- let X = B.data, Z = X.members ?? [], Q = X.fixtures ?? [];
45
- return /* @__PURE__ */ D(t, {
46
- title: X.name,
47
- description: `${i[X.sport]}${X.season ? ` · ${X.season}` : ""}`,
48
- actions: /* @__PURE__ */ D("div", {
45
+ let Z = V.data, Q = Z.members ?? [], $ = Z.fixtures ?? [];
46
+ return /* @__PURE__ */ O(t, {
47
+ title: Z.name,
48
+ description: `${i[Z.sport]}${Z.season ? ` · ${Z.season}` : ""}`,
49
+ actions: /* @__PURE__ */ O("div", {
49
50
  className: "flex flex-wrap items-center gap-2",
50
51
  children: [
51
- /* @__PURE__ */ D("button", {
52
+ /* @__PURE__ */ O("button", {
52
53
  type: "button",
53
- onClick: () => z("/teams"),
54
+ onClick: () => B("/teams"),
54
55
  className: "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",
55
- children: [/* @__PURE__ */ E(_, { className: "h-4 w-4" }), " Back"]
56
+ children: [/* @__PURE__ */ D(v, { className: "h-4 w-4" }), " Back"]
56
57
  }),
57
- /* @__PURE__ */ D("button", {
58
+ /* @__PURE__ */ O("button", {
58
59
  type: "button",
59
- onClick: () => z(`/teams/${X.id}/edit`),
60
+ onClick: () => B(`/teams/${Z.id}/edit`),
60
61
  className: "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",
61
- children: [/* @__PURE__ */ E(y, { className: "h-4 w-4" }), " Edit"]
62
+ children: [/* @__PURE__ */ D(b, { className: "h-4 w-4" }), " Edit"]
62
63
  }),
63
- X.status !== "ARCHIVED" && /* @__PURE__ */ D("button", {
64
+ Z.status !== "ARCHIVED" && /* @__PURE__ */ O("button", {
64
65
  type: "button",
65
66
  onClick: async () => {
66
- R && (await V.mutateAsync(R), z("/teams"));
67
+ z && (await H.mutateAsync(z), B("/teams"));
67
68
  },
68
- disabled: V.isPending,
69
+ disabled: H.isPending,
69
70
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-60",
70
71
  children: [
71
- V.isPending ? /* @__PURE__ */ E(b, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ E(g, { className: "h-4 w-4" }),
72
+ H.isPending ? /* @__PURE__ */ D(x, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ D(_, { className: "h-4 w-4" }),
72
73
  " ",
73
74
  "Archive"
74
75
  ]
@@ -76,246 +77,240 @@ function R() {
76
77
  ]
77
78
  }),
78
79
  children: [
79
- /* @__PURE__ */ D(k, {
80
+ /* @__PURE__ */ O(A, {
80
81
  treatment: "insight",
81
82
  className: "mb-8 p-6",
82
83
  children: [
83
- /* @__PURE__ */ D("div", {
84
+ /* @__PURE__ */ O("div", {
84
85
  className: "flex flex-wrap items-center gap-3",
85
86
  children: [
86
- /* @__PURE__ */ E(n, { status: X.status }),
87
- X.ageGroup && /* @__PURE__ */ D("span", {
87
+ /* @__PURE__ */ D(n, { status: Z.status }),
88
+ Z.ageGroup && /* @__PURE__ */ O("span", {
88
89
  className: "text-sm text-text-secondary",
89
- children: ["Age group: ", X.ageGroup]
90
+ children: ["Age group: ", Z.ageGroup]
90
91
  }),
91
- X.homeVenue && /* @__PURE__ */ D("span", {
92
+ Z.homeVenue && /* @__PURE__ */ O("span", {
92
93
  className: "flex items-center gap-1 text-sm text-text-secondary",
93
94
  children: [
94
- /* @__PURE__ */ E(x, { className: "h-3.5 w-3.5" }),
95
+ /* @__PURE__ */ D(S, { className: "h-3.5 w-3.5" }),
95
96
  " ",
96
- X.homeVenue
97
+ Z.homeVenue
97
98
  ]
98
99
  })
99
100
  ]
100
101
  }),
101
- X.description && /* @__PURE__ */ E("p", {
102
+ Z.description && /* @__PURE__ */ D("p", {
102
103
  className: "mt-4 text-sm text-text-secondary",
103
- children: X.description
104
+ children: Z.description
104
105
  }),
105
- X.tags.length > 0 && /* @__PURE__ */ E("div", {
106
+ Z.tags.length > 0 && /* @__PURE__ */ D("div", {
106
107
  className: "mt-4 flex flex-wrap gap-1.5",
107
- children: X.tags.map((e) => /* @__PURE__ */ E("span", {
108
+ children: Z.tags.map((e) => /* @__PURE__ */ D("span", {
108
109
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
109
110
  children: e
110
111
  }, e))
111
112
  })
112
113
  ]
113
114
  }),
114
- /* @__PURE__ */ D("section", {
115
+ /* @__PURE__ */ O("section", {
115
116
  className: "mb-8",
116
- children: [/* @__PURE__ */ D("div", {
117
+ children: [/* @__PURE__ */ O("div", {
117
118
  className: "mb-4 flex items-center justify-between",
118
- children: [/* @__PURE__ */ D("h2", {
119
+ children: [/* @__PURE__ */ O("h2", {
119
120
  className: "text-lg font-semibold text-text-primary",
120
121
  children: [
121
122
  "Roster (",
122
- Z.length,
123
+ Q.length,
123
124
  ")"
124
125
  ]
125
- }), /* @__PURE__ */ D("button", {
126
+ }), /* @__PURE__ */ O("button", {
126
127
  type: "button",
127
128
  onClick: () => {
128
- Y(null), G(!0);
129
+ X(null), K(!0);
129
130
  },
130
131
  className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
131
- children: [/* @__PURE__ */ E(w, { className: "h-4 w-4" }), " Add member"]
132
+ children: [/* @__PURE__ */ D(T, { className: "h-4 w-4" }), " Add member"]
132
133
  })]
133
- }), Z.length === 0 ? /* @__PURE__ */ E(o, {
134
+ }), Q.length === 0 ? /* @__PURE__ */ D(o, {
134
135
  illustration: "empty-data",
135
- icon: /* @__PURE__ */ E(w, { className: "h-10 w-10" }),
136
+ icon: /* @__PURE__ */ D(T, { className: "h-10 w-10" }),
136
137
  title: "No members yet",
137
138
  description: "Add players, coaches and staff to build the roster."
138
- }) : /* @__PURE__ */ E(O, { children: /* @__PURE__ */ E("div", {
139
+ }) : /* @__PURE__ */ D(k, { children: /* @__PURE__ */ D("div", {
139
140
  className: "divide-y divide-border-seam",
140
- children: Z.map((e) => /* @__PURE__ */ D("div", {
141
+ children: Q.map((e) => /* @__PURE__ */ O("div", {
141
142
  className: "flex items-center gap-4 py-3",
142
143
  children: [
143
- /* @__PURE__ */ E("div", {
144
+ /* @__PURE__ */ D("div", {
144
145
  className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold tabular-nums text-text-primary",
145
146
  children: e.jerseyNumber ?? e.displayName.charAt(0).toUpperCase()
146
147
  }),
147
- /* @__PURE__ */ D("div", {
148
+ /* @__PURE__ */ O("div", {
148
149
  className: "min-w-0 flex-1",
149
- children: [/* @__PURE__ */ E("p", {
150
+ children: [/* @__PURE__ */ D("p", {
150
151
  className: "truncate text-sm font-medium text-text-primary",
151
152
  children: e.displayName
152
- }), /* @__PURE__ */ D("p", {
153
+ }), /* @__PURE__ */ O("p", {
153
154
  className: "text-xs text-text-secondary",
154
155
  children: [r[e.role], e.position ? ` · ${e.position}` : ""]
155
156
  })]
156
157
  }),
157
- /* @__PURE__ */ E(n, { status: e.status }),
158
- /* @__PURE__ */ E("button", {
158
+ /* @__PURE__ */ D(n, { status: e.status }),
159
+ /* @__PURE__ */ D("button", {
159
160
  type: "button",
160
- onClick: () => void U.mutate(e.id),
161
- disabled: U.isPending,
161
+ onClick: () => void W.mutate(e.id),
162
+ disabled: W.isPending,
162
163
  "aria-label": `Remove ${e.displayName}`,
163
164
  className: "rounded-lg p-2 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-60",
164
- children: /* @__PURE__ */ E(C, { className: "h-4 w-4" })
165
+ children: /* @__PURE__ */ D(w, { className: "h-4 w-4" })
165
166
  })
166
167
  ]
167
168
  }, e.id))
168
169
  }) })]
169
170
  }),
170
- /* @__PURE__ */ D("section", { children: [/* @__PURE__ */ D("div", {
171
+ /* @__PURE__ */ O("section", { children: [/* @__PURE__ */ O("div", {
171
172
  className: "mb-4 flex items-center justify-between",
172
- children: [/* @__PURE__ */ D("h2", {
173
+ children: [/* @__PURE__ */ O("h2", {
173
174
  className: "text-lg font-semibold text-text-primary",
174
175
  children: [
175
176
  "Fixtures (",
176
- Q.length,
177
+ $.length,
177
178
  ")"
178
179
  ]
179
- }), /* @__PURE__ */ D("button", {
180
+ }), /* @__PURE__ */ O("button", {
180
181
  type: "button",
181
- onClick: () => z(`/fixtures/new?homeTeamId=${X.id}`),
182
+ onClick: () => B(`/fixtures/new?homeTeamId=${Z.id}`),
182
183
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
183
- children: [/* @__PURE__ */ E(S, { className: "h-4 w-4" }), " Schedule"]
184
+ children: [/* @__PURE__ */ D(C, { className: "h-4 w-4" }), " Schedule"]
184
185
  })]
185
- }), Q.length === 0 ? /* @__PURE__ */ E(o, {
186
+ }), $.length === 0 ? /* @__PURE__ */ D(o, {
186
187
  illustration: "empty-calendar",
187
- icon: /* @__PURE__ */ E(v, { className: "h-10 w-10" }),
188
+ icon: /* @__PURE__ */ D(y, { className: "h-10 w-10" }),
188
189
  title: "No fixtures scheduled",
189
190
  description: "Schedule a match for this team to start tracking results."
190
- }) : /* @__PURE__ */ E("div", {
191
+ }) : /* @__PURE__ */ D("div", {
191
192
  className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",
192
- children: Q.map((e) => /* @__PURE__ */ E(a, {
193
+ children: $.map((e) => /* @__PURE__ */ D(a, {
193
194
  fixture: e,
194
- onClick: () => z(`/fixtures/${e.id}`)
195
+ onClick: () => B(`/fixtures/${e.id}`)
195
196
  }, e.id))
196
197
  })] }),
197
- /* @__PURE__ */ E(A, {
198
- open: W,
199
- onOpenChange: G,
200
- children: /* @__PURE__ */ D(j, { children: [/* @__PURE__ */ E(N, { children: /* @__PURE__ */ E(P, { children: "Add member" }) }), /* @__PURE__ */ D("form", {
198
+ /* @__PURE__ */ D(j, {
199
+ open: G,
200
+ onOpenChange: K,
201
+ children: /* @__PURE__ */ O(M, { children: [/* @__PURE__ */ D(P, { children: /* @__PURE__ */ D(F, { children: "Add member" }) }), /* @__PURE__ */ O("form", {
201
202
  onSubmit: async (e) => {
202
- if (e.preventDefault(), Y(null), !R) return;
203
- if (!K.userId.trim() || !K.displayName.trim()) {
204
- Y("User ID and display name are required.");
203
+ if (e.preventDefault(), X(null), !z) return;
204
+ if (!q.userId.trim() || !q.displayName.trim()) {
205
+ X("User ID and display name are required.");
205
206
  return;
206
207
  }
207
- let t = K.jerseyNumber.trim() ? Number.parseInt(K.jerseyNumber, 10) : void 0;
208
+ let t = q.jerseyNumber.trim() ? Number.parseInt(q.jerseyNumber, 10) : void 0;
208
209
  if (t !== void 0 && Number.isNaN(t)) {
209
- Y("Jersey number must be a number.");
210
+ X("Jersey number must be a number.");
210
211
  return;
211
212
  }
212
213
  try {
213
- await H.mutateAsync({
214
- teamId: R,
215
- userId: K.userId.trim(),
216
- displayName: K.displayName.trim(),
217
- role: K.role,
218
- status: K.status,
219
- position: K.position.trim() || void 0,
214
+ await U.mutateAsync({
215
+ teamId: z,
216
+ userId: q.userId.trim(),
217
+ displayName: q.displayName.trim(),
218
+ role: q.role,
219
+ status: q.status,
220
+ position: q.position.trim() || void 0,
220
221
  jerseyNumber: t
221
- }), q(L), G(!1);
222
+ }), J(R), K(!1);
222
223
  } catch (e) {
223
- Y(e instanceof Error ? e.message : "Failed to add member.");
224
+ X(e instanceof Error ? e.message : "Failed to add member.");
224
225
  }
225
226
  },
226
227
  className: "space-y-4 px-1",
227
228
  children: [
228
- /* @__PURE__ */ E(p, {
229
- label: "User ID",
230
- htmlFor: "userId",
231
- required: !0,
232
- hint: "The auth-svc user id.",
233
- children: /* @__PURE__ */ E("input", {
234
- id: "userId",
235
- className: m,
236
- value: K.userId,
237
- onChange: (e) => q((t) => ({
238
- ...t,
239
- userId: e.target.value
240
- })),
241
- placeholder: "user-uuid"
242
- })
229
+ /* @__PURE__ */ D(h, {
230
+ userId: q.userId,
231
+ displayName: q.displayName,
232
+ onSelect: ({ userId: e, displayName: t }) => J((n) => ({
233
+ ...n,
234
+ userId: e,
235
+ displayName: t || n.displayName
236
+ })),
237
+ required: !0
243
238
  }),
244
- /* @__PURE__ */ E(p, {
239
+ /* @__PURE__ */ D(p, {
245
240
  label: "Display name",
246
241
  htmlFor: "displayName",
247
242
  required: !0,
248
- children: /* @__PURE__ */ E("input", {
243
+ children: /* @__PURE__ */ D("input", {
249
244
  id: "displayName",
250
245
  className: m,
251
- value: K.displayName,
252
- onChange: (e) => q((t) => ({
246
+ value: q.displayName,
247
+ onChange: (e) => J((t) => ({
253
248
  ...t,
254
249
  displayName: e.target.value
255
250
  })),
256
251
  placeholder: "e.g. Alex Morgan"
257
252
  })
258
253
  }),
259
- /* @__PURE__ */ D("div", {
254
+ /* @__PURE__ */ O("div", {
260
255
  className: "grid grid-cols-2 gap-4",
261
- children: [/* @__PURE__ */ E(p, {
256
+ children: [/* @__PURE__ */ D(p, {
262
257
  label: "Role",
263
258
  htmlFor: "role",
264
- children: /* @__PURE__ */ E("select", {
259
+ children: /* @__PURE__ */ D("select", {
265
260
  id: "role",
266
261
  className: m,
267
- value: K.role,
268
- onChange: (e) => q((t) => ({
262
+ value: q.role,
263
+ onChange: (e) => J((t) => ({
269
264
  ...t,
270
265
  role: e.target.value
271
266
  })),
272
- children: F.map((e) => /* @__PURE__ */ E("option", {
267
+ children: I.map((e) => /* @__PURE__ */ D("option", {
273
268
  value: e,
274
269
  children: r[e]
275
270
  }, e))
276
271
  })
277
- }), /* @__PURE__ */ E(p, {
272
+ }), /* @__PURE__ */ D(p, {
278
273
  label: "Status",
279
274
  htmlFor: "memberStatus",
280
- children: /* @__PURE__ */ E("select", {
275
+ children: /* @__PURE__ */ D("select", {
281
276
  id: "memberStatus",
282
277
  className: m,
283
- value: K.status,
284
- onChange: (e) => q((t) => ({
278
+ value: q.status,
279
+ onChange: (e) => J((t) => ({
285
280
  ...t,
286
281
  status: e.target.value
287
282
  })),
288
- children: I.map((e) => /* @__PURE__ */ E("option", {
283
+ children: L.map((e) => /* @__PURE__ */ D("option", {
289
284
  value: e,
290
285
  children: e.charAt(0) + e.slice(1).toLowerCase()
291
286
  }, e))
292
287
  })
293
288
  })]
294
289
  }),
295
- /* @__PURE__ */ D("div", {
290
+ /* @__PURE__ */ O("div", {
296
291
  className: "grid grid-cols-2 gap-4",
297
- children: [/* @__PURE__ */ E(p, {
292
+ children: [/* @__PURE__ */ D(p, {
298
293
  label: "Position",
299
294
  htmlFor: "position",
300
- children: /* @__PURE__ */ E("input", {
295
+ children: /* @__PURE__ */ D("input", {
301
296
  id: "position",
302
297
  className: m,
303
- value: K.position,
304
- onChange: (e) => q((t) => ({
298
+ value: q.position,
299
+ onChange: (e) => J((t) => ({
305
300
  ...t,
306
301
  position: e.target.value
307
302
  })),
308
303
  placeholder: "e.g. Striker"
309
304
  })
310
- }), /* @__PURE__ */ E(p, {
305
+ }), /* @__PURE__ */ D(p, {
311
306
  label: "Jersey #",
312
307
  htmlFor: "jersey",
313
- children: /* @__PURE__ */ E("input", {
308
+ children: /* @__PURE__ */ D("input", {
314
309
  id: "jersey",
315
310
  className: m,
316
311
  inputMode: "numeric",
317
- value: K.jerseyNumber,
318
- onChange: (e) => q((t) => ({
312
+ value: q.jerseyNumber,
313
+ onChange: (e) => J((t) => ({
319
314
  ...t,
320
315
  jerseyNumber: e.target.value
321
316
  })),
@@ -323,20 +318,20 @@ function R() {
323
318
  })
324
319
  })]
325
320
  }),
326
- J && /* @__PURE__ */ E("p", {
321
+ Y && /* @__PURE__ */ D("p", {
327
322
  className: "text-sm text-status-error-text",
328
- children: J
323
+ children: Y
329
324
  }),
330
- /* @__PURE__ */ D(M, { children: [/* @__PURE__ */ E("button", {
325
+ /* @__PURE__ */ O(N, { children: [/* @__PURE__ */ D("button", {
331
326
  type: "button",
332
- onClick: () => G(!1),
327
+ onClick: () => K(!1),
333
328
  className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
334
329
  children: "Cancel"
335
- }), /* @__PURE__ */ D("button", {
330
+ }), /* @__PURE__ */ O("button", {
336
331
  type: "submit",
337
- disabled: H.isPending,
332
+ disabled: U.isPending,
338
333
  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",
339
- children: [H.isPending && /* @__PURE__ */ E(b, { className: "h-4 w-4 animate-spin" }), "Add member"]
334
+ children: [U.isPending && /* @__PURE__ */ D(x, { className: "h-4 w-4 animate-spin" }), "Add member"]
340
335
  })] })
341
336
  ]
342
337
  })] })
@@ -345,6 +340,6 @@ function R() {
345
340
  });
346
341
  }
347
342
  //#endregion
348
- export { R as TeamDetailPage };
343
+ export { z as TeamDetailPage };
349
344
 
350
345
  //# sourceMappingURL=TeamDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamDetailPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/teams/TeamDetailPage.tsx"],"sourcesContent":["/**\n * Team Detail\n * @module atheletebridge/pages/teams\n *\n * Reads a single team (with members + fixtures) from `athTeam`, supports adding\n * and removing members (athAddMember / athRemoveMember), editing and archiving\n * the team (athUpdateTeam via the form / athArchiveTeam), and links into the\n * team's fixtures.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n CalendarDays,\n Edit,\n Archive,\n MapPin,\n Plus,\n Trash2,\n UserPlus,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n EmphasisPanel,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { FixtureCard } from '../../components/FixtureCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/LoadingState';\nimport { FormField, fieldInputClass } from '../../components/form';\nimport { SPORT_LABELS, MEMBER_ROLE_LABELS } from '../../components/domain';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport {\n useTeam,\n useArchiveTeam,\n useAddMember,\n useRemoveMember,\n} from '../../hooks/useAthleteBridgeApi';\nimport type { AthMemberRole, AthMemberStatus } from '../../types';\n\nconst ROLES = Object.keys(MEMBER_ROLE_LABELS) as AthMemberRole[];\nconst MEMBER_STATUSES: AthMemberStatus[] = ['TRIAL', 'ACTIVE', 'INJURED', 'SUSPENDED', 'RELEASED'];\n\ninterface AddMemberForm {\n userId: string;\n displayName: string;\n role: AthMemberRole;\n status: AthMemberStatus;\n position: string;\n jerseyNumber: string;\n}\n\nconst EMPTY_MEMBER: AddMemberForm = {\n userId: '',\n displayName: '',\n role: 'PLAYER',\n status: 'ACTIVE',\n position: '',\n jerseyNumber: '',\n};\n\nexport function TeamDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useAthleteBridge();\n\n const team = useTeam(id);\n const archiveTeam = useArchiveTeam();\n const addMember = useAddMember();\n const removeMember = useRemoveMember(id);\n\n const [addOpen, setAddOpen] = useState(false);\n const [memberForm, setMemberForm] = useState<AddMemberForm>(EMPTY_MEMBER);\n const [memberError, setMemberError] = useState<string | null>(null);\n\n if (team.isLoading) {\n return (\n <PageLayout title=\"Team\">\n <LoadingState label=\"Loading team…\" />\n </PageLayout>\n );\n }\n\n if (team.isError || !team.data) {\n return (\n <PageLayout title=\"Team\">\n <ErrorState\n title=\"Team not found\"\n message=\"This team does not exist or you do not have access to it.\"\n onRetry={() => navigateTo('/teams')}\n />\n </PageLayout>\n );\n }\n\n const t = team.data;\n const members = t.members ?? [];\n const fixtures = t.fixtures ?? [];\n\n const handleArchive = async () => {\n if (!id) return;\n await archiveTeam.mutateAsync(id);\n navigateTo('/teams');\n };\n\n const handleAddMember = async (e: React.FormEvent) => {\n e.preventDefault();\n setMemberError(null);\n if (!id) return;\n if (!memberForm.userId.trim() || !memberForm.displayName.trim()) {\n setMemberError('User ID and display name are required.');\n return;\n }\n const jersey = memberForm.jerseyNumber.trim()\n ? Number.parseInt(memberForm.jerseyNumber, 10)\n : undefined;\n if (jersey !== undefined && Number.isNaN(jersey)) {\n setMemberError('Jersey number must be a number.');\n return;\n }\n try {\n await addMember.mutateAsync({\n teamId: id,\n userId: memberForm.userId.trim(),\n displayName: memberForm.displayName.trim(),\n role: memberForm.role,\n status: memberForm.status,\n position: memberForm.position.trim() || undefined,\n jerseyNumber: jersey,\n });\n setMemberForm(EMPTY_MEMBER);\n setAddOpen(false);\n } catch (err) {\n setMemberError(err instanceof Error ? err.message : 'Failed to add member.');\n }\n };\n\n return (\n <PageLayout\n title={t.name}\n description={`${SPORT_LABELS[t.sport]}${t.season ? ` · ${t.season}` : ''}`}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/teams')}\n className=\"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\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/teams/${t.id}/edit`)}\n className=\"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\"\n >\n <Edit className=\"h-4 w-4\" /> Edit\n </button>\n {t.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n onClick={handleArchive}\n disabled={archiveTeam.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-60\"\n >\n {archiveTeam.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Archive className=\"h-4 w-4\" />\n )}{' '}\n Archive\n </button>\n )}\n </div>\n }\n >\n {/* Summary */}\n <GlassCard treatment=\"insight\" className=\"mb-8 p-6\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <StatusBadge status={t.status} />\n {t.ageGroup && (\n <span className=\"text-sm text-text-secondary\">Age group: {t.ageGroup}</span>\n )}\n {t.homeVenue && (\n <span className=\"flex items-center gap-1 text-sm text-text-secondary\">\n <MapPin className=\"h-3.5 w-3.5\" /> {t.homeVenue}\n </span>\n )}\n </div>\n {t.description && <p className=\"mt-4 text-sm text-text-secondary\">{t.description}</p>}\n {t.tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-1.5\">\n {t.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </GlassCard>\n\n {/* Roster */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Roster ({members.length})</h2>\n <button\n type=\"button\"\n onClick={() => {\n setMemberError(null);\n setAddOpen(true);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <UserPlus className=\"h-4 w-4\" /> Add member\n </button>\n </div>\n\n {members.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<UserPlus className=\"h-10 w-10\" />}\n title=\"No members yet\"\n description=\"Add players, coaches and staff to build the roster.\"\n />\n ) : (\n <EmphasisPanel>\n <div className=\"divide-y divide-border-seam\">\n {members.map((m) => (\n <div key={m.id} className=\"flex items-center gap-4 py-3\">\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold tabular-nums text-text-primary\">\n {m.jerseyNumber ?? m.displayName.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {m.displayName}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {MEMBER_ROLE_LABELS[m.role]}\n {m.position ? ` · ${m.position}` : ''}\n </p>\n </div>\n <StatusBadge status={m.status} />\n <button\n type=\"button\"\n onClick={() => void removeMember.mutate(m.id)}\n disabled={removeMember.isPending}\n aria-label={`Remove ${m.displayName}`}\n className=\"rounded-lg p-2 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-60\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n )}\n </section>\n\n {/* Fixtures */}\n <section>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Fixtures ({fixtures.length})</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/fixtures/new?homeTeamId=${t.id}`)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"h-4 w-4\" /> Schedule\n </button>\n </div>\n {fixtures.length === 0 ? (\n <EmptyState\n illustration=\"empty-calendar\"\n icon={<CalendarDays className=\"h-10 w-10\" />}\n title=\"No fixtures scheduled\"\n description=\"Schedule a match for this team to start tracking results.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {fixtures.map((f) => (\n <FixtureCard key={f.id} fixture={f} onClick={() => navigateTo(`/fixtures/${f.id}`)} />\n ))}\n </div>\n )}\n </section>\n\n {/* Add member dialog */}\n <ResponsiveDialog open={addOpen} onOpenChange={setAddOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add member</ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <form onSubmit={handleAddMember} className=\"space-y-4 px-1\">\n <FormField label=\"User ID\" htmlFor=\"userId\" required hint=\"The auth-svc user id.\">\n <input\n id=\"userId\"\n className={fieldInputClass}\n value={memberForm.userId}\n onChange={(e) => setMemberForm((p) => ({ ...p, userId: e.target.value }))}\n placeholder=\"user-uuid\"\n />\n </FormField>\n <FormField label=\"Display name\" htmlFor=\"displayName\" required>\n <input\n id=\"displayName\"\n className={fieldInputClass}\n value={memberForm.displayName}\n onChange={(e) => setMemberForm((p) => ({ ...p, displayName: e.target.value }))}\n placeholder=\"e.g. Alex Morgan\"\n />\n </FormField>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Role\" htmlFor=\"role\">\n <select\n id=\"role\"\n className={fieldInputClass}\n value={memberForm.role}\n onChange={(e) =>\n setMemberForm((p) => ({ ...p, role: e.target.value as AthMemberRole }))\n }\n >\n {ROLES.map((r) => (\n <option key={r} value={r}>\n {MEMBER_ROLE_LABELS[r]}\n </option>\n ))}\n </select>\n </FormField>\n <FormField label=\"Status\" htmlFor=\"memberStatus\">\n <select\n id=\"memberStatus\"\n className={fieldInputClass}\n value={memberForm.status}\n onChange={(e) =>\n setMemberForm((p) => ({ ...p, status: e.target.value as AthMemberStatus }))\n }\n >\n {MEMBER_STATUSES.map((s) => (\n <option key={s} value={s}>\n {s.charAt(0) + s.slice(1).toLowerCase()}\n </option>\n ))}\n </select>\n </FormField>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Position\" htmlFor=\"position\">\n <input\n id=\"position\"\n className={fieldInputClass}\n value={memberForm.position}\n onChange={(e) => setMemberForm((p) => ({ ...p, position: e.target.value }))}\n placeholder=\"e.g. Striker\"\n />\n </FormField>\n <FormField label=\"Jersey #\" htmlFor=\"jersey\">\n <input\n id=\"jersey\"\n className={fieldInputClass}\n inputMode=\"numeric\"\n value={memberForm.jerseyNumber}\n onChange={(e) => setMemberForm((p) => ({ ...p, jerseyNumber: e.target.value }))}\n placeholder=\"9\"\n />\n </FormField>\n </div>\n {memberError && <p className=\"text-sm text-status-error-text\">{memberError}</p>}\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setAddOpen(false)}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={addMember.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 {addMember.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n Add member\n </button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TeamDetailPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/teams/TeamDetailPage.tsx"],"sourcesContent":["/**\n * Team Detail\n * @module atheletebridge/pages/teams\n *\n * Reads a single team (with members + fixtures) from `athTeam`, supports adding\n * and removing members (athAddMember / athRemoveMember), editing and archiving\n * the team (athUpdateTeam via the form / athArchiveTeam), and links into the\n * team's fixtures.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n CalendarDays,\n Edit,\n Archive,\n MapPin,\n Plus,\n Trash2,\n UserPlus,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n EmphasisPanel,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { FixtureCard } from '../../components/FixtureCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/LoadingState';\nimport { FormField, fieldInputClass } from '../../components/form';\nimport { UserSearchSelect } from '../../components/UserSearchSelect';\nimport { SPORT_LABELS, MEMBER_ROLE_LABELS } from '../../components/domain';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport {\n useTeam,\n useArchiveTeam,\n useAddMember,\n useRemoveMember,\n} from '../../hooks/useAthleteBridgeApi';\nimport type { AthMemberRole, AthMemberStatus } from '../../types';\n\nconst ROLES = Object.keys(MEMBER_ROLE_LABELS) as AthMemberRole[];\nconst MEMBER_STATUSES: AthMemberStatus[] = ['TRIAL', 'ACTIVE', 'INJURED', 'SUSPENDED', 'RELEASED'];\n\ninterface AddMemberForm {\n userId: string;\n displayName: string;\n role: AthMemberRole;\n status: AthMemberStatus;\n position: string;\n jerseyNumber: string;\n}\n\nconst EMPTY_MEMBER: AddMemberForm = {\n userId: '',\n displayName: '',\n role: 'PLAYER',\n status: 'ACTIVE',\n position: '',\n jerseyNumber: '',\n};\n\nexport function TeamDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useAthleteBridge();\n\n const team = useTeam(id);\n const archiveTeam = useArchiveTeam();\n const addMember = useAddMember();\n const removeMember = useRemoveMember(id);\n\n const [addOpen, setAddOpen] = useState(false);\n const [memberForm, setMemberForm] = useState<AddMemberForm>(EMPTY_MEMBER);\n const [memberError, setMemberError] = useState<string | null>(null);\n\n if (team.isLoading) {\n return (\n <PageLayout title=\"Team\">\n <LoadingState label=\"Loading team…\" />\n </PageLayout>\n );\n }\n\n if (team.isError || !team.data) {\n return (\n <PageLayout title=\"Team\">\n <ErrorState\n title=\"Team not found\"\n message=\"This team does not exist or you do not have access to it.\"\n onRetry={() => navigateTo('/teams')}\n />\n </PageLayout>\n );\n }\n\n const t = team.data;\n const members = t.members ?? [];\n const fixtures = t.fixtures ?? [];\n\n const handleArchive = async () => {\n if (!id) return;\n await archiveTeam.mutateAsync(id);\n navigateTo('/teams');\n };\n\n const handleAddMember = async (e: React.FormEvent) => {\n e.preventDefault();\n setMemberError(null);\n if (!id) return;\n if (!memberForm.userId.trim() || !memberForm.displayName.trim()) {\n setMemberError('User ID and display name are required.');\n return;\n }\n const jersey = memberForm.jerseyNumber.trim()\n ? Number.parseInt(memberForm.jerseyNumber, 10)\n : undefined;\n if (jersey !== undefined && Number.isNaN(jersey)) {\n setMemberError('Jersey number must be a number.');\n return;\n }\n try {\n await addMember.mutateAsync({\n teamId: id,\n userId: memberForm.userId.trim(),\n displayName: memberForm.displayName.trim(),\n role: memberForm.role,\n status: memberForm.status,\n position: memberForm.position.trim() || undefined,\n jerseyNumber: jersey,\n });\n setMemberForm(EMPTY_MEMBER);\n setAddOpen(false);\n } catch (err) {\n setMemberError(err instanceof Error ? err.message : 'Failed to add member.');\n }\n };\n\n return (\n <PageLayout\n title={t.name}\n description={`${SPORT_LABELS[t.sport]}${t.season ? ` · ${t.season}` : ''}`}\n actions={\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/teams')}\n className=\"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\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/teams/${t.id}/edit`)}\n className=\"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\"\n >\n <Edit className=\"h-4 w-4\" /> Edit\n </button>\n {t.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n onClick={handleArchive}\n disabled={archiveTeam.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-60\"\n >\n {archiveTeam.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Archive className=\"h-4 w-4\" />\n )}{' '}\n Archive\n </button>\n )}\n </div>\n }\n >\n {/* Summary */}\n <GlassCard treatment=\"insight\" className=\"mb-8 p-6\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <StatusBadge status={t.status} />\n {t.ageGroup && (\n <span className=\"text-sm text-text-secondary\">Age group: {t.ageGroup}</span>\n )}\n {t.homeVenue && (\n <span className=\"flex items-center gap-1 text-sm text-text-secondary\">\n <MapPin className=\"h-3.5 w-3.5\" /> {t.homeVenue}\n </span>\n )}\n </div>\n {t.description && <p className=\"mt-4 text-sm text-text-secondary\">{t.description}</p>}\n {t.tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-1.5\">\n {t.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </GlassCard>\n\n {/* Roster */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Roster ({members.length})</h2>\n <button\n type=\"button\"\n onClick={() => {\n setMemberError(null);\n setAddOpen(true);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <UserPlus className=\"h-4 w-4\" /> Add member\n </button>\n </div>\n\n {members.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<UserPlus className=\"h-10 w-10\" />}\n title=\"No members yet\"\n description=\"Add players, coaches and staff to build the roster.\"\n />\n ) : (\n <EmphasisPanel>\n <div className=\"divide-y divide-border-seam\">\n {members.map((m) => (\n <div key={m.id} className=\"flex items-center gap-4 py-3\">\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold tabular-nums text-text-primary\">\n {m.jerseyNumber ?? m.displayName.charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {m.displayName}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {MEMBER_ROLE_LABELS[m.role]}\n {m.position ? ` · ${m.position}` : ''}\n </p>\n </div>\n <StatusBadge status={m.status} />\n <button\n type=\"button\"\n onClick={() => void removeMember.mutate(m.id)}\n disabled={removeMember.isPending}\n aria-label={`Remove ${m.displayName}`}\n className=\"rounded-lg p-2 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-60\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n )}\n </section>\n\n {/* Fixtures */}\n <section>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Fixtures ({fixtures.length})</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/fixtures/new?homeTeamId=${t.id}`)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"h-4 w-4\" /> Schedule\n </button>\n </div>\n {fixtures.length === 0 ? (\n <EmptyState\n illustration=\"empty-calendar\"\n icon={<CalendarDays className=\"h-10 w-10\" />}\n title=\"No fixtures scheduled\"\n description=\"Schedule a match for this team to start tracking results.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {fixtures.map((f) => (\n <FixtureCard key={f.id} fixture={f} onClick={() => navigateTo(`/fixtures/${f.id}`)} />\n ))}\n </div>\n )}\n </section>\n\n {/* Add member dialog */}\n <ResponsiveDialog open={addOpen} onOpenChange={setAddOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add member</ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <form onSubmit={handleAddMember} className=\"space-y-4 px-1\">\n <UserSearchSelect\n userId={memberForm.userId}\n displayName={memberForm.displayName}\n onSelect={({ userId, displayName }) =>\n setMemberForm((p) => ({ ...p, userId, displayName: displayName || p.displayName }))\n }\n required\n />\n <FormField label=\"Display name\" htmlFor=\"displayName\" required>\n <input\n id=\"displayName\"\n className={fieldInputClass}\n value={memberForm.displayName}\n onChange={(e) => setMemberForm((p) => ({ ...p, displayName: e.target.value }))}\n placeholder=\"e.g. Alex Morgan\"\n />\n </FormField>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Role\" htmlFor=\"role\">\n <select\n id=\"role\"\n className={fieldInputClass}\n value={memberForm.role}\n onChange={(e) =>\n setMemberForm((p) => ({ ...p, role: e.target.value as AthMemberRole }))\n }\n >\n {ROLES.map((r) => (\n <option key={r} value={r}>\n {MEMBER_ROLE_LABELS[r]}\n </option>\n ))}\n </select>\n </FormField>\n <FormField label=\"Status\" htmlFor=\"memberStatus\">\n <select\n id=\"memberStatus\"\n className={fieldInputClass}\n value={memberForm.status}\n onChange={(e) =>\n setMemberForm((p) => ({ ...p, status: e.target.value as AthMemberStatus }))\n }\n >\n {MEMBER_STATUSES.map((s) => (\n <option key={s} value={s}>\n {s.charAt(0) + s.slice(1).toLowerCase()}\n </option>\n ))}\n </select>\n </FormField>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <FormField label=\"Position\" htmlFor=\"position\">\n <input\n id=\"position\"\n className={fieldInputClass}\n value={memberForm.position}\n onChange={(e) => setMemberForm((p) => ({ ...p, position: e.target.value }))}\n placeholder=\"e.g. Striker\"\n />\n </FormField>\n <FormField label=\"Jersey #\" htmlFor=\"jersey\">\n <input\n id=\"jersey\"\n className={fieldInputClass}\n inputMode=\"numeric\"\n value={memberForm.jerseyNumber}\n onChange={(e) => setMemberForm((p) => ({ ...p, jerseyNumber: e.target.value }))}\n placeholder=\"9\"\n />\n </FormField>\n </div>\n {memberError && <p className=\"text-sm text-status-error-text\">{memberError}</p>}\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setAddOpen(false)}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={addMember.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 {addMember.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n Add member\n </button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,14 +1,5 @@
1
1
  //#region src/atheletebridge/utils/formatters.ts
2
2
  function e(e, t) {
3
- return new Intl.NumberFormat("en-IN", {
4
- style: "currency",
5
- currency: "INR",
6
- minimumFractionDigits: 2,
7
- maximumFractionDigits: 2,
8
- ...t
9
- }).format(e);
10
- }
11
- function t(e, t) {
12
3
  let n = typeof e == "string" ? new Date(e) : e;
13
4
  return new Intl.DateTimeFormat("en-IN", {
14
5
  day: "numeric",
@@ -20,21 +11,7 @@ function t(e, t) {
20
11
  ...t
21
12
  }).format(n);
22
13
  }
23
- function n(e) {
24
- let t = typeof e == "string" ? new Date(e) : e, n = (/* @__PURE__ */ new Date()).getTime() - t.getTime(), r = Math.floor(n / 1e3), i = Math.floor(r / 60), a = Math.floor(i / 60), o = Math.floor(a / 24), s = Math.floor(o / 7), c = Math.floor(o / 30);
25
- if (r < 60) return "just now";
26
- if (i < 60) return `${i} min${i === 1 ? "" : "s"} ago`;
27
- if (a < 24) return `${a} hour${a === 1 ? "" : "s"} ago`;
28
- if (o < 7) return `${o} day${o === 1 ? "" : "s"} ago`;
29
- if (s < 4) return `${s} week${s === 1 ? "" : "s"} ago`;
30
- if (c < 12) return `${c} month${c === 1 ? "" : "s"} ago`;
31
- let l = Math.floor(o / 365);
32
- return `${l} year${l === 1 ? "" : "s"} ago`;
33
- }
34
- function r(e, t) {
35
- return new Intl.NumberFormat("en-IN", t).format(e);
36
- }
37
- function i(e) {
14
+ function t(e) {
38
15
  if (e < 1) return "instant";
39
16
  if (e < 60) return `${e} min`;
40
17
  let t = Math.floor(e / 60), n = e % 60;
@@ -43,6 +20,6 @@ function i(e) {
43
20
  return i === 0 ? `${r} day${r === 1 ? "" : "s"}` : `${r} day${r === 1 ? "" : "s"} ${i}h`;
44
21
  }
45
22
  //#endregion
46
- export { e as formatCurrency, t as formatDate, i as formatDuration, r as formatNumber, n as formatRelativeTime };
23
+ export { e as formatDate, t as formatDuration };
47
24
 
48
25
  //# sourceMappingURL=formatters.js.map