@burdenoff/microfe-atheletebridge 2026.705.2 → 2026.706.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 (101) hide show
  1. package/dist/atheletebridge/AthleteBridgeRoot.js +55 -39
  2. package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
  3. package/dist/atheletebridge/AthleteBridgeRoutes.js +18 -6
  4. package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
  5. package/dist/atheletebridge/components/Crest.js +70 -0
  6. package/dist/atheletebridge/components/Crest.js.map +1 -0
  7. package/dist/atheletebridge/components/FixtureCard.js +8 -72
  8. package/dist/atheletebridge/components/FixtureCard.js.map +1 -1
  9. package/dist/atheletebridge/components/MatchupRow.js +74 -0
  10. package/dist/atheletebridge/components/MatchupRow.js.map +1 -0
  11. package/dist/atheletebridge/components/MetricsCard.js +61 -21
  12. package/dist/atheletebridge/components/MetricsCard.js.map +1 -1
  13. package/dist/atheletebridge/components/ProgramCard.js +75 -43
  14. package/dist/atheletebridge/components/ProgramCard.js.map +1 -1
  15. package/dist/atheletebridge/components/Scoreboard.js +163 -0
  16. package/dist/atheletebridge/components/Scoreboard.js.map +1 -0
  17. package/dist/atheletebridge/components/SessionCard.js +64 -41
  18. package/dist/atheletebridge/components/SessionCard.js.map +1 -1
  19. package/dist/atheletebridge/components/SessionStatusTimeline.js +80 -0
  20. package/dist/atheletebridge/components/SessionStatusTimeline.js.map +1 -0
  21. package/dist/atheletebridge/components/StatusBadge.js +5 -5
  22. package/dist/atheletebridge/components/StatusBadge.js.map +1 -1
  23. package/dist/atheletebridge/components/TeamCard.js +65 -35
  24. package/dist/atheletebridge/components/TeamCard.js.map +1 -1
  25. package/dist/atheletebridge/components/UserAvatar.js +33 -0
  26. package/dist/atheletebridge/components/UserAvatar.js.map +1 -0
  27. package/dist/atheletebridge/components/domain.js +5 -2
  28. package/dist/atheletebridge/components/domain.js.map +1 -1
  29. package/dist/atheletebridge/components/viz/AvatarStack.js +2 -0
  30. package/dist/atheletebridge/components/viz/BarChart.js +83 -0
  31. package/dist/atheletebridge/components/viz/BarChart.js.map +1 -0
  32. package/dist/atheletebridge/components/viz/DonutChart.js +109 -0
  33. package/dist/atheletebridge/components/viz/DonutChart.js.map +1 -0
  34. package/dist/atheletebridge/components/viz/LineChart.js +123 -0
  35. package/dist/atheletebridge/components/viz/LineChart.js.map +1 -0
  36. package/dist/atheletebridge/components/viz/ProgressRing.js +6 -0
  37. package/dist/atheletebridge/components/viz/ProgressRing.js.map +1 -0
  38. package/dist/atheletebridge/components/viz/RatingStars.js +92 -0
  39. package/dist/atheletebridge/components/viz/RatingStars.js.map +1 -0
  40. package/dist/atheletebridge/components/viz/Sparkline.js +74 -0
  41. package/dist/atheletebridge/components/viz/Sparkline.js.map +1 -0
  42. package/dist/atheletebridge/components/viz/StatCard.js +60 -0
  43. package/dist/atheletebridge/components/viz/StatCard.js.map +1 -0
  44. package/dist/atheletebridge/components/viz/StepProgress.js +3 -0
  45. package/dist/atheletebridge/components/viz/Timeline.js +66 -0
  46. package/dist/atheletebridge/components/viz/Timeline.js.map +1 -0
  47. package/dist/atheletebridge/components/viz/index.js +13 -0
  48. package/dist/atheletebridge/components/viz/lib/Avatar.js +1 -0
  49. package/dist/atheletebridge/components/viz/lib/CartesianFrame.js +119 -0
  50. package/dist/atheletebridge/components/viz/lib/CartesianFrame.js.map +1 -0
  51. package/dist/atheletebridge/components/viz/lib/ResponsiveSvg.js +35 -0
  52. package/dist/atheletebridge/components/viz/lib/ResponsiveSvg.js.map +1 -0
  53. package/dist/atheletebridge/components/viz/lib/format.js +17 -0
  54. package/dist/atheletebridge/components/viz/lib/format.js.map +1 -0
  55. package/dist/atheletebridge/components/viz/lib/geometry.js +61 -0
  56. package/dist/atheletebridge/components/viz/lib/geometry.js.map +1 -0
  57. package/dist/atheletebridge/components/viz/lib/hooks.js +39 -0
  58. package/dist/atheletebridge/components/viz/lib/hooks.js.map +1 -0
  59. package/dist/atheletebridge/components/viz/lib/palette.js +27 -0
  60. package/dist/atheletebridge/components/viz/lib/palette.js.map +1 -0
  61. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +369 -163
  62. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  63. package/dist/atheletebridge/pages/DashboardPage.js +182 -117
  64. package/dist/atheletebridge/pages/DashboardPage.js.map +1 -1
  65. package/dist/atheletebridge/pages/StandingsPage.js +119 -95
  66. package/dist/atheletebridge/pages/StandingsPage.js.map +1 -1
  67. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js +372 -0
  68. package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js.map +1 -0
  69. package/dist/atheletebridge/pages/athletes/AthleteProfilePage.js +511 -0
  70. package/dist/atheletebridge/pages/athletes/AthleteProfilePage.js.map +1 -0
  71. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +120 -131
  72. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -1
  73. package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js +264 -176
  74. package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js.map +1 -1
  75. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js +84 -47
  76. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js.map +1 -1
  77. package/dist/atheletebridge/pages/performance/PerformancePage.js +432 -281
  78. package/dist/atheletebridge/pages/performance/PerformancePage.js.map +1 -1
  79. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +187 -123
  80. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -1
  81. package/dist/atheletebridge/pages/programs/ProgramsListPage.js +56 -39
  82. package/dist/atheletebridge/pages/programs/ProgramsListPage.js.map +1 -1
  83. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +267 -139
  84. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -1
  85. package/dist/atheletebridge/pages/sessions/SessionFormPage.js +253 -162
  86. package/dist/atheletebridge/pages/sessions/SessionFormPage.js.map +1 -1
  87. package/dist/atheletebridge/pages/sessions/SessionsListPage.js +38 -36
  88. package/dist/atheletebridge/pages/sessions/SessionsListPage.js.map +1 -1
  89. package/dist/atheletebridge/pages/teams/TeamDetailPage.js +437 -189
  90. package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -1
  91. package/dist/atheletebridge/pages/teams/TeamFormPage.js +368 -177
  92. package/dist/atheletebridge/pages/teams/TeamFormPage.js.map +1 -1
  93. package/dist/atheletebridge/pages/teams/TeamsListPage.js +3 -0
  94. package/dist/atheletebridge/pages/teams/TeamsListPage.js.map +1 -1
  95. package/dist/atheletebridge/pages/tournaments/TournamentBracketPage.js +298 -0
  96. package/dist/atheletebridge/pages/tournaments/TournamentBracketPage.js.map +1 -0
  97. package/dist/atheletebridge/utils/identity.js +31 -0
  98. package/dist/atheletebridge/utils/identity.js.map +1 -0
  99. package/dist/atheletebridge/utils/timeAgo.js +20 -0
  100. package/dist/atheletebridge/utils/timeAgo.js.map +1 -0
  101. package/package.json +1 -1
