@burdenoff/microfe-atheletebridge 2026.629.1 → 2026.705.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/atheletebridge/AthleteBridgeRoot.js +45 -37
- package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
- package/dist/atheletebridge/AthleteBridgeRoutes.js +10 -6
- package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
- package/dist/atheletebridge/components/AthleteSelect.js +66 -0
- package/dist/atheletebridge/components/AthleteSelect.js.map +1 -0
- package/dist/atheletebridge/components/DrillVideoLink.js +28 -0
- package/dist/atheletebridge/components/DrillVideoLink.js.map +1 -0
- package/dist/atheletebridge/components/MetricsCard.js +20 -46
- package/dist/atheletebridge/components/MetricsCard.js.map +1 -1
- package/dist/atheletebridge/components/UserSearchSelect.js +129 -0
- package/dist/atheletebridge/components/UserSearchSelect.js.map +1 -0
- package/dist/atheletebridge/components/domain.js +10 -1
- package/dist/atheletebridge/components/domain.js.map +1 -1
- package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +313 -180
- package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
- package/dist/atheletebridge/pages/DashboardPage.js +77 -69
- package/dist/atheletebridge/pages/DashboardPage.js.map +1 -1
- package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +4 -4
- package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/performance/PerformancePage.js +496 -0
- package/dist/atheletebridge/pages/performance/PerformancePage.js.map +1 -0
- package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +176 -142
- package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +86 -85
- package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -1
- package/dist/atheletebridge/pages/sessions/SessionFormPage.js +92 -98
- package/dist/atheletebridge/pages/sessions/SessionFormPage.js.map +1 -1
- package/dist/atheletebridge/pages/teams/TeamDetailPage.js +132 -137
- package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -1
- package/dist/atheletebridge/utils/formatters.js +2 -25
- package/dist/atheletebridge/utils/formatters.js.map +1 -1
- package/dist/atheletebridge/utils/url.js +17 -0
- package/dist/atheletebridge/utils/url.js.map +1 -0
- package/dist/index.js +4 -4
- package/package.json +5 -5
|
@@ -3,16 +3,17 @@ import { PageLayout as t } from "../../components/PageLayout.js";
|
|
|
3
3
|
import { StatusBadge as n } from "../../components/StatusBadge.js";
|
|
4
4
|
import { PROGRAM_LEVEL_LABELS as r, SPORT_LABELS as i } from "../../components/domain.js";
|
|
5
5
|
import { EmptyState as a } from "../../components/EmptyState.js";
|
|
6
|
-
import { ErrorState as
|
|
7
|
-
import { useAddDrill as
|
|
8
|
-
import { FormField as
|
|
6
|
+
import { ErrorState as o, LoadingState as ee } from "../../components/LoadingState.js";
|
|
7
|
+
import { useAddDrill as te, useArchiveProgram as ne, useProgram as re, useRemoveDrill as s, useTransitionProgram as c, useUploadFile as l } from "../../hooks/useAthleteBridgeApi.js";
|
|
8
|
+
import { FormField as u, fieldInputClass as d } from "../../components/form.js";
|
|
9
|
+
import { DrillVideoLink as f } from "../../components/DrillVideoLink.js";
|
|
9
10
|
import { useMemo as p, useState as m } from "react";
|
|
10
|
-
import { Archive as h, ArrowLeft as g, Copy as _, Edit as v,
|
|
11
|
-
import { useParams as
|
|
12
|
-
import { Fragment as
|
|
13
|
-
import { EmphasisPanel as
|
|
11
|
+
import { Archive as h, ArrowLeft as g, Copy as _, Edit as v, FileVideo as y, Loader2 as b, Plus as x, Send as ie, Trash2 as ae, Undo2 as oe } from "lucide-react";
|
|
12
|
+
import { useParams as se } from "react-router-dom";
|
|
13
|
+
import { Fragment as ce, jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
14
|
+
import { EmphasisPanel as w, GlassCard as T, ResponsiveDialog as E, ResponsiveDialogContent as D, ResponsiveDialogFooter as O, ResponsiveDialogHeader as k, ResponsiveDialogTitle as A } from "@burdenoff/fe-libs/ui";
|
|
14
15
|
//#region src/atheletebridge/pages/programs/ProgramDetailPage.tsx
|
|
15
|
-
var
|
|
16
|
+
var j = {
|
|
16
17
|
name: "",
|
|
17
18
|
description: "",
|
|
18
19
|
weekNumber: "1",
|
|
@@ -20,15 +21,15 @@ var F = {
|
|
|
20
21
|
reps: "",
|
|
21
22
|
durationSec: "",
|
|
22
23
|
restSec: ""
|
|
23
|
-
},
|
|
24
|
+
}, M = (e) => {
|
|
24
25
|
let t = e.trim();
|
|
25
26
|
if (!t) return;
|
|
26
27
|
let n = Number.parseInt(t, 10);
|
|
27
28
|
return Number.isNaN(n) ? void 0 : n;
|
|
28
29
|
};
|
|
29
|
-
function
|
|
30
|
-
let { id:
|
|
31
|
-
let e =
|
|
30
|
+
function N() {
|
|
31
|
+
let { id: N } = se(), { navigateTo: P } = e(), F = re(N), I = c(), L = ne(), R = te(), z = s(N), B = l(), [V, H] = m(!1), [U, W] = m(j), [G, K] = m(null), [q, J] = m(!1), [Y, X] = m(null), le = p(() => {
|
|
32
|
+
let e = F.data?.drills ?? [], t = /* @__PURE__ */ new Map();
|
|
32
33
|
for (let n of e) {
|
|
33
34
|
let e = t.get(n.weekNumber) ?? [];
|
|
34
35
|
e.push(n), t.set(n.weekNumber, e);
|
|
@@ -37,52 +38,52 @@ function L() {
|
|
|
37
38
|
week: e,
|
|
38
39
|
drills: [...t].sort((e, t) => e.orderIndex - t.orderIndex)
|
|
39
40
|
}));
|
|
40
|
-
}, [
|
|
41
|
-
if (
|
|
41
|
+
}, [F.data]);
|
|
42
|
+
if (F.isLoading) return /* @__PURE__ */ S(t, {
|
|
42
43
|
title: "Program",
|
|
43
|
-
children: /* @__PURE__ */
|
|
44
|
+
children: /* @__PURE__ */ S(ee, { label: "Loading program…" })
|
|
44
45
|
});
|
|
45
|
-
if (
|
|
46
|
+
if (F.isError || !F.data) return /* @__PURE__ */ S(t, {
|
|
46
47
|
title: "Program",
|
|
47
|
-
children: /* @__PURE__ */
|
|
48
|
+
children: /* @__PURE__ */ S(o, {
|
|
48
49
|
title: "Program not found",
|
|
49
50
|
message: "This program does not exist or you do not have access to it.",
|
|
50
|
-
onRetry: () =>
|
|
51
|
+
onRetry: () => P("/programs")
|
|
51
52
|
})
|
|
52
53
|
});
|
|
53
|
-
let Z =
|
|
54
|
-
|
|
55
|
-
id:
|
|
54
|
+
let Z = F.data, Q = Z.drills?.length ?? 0, $ = (e) => {
|
|
55
|
+
N && I.mutate({
|
|
56
|
+
id: N,
|
|
56
57
|
status: e
|
|
57
58
|
});
|
|
58
59
|
};
|
|
59
|
-
return /* @__PURE__ */
|
|
60
|
+
return /* @__PURE__ */ C(t, {
|
|
60
61
|
title: Z.name,
|
|
61
62
|
description: `${i[Z.sport]} · ${r[Z.level]} · ${Z.weeks} ${Z.weeks === 1 ? "week" : "weeks"}`,
|
|
62
|
-
actions: /* @__PURE__ */
|
|
63
|
+
actions: /* @__PURE__ */ C("div", {
|
|
63
64
|
className: "flex flex-wrap items-center gap-2",
|
|
64
65
|
children: [
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ C("button", {
|
|
66
67
|
type: "button",
|
|
67
|
-
onClick: () =>
|
|
68
|
+
onClick: () => P("/programs"),
|
|
68
69
|
className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
|
|
69
|
-
children: [/* @__PURE__ */
|
|
70
|
+
children: [/* @__PURE__ */ S(g, { className: "h-4 w-4" }), " Back"]
|
|
70
71
|
}),
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
+
/* @__PURE__ */ C("button", {
|
|
72
73
|
type: "button",
|
|
73
|
-
onClick: () =>
|
|
74
|
+
onClick: () => P(`/programs/${Z.id}/edit`),
|
|
74
75
|
className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
|
|
75
|
-
children: [/* @__PURE__ */
|
|
76
|
+
children: [/* @__PURE__ */ S(v, { className: "h-4 w-4" }), " Edit"]
|
|
76
77
|
}),
|
|
77
|
-
Z.status !== "ARCHIVED" && /* @__PURE__ */
|
|
78
|
+
Z.status !== "ARCHIVED" && /* @__PURE__ */ C("button", {
|
|
78
79
|
type: "button",
|
|
79
80
|
onClick: async () => {
|
|
80
|
-
|
|
81
|
+
N && (await L.mutateAsync(N), P("/programs"));
|
|
81
82
|
},
|
|
82
|
-
disabled:
|
|
83
|
+
disabled: L.isPending,
|
|
83
84
|
className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-60",
|
|
84
85
|
children: [
|
|
85
|
-
|
|
86
|
+
L.isPending ? /* @__PURE__ */ S(b, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ S(h, { className: "h-4 w-4" }),
|
|
86
87
|
" ",
|
|
87
88
|
"Archive"
|
|
88
89
|
]
|
|
@@ -90,226 +91,238 @@ function L() {
|
|
|
90
91
|
]
|
|
91
92
|
}),
|
|
92
93
|
children: [
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
+
/* @__PURE__ */ C(T, {
|
|
94
95
|
treatment: "insight",
|
|
95
96
|
className: "mb-8 p-6",
|
|
96
97
|
children: [
|
|
97
|
-
/* @__PURE__ */
|
|
98
|
+
/* @__PURE__ */ C("div", {
|
|
98
99
|
className: "flex flex-wrap items-center gap-3",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
100
|
+
children: [/* @__PURE__ */ S(n, { status: Z.status }), Z.isTemplate && /* @__PURE__ */ C("span", {
|
|
100
101
|
className: "inline-flex items-center gap-1 text-sm text-text-secondary",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
102
|
+
children: [/* @__PURE__ */ S(_, { className: "h-3.5 w-3.5" }), " Template"]
|
|
102
103
|
})]
|
|
103
104
|
}),
|
|
104
|
-
Z.summary && /* @__PURE__ */
|
|
105
|
+
Z.summary && /* @__PURE__ */ S("p", {
|
|
105
106
|
className: "mt-4 text-sm text-text-secondary",
|
|
106
107
|
children: Z.summary
|
|
107
108
|
}),
|
|
108
|
-
Z.tags.length > 0 && /* @__PURE__ */
|
|
109
|
+
Z.tags.length > 0 && /* @__PURE__ */ S("div", {
|
|
109
110
|
className: "mt-4 flex flex-wrap gap-1.5",
|
|
110
|
-
children: Z.tags.map((e) => /* @__PURE__ */
|
|
111
|
+
children: Z.tags.map((e) => /* @__PURE__ */ S("span", {
|
|
111
112
|
className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
|
|
112
113
|
children: e
|
|
113
114
|
}, e))
|
|
114
115
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ C("div", {
|
|
116
117
|
className: "mt-5 flex flex-wrap items-center gap-2 border-t border-border-seam pt-5",
|
|
117
118
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
119
|
+
/* @__PURE__ */ S("span", {
|
|
119
120
|
className: "text-sm font-medium text-text-primary",
|
|
120
121
|
children: "Publish lifecycle:"
|
|
121
122
|
}),
|
|
122
|
-
Z.status === "DRAFT" && /* @__PURE__ */
|
|
123
|
+
Z.status === "DRAFT" && /* @__PURE__ */ C("button", {
|
|
123
124
|
type: "button",
|
|
124
125
|
onClick: () => $("PUBLISHED"),
|
|
125
|
-
disabled:
|
|
126
|
+
disabled: I.isPending,
|
|
126
127
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-60",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ S(ie, { className: "h-4 w-4" }), " Publish"]
|
|
128
129
|
}),
|
|
129
|
-
Z.status === "PUBLISHED" && /* @__PURE__ */
|
|
130
|
+
Z.status === "PUBLISHED" && /* @__PURE__ */ C(ce, { children: [/* @__PURE__ */ C("button", {
|
|
130
131
|
type: "button",
|
|
131
132
|
onClick: () => $("DRAFT"),
|
|
132
|
-
disabled:
|
|
133
|
+
disabled: I.isPending,
|
|
133
134
|
className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-60",
|
|
134
|
-
children: [/* @__PURE__ */
|
|
135
|
-
}), /* @__PURE__ */
|
|
135
|
+
children: [/* @__PURE__ */ S(oe, { className: "h-4 w-4" }), " Pull back to draft"]
|
|
136
|
+
}), /* @__PURE__ */ C("button", {
|
|
136
137
|
type: "button",
|
|
137
138
|
onClick: () => $("ARCHIVED"),
|
|
138
|
-
disabled:
|
|
139
|
+
disabled: I.isPending,
|
|
139
140
|
className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-60",
|
|
140
|
-
children: [/* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ S(h, { className: "h-4 w-4" }), " Archive"]
|
|
141
142
|
})] }),
|
|
142
|
-
Z.status === "ARCHIVED" && /* @__PURE__ */
|
|
143
|
+
Z.status === "ARCHIVED" && /* @__PURE__ */ S("span", {
|
|
143
144
|
className: "text-sm text-text-secondary",
|
|
144
145
|
children: "This program is archived."
|
|
145
146
|
}),
|
|
146
|
-
|
|
147
|
+
I.isPending && /* @__PURE__ */ S(b, { className: "h-4 w-4 animate-spin text-text-secondary" })
|
|
147
148
|
]
|
|
148
149
|
})
|
|
149
150
|
]
|
|
150
151
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ C("section", { children: [/* @__PURE__ */ C("div", {
|
|
152
153
|
className: "mb-4 flex items-center justify-between",
|
|
153
|
-
children: [/* @__PURE__ */
|
|
154
|
+
children: [/* @__PURE__ */ C("h2", {
|
|
154
155
|
className: "text-lg font-semibold text-text-primary",
|
|
155
156
|
children: [
|
|
156
157
|
"Drills (",
|
|
157
158
|
Q,
|
|
158
159
|
")"
|
|
159
160
|
]
|
|
160
|
-
}), /* @__PURE__ */
|
|
161
|
+
}), /* @__PURE__ */ C("button", {
|
|
161
162
|
type: "button",
|
|
162
163
|
onClick: () => {
|
|
163
|
-
|
|
164
|
+
X(null), H(!0);
|
|
164
165
|
},
|
|
165
166
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
|
|
166
|
-
children: [/* @__PURE__ */
|
|
167
|
+
children: [/* @__PURE__ */ S(x, { className: "h-4 w-4" }), " Add drill"]
|
|
167
168
|
})]
|
|
168
|
-
}), Q === 0 ? /* @__PURE__ */
|
|
169
|
+
}), Q === 0 ? /* @__PURE__ */ S(a, {
|
|
169
170
|
illustration: "empty-data",
|
|
170
|
-
icon: /* @__PURE__ */
|
|
171
|
+
icon: /* @__PURE__ */ S(x, { className: "h-10 w-10" }),
|
|
171
172
|
title: "No drills yet",
|
|
172
173
|
description: "Add drills with sets, reps and durations, organized by week."
|
|
173
|
-
}) : /* @__PURE__ */
|
|
174
|
+
}) : /* @__PURE__ */ S("div", {
|
|
174
175
|
className: "space-y-6",
|
|
175
|
-
children:
|
|
176
|
+
children: le.map(({ week: e, drills: t }) => /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("h3", {
|
|
176
177
|
className: "mb-3 text-sm font-semibold uppercase tracking-wide text-text-secondary",
|
|
177
178
|
children: ["Week ", e]
|
|
178
|
-
}), /* @__PURE__ */
|
|
179
|
+
}), /* @__PURE__ */ S(w, { children: /* @__PURE__ */ S("div", {
|
|
179
180
|
className: "divide-y divide-border-seam",
|
|
180
|
-
children: t.map((e) => /* @__PURE__ */
|
|
181
|
+
children: t.map((e) => /* @__PURE__ */ C("div", {
|
|
181
182
|
className: "flex items-start gap-4 py-3",
|
|
182
|
-
children: [/* @__PURE__ */
|
|
183
|
+
children: [/* @__PURE__ */ C("div", {
|
|
183
184
|
className: "min-w-0 flex-1",
|
|
184
185
|
children: [
|
|
185
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ S("p", {
|
|
186
187
|
className: "text-sm font-medium text-text-primary",
|
|
187
188
|
children: e.name
|
|
188
189
|
}),
|
|
189
|
-
e.description && /* @__PURE__ */
|
|
190
|
+
e.description && /* @__PURE__ */ S("p", {
|
|
190
191
|
className: "mt-0.5 text-xs text-text-secondary",
|
|
191
192
|
children: e.description
|
|
192
193
|
}),
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ C("div", {
|
|
194
195
|
className: "mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-text-secondary",
|
|
195
196
|
children: [
|
|
196
|
-
e.sets !== null && /* @__PURE__ */
|
|
197
|
-
e.reps !== null && /* @__PURE__ */
|
|
198
|
-
e.durationSec !== null && /* @__PURE__ */
|
|
199
|
-
e.restSec !== null && /* @__PURE__ */
|
|
197
|
+
e.sets !== null && /* @__PURE__ */ C("span", { children: [e.sets, " sets"] }),
|
|
198
|
+
e.reps !== null && /* @__PURE__ */ C("span", { children: [e.reps, " reps"] }),
|
|
199
|
+
e.durationSec !== null && /* @__PURE__ */ C("span", { children: [e.durationSec, "s work"] }),
|
|
200
|
+
e.restSec !== null && /* @__PURE__ */ C("span", { children: [e.restSec, "s rest"] })
|
|
200
201
|
]
|
|
201
|
-
})
|
|
202
|
+
}),
|
|
203
|
+
e.video?.id && /* @__PURE__ */ S("div", { children: /* @__PURE__ */ S(f, { fileId: e.video.id }) })
|
|
202
204
|
]
|
|
203
|
-
}), /* @__PURE__ */
|
|
205
|
+
}), /* @__PURE__ */ S("button", {
|
|
204
206
|
type: "button",
|
|
205
|
-
onClick: () => void
|
|
206
|
-
disabled:
|
|
207
|
+
onClick: () => void z.mutate(e.id),
|
|
208
|
+
disabled: z.isPending,
|
|
207
209
|
"aria-label": `Remove ${e.name}`,
|
|
208
210
|
className: "rounded-lg p-2 text-text-secondary transition-colors hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-60",
|
|
209
|
-
children: /* @__PURE__ */
|
|
211
|
+
children: /* @__PURE__ */ S(ae, { className: "h-4 w-4" })
|
|
210
212
|
})]
|
|
211
213
|
}, e.id))
|
|
212
214
|
}) })] }, e))
|
|
213
215
|
})] }),
|
|
214
|
-
/* @__PURE__ */ E
|
|
215
|
-
open:
|
|
216
|
-
onOpenChange:
|
|
217
|
-
children: /* @__PURE__ */ D
|
|
216
|
+
/* @__PURE__ */ S(E, {
|
|
217
|
+
open: V,
|
|
218
|
+
onOpenChange: H,
|
|
219
|
+
children: /* @__PURE__ */ C(D, { children: [/* @__PURE__ */ S(k, { children: /* @__PURE__ */ S(A, { children: "Add drill" }) }), /* @__PURE__ */ C("form", {
|
|
218
220
|
onSubmit: async (e) => {
|
|
219
|
-
if (e.preventDefault(),
|
|
220
|
-
if (!
|
|
221
|
-
|
|
221
|
+
if (e.preventDefault(), X(null), !N) return;
|
|
222
|
+
if (!U.name.trim()) {
|
|
223
|
+
X("Drill name is required.");
|
|
222
224
|
return;
|
|
223
225
|
}
|
|
224
|
-
let t =
|
|
226
|
+
let t = M(U.weekNumber) ?? 1, n;
|
|
227
|
+
if (G) {
|
|
228
|
+
J(!0);
|
|
229
|
+
try {
|
|
230
|
+
n = await B(G);
|
|
231
|
+
} catch (e) {
|
|
232
|
+
X(e instanceof Error ? e.message : "Failed to upload the demo video."), J(!1);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
J(!1);
|
|
236
|
+
}
|
|
225
237
|
try {
|
|
226
|
-
await
|
|
227
|
-
programId:
|
|
228
|
-
name:
|
|
229
|
-
description:
|
|
238
|
+
await R.mutateAsync({
|
|
239
|
+
programId: N,
|
|
240
|
+
name: U.name.trim(),
|
|
241
|
+
description: U.description.trim() || void 0,
|
|
230
242
|
weekNumber: t,
|
|
231
|
-
orderIndex:
|
|
232
|
-
sets:
|
|
233
|
-
reps:
|
|
234
|
-
durationSec:
|
|
235
|
-
restSec:
|
|
236
|
-
|
|
243
|
+
orderIndex: F.data?.drills?.filter((e) => e.weekNumber === t).length ?? 0,
|
|
244
|
+
sets: M(U.sets),
|
|
245
|
+
reps: M(U.reps),
|
|
246
|
+
durationSec: M(U.durationSec),
|
|
247
|
+
restSec: M(U.restSec),
|
|
248
|
+
videoFileId: n
|
|
249
|
+
}), W(j), K(null), H(!1);
|
|
237
250
|
} catch (e) {
|
|
238
|
-
|
|
251
|
+
X(e instanceof Error ? e.message : "Failed to add drill.");
|
|
239
252
|
}
|
|
240
253
|
},
|
|
241
254
|
className: "space-y-4 px-1",
|
|
242
255
|
children: [
|
|
243
|
-
/* @__PURE__ */
|
|
256
|
+
/* @__PURE__ */ S(u, {
|
|
244
257
|
label: "Name",
|
|
245
258
|
htmlFor: "drillName",
|
|
246
259
|
required: !0,
|
|
247
|
-
children: /* @__PURE__ */
|
|
260
|
+
children: /* @__PURE__ */ S("input", {
|
|
248
261
|
id: "drillName",
|
|
249
|
-
className:
|
|
250
|
-
value:
|
|
251
|
-
onChange: (e) =>
|
|
262
|
+
className: d,
|
|
263
|
+
value: U.name,
|
|
264
|
+
onChange: (e) => W((t) => ({
|
|
252
265
|
...t,
|
|
253
266
|
name: e.target.value
|
|
254
267
|
})),
|
|
255
268
|
placeholder: "e.g. Box jumps"
|
|
256
269
|
})
|
|
257
270
|
}),
|
|
258
|
-
/* @__PURE__ */
|
|
271
|
+
/* @__PURE__ */ S(u, {
|
|
259
272
|
label: "Description",
|
|
260
273
|
htmlFor: "drillDesc",
|
|
261
|
-
children: /* @__PURE__ */
|
|
274
|
+
children: /* @__PURE__ */ S("textarea", {
|
|
262
275
|
id: "drillDesc",
|
|
263
|
-
className:
|
|
276
|
+
className: d,
|
|
264
277
|
rows: 2,
|
|
265
|
-
value:
|
|
266
|
-
onChange: (e) =>
|
|
278
|
+
value: U.description,
|
|
279
|
+
onChange: (e) => W((t) => ({
|
|
267
280
|
...t,
|
|
268
281
|
description: e.target.value
|
|
269
282
|
})),
|
|
270
283
|
placeholder: "How to perform the drill."
|
|
271
284
|
})
|
|
272
285
|
}),
|
|
273
|
-
/* @__PURE__ */
|
|
274
|
-
className: "grid grid-cols-
|
|
286
|
+
/* @__PURE__ */ C("div", {
|
|
287
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
|
|
275
288
|
children: [
|
|
276
|
-
/* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ S(u, {
|
|
277
290
|
label: "Week",
|
|
278
291
|
htmlFor: "drillWeek",
|
|
279
|
-
children: /* @__PURE__ */
|
|
292
|
+
children: /* @__PURE__ */ S("input", {
|
|
280
293
|
id: "drillWeek",
|
|
281
294
|
inputMode: "numeric",
|
|
282
|
-
className:
|
|
283
|
-
value:
|
|
284
|
-
onChange: (e) =>
|
|
295
|
+
className: d,
|
|
296
|
+
value: U.weekNumber,
|
|
297
|
+
onChange: (e) => W((t) => ({
|
|
285
298
|
...t,
|
|
286
299
|
weekNumber: e.target.value
|
|
287
300
|
}))
|
|
288
301
|
})
|
|
289
302
|
}),
|
|
290
|
-
/* @__PURE__ */
|
|
303
|
+
/* @__PURE__ */ S(u, {
|
|
291
304
|
label: "Sets",
|
|
292
305
|
htmlFor: "drillSets",
|
|
293
|
-
children: /* @__PURE__ */
|
|
306
|
+
children: /* @__PURE__ */ S("input", {
|
|
294
307
|
id: "drillSets",
|
|
295
308
|
inputMode: "numeric",
|
|
296
|
-
className:
|
|
297
|
-
value:
|
|
298
|
-
onChange: (e) =>
|
|
309
|
+
className: d,
|
|
310
|
+
value: U.sets,
|
|
311
|
+
onChange: (e) => W((t) => ({
|
|
299
312
|
...t,
|
|
300
313
|
sets: e.target.value
|
|
301
314
|
}))
|
|
302
315
|
})
|
|
303
316
|
}),
|
|
304
|
-
/* @__PURE__ */
|
|
317
|
+
/* @__PURE__ */ S(u, {
|
|
305
318
|
label: "Reps",
|
|
306
319
|
htmlFor: "drillReps",
|
|
307
|
-
children: /* @__PURE__ */
|
|
320
|
+
children: /* @__PURE__ */ S("input", {
|
|
308
321
|
id: "drillReps",
|
|
309
322
|
inputMode: "numeric",
|
|
310
|
-
className:
|
|
311
|
-
value:
|
|
312
|
-
onChange: (e) =>
|
|
323
|
+
className: d,
|
|
324
|
+
value: U.reps,
|
|
325
|
+
onChange: (e) => W((t) => ({
|
|
313
326
|
...t,
|
|
314
327
|
reps: e.target.value
|
|
315
328
|
}))
|
|
@@ -317,50 +330,71 @@ function L() {
|
|
|
317
330
|
})
|
|
318
331
|
]
|
|
319
332
|
}),
|
|
320
|
-
/* @__PURE__ */
|
|
333
|
+
/* @__PURE__ */ C("div", {
|
|
321
334
|
className: "grid grid-cols-2 gap-4",
|
|
322
|
-
children: [/* @__PURE__ */
|
|
335
|
+
children: [/* @__PURE__ */ S(u, {
|
|
323
336
|
label: "Work (sec)",
|
|
324
337
|
htmlFor: "drillDuration",
|
|
325
|
-
children: /* @__PURE__ */
|
|
338
|
+
children: /* @__PURE__ */ S("input", {
|
|
326
339
|
id: "drillDuration",
|
|
327
340
|
inputMode: "numeric",
|
|
328
|
-
className:
|
|
329
|
-
value:
|
|
330
|
-
onChange: (e) =>
|
|
341
|
+
className: d,
|
|
342
|
+
value: U.durationSec,
|
|
343
|
+
onChange: (e) => W((t) => ({
|
|
331
344
|
...t,
|
|
332
345
|
durationSec: e.target.value
|
|
333
346
|
}))
|
|
334
347
|
})
|
|
335
|
-
}), /* @__PURE__ */
|
|
348
|
+
}), /* @__PURE__ */ S(u, {
|
|
336
349
|
label: "Rest (sec)",
|
|
337
350
|
htmlFor: "drillRest",
|
|
338
|
-
children: /* @__PURE__ */
|
|
351
|
+
children: /* @__PURE__ */ S("input", {
|
|
339
352
|
id: "drillRest",
|
|
340
353
|
inputMode: "numeric",
|
|
341
|
-
className:
|
|
342
|
-
value:
|
|
343
|
-
onChange: (e) =>
|
|
354
|
+
className: d,
|
|
355
|
+
value: U.restSec,
|
|
356
|
+
onChange: (e) => W((t) => ({
|
|
344
357
|
...t,
|
|
345
358
|
restSec: e.target.value
|
|
346
359
|
}))
|
|
347
360
|
})
|
|
348
361
|
})]
|
|
349
362
|
}),
|
|
350
|
-
|
|
363
|
+
/* @__PURE__ */ C(u, {
|
|
364
|
+
label: "Demo video",
|
|
365
|
+
htmlFor: "drillVideo",
|
|
366
|
+
hint: "Optional — attach a short demo clip; it's stored in workspace files.",
|
|
367
|
+
children: [/* @__PURE__ */ S("input", {
|
|
368
|
+
id: "drillVideo",
|
|
369
|
+
type: "file",
|
|
370
|
+
accept: "video/*",
|
|
371
|
+
className: d,
|
|
372
|
+
onChange: (e) => K(e.target.files?.[0] ?? null)
|
|
373
|
+
}), G && /* @__PURE__ */ C("p", {
|
|
374
|
+
className: "mt-1 inline-flex items-center gap-1 text-xs text-text-secondary",
|
|
375
|
+
children: [
|
|
376
|
+
/* @__PURE__ */ S(y, { className: "h-3.5 w-3.5" }),
|
|
377
|
+
" ",
|
|
378
|
+
G.name
|
|
379
|
+
]
|
|
380
|
+
})]
|
|
381
|
+
}),
|
|
382
|
+
Y && /* @__PURE__ */ S("p", {
|
|
351
383
|
className: "text-sm text-status-error-text",
|
|
352
|
-
children:
|
|
384
|
+
children: Y
|
|
353
385
|
}),
|
|
354
|
-
/* @__PURE__ */
|
|
386
|
+
/* @__PURE__ */ C(O, { children: [/* @__PURE__ */ S("button", {
|
|
355
387
|
type: "button",
|
|
356
|
-
onClick: () =>
|
|
388
|
+
onClick: () => {
|
|
389
|
+
H(!1), K(null);
|
|
390
|
+
},
|
|
357
391
|
className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
|
|
358
392
|
children: "Cancel"
|
|
359
|
-
}), /* @__PURE__ */
|
|
393
|
+
}), /* @__PURE__ */ C("button", {
|
|
360
394
|
type: "submit",
|
|
361
|
-
disabled:
|
|
395
|
+
disabled: R.isPending || q,
|
|
362
396
|
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",
|
|
363
|
-
children: [
|
|
397
|
+
children: [(R.isPending || q) && /* @__PURE__ */ S(b, { className: "h-4 w-4 animate-spin" }), q ? "Uploading video…" : "Add drill"]
|
|
364
398
|
})] })
|
|
365
399
|
]
|
|
366
400
|
})] })
|
|
@@ -369,6 +403,6 @@ function L() {
|
|
|
369
403
|
});
|
|
370
404
|
}
|
|
371
405
|
//#endregion
|
|
372
|
-
export {
|
|
406
|
+
export { N as ProgramDetailPage };
|
|
373
407
|
|
|
374
408
|
//# sourceMappingURL=ProgramDetailPage.js.map
|