@burdenoff/microfe-mybodyshield 2026.820.1 → 2026.821.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.
Files changed (48) hide show
  1. package/dist/mybodyshield/MyBodyShieldRoot.d.ts.map +1 -1
  2. package/dist/mybodyshield/MyBodyShieldRoot.js +68 -44
  3. package/dist/mybodyshield/MyBodyShieldRoot.js.map +1 -1
  4. package/dist/mybodyshield/MyBodyShieldRoutes.d.ts.map +1 -1
  5. package/dist/mybodyshield/MyBodyShieldRoutes.js +37 -16
  6. package/dist/mybodyshield/MyBodyShieldRoutes.js.map +1 -1
  7. package/dist/mybodyshield/hooks/useMyBodyShieldApi.d.ts +11 -1
  8. package/dist/mybodyshield/hooks/useMyBodyShieldApi.d.ts.map +1 -1
  9. package/dist/mybodyshield/hooks/useMyBodyShieldApi.js +113 -46
  10. package/dist/mybodyshield/hooks/useMyBodyShieldApi.js.map +1 -1
  11. package/dist/mybodyshield/pages/SettingsPage.d.ts +10 -0
  12. package/dist/mybodyshield/pages/SettingsPage.d.ts.map +1 -0
  13. package/dist/mybodyshield/pages/SettingsPage.js +104 -0
  14. package/dist/mybodyshield/pages/SettingsPage.js.map +1 -0
  15. package/dist/mybodyshield/pages/ai/AiControlsPage.d.ts +10 -0
  16. package/dist/mybodyshield/pages/ai/AiControlsPage.d.ts.map +1 -0
  17. package/dist/mybodyshield/pages/ai/AiControlsPage.js +378 -0
  18. package/dist/mybodyshield/pages/ai/AiControlsPage.js.map +1 -0
  19. package/dist/mybodyshield/pages/insights/InsightsCharts.d.ts +18 -0
  20. package/dist/mybodyshield/pages/insights/InsightsCharts.d.ts.map +1 -0
  21. package/dist/mybodyshield/pages/insights/InsightsCharts.js +549 -0
  22. package/dist/mybodyshield/pages/insights/InsightsCharts.js.map +1 -0
  23. package/dist/mybodyshield/pages/insights/InsightsPage.d.ts +12 -0
  24. package/dist/mybodyshield/pages/insights/InsightsPage.d.ts.map +1 -0
  25. package/dist/mybodyshield/pages/insights/InsightsPage.js +317 -0
  26. package/dist/mybodyshield/pages/insights/InsightsPage.js.map +1 -0
  27. package/dist/mybodyshield/types/index.d.ts +75 -0
  28. package/dist/mybodyshield/types/index.d.ts.map +1 -1
  29. package/dist/mybodyshield/utils/pageContext.d.ts.map +1 -1
  30. package/dist/mybodyshield/utils/pageContext.js +4 -1
  31. package/dist/mybodyshield/utils/pageContext.js.map +1 -1
  32. package/dist/node_modules/recharts/es6/cartesian/Line.js +473 -0
  33. package/dist/node_modules/recharts/es6/cartesian/Line.js.map +1 -0
  34. package/dist/node_modules/recharts/es6/cartesian/Scatter.js +368 -0
  35. package/dist/node_modules/recharts/es6/cartesian/Scatter.js.map +1 -0
  36. package/dist/node_modules/recharts/es6/cartesian/ZAxis.js +103 -0
  37. package/dist/node_modules/recharts/es6/cartesian/ZAxis.js.map +1 -0
  38. package/dist/node_modules/recharts/es6/chart/BarChart.js +24 -0
  39. package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -0
  40. package/dist/node_modules/recharts/es6/chart/ComposedChart.js +38 -0
  41. package/dist/node_modules/recharts/es6/chart/ComposedChart.js.map +1 -0
  42. package/dist/node_modules/recharts/es6/util/DataUtils.js +12 -2
  43. package/dist/node_modules/recharts/es6/util/DataUtils.js.map +1 -1
  44. package/dist/node_modules/recharts/es6/util/ScatterUtils.js +48 -0
  45. package/dist/node_modules/recharts/es6/util/ScatterUtils.js.map +1 -0
  46. package/dist/stories/InsightsCharts.stories.d.ts +15 -0
  47. package/dist/stories/InsightsCharts.stories.d.ts.map +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,549 @@
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import { formatDate as t, formatGrams as n, formatKcal as r, formatNumber as i, formatWeight as a } from "../../utils/formatters.js";
3
+ import { IconChip as o, MACRO_HUE as s } from "../_shared/visuals.js";
4
+ import { Legend as c } from "../../../node_modules/recharts/es6/component/Legend.js";
5
+ import { Tooltip as l } from "../../../node_modules/recharts/es6/component/Tooltip.js";
6
+ import { ResponsiveContainer as u } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
7
+ import { Bar as d } from "../../../node_modules/recharts/es6/cartesian/Bar.js";
8
+ import { CartesianGrid as f } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
9
+ import { Line as p } from "../../../node_modules/recharts/es6/cartesian/Line.js";
10
+ import { Area as m } from "../../../node_modules/recharts/es6/cartesian/Area.js";
11
+ import { XAxis as h } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
12
+ import { YAxis as g } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
13
+ import { BarChart as _ } from "../../../node_modules/recharts/es6/chart/BarChart.js";
14
+ import { ComposedChart as v } from "../../../node_modules/recharts/es6/chart/ComposedChart.js";
15
+ import { useMemo as y } from "react";
16
+ import { Activity as b, Dumbbell as x, HeartPulse as S, Moon as C, Scale as w, Utensils as T } from "lucide-react";
17
+ import { jsx as E, jsxs as D } from "react/jsx-runtime";
18
+ import { GlassCard as O } from "@burdenoff/fe-libs/ui";
19
+ //#region src/mybodyshield/pages/insights/InsightsCharts.tsx
20
+ var k = {
21
+ primary: "var(--color-action-primary-bg)",
22
+ secondary: "var(--color-accent-primary)",
23
+ success: "var(--color-status-success-text)",
24
+ warning: "var(--color-status-warning-text)",
25
+ error: "var(--color-status-error-text)",
26
+ chart1: "var(--color-chart-1)",
27
+ chart2: "var(--color-chart-2)",
28
+ chart3: "var(--color-chart-3)",
29
+ chart4: "var(--color-chart-4)"
30
+ }, A = {
31
+ background: "var(--color-bg-surface)",
32
+ border: "1px solid var(--color-border-seam)",
33
+ borderRadius: 12,
34
+ color: "var(--color-text-primary)",
35
+ fontSize: 12
36
+ }, j = {
37
+ stroke: "var(--color-border-seam)",
38
+ strokeDasharray: "4 4"
39
+ }, M = {
40
+ fill: "var(--color-text-tertiary)",
41
+ fontSize: 12
42
+ };
43
+ function N(e) {
44
+ return y(() => [...e].sort((e, t) => new Date(e.date).getTime() - new Date(t.date).getTime()).map((e) => ({
45
+ label: t(e.date),
46
+ date: e.date,
47
+ sessions: e.sessions,
48
+ volumeKg: e.volumeKg,
49
+ readiness: e.readiness ?? null,
50
+ sleepHours: e.sleepHours ?? null,
51
+ calories: e.calories,
52
+ proteinG: e.proteinG,
53
+ carbsG: e.carbsG,
54
+ fatG: e.fatG,
55
+ weight: e.weight ?? null
56
+ })), [e]);
57
+ }
58
+ function P({ message: e = "No data for the selected range" }) {
59
+ return /* @__PURE__ */ D("div", {
60
+ className: "flex h-[240px] flex-col items-center justify-center gap-2 text-center",
61
+ children: [/* @__PURE__ */ E(b, { className: "h-8 w-8 text-text-tertiary" }), /* @__PURE__ */ E("p", {
62
+ className: "text-sm text-text-secondary",
63
+ children: e
64
+ })]
65
+ });
66
+ }
67
+ function F({ title: t, icon: n, children: r, className: i }) {
68
+ return /* @__PURE__ */ D(O, {
69
+ treatment: "plain",
70
+ className: e("overflow-hidden p-5", i),
71
+ children: [/* @__PURE__ */ D("div", {
72
+ className: "mb-4 flex items-center gap-2.5",
73
+ children: [n, /* @__PURE__ */ E("h3", {
74
+ className: "text-sm font-semibold text-text-primary",
75
+ children: t
76
+ })]
77
+ }), r]
78
+ });
79
+ }
80
+ function I({ daily: e }) {
81
+ let t = N(e);
82
+ return t.length === 0 ? /* @__PURE__ */ E(F, {
83
+ title: "Training volume",
84
+ icon: /* @__PURE__ */ E(o, {
85
+ icon: /* @__PURE__ */ E(x, { className: "h-4 w-4" }),
86
+ tint: k.primary
87
+ }),
88
+ children: /* @__PURE__ */ E(P, { message: "Log completed sessions to see volume trends." })
89
+ }) : /* @__PURE__ */ E(F, {
90
+ title: "Training volume",
91
+ icon: /* @__PURE__ */ E(o, {
92
+ icon: /* @__PURE__ */ E(x, { className: "h-4 w-4" }),
93
+ tint: k.primary
94
+ }),
95
+ children: /* @__PURE__ */ E("div", {
96
+ className: "h-[260px] w-full",
97
+ children: /* @__PURE__ */ E(u, {
98
+ width: "100%",
99
+ height: "100%",
100
+ children: /* @__PURE__ */ D(v, {
101
+ data: t,
102
+ margin: {
103
+ top: 4,
104
+ right: 16,
105
+ bottom: 4,
106
+ left: 4
107
+ },
108
+ children: [
109
+ /* @__PURE__ */ E(f, {
110
+ ...j,
111
+ vertical: !1
112
+ }),
113
+ /* @__PURE__ */ E(h, {
114
+ dataKey: "label",
115
+ tickLine: !1,
116
+ axisLine: !1,
117
+ tick: M,
118
+ tickMargin: 8,
119
+ minTickGap: 24
120
+ }),
121
+ /* @__PURE__ */ E(g, {
122
+ yAxisId: "left",
123
+ tickLine: !1,
124
+ axisLine: !1,
125
+ tick: M,
126
+ width: 52,
127
+ tickFormatter: (e) => a(Number(e))
128
+ }),
129
+ /* @__PURE__ */ E(g, {
130
+ yAxisId: "right",
131
+ orientation: "right",
132
+ tickLine: !1,
133
+ axisLine: !1,
134
+ tick: M,
135
+ width: 36,
136
+ allowDecimals: !1
137
+ }),
138
+ /* @__PURE__ */ E(l, {
139
+ contentStyle: A,
140
+ labelStyle: { color: "var(--color-text-tertiary)" },
141
+ formatter: (e, t) => t === "Volume" ? [a(Number(e)), t] : [i(Number(e)), "Sessions"]
142
+ }),
143
+ /* @__PURE__ */ E(c, { wrapperStyle: {
144
+ fontSize: 12,
145
+ paddingTop: 8
146
+ } }),
147
+ /* @__PURE__ */ E(d, {
148
+ yAxisId: "left",
149
+ dataKey: "volumeKg",
150
+ name: "Volume",
151
+ fill: k.primary,
152
+ radius: [
153
+ 4,
154
+ 4,
155
+ 0,
156
+ 0
157
+ ],
158
+ opacity: .85
159
+ }),
160
+ /* @__PURE__ */ E(p, {
161
+ yAxisId: "right",
162
+ type: "monotone",
163
+ dataKey: "sessions",
164
+ name: "Sessions",
165
+ stroke: k.secondary,
166
+ strokeWidth: 2.5,
167
+ dot: !1,
168
+ activeDot: {
169
+ r: 4,
170
+ strokeWidth: 2,
171
+ stroke: "var(--color-bg-surface)"
172
+ }
173
+ })
174
+ ]
175
+ })
176
+ })
177
+ })
178
+ });
179
+ }
180
+ function L({ daily: e }) {
181
+ let t = N(e);
182
+ return t.some((e) => e.readiness != null || e.sleepHours != null) ? /* @__PURE__ */ E(F, {
183
+ title: "Recovery & sleep",
184
+ icon: /* @__PURE__ */ E(o, {
185
+ icon: /* @__PURE__ */ E(S, { className: "h-4 w-4" }),
186
+ tint: k.success
187
+ }),
188
+ children: /* @__PURE__ */ E("div", {
189
+ className: "h-[260px] w-full",
190
+ children: /* @__PURE__ */ E(u, {
191
+ width: "100%",
192
+ height: "100%",
193
+ children: /* @__PURE__ */ D(v, {
194
+ data: t,
195
+ margin: {
196
+ top: 4,
197
+ right: 16,
198
+ bottom: 4,
199
+ left: 4
200
+ },
201
+ children: [
202
+ /* @__PURE__ */ E(f, {
203
+ ...j,
204
+ vertical: !1
205
+ }),
206
+ /* @__PURE__ */ E(h, {
207
+ dataKey: "label",
208
+ tickLine: !1,
209
+ axisLine: !1,
210
+ tick: M,
211
+ tickMargin: 8,
212
+ minTickGap: 24
213
+ }),
214
+ /* @__PURE__ */ E(g, {
215
+ yAxisId: "left",
216
+ tickLine: !1,
217
+ axisLine: !1,
218
+ tick: M,
219
+ width: 36,
220
+ domain: [0, 100],
221
+ hide: !t.some((e) => e.readiness != null)
222
+ }),
223
+ /* @__PURE__ */ E(g, {
224
+ yAxisId: "right",
225
+ orientation: "right",
226
+ tickLine: !1,
227
+ axisLine: !1,
228
+ tick: M,
229
+ width: 44,
230
+ tickFormatter: (e) => `${i(Number(e))} h`,
231
+ hide: !t.some((e) => e.sleepHours != null)
232
+ }),
233
+ /* @__PURE__ */ E(l, {
234
+ contentStyle: A,
235
+ labelStyle: { color: "var(--color-text-tertiary)" },
236
+ formatter: (e, t) => t === "Readiness" ? [i(Number(e)), t] : [`${i(Number(e))} h`, t]
237
+ }),
238
+ /* @__PURE__ */ E(c, { wrapperStyle: {
239
+ fontSize: 12,
240
+ paddingTop: 8
241
+ } }),
242
+ /* @__PURE__ */ E(m, {
243
+ yAxisId: "right",
244
+ type: "monotone",
245
+ dataKey: "sleepHours",
246
+ name: "Sleep",
247
+ stroke: k.secondary,
248
+ strokeWidth: 2,
249
+ fill: k.secondary,
250
+ fillOpacity: .12,
251
+ dot: !1,
252
+ activeDot: {
253
+ r: 4,
254
+ strokeWidth: 2,
255
+ stroke: "var(--color-bg-surface)"
256
+ },
257
+ connectNulls: !0
258
+ }),
259
+ /* @__PURE__ */ E(p, {
260
+ yAxisId: "left",
261
+ type: "monotone",
262
+ dataKey: "readiness",
263
+ name: "Readiness",
264
+ stroke: k.success,
265
+ strokeWidth: 2.5,
266
+ dot: !1,
267
+ activeDot: {
268
+ r: 4,
269
+ strokeWidth: 2,
270
+ stroke: "var(--color-bg-surface)"
271
+ },
272
+ connectNulls: !0
273
+ })
274
+ ]
275
+ })
276
+ })
277
+ })
278
+ }) : /* @__PURE__ */ E(F, {
279
+ title: "Recovery & sleep",
280
+ icon: /* @__PURE__ */ E(o, {
281
+ icon: /* @__PURE__ */ E(S, { className: "h-4 w-4" }),
282
+ tint: k.success
283
+ }),
284
+ children: /* @__PURE__ */ E(P, { message: "Log recovery entries to see readiness and sleep trends." })
285
+ });
286
+ }
287
+ function R({ daily: e }) {
288
+ let t = N(e);
289
+ return t.length === 0 ? /* @__PURE__ */ E(F, {
290
+ title: "Macro adherence",
291
+ icon: /* @__PURE__ */ E(o, {
292
+ icon: /* @__PURE__ */ E(T, { className: "h-4 w-4" }),
293
+ tint: k.warning
294
+ }),
295
+ children: /* @__PURE__ */ E(P, { message: "Log meals to see macro trends." })
296
+ }) : /* @__PURE__ */ E(F, {
297
+ title: "Macro adherence",
298
+ icon: /* @__PURE__ */ E(o, {
299
+ icon: /* @__PURE__ */ E(T, { className: "h-4 w-4" }),
300
+ tint: k.warning
301
+ }),
302
+ children: /* @__PURE__ */ E("div", {
303
+ className: "h-[260px] w-full",
304
+ children: /* @__PURE__ */ E(u, {
305
+ width: "100%",
306
+ height: "100%",
307
+ children: /* @__PURE__ */ D(_, {
308
+ data: t,
309
+ margin: {
310
+ top: 4,
311
+ right: 16,
312
+ bottom: 4,
313
+ left: 4
314
+ },
315
+ children: [
316
+ /* @__PURE__ */ E(f, {
317
+ ...j,
318
+ vertical: !1
319
+ }),
320
+ /* @__PURE__ */ E(h, {
321
+ dataKey: "label",
322
+ tickLine: !1,
323
+ axisLine: !1,
324
+ tick: M,
325
+ tickMargin: 8,
326
+ minTickGap: 24
327
+ }),
328
+ /* @__PURE__ */ E(g, {
329
+ tickLine: !1,
330
+ axisLine: !1,
331
+ tick: M,
332
+ width: 44,
333
+ tickFormatter: (e) => n(Number(e))
334
+ }),
335
+ /* @__PURE__ */ E(l, {
336
+ contentStyle: A,
337
+ labelStyle: { color: "var(--color-text-tertiary)" },
338
+ formatter: (e, t) => [n(Number(e)), t]
339
+ }),
340
+ /* @__PURE__ */ E(c, { wrapperStyle: {
341
+ fontSize: 12,
342
+ paddingTop: 8
343
+ } }),
344
+ /* @__PURE__ */ E(d, {
345
+ dataKey: "proteinG",
346
+ name: "Protein",
347
+ stackId: "macros",
348
+ fill: s.protein
349
+ }),
350
+ /* @__PURE__ */ E(d, {
351
+ dataKey: "carbsG",
352
+ name: "Carbs",
353
+ stackId: "macros",
354
+ fill: s.carbs
355
+ }),
356
+ /* @__PURE__ */ E(d, {
357
+ dataKey: "fatG",
358
+ name: "Fat",
359
+ stackId: "macros",
360
+ fill: s.fat
361
+ })
362
+ ]
363
+ })
364
+ })
365
+ })
366
+ });
367
+ }
368
+ function z({ daily: e }) {
369
+ let t = N(e);
370
+ return t.length === 0 ? /* @__PURE__ */ E(F, {
371
+ title: "Calorie trend",
372
+ icon: /* @__PURE__ */ E(o, {
373
+ icon: /* @__PURE__ */ E(w, { className: "h-4 w-4" }),
374
+ tint: k.chart1
375
+ }),
376
+ children: /* @__PURE__ */ E(P, { message: "Log meals to see calorie trends." })
377
+ }) : /* @__PURE__ */ E(F, {
378
+ title: "Calorie trend",
379
+ icon: /* @__PURE__ */ E(o, {
380
+ icon: /* @__PURE__ */ E(w, { className: "h-4 w-4" }),
381
+ tint: k.chart1
382
+ }),
383
+ children: /* @__PURE__ */ E("div", {
384
+ className: "h-[260px] w-full",
385
+ children: /* @__PURE__ */ E(u, {
386
+ width: "100%",
387
+ height: "100%",
388
+ children: /* @__PURE__ */ D(v, {
389
+ data: t,
390
+ margin: {
391
+ top: 4,
392
+ right: 16,
393
+ bottom: 4,
394
+ left: 4
395
+ },
396
+ children: [
397
+ /* @__PURE__ */ E(f, {
398
+ ...j,
399
+ vertical: !1
400
+ }),
401
+ /* @__PURE__ */ E(h, {
402
+ dataKey: "label",
403
+ tickLine: !1,
404
+ axisLine: !1,
405
+ tick: M,
406
+ tickMargin: 8,
407
+ minTickGap: 24
408
+ }),
409
+ /* @__PURE__ */ E(g, {
410
+ tickLine: !1,
411
+ axisLine: !1,
412
+ tick: M,
413
+ width: 52,
414
+ tickFormatter: (e) => r(Number(e))
415
+ }),
416
+ /* @__PURE__ */ E(l, {
417
+ contentStyle: A,
418
+ labelStyle: { color: "var(--color-text-tertiary)" },
419
+ formatter: (e) => [r(Number(e)), "Calories"]
420
+ }),
421
+ /* @__PURE__ */ E(m, {
422
+ type: "monotone",
423
+ dataKey: "calories",
424
+ name: "Calories",
425
+ stroke: k.chart1,
426
+ strokeWidth: 2,
427
+ fill: k.chart1,
428
+ fillOpacity: .12,
429
+ dot: !1,
430
+ activeDot: {
431
+ r: 4,
432
+ strokeWidth: 2,
433
+ stroke: "var(--color-bg-surface)"
434
+ }
435
+ })
436
+ ]
437
+ })
438
+ })
439
+ })
440
+ });
441
+ }
442
+ function B(e, t) {
443
+ let n = e.map((e, n) => [e, t[n]]).filter(([e, t]) => e != null && t != null);
444
+ if (n.length < 3) return {
445
+ r: null,
446
+ n: n.length
447
+ };
448
+ let r = n.length, i = n.reduce((e, [t]) => e + t, 0), a = n.reduce((e, [, t]) => e + t, 0), o = n.reduce((e, [t]) => e + t * t, 0), s = n.reduce((e, [, t]) => e + t * t, 0), c = n.reduce((e, [t, n]) => e + t * n, 0), l = Math.sqrt((r * o - i * i) * (r * s - a * a));
449
+ return !Number.isFinite(l) || l === 0 ? {
450
+ r: null,
451
+ n: r
452
+ } : {
453
+ r: (r * c - i * a) / l,
454
+ n: r
455
+ };
456
+ }
457
+ function V(e) {
458
+ return y(() => {
459
+ let t = e.map((e) => e.readiness ?? null), n = e.map((e) => e.sleepHours ?? null), r = e.map((e) => e.volumeKg), i = e.map((e) => e.sessions), a = e.map((e) => e.proteinG), o = e.map((e) => e.calories), s = (e, t, n, r, i) => {
460
+ let { r: a, n: o } = B(r, i);
461
+ return {
462
+ label: e,
463
+ x: t,
464
+ y: n,
465
+ r: a,
466
+ n: o
467
+ };
468
+ };
469
+ return [
470
+ s("Sleep → Readiness", "Sleep", "Readiness", n, t),
471
+ s("Volume → Readiness", "Volume", "Readiness", r, t),
472
+ s("Sessions → Sleep", "Sessions", "Sleep", i, n),
473
+ s("Protein → Readiness", "Protein", "Readiness", a, t),
474
+ s("Calories → Volume", "Calories", "Volume", o, r)
475
+ ];
476
+ }, [e]);
477
+ }
478
+ function H(e) {
479
+ let t = Math.abs(e);
480
+ return t >= .7 ? "Strong" : t >= .4 ? "Moderate" : t >= .2 ? "Weak" : "None";
481
+ }
482
+ function U(e) {
483
+ return e > 0 ? "var(--color-status-success-text)" : e < 0 ? "var(--color-status-error-text)" : "var(--color-text-tertiary)";
484
+ }
485
+ function W({ daily: e }) {
486
+ let t = V(e).filter((e) => e.r != null);
487
+ return t.length === 0 ? /* @__PURE__ */ D(O, {
488
+ treatment: "plain",
489
+ className: "p-6",
490
+ children: [/* @__PURE__ */ D("div", {
491
+ className: "flex items-center gap-2.5",
492
+ children: [/* @__PURE__ */ E(o, {
493
+ icon: /* @__PURE__ */ E(C, { className: "h-4 w-4" }),
494
+ tint: k.secondary
495
+ }), /* @__PURE__ */ E("h3", {
496
+ className: "text-sm font-semibold text-text-primary",
497
+ children: "Correlations"
498
+ })]
499
+ }), /* @__PURE__ */ E("p", {
500
+ className: "mt-3 text-sm text-text-secondary",
501
+ children: "Log a few more recovery, training and nutrition days to surface correlations."
502
+ })]
503
+ }) : /* @__PURE__ */ D(O, {
504
+ treatment: "plain",
505
+ className: "overflow-hidden p-0",
506
+ children: [/* @__PURE__ */ D("div", {
507
+ className: "border-b border-border-seam px-5 py-4",
508
+ children: [/* @__PURE__ */ D("div", {
509
+ className: "flex items-center gap-2.5",
510
+ children: [/* @__PURE__ */ E(o, {
511
+ icon: /* @__PURE__ */ E(C, { className: "h-4 w-4" }),
512
+ tint: k.secondary
513
+ }), /* @__PURE__ */ E("h3", {
514
+ className: "text-sm font-semibold text-text-primary",
515
+ children: "Correlations"
516
+ })]
517
+ }), /* @__PURE__ */ E("p", {
518
+ className: "mt-1 text-xs text-text-secondary",
519
+ children: "Pearson correlation across the selected range. More data gives more reliable signals."
520
+ })]
521
+ }), /* @__PURE__ */ E("div", {
522
+ className: "divide-y divide-border-seam/60",
523
+ children: t.map((e) => /* @__PURE__ */ D("div", {
524
+ className: "flex items-center justify-between px-5 py-3",
525
+ children: [/* @__PURE__ */ D("div", { children: [/* @__PURE__ */ E("p", {
526
+ className: "text-sm font-medium text-text-primary",
527
+ children: e.label
528
+ }), /* @__PURE__ */ D("p", {
529
+ className: "text-xs text-text-tertiary",
530
+ children: [e.n, " days with both metrics"]
531
+ })] }), /* @__PURE__ */ D("div", {
532
+ className: "text-right",
533
+ children: [/* @__PURE__ */ E("p", {
534
+ className: "text-sm font-semibold tabular-nums",
535
+ style: { color: U(e.r ?? 0) },
536
+ children: (e.r ?? 0).toFixed(2)
537
+ }), /* @__PURE__ */ E("p", {
538
+ className: "text-xs text-text-tertiary",
539
+ children: H(e.r ?? 0)
540
+ })]
541
+ })]
542
+ }, e.label))
543
+ })]
544
+ });
545
+ }
546
+ //#endregion
547
+ export { z as CalorieChart, W as CorrelationView, R as MacroChart, L as ReadinessSleepChart, I as VolumeChart };
548
+
549
+ //# sourceMappingURL=InsightsCharts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InsightsCharts.js","names":[],"sources":["../../../../src/mybodyshield/pages/insights/InsightsCharts.tsx"],"sourcesContent":["/**\n * Insights visualisations — recharts-based charts and correlation summary for\n * the MyBodyShield Insights page.\n * @module mybodyshield/pages/insights\n *\n * BOFF-4056: charts are pure presentational components that receive the\n * `MybInsightsDay[]` series already aggregated by the backend. No network\n * calls here.\n */\n\nimport { useMemo, type ReactNode } from 'react';\nimport {\n ResponsiveContainer,\n ComposedChart,\n BarChart,\n Bar,\n Area,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n} from 'recharts';\nimport { Dumbbell, HeartPulse, Moon, Utensils, Scale, Activity } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../../utils/cn';\nimport {\n formatDate,\n formatNumber,\n formatWeight,\n formatGrams,\n formatKcal,\n} from '../../utils/formatters';\nimport { IconChip, MACRO_HUE } from '../_shared/visuals';\nimport type { MybInsightsDay } from '../../types';\n\n// ============================================================================\n// Tokens\n// ============================================================================\n\nconst CHART_COLORS = {\n primary: 'var(--color-action-primary-bg)',\n secondary: 'var(--color-accent-primary)',\n success: 'var(--color-status-success-text)',\n warning: 'var(--color-status-warning-text)',\n error: 'var(--color-status-error-text)',\n chart1: 'var(--color-chart-1)',\n chart2: 'var(--color-chart-2)',\n chart3: 'var(--color-chart-3)',\n chart4: 'var(--color-chart-4)',\n} as const;\n\nconst TOOLTIP_STYLE = {\n background: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border-seam)',\n borderRadius: 12,\n color: 'var(--color-text-primary)',\n fontSize: 12,\n};\n\nconst GRID_STYLE = {\n stroke: 'var(--color-border-seam)',\n strokeDasharray: '4 4',\n};\n\nconst AXIS_TICK_STYLE = { fill: 'var(--color-text-tertiary)', fontSize: 12 };\n\n// ============================================================================\n// Chart data shaping\n// ============================================================================\n\ntype ChartRow = {\n label: string;\n date: string;\n sessions: number;\n volumeKg: number;\n readiness: number | null;\n sleepHours: number | null;\n calories: number;\n proteinG: number;\n carbsG: number;\n fatG: number;\n weight: number | null;\n};\n\nfunction useChartData(daily: MybInsightsDay[]): ChartRow[] {\n return useMemo(\n () =>\n [...daily]\n .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())\n .map((d) => ({\n label: formatDate(d.date),\n date: d.date,\n sessions: d.sessions,\n volumeKg: d.volumeKg,\n readiness: d.readiness ?? null,\n sleepHours: d.sleepHours ?? null,\n calories: d.calories,\n proteinG: d.proteinG,\n carbsG: d.carbsG,\n fatG: d.fatG,\n weight: d.weight ?? null,\n })),\n [daily]\n );\n}\n\nfunction EmptyChart({ message = 'No data for the selected range' }: { message?: string }) {\n return (\n <div className=\"flex h-[240px] flex-col items-center justify-center gap-2 text-center\">\n <Activity className=\"h-8 w-8 text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n );\n}\n\nfunction ChartCard({\n title,\n icon,\n children,\n className,\n}: {\n title: string;\n icon: ReactNode;\n children: ReactNode;\n className?: string;\n}) {\n return (\n <GlassCard treatment=\"plain\" className={cn('overflow-hidden p-5', className)}>\n <div className=\"mb-4 flex items-center gap-2.5\">\n {icon}\n <h3 className=\"text-sm font-semibold text-text-primary\">{title}</h3>\n </div>\n {children}\n </GlassCard>\n );\n}\n\n// ============================================================================\n// Volume + sessions over time\n// ============================================================================\n\nexport function VolumeChart({ daily }: { daily: MybInsightsDay[] }) {\n const data = useChartData(daily);\n\n if (data.length === 0) {\n return (\n <ChartCard\n title=\"Training volume\"\n icon={<IconChip icon={<Dumbbell className=\"h-4 w-4\" />} tint={CHART_COLORS.primary} />}\n >\n <EmptyChart message=\"Log completed sessions to see volume trends.\" />\n </ChartCard>\n );\n }\n\n return (\n <ChartCard\n title=\"Training volume\"\n icon={<IconChip icon={<Dumbbell className=\"h-4 w-4\" />} tint={CHART_COLORS.primary} />}\n >\n <div className=\"h-[260px] w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <ComposedChart data={data} margin={{ top: 4, right: 16, bottom: 4, left: 4 }}>\n <CartesianGrid {...GRID_STYLE} vertical={false} />\n <XAxis\n dataKey=\"label\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n tickMargin={8}\n minTickGap={24}\n />\n <YAxis\n yAxisId=\"left\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={52}\n tickFormatter={(v) => formatWeight(Number(v))}\n />\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={36}\n allowDecimals={false}\n />\n <Tooltip\n contentStyle={TOOLTIP_STYLE}\n labelStyle={{ color: 'var(--color-text-tertiary)' }}\n formatter={(value, name) => {\n if (name === 'Volume') return [formatWeight(Number(value)), name];\n return [formatNumber(Number(value)), 'Sessions'];\n }}\n />\n <Legend wrapperStyle={{ fontSize: 12, paddingTop: 8 }} />\n <Bar\n yAxisId=\"left\"\n dataKey=\"volumeKg\"\n name=\"Volume\"\n fill={CHART_COLORS.primary}\n radius={[4, 4, 0, 0]}\n opacity={0.85}\n />\n <Line\n yAxisId=\"right\"\n type=\"monotone\"\n dataKey=\"sessions\"\n name=\"Sessions\"\n stroke={CHART_COLORS.secondary}\n strokeWidth={2.5}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: 'var(--color-bg-surface)' }}\n />\n </ComposedChart>\n </ResponsiveContainer>\n </div>\n </ChartCard>\n );\n}\n\n// ============================================================================\n// Readiness + sleep over time\n// ============================================================================\n\nexport function ReadinessSleepChart({ daily }: { daily: MybInsightsDay[] }) {\n const data = useChartData(daily);\n const hasData = data.some((d) => d.readiness != null || d.sleepHours != null);\n\n if (!hasData) {\n return (\n <ChartCard\n title=\"Recovery & sleep\"\n icon={<IconChip icon={<HeartPulse className=\"h-4 w-4\" />} tint={CHART_COLORS.success} />}\n >\n <EmptyChart message=\"Log recovery entries to see readiness and sleep trends.\" />\n </ChartCard>\n );\n }\n\n return (\n <ChartCard\n title=\"Recovery & sleep\"\n icon={<IconChip icon={<HeartPulse className=\"h-4 w-4\" />} tint={CHART_COLORS.success} />}\n >\n <div className=\"h-[260px] w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <ComposedChart data={data} margin={{ top: 4, right: 16, bottom: 4, left: 4 }}>\n <CartesianGrid {...GRID_STYLE} vertical={false} />\n <XAxis\n dataKey=\"label\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n tickMargin={8}\n minTickGap={24}\n />\n <YAxis\n yAxisId=\"left\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={36}\n domain={[0, 100]}\n hide={!data.some((d) => d.readiness != null)}\n />\n <YAxis\n yAxisId=\"right\"\n orientation=\"right\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={44}\n tickFormatter={(v) => `${formatNumber(Number(v))} h`}\n hide={!data.some((d) => d.sleepHours != null)}\n />\n <Tooltip\n contentStyle={TOOLTIP_STYLE}\n labelStyle={{ color: 'var(--color-text-tertiary)' }}\n formatter={(value, name) => {\n if (name === 'Readiness') return [formatNumber(Number(value)), name];\n return [`${formatNumber(Number(value))} h`, name];\n }}\n />\n <Legend wrapperStyle={{ fontSize: 12, paddingTop: 8 }} />\n <Area\n yAxisId=\"right\"\n type=\"monotone\"\n dataKey=\"sleepHours\"\n name=\"Sleep\"\n stroke={CHART_COLORS.secondary}\n strokeWidth={2}\n fill={CHART_COLORS.secondary}\n fillOpacity={0.12}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: 'var(--color-bg-surface)' }}\n connectNulls\n />\n <Line\n yAxisId=\"left\"\n type=\"monotone\"\n dataKey=\"readiness\"\n name=\"Readiness\"\n stroke={CHART_COLORS.success}\n strokeWidth={2.5}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: 'var(--color-bg-surface)' }}\n connectNulls\n />\n </ComposedChart>\n </ResponsiveContainer>\n </div>\n </ChartCard>\n );\n}\n\n// ============================================================================\n// Macros over time\n// ============================================================================\n\nexport function MacroChart({ daily }: { daily: MybInsightsDay[] }) {\n const data = useChartData(daily);\n\n if (data.length === 0) {\n return (\n <ChartCard\n title=\"Macro adherence\"\n icon={<IconChip icon={<Utensils className=\"h-4 w-4\" />} tint={CHART_COLORS.warning} />}\n >\n <EmptyChart message=\"Log meals to see macro trends.\" />\n </ChartCard>\n );\n }\n\n return (\n <ChartCard\n title=\"Macro adherence\"\n icon={<IconChip icon={<Utensils className=\"h-4 w-4\" />} tint={CHART_COLORS.warning} />}\n >\n <div className=\"h-[260px] w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={data} margin={{ top: 4, right: 16, bottom: 4, left: 4 }}>\n <CartesianGrid {...GRID_STYLE} vertical={false} />\n <XAxis\n dataKey=\"label\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n tickMargin={8}\n minTickGap={24}\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={44}\n tickFormatter={(v) => formatGrams(Number(v))}\n />\n <Tooltip\n contentStyle={TOOLTIP_STYLE}\n labelStyle={{ color: 'var(--color-text-tertiary)' }}\n formatter={(value, name) => [formatGrams(Number(value)), name as string]}\n />\n <Legend wrapperStyle={{ fontSize: 12, paddingTop: 8 }} />\n <Bar dataKey=\"proteinG\" name=\"Protein\" stackId=\"macros\" fill={MACRO_HUE.protein} />\n <Bar dataKey=\"carbsG\" name=\"Carbs\" stackId=\"macros\" fill={MACRO_HUE.carbs} />\n <Bar dataKey=\"fatG\" name=\"Fat\" stackId=\"macros\" fill={MACRO_HUE.fat} />\n </BarChart>\n </ResponsiveContainer>\n </div>\n </ChartCard>\n );\n}\n\n// ============================================================================\n// Calorie trend\n// ============================================================================\n\nexport function CalorieChart({ daily }: { daily: MybInsightsDay[] }) {\n const data = useChartData(daily);\n\n if (data.length === 0) {\n return (\n <ChartCard\n title=\"Calorie trend\"\n icon={<IconChip icon={<Scale className=\"h-4 w-4\" />} tint={CHART_COLORS.chart1} />}\n >\n <EmptyChart message=\"Log meals to see calorie trends.\" />\n </ChartCard>\n );\n }\n\n return (\n <ChartCard\n title=\"Calorie trend\"\n icon={<IconChip icon={<Scale className=\"h-4 w-4\" />} tint={CHART_COLORS.chart1} />}\n >\n <div className=\"h-[260px] w-full\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <ComposedChart data={data} margin={{ top: 4, right: 16, bottom: 4, left: 4 }}>\n <CartesianGrid {...GRID_STYLE} vertical={false} />\n <XAxis\n dataKey=\"label\"\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n tickMargin={8}\n minTickGap={24}\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={AXIS_TICK_STYLE}\n width={52}\n tickFormatter={(v) => formatKcal(Number(v))}\n />\n <Tooltip\n contentStyle={TOOLTIP_STYLE}\n labelStyle={{ color: 'var(--color-text-tertiary)' }}\n formatter={(value) => [formatKcal(Number(value)), 'Calories']}\n />\n <Area\n type=\"monotone\"\n dataKey=\"calories\"\n name=\"Calories\"\n stroke={CHART_COLORS.chart1}\n strokeWidth={2}\n fill={CHART_COLORS.chart1}\n fillOpacity={0.12}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: 'var(--color-bg-surface)' }}\n />\n </ComposedChart>\n </ResponsiveContainer>\n </div>\n </ChartCard>\n );\n}\n\n// ============================================================================\n// Correlation view\n// ============================================================================\n\ntype CorrelationPair = {\n label: string;\n x: string;\n y: string;\n r: number | null;\n n: number;\n};\n\nfunction pearson(xs: (number | null)[], ys: (number | null)[]): { r: number | null; n: number } {\n const pairs = xs\n .map((x, i) => [x, ys[i]] as const)\n .filter(([x, y]) => x != null && y != null) as [number, number][];\n if (pairs.length < 3) return { r: null, n: pairs.length };\n\n const n = pairs.length;\n const sumX = pairs.reduce((a, [x]) => a + x, 0);\n const sumY = pairs.reduce((a, [, y]) => a + y, 0);\n const sumX2 = pairs.reduce((a, [x]) => a + x * x, 0);\n const sumY2 = pairs.reduce((a, [, y]) => a + y * y, 0);\n const sumXY = pairs.reduce((a, [x, y]) => a + x * y, 0);\n\n const denom = Math.sqrt((n * sumX2 - sumX * sumX) * (n * sumY2 - sumY * sumY));\n if (!Number.isFinite(denom) || denom === 0) return { r: null, n };\n\n return { r: (n * sumXY - sumX * sumY) / denom, n };\n}\n\nfunction useCorrelations(daily: MybInsightsDay[]): CorrelationPair[] {\n return useMemo(() => {\n const readiness = daily.map((d) => d.readiness ?? null);\n const sleep = daily.map((d) => d.sleepHours ?? null);\n const volume = daily.map((d) => d.volumeKg);\n const sessions = daily.map((d) => d.sessions);\n const protein = daily.map((d) => d.proteinG);\n const calories = daily.map((d) => d.calories);\n\n const compute = (\n label: string,\n x: string,\n y: string,\n xs: (number | null)[],\n ys: (number | null)[]\n ) => {\n const { r, n } = pearson(xs, ys);\n return { label, x, y, r, n };\n };\n\n return [\n compute('Sleep → Readiness', 'Sleep', 'Readiness', sleep, readiness),\n compute('Volume → Readiness', 'Volume', 'Readiness', volume, readiness),\n compute('Sessions → Sleep', 'Sessions', 'Sleep', sessions, sleep),\n compute('Protein → Readiness', 'Protein', 'Readiness', protein, readiness),\n compute('Calories → Volume', 'Calories', 'Volume', calories, volume),\n ];\n }, [daily]);\n}\n\nfunction correlationLabel(r: number): string {\n const abs = Math.abs(r);\n if (abs >= 0.7) return 'Strong';\n if (abs >= 0.4) return 'Moderate';\n if (abs >= 0.2) return 'Weak';\n return 'None';\n}\n\nfunction correlationColor(r: number): string {\n if (r > 0) return 'var(--color-status-success-text)';\n if (r < 0) return 'var(--color-status-error-text)';\n return 'var(--color-text-tertiary)';\n}\n\nexport function CorrelationView({ daily }: { daily: MybInsightsDay[] }) {\n const correlations = useCorrelations(daily);\n const available = correlations.filter((c) => c.r != null);\n\n if (available.length === 0) {\n return (\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"flex items-center gap-2.5\">\n <IconChip icon={<Moon className=\"h-4 w-4\" />} tint={CHART_COLORS.secondary} />\n <h3 className=\"text-sm font-semibold text-text-primary\">Correlations</h3>\n </div>\n <p className=\"mt-3 text-sm text-text-secondary\">\n Log a few more recovery, training and nutrition days to surface correlations.\n </p>\n </GlassCard>\n );\n }\n\n return (\n <GlassCard treatment=\"plain\" className=\"overflow-hidden p-0\">\n <div className=\"border-b border-border-seam px-5 py-4\">\n <div className=\"flex items-center gap-2.5\">\n <IconChip icon={<Moon className=\"h-4 w-4\" />} tint={CHART_COLORS.secondary} />\n <h3 className=\"text-sm font-semibold text-text-primary\">Correlations</h3>\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n Pearson correlation across the selected range. More data gives more reliable signals.\n </p>\n </div>\n <div className=\"divide-y divide-border-seam/60\">\n {available.map((c) => (\n <div key={c.label} className=\"flex items-center justify-between px-5 py-3\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{c.label}</p>\n <p className=\"text-xs text-text-tertiary\">{c.n} days with both metrics</p>\n </div>\n <div className=\"text-right\">\n <p\n className=\"text-sm font-semibold tabular-nums\"\n style={{ color: correlationColor(c.r ?? 0) }}\n >\n {(c.r ?? 0).toFixed(2)}\n </p>\n <p className=\"text-xs text-text-tertiary\">{correlationLabel(c.r ?? 0)}</p>\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Insights — unified analytics dashboard for MyBodyShield.
3
+ * @module mybodyshield/pages/insights
4
+ *
5
+ * BOFF-4056: surfaces a 30-day rollup of training volume, sessions,
6
+ * readiness, sleep, nutrition, body weight, and active goals using the
7
+ * `mybInsights` federated query. The backend already aggregates and
8
+ * anonymizes the data; this page only renders what the member is allowed
9
+ * to see.
10
+ */
11
+ export declare function InsightsPage(): import("react").JSX.Element;
12
+ //# sourceMappingURL=InsightsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InsightsPage.d.ts","sourceRoot":"","sources":["../../../../src/mybodyshield/pages/insights/InsightsPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqEH,wBAAgB,YAAY,gCAsR3B"}