@burdenoff/microfe-atheletebridge 2026.805.1 → 2026.829.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 (54) hide show
  1. package/dist/atheletebridge/components/LoadingState.d.ts.map +1 -1
  2. package/dist/atheletebridge/components/LoadingState.js +39 -32
  3. package/dist/atheletebridge/components/LoadingState.js.map +1 -1
  4. package/dist/atheletebridge/components/TeamCard.d.ts.map +1 -1
  5. package/dist/atheletebridge/components/TeamCard.js +45 -49
  6. package/dist/atheletebridge/components/TeamCard.js.map +1 -1
  7. package/dist/atheletebridge/hooks/index.d.ts +1 -1
  8. package/dist/atheletebridge/hooks/index.d.ts.map +1 -1
  9. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts +41 -1
  10. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts.map +1 -1
  11. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +58 -28
  12. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  13. package/dist/atheletebridge/pages/DashboardPage.d.ts.map +1 -1
  14. package/dist/atheletebridge/pages/DashboardPage.js +56 -24
  15. package/dist/atheletebridge/pages/DashboardPage.js.map +1 -1
  16. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.d.ts +6 -2
  17. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.d.ts.map +1 -1
  18. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js +330 -174
  19. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js.map +1 -1
  20. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.d.ts.map +1 -1
  21. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +110 -106
  22. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -1
  23. package/dist/atheletebridge/pages/fixtures/FixturesListPage.d.ts.map +1 -1
  24. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js +80 -71
  25. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js.map +1 -1
  26. package/dist/atheletebridge/pages/onboarding/OnboardingPage.d.ts.map +1 -1
  27. package/dist/atheletebridge/pages/onboarding/OnboardingPage.js +244 -210
  28. package/dist/atheletebridge/pages/onboarding/OnboardingPage.js.map +1 -1
  29. package/dist/atheletebridge/pages/performance/PerformancePage.d.ts +7 -0
  30. package/dist/atheletebridge/pages/performance/PerformancePage.d.ts.map +1 -1
  31. package/dist/atheletebridge/pages/performance/PerformancePage.js +526 -362
  32. package/dist/atheletebridge/pages/performance/PerformancePage.js.map +1 -1
  33. package/dist/atheletebridge/pages/programs/ProgramDetailPage.d.ts.map +1 -1
  34. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +169 -143
  35. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -1
  36. package/dist/atheletebridge/pages/programs/ProgramsListPage.d.ts.map +1 -1
  37. package/dist/atheletebridge/pages/programs/ProgramsListPage.js +77 -72
  38. package/dist/atheletebridge/pages/programs/ProgramsListPage.js.map +1 -1
  39. package/dist/atheletebridge/pages/sessions/SessionDetailPage.d.ts.map +1 -1
  40. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +104 -86
  41. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -1
  42. package/dist/atheletebridge/pages/sessions/SessionsListPage.d.ts.map +1 -1
  43. package/dist/atheletebridge/pages/sessions/SessionsListPage.js +54 -49
  44. package/dist/atheletebridge/pages/sessions/SessionsListPage.js.map +1 -1
  45. package/dist/atheletebridge/pages/teams/TeamDetailPage.d.ts.map +1 -1
  46. package/dist/atheletebridge/pages/teams/TeamDetailPage.js +286 -267
  47. package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -1
  48. package/dist/atheletebridge/pages/teams/TeamFormPage.d.ts.map +1 -1
  49. package/dist/atheletebridge/pages/teams/TeamFormPage.js +185 -180
  50. package/dist/atheletebridge/pages/teams/TeamFormPage.js.map +1 -1
  51. package/dist/atheletebridge/pages/teams/TeamsListPage.d.ts.map +1 -1
  52. package/dist/atheletebridge/pages/teams/TeamsListPage.js +70 -74
  53. package/dist/atheletebridge/pages/teams/TeamsListPage.js.map +1 -1
  54. package/package.json +1 -1
@@ -1,99 +1,116 @@
1
- import { useAthleteBridge as e } from "../../context/AthleteBridgeContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { STATUS as n } from "../../components/viz/lib/palette.js";
4
- import { LineChart as r } from "../../components/viz/LineChart.js";
5
- import { BarChart as i } from "../../components/viz/BarChart.js";
6
- import { DonutChart as a } from "../../components/viz/DonutChart.js";
7
- import { RatingStars as o } from "../../components/viz/RatingStars.js";
1
+ import { useAbTranslate as e } from "../../i18n.js";
2
+ import { useAthleteBridge as t } from "../../context/AthleteBridgeContext.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { STATUS as r } from "../../components/viz/lib/palette.js";
5
+ import { LineChart as i } from "../../components/viz/LineChart.js";
6
+ import { BarChart as a } from "../../components/viz/BarChart.js";
7
+ import { DonutChart as o } from "../../components/viz/DonutChart.js";
8
+ import { RatingStars as s } from "../../components/viz/RatingStars.js";
8
9
  import "../../components/viz/index.js";
