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