@burdenoff/microfe-mybodyshield 2026.720.1 → 2026.720.3
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/mybodyshield/data/programTemplates.d.ts +23 -0
- package/dist/mybodyshield/data/programTemplates.d.ts.map +1 -0
- package/dist/mybodyshield/data/programTemplates.js +212 -0
- package/dist/mybodyshield/data/programTemplates.js.map +1 -0
- package/dist/mybodyshield/hooks/useMyBodyShieldApi.d.ts +15 -1
- package/dist/mybodyshield/hooks/useMyBodyShieldApi.d.ts.map +1 -1
- package/dist/mybodyshield/hooks/useMyBodyShieldApi.js +77 -32
- package/dist/mybodyshield/hooks/useMyBodyShieldApi.js.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramsPage.js +169 -121
- package/dist/mybodyshield/pages/programs/ProgramsPage.js.map +1 -1
- package/dist/mybodyshield/pages/train/SessionDetailPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/train/SessionDetailPage.js +438 -266
- package/dist/mybodyshield/pages/train/SessionDetailPage.js.map +1 -1
- package/dist/mybodyshield/pages/train/SessionsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/train/SessionsPage.js +162 -123
- package/dist/mybodyshield/pages/train/SessionsPage.js.map +1 -1
- package/dist/mybodyshield/types/assistant.d.ts.map +1 -1
- package/dist/mybodyshield/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -7,20 +7,20 @@ import { ErrorView as i, LoadingView as a } from "../../components/StateViews.js
|
|
|
7
7
|
import { FilterTabs as o } from "../../components/FilterTabs.js";
|
|
8
8
|
import { Pagination as s } from "../../components/Pagination.js";
|
|
9
9
|
import "../../context/index.js";
|
|
10
|
-
import {
|
|
11
|
-
import { useOffsetPager as
|
|
12
|
-
import { useMyBodyShieldAnalytics as
|
|
10
|
+
import { useMybProgramWorkouts as c, useMybPrograms as l, useMybSessions as u, useMybStartSession as re } from "../../hooks/useMyBodyShieldApi.js";
|
|
11
|
+
import { useOffsetPager as d } from "../../hooks/usePager.js";
|
|
12
|
+
import { useMyBodyShieldAnalytics as f } from "../../hooks/useMyBodyShieldAnalytics.js";
|
|
13
13
|
import "../../hooks/index.js";
|
|
14
14
|
import "../../components/index.js";
|
|
15
|
-
import { motion as
|
|
16
|
-
import { useReducedMotion as
|
|
17
|
-
import { IconChip as
|
|
18
|
-
import { useState as
|
|
19
|
-
import { CalendarClock as
|
|
20
|
-
import { Fragment as
|
|
21
|
-
import { Button as
|
|
15
|
+
import { motion as p } from "../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js";
|
|
16
|
+
import { useReducedMotion as m } from "../../../node_modules/framer-motion/dist/es/utils/reduced-motion/use-reduced-motion.js";
|
|
17
|
+
import { IconChip as h, Meter as ie } from "../_shared/visuals.js";
|
|
18
|
+
import { useState as g } from "react";
|
|
19
|
+
import { CalendarClock as _, CheckCircle2 as v, Flame as y, Gauge as ae, ListChecks as oe, PlayCircle as b, Plus as x, SkipForward as S } from "lucide-react";
|
|
20
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
21
|
+
import { Button as E, GlassCard as D, Input as se, Label as O, ResponsiveDialog as ce, ResponsiveDialogContent as le, ResponsiveDialogDescription as ue, ResponsiveDialogFooter as de, ResponsiveDialogHeader as fe, ResponsiveDialogTitle as pe, Select as k, SelectContent as A, SelectItem as j, SelectTrigger as M, SelectValue as N, Textarea as P } from "@burdenoff/fe-libs/ui";
|
|
22
22
|
//#region src/mybodyshield/pages/train/SessionsPage.tsx
|
|
23
|
-
var
|
|
23
|
+
var F = [
|
|
24
24
|
{
|
|
25
25
|
value: "ALL",
|
|
26
26
|
label: "All"
|
|
@@ -37,41 +37,42 @@ var L = [
|
|
|
37
37
|
value: "COMPLETED",
|
|
38
38
|
label: "Completed"
|
|
39
39
|
}
|
|
40
|
-
],
|
|
40
|
+
], I = 24, L = [
|
|
41
41
|
.16,
|
|
42
42
|
1,
|
|
43
43
|
.3,
|
|
44
44
|
1
|
|
45
|
-
],
|
|
46
|
-
programId:
|
|
45
|
+
], R = "__none__", z = "__none__", B = {
|
|
46
|
+
programId: R,
|
|
47
|
+
workoutId: z,
|
|
47
48
|
scheduledFor: "",
|
|
48
49
|
notes: ""
|
|
49
50
|
};
|
|
50
|
-
function
|
|
51
|
+
function me(e) {
|
|
51
52
|
switch (e.status) {
|
|
52
53
|
case "IN_PROGRESS": return {
|
|
53
|
-
icon:
|
|
54
|
+
icon: b,
|
|
54
55
|
tint: "var(--color-accent-teal)",
|
|
55
56
|
title: "Live workout in progress",
|
|
56
57
|
stampLabel: "Started",
|
|
57
58
|
stamp: e.startedAt ?? e.createdAt
|
|
58
59
|
};
|
|
59
60
|
case "COMPLETED": return {
|
|
60
|
-
icon:
|
|
61
|
+
icon: v,
|
|
61
62
|
tint: "var(--color-status-success-text)",
|
|
62
63
|
title: e.caloriesBurned > 0 ? `${n(e.caloriesBurned)} burned` : "Workout completed",
|
|
63
64
|
stampLabel: "Completed",
|
|
64
65
|
stamp: e.completedAt ?? e.startedAt ?? e.createdAt
|
|
65
66
|
};
|
|
66
67
|
case "SKIPPED": return {
|
|
67
|
-
icon:
|
|
68
|
+
icon: S,
|
|
68
69
|
tint: "var(--color-text-secondary)",
|
|
69
70
|
title: "Skipped session",
|
|
70
71
|
stampLabel: "Scheduled",
|
|
71
72
|
stamp: e.scheduledFor ?? e.createdAt
|
|
72
73
|
};
|
|
73
74
|
default: return {
|
|
74
|
-
icon:
|
|
75
|
+
icon: _,
|
|
75
76
|
tint: "var(--color-accent-primary)",
|
|
76
77
|
title: "Scheduled session",
|
|
77
78
|
stampLabel: "Scheduled",
|
|
@@ -79,58 +80,58 @@ function H(e) {
|
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
let { navigateTo:
|
|
84
|
-
status:
|
|
83
|
+
function V() {
|
|
84
|
+
let { navigateTo: _, workspaceId: v } = e(), b = m(), S = f(), [V, he] = g("ALL"), H = d(I), U = u({
|
|
85
|
+
status: V === "ALL" ? void 0 : V,
|
|
85
86
|
pagination: {
|
|
86
|
-
limit:
|
|
87
|
-
offset:
|
|
87
|
+
limit: I,
|
|
88
|
+
offset: H.offset
|
|
88
89
|
}
|
|
89
|
-
}),
|
|
90
|
+
}), ge = l({
|
|
90
91
|
status: "ACTIVE",
|
|
91
92
|
pagination: { limit: 50 }
|
|
92
|
-
}).data?.items ?? [],
|
|
93
|
-
|
|
93
|
+
}).data?.items ?? [], W = re(), [_e, G] = g(!1), [K, q] = g(B), [J, Y] = g(null), X = K.programId === R ? void 0 : K.programId, Z = c(X).data ?? [], Q = U.data?.items ?? [], ve = U.data?.pageInfo?.hasMore ?? !1, ye = (e) => {
|
|
94
|
+
he(e), H.reset();
|
|
94
95
|
}, $ = () => {
|
|
95
|
-
|
|
96
|
+
q(B), Y(null), G(!0), S.emitIntent("session", "create", { workspaceId: v });
|
|
96
97
|
};
|
|
97
|
-
return /* @__PURE__ */
|
|
98
|
+
return /* @__PURE__ */ T(t, {
|
|
98
99
|
title: "Train",
|
|
99
100
|
description: "Live workout sessions — start, log sets, and complete.",
|
|
100
|
-
actions: /* @__PURE__ */
|
|
101
|
+
actions: /* @__PURE__ */ T(E, {
|
|
101
102
|
onClick: $,
|
|
102
|
-
children: [/* @__PURE__ */ x
|
|
103
|
+
children: [/* @__PURE__ */ w(x, { className: "h-4 w-4" }), " Start session"]
|
|
103
104
|
}),
|
|
104
105
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ w("div", {
|
|
106
107
|
className: "mb-6",
|
|
107
|
-
children: /* @__PURE__ */
|
|
108
|
-
options:
|
|
109
|
-
value:
|
|
110
|
-
onChange:
|
|
108
|
+
children: /* @__PURE__ */ w(o, {
|
|
109
|
+
options: F,
|
|
110
|
+
value: V,
|
|
111
|
+
onChange: ye
|
|
111
112
|
})
|
|
112
113
|
}),
|
|
113
|
-
|
|
114
|
+
U.isLoading ? /* @__PURE__ */ w(a, { label: "Loading your sessions…" }) : U.isError ? /* @__PURE__ */ w(i, {
|
|
114
115
|
message: "We couldn't load your workout sessions.",
|
|
115
|
-
onRetry: () =>
|
|
116
|
-
}) : Q.length === 0 ? /* @__PURE__ */
|
|
116
|
+
onRetry: () => U.refetch()
|
|
117
|
+
}) : Q.length === 0 ? /* @__PURE__ */ w(r, {
|
|
117
118
|
illustration: "empty-data",
|
|
118
|
-
icon: /* @__PURE__ */
|
|
119
|
-
title:
|
|
120
|
-
description:
|
|
121
|
-
action: /* @__PURE__ */
|
|
119
|
+
icon: /* @__PURE__ */ w(y, { className: "h-10 w-10" }),
|
|
120
|
+
title: V === "ALL" ? "No sessions yet" : "No sessions in this state",
|
|
121
|
+
description: V === "ALL" ? "Start a workout session to begin logging sets and tracking your training." : "Try a different filter, or start a new workout session.",
|
|
122
|
+
action: /* @__PURE__ */ T(E, {
|
|
122
123
|
onClick: $,
|
|
123
|
-
children: [/* @__PURE__ */ x
|
|
124
|
+
children: [/* @__PURE__ */ w(x, { className: "h-4 w-4" }), " Start session"]
|
|
124
125
|
})
|
|
125
|
-
}) : /* @__PURE__ */
|
|
126
|
+
}) : /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("div", {
|
|
126
127
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
127
128
|
children: Q.map((e, t) => {
|
|
128
|
-
let r =
|
|
129
|
-
return /* @__PURE__ */
|
|
129
|
+
let r = me(e), i = r.icon, a = e.status === "IN_PROGRESS", o = e.sets?.length, s = e.perceivedExertion;
|
|
130
|
+
return /* @__PURE__ */ w(p.button, {
|
|
130
131
|
type: "button",
|
|
131
|
-
onClick: () =>
|
|
132
|
+
onClick: () => _(`train/${e.id}`),
|
|
132
133
|
className: "block w-full text-left",
|
|
133
|
-
initial:
|
|
134
|
+
initial: b ? !1 : {
|
|
134
135
|
opacity: 0,
|
|
135
136
|
y: 12
|
|
136
137
|
},
|
|
@@ -138,30 +139,30 @@ function U() {
|
|
|
138
139
|
opacity: 1,
|
|
139
140
|
y: 0
|
|
140
141
|
},
|
|
141
|
-
transition:
|
|
142
|
+
transition: b ? { duration: 0 } : {
|
|
142
143
|
duration: .35,
|
|
143
144
|
delay: Math.min(t, 8) * .05,
|
|
144
|
-
ease:
|
|
145
|
+
ease: L
|
|
145
146
|
},
|
|
146
|
-
whileHover:
|
|
147
|
-
whileTap:
|
|
148
|
-
children: /* @__PURE__ */
|
|
147
|
+
whileHover: b ? void 0 : { y: -3 },
|
|
148
|
+
whileTap: b ? void 0 : { scale: .995 },
|
|
149
|
+
children: /* @__PURE__ */ T(D, {
|
|
149
150
|
treatment: "plain",
|
|
150
151
|
glow: a,
|
|
151
152
|
className: "h-full p-4 transition-shadow hover:shadow-float" + (a ? " ring-1 ring-inset ring-[color-mix(in_oklab,var(--color-action-primary-bg)_45%,transparent)]" : ""),
|
|
152
153
|
children: [
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ T("div", {
|
|
154
155
|
className: "flex items-center justify-between gap-2",
|
|
155
|
-
children: [/* @__PURE__ */
|
|
156
|
-
icon: /* @__PURE__ */
|
|
156
|
+
children: [/* @__PURE__ */ w(h, {
|
|
157
|
+
icon: /* @__PURE__ */ w(i, { className: "h-4 w-4" }),
|
|
157
158
|
tint: r.tint
|
|
158
|
-
}), /* @__PURE__ */
|
|
159
|
+
}), /* @__PURE__ */ w(ne, { status: e.status })]
|
|
159
160
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
161
|
+
/* @__PURE__ */ w("p", {
|
|
161
162
|
className: "mt-3 text-base font-semibold text-text-primary",
|
|
162
163
|
children: r.title
|
|
163
164
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ T("p", {
|
|
165
166
|
className: "mt-0.5 text-xs text-text-tertiary",
|
|
166
167
|
children: [
|
|
167
168
|
r.stampLabel,
|
|
@@ -169,46 +170,46 @@ function U() {
|
|
|
169
170
|
te(r.stamp)
|
|
170
171
|
]
|
|
171
172
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
173
|
+
/* @__PURE__ */ T("div", {
|
|
173
174
|
className: "mt-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary",
|
|
174
175
|
children: [
|
|
175
|
-
e.caloriesBurned > 0 && /* @__PURE__ */
|
|
176
|
+
e.caloriesBurned > 0 && /* @__PURE__ */ T("span", {
|
|
176
177
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
177
|
-
children: [/* @__PURE__ */
|
|
178
|
+
children: [/* @__PURE__ */ w(y, { className: "h-3.5 w-3.5 text-status-warning-text" }), n(e.caloriesBurned)]
|
|
178
179
|
}),
|
|
179
|
-
s != null && /* @__PURE__ */
|
|
180
|
+
s != null && /* @__PURE__ */ T("span", {
|
|
180
181
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
181
182
|
children: [
|
|
182
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ w(ae, { className: "h-3.5 w-3.5 text-accent" }),
|
|
183
184
|
"RPE ",
|
|
184
185
|
s,
|
|
185
186
|
"/10"
|
|
186
187
|
]
|
|
187
188
|
}),
|
|
188
|
-
o != null && o > 0 && /* @__PURE__ */
|
|
189
|
+
o != null && o > 0 && /* @__PURE__ */ T("span", {
|
|
189
190
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
190
191
|
children: [
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ w(oe, { className: "h-3.5 w-3.5 text-accent" }),
|
|
192
193
|
ee(o),
|
|
193
194
|
" sets"
|
|
194
195
|
]
|
|
195
196
|
})
|
|
196
197
|
]
|
|
197
198
|
}),
|
|
198
|
-
s != null && /* @__PURE__ */
|
|
199
|
+
s != null && /* @__PURE__ */ T("div", {
|
|
199
200
|
className: "mt-3",
|
|
200
|
-
children: [/* @__PURE__ */
|
|
201
|
+
children: [/* @__PURE__ */ T("div", {
|
|
201
202
|
className: "mb-1 flex items-center justify-between text-[11px] text-text-tertiary",
|
|
202
|
-
children: [/* @__PURE__ */
|
|
203
|
+
children: [/* @__PURE__ */ w("span", { children: "RPE intensity" }), /* @__PURE__ */ T("span", {
|
|
203
204
|
className: "tabular-nums",
|
|
204
205
|
children: [s, "/10"]
|
|
205
206
|
})]
|
|
206
|
-
}), /* @__PURE__ */
|
|
207
|
+
}), /* @__PURE__ */ w(ie, {
|
|
207
208
|
value: s * 10,
|
|
208
209
|
height: 6
|
|
209
210
|
})]
|
|
210
211
|
}),
|
|
211
|
-
a && /* @__PURE__ */
|
|
212
|
+
a && /* @__PURE__ */ w("p", {
|
|
212
213
|
className: "mt-3 inline-flex items-center gap-1 text-xs font-semibold text-action-primary-bg",
|
|
213
214
|
children: "In progress — Resume →"
|
|
214
215
|
})
|
|
@@ -216,112 +217,150 @@ function U() {
|
|
|
216
217
|
})
|
|
217
218
|
}, e.id);
|
|
218
219
|
})
|
|
219
|
-
}), /* @__PURE__ */
|
|
220
|
-
page:
|
|
221
|
-
pageSize:
|
|
220
|
+
}), /* @__PURE__ */ w(s, {
|
|
221
|
+
page: H.page,
|
|
222
|
+
pageSize: I,
|
|
222
223
|
itemCount: Q.length,
|
|
223
|
-
hasMore:
|
|
224
|
-
onPageChange: (e) =>
|
|
224
|
+
hasMore: ve,
|
|
225
|
+
onPageChange: (e) => H.onPageChange(e)
|
|
225
226
|
})] }),
|
|
226
|
-
/* @__PURE__ */
|
|
227
|
-
open:
|
|
228
|
-
onOpenChange:
|
|
229
|
-
children: /* @__PURE__ */
|
|
230
|
-
/* @__PURE__ */
|
|
231
|
-
/* @__PURE__ */
|
|
227
|
+
/* @__PURE__ */ w(ce, {
|
|
228
|
+
open: _e,
|
|
229
|
+
onOpenChange: G,
|
|
230
|
+
children: /* @__PURE__ */ T(le, { children: [
|
|
231
|
+
/* @__PURE__ */ T(fe, { children: [/* @__PURE__ */ w(pe, { children: "Start a workout session" }), /* @__PURE__ */ w(ue, { children: "Begin a live session now, or schedule one for later. Attach an active program to keep your training organised." })] }),
|
|
232
|
+
/* @__PURE__ */ T("div", {
|
|
232
233
|
className: "space-y-4 px-1",
|
|
233
234
|
children: [
|
|
234
|
-
/* @__PURE__ */
|
|
235
|
+
/* @__PURE__ */ T("div", {
|
|
235
236
|
className: "space-y-1.5",
|
|
236
|
-
children: [/* @__PURE__ */
|
|
237
|
+
children: [/* @__PURE__ */ w(O, {
|
|
237
238
|
htmlFor: "myb-start-program",
|
|
238
239
|
children: "Program (optional)"
|
|
239
|
-
}), /* @__PURE__ */
|
|
240
|
-
value:
|
|
241
|
-
onValueChange: (e) =>
|
|
240
|
+
}), /* @__PURE__ */ T(k, {
|
|
241
|
+
value: K.programId,
|
|
242
|
+
onValueChange: (e) => q((t) => ({
|
|
242
243
|
...t,
|
|
243
|
-
programId: e
|
|
244
|
+
programId: e,
|
|
245
|
+
workoutId: z
|
|
244
246
|
})),
|
|
245
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ w(M, {
|
|
246
248
|
id: "myb-start-program",
|
|
247
|
-
children: /* @__PURE__ */
|
|
248
|
-
}), /* @__PURE__ */
|
|
249
|
-
value:
|
|
249
|
+
children: /* @__PURE__ */ w(N, { placeholder: "No program" })
|
|
250
|
+
}), /* @__PURE__ */ T(A, { children: [/* @__PURE__ */ w(j, {
|
|
251
|
+
value: R,
|
|
250
252
|
children: "No program"
|
|
251
|
-
}),
|
|
253
|
+
}), ge.map((e) => /* @__PURE__ */ w(j, {
|
|
252
254
|
value: e.id,
|
|
253
255
|
children: e.name
|
|
254
256
|
}, e.id))] })]
|
|
255
257
|
})]
|
|
256
258
|
}),
|
|
257
|
-
/* @__PURE__ */
|
|
259
|
+
X && Z.length > 0 && /* @__PURE__ */ T("div", {
|
|
260
|
+
className: "space-y-1.5",
|
|
261
|
+
children: [
|
|
262
|
+
/* @__PURE__ */ w(O, {
|
|
263
|
+
htmlFor: "myb-start-workout",
|
|
264
|
+
children: "Workout (optional)"
|
|
265
|
+
}),
|
|
266
|
+
/* @__PURE__ */ T(k, {
|
|
267
|
+
value: K.workoutId,
|
|
268
|
+
onValueChange: (e) => q((t) => ({
|
|
269
|
+
...t,
|
|
270
|
+
workoutId: e
|
|
271
|
+
})),
|
|
272
|
+
children: [/* @__PURE__ */ w(M, {
|
|
273
|
+
id: "myb-start-workout",
|
|
274
|
+
children: /* @__PURE__ */ w(N, { placeholder: "No specific workout" })
|
|
275
|
+
}), /* @__PURE__ */ T(A, { children: [/* @__PURE__ */ w(j, {
|
|
276
|
+
value: z,
|
|
277
|
+
children: "No specific workout"
|
|
278
|
+
}), Z.map((e) => /* @__PURE__ */ T(j, {
|
|
279
|
+
value: e.id,
|
|
280
|
+
children: [
|
|
281
|
+
e.name,
|
|
282
|
+
" — Week ",
|
|
283
|
+
e.weekNumber,
|
|
284
|
+
", Day ",
|
|
285
|
+
e.dayOfWeek
|
|
286
|
+
]
|
|
287
|
+
}, e.id))] })]
|
|
288
|
+
}),
|
|
289
|
+
/* @__PURE__ */ w("p", {
|
|
290
|
+
className: "text-xs text-text-tertiary",
|
|
291
|
+
children: "Attach a planned workout to guide this session exercise-by-exercise."
|
|
292
|
+
})
|
|
293
|
+
]
|
|
294
|
+
}),
|
|
295
|
+
/* @__PURE__ */ T("div", {
|
|
258
296
|
className: "space-y-1.5",
|
|
259
297
|
children: [
|
|
260
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ w(O, {
|
|
261
299
|
htmlFor: "myb-start-scheduled",
|
|
262
300
|
children: "Scheduled for (optional)"
|
|
263
301
|
}),
|
|
264
|
-
/* @__PURE__ */
|
|
302
|
+
/* @__PURE__ */ w(se, {
|
|
265
303
|
id: "myb-start-scheduled",
|
|
266
304
|
type: "datetime-local",
|
|
267
|
-
value:
|
|
268
|
-
onChange: (e) =>
|
|
305
|
+
value: K.scheduledFor,
|
|
306
|
+
onChange: (e) => q((t) => ({
|
|
269
307
|
...t,
|
|
270
308
|
scheduledFor: e.target.value
|
|
271
309
|
}))
|
|
272
310
|
}),
|
|
273
|
-
/* @__PURE__ */
|
|
311
|
+
/* @__PURE__ */ w("p", {
|
|
274
312
|
className: "text-xs text-text-tertiary",
|
|
275
313
|
children: "Leave empty to start a live session right now."
|
|
276
314
|
})
|
|
277
315
|
]
|
|
278
316
|
}),
|
|
279
|
-
/* @__PURE__ */
|
|
317
|
+
/* @__PURE__ */ T("div", {
|
|
280
318
|
className: "space-y-1.5",
|
|
281
|
-
children: [/* @__PURE__ */
|
|
319
|
+
children: [/* @__PURE__ */ w(O, {
|
|
282
320
|
htmlFor: "myb-start-notes",
|
|
283
321
|
children: "Notes (optional)"
|
|
284
|
-
}), /* @__PURE__ */
|
|
322
|
+
}), /* @__PURE__ */ w(P, {
|
|
285
323
|
id: "myb-start-notes",
|
|
286
324
|
rows: 3,
|
|
287
|
-
value:
|
|
288
|
-
onChange: (e) =>
|
|
325
|
+
value: K.notes,
|
|
326
|
+
onChange: (e) => q((t) => ({
|
|
289
327
|
...t,
|
|
290
328
|
notes: e.target.value
|
|
291
329
|
})),
|
|
292
330
|
placeholder: "Focus, target lifts, how you're feeling…"
|
|
293
331
|
})]
|
|
294
332
|
}),
|
|
295
|
-
|
|
333
|
+
J && /* @__PURE__ */ w("p", {
|
|
296
334
|
className: "text-sm text-status-error-text",
|
|
297
|
-
children:
|
|
335
|
+
children: J
|
|
298
336
|
})
|
|
299
337
|
]
|
|
300
338
|
}),
|
|
301
|
-
/* @__PURE__ */
|
|
339
|
+
/* @__PURE__ */ T(de, { children: [/* @__PURE__ */ w(E, {
|
|
302
340
|
variant: "outline",
|
|
303
|
-
onClick: () =>
|
|
304
|
-
disabled:
|
|
341
|
+
onClick: () => G(!1),
|
|
342
|
+
disabled: W.isPending,
|
|
305
343
|
children: "Cancel"
|
|
306
|
-
}), /* @__PURE__ */
|
|
344
|
+
}), /* @__PURE__ */ w(E, {
|
|
307
345
|
onClick: async () => {
|
|
308
|
-
|
|
346
|
+
Y(null);
|
|
309
347
|
try {
|
|
310
|
-
let e = await
|
|
311
|
-
programId:
|
|
312
|
-
|
|
313
|
-
|
|
348
|
+
let e = await W.mutateAsync({
|
|
349
|
+
programId: X,
|
|
350
|
+
workoutId: K.workoutId === z ? void 0 : K.workoutId,
|
|
351
|
+
scheduledFor: K.scheduledFor ? new Date(K.scheduledFor).toISOString() : void 0,
|
|
352
|
+
notes: K.notes.trim() ? K.notes.trim() : void 0
|
|
314
353
|
});
|
|
315
|
-
|
|
316
|
-
workspaceId:
|
|
354
|
+
S.emitFact("session", "started", {
|
|
355
|
+
workspaceId: v,
|
|
317
356
|
entityId: e.id
|
|
318
|
-
}),
|
|
357
|
+
}), G(!1), _(`train/${e.id}`);
|
|
319
358
|
} catch (e) {
|
|
320
|
-
|
|
359
|
+
Y(e instanceof Error ? e.message : "Failed to start the session.");
|
|
321
360
|
}
|
|
322
361
|
},
|
|
323
|
-
disabled:
|
|
324
|
-
children:
|
|
362
|
+
disabled: W.isPending,
|
|
363
|
+
children: W.isPending ? "Starting…" : "Start session"
|
|
325
364
|
})] })
|
|
326
365
|
] })
|
|
327
366
|
})
|
|
@@ -329,6 +368,6 @@ function U() {
|
|
|
329
368
|
});
|
|
330
369
|
}
|
|
331
370
|
//#endregion
|
|
332
|
-
export {
|
|
371
|
+
export { V as SessionsPage };
|
|
333
372
|
|
|
334
373
|
//# sourceMappingURL=SessionsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionsPage.js","names":[],"sources":["../../../../src/mybodyshield/pages/train/SessionsPage.tsx"],"sourcesContent":["/**\n * Train — live workout sessions.\n * @module mybodyshield/pages/train\n *\n * Lists the member's workout sessions (real `mybListSessions`) filtered by\n * status, and lets you start a new live session (optionally attached to an\n * active program). In-progress sessions are highlighted with an accent ring and\n * a \"Resume\" affordance. No mock data — everything comes from the myb* hooks.\n */\n\nimport { useState } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport {\n Plus,\n Flame,\n CheckCircle2,\n CalendarClock,\n PlayCircle,\n SkipForward,\n Gauge,\n ListChecks,\n} from 'lucide-react';\nimport {\n Button,\n GlassCard,\n Label,\n Textarea,\n Input,\n Select,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n FilterTabs,\n Pagination,\n LoadingView,\n ErrorView,\n EmptyState,\n type FilterOption,\n} from '../../components';\nimport { IconChip, Meter } from '../_shared/visuals';\nimport { useMyBodyShield } from '../../context';\nimport {\n useMybSessions,\n useMybStartSession,\n useMybPrograms,\n useOffsetPager,\n useMyBodyShieldAnalytics,\n} from '../../hooks';\nimport { formatRelativeTime, formatKcal, formatNumber } from '../../utils/formatters';\nimport type { MybSessionStatus, MybWorkoutSession } from '../../types';\n\ntype SessionFilterValue = MybSessionStatus | 'ALL';\n\n// Only statuses a control can actually reach are offered as filters: start →\n// IN_PROGRESS / SCHEDULED, complete → COMPLETED. Nothing moves a session to\n// SKIPPED, so that tab would always be empty. sessionMeta still handles the\n// SKIPPED case for display safety.\nconst STATUS_TABS: FilterOption<SessionFilterValue>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'IN_PROGRESS', label: 'Live' },\n { value: 'COMPLETED', label: 'Completed' },\n];\n\nconst PAGE_SIZE = 24;\n\n/** Shared entrance easing — a soft, decelerating cubic-bezier. */\nconst MOTION_EASE: [number, number, number, number] = [0.16, 1, 0.3, 1];\n\n/** Sentinel for the optional program picker (Radix Select forbids an empty value). */\nconst NO_PROGRAM = '__none__';\n\ninterface StartForm {\n programId: string;\n scheduledFor: string;\n notes: string;\n}\n\nconst EMPTY_START_FORM: StartForm = { programId: NO_PROGRAM, scheduledFor: '', notes: '' };\n\ninterface SessionMeta {\n icon: typeof Flame;\n tint: string;\n title: string;\n stampLabel: string;\n stamp?: string | null;\n}\n\nfunction sessionMeta(s: MybWorkoutSession): SessionMeta {\n switch (s.status) {\n case 'IN_PROGRESS':\n return {\n icon: PlayCircle,\n tint: 'var(--color-accent-teal)',\n title: 'Live workout in progress',\n stampLabel: 'Started',\n stamp: s.startedAt ?? s.createdAt,\n };\n case 'COMPLETED':\n return {\n icon: CheckCircle2,\n tint: 'var(--color-status-success-text)',\n title:\n s.caloriesBurned > 0 ? `${formatKcal(s.caloriesBurned)} burned` : 'Workout completed',\n stampLabel: 'Completed',\n stamp: s.completedAt ?? s.startedAt ?? s.createdAt,\n };\n case 'SKIPPED':\n return {\n icon: SkipForward,\n tint: 'var(--color-text-secondary)',\n title: 'Skipped session',\n stampLabel: 'Scheduled',\n stamp: s.scheduledFor ?? s.createdAt,\n };\n case 'SCHEDULED':\n default:\n return {\n icon: CalendarClock,\n tint: 'var(--color-accent-primary)',\n title: 'Scheduled session',\n stampLabel: 'Scheduled',\n stamp: s.scheduledFor ?? s.createdAt,\n };\n }\n}\n\nexport function SessionsPage() {\n const { navigateTo, workspaceId } = useMyBodyShield();\n const reduce = useReducedMotion();\n const analytics = useMyBodyShieldAnalytics();\n\n const [filter, setFilter] = useState<SessionFilterValue>('ALL');\n const pager = useOffsetPager(PAGE_SIZE);\n\n const sessions = useMybSessions({\n status: filter === 'ALL' ? undefined : filter,\n pagination: { limit: PAGE_SIZE, offset: pager.offset },\n });\n\n const programs = useMybPrograms({ status: 'ACTIVE', pagination: { limit: 50 } });\n const activePrograms = programs.data?.items ?? [];\n\n const startSession = useMybStartSession();\n\n const [startOpen, setStartOpen] = useState(false);\n const [form, setForm] = useState<StartForm>(EMPTY_START_FORM);\n const [formError, setFormError] = useState<string | null>(null);\n\n const rows = sessions.data?.items ?? [];\n const hasMore = sessions.data?.pageInfo?.hasMore ?? false;\n\n const onFilterChange = (value: SessionFilterValue) => {\n setFilter(value);\n pager.reset();\n };\n\n const openStart = () => {\n setForm(EMPTY_START_FORM);\n setFormError(null);\n setStartOpen(true);\n analytics.emitIntent('session', 'create', { workspaceId });\n };\n\n const submitStart = async () => {\n setFormError(null);\n try {\n const created = await startSession.mutateAsync({\n programId: form.programId === NO_PROGRAM ? undefined : form.programId,\n scheduledFor: form.scheduledFor ? new Date(form.scheduledFor).toISOString() : undefined,\n notes: form.notes.trim() ? form.notes.trim() : undefined,\n });\n analytics.emitFact('session', 'started', { workspaceId, entityId: created.id });\n setStartOpen(false);\n navigateTo(`train/${created.id}`);\n } catch (e) {\n setFormError(e instanceof Error ? e.message : 'Failed to start the session.');\n }\n };\n\n return (\n <PageLayout\n title=\"Train\"\n description=\"Live workout sessions — start, log sets, and complete.\"\n actions={\n <Button onClick={openStart}>\n <Plus className=\"h-4 w-4\" /> Start session\n </Button>\n }\n >\n <div className=\"mb-6\">\n <FilterTabs options={STATUS_TABS} value={filter} onChange={onFilterChange} />\n </div>\n\n {sessions.isLoading ? (\n <LoadingView label=\"Loading your sessions…\" />\n ) : sessions.isError ? (\n <ErrorView\n message=\"We couldn't load your workout sessions.\"\n onRetry={() => sessions.refetch()}\n />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Flame className=\"h-10 w-10\" />}\n title={filter === 'ALL' ? 'No sessions yet' : 'No sessions in this state'}\n description={\n filter === 'ALL'\n ? 'Start a workout session to begin logging sets and tracking your training.'\n : 'Try a different filter, or start a new workout session.'\n }\n action={\n <Button onClick={openStart}>\n <Plus className=\"h-4 w-4\" /> Start session\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {rows.map((s, i) => {\n const meta = sessionMeta(s);\n const Icon = meta.icon;\n const isLive = s.status === 'IN_PROGRESS';\n const setCount = s.sets?.length;\n const rpe = s.perceivedExertion;\n return (\n <motion.button\n key={s.id}\n type=\"button\"\n onClick={() => navigateTo(`train/${s.id}`)}\n className=\"block w-full text-left\"\n initial={reduce ? false : { opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={\n reduce\n ? { duration: 0 }\n : { duration: 0.35, delay: Math.min(i, 8) * 0.05, ease: MOTION_EASE }\n }\n whileHover={reduce ? undefined : { y: -3 }}\n whileTap={reduce ? undefined : { scale: 0.995 }}\n >\n <GlassCard\n treatment=\"plain\"\n glow={isLive}\n className={\n 'h-full p-4 transition-shadow hover:shadow-float' +\n (isLive\n ? ' ring-1 ring-inset ring-[color-mix(in_oklab,var(--color-action-primary-bg)_45%,transparent)]'\n : '')\n }\n >\n <div className=\"flex items-center justify-between gap-2\">\n <IconChip icon={<Icon className=\"h-4 w-4\" />} tint={meta.tint} />\n <StatusBadge status={s.status} />\n </div>\n <p className=\"mt-3 text-base font-semibold text-text-primary\">{meta.title}</p>\n <p className=\"mt-0.5 text-xs text-text-tertiary\">\n {meta.stampLabel} {formatRelativeTime(meta.stamp)}\n </p>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary\">\n {s.caloriesBurned > 0 && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Flame className=\"h-3.5 w-3.5 text-status-warning-text\" />\n {formatKcal(s.caloriesBurned)}\n </span>\n )}\n {rpe != null && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Gauge className=\"h-3.5 w-3.5 text-accent\" />\n RPE {rpe}/10\n </span>\n )}\n {setCount != null && setCount > 0 && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <ListChecks className=\"h-3.5 w-3.5 text-accent\" />\n {formatNumber(setCount)} sets\n </span>\n )}\n </div>\n\n {rpe != null && (\n <div className=\"mt-3\">\n <div className=\"mb-1 flex items-center justify-between text-[11px] text-text-tertiary\">\n <span>RPE intensity</span>\n <span className=\"tabular-nums\">{rpe}/10</span>\n </div>\n <Meter value={rpe * 10} height={6} />\n </div>\n )}\n\n {isLive && (\n <p className=\"mt-3 inline-flex items-center gap-1 text-xs font-semibold text-action-primary-bg\">\n In progress — Resume →\n </p>\n )}\n </GlassCard>\n </motion.button>\n );\n })}\n </div>\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={hasMore}\n onPageChange={(t) => pager.onPageChange(t)}\n />\n </>\n )}\n\n {/* Start session dialog */}\n <ResponsiveDialog open={startOpen} onOpenChange={setStartOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Start a workout session</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Begin a live session now, or schedule one for later. Attach an active program to keep\n your training organised.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"space-y-4 px-1\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-program\">Program (optional)</Label>\n <Select\n value={form.programId}\n onValueChange={(v) => setForm((f) => ({ ...f, programId: v }))}\n >\n <SelectTrigger id=\"myb-start-program\">\n <SelectValue placeholder=\"No program\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NO_PROGRAM}>No program</SelectItem>\n {activePrograms.map((p) => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-scheduled\">Scheduled for (optional)</Label>\n <Input\n id=\"myb-start-scheduled\"\n type=\"datetime-local\"\n value={form.scheduledFor}\n onChange={(e) => setForm((f) => ({ ...f, scheduledFor: e.target.value }))}\n />\n <p className=\"text-xs text-text-tertiary\">\n Leave empty to start a live session right now.\n </p>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-notes\">Notes (optional)</Label>\n <Textarea\n id=\"myb-start-notes\"\n rows={3}\n value={form.notes}\n onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}\n placeholder=\"Focus, target lifts, how you're feeling…\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setStartOpen(false)}\n disabled={startSession.isPending}\n >\n Cancel\n </Button>\n <Button onClick={submitStart} disabled={startSession.isPending}>\n {startSession.isPending ? 'Starting…' : 'Start session'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionsPage.js","names":[],"sources":["../../../../src/mybodyshield/pages/train/SessionsPage.tsx"],"sourcesContent":["/**\n * Train — live workout sessions.\n * @module mybodyshield/pages/train\n *\n * Lists the member's workout sessions (real `mybListSessions`) filtered by\n * status, and lets you start a new live session (optionally attached to an\n * active program). In-progress sessions are highlighted with an accent ring and\n * a \"Resume\" affordance. No mock data — everything comes from the myb* hooks.\n */\n\nimport { useState } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport {\n Plus,\n Flame,\n CheckCircle2,\n CalendarClock,\n PlayCircle,\n SkipForward,\n Gauge,\n ListChecks,\n} from 'lucide-react';\nimport {\n Button,\n GlassCard,\n Label,\n Textarea,\n Input,\n Select,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n PageLayout,\n StatusBadge,\n FilterTabs,\n Pagination,\n LoadingView,\n ErrorView,\n EmptyState,\n type FilterOption,\n} from '../../components';\nimport { IconChip, Meter } from '../_shared/visuals';\nimport { useMyBodyShield } from '../../context';\nimport {\n useMybSessions,\n useMybStartSession,\n useMybPrograms,\n useMybProgramWorkouts,\n useOffsetPager,\n useMyBodyShieldAnalytics,\n} from '../../hooks';\nimport { formatRelativeTime, formatKcal, formatNumber } from '../../utils/formatters';\nimport type { MybSessionStatus, MybWorkoutSession } from '../../types';\n\ntype SessionFilterValue = MybSessionStatus | 'ALL';\n\n// Only statuses a control can actually reach are offered as filters: start →\n// IN_PROGRESS / SCHEDULED, complete → COMPLETED. Nothing moves a session to\n// SKIPPED, so that tab would always be empty. sessionMeta still handles the\n// SKIPPED case for display safety.\nconst STATUS_TABS: FilterOption<SessionFilterValue>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'SCHEDULED', label: 'Scheduled' },\n { value: 'IN_PROGRESS', label: 'Live' },\n { value: 'COMPLETED', label: 'Completed' },\n];\n\nconst PAGE_SIZE = 24;\n\n/** Shared entrance easing — a soft, decelerating cubic-bezier. */\nconst MOTION_EASE: [number, number, number, number] = [0.16, 1, 0.3, 1];\n\n/** Sentinel for the optional program/workout pickers (Radix Select forbids an empty value). */\nconst NO_PROGRAM = '__none__';\nconst NO_WORKOUT = '__none__';\n\ninterface StartForm {\n programId: string;\n workoutId: string;\n scheduledFor: string;\n notes: string;\n}\n\nconst EMPTY_START_FORM: StartForm = {\n programId: NO_PROGRAM,\n workoutId: NO_WORKOUT,\n scheduledFor: '',\n notes: '',\n};\n\ninterface SessionMeta {\n icon: typeof Flame;\n tint: string;\n title: string;\n stampLabel: string;\n stamp?: string | null;\n}\n\nfunction sessionMeta(s: MybWorkoutSession): SessionMeta {\n switch (s.status) {\n case 'IN_PROGRESS':\n return {\n icon: PlayCircle,\n tint: 'var(--color-accent-teal)',\n title: 'Live workout in progress',\n stampLabel: 'Started',\n stamp: s.startedAt ?? s.createdAt,\n };\n case 'COMPLETED':\n return {\n icon: CheckCircle2,\n tint: 'var(--color-status-success-text)',\n title:\n s.caloriesBurned > 0 ? `${formatKcal(s.caloriesBurned)} burned` : 'Workout completed',\n stampLabel: 'Completed',\n stamp: s.completedAt ?? s.startedAt ?? s.createdAt,\n };\n case 'SKIPPED':\n return {\n icon: SkipForward,\n tint: 'var(--color-text-secondary)',\n title: 'Skipped session',\n stampLabel: 'Scheduled',\n stamp: s.scheduledFor ?? s.createdAt,\n };\n case 'SCHEDULED':\n default:\n return {\n icon: CalendarClock,\n tint: 'var(--color-accent-primary)',\n title: 'Scheduled session',\n stampLabel: 'Scheduled',\n stamp: s.scheduledFor ?? s.createdAt,\n };\n }\n}\n\nexport function SessionsPage() {\n const { navigateTo, workspaceId } = useMyBodyShield();\n const reduce = useReducedMotion();\n const analytics = useMyBodyShieldAnalytics();\n\n const [filter, setFilter] = useState<SessionFilterValue>('ALL');\n const pager = useOffsetPager(PAGE_SIZE);\n\n const sessions = useMybSessions({\n status: filter === 'ALL' ? undefined : filter,\n pagination: { limit: PAGE_SIZE, offset: pager.offset },\n });\n\n const programs = useMybPrograms({ status: 'ACTIVE', pagination: { limit: 50 } });\n const activePrograms = programs.data?.items ?? [];\n\n const startSession = useMybStartSession();\n\n const [startOpen, setStartOpen] = useState(false);\n const [form, setForm] = useState<StartForm>(EMPTY_START_FORM);\n const [formError, setFormError] = useState<string | null>(null);\n\n // Workouts for the selected program, so a session can be tied to a specific\n // planned workout — required for the guided next-exercise stepper on\n // SessionDetailPage (BOFF-4096) to have anything to walk through.\n const selectedProgramId = form.programId === NO_PROGRAM ? undefined : form.programId;\n const programWorkouts = useMybProgramWorkouts(selectedProgramId);\n const workoutOptions = programWorkouts.data ?? [];\n\n const rows = sessions.data?.items ?? [];\n const hasMore = sessions.data?.pageInfo?.hasMore ?? false;\n\n const onFilterChange = (value: SessionFilterValue) => {\n setFilter(value);\n pager.reset();\n };\n\n const openStart = () => {\n setForm(EMPTY_START_FORM);\n setFormError(null);\n setStartOpen(true);\n analytics.emitIntent('session', 'create', { workspaceId });\n };\n\n const submitStart = async () => {\n setFormError(null);\n try {\n const created = await startSession.mutateAsync({\n programId: selectedProgramId,\n workoutId: form.workoutId === NO_WORKOUT ? undefined : form.workoutId,\n scheduledFor: form.scheduledFor ? new Date(form.scheduledFor).toISOString() : undefined,\n notes: form.notes.trim() ? form.notes.trim() : undefined,\n });\n analytics.emitFact('session', 'started', { workspaceId, entityId: created.id });\n setStartOpen(false);\n navigateTo(`train/${created.id}`);\n } catch (e) {\n setFormError(e instanceof Error ? e.message : 'Failed to start the session.');\n }\n };\n\n return (\n <PageLayout\n title=\"Train\"\n description=\"Live workout sessions — start, log sets, and complete.\"\n actions={\n <Button onClick={openStart}>\n <Plus className=\"h-4 w-4\" /> Start session\n </Button>\n }\n >\n <div className=\"mb-6\">\n <FilterTabs options={STATUS_TABS} value={filter} onChange={onFilterChange} />\n </div>\n\n {sessions.isLoading ? (\n <LoadingView label=\"Loading your sessions…\" />\n ) : sessions.isError ? (\n <ErrorView\n message=\"We couldn't load your workout sessions.\"\n onRetry={() => sessions.refetch()}\n />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Flame className=\"h-10 w-10\" />}\n title={filter === 'ALL' ? 'No sessions yet' : 'No sessions in this state'}\n description={\n filter === 'ALL'\n ? 'Start a workout session to begin logging sets and tracking your training.'\n : 'Try a different filter, or start a new workout session.'\n }\n action={\n <Button onClick={openStart}>\n <Plus className=\"h-4 w-4\" /> Start session\n </Button>\n }\n />\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {rows.map((s, i) => {\n const meta = sessionMeta(s);\n const Icon = meta.icon;\n const isLive = s.status === 'IN_PROGRESS';\n const setCount = s.sets?.length;\n const rpe = s.perceivedExertion;\n return (\n <motion.button\n key={s.id}\n type=\"button\"\n onClick={() => navigateTo(`train/${s.id}`)}\n className=\"block w-full text-left\"\n initial={reduce ? false : { opacity: 0, y: 12 }}\n animate={{ opacity: 1, y: 0 }}\n transition={\n reduce\n ? { duration: 0 }\n : { duration: 0.35, delay: Math.min(i, 8) * 0.05, ease: MOTION_EASE }\n }\n whileHover={reduce ? undefined : { y: -3 }}\n whileTap={reduce ? undefined : { scale: 0.995 }}\n >\n <GlassCard\n treatment=\"plain\"\n glow={isLive}\n className={\n 'h-full p-4 transition-shadow hover:shadow-float' +\n (isLive\n ? ' ring-1 ring-inset ring-[color-mix(in_oklab,var(--color-action-primary-bg)_45%,transparent)]'\n : '')\n }\n >\n <div className=\"flex items-center justify-between gap-2\">\n <IconChip icon={<Icon className=\"h-4 w-4\" />} tint={meta.tint} />\n <StatusBadge status={s.status} />\n </div>\n <p className=\"mt-3 text-base font-semibold text-text-primary\">{meta.title}</p>\n <p className=\"mt-0.5 text-xs text-text-tertiary\">\n {meta.stampLabel} {formatRelativeTime(meta.stamp)}\n </p>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary\">\n {s.caloriesBurned > 0 && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Flame className=\"h-3.5 w-3.5 text-status-warning-text\" />\n {formatKcal(s.caloriesBurned)}\n </span>\n )}\n {rpe != null && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Gauge className=\"h-3.5 w-3.5 text-accent\" />\n RPE {rpe}/10\n </span>\n )}\n {setCount != null && setCount > 0 && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <ListChecks className=\"h-3.5 w-3.5 text-accent\" />\n {formatNumber(setCount)} sets\n </span>\n )}\n </div>\n\n {rpe != null && (\n <div className=\"mt-3\">\n <div className=\"mb-1 flex items-center justify-between text-[11px] text-text-tertiary\">\n <span>RPE intensity</span>\n <span className=\"tabular-nums\">{rpe}/10</span>\n </div>\n <Meter value={rpe * 10} height={6} />\n </div>\n )}\n\n {isLive && (\n <p className=\"mt-3 inline-flex items-center gap-1 text-xs font-semibold text-action-primary-bg\">\n In progress — Resume →\n </p>\n )}\n </GlassCard>\n </motion.button>\n );\n })}\n </div>\n\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={rows.length}\n hasMore={hasMore}\n onPageChange={(t) => pager.onPageChange(t)}\n />\n </>\n )}\n\n {/* Start session dialog */}\n <ResponsiveDialog open={startOpen} onOpenChange={setStartOpen}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Start a workout session</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Begin a live session now, or schedule one for later. Attach an active program to keep\n your training organised.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"space-y-4 px-1\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-program\">Program (optional)</Label>\n <Select\n value={form.programId}\n onValueChange={(v) =>\n // Reset the workout choice too — the previous selection almost\n // certainly doesn't belong to the newly-picked program.\n setForm((f) => ({ ...f, programId: v, workoutId: NO_WORKOUT }))\n }\n >\n <SelectTrigger id=\"myb-start-program\">\n <SelectValue placeholder=\"No program\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NO_PROGRAM}>No program</SelectItem>\n {activePrograms.map((p) => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {selectedProgramId && workoutOptions.length > 0 && (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-workout\">Workout (optional)</Label>\n <Select\n value={form.workoutId}\n onValueChange={(v) => setForm((f) => ({ ...f, workoutId: v }))}\n >\n <SelectTrigger id=\"myb-start-workout\">\n <SelectValue placeholder=\"No specific workout\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NO_WORKOUT}>No specific workout</SelectItem>\n {workoutOptions.map((w) => (\n <SelectItem key={w.id} value={w.id}>\n {w.name} — Week {w.weekNumber}, Day {w.dayOfWeek}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-xs text-text-tertiary\">\n Attach a planned workout to guide this session exercise-by-exercise.\n </p>\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-scheduled\">Scheduled for (optional)</Label>\n <Input\n id=\"myb-start-scheduled\"\n type=\"datetime-local\"\n value={form.scheduledFor}\n onChange={(e) => setForm((f) => ({ ...f, scheduledFor: e.target.value }))}\n />\n <p className=\"text-xs text-text-tertiary\">\n Leave empty to start a live session right now.\n </p>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"myb-start-notes\">Notes (optional)</Label>\n <Textarea\n id=\"myb-start-notes\"\n rows={3}\n value={form.notes}\n onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}\n placeholder=\"Focus, target lifts, how you're feeling…\"\n />\n </div>\n\n {formError && <p className=\"text-sm text-status-error-text\">{formError}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setStartOpen(false)}\n disabled={startSession.isPending}\n >\n Cancel\n </Button>\n <Button onClick={submitStart} disabled={startSession.isPending}>\n {startSession.isPending ? 'Starting…' : 'Start session'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/types/assistant.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAEnF,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEhG,MAAM,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/types/assistant.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAEnF,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAEhG,MAAM,MAAM,2BAA2B,GACrC,MAAM,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|