9
- import { MetricsCard as s } from "../../components/MetricsCard.js";
10
- import { humanizeEnum as c } from "../../components/domain.js";
11
- import { Crest as l } from "../../components/Crest.js";
12
- import { UserAvatar as u } from "../../components/UserAvatar.js";
13
- import { EmptyState as d } from "../../components/EmptyState.js";
14
- import { ErrorState as f, LoadingState as p } from "../../components/LoadingState.js";
15
- import { useCoachAnalytics as m, useUserDirectory as h } from "../../hooks/useAthleteBridgeApi.js";
16
- import { useMemo as g } from "react";
17
- import { Activity as _, BarChart3 as v, CheckCircle2 as y, Info as b, ListChecks as x, Star as S } from "lucide-react";
18
- import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
19
- import { Badge as E, GlassCard as D, GradientText as O, ResponsiveTable as k, Tooltip as A, TooltipContent as j, TooltipProvider as M, TooltipTrigger as N } from "@burdenoff/fe-libs/ui";
10
+ import { MetricsCard as c } from "../../components/MetricsCard.js";
11
+ import { humanizeEnum as l } from "../../components/domain.js";
12
+ import { Crest as u } from "../../components/Crest.js";
13
+ import { UserAvatar as d } from "../../components/UserAvatar.js";
14
+ import { EmptyState as f } from "../../components/EmptyState.js";
15
+ import { ErrorState as p, LoadingState as m } from "../../components/LoadingState.js";
16
+ import { useCoachAnalytics as h, useUserDirectory as g } from "../../hooks/useAthleteBridgeApi.js";
17
+ import { useMemo as _ } from "react";
18
+ import { Activity as v, BarChart3 as y, CheckCircle2 as b, Info as x, ListChecks as S, Star as C, Users as w } from "lucide-react";
19
+ import { Fragment as T, jsx as E, jsxs as D } from "react/jsx-runtime";
20
+ import { Badge as O, GlassCard as k, GradientText as A, ResponsiveTable as j, Tooltip as M, TooltipContent as N, TooltipProvider as P, TooltipTrigger as F } from "@burdenoff/fe-libs/ui";
20
21
  //#region src/atheletebridge/pages/analytics/CoachAnalyticsPage.tsx
