@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.
- package/dist/atheletebridge/AthleteBridgeRoot.js +55 -39
- package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
- package/dist/atheletebridge/AthleteBridgeRoutes.js +18 -6
- package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
- package/dist/atheletebridge/components/Crest.js +70 -0
- package/dist/atheletebridge/components/Crest.js.map +1 -0
- package/dist/atheletebridge/components/FixtureCard.js +8 -72
- package/dist/atheletebridge/components/FixtureCard.js.map +1 -1
- package/dist/atheletebridge/components/MatchupRow.js +74 -0
- package/dist/atheletebridge/components/MatchupRow.js.map +1 -0
- package/dist/atheletebridge/components/MetricsCard.js +61 -21
- package/dist/atheletebridge/components/MetricsCard.js.map +1 -1
- package/dist/atheletebridge/components/ProgramCard.js +75 -43
- package/dist/atheletebridge/components/ProgramCard.js.map +1 -1
- package/dist/atheletebridge/components/Scoreboard.js +163 -0
- package/dist/atheletebridge/components/Scoreboard.js.map +1 -0
- package/dist/atheletebridge/components/SessionCard.js +64 -41
- package/dist/atheletebridge/components/SessionCard.js.map +1 -1
- package/dist/atheletebridge/components/SessionStatusTimeline.js +80 -0
- package/dist/atheletebridge/components/SessionStatusTimeline.js.map +1 -0
- package/dist/atheletebridge/components/StatusBadge.js +5 -5
- package/dist/atheletebridge/components/StatusBadge.js.map +1 -1
- package/dist/atheletebridge/components/TeamCard.js +65 -35
- package/dist/atheletebridge/components/TeamCard.js.map +1 -1
- package/dist/atheletebridge/components/UserAvatar.js +33 -0
- package/dist/atheletebridge/components/UserAvatar.js.map +1 -0
- package/dist/atheletebridge/components/domain.js +5 -2
- package/dist/atheletebridge/components/domain.js.map +1 -1
- package/dist/atheletebridge/components/viz/AvatarStack.js +2 -0
- package/dist/atheletebridge/components/viz/BarChart.js +83 -0
- package/dist/atheletebridge/components/viz/BarChart.js.map +1 -0
- package/dist/atheletebridge/components/viz/DonutChart.js +109 -0
- package/dist/atheletebridge/components/viz/DonutChart.js.map +1 -0
- package/dist/atheletebridge/components/viz/LineChart.js +123 -0
- package/dist/atheletebridge/components/viz/LineChart.js.map +1 -0
- package/dist/atheletebridge/components/viz/ProgressRing.js +6 -0
- package/dist/atheletebridge/components/viz/ProgressRing.js.map +1 -0
- package/dist/atheletebridge/components/viz/RatingStars.js +92 -0
- package/dist/atheletebridge/components/viz/RatingStars.js.map +1 -0
- package/dist/atheletebridge/components/viz/Sparkline.js +74 -0
- package/dist/atheletebridge/components/viz/Sparkline.js.map +1 -0
- package/dist/atheletebridge/components/viz/StatCard.js +60 -0
- package/dist/atheletebridge/components/viz/StatCard.js.map +1 -0
- package/dist/atheletebridge/components/viz/StepProgress.js +3 -0
- package/dist/atheletebridge/components/viz/Timeline.js +66 -0
- package/dist/atheletebridge/components/viz/Timeline.js.map +1 -0
- package/dist/atheletebridge/components/viz/index.js +13 -0
- package/dist/atheletebridge/components/viz/lib/Avatar.js +1 -0
- package/dist/atheletebridge/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/atheletebridge/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/atheletebridge/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/atheletebridge/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/atheletebridge/components/viz/lib/format.js +17 -0
- package/dist/atheletebridge/components/viz/lib/format.js.map +1 -0
- package/dist/atheletebridge/components/viz/lib/geometry.js +61 -0
- package/dist/atheletebridge/components/viz/lib/geometry.js.map +1 -0
- package/dist/atheletebridge/components/viz/lib/hooks.js +39 -0
- package/dist/atheletebridge/components/viz/lib/hooks.js.map +1 -0
- package/dist/atheletebridge/components/viz/lib/palette.js +27 -0
- package/dist/atheletebridge/components/viz/lib/palette.js.map +1 -0
- package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +369 -163
- package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
- package/dist/atheletebridge/pages/DashboardPage.js +182 -117
- package/dist/atheletebridge/pages/DashboardPage.js.map +1 -1
- package/dist/atheletebridge/pages/StandingsPage.js +119 -95
- package/dist/atheletebridge/pages/StandingsPage.js.map +1 -1
- package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js +372 -0
- package/dist/atheletebridge/pages/analytics/CoachAnalyticsPage.js.map +1 -0
- package/dist/atheletebridge/pages/athletes/AthleteProfilePage.js +511 -0
- package/dist/atheletebridge/pages/athletes/AthleteProfilePage.js.map +1 -0
- package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +120 -131
- package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js +264 -176
- package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js.map +1 -1
- package/dist/atheletebridge/pages/fixtures/FixturesListPage.js +84 -47
- package/dist/atheletebridge/pages/fixtures/FixturesListPage.js.map +1 -1
- package/dist/atheletebridge/pages/performance/PerformancePage.js +432 -281
- package/dist/atheletebridge/pages/performance/PerformancePage.js.map +1 -1
- package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +187 -123
- package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/programs/ProgramsListPage.js +56 -39
- package/dist/atheletebridge/pages/programs/ProgramsListPage.js.map +1 -1
- package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +267 -139
- package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/sessions/SessionFormPage.js +253 -162
- package/dist/atheletebridge/pages/sessions/SessionFormPage.js.map +1 -1
- package/dist/atheletebridge/pages/sessions/SessionsListPage.js +38 -36
- package/dist/atheletebridge/pages/sessions/SessionsListPage.js.map +1 -1
- package/dist/atheletebridge/pages/teams/TeamDetailPage.js +437 -189
- package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/teams/TeamFormPage.js +368 -177
- package/dist/atheletebridge/pages/teams/TeamFormPage.js.map +1 -1
- package/dist/atheletebridge/pages/teams/TeamsListPage.js +3 -0
- package/dist/atheletebridge/pages/teams/TeamsListPage.js.map +1 -1
- package/dist/atheletebridge/pages/tournaments/TournamentBracketPage.js +298 -0
- package/dist/atheletebridge/pages/tournaments/TournamentBracketPage.js.map +1 -0
- package/dist/atheletebridge/utils/identity.js +31 -0
- package/dist/atheletebridge/utils/identity.js.map +1 -0
- package/dist/atheletebridge/utils/timeAgo.js +20 -0
- package/dist/atheletebridge/utils/timeAgo.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,496 +1,647 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
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
|
|
19
|
+
var W = 10, G = [
|
|
17
20
|
"COMPLETED",
|
|
18
21
|
"PLANNED",
|
|
19
22
|
"SKIPPED"
|
|
20
|
-
],
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
|
35
|
-
let [
|
|
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__ */
|
|
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__ */
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
}),
|
|
51
|
-
athleteId:
|
|
52
|
-
displayName:
|
|
53
|
-
}) : /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
62
|
-
let [
|
|
63
|
-
athleteId:
|
|
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:
|
|
66
|
-
offset:
|
|
80
|
+
limit: W,
|
|
81
|
+
offset: i * W
|
|
67
82
|
}
|
|
68
|
-
}),
|
|
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
|
|
71
|
-
let n = e.get(
|
|
72
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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__ */
|
|
180
|
+
/* @__PURE__ */ I("div", {
|
|
84
181
|
className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
85
|
-
children: [/* @__PURE__ */
|
|
182
|
+
children: [/* @__PURE__ */ I("p", {
|
|
86
183
|
className: "text-sm text-text-secondary",
|
|
87
|
-
children: ["Tracking ", /* @__PURE__ */
|
|
184
|
+
children: ["Tracking ", /* @__PURE__ */ F("span", {
|
|
88
185
|
className: "font-medium text-text-primary",
|
|
89
|
-
children:
|
|
186
|
+
children: n || "athlete"
|
|
90
187
|
})]
|
|
91
|
-
}), /* @__PURE__ */
|
|
188
|
+
}), /* @__PURE__ */ I("div", {
|
|
92
189
|
className: "flex flex-wrap gap-2",
|
|
93
|
-
children: [/* @__PURE__ */
|
|
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: () =>
|
|
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__ */
|
|
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__ */
|
|
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
|
-
}),
|
|
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__ */
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
className: "
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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__ */
|
|
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
|
-
}),
|
|
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__ */
|
|
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__ */
|
|
229
|
+
action: /* @__PURE__ */ I("button", {
|
|
161
230
|
type: "button",
|
|
162
|
-
onClick: () =>
|
|
163
|
-
className:
|
|
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__ */
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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:
|
|
196
|
-
hasMore:
|
|
197
|
-
onPrev: () =>
|
|
198
|
-
onNext: () =>
|
|
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__ */
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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__ */
|
|
207
|
-
open:
|
|
208
|
-
onOpenChange:
|
|
209
|
-
athleteId:
|
|
210
|
-
displayName:
|
|
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
|
|
216
|
-
let
|
|
217
|
-
|
|
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__ */
|
|
220
|
-
open:
|
|
221
|
-
onOpenChange:
|
|
222
|
-
children: /* @__PURE__ */
|
|
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(),
|
|
225
|
-
|
|
375
|
+
if (e.preventDefault(), T(null), !o.trim()) {
|
|
376
|
+
T("A workout title is required.");
|
|
226
377
|
return;
|
|
227
378
|
}
|
|
228
|
-
if (!
|
|
229
|
-
|
|
379
|
+
if (!d) {
|
|
380
|
+
T("A performed date and time is required.");
|
|
230
381
|
return;
|
|
231
382
|
}
|
|
232
383
|
try {
|
|
233
|
-
await
|
|
234
|
-
athleteId:
|
|
235
|
-
title:
|
|
236
|
-
status:
|
|
237
|
-
performedAt: new Date(
|
|
238
|
-
durationMin:
|
|
239
|
-
rpe:
|
|
240
|
-
totalLoad:
|
|
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
|
-
}),
|
|
393
|
+
}), D(), n(!1);
|
|
243
394
|
} catch (e) {
|
|
244
|
-
|
|
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__ */
|
|
400
|
+
/* @__PURE__ */ F(m, {
|
|
250
401
|
label: "Title",
|
|
251
402
|
htmlFor: "workoutTitle",
|
|
252
403
|
required: !0,
|
|
253
|
-
children: /* @__PURE__ */
|
|
404
|
+
children: /* @__PURE__ */ F("input", {
|
|
254
405
|
id: "workoutTitle",
|
|
255
|
-
className:
|
|
256
|
-
value:
|
|
257
|
-
onChange: (e) =>
|
|
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__ */
|
|
412
|
+
/* @__PURE__ */ I("div", {
|
|
262
413
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
263
|
-
children: [/* @__PURE__ */
|
|
414
|
+
children: [/* @__PURE__ */ F(m, {
|
|
264
415
|
label: "Status",
|
|
265
416
|
htmlFor: "workoutStatus",
|
|
266
|
-
children: /* @__PURE__ */
|
|
417
|
+
children: /* @__PURE__ */ F("select", {
|
|
267
418
|
id: "workoutStatus",
|
|
268
|
-
className:
|
|
269
|
-
value:
|
|
419
|
+
className: h,
|
|
420
|
+
value: c,
|
|
270
421
|
onChange: (e) => l(e.target.value),
|
|
271
|
-
children:
|
|
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__ */
|
|
427
|
+
}), /* @__PURE__ */ F(m, {
|
|
277
428
|
label: "Performed at",
|
|
278
429
|
htmlFor: "workoutPerformedAt",
|
|
279
430
|
required: !0,
|
|
280
|
-
children: /* @__PURE__ */
|
|
431
|
+
children: /* @__PURE__ */ F("input", {
|
|
281
432
|
id: "workoutPerformedAt",
|
|
282
433
|
type: "datetime-local",
|
|
283
|
-
className:
|
|
284
|
-
value:
|
|
285
|
-
onChange: (e) =>
|
|
434
|
+
className: h,
|
|
435
|
+
value: d,
|
|
436
|
+
onChange: (e) => f(e.target.value)
|
|
286
437
|
})
|
|
287
438
|
})]
|
|
288
439
|
}),
|
|
289
|
-
/* @__PURE__ */
|
|
440
|
+
/* @__PURE__ */ I("div", {
|
|
290
441
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
|
|
291
442
|
children: [
|
|
292
|
-
/* @__PURE__ */
|
|
443
|
+
/* @__PURE__ */ F(m, {
|
|
293
444
|
label: "Duration (min)",
|
|
294
445
|
htmlFor: "workoutDuration",
|
|
295
|
-
children: /* @__PURE__ */
|
|
446
|
+
children: /* @__PURE__ */ F("input", {
|
|
296
447
|
id: "workoutDuration",
|
|
297
448
|
inputMode: "numeric",
|
|
298
|
-
className:
|
|
299
|
-
value:
|
|
300
|
-
onChange: (e) =>
|
|
449
|
+
className: h,
|
|
450
|
+
value: p,
|
|
451
|
+
onChange: (e) => g(e.target.value)
|
|
301
452
|
})
|
|
302
453
|
}),
|
|
303
|
-
/* @__PURE__ */
|
|
454
|
+
/* @__PURE__ */ F(m, {
|
|
304
455
|
label: "RPE (1–10)",
|
|
305
456
|
htmlFor: "workoutRpe",
|
|
306
|
-
children: /* @__PURE__ */
|
|
457
|
+
children: /* @__PURE__ */ F("input", {
|
|
307
458
|
id: "workoutRpe",
|
|
308
459
|
inputMode: "numeric",
|
|
309
|
-
className:
|
|
310
|
-
value:
|
|
460
|
+
className: h,
|
|
461
|
+
value: _,
|
|
311
462
|
onChange: (e) => v(e.target.value)
|
|
312
463
|
})
|
|
313
464
|
}),
|
|
314
|
-
/* @__PURE__ */
|
|
465
|
+
/* @__PURE__ */ F(m, {
|
|
315
466
|
label: "Total load",
|
|
316
467
|
htmlFor: "workoutLoad",
|
|
317
|
-
children: /* @__PURE__ */
|
|
468
|
+
children: /* @__PURE__ */ F("input", {
|
|
318
469
|
id: "workoutLoad",
|
|
319
470
|
inputMode: "decimal",
|
|
320
|
-
className:
|
|
321
|
-
value:
|
|
322
|
-
onChange: (e) =>
|
|
471
|
+
className: h,
|
|
472
|
+
value: b,
|
|
473
|
+
onChange: (e) => x(e.target.value)
|
|
323
474
|
})
|
|
324
475
|
})
|
|
325
476
|
]
|
|
326
477
|
}),
|
|
327
|
-
/* @__PURE__ */
|
|
478
|
+
/* @__PURE__ */ F(m, {
|
|
328
479
|
label: "Notes",
|
|
329
480
|
htmlFor: "workoutNotes",
|
|
330
|
-
children: /* @__PURE__ */
|
|
481
|
+
children: /* @__PURE__ */ F("textarea", {
|
|
331
482
|
id: "workoutNotes",
|
|
332
483
|
rows: 2,
|
|
333
|
-
className:
|
|
484
|
+
className: h,
|
|
334
485
|
value: S,
|
|
335
|
-
onChange: (e) =>
|
|
486
|
+
onChange: (e) => C(e.target.value),
|
|
336
487
|
placeholder: "How did the session go?"
|
|
337
488
|
})
|
|
338
489
|
}),
|
|
339
|
-
|
|
490
|
+
w && /* @__PURE__ */ F("p", {
|
|
340
491
|
className: "text-sm text-status-error-text",
|
|
341
|
-
children:
|
|
492
|
+
children: w
|
|
342
493
|
}),
|
|
343
|
-
/* @__PURE__ */
|
|
494
|
+
/* @__PURE__ */ I(B, { children: [/* @__PURE__ */ F("button", {
|
|
344
495
|
type: "button",
|
|
345
|
-
onClick: () =>
|
|
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__ */
|
|
499
|
+
}), /* @__PURE__ */ I("button", {
|
|
349
500
|
type: "submit",
|
|
350
|
-
disabled:
|
|
351
|
-
className: "
|
|
352
|
-
children: [
|
|
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
|
|
359
|
-
let
|
|
360
|
-
|
|
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__ */
|
|
363
|
-
open:
|
|
364
|
-
onOpenChange:
|
|
365
|
-
children: /* @__PURE__ */
|
|
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(),
|
|
368
|
-
|
|
518
|
+
if (e.preventDefault(), w(null), !l.trim()) {
|
|
519
|
+
w("A metric label is required.");
|
|
369
520
|
return;
|
|
370
521
|
}
|
|
371
|
-
let
|
|
372
|
-
if (
|
|
373
|
-
|
|
522
|
+
let t = X(d);
|
|
523
|
+
if (t === void 0) {
|
|
524
|
+
w("A numeric value is required.");
|
|
374
525
|
return;
|
|
375
526
|
}
|
|
376
|
-
if (!
|
|
377
|
-
|
|
527
|
+
if (!x) {
|
|
528
|
+
w("A recorded date and time is required.");
|
|
378
529
|
return;
|
|
379
530
|
}
|
|
380
531
|
try {
|
|
381
|
-
await
|
|
532
|
+
await o.mutateAsync({
|
|
382
533
|
athleteId: r,
|
|
383
|
-
type:
|
|
384
|
-
label:
|
|
385
|
-
value:
|
|
386
|
-
unit:
|
|
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(
|
|
389
|
-
}),
|
|
539
|
+
recordedAt: new Date(x).toISOString()
|
|
540
|
+
}), T(), n(!1);
|
|
390
541
|
} catch (e) {
|
|
391
|
-
|
|
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__ */
|
|
547
|
+
/* @__PURE__ */ I("div", {
|
|
397
548
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
398
|
-
children: [/* @__PURE__ */
|
|
549
|
+
children: [/* @__PURE__ */ F(m, {
|
|
399
550
|
label: "Type",
|
|
400
551
|
htmlFor: "metricType",
|
|
401
|
-
children: /* @__PURE__ */
|
|
552
|
+
children: /* @__PURE__ */ F("select", {
|
|
402
553
|
id: "metricType",
|
|
403
|
-
className:
|
|
404
|
-
value:
|
|
405
|
-
onChange: (e) =>
|
|
406
|
-
children:
|
|
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:
|
|
559
|
+
children: i[e]
|
|
409
560
|
}, e))
|
|
410
561
|
})
|
|
411
|
-
}), /* @__PURE__ */
|
|
562
|
+
}), /* @__PURE__ */ F(m, {
|
|
412
563
|
label: "Recorded at",
|
|
413
564
|
htmlFor: "metricRecordedAt",
|
|
414
565
|
required: !0,
|
|
415
|
-
children: /* @__PURE__ */
|
|
566
|
+
children: /* @__PURE__ */ F("input", {
|
|
416
567
|
id: "metricRecordedAt",
|
|
417
568
|
type: "datetime-local",
|
|
418
|
-
className:
|
|
419
|
-
value:
|
|
420
|
-
onChange: (e) =>
|
|
569
|
+
className: h,
|
|
570
|
+
value: x,
|
|
571
|
+
onChange: (e) => S(e.target.value)
|
|
421
572
|
})
|
|
422
573
|
})]
|
|
423
574
|
}),
|
|
424
|
-
/* @__PURE__ */
|
|
575
|
+
/* @__PURE__ */ F(m, {
|
|
425
576
|
label: "Label",
|
|
426
577
|
htmlFor: "metricLabel",
|
|
427
578
|
required: !0,
|
|
428
|
-
children: /* @__PURE__ */
|
|
579
|
+
children: /* @__PURE__ */ F("input", {
|
|
429
580
|
id: "metricLabel",
|
|
430
|
-
className:
|
|
431
|
-
value:
|
|
432
|
-
onChange: (e) =>
|
|
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__ */
|
|
587
|
+
/* @__PURE__ */ I("div", {
|
|
437
588
|
className: "grid grid-cols-2 gap-4",
|
|
438
|
-
children: [/* @__PURE__ */
|
|
589
|
+
children: [/* @__PURE__ */ F(m, {
|
|
439
590
|
label: "Value",
|
|
440
591
|
htmlFor: "metricValue",
|
|
441
592
|
required: !0,
|
|
442
|
-
children: /* @__PURE__ */
|
|
593
|
+
children: /* @__PURE__ */ F("input", {
|
|
443
594
|
id: "metricValue",
|
|
444
595
|
inputMode: "decimal",
|
|
445
|
-
className:
|
|
596
|
+
className: h,
|
|
446
597
|
value: d,
|
|
447
|
-
onChange: (e) =>
|
|
598
|
+
onChange: (e) => p(e.target.value),
|
|
448
599
|
placeholder: "e.g. 4.8"
|
|
449
600
|
})
|
|
450
|
-
}), /* @__PURE__ */
|
|
601
|
+
}), /* @__PURE__ */ F(m, {
|
|
451
602
|
label: "Unit",
|
|
452
603
|
htmlFor: "metricUnit",
|
|
453
|
-
children: /* @__PURE__ */
|
|
604
|
+
children: /* @__PURE__ */ F("input", {
|
|
454
605
|
id: "metricUnit",
|
|
455
|
-
className:
|
|
456
|
-
value:
|
|
457
|
-
onChange: (e) =>
|
|
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__ */
|
|
613
|
+
/* @__PURE__ */ F(m, {
|
|
463
614
|
label: "Source",
|
|
464
615
|
htmlFor: "metricSource",
|
|
465
616
|
hint: "Optional — device, test or coach.",
|
|
466
|
-
children: /* @__PURE__ */
|
|
617
|
+
children: /* @__PURE__ */ F("input", {
|
|
467
618
|
id: "metricSource",
|
|
468
|
-
className:
|
|
619
|
+
className: h,
|
|
469
620
|
value: v,
|
|
470
|
-
onChange: (e) =>
|
|
621
|
+
onChange: (e) => b(e.target.value),
|
|
471
622
|
placeholder: "e.g. GPS vest"
|
|
472
623
|
})
|
|
473
624
|
}),
|
|
474
|
-
|
|
625
|
+
C && /* @__PURE__ */ F("p", {
|
|
475
626
|
className: "text-sm text-status-error-text",
|
|
476
|
-
children:
|
|
627
|
+
children: C
|
|
477
628
|
}),
|
|
478
|
-
/* @__PURE__ */
|
|
629
|
+
/* @__PURE__ */ I(B, { children: [/* @__PURE__ */ F("button", {
|
|
479
630
|
type: "button",
|
|
480
|
-
onClick: () =>
|
|
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__ */
|
|
634
|
+
}), /* @__PURE__ */ I("button", {
|
|
484
635
|
type: "submit",
|
|
485
|
-
disabled:
|
|
486
|
-
className: "
|
|
487
|
-
children: [
|
|
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 {
|
|
645
|
+
export { $ as PerformancePage };
|
|
495
646
|
|
|
496
647
|
//# sourceMappingURL=PerformancePage.js.map
|