@@ -1,496 +1,647 @@
1
- import { PageLayout as e } from "../../components/PageLayout.js";
2
- import { StatusBadge as t } from "../../components/StatusBadge.js";
3
- import { METRIC_TYPE_LABELS as n } from "../../components/domain.js";
4
- import { formatDate as r, formatDuration as i } from "../../utils/formatters.js";
5
- import { EmptyState as a } from "../../components/EmptyState.js";
6
- import { ErrorState as o, LoadingState as s } from "../../components/LoadingState.js";
7
- import { useLogWorkout as c, usePerformanceMetrics as l, useRecordMetric as u, useWorkoutLogs as d } from "../../hooks/useAthleteBridgeApi.js";
8
- import { FormField as f, fieldInputClass as p } from "../../components/form.js";
9
- import { CursorPager as m } from "../../components/CursorPager.js";
10
- import { AthleteSelect as h } from "../../components/AthleteSelect.js";
11
- import { useMemo as g, useState as _ } from "react";
12
- import { Activity as v, Dumbbell as y, Gauge as b, Loader2 as x, Plus as S, Save as C, Users as w } from "lucide-react";
13
- import { Fragment as T, 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";
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { Sparkline as n } from "../../components/viz/Sparkline.js";
4
+ import "../../components/viz/index.js";
5
+ import { StatusBadge as r } from "../../components/StatusBadge.js";
6
+ import { METRIC_TYPE_LABELS as i } from "../../components/domain.js";
7
+ import { formatDate as a, formatDuration as o } from "../../utils/formatters.js";
8
+ import { EmptyState as s } from "../../components/EmptyState.js";
9
+ import { ErrorState as c, LoadingState as l } from "../../components/LoadingState.js";
10
+ import { useLogWorkout as u, usePerformanceMetrics as d, useRecordMetric as f, useWorkoutLogs as p } from "../../hooks/useAthleteBridgeApi.js";
11
+ import { FormField as m, fieldInputClass as h } from "../../components/form.js";
12
+ import { CursorPager as g } from "../../components/CursorPager.js";
13
+ import { AthleteSelect as _ } from "../../components/AthleteSelect.js";
14
+ import { useMemo as v, useState as y } from "react";
15
+ import { Activity as b, ArrowDown as x, ArrowUp as S, Dumbbell as C, Gauge as w, HeartPulse as T, Loader2 as E, Move as D, Plus as O, Save as k, Scale as A, Target as j, Users as M, Zap as N } from "lucide-react";
16
+ import { Fragment as P, jsx as F, jsxs as I } from "react/jsx-runtime";
17
+ import { GlassCard as L, ResponsiveDialog as R, ResponsiveDialogContent as z, ResponsiveDialogFooter as B, ResponsiveDialogHeader as V, ResponsiveDialogTitle as H, ResponsiveTable as U } from "@burdenoff/fe-libs/ui";
15
18
  //#region src/atheletebridge/pages/performance/PerformancePage.tsx
16
- var F = 10, I = [
19
+ var W = 10, G = [
17
20
  "COMPLETED",
18
21
  "PLANNED",
19
22
  "SKIPPED"
20
- ], L = Object.keys(n), R = (e) => {
23
+ ], K = Object.keys(i), q = "inline-flex items-center justify-center gap-1.5 rounded-lg px-4 py-2 text-sm font-semibold text-action-primary-text shadow-elevation-1 transition-[filter,box-shadow] hover:shadow-elevation-2 hover:brightness-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] bg-[linear-gradient(120deg,var(--color-action-primary-bg),color-mix(in_oklab,var(--color-action-primary-bg)_62%,var(--color-accent-purple)),var(--color-action-primary-bg))]", J = {
24
+ SPEED: N,
25
+ ENDURANCE: b,
26
+ STRENGTH: C,
27
+ AGILITY: D,
28
+ ACCURACY: j,
29
+ WEIGHT: A,
30
+ HEART_RATE: T,
31
+ CUSTOM: w
32
+ }, Y = (e) => {
21
33
  let t = e.trim();
22
34
  if (!t) return;
23
35
  let n = Number.parseInt(t, 10);
24
36
  return Number.isNaN(n) ? void 0 : n;
25
- }, z = (e) => {
37
+ }, X = (e) => {
26
38
  let t = e.trim();
27
39
  if (!t) return;
28
40
  let n = Number.parseFloat(t);
29
41
  return Number.isNaN(n) ? void 0 : n;
30
- }, B = () => {
42
+ }, Z = () => {
31
43
  let e = /* @__PURE__ */ new Date();
32
44
  return (/* @__PURE__ */ new Date(e.getTime() - e.getTimezoneOffset() * 6e4)).toISOString().slice(0, 16);
33
- };
34
- function V() {
35
- let [t, n] = _({
45
+ }, Q = (e) => (Math.abs(e) >= 100 ? e.toFixed(0) : e.toFixed(2)).replace(/\.?0+$/, "");
46
+ function $() {
47
+ let [e, n] = y({
36
48
  athleteId: "",
37
49
  displayName: ""
38
50
  });
39
- return /* @__PURE__ */ D(e, {
51
+ return /* @__PURE__ */ I(t, {
40
52
  title: "Performance",
41
53
  description: "Log workouts, record metrics and track an athlete's progress over time.",
42
- children: [/* @__PURE__ */ E(k, {
43
- treatment: "insight",
44
- className: "mb-8 p-6",
45
- children: /* @__PURE__ */ E(h, {
46
- athleteId: t.athleteId,
47
- onSelect: n,
48
- idPrefix: "perf-athlete"
54
+ children: [/* @__PURE__ */ F("div", {
55
+ className: "sticky top-0 z-20 -mx-6 mb-8 bg-bg-canvas/80 px-6 pb-4 pt-1 backdrop-blur supports-[backdrop-filter]:bg-bg-canvas/60",
56
+ children: /* @__PURE__ */ F(L, {
57
+ treatment: "insight",
58
+ className: "p-5 sm:p-6",
59
+ children: /* @__PURE__ */ F(_, {
60
+ athleteId: e.athleteId,
61
+ onSelect: n,
62
+ idPrefix: "perf-athlete"
63
+ })
49
64
  })
50
- }), t.athleteId ? /* @__PURE__ */ E(H, {
51
- athleteId: t.athleteId,
52
- displayName: t.displayName
53
- }) : /* @__PURE__ */ E(a, {
65
+ }), e.athleteId ? /* @__PURE__ */ F(ee, {
66
+ athleteId: e.athleteId,
67
+ displayName: e.displayName
68
+ }) : /* @__PURE__ */ F(s, {
54
69
  illustration: "empty-data",
55
- icon: /* @__PURE__ */ E(w, { className: "h-10 w-10" }),
70
+ icon: /* @__PURE__ */ F(M, { className: "h-10 w-10" }),
56
71
  title: "Pick an athlete to begin",
57
72
  description: "Choose a team and an athlete above to log workouts, record metrics and review their history."
58
73
  })]
59
74
  });
60
75
  }
61
- function H({ athleteId: e, displayName: c }) {
62
- let [u, f] = _(0), [p, h] = _(!1), [x, S] = _(!1), C = d({
63
- athleteId: e,
76
+ function ee({ athleteId: t, displayName: n }) {
77
+ let [i, u] = y(0), [f, m] = y(!1), [h, _] = y(!1), x = p({
78
+ athleteId: t,
64
79
  pagination: {
65
- limit: F,
66
- offset: u * F
80
+ limit: W,
81
+ offset: i * W
67
82
  }
68
- }), w = l(e), A = C.data?.items ?? [], j = C.data?.pageInfo.hasMore ?? !1, M = g(() => {
83
+ }), S = d(t), T = x.data?.items ?? [], E = x.data?.pageInfo.hasMore ?? !1, D = v(() => {
69
84
  let e = /* @__PURE__ */ new Map();
70
- for (let t of w.data ?? []) {
71
- let n = e.get(t.type) ?? [];
72
- n.push(t), e.set(t.type, n);
85
+ for (let t of S.data ?? []) {
86
+ let n = `${t.type}::${t.label}`, r = e.get(n) ?? [];
87
+ r.push(t), e.set(n, r);
88
+ }
89
+ return Array.from(e.entries()).map(([e, t]) => {
90
+ let n = [...t].sort((e, t) => new Date(e.recordedAt).getTime() - new Date(t.recordedAt).getTime()), r = n.map((e) => e.value), i = n[n.length - 1], a = n.length > 1 ? n[n.length - 2] : null;
91
+ return {
92
+ key: e,
93
+ type: i.type,
94
+ label: i.label,
95
+ unit: i.unit,
96
+ latest: i.value,
97
+ previous: a ? a.value : null,
98
+ min: Math.min(...r),
99
+ max: Math.max(...r),
100
+ series: r,
101
+ recordedAt: i.recordedAt,
102
+ count: n.length
103
+ };
104
+ }).sort((e, t) => new Date(t.recordedAt).getTime() - new Date(e.recordedAt).getTime());
105
+ }, [S.data]), k = v(() => [
106
+ {
107
+ key: "workout",
108
+ header: "Workout",
109
+ priority: "primary",
110
+ cell: (e) => /* @__PURE__ */ I("div", {
111
+ className: "flex items-center gap-3",
112
+ children: [/* @__PURE__ */ F("span", {
113
+ className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-[var(--color-accent-teal)]",
114
+ children: /* @__PURE__ */ F(te(e.title), {
115
+ className: "h-4 w-4",
116
+ "aria-hidden": "true"
117
+ })
118
+ }), /* @__PURE__ */ F("span", {
119
+ className: "min-w-0 truncate font-medium text-text-primary",
120
+ children: e.title
121
+ })]
122
+ })
123
+ },
124
+ {
125
+ key: "duration",
126
+ header: "Duration",
127
+ priority: "secondary",
128
+ mobileLabel: "Duration",
129
+ cell: (e) => e.durationMin == null ? /* @__PURE__ */ F("span", {
130
+ className: "text-text-muted",
131
+ children: "—"
132
+ }) : /* @__PURE__ */ F("span", {
133
+ className: "tabular-nums text-text-secondary",
134
+ children: o(e.durationMin)
135
+ })
136
+ },
137
+ {
138
+ key: "rpe",
139
+ header: "RPE",
140
+ priority: "secondary",
141
+ mobileLabel: "RPE",
142
+ cell: (e) => e.rpe == null ? /* @__PURE__ */ F("span", {
143
+ className: "text-text-muted",
144
+ children: "—"
145
+ }) : /* @__PURE__ */ F(ne, { rpe: e.rpe })
146
+ },
147
+ {
148
+ key: "date",
149
+ header: "Date",
150
+ priority: "secondary",
151
+ mobileLabel: "Date",
152
+ cell: (e) => /* @__PURE__ */ F("span", {
153
+ className: "tabular-nums text-text-secondary",
154
+ children: a(e.performedAt)
155
+ })
156
+ },
157
+ {
158
+ key: "status",
159
+ header: "Status",
160
+ priority: "primary",
161
+ mobileLabel: "Status",
162
+ cell: (e) => /* @__PURE__ */ F(r, { status: e.status })
163
+ },
164
+ {
165
+ key: "notes",
166
+ header: "Notes",
167
+ priority: "hidden-on-mobile",
168
+ cell: (e) => e.notes ? /* @__PURE__ */ F("span", {
169
+ className: "line-clamp-2 max-w-[22ch] text-text-secondary",
170
+ children: e.notes
171
+ }) : /* @__PURE__ */ F("span", {
172
+ className: "text-text-muted",
173
+ children: "—"
174
+ })
73
175
  }
74
- return Array.from(e.entries()).map(([e, t]) => ({
75
- type: e,
76
- metrics: [...t].sort((e, t) => new Date(t.recordedAt).getTime() - new Date(e.recordedAt).getTime()),
77
- max: Math.max(...t.map((e) => Math.abs(e.value)), 0) || 1
78
- }));
79
- }, [w.data]);
80
- return /* @__PURE__ */ D("div", {
81
- className: "space-y-8",
176
+ ], []);
177
+ return /* @__PURE__ */ I("div", {
178
+ className: "space-y-8 pb-24 sm:pb-0",
82
179
  children: [
83
- /* @__PURE__ */ D("div", {
180
+ /* @__PURE__ */ I("div", {
84
181
  className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
85
- children: [/* @__PURE__ */ D("p", {
182
+ children: [/* @__PURE__ */ I("p", {
86
183
  className: "text-sm text-text-secondary",
87
- children: ["Tracking ", /* @__PURE__ */ E("span", {
184
+ children: ["Tracking ", /* @__PURE__ */ F("span", {
88
185
  className: "font-medium text-text-primary",
89
- children: c || "athlete"
186
+ children: n || "athlete"
90
187
  })]
91
- }), /* @__PURE__ */ D("div", {
188
+ }), /* @__PURE__ */ I("div", {
92
189
  className: "flex flex-wrap gap-2",
93
- children: [/* @__PURE__ */ D("button", {
94
- type: "button",
95
- onClick: () => h(!0),
96
- 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",
97
- children: [/* @__PURE__ */ E(y, { className: "h-4 w-4" }), " Log workout"]
98
- }), /* @__PURE__ */ D("button", {
190
+ children: [/* @__PURE__ */ I("button", {
99
191
  type: "button",
100
- onClick: () => S(!0),
192
+ onClick: () => _(!0),
101
193
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
102
- children: [/* @__PURE__ */ E(b, { className: "h-4 w-4" }), " Record metric"]
194
+ children: [/* @__PURE__ */ F(w, { className: "h-4 w-4" }), " Record metric"]
195
+ }), /* @__PURE__ */ I("button", {
196
+ type: "button",
197
+ onClick: () => m(!0),
198
+ className: e(q, "hidden sm:inline-flex"),
199
+ children: [/* @__PURE__ */ F(C, { className: "h-4 w-4" }), " Log workout"]
103
200
  })]
104
201
  })]
105
202
  }),
106
- /* @__PURE__ */ D("section", { children: [/* @__PURE__ */ E("h2", {
203
+ /* @__PURE__ */ I("section", { children: [/* @__PURE__ */ F("h2", {
107
204
  className: "mb-4 text-lg font-semibold text-text-primary",
108
205
  children: "Performance metrics"
109
- }), w.isLoading ? /* @__PURE__ */ E(s, { label: "Loading metrics…" }) : w.isError ? /* @__PURE__ */ E(o, { onRetry: () => void w.refetch() }) : M.length === 0 ? /* @__PURE__ */ E(a, {
206
+ }), S.isLoading ? /* @__PURE__ */ F(l, { label: "Loading metrics…" }) : S.isError ? /* @__PURE__ */ F(c, { onRetry: () => void S.refetch() }) : D.length === 0 ? /* @__PURE__ */ F(s, {
110
207
  illustration: "empty-data",
111
- icon: /* @__PURE__ */ E(b, { className: "h-10 w-10" }),
208
+ icon: /* @__PURE__ */ F(w, { className: "h-10 w-10" }),
112
209
  title: "No metrics recorded",
113
- description: "Record a metric — speed, strength, endurance and more — to start charting progress."
114
- }) : /* @__PURE__ */ E("div", {
115
- className: "grid grid-cols-1 gap-4 lg:grid-cols-2",
116
- children: M.map((e) => /* @__PURE__ */ D(k, {
117
- treatment: "metric",
118
- className: "p-5",
119
- children: [/* @__PURE__ */ E("h3", {
120
- className: "mb-3 text-sm font-semibold uppercase tracking-wide text-text-secondary",
121
- children: n[e.type]
122
- }), /* @__PURE__ */ E("ul", {
123
- className: "space-y-3",
124
- children: e.metrics.map((t) => {
125
- let n = Math.max(4, Math.round(Math.abs(t.value) / e.max * 100));
126
- return /* @__PURE__ */ D("li", {
127
- className: "flex items-center gap-3",
128
- title: r(t.recordedAt),
129
- children: [
130
- /* @__PURE__ */ E("span", {
131
- className: "w-24 shrink-0 truncate text-sm text-text-primary",
132
- children: t.label
133
- }),
134
- /* @__PURE__ */ E("span", {
135
- className: "h-2 flex-1 overflow-hidden rounded-full bg-bg-sunken",
136
- "aria-hidden": "true",
137
- children: /* @__PURE__ */ E("span", {
138
- className: "block h-2 rounded-full bg-[var(--color-accent-teal)]",
139
- style: { width: `${n}%` }
140
- })
141
- }),
142
- /* @__PURE__ */ D("span", {
143
- className: "w-24 shrink-0 text-right text-sm tabular-nums text-text-primary",
144
- children: [t.value, t.unit ? ` ${t.unit}` : ""]
145
- })
146
- ]
147
- }, t.id);
148
- })
149
- })]
150
- }, e.type))
210
+ description: "Record a metric — speed, strength, endurance and more — to start charting progress.",
211
+ action: /* @__PURE__ */ I("button", {
212
+ type: "button",
213
+ onClick: () => _(!0),
214
+ className: q,
215
+ children: [/* @__PURE__ */ F(O, { className: "h-4 w-4" }), " Record metric"]
216
+ })
217
+ }) : /* @__PURE__ */ F("div", {
218
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
219
+ children: D.map((e) => /* @__PURE__ */ F(re, { metric: e }, e.key))
151
220
  })] }),
152
- /* @__PURE__ */ D("section", { children: [/* @__PURE__ */ E("h2", {
221
+ /* @__PURE__ */ I("section", { children: [/* @__PURE__ */ F("h2", {
153
222
  className: "mb-4 text-lg font-semibold text-text-primary",
154
223
  children: "Workout history"
155
- }), C.isLoading ? /* @__PURE__ */ E(s, { label: "Loading workouts…" }) : C.isError ? /* @__PURE__ */ E(o, { onRetry: () => void C.refetch() }) : A.length === 0 ? /* @__PURE__ */ E(a, {
224
+ }), x.isLoading ? /* @__PURE__ */ F(l, { label: "Loading workouts…" }) : x.isError ? /* @__PURE__ */ F(c, { onRetry: () => void x.refetch() }) : T.length === 0 ? /* @__PURE__ */ F(s, {
156
225
  illustration: "empty-data",
157
- icon: /* @__PURE__ */ E(v, { className: "h-10 w-10" }),
226
+ icon: /* @__PURE__ */ F(b, { className: "h-10 w-10" }),
158
227
  title: "No workouts logged",
159
228
  description: "Log a workout to build this athlete's training history.",
160
- action: /* @__PURE__ */ E("button", {
229
+ action: /* @__PURE__ */ I("button", {
161
230
  type: "button",
162
- onClick: () => h(!0),
163
- className: "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",
164
- children: "Log workout"
231
+ onClick: () => m(!0),
232
+ className: q,
233
+ children: [/* @__PURE__ */ F(C, { className: "h-4 w-4" }), " Log workout"]
165
234
  })
166
- }) : /* @__PURE__ */ D(T, { children: [/* @__PURE__ */ E(O, { children: /* @__PURE__ */ E("div", {
167
- className: "divide-y divide-border-seam",
168
- children: A.map((e) => /* @__PURE__ */ D("div", {
169
- className: "flex flex-wrap items-center gap-x-4 gap-y-1 py-3",
170
- children: [/* @__PURE__ */ D("div", {
171
- className: "min-w-0 flex-1",
172
- children: [
173
- /* @__PURE__ */ E("p", {
174
- className: "truncate text-sm font-medium text-text-primary",
175
- children: e.title
176
- }),
177
- /* @__PURE__ */ D("div", {
178
- className: "mt-0.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-text-secondary",
179
- children: [
180
- /* @__PURE__ */ E("span", { children: r(e.performedAt) }),
181
- e.durationMin != null && /* @__PURE__ */ E("span", { children: i(e.durationMin) }),
182
- e.rpe != null && /* @__PURE__ */ D("span", { children: ["RPE ", e.rpe] }),
183
- e.totalLoad != null && /* @__PURE__ */ D("span", { children: ["Load ", e.totalLoad] })
184
- ]
185
- }),
186
- e.notes && /* @__PURE__ */ E("p", {
187
- className: "mt-0.5 truncate text-xs text-text-secondary",
188
- children: e.notes
189
- })
190
- ]
191
- }), /* @__PURE__ */ E(t, { status: e.status })]
192
- }, e.id))
193
- }) }), /* @__PURE__ */ E(m, {
235
+ }) : /* @__PURE__ */ I(P, { children: [/* @__PURE__ */ F(L, {
236
+ treatment: "metric",
237
+ className: "overflow-hidden p-1 sm:p-2",
238
+ children: /* @__PURE__ */ F(U, {
239
+ columns: k,
240
+ data: T,
241
+ rowKey: (e) => e.id,
242
+ caption: `Workout history for ${n || "athlete"}`
243
+ })
244
+ }), /* @__PURE__ */ F(g, {
194
245
  className: "mt-6",
195
- page: u,
196
- hasMore: j,
197
- onPrev: () => f((e) => Math.max(0, e - 1)),
198
- onNext: () => f((e) => e + 1)
246
+ page: i,
247
+ hasMore: E,
248
+ onPrev: () => u((e) => Math.max(0, e - 1)),
249
+ onNext: () => u((e) => e + 1)
199
250
  })] })] }),
200
- /* @__PURE__ */ E(U, {
201
- open: p,
202
- onOpenChange: h,
203
- athleteId: e,
204
- displayName: c
251
+ /* @__PURE__ */ F("div", {
252
+ className: "sticky bottom-0 z-30 -mx-6 border-t border-border-seam bg-bg-canvas/85 px-6 pb-[max(env(safe-area-inset-bottom),0.75rem)] pt-3 backdrop-blur sm:hidden",
253
+ children: /* @__PURE__ */ I("button", {
254
+ type: "button",
255
+ onClick: () => m(!0),
256
+ className: e(q, "w-full py-3 text-base"),
257
+ children: [/* @__PURE__ */ F(O, { className: "h-5 w-5" }), " Log workout"]
258
+ })
205
259
  }),
206
- /* @__PURE__ */ E(W, {
207
- open: x,
208
- onOpenChange: S,
209
- athleteId: e,
210
- displayName: c
260
+ /* @__PURE__ */ F(ie, {
261
+ open: f,
262
+ onOpenChange: m,
263
+ athleteId: t,
264
+ displayName: n
265
+ }),
266
+ /* @__PURE__ */ F(ae, {
267
+ open: h,
268
+ onOpenChange: _,
269
+ athleteId: t,
270
+ displayName: n
211
271
  })
212
272
  ]
213
273
  });
214
274
  }
215
- function U({ open: e, onOpenChange: t, athleteId: n, displayName: r }) {
216
- let i = c(), [a, o] = _(""), [s, l] = _("COMPLETED"), [u, d] = _(B), [m, h] = _(""), [g, v] = _(""), [y, b] = _(""), [S, w] = _(""), [T, O] = _(null), k = () => {
217
- o(""), l("COMPLETED"), d(B()), h(""), v(""), b(""), w(""), O(null);
275
+ function te(e) {
276
+ let t = e.toLowerCase();
277
+ return /strength|lift|squat|deadlift|bench|1rm|weight/.test(t) ? C : /speed|sprint|agility|accel|split/.test(t) ? N : /endurance|aerobic|cardio|run|beep|yo-?yo/.test(t) ? b : /recovery|mobility|stretch|rest/.test(t) ? T : /accuracy|shoot|target/.test(t) ? j : C;
278
+ }
279
+ function ne({ rpe: t }) {
280
+ return /* @__PURE__ */ F("span", {
281
+ className: e("inline-flex h-7 min-w-[1.75rem] items-center justify-center rounded-md border px-1.5 text-sm font-semibold tabular-nums", t >= 8 ? "border-status-error-border text-status-error-text" : t >= 5 ? "border-status-warning-border text-status-warning-text" : "border-border-seam text-text-secondary"),
282
+ children: t
283
+ });
284
+ }
285
+ function re({ metric: e }) {
286
+ let t = J[e.type], r = e.previous == null ? null : e.latest - e.previous, o = e.max > e.min, s = o ? Math.round((e.latest - e.min) / (e.max - e.min) * 100) : 100, c = e.unit ? ` ${e.unit}` : "";
287
+ return /* @__PURE__ */ I(L, {
288
+ treatment: "metric",
289
+ className: "flex flex-col gap-3 p-5",
290
+ children: [
291
+ /* @__PURE__ */ I("div", {
292
+ className: "flex items-center justify-between gap-2",
293
+ children: [/* @__PURE__ */ I("span", {
294
+ className: "flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-[var(--color-accent-teal)]",
295
+ children: [/* @__PURE__ */ F(t, {
296
+ className: "h-4 w-4",
297
+ "aria-hidden": "true"
298
+ }), i[e.type]]
299
+ }), /* @__PURE__ */ F("span", {
300
+ className: "text-xs text-text-muted",
301
+ children: a(e.recordedAt)
302
+ })]
303
+ }),
304
+ /* @__PURE__ */ I("div", {
305
+ className: "flex items-end justify-between gap-3",
306
+ children: [/* @__PURE__ */ I("div", {
307
+ className: "min-w-0",
308
+ children: [/* @__PURE__ */ F("p", {
309
+ className: "truncate text-sm text-text-secondary",
310
+ children: e.label
311
+ }), /* @__PURE__ */ I("p", {
312
+ className: "mt-0.5 text-3xl font-bold leading-none tracking-tight tabular-nums text-text-primary",
313
+ children: [Q(e.latest), e.unit ? /* @__PURE__ */ F("span", {
314
+ className: "ml-1 text-base font-medium text-text-secondary",
315
+ children: e.unit
316
+ }) : null]
317
+ })]
318
+ }), e.series.length > 1 ? /* @__PURE__ */ F("div", {
319
+ className: "w-24 shrink-0 sm:w-28",
320
+ children: /* @__PURE__ */ F(n, {
321
+ data: e.series,
322
+ variant: "area",
323
+ height: 40,
324
+ label: `${e.label} trend`
325
+ })
326
+ }) : null]
327
+ }),
328
+ o ? /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("span", {
329
+ className: "block h-1.5 overflow-hidden rounded-full bg-bg-sunken",
330
+ "aria-hidden": "true",
331
+ children: /* @__PURE__ */ F("span", {
332
+ className: "block h-1.5 rounded-full bg-[var(--color-accent-teal)]",
333
+ style: { width: `${Math.max(4, Math.min(100, s))}%` }
334
+ })
335
+ }), /* @__PURE__ */ I("div", {
336
+ className: "mt-1 flex justify-between text-[0.7rem] tabular-nums text-text-muted",
337
+ children: [
338
+ /* @__PURE__ */ F("span", { children: Q(e.min) }),
339
+ /* @__PURE__ */ F("span", { children: Q((e.min + e.max) / 2) }),
340
+ /* @__PURE__ */ F("span", { children: Q(e.max) })
341
+ ]
342
+ })] }) : null,
343
+ /* @__PURE__ */ F("div", {
344
+ className: "mt-auto flex items-center gap-1.5 text-sm",
345
+ children: r == null || r === 0 ? /* @__PURE__ */ F("span", {
346
+ className: "text-text-muted",
347
+ children: e.count > 1 ? "No change vs previous" : "First reading"
348
+ }) : /* @__PURE__ */ I(P, { children: [/* @__PURE__ */ I("span", {
349
+ className: "inline-flex items-center gap-0.5 font-medium tabular-nums text-text-secondary",
350
+ children: [
351
+ F(r > 0 ? S : x, {
352
+ className: "h-4 w-4",
353
+ "aria-hidden": "true"
354
+ }),
355
+ Q(Math.abs(r)),
356
+ c
357
+ ]
358
+ }), /* @__PURE__ */ F("span", {
359
+ className: "text-text-muted",
360
+ children: "vs previous"
361
+ })] })
362
+ })
363
+ ]
364
+ });
365
+ }
366
+ function ie({ open: t, onOpenChange: n, athleteId: r, displayName: i }) {
367
+ let a = u(), [o, s] = y(""), [c, l] = y("COMPLETED"), [d, f] = y(Z), [p, g] = y(""), [_, v] = y(""), [b, x] = y(""), [S, C] = y(""), [w, T] = y(null), D = () => {
368
+ s(""), l("COMPLETED"), f(Z()), g(""), v(""), x(""), C(""), T(null);
218
369
  };
219
- return /* @__PURE__ */ E(A, {
220
- open: e,
221
- onOpenChange: t,
222
- children: /* @__PURE__ */ D(j, { children: [/* @__PURE__ */ E(N, { children: /* @__PURE__ */ D(P, { children: ["Log workout", r ? ` — ${r}` : ""] }) }), /* @__PURE__ */ D("form", {
370
+ return /* @__PURE__ */ F(R, {
371
+ open: t,
372
+ onOpenChange: n,
373
+ children: /* @__PURE__ */ I(z, { children: [/* @__PURE__ */ F(V, { children: /* @__PURE__ */ I(H, { children: ["Log workout", i ? ` — ${i}` : ""] }) }), /* @__PURE__ */ I("form", {
223
374
  onSubmit: async (e) => {
224
- if (e.preventDefault(), O(null), !a.trim()) {
225
- O("A workout title is required.");
375
+ if (e.preventDefault(), T(null), !o.trim()) {
376
+ T("A workout title is required.");
226
377
  return;
227
378
  }
228
- if (!u) {
229
- O("A performed date and time is required.");
379
+ if (!d) {
380
+ T("A performed date and time is required.");
230
381
  return;
231
382
  }
232
383
  try {
233
- await i.mutateAsync({
234
- athleteId: n,
235
- title: a.trim(),
236
- status: s,
237
- performedAt: new Date(u).toISOString(),
238
- durationMin: R(m),
239
- rpe: R(g),
240
- totalLoad: z(y),
384
+ await a.mutateAsync({
385
+ athleteId: r,
386
+ title: o.trim(),
387
+ status: c,
388
+ performedAt: new Date(d).toISOString(),
389
+ durationMin: Y(p),
390
+ rpe: Y(_),
391
+ totalLoad: X(b),
241
392
  notes: S.trim() || void 0
242
- }), k(), t(!1);
393
+ }), D(), n(!1);
243
394
  } catch (e) {
244
- O(e instanceof Error ? e.message : "Failed to log workout.");
395
+ T(e instanceof Error ? e.message : "Failed to log workout.");
245
396
  }
246
397
  },
247
398
  className: "space-y-4 px-1",
248
399
  children: [
249
- /* @__PURE__ */ E(f, {
400
+ /* @__PURE__ */ F(m, {
250
401
  label: "Title",
251
402
  htmlFor: "workoutTitle",
252
403
  required: !0,
253
- children: /* @__PURE__ */ E("input", {
404
+ children: /* @__PURE__ */ F("input", {
254
405
  id: "workoutTitle",
255
- className: p,
256
- value: a,
257
- onChange: (e) => o(e.target.value),
406
+ className: h,
407
+ value: o,
408
+ onChange: (e) => s(e.target.value),
258
409
  placeholder: "e.g. Lower-body strength"
259
410
  })
260
411
  }),
261
- /* @__PURE__ */ D("div", {
412
+ /* @__PURE__ */ I("div", {
262
413
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
263
- children: [/* @__PURE__ */ E(f, {
414
+ children: [/* @__PURE__ */ F(m, {
264
415
  label: "Status",
265
416
  htmlFor: "workoutStatus",
266
- children: /* @__PURE__ */ E("select", {
417
+ children: /* @__PURE__ */ F("select", {
267
418
  id: "workoutStatus",
268
- className: p,
269
- value: s,
419
+ className: h,
420
+ value: c,
270
421
  onChange: (e) => l(e.target.value),
271
- children: I.map((e) => /* @__PURE__ */ E("option", {
422
+ children: G.map((e) => /* @__PURE__ */ F("option", {
272
423
  value: e,
273
424
  children: e.charAt(0) + e.slice(1).toLowerCase()
274
425
  }, e))
275
426
  })
276
- }), /* @__PURE__ */ E(f, {
427
+ }), /* @__PURE__ */ F(m, {
277
428
  label: "Performed at",
278
429
  htmlFor: "workoutPerformedAt",
279
430
  required: !0,
280
- children: /* @__PURE__ */ E("input", {
431
+ children: /* @__PURE__ */ F("input", {
281
432
  id: "workoutPerformedAt",
282
433
  type: "datetime-local",
283
- className: p,
284
- value: u,
285
- onChange: (e) => d(e.target.value)
434
+ className: h,
435
+ value: d,
436
+ onChange: (e) => f(e.target.value)
286
437
  })
287
438
  })]
288
439
  }),
289
- /* @__PURE__ */ D("div", {
440
+ /* @__PURE__ */ I("div", {
290
441
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
291
442
  children: [
292
- /* @__PURE__ */ E(f, {
443
+ /* @__PURE__ */ F(m, {
293
444
  label: "Duration (min)",
294
445
  htmlFor: "workoutDuration",
295
- children: /* @__PURE__ */ E("input", {
446
+ children: /* @__PURE__ */ F("input", {
296
447
  id: "workoutDuration",
297
448
  inputMode: "numeric",
298
- className: p,
299
- value: m,
300
- onChange: (e) => h(e.target.value)
449
+ className: h,
450
+ value: p,
451
+ onChange: (e) => g(e.target.value)
301
452
  })
302
453
  }),
303
- /* @__PURE__ */ E(f, {
454
+ /* @__PURE__ */ F(m, {
304
455
  label: "RPE (1–10)",
305
456
  htmlFor: "workoutRpe",
306
- children: /* @__PURE__ */ E("input", {
457
+ children: /* @__PURE__ */ F("input", {
307
458
  id: "workoutRpe",
308
459
  inputMode: "numeric",
309
- className: p,
310
- value: g,
460
+ className: h,
461
+ value: _,
311
462
  onChange: (e) => v(e.target.value)
312
463
  })
313
464
  }),
314
- /* @__PURE__ */ E(f, {
465
+ /* @__PURE__ */ F(m, {
315
466
  label: "Total load",
316
467
  htmlFor: "workoutLoad",
317
- children: /* @__PURE__ */ E("input", {
468
+ children: /* @__PURE__ */ F("input", {
318
469
  id: "workoutLoad",
319
470
  inputMode: "decimal",
320
- className: p,
321
- value: y,
322
- onChange: (e) => b(e.target.value)
471
+ className: h,
472
+ value: b,
473
+ onChange: (e) => x(e.target.value)
323
474
  })
324
475
  })
325
476
  ]
326
477
  }),
327
- /* @__PURE__ */ E(f, {
478
+ /* @__PURE__ */ F(m, {
328
479
  label: "Notes",
329
480
  htmlFor: "workoutNotes",
330
- children: /* @__PURE__ */ E("textarea", {
481
+ children: /* @__PURE__ */ F("textarea", {
331
482
  id: "workoutNotes",
332
483
  rows: 2,
333
- className: p,
484
+ className: h,
334
485
  value: S,
335
- onChange: (e) => w(e.target.value),
486
+ onChange: (e) => C(e.target.value),
336
487
  placeholder: "How did the session go?"
337
488
  })
338
489
  }),
339
- T && /* @__PURE__ */ E("p", {
490
+ w && /* @__PURE__ */ F("p", {
340
491
  className: "text-sm text-status-error-text",
341
- children: T
492
+ children: w
342
493
  }),
343
- /* @__PURE__ */ D(M, { children: [/* @__PURE__ */ E("button", {
494
+ /* @__PURE__ */ I(B, { children: [/* @__PURE__ */ F("button", {
344
495
  type: "button",
345
- onClick: () => t(!1),
496
+ onClick: () => n(!1),
346
497
  className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
347
498
  children: "Cancel"
348
- }), /* @__PURE__ */ D("button", {
499
+ }), /* @__PURE__ */ I("button", {
349
500
  type: "submit",
350
- disabled: i.isPending,
351
- 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",
352
- children: [i.isPending ? /* @__PURE__ */ E(x, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ E(C, { className: "h-4 w-4" }), "Log workout"]
501
+ disabled: a.isPending,
502
+ className: e(q, "disabled:opacity-60"),
503
+ children: [a.isPending ? /* @__PURE__ */ F(E, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ F(k, { className: "h-4 w-4" }), "Log workout"]
353
504
  })] })
354
505
  ]
355
506
  })] })
356
507
  });
357
508
  }
358
- function W({ open: e, onOpenChange: t, athleteId: r, displayName: i }) {
359
- let a = u(), [o, s] = _("CUSTOM"), [c, l] = _(""), [d, m] = _(""), [h, g] = _(""), [v, y] = _(""), [b, C] = _(B), [w, T] = _(null), O = () => {
360
- s("CUSTOM"), l(""), m(""), g(""), y(""), C(B()), T(null);
509
+ function ae({ open: t, onOpenChange: n, athleteId: r, displayName: a }) {
510
+ let o = f(), [s, c] = y("CUSTOM"), [l, u] = y(""), [d, p] = y(""), [g, _] = y(""), [v, b] = y(""), [x, S] = y(Z), [C, w] = y(null), T = () => {
511
+ c("CUSTOM"), u(""), p(""), _(""), b(""), S(Z()), w(null);
361
512
  };
362
- return /* @__PURE__ */ E(A, {
363
- open: e,
364
- onOpenChange: t,
365
- children: /* @__PURE__ */ D(j, { children: [/* @__PURE__ */ E(N, { children: /* @__PURE__ */ D(P, { children: ["Record metric", i ? ` — ${i}` : ""] }) }), /* @__PURE__ */ D("form", {
513
+ return /* @__PURE__ */ F(R, {
514
+ open: t,
515
+ onOpenChange: n,
516
+ children: /* @__PURE__ */ I(z, { children: [/* @__PURE__ */ F(V, { children: /* @__PURE__ */ I(H, { children: ["Record metric", a ? ` — ${a}` : ""] }) }), /* @__PURE__ */ I("form", {
366
517
  onSubmit: async (e) => {
367
- if (e.preventDefault(), T(null), !c.trim()) {
368
- T("A metric label is required.");
518
+ if (e.preventDefault(), w(null), !l.trim()) {
519
+ w("A metric label is required.");
369
520
  return;
370
521
  }
371
- let n = z(d);
372
- if (n === void 0) {
373
- T("A numeric value is required.");
522
+ let t = X(d);
523
+ if (t === void 0) {
524
+ w("A numeric value is required.");
374
525
  return;
375
526
  }
376
- if (!b) {
377
- T("A recorded date and time is required.");
527
+ if (!x) {
528
+ w("A recorded date and time is required.");
378
529
  return;
379
530
  }
380
531
  try {
381
- await a.mutateAsync({
532
+ await o.mutateAsync({
382
533
  athleteId: r,
383
- type: o,
384
- label: c.trim(),
385
- value: n,
386
- unit: h.trim() || void 0,
534
+ type: s,
535
+ label: l.trim(),
536
+ value: t,
537
+ unit: g.trim() || void 0,
387
538
  source: v.trim() || void 0,
388
- recordedAt: new Date(b).toISOString()
389
- }), O(), t(!1);
539
+ recordedAt: new Date(x).toISOString()
540
+ }), T(), n(!1);
390
541
  } catch (e) {
391
- T(e instanceof Error ? e.message : "Failed to record metric.");
542
+ w(e instanceof Error ? e.message : "Failed to record metric.");
392
543
  }
393
544
  },
394
545
  className: "space-y-4 px-1",
395
546
  children: [
396
- /* @__PURE__ */ D("div", {
547
+ /* @__PURE__ */ I("div", {
397
548
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
398
- children: [/* @__PURE__ */ E(f, {
549
+ children: [/* @__PURE__ */ F(m, {
399
550
  label: "Type",
400
551
  htmlFor: "metricType",
401
- children: /* @__PURE__ */ E("select", {
552
+ children: /* @__PURE__ */ F("select", {
402
553
  id: "metricType",
403
- className: p,
404
- value: o,
405
- onChange: (e) => s(e.target.value),
406
- children: L.map((e) => /* @__PURE__ */ E("option", {
554
+ className: h,
555
+ value: s,
556
+ onChange: (e) => c(e.target.value),
557
+ children: K.map((e) => /* @__PURE__ */ F("option", {
407
558
  value: e,
408
- children: n[e]
559
+ children: i[e]
409
560
  }, e))
410
561
  })
411
- }), /* @__PURE__ */ E(f, {
562
+ }), /* @__PURE__ */ F(m, {
412
563
  label: "Recorded at",
413
564
  htmlFor: "metricRecordedAt",
414
565
  required: !0,
415
- children: /* @__PURE__ */ E("input", {
566
+ children: /* @__PURE__ */ F("input", {
416
567
  id: "metricRecordedAt",
417
568
  type: "datetime-local",
418
- className: p,
419
- value: b,
420
- onChange: (e) => C(e.target.value)
569
+ className: h,
570
+ value: x,
571
+ onChange: (e) => S(e.target.value)
421
572
  })
422
573
  })]
423
574
  }),
424
- /* @__PURE__ */ E(f, {
575
+ /* @__PURE__ */ F(m, {
425
576
  label: "Label",
426
577
  htmlFor: "metricLabel",
427
578
  required: !0,
428
- children: /* @__PURE__ */ E("input", {
579
+ children: /* @__PURE__ */ F("input", {
429
580
  id: "metricLabel",
430
- className: p,
431
- value: c,
432
- onChange: (e) => l(e.target.value),
581
+ className: h,
582
+ value: l,
583
+ onChange: (e) => u(e.target.value),
433
584
  placeholder: "e.g. 40m sprint"
434
585
  })
435
586
  }),
436
- /* @__PURE__ */ D("div", {
587
+ /* @__PURE__ */ I("div", {
437
588
  className: "grid grid-cols-2 gap-4",
438
- children: [/* @__PURE__ */ E(f, {
589
+ children: [/* @__PURE__ */ F(m, {
439
590
  label: "Value",
440
591
  htmlFor: "metricValue",
441
592
  required: !0,
442
- children: /* @__PURE__ */ E("input", {
593
+ children: /* @__PURE__ */ F("input", {
443
594
  id: "metricValue",
444
595
  inputMode: "decimal",
445
- className: p,
596
+ className: h,
446
597
  value: d,
447
- onChange: (e) => m(e.target.value),
598
+ onChange: (e) => p(e.target.value),
448
599
  placeholder: "e.g. 4.8"
449
600
  })
450
- }), /* @__PURE__ */ E(f, {
601
+ }), /* @__PURE__ */ F(m, {
451
602
  label: "Unit",
452
603
  htmlFor: "metricUnit",
453
- children: /* @__PURE__ */ E("input", {
604
+ children: /* @__PURE__ */ F("input", {
454
605
  id: "metricUnit",
455
- className: p,
456
- value: h,
457
- onChange: (e) => g(e.target.value),
606
+ className: h,
607
+ value: g,
608
+ onChange: (e) => _(e.target.value),
458
609
  placeholder: "e.g. s, kg, bpm"
459
610
  })
460
611
  })]
461
612
  }),
462
- /* @__PURE__ */ E(f, {
613
+ /* @__PURE__ */ F(m, {
463
614
  label: "Source",
464
615
  htmlFor: "metricSource",
465
616
  hint: "Optional — device, test or coach.",
466
- children: /* @__PURE__ */ E("input", {
617
+ children: /* @__PURE__ */ F("input", {
467
618
  id: "metricSource",
468
- className: p,
619
+ className: h,
469
620
  value: v,
470
- onChange: (e) => y(e.target.value),
621
+ onChange: (e) => b(e.target.value),
471
622
  placeholder: "e.g. GPS vest"
472
623
  })
473
624
  }),
474
- w && /* @__PURE__ */ E("p", {
625
+ C && /* @__PURE__ */ F("p", {
475
626
  className: "text-sm text-status-error-text",
476
- children: w
627
+ children: C
477
628
  }),
478
- /* @__PURE__ */ D(M, { children: [/* @__PURE__ */ E("button", {
629
+ /* @__PURE__ */ I(B, { children: [/* @__PURE__ */ F("button", {
479
630
  type: "button",
480
- onClick: () => t(!1),
631
+ onClick: () => n(!1),
481
632
  className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
482
633
  children: "Cancel"
483
- }), /* @__PURE__ */ D("button", {
634
+ }), /* @__PURE__ */ I("button", {
484
635
  type: "submit",
485
- disabled: a.isPending,
486
- 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",
487
- children: [a.isPending ? /* @__PURE__ */ E(x, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ E(S, { className: "h-4 w-4" }), "Record metric"]
636
+ disabled: o.isPending,
637
+ className: e(q, "disabled:opacity-60"),
638
+ children: [o.isPending ? /* @__PURE__ */ F(E, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ F(O, { className: "h-4 w-4" }), "Record metric"]
488
639
  })] })
489
640
  ]
490
641
  })] })
491
642
  });
492
643
  }
493
644
  //#endregion
494
- export { V as PerformancePage };
645
+ export { $ as PerformancePage };
495
646
 
496
647
  //# sourceMappingURL=PerformancePage.js.map