21
- var P = {
22
- COMPLETED: n.success,
23
- CONFIRMED: n.info,
24
- REQUESTED: n.warning,
25
- CANCELLED: n.danger,
22
+ var I = {
23
+ COMPLETED: r.success,
24
+ CONFIRMED: r.info,
25
+ REQUESTED: r.warning,
26
+ CANCELLED: r.danger,
26
27
  NO_SHOW: "var(--color-text-muted)"
27
28
  };
28
- function F(e) {
29
+ function L(e, t) {
29
30
  return e == null ? {
30
- label: "No data",
31
+ label: t("atheletebridge.pages.analytics.acwr.noData", "No data"),
31
32
  variant: "secondary"
32
33
  } : e > 1.5 ? {
33
- label: "At risk",
34
+ label: t("atheletebridge.pages.analytics.acwr.atRisk", "At risk"),
34
35
  variant: "destructive"
35
36
  } : e < .8 || e > 1.3 ? {
36
- label: "Watch",
37
+ label: t("atheletebridge.pages.analytics.acwr.watch", "Watch"),
37
38
  variant: "secondary"
38
39
  } : {
39
- label: "Optimal",
40
+ label: t("atheletebridge.pages.analytics.acwr.optimal", "Optimal"),
40
41
  variant: "default"
41
42
  };
42
43
  }
43
- function I(e, t) {
44
- return e && e.trim() ? e : `Coach ${t.slice(0, 4)}`;
44
+ function R(e, t, n) {
45
+ return e && e.trim() ? e : `${n} ${t.slice(0, 4)}`;
45
46
  }
46
- function L() {
47
- let { navigateTo: n } = e(), L = m(), R = h(L.coachIds), z = g(() => L.sessionsByStatus.map((e) => ({
48
- label: c(e.status),
47
+ var z = (e) => Math.round(e).toLocaleString();
48
+ function B({ value: e, max: t }) {
49
+ let n = t > 0 ? Math.round(e / t * 100) : 0;
50
+ return /* @__PURE__ */ E("span", {
51
+ className: "block h-1.5 w-16 overflow-hidden rounded-full bg-bg-sunken",
52
+ "aria-hidden": "true",
53
+ children: /* @__PURE__ */ E("span", {
54
+ className: "block h-1.5 rounded-full bg-[var(--color-accent-teal)]",
55
+ style: { width: `${Math.max(e > 0 ? 4 : 0, Math.min(100, n))}%` }
56
+ })
57
+ });
58
+ }
59
+ function V() {
60
+ let r = e(), { navigateTo: w } = t(), z = h(), B = g(_(() => [...z.coachIds, ...z.athleteIds], [z.coachIds, z.athleteIds])), V = _(() => z.sessionsByStatus.map((e) => ({
61
+ label: l(e.status),
49
62
  value: e.count,
50
- color: P[e.status]
51
- })), [L.sessionsByStatus]), B = g(() => L.ratingByCoach.map((e) => ({
52
- label: I(R.nameOf(e.coachId), e.coachId),
63
+ color: I[e.status]
64
+ })), [z.sessionsByStatus]), U = _(() => z.ratingByCoach.map((e) => ({
65
+ label: R(B.nameOf(e.coachId), e.coachId, r("atheletebridge.rolePrefix.coach", "Coach")),
53
66
  value: Number(e.avgRating.toFixed(2))
54
- })), [L.ratingByCoach, R]), V = [
67
+ })), [
68
+ z.ratingByCoach,
69
+ B,
70
+ r
71
+ ]), W = [
55
72
  {
56
73
  key: "rank",
57
- header: "#",
74
+ header: r("atheletebridge.pages.analytics.standings.rank", "#"),
58
75
  priority: "secondary",
59
- cell: (e, t) => /* @__PURE__ */ w("span", {
76
+ cell: (e, t) => /* @__PURE__ */ E("span", {
60
77
  className: "tabular-nums text-text-secondary",
61
78
  children: e.rank ?? t + 1
62
79
  })
63
80
  },
64
81
  {
65
82
  key: "team",
66
- header: "Team",
83
+ header: r("atheletebridge.pages.analytics.standings.team", "Team"),
67
84
  priority: "primary",
68
- cell: (e) => /* @__PURE__ */ T("span", {
85
+ cell: (e) => /* @__PURE__ */ D("span", {
69
86
  className: "flex items-center gap-2",
70
- children: [/* @__PURE__ */ w(l, {
71
- name: e.team?.name ?? "Team",
87
+ children: [/* @__PURE__ */ E(u, {
88
+ name: e.team?.name ?? r("atheletebridge.pages.analytics.standings.teamFallback", "Team"),
72
89
  sport: e.team?.sport,
73
90
  size: 20,
74
91
  showSportGlyph: !1
75
- }), /* @__PURE__ */ w("span", {
92
+ }), /* @__PURE__ */ E("span", {
76
93
  className: "truncate font-medium text-text-primary",
77
- children: e.team?.name ?? "Team"
94
+ children: e.team?.name ?? r("atheletebridge.pages.analytics.standings.teamFallback", "Team")
78
95
  })]
79
96
  })
80
97
  },
81
98
  {
82
99
  key: "played",
83
- header: "P",
100
+ header: r("atheletebridge.pages.analytics.standings.played", "P"),
84
101
  priority: "hidden-on-mobile",
85
- cell: (e) => /* @__PURE__ */ w("span", {
102
+ cell: (e) => /* @__PURE__ */ E("span", {
86
103
  className: "tabular-nums text-text-secondary",
87
104
  children: e.played
88
105
  })
89
106
  },
90
107
  {
91
108
  key: "gd",
92
- header: "GD",
109
+ header: r("atheletebridge.pages.analytics.standings.gd", "GD"),
93
110
  priority: "hidden-on-mobile",
94
111
  cell: (e) => {
95
112
  let t = e.goalsFor - e.goalsAgainst;
96
- return /* @__PURE__ */ T("span", {
113
+ return /* @__PURE__ */ D("span", {
97
114
  className: "tabular-nums text-text-secondary",
98
115
  children: [t > 0 ? "+" : "", t]
99
116
  });
@@ -101,135 +118,137 @@ function L() {
101
118
  },
102
119
  {
103
120
  key: "points",
104
- header: "Pts",
121
+ header: r("atheletebridge.pages.analytics.standings.points", "Pts"),
105
122
  priority: "secondary",
106
- cell: (e) => /* @__PURE__ */ w("span", {
123
+ cell: (e) => /* @__PURE__ */ E("span", {
107
124
  className: "font-semibold tabular-nums text-text-primary",
108
125
  children: e.points
109
126
  })
110
127
  }
111
128
  ];
112
- if (L.isLoading) return /* @__PURE__ */ w(t, {
113
- title: "Coach analytics",
114
- children: /* @__PURE__ */ w(p, { label: "Crunching coaching data…" })
129
+ if (z.isLoading) return /* @__PURE__ */ E(n, {
130
+ title: r("atheletebridge.pages.analytics.title", "Coach analytics"),
131
+ children: /* @__PURE__ */ E(m, { label: r("atheletebridge.pages.analytics.loading", "Crunching coaching data…") })
115
132
  });
116
- if (L.isError) return /* @__PURE__ */ w(t, {
117
- title: "Coach analytics",
118
- children: /* @__PURE__ */ w(f, {
119
- title: "Analytics unavailable",
120
- message: "We could not load coaching analytics. Please try again."
133
+ if (z.isError) return /* @__PURE__ */ E(n, {
134
+ title: r("atheletebridge.pages.analytics.title", "Coach analytics"),
135
+ children: /* @__PURE__ */ E(p, {
136
+ title: r("atheletebridge.pages.analytics.errorTitle", "Analytics unavailable"),
137
+ message: r("atheletebridge.pages.analytics.errorMessage", "We could not load coaching analytics. Please try again.")
121
138
  })
122
139
  });
123
- let H = L.totalSessions > 0 || L.standings.length > 0, U = F(L.trainingLoad.ratio);
124
- return /* @__PURE__ */ w(t, {
125
- title: /* @__PURE__ */ T("span", {
140
+ let G = z.totalSessions > 0 || z.standings.length > 0 || z.loadByAthlete.length > 0, K = L(z.trainingLoad.ratio, r);
141
+ return /* @__PURE__ */ E(n, {
142
+ title: /* @__PURE__ */ D("span", {
126
143
  className: "flex items-center gap-2",
127
- children: [/* @__PURE__ */ w(O, { children: "Coach analytics" }), /* @__PURE__ */ w(E, {
144
+ children: [/* @__PURE__ */ E(A, { children: r("atheletebridge.pages.analytics.title", "Coach analytics") }), /* @__PURE__ */ E(O, {
128
145
  variant: "outline",
129
- children: "Beta"
146
+ children: r("common.beta", "Beta")
130
147
  })]
131
148
  }),
132
- description: "Honest aggregates over your real sessions, workouts and results.",
133
- children: H ? /* @__PURE__ */ T("div", {
149
+ description: r("atheletebridge.pages.analytics.description", "Honest aggregates over your real sessions, workouts and results."),
150
+ children: G ? /* @__PURE__ */ D("div", {
134
151
  className: "space-y-8",
135
152
  children: [
136
- /* @__PURE__ */ T("div", {
153
+ /* @__PURE__ */ D("div", {
137
154
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
138
155
  children: [
139
- /* @__PURE__ */ w(s, {
140
- icon: /* @__PURE__ */ w(x, { className: "h-5 w-5" }),
141
- value: L.totalSessions,
142
- label: "Total sessions",
156
+ /* @__PURE__ */ E(c, {
157
+ icon: /* @__PURE__ */ E(S, { className: "h-5 w-5" }),
158
+ value: z.totalSessions,
159
+ label: r("atheletebridge.pages.analytics.totalSessions", "Total sessions"),
143
160
  tone: "accent"
144
161
  }),
145
- /* @__PURE__ */ T(D, {
162
+ /* @__PURE__ */ D(k, {
146
163
  treatment: "metric",
147
164
  className: "flex flex-col justify-between gap-3 p-5",
148
165
  children: [
149
- /* @__PURE__ */ T("div", {
166
+ /* @__PURE__ */ D("div", {
150
167
  className: "flex items-start justify-between gap-2",
151
- children: [/* @__PURE__ */ w("span", {
168
+ children: [/* @__PURE__ */ E("span", {
152
169
  className: "text-sm font-medium text-text-secondary",
153
- children: "Avg session rating"
154
- }), /* @__PURE__ */ w(S, { className: "h-5 w-5 text-text-muted" })]
170
+ children: r("atheletebridge.pages.analytics.avgRating", "Avg session rating")
171
+ }), /* @__PURE__ */ E(C, { className: "h-5 w-5 text-text-muted" })]
155
172
  }),
156
- L.avgRating == null ? /* @__PURE__ */ w("span", {
173
+ z.avgRating == null ? /* @__PURE__ */ E("span", {
157
174
  className: "text-sm text-text-muted",
158
- children: "No rated sessions yet"
159
- }) : /* @__PURE__ */ T("div", {
175
+ children: r("atheletebridge.pages.analytics.noRatedSessions", "No rated sessions yet")
176
+ }) : /* @__PURE__ */ D("div", {
160
177
  className: "flex items-end gap-3",
161
- children: [/* @__PURE__ */ T("span", {
178
+ children: [/* @__PURE__ */ D("span", {
162
179
  className: "text-3xl font-semibold leading-none tabular-nums text-text-primary",
163
- children: [L.avgRating.toFixed(1), /* @__PURE__ */ w("span", {
180
+ children: [z.avgRating.toFixed(1), /* @__PURE__ */ E("span", {
164
181
  className: "ml-1 text-base text-text-secondary",
165
- children: "/5"
182
+ children: r("atheletebridge.pages.analytics.ratingOutOf", "/5")
166
183
  })]
167
- }), /* @__PURE__ */ w("div", {
184
+ }), /* @__PURE__ */ E("div", {
168
185
  className: "pb-1",
169
- children: /* @__PURE__ */ w(o, {
170
- value: L.avgRating,
186
+ children: /* @__PURE__ */ E(s, {
187
+ value: z.avgRating,
171
188
  max: 5,
172
189
  size: 16
173
190
  })
174
191
  })]
175
192
  }),
176
- /* @__PURE__ */ T("span", {
193
+ /* @__PURE__ */ D("span", {
177
194
  className: "text-xs text-text-muted tabular-nums",
178
195
  children: [
179
- L.ratedCount,
180
- " rated of ",
181
- L.totalSessions
196
+ z.ratedCount,
197
+ " ",
198
+ r("atheletebridge.pages.analytics.ratedOf", "rated of"),
199
+ " ",
200
+ z.totalSessions
182
201
  ]
183
202
  })
184
203
  ]
185
204
  }),
186
- /* @__PURE__ */ w(s, {
187
- icon: /* @__PURE__ */ w(y, { className: "h-5 w-5" }),
188
- value: `${Math.round(L.completedPct)}%`,
189
- label: "Sessions completed",
205
+ /* @__PURE__ */ E(c, {
206
+ icon: /* @__PURE__ */ E(b, { className: "h-5 w-5" }),
207
+ value: `${Math.round(z.completedPct)}%`,
208
+ label: r("atheletebridge.pages.analytics.sessionsCompleted", "Sessions completed"),
190
209
  tone: "success"
191
210
  })
192
211
  ]
193
212
  }),
194
- /* @__PURE__ */ T("div", {
213
+ /* @__PURE__ */ D("div", {
195
214
  className: "grid grid-cols-1 gap-6 lg:grid-cols-2",
196
- children: [/* @__PURE__ */ T(D, {
215
+ children: [/* @__PURE__ */ D(k, {
197
216
  treatment: "insight",
198
217
  className: "p-6",
199
- children: [/* @__PURE__ */ w("h2", {
218
+ children: [/* @__PURE__ */ E("h2", {
200
219
  className: "mb-4 text-lg font-semibold text-text-primary",
201
- children: "Session status overview"
202
- }), z.length > 0 ? /* @__PURE__ */ w(a, {
203
- segments: z,
204
- centerLabel: L.totalSessions,
205
- centerCaption: "sessions",
220
+ children: r("atheletebridge.pages.analytics.statusOverviewTitle", "Session status overview")
221
+ }), V.length > 0 ? /* @__PURE__ */ E(o, {
222
+ segments: V,
223
+ centerLabel: z.totalSessions,
224
+ centerCaption: r("atheletebridge.pages.analytics.sessionsCaption", "sessions"),
206
225
  valueFormatter: (e) => e.toLocaleString()
207
- }) : /* @__PURE__ */ w("p", {
226
+ }) : /* @__PURE__ */ E("p", {
208
227
  className: "text-sm text-text-muted",
209
- children: "No sessions to break down yet."
228
+ children: r("atheletebridge.pages.analytics.statusOverviewEmpty", "No sessions to break down yet.")
210
229
  })]
211
- }), /* @__PURE__ */ T(D, {
230
+ }), /* @__PURE__ */ D(k, {
212
231
  treatment: "insight",
213
232
  className: "p-6",
214
- children: [/* @__PURE__ */ w("h2", {
233
+ children: [/* @__PURE__ */ E("h2", {
215
234
  className: "mb-4 text-lg font-semibold text-text-primary",
216
- children: "Average rating by coach"
217
- }), B.length > 0 ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(i, {
218
- series: B,
235
+ children: r("atheletebridge.pages.analytics.ratingByCoachTitle", "Average rating by coach")
236
+ }), U.length > 0 ? /* @__PURE__ */ D(T, { children: [/* @__PURE__ */ E(a, {
237
+ series: U,
219
238
  height: 220,
220
239
  colorful: !0,
221
240
  valueFormatter: (e) => e.toFixed(1)
222
- }), /* @__PURE__ */ w("div", {
241
+ }), /* @__PURE__ */ E("div", {
223
242
  className: "mt-3 flex flex-wrap gap-x-4 gap-y-2",
224
- children: L.ratingByCoach.map((e) => /* @__PURE__ */ T("span", {
243
+ children: z.ratingByCoach.map((e) => /* @__PURE__ */ D("span", {
225
244
  className: "flex items-center gap-2 text-xs text-text-secondary",
226
- children: [/* @__PURE__ */ w(u, {
227
- name: R.nameOf(e.coachId),
245
+ children: [/* @__PURE__ */ E(d, {
246
+ name: B.nameOf(e.coachId),
228
247
  id: e.coachId,
229
248
  size: "xs"
230
- }), /* @__PURE__ */ T("span", {
249
+ }), /* @__PURE__ */ D("span", {
231
250
  className: "truncate",
232
- children: [I(R.nameOf(e.coachId), e.coachId), /* @__PURE__ */ T("span", {
251
+ children: [R(B.nameOf(e.coachId), e.coachId, r("atheletebridge.rolePrefix.coach", "Coach")), /* @__PURE__ */ D("span", {
233
252
  className: "ml-1 text-text-muted tabular-nums",
234
253
  children: [
235
254
  "(",
@@ -239,134 +258,271 @@ function L() {
239
258
  })]
240
259
  })]
241
260
  }, e.coachId))
242
- })] }) : /* @__PURE__ */ w("p", {
261
+ })] }) : /* @__PURE__ */ E("p", {
243
262
  className: "text-sm text-text-muted",
244
- children: "Rate completed sessions to compare coaches."
263
+ children: r("atheletebridge.pages.analytics.ratingByCoachEmpty", "Rate completed sessions to compare coaches.")
245
264
  })]
246
265
  })]
247
266
  }),
248
- /* @__PURE__ */ T("div", {
267
+ /* @__PURE__ */ D("div", {
249
268
  className: "grid grid-cols-1 gap-6 lg:grid-cols-2",
250
- children: [/* @__PURE__ */ T(D, {
269
+ children: [/* @__PURE__ */ D(k, {
251
270
  treatment: "insight",
252
271
  className: "p-6",
253
- children: [/* @__PURE__ */ T("div", {
272
+ children: [/* @__PURE__ */ D("div", {
254
273
  className: "mb-4 flex items-center justify-between gap-2",
255
- children: [/* @__PURE__ */ w("h2", {
274
+ children: [/* @__PURE__ */ E("h2", {
256
275
  className: "text-lg font-semibold text-text-primary",
257
- children: "Weekly training load"
258
- }), /* @__PURE__ */ w(M, { children: /* @__PURE__ */ T(A, { children: [/* @__PURE__ */ w(N, {
276
+ children: r("atheletebridge.pages.analytics.weeklyLoadTitle", "Weekly training load")
277
+ }), /* @__PURE__ */ E(P, { children: /* @__PURE__ */ D(M, { children: [/* @__PURE__ */ E(F, {
259
278
  asChild: !0,
260
- children: /* @__PURE__ */ w("button", {
279
+ children: /* @__PURE__ */ E("button", {
261
280
  type: "button",
262
- "aria-label": "About ACWR training load",
281
+ "aria-label": r("atheletebridge.pages.analytics.acwrAboutLabel", "About ACWR training load"),
263
282
  className: "rounded-full p-1 text-text-muted transition-colors hover:text-text-primary",
264
- children: /* @__PURE__ */ w(b, { className: "h-4 w-4" })
283
+ children: /* @__PURE__ */ E(x, { className: "h-4 w-4" })
265
284
  })
266
- }), /* @__PURE__ */ T(j, {
285
+ }), /* @__PURE__ */ E(N, {
267
286
  className: "max-w-xs",
268
- children: [
269
- "Total workout load per week (sum of real ",
270
- /* @__PURE__ */ w("code", { children: "totalLoad" }),
271
- "). The badge is the acute:chronic workload ratio (last 7 days vs 28-day average) — a standard sports-science load indicator; 0.8–1.3 is the typical sweet spot."
272
- ]
287
+ children: r("atheletebridge.pages.analytics.acwrAbout", "Total workout load per week (sum of real totalLoad). The badge is the acute:chronic workload ratio (last 7 days vs 28-day average) — a standard sports-science load indicator; 0.8–1.3 is the typical sweet spot.")
273
288
  })] }) })]
274
- }), L.loadTrend.some((e) => e.value > 0) ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(r, {
275
- series: L.loadTrend,
276
- seriesLabel: "Training load",
289
+ }), z.loadTrend.some((e) => e.value > 0) ? /* @__PURE__ */ D(T, { children: [/* @__PURE__ */ E(i, {
290
+ series: z.loadTrend,
291
+ seriesLabel: r("atheletebridge.pages.analytics.trainingLoadLabel", "Training load"),
277
292
  height: 200,
278
293
  valueFormatter: (e) => e.toLocaleString()
279
- }), /* @__PURE__ */ T("div", {
294
+ }), /* @__PURE__ */ D("div", {
280
295
  className: "mt-4 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm",
281
296
  children: [
282
- /* @__PURE__ */ T("span", {
297
+ /* @__PURE__ */ D("span", {
283
298
  className: "text-text-secondary",
284
299
  children: [
285
- "Acute (7d)",
300
+ r("atheletebridge.pages.analytics.acuteLoad", "Acute (7d)"),
286
301
  " ",
287
- /* @__PURE__ */ w("span", {
302
+ /* @__PURE__ */ E("span", {
288
303
  className: "font-semibold tabular-nums text-text-primary",
289
- children: Math.round(L.trainingLoad.acute).toLocaleString()
304
+ children: Math.round(z.trainingLoad.acute).toLocaleString()
290
305
  })
291
306
  ]
292
307
  }),
293
- /* @__PURE__ */ T("span", {
308
+ /* @__PURE__ */ D("span", {
294
309
  className: "text-text-secondary",
295
310
  children: [
296
- "Chronic (28d avg)",
311
+ r("atheletebridge.pages.analytics.chronicLoad", "Chronic (28d avg)"),
297
312
  " ",
298
- /* @__PURE__ */ w("span", {
313
+ /* @__PURE__ */ E("span", {
299
314
  className: "font-semibold tabular-nums text-text-primary",
300
- children: Math.round(L.trainingLoad.chronic).toLocaleString()
315
+ children: Math.round(z.trainingLoad.chronic).toLocaleString()
301
316
  })
302
317
  ]
303
318
  }),
304
- /* @__PURE__ */ T("span", {
319
+ /* @__PURE__ */ D("span", {
305
320
  className: "flex items-center gap-2 text-text-secondary",
306
- children: ["ACWR", /* @__PURE__ */ w(E, {
307
- variant: U.variant,
321
+ children: [r("atheletebridge.pages.analytics.acwrAbbreviation", "ACWR"), /* @__PURE__ */ E(O, {
322
+ variant: K.variant,
308
323
  className: "tabular-nums",
309
- children: L.trainingLoad.ratio == null ? U.label : `${L.trainingLoad.ratio.toFixed(2)} · ${U.label}`
324
+ children: z.trainingLoad.ratio == null ? K.label : `${z.trainingLoad.ratio.toFixed(2)} · ${K.label}`
310
325
  })]
311
326
  })
312
327
  ]
313
- })] }) : /* @__PURE__ */ w("p", {
328
+ })] }) : /* @__PURE__ */ E("p", {
314
329
  className: "text-sm text-text-muted",
315
- children: "Log workouts with a load to see training trend."
330
+ children: r("atheletebridge.pages.analytics.weeklyLoadEmpty", "Log workouts with a load to see training trend.")
316
331
  })]
317
- }), /* @__PURE__ */ T(D, {
332
+ }), /* @__PURE__ */ D(k, {
318
333
  treatment: "insight",
319
334
  className: "p-6",
320
- children: [/* @__PURE__ */ w("h2", {
335
+ children: [/* @__PURE__ */ E("h2", {
321
336
  className: "mb-4 text-lg font-semibold text-text-primary",
322
- children: "Sessions per week"
323
- }), L.sessionTrend.some((e) => e.value > 0) ? /* @__PURE__ */ w(i, {
324
- series: L.sessionTrend,
337
+ children: r("atheletebridge.pages.analytics.sessionsPerWeekTitle", "Sessions per week")
338
+ }), z.sessionTrend.some((e) => e.value > 0) ? /* @__PURE__ */ E(a, {
339
+ series: z.sessionTrend,
325
340
  height: 200,
326
341
  valueFormatter: (e) => e.toLocaleString()
327
- }) : /* @__PURE__ */ w("p", {
342
+ }) : /* @__PURE__ */ E("p", {
328
343
  className: "text-sm text-text-muted",
329
- children: "Schedule sessions to see weekly volume."
344
+ children: r("atheletebridge.pages.analytics.sessionsPerWeekEmpty", "Schedule sessions to see weekly volume.")
330
345
  })]
331
346
  })]
332
347
  }),
333
- L.standings.length > 0 ? /* @__PURE__ */ T("section", { children: [/* @__PURE__ */ T("div", {
348
+ /* @__PURE__ */ E(H, {
349
+ rows: z.loadByAthlete,
350
+ directory: B,
351
+ truncated: z.loadSampleTruncated,
352
+ tr: r
353
+ }),
354
+ z.standings.length > 0 ? /* @__PURE__ */ D("section", { children: [/* @__PURE__ */ D("div", {
334
355
  className: "mb-4 flex flex-wrap items-center justify-between gap-3",
335
- children: [/* @__PURE__ */ T("h2", {
356
+ children: [/* @__PURE__ */ D("h2", {
336
357
  className: "flex items-center gap-2 text-lg font-semibold text-text-primary",
337
358
  children: [
338
- /* @__PURE__ */ w(_, { className: "h-5 w-5 text-text-muted" }),
339
- "League standings",
340
- L.competition ? /* @__PURE__ */ w(E, {
359
+ /* @__PURE__ */ E(v, { className: "h-5 w-5 text-text-muted" }),
360
+ r("atheletebridge.pages.analytics.standingsTitle", "League standings"),
361
+ z.competition ? /* @__PURE__ */ E(O, {
341
362
  variant: "secondary",
342
- children: L.competition
363
+ children: z.competition
343
364
  }) : null
344
365
  ]
345
- }), /* @__PURE__ */ w("button", {
366
+ }), /* @__PURE__ */ E("button", {
346
367
  type: "button",
347
- onClick: () => n("/standings"),
368
+ onClick: () => w("/standings"),
348
369
  className: "text-sm font-medium text-[var(--color-accent-teal)] transition-colors hover:underline",
349
- children: "View full standings"
370
+ children: r("atheletebridge.pages.analytics.viewFullStandings", "View full standings")
350
371
  })]
351
- }), /* @__PURE__ */ w(D, {
372
+ }), /* @__PURE__ */ E(k, {
352
373
  treatment: "insight",
353
374
  className: "p-2 sm:p-4",
354
- children: /* @__PURE__ */ w(k, {
355
- columns: V,
356
- data: L.standings,
375
+ children: /* @__PURE__ */ E(j, {
376
+ columns: W,
377
+ data: z.standings,
357
378
  rowKey: (e) => e.id
358
379
  })
359
380
  })] }) : null
360
381
  ]
361
- }) : /* @__PURE__ */ w(d, {
382
+ }) : /* @__PURE__ */ E(f, {
362
383
  illustration: "empty-data",
363
- icon: /* @__PURE__ */ w(v, { className: "h-10 w-10" }),
364
- title: "No coaching data yet",
365
- description: "Book and complete sessions, log workouts and record fixtures to unlock analytics."
384
+ icon: /* @__PURE__ */ E(y, { className: "h-10 w-10" }),
385
+ title: r("atheletebridge.pages.analytics.emptyTitle", "No coaching data yet"),
386
+ description: r("atheletebridge.pages.analytics.emptyDescription", "Book and complete sessions, log workouts and record fixtures to unlock analytics.")
366
387
  })
367
388
  });
368
389
  }
390
+ function H({ rows: e, directory: t, truncated: n, tr: r }) {
391
+ let i = _(() => e.reduce((e, t) => Math.max(e, t.acute, t.chronic), 0), [e]), a = _(() => [
392
+ {
393
+ key: "athlete",
394
+ header: r("atheletebridge.pages.analytics.loadByAthlete.athlete", "Athlete"),
395
+ priority: "primary",
396
+ cell: (e) => /* @__PURE__ */ D("span", {
397
+ className: "flex items-center gap-2",
398
+ children: [/* @__PURE__ */ E(d, {
399
+ name: t.nameOf(e.athleteId),
400
+ id: e.athleteId,
401
+ size: "xs"
402
+ }), /* @__PURE__ */ D("span", {
403
+ className: "min-w-0",
404
+ children: [/* @__PURE__ */ E("span", {
405
+ className: "block truncate font-medium text-text-primary",
406
+ children: R(t.nameOf(e.athleteId), e.athleteId, r("atheletebridge.rolePrefix.athlete", "Athlete"))
407
+ }), /* @__PURE__ */ D("span", {
408
+ className: "block text-xs tabular-nums text-text-muted",
409
+ children: [
410
+ e.workoutCount,
411
+ " ",
412
+ r("atheletebridge.pages.analytics.loadByAthlete.workouts28d", "workouts · 28d")
413
+ ]
414
+ })]
415
+ })]
416
+ })
417
+ },
418
+ {
419
+ key: "acute",
420
+ header: r("atheletebridge.pages.analytics.loadByAthlete.acute", "Acute load (7d)"),
421
+ priority: "secondary",
422
+ mobileLabel: r("atheletebridge.pages.analytics.loadByAthlete.acute", "Acute load (7d)"),
423
+ cell: (e) => e.loadedCount === 0 ? /* @__PURE__ */ E("span", {
424
+ className: "text-text-muted",
425
+ children: "—"
426
+ }) : /* @__PURE__ */ D("span", {
427
+ className: "flex items-center gap-2",
428
+ children: [/* @__PURE__ */ E("span", {
429
+ className: "w-14 text-right font-medium tabular-nums text-text-primary",
430
+ children: z(e.acute)
431
+ }), /* @__PURE__ */ E(B, {
432
+ value: e.acute,
433
+ max: i
434
+ })]
435
+ })
436
+ },
437
+ {
438
+ key: "chronic",
439
+ header: r("atheletebridge.pages.analytics.loadByAthlete.chronic", "Chronic load (28d avg)"),
440
+ priority: "secondary",
441
+ mobileLabel: r("atheletebridge.pages.analytics.loadByAthlete.chronic", "Chronic load (28d avg)"),
442
+ cell: (e) => e.loadedCount === 0 ? /* @__PURE__ */ E("span", {
443
+ className: "text-text-muted",
444
+ children: "—"
445
+ }) : /* @__PURE__ */ D("span", {
446
+ className: "flex items-center gap-2",
447
+ children: [/* @__PURE__ */ E("span", {
448
+ className: "w-14 text-right font-medium tabular-nums text-text-primary",
449
+ children: z(e.chronic)
450
+ }), /* @__PURE__ */ E(B, {
451
+ value: e.chronic,
452
+ max: i
453
+ })]
454
+ })
455
+ },
456
+ {
457
+ key: "ratio",
458
+ header: r("atheletebridge.pages.analytics.loadByAthlete.ratio", "Load ratio"),
459
+ priority: "secondary",
460
+ mobileLabel: r("atheletebridge.pages.analytics.loadByAthlete.ratio", "Load ratio"),
461
+ cell: (e) => e.ratio == null ? /* @__PURE__ */ E("span", {
462
+ className: "text-text-muted",
463
+ children: "—"
464
+ }) : /* @__PURE__ */ E("span", {
465
+ className: "font-semibold tabular-nums text-text-primary",
466
+ children: e.ratio.toFixed(2)
467
+ })
468
+ },
469
+ {
470
+ key: "band",
471
+ header: r("atheletebridge.pages.analytics.loadByAthlete.status", "Status"),
472
+ priority: "primary",
473
+ mobileLabel: r("atheletebridge.pages.analytics.loadByAthlete.status", "Status"),
474
+ cell: (e) => {
475
+ let t = L(e.ratio, r);
476
+ return /* @__PURE__ */ E(O, {
477
+ variant: t.variant,
478
+ children: t.label
479
+ });
480
+ }
481
+ }
482
+ ], [
483
+ t,
484
+ i,
485
+ r
486
+ ]);
487
+ return /* @__PURE__ */ D("section", { children: [/* @__PURE__ */ D("div", {
488
+ className: "mb-4 flex flex-wrap items-center gap-2",
489
+ children: [/* @__PURE__ */ D("h2", {
490
+ className: "flex items-center gap-2 text-lg font-semibold text-text-primary",
491
+ children: [/* @__PURE__ */ E(w, { className: "h-5 w-5 text-text-muted" }), r("atheletebridge.pages.analytics.loadByAthlete.title", "Training load by athlete")]
492
+ }), /* @__PURE__ */ E(P, { children: /* @__PURE__ */ D(M, { children: [/* @__PURE__ */ E(F, {
493
+ asChild: !0,
494
+ children: /* @__PURE__ */ E("button", {
495
+ type: "button",
496
+ "aria-label": r("atheletebridge.pages.analytics.loadByAthlete.aboutLabel", "About per-athlete training load"),
497
+ className: "rounded-full p-1 text-text-muted transition-colors hover:text-text-primary",
498
+ children: /* @__PURE__ */ E(x, { className: "h-4 w-4" })
499
+ })
500
+ }), /* @__PURE__ */ E(N, {
501
+ className: "max-w-xs",
502
+ children: r("atheletebridge.pages.analytics.loadByAthlete.about", "Each athlete’s acute:chronic workload ratio — their last 7 days of logged workout load against their 28-day weekly average. 0.8–1.3 is the typical sweet spot; above 1.5 is a spike worth reviewing.")
503
+ })] }) })]
504
+ }), e.length === 0 ? /* @__PURE__ */ E(k, {
505
+ treatment: "insight",
506
+ className: "p-6",
507
+ children: /* @__PURE__ */ E("p", {
508
+ className: "text-sm text-text-muted",
509
+ children: r("atheletebridge.pages.analytics.loadByAthlete.empty", "No workouts logged in the last 28 days. Log workouts with a total load to compare athletes.")
510
+ })
511
+ }) : /* @__PURE__ */ D(T, { children: [/* @__PURE__ */ E(k, {
512
+ treatment: "insight",
513
+ className: "p-2 sm:p-4",
514
+ children: /* @__PURE__ */ E(j, {
515
+ columns: a,
516
+ data: e,
517
+ rowKey: (e) => e.athleteId,
518
+ caption: r("atheletebridge.pages.analytics.loadByAthlete.caption", "Acute and chronic training load per athlete over the last 28 days")
519
+ })
520
+ }), n ? /* @__PURE__ */ E("p", {
521
+ className: "mt-3 text-xs text-text-muted",
522
+ children: r("atheletebridge.pages.analytics.loadByAthlete.truncated", "Computed from the most recent page of workout logs, which does not reach back a full 28 days — these loads are a floor, not a total.")
523
+ }) : null] })] });
524
+ }
369
525
  //#endregion
370
- export { L as CoachAnalyticsPage };
526
+ export { V as CoachAnalyticsPage };
371
527
 
372
528
  //# sourceMappingURL=CoachAnalyticsPage.js.map