@contractspec/example.learning-journey-ui-coaching 1.57.0 → 1.58.0

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 (87) hide show
  1. package/.turbo/turbo-build.log +58 -59
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +18 -0
  4. package/dist/CoachingMiniApp.d.ts +4 -14
  5. package/dist/CoachingMiniApp.d.ts.map +1 -1
  6. package/dist/CoachingMiniApp.js +1056 -59
  7. package/dist/browser/CoachingMiniApp.js +1059 -0
  8. package/dist/browser/components/EngagementMeter.js +143 -0
  9. package/dist/browser/components/TipCard.js +89 -0
  10. package/dist/browser/components/TipFeed.js +90 -0
  11. package/dist/browser/components/index.js +320 -0
  12. package/dist/browser/docs/index.js +22 -0
  13. package/dist/browser/docs/learning-journey-ui-coaching.docblock.js +22 -0
  14. package/dist/browser/example.js +32 -0
  15. package/dist/browser/index.js +1118 -0
  16. package/dist/browser/views/Overview.js +303 -0
  17. package/dist/browser/views/Progress.js +344 -0
  18. package/dist/browser/views/Steps.js +159 -0
  19. package/dist/browser/views/Timeline.js +266 -0
  20. package/dist/browser/views/index.js +980 -0
  21. package/dist/components/EngagementMeter.d.ts +6 -15
  22. package/dist/components/EngagementMeter.d.ts.map +1 -1
  23. package/dist/components/EngagementMeter.js +143 -107
  24. package/dist/components/TipCard.d.ts +8 -18
  25. package/dist/components/TipCard.d.ts.map +1 -1
  26. package/dist/components/TipCard.js +86 -72
  27. package/dist/components/TipFeed.d.ts +7 -13
  28. package/dist/components/TipFeed.d.ts.map +1 -1
  29. package/dist/components/TipFeed.js +87 -62
  30. package/dist/components/index.d.ts +4 -4
  31. package/dist/components/index.d.ts.map +1 -0
  32. package/dist/components/index.js +320 -4
  33. package/dist/docs/index.d.ts +2 -1
  34. package/dist/docs/index.d.ts.map +1 -0
  35. package/dist/docs/index.js +23 -1
  36. package/dist/docs/learning-journey-ui-coaching.docblock.d.ts +2 -1
  37. package/dist/docs/learning-journey-ui-coaching.docblock.d.ts.map +1 -0
  38. package/dist/docs/learning-journey-ui-coaching.docblock.js +21 -18
  39. package/dist/example.d.ts +2 -6
  40. package/dist/example.d.ts.map +1 -1
  41. package/dist/example.js +31 -39
  42. package/dist/index.d.ts +6 -12
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +1119 -14
  45. package/dist/node/CoachingMiniApp.js +1059 -0
  46. package/dist/node/components/EngagementMeter.js +143 -0
  47. package/dist/node/components/TipCard.js +89 -0
  48. package/dist/node/components/TipFeed.js +90 -0
  49. package/dist/node/components/index.js +320 -0
  50. package/dist/node/docs/index.js +22 -0
  51. package/dist/node/docs/learning-journey-ui-coaching.docblock.js +22 -0
  52. package/dist/node/example.js +32 -0
  53. package/dist/node/index.js +1118 -0
  54. package/dist/node/views/Overview.js +303 -0
  55. package/dist/node/views/Progress.js +344 -0
  56. package/dist/node/views/Steps.js +159 -0
  57. package/dist/node/views/Timeline.js +266 -0
  58. package/dist/node/views/index.js +980 -0
  59. package/dist/views/Overview.d.ts +4 -13
  60. package/dist/views/Overview.d.ts.map +1 -1
  61. package/dist/views/Overview.js +301 -148
  62. package/dist/views/Progress.d.ts +3 -10
  63. package/dist/views/Progress.d.ts.map +1 -1
  64. package/dist/views/Progress.js +342 -112
  65. package/dist/views/Steps.d.ts +2 -11
  66. package/dist/views/Steps.d.ts.map +1 -1
  67. package/dist/views/Steps.js +157 -66
  68. package/dist/views/Timeline.d.ts +2 -10
  69. package/dist/views/Timeline.d.ts.map +1 -1
  70. package/dist/views/Timeline.js +264 -110
  71. package/dist/views/index.d.ts +5 -5
  72. package/dist/views/index.d.ts.map +1 -0
  73. package/dist/views/index.js +980 -5
  74. package/package.json +154 -38
  75. package/tsdown.config.js +1 -2
  76. package/.turbo/turbo-build$colon$bundle.log +0 -62
  77. package/dist/CoachingMiniApp.js.map +0 -1
  78. package/dist/components/EngagementMeter.js.map +0 -1
  79. package/dist/components/TipCard.js.map +0 -1
  80. package/dist/components/TipFeed.js.map +0 -1
  81. package/dist/docs/learning-journey-ui-coaching.docblock.js.map +0 -1
  82. package/dist/example.js.map +0 -1
  83. package/dist/views/Overview.js.map +0 -1
  84. package/dist/views/Progress.js.map +0 -1
  85. package/dist/views/Steps.js.map +0 -1
  86. package/dist/views/Timeline.js.map +0 -1
  87. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,1118 @@
1
+ // src/components/TipCard.tsx
2
+ import { Button } from "@contractspec/lib.design-system";
3
+ import { Card, CardContent } from "@contractspec/lib.ui-kit-web/ui/card";
4
+ import { cn } from "@contractspec/lib.ui-kit-web/ui/utils";
5
+ import { jsxDEV } from "react/jsx-dev-runtime";
6
+ "use client";
7
+ var TIP_ICONS = {
8
+ cash_buffer_too_high: "\uD83D\uDCB0",
9
+ no_savings_goal: "\uD83C\uDFAF",
10
+ irregular_savings: "\uD83D\uDCC5",
11
+ noise_late_evening: "\uD83D\uDD07",
12
+ guest_frequency_high: "\uD83D\uDC65",
13
+ shared_space_conflicts: "\uD83C\uDFE0",
14
+ default: "\uD83D\uDCA1"
15
+ };
16
+ function TipCard({
17
+ step,
18
+ isCompleted,
19
+ isCurrent,
20
+ onComplete,
21
+ onDismiss
22
+ }) {
23
+ const tipId = step.metadata?.tipId ?? "default";
24
+ const icon = TIP_ICONS[tipId] ?? TIP_ICONS.default;
25
+ return /* @__PURE__ */ jsxDEV(Card, {
26
+ className: cn("transition-all", isCompleted && "opacity-60", isCurrent && "ring-2 ring-amber-500"),
27
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
28
+ className: "p-4",
29
+ children: /* @__PURE__ */ jsxDEV("div", {
30
+ className: "flex gap-4",
31
+ children: [
32
+ /* @__PURE__ */ jsxDEV("div", {
33
+ className: cn("flex h-12 w-12 shrink-0 items-center justify-center rounded-xl text-2xl", isCompleted ? "bg-green-500/10" : isCurrent ? "bg-amber-500/10" : "bg-muted"),
34
+ children: isCompleted ? "✓" : icon
35
+ }, undefined, false, undefined, this),
36
+ /* @__PURE__ */ jsxDEV("div", {
37
+ className: "min-w-0 flex-1",
38
+ children: [
39
+ /* @__PURE__ */ jsxDEV("div", {
40
+ className: "flex items-start justify-between gap-2",
41
+ children: [
42
+ /* @__PURE__ */ jsxDEV("h4", {
43
+ className: "font-semibold",
44
+ children: step.title
45
+ }, undefined, false, undefined, this),
46
+ step.xpReward && /* @__PURE__ */ jsxDEV("span", {
47
+ className: cn("shrink-0 rounded-full px-2 py-0.5 text-xs font-semibold", isCompleted ? "bg-green-500/10 text-green-500" : "bg-amber-500/10 text-amber-500"),
48
+ children: [
49
+ "+",
50
+ step.xpReward,
51
+ " XP"
52
+ ]
53
+ }, undefined, true, undefined, this)
54
+ ]
55
+ }, undefined, true, undefined, this),
56
+ /* @__PURE__ */ jsxDEV("p", {
57
+ className: "text-muted-foreground mt-1 text-sm",
58
+ children: step.description
59
+ }, undefined, false, undefined, this),
60
+ !isCompleted && /* @__PURE__ */ jsxDEV("div", {
61
+ className: "mt-3 flex flex-wrap gap-2",
62
+ children: [
63
+ /* @__PURE__ */ jsxDEV(Button, {
64
+ size: "sm",
65
+ onClick: onComplete,
66
+ children: "Take Action"
67
+ }, undefined, false, undefined, this),
68
+ /* @__PURE__ */ jsxDEV(Button, {
69
+ variant: "outline",
70
+ size: "sm",
71
+ onClick: onDismiss,
72
+ children: "Dismiss"
73
+ }, undefined, false, undefined, this)
74
+ ]
75
+ }, undefined, true, undefined, this),
76
+ isCompleted && /* @__PURE__ */ jsxDEV("p", {
77
+ className: "mt-2 text-sm text-green-500",
78
+ children: "✓ Tip acknowledged"
79
+ }, undefined, false, undefined, this)
80
+ ]
81
+ }, undefined, true, undefined, this)
82
+ ]
83
+ }, undefined, true, undefined, this)
84
+ }, undefined, false, undefined, this)
85
+ }, undefined, false, undefined, this);
86
+ }
87
+
88
+ // src/views/Overview.tsx
89
+ import { Button as Button2 } from "@contractspec/lib.design-system";
90
+ import {
91
+ Card as Card2,
92
+ CardContent as CardContent2,
93
+ CardHeader,
94
+ CardTitle
95
+ } from "@contractspec/lib.ui-kit-web/ui/card";
96
+ import {
97
+ XpBar,
98
+ StreakCounter
99
+ } from "@contractspec/example.learning-journey-ui-shared";
100
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
101
+ "use client";
102
+ function Overview({
103
+ track,
104
+ progress,
105
+ onStepComplete,
106
+ onStart
107
+ }) {
108
+ const totalXp = track.totalXp ?? track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0);
109
+ const completedSteps = progress.completedStepIds.length;
110
+ const totalSteps = track.steps.length;
111
+ const pendingSteps = totalSteps - completedSteps;
112
+ const activeTips = track.steps.filter((s) => !progress.completedStepIds.includes(s.id)).slice(0, 3);
113
+ return /* @__PURE__ */ jsxDEV2("div", {
114
+ className: "space-y-6",
115
+ children: [
116
+ /* @__PURE__ */ jsxDEV2(Card2, {
117
+ className: "overflow-hidden bg-gradient-to-br from-amber-500/10 via-orange-500/10 to-red-500/10",
118
+ children: /* @__PURE__ */ jsxDEV2(CardContent2, {
119
+ className: "p-6",
120
+ children: /* @__PURE__ */ jsxDEV2("div", {
121
+ className: "flex flex-col items-center gap-4 text-center md:flex-row md:text-left",
122
+ children: [
123
+ /* @__PURE__ */ jsxDEV2("div", {
124
+ className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-amber-500 to-orange-600 text-3xl shadow-lg",
125
+ children: "\uD83D\uDCA1"
126
+ }, undefined, false, undefined, this),
127
+ /* @__PURE__ */ jsxDEV2("div", {
128
+ className: "flex-1",
129
+ children: [
130
+ /* @__PURE__ */ jsxDEV2("h1", {
131
+ className: "text-2xl font-bold",
132
+ children: track.name
133
+ }, undefined, false, undefined, this),
134
+ /* @__PURE__ */ jsxDEV2("p", {
135
+ className: "text-muted-foreground mt-1",
136
+ children: track.description
137
+ }, undefined, false, undefined, this)
138
+ ]
139
+ }, undefined, true, undefined, this),
140
+ /* @__PURE__ */ jsxDEV2("div", {
141
+ className: "flex items-center gap-4",
142
+ children: /* @__PURE__ */ jsxDEV2(StreakCounter, {
143
+ days: progress.streakDays,
144
+ size: "lg"
145
+ }, undefined, false, undefined, this)
146
+ }, undefined, false, undefined, this)
147
+ ]
148
+ }, undefined, true, undefined, this)
149
+ }, undefined, false, undefined, this)
150
+ }, undefined, false, undefined, this),
151
+ /* @__PURE__ */ jsxDEV2("div", {
152
+ className: "grid gap-4 md:grid-cols-3",
153
+ children: [
154
+ /* @__PURE__ */ jsxDEV2(Card2, {
155
+ children: [
156
+ /* @__PURE__ */ jsxDEV2(CardHeader, {
157
+ className: "pb-2",
158
+ children: /* @__PURE__ */ jsxDEV2(CardTitle, {
159
+ className: "text-muted-foreground text-sm font-medium",
160
+ children: "Active Tips"
161
+ }, undefined, false, undefined, this)
162
+ }, undefined, false, undefined, this),
163
+ /* @__PURE__ */ jsxDEV2(CardContent2, {
164
+ children: [
165
+ /* @__PURE__ */ jsxDEV2("div", {
166
+ className: "text-3xl font-bold text-amber-500",
167
+ children: pendingSteps
168
+ }, undefined, false, undefined, this),
169
+ /* @__PURE__ */ jsxDEV2("p", {
170
+ className: "text-muted-foreground text-sm",
171
+ children: "tips for you today"
172
+ }, undefined, false, undefined, this)
173
+ ]
174
+ }, undefined, true, undefined, this)
175
+ ]
176
+ }, undefined, true, undefined, this),
177
+ /* @__PURE__ */ jsxDEV2(Card2, {
178
+ children: [
179
+ /* @__PURE__ */ jsxDEV2(CardHeader, {
180
+ className: "pb-2",
181
+ children: /* @__PURE__ */ jsxDEV2(CardTitle, {
182
+ className: "text-muted-foreground text-sm font-medium",
183
+ children: "Tips Actioned"
184
+ }, undefined, false, undefined, this)
185
+ }, undefined, false, undefined, this),
186
+ /* @__PURE__ */ jsxDEV2(CardContent2, {
187
+ children: [
188
+ /* @__PURE__ */ jsxDEV2("div", {
189
+ className: "text-3xl font-bold text-green-500",
190
+ children: completedSteps
191
+ }, undefined, false, undefined, this),
192
+ /* @__PURE__ */ jsxDEV2("p", {
193
+ className: "text-muted-foreground text-sm",
194
+ children: [
195
+ "out of ",
196
+ totalSteps,
197
+ " total"
198
+ ]
199
+ }, undefined, true, undefined, this)
200
+ ]
201
+ }, undefined, true, undefined, this)
202
+ ]
203
+ }, undefined, true, undefined, this),
204
+ /* @__PURE__ */ jsxDEV2(Card2, {
205
+ children: [
206
+ /* @__PURE__ */ jsxDEV2(CardHeader, {
207
+ className: "pb-2",
208
+ children: /* @__PURE__ */ jsxDEV2(CardTitle, {
209
+ className: "text-muted-foreground text-sm font-medium",
210
+ children: "XP Earned"
211
+ }, undefined, false, undefined, this)
212
+ }, undefined, false, undefined, this),
213
+ /* @__PURE__ */ jsxDEV2(CardContent2, {
214
+ children: [
215
+ /* @__PURE__ */ jsxDEV2("div", {
216
+ className: "text-3xl font-bold text-orange-500",
217
+ children: progress.xpEarned
218
+ }, undefined, false, undefined, this),
219
+ /* @__PURE__ */ jsxDEV2(XpBar, {
220
+ current: progress.xpEarned,
221
+ max: totalXp,
222
+ showLabel: false,
223
+ size: "sm"
224
+ }, undefined, false, undefined, this)
225
+ ]
226
+ }, undefined, true, undefined, this)
227
+ ]
228
+ }, undefined, true, undefined, this)
229
+ ]
230
+ }, undefined, true, undefined, this),
231
+ activeTips.length > 0 && /* @__PURE__ */ jsxDEV2(Card2, {
232
+ children: [
233
+ /* @__PURE__ */ jsxDEV2(CardHeader, {
234
+ className: "flex flex-row items-center justify-between",
235
+ children: [
236
+ /* @__PURE__ */ jsxDEV2(CardTitle, {
237
+ className: "flex items-center gap-2",
238
+ children: [
239
+ /* @__PURE__ */ jsxDEV2("span", {
240
+ children: "\uD83D\uDCA1"
241
+ }, undefined, false, undefined, this),
242
+ /* @__PURE__ */ jsxDEV2("span", {
243
+ children: "Tips for You"
244
+ }, undefined, false, undefined, this)
245
+ ]
246
+ }, undefined, true, undefined, this),
247
+ activeTips.length < pendingSteps && /* @__PURE__ */ jsxDEV2(Button2, {
248
+ variant: "outline",
249
+ size: "sm",
250
+ onClick: onStart,
251
+ children: [
252
+ "View All (",
253
+ pendingSteps,
254
+ ")"
255
+ ]
256
+ }, undefined, true, undefined, this)
257
+ ]
258
+ }, undefined, true, undefined, this),
259
+ /* @__PURE__ */ jsxDEV2(CardContent2, {
260
+ className: "space-y-3",
261
+ children: activeTips.map((step) => /* @__PURE__ */ jsxDEV2(TipCard, {
262
+ step,
263
+ isCompleted: false,
264
+ isCurrent: step.id === activeTips[0]?.id,
265
+ onComplete: () => onStepComplete?.(step.id)
266
+ }, step.id, false, undefined, this))
267
+ }, undefined, false, undefined, this)
268
+ ]
269
+ }, undefined, true, undefined, this),
270
+ pendingSteps === 0 && /* @__PURE__ */ jsxDEV2(Card2, {
271
+ className: "border-green-500/50 bg-green-500/5",
272
+ children: /* @__PURE__ */ jsxDEV2(CardContent2, {
273
+ className: "flex items-center gap-4 p-6",
274
+ children: [
275
+ /* @__PURE__ */ jsxDEV2("div", {
276
+ className: "text-4xl",
277
+ children: "\uD83C\uDF89"
278
+ }, undefined, false, undefined, this),
279
+ /* @__PURE__ */ jsxDEV2("div", {
280
+ children: [
281
+ /* @__PURE__ */ jsxDEV2("h3", {
282
+ className: "text-lg font-semibold text-green-500",
283
+ children: "All Tips Actioned!"
284
+ }, undefined, false, undefined, this),
285
+ /* @__PURE__ */ jsxDEV2("p", {
286
+ className: "text-muted-foreground",
287
+ children: [
288
+ "Great job! You've addressed all ",
289
+ totalSteps,
290
+ " coaching tips."
291
+ ]
292
+ }, undefined, true, undefined, this)
293
+ ]
294
+ }, undefined, true, undefined, this)
295
+ ]
296
+ }, undefined, true, undefined, this)
297
+ }, undefined, false, undefined, this)
298
+ ]
299
+ }, undefined, true, undefined, this);
300
+ }
301
+
302
+ // src/views/Steps.tsx
303
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
304
+ "use client";
305
+ function Steps({ track, progress, onStepComplete }) {
306
+ const completedSteps = progress.completedStepIds.length;
307
+ const totalSteps = track.steps.length;
308
+ const sortedSteps = [...track.steps].sort((a, b) => {
309
+ const aCompleted = progress.completedStepIds.includes(a.id);
310
+ const bCompleted = progress.completedStepIds.includes(b.id);
311
+ if (aCompleted === bCompleted)
312
+ return 0;
313
+ return aCompleted ? 1 : -1;
314
+ });
315
+ const currentStepId = track.steps.find((s) => !progress.completedStepIds.includes(s.id))?.id;
316
+ return /* @__PURE__ */ jsxDEV3("div", {
317
+ className: "space-y-6",
318
+ children: [
319
+ /* @__PURE__ */ jsxDEV3("div", {
320
+ className: "text-center",
321
+ children: [
322
+ /* @__PURE__ */ jsxDEV3("h2", {
323
+ className: "text-xl font-bold",
324
+ children: "Coaching Tips"
325
+ }, undefined, false, undefined, this),
326
+ /* @__PURE__ */ jsxDEV3("p", {
327
+ className: "text-muted-foreground",
328
+ children: "Review and take action on personalized tips"
329
+ }, undefined, false, undefined, this),
330
+ /* @__PURE__ */ jsxDEV3("p", {
331
+ className: "text-muted-foreground mt-2 text-sm",
332
+ children: [
333
+ completedSteps,
334
+ " of ",
335
+ totalSteps,
336
+ " tips actioned"
337
+ ]
338
+ }, undefined, true, undefined, this)
339
+ ]
340
+ }, undefined, true, undefined, this),
341
+ /* @__PURE__ */ jsxDEV3("div", {
342
+ className: "space-y-3",
343
+ children: sortedSteps.map((step) => {
344
+ const isCompleted = progress.completedStepIds.includes(step.id);
345
+ const isCurrent = step.id === currentStepId;
346
+ return /* @__PURE__ */ jsxDEV3(TipCard, {
347
+ step,
348
+ isCompleted,
349
+ isCurrent,
350
+ onComplete: () => onStepComplete?.(step.id),
351
+ onDismiss: () => onStepComplete?.(step.id)
352
+ }, step.id, false, undefined, this);
353
+ })
354
+ }, undefined, false, undefined, this),
355
+ completedSteps === totalSteps && /* @__PURE__ */ jsxDEV3("div", {
356
+ className: "text-muted-foreground text-center",
357
+ children: [
358
+ /* @__PURE__ */ jsxDEV3("span", {
359
+ className: "text-2xl",
360
+ children: "✨"
361
+ }, undefined, false, undefined, this),
362
+ /* @__PURE__ */ jsxDEV3("p", {
363
+ className: "mt-2",
364
+ children: "All tips have been addressed!"
365
+ }, undefined, false, undefined, this)
366
+ ]
367
+ }, undefined, true, undefined, this)
368
+ ]
369
+ }, undefined, true, undefined, this);
370
+ }
371
+
372
+ // src/components/EngagementMeter.tsx
373
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
374
+ "use client";
375
+ function EngagementMeter({
376
+ acknowledged,
377
+ actioned,
378
+ pending,
379
+ streak = 0
380
+ }) {
381
+ const total = acknowledged + actioned + pending;
382
+ const actionedPercent = total > 0 ? actioned / total * 100 : 0;
383
+ const acknowledgedPercent = total > 0 ? acknowledged / total * 100 : 0;
384
+ return /* @__PURE__ */ jsxDEV4("div", {
385
+ className: "space-y-4",
386
+ children: [
387
+ /* @__PURE__ */ jsxDEV4("div", {
388
+ className: "flex items-center justify-center",
389
+ children: /* @__PURE__ */ jsxDEV4("div", {
390
+ className: "relative h-32 w-32",
391
+ children: [
392
+ /* @__PURE__ */ jsxDEV4("svg", {
393
+ className: "h-full w-full -rotate-90",
394
+ viewBox: "0 0 100 100",
395
+ children: [
396
+ /* @__PURE__ */ jsxDEV4("circle", {
397
+ cx: "50",
398
+ cy: "50",
399
+ r: "40",
400
+ fill: "none",
401
+ strokeWidth: "12",
402
+ className: "stroke-muted"
403
+ }, undefined, false, undefined, this),
404
+ /* @__PURE__ */ jsxDEV4("circle", {
405
+ cx: "50",
406
+ cy: "50",
407
+ r: "40",
408
+ fill: "none",
409
+ strokeWidth: "12",
410
+ strokeLinecap: "round",
411
+ strokeDasharray: `${actionedPercent * 2.51} 251`,
412
+ className: "stroke-green-500 transition-all duration-500"
413
+ }, undefined, false, undefined, this),
414
+ /* @__PURE__ */ jsxDEV4("circle", {
415
+ cx: "50",
416
+ cy: "50",
417
+ r: "40",
418
+ fill: "none",
419
+ strokeWidth: "12",
420
+ strokeLinecap: "round",
421
+ strokeDasharray: `${acknowledgedPercent * 2.51} 251`,
422
+ strokeDashoffset: `${-actionedPercent * 2.51}`,
423
+ className: "stroke-amber-500 transition-all duration-500"
424
+ }, undefined, false, undefined, this)
425
+ ]
426
+ }, undefined, true, undefined, this),
427
+ /* @__PURE__ */ jsxDEV4("div", {
428
+ className: "absolute inset-0 flex flex-col items-center justify-center",
429
+ children: [
430
+ /* @__PURE__ */ jsxDEV4("span", {
431
+ className: "text-2xl font-bold",
432
+ children: total
433
+ }, undefined, false, undefined, this),
434
+ /* @__PURE__ */ jsxDEV4("span", {
435
+ className: "text-muted-foreground text-xs",
436
+ children: "tips"
437
+ }, undefined, false, undefined, this)
438
+ ]
439
+ }, undefined, true, undefined, this)
440
+ ]
441
+ }, undefined, true, undefined, this)
442
+ }, undefined, false, undefined, this),
443
+ /* @__PURE__ */ jsxDEV4("div", {
444
+ className: "flex justify-center gap-4 text-sm",
445
+ children: [
446
+ /* @__PURE__ */ jsxDEV4("div", {
447
+ className: "flex items-center gap-1.5",
448
+ children: [
449
+ /* @__PURE__ */ jsxDEV4("div", {
450
+ className: "h-3 w-3 rounded-full bg-green-500"
451
+ }, undefined, false, undefined, this),
452
+ /* @__PURE__ */ jsxDEV4("span", {
453
+ children: [
454
+ "Actioned (",
455
+ actioned,
456
+ ")"
457
+ ]
458
+ }, undefined, true, undefined, this)
459
+ ]
460
+ }, undefined, true, undefined, this),
461
+ /* @__PURE__ */ jsxDEV4("div", {
462
+ className: "flex items-center gap-1.5",
463
+ children: [
464
+ /* @__PURE__ */ jsxDEV4("div", {
465
+ className: "h-3 w-3 rounded-full bg-amber-500"
466
+ }, undefined, false, undefined, this),
467
+ /* @__PURE__ */ jsxDEV4("span", {
468
+ children: [
469
+ "Acknowledged (",
470
+ acknowledged,
471
+ ")"
472
+ ]
473
+ }, undefined, true, undefined, this)
474
+ ]
475
+ }, undefined, true, undefined, this),
476
+ /* @__PURE__ */ jsxDEV4("div", {
477
+ className: "flex items-center gap-1.5",
478
+ children: [
479
+ /* @__PURE__ */ jsxDEV4("div", {
480
+ className: "bg-muted h-3 w-3 rounded-full"
481
+ }, undefined, false, undefined, this),
482
+ /* @__PURE__ */ jsxDEV4("span", {
483
+ children: [
484
+ "Pending (",
485
+ pending,
486
+ ")"
487
+ ]
488
+ }, undefined, true, undefined, this)
489
+ ]
490
+ }, undefined, true, undefined, this)
491
+ ]
492
+ }, undefined, true, undefined, this),
493
+ streak > 0 && /* @__PURE__ */ jsxDEV4("div", {
494
+ className: "flex items-center justify-center gap-2 rounded-lg bg-orange-500/10 px-4 py-2",
495
+ children: [
496
+ /* @__PURE__ */ jsxDEV4("span", {
497
+ className: "text-xl",
498
+ children: "\uD83D\uDD25"
499
+ }, undefined, false, undefined, this),
500
+ /* @__PURE__ */ jsxDEV4("span", {
501
+ className: "font-semibold text-orange-500",
502
+ children: [
503
+ streak,
504
+ " day engagement streak!"
505
+ ]
506
+ }, undefined, true, undefined, this)
507
+ ]
508
+ }, undefined, true, undefined, this)
509
+ ]
510
+ }, undefined, true, undefined, this);
511
+ }
512
+
513
+ // src/views/Progress.tsx
514
+ import {
515
+ Card as Card3,
516
+ CardContent as CardContent3,
517
+ CardHeader as CardHeader2,
518
+ CardTitle as CardTitle2
519
+ } from "@contractspec/lib.ui-kit-web/ui/card";
520
+ import {
521
+ XpBar as XpBar2,
522
+ BadgeDisplay,
523
+ StreakCounter as StreakCounter2
524
+ } from "@contractspec/example.learning-journey-ui-shared";
525
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
526
+ "use client";
527
+ function ProgressView({ track, progress }) {
528
+ const totalXp = track.totalXp ?? track.steps.reduce((sum, s) => sum + (s.xpReward ?? 0), 0);
529
+ const completedSteps = progress.completedStepIds.length;
530
+ const totalSteps = track.steps.length;
531
+ const pendingSteps = totalSteps - completedSteps;
532
+ const actioned = Math.floor(completedSteps * 0.7);
533
+ const acknowledged = completedSteps - actioned;
534
+ return /* @__PURE__ */ jsxDEV5("div", {
535
+ className: "space-y-6",
536
+ children: [
537
+ /* @__PURE__ */ jsxDEV5(Card3, {
538
+ children: [
539
+ /* @__PURE__ */ jsxDEV5(CardHeader2, {
540
+ children: /* @__PURE__ */ jsxDEV5(CardTitle2, {
541
+ className: "flex items-center gap-2",
542
+ children: [
543
+ /* @__PURE__ */ jsxDEV5("span", {
544
+ children: "\uD83D\uDCCA"
545
+ }, undefined, false, undefined, this),
546
+ /* @__PURE__ */ jsxDEV5("span", {
547
+ children: "Engagement Overview"
548
+ }, undefined, false, undefined, this)
549
+ ]
550
+ }, undefined, true, undefined, this)
551
+ }, undefined, false, undefined, this),
552
+ /* @__PURE__ */ jsxDEV5(CardContent3, {
553
+ children: /* @__PURE__ */ jsxDEV5(EngagementMeter, {
554
+ actioned,
555
+ acknowledged,
556
+ pending: pendingSteps,
557
+ streak: progress.streakDays
558
+ }, undefined, false, undefined, this)
559
+ }, undefined, false, undefined, this)
560
+ ]
561
+ }, undefined, true, undefined, this),
562
+ /* @__PURE__ */ jsxDEV5("div", {
563
+ className: "grid gap-4 md:grid-cols-2",
564
+ children: [
565
+ /* @__PURE__ */ jsxDEV5(Card3, {
566
+ children: [
567
+ /* @__PURE__ */ jsxDEV5(CardHeader2, {
568
+ className: "pb-2",
569
+ children: /* @__PURE__ */ jsxDEV5(CardTitle2, {
570
+ className: "text-muted-foreground text-sm font-medium",
571
+ children: "XP Earned"
572
+ }, undefined, false, undefined, this)
573
+ }, undefined, false, undefined, this),
574
+ /* @__PURE__ */ jsxDEV5(CardContent3, {
575
+ className: "space-y-3",
576
+ children: [
577
+ /* @__PURE__ */ jsxDEV5("div", {
578
+ className: "flex items-baseline gap-2",
579
+ children: [
580
+ /* @__PURE__ */ jsxDEV5("span", {
581
+ className: "text-3xl font-bold text-orange-500",
582
+ children: progress.xpEarned
583
+ }, undefined, false, undefined, this),
584
+ /* @__PURE__ */ jsxDEV5("span", {
585
+ className: "text-muted-foreground",
586
+ children: [
587
+ "/ ",
588
+ totalXp,
589
+ " XP"
590
+ ]
591
+ }, undefined, true, undefined, this)
592
+ ]
593
+ }, undefined, true, undefined, this),
594
+ /* @__PURE__ */ jsxDEV5(XpBar2, {
595
+ current: progress.xpEarned,
596
+ max: totalXp,
597
+ showLabel: false,
598
+ size: "lg"
599
+ }, undefined, false, undefined, this)
600
+ ]
601
+ }, undefined, true, undefined, this)
602
+ ]
603
+ }, undefined, true, undefined, this),
604
+ /* @__PURE__ */ jsxDEV5(Card3, {
605
+ children: [
606
+ /* @__PURE__ */ jsxDEV5(CardHeader2, {
607
+ className: "pb-2",
608
+ children: /* @__PURE__ */ jsxDEV5(CardTitle2, {
609
+ className: "text-muted-foreground text-sm font-medium",
610
+ children: "Engagement Streak"
611
+ }, undefined, false, undefined, this)
612
+ }, undefined, false, undefined, this),
613
+ /* @__PURE__ */ jsxDEV5(CardContent3, {
614
+ children: /* @__PURE__ */ jsxDEV5("div", {
615
+ className: "flex items-center gap-4",
616
+ children: [
617
+ /* @__PURE__ */ jsxDEV5(StreakCounter2, {
618
+ days: progress.streakDays,
619
+ size: "lg"
620
+ }, undefined, false, undefined, this),
621
+ /* @__PURE__ */ jsxDEV5("div", {
622
+ className: "text-muted-foreground text-sm",
623
+ children: progress.streakDays > 0 ? "Keep going!" : "Start your streak today!"
624
+ }, undefined, false, undefined, this)
625
+ ]
626
+ }, undefined, true, undefined, this)
627
+ }, undefined, false, undefined, this)
628
+ ]
629
+ }, undefined, true, undefined, this)
630
+ ]
631
+ }, undefined, true, undefined, this),
632
+ /* @__PURE__ */ jsxDEV5(Card3, {
633
+ children: [
634
+ /* @__PURE__ */ jsxDEV5(CardHeader2, {
635
+ children: /* @__PURE__ */ jsxDEV5(CardTitle2, {
636
+ className: "flex items-center gap-2",
637
+ children: [
638
+ /* @__PURE__ */ jsxDEV5("span", {
639
+ children: "\uD83C\uDFC5"
640
+ }, undefined, false, undefined, this),
641
+ /* @__PURE__ */ jsxDEV5("span", {
642
+ children: "Achievements"
643
+ }, undefined, false, undefined, this)
644
+ ]
645
+ }, undefined, true, undefined, this)
646
+ }, undefined, false, undefined, this),
647
+ /* @__PURE__ */ jsxDEV5(CardContent3, {
648
+ children: [
649
+ /* @__PURE__ */ jsxDEV5(BadgeDisplay, {
650
+ badges: progress.badges,
651
+ size: "lg",
652
+ maxVisible: 10
653
+ }, undefined, false, undefined, this),
654
+ progress.badges.length === 0 && /* @__PURE__ */ jsxDEV5("p", {
655
+ className: "text-muted-foreground text-sm",
656
+ children: "Action tips to unlock achievements!"
657
+ }, undefined, false, undefined, this)
658
+ ]
659
+ }, undefined, true, undefined, this)
660
+ ]
661
+ }, undefined, true, undefined, this),
662
+ /* @__PURE__ */ jsxDEV5(Card3, {
663
+ children: [
664
+ /* @__PURE__ */ jsxDEV5(CardHeader2, {
665
+ children: /* @__PURE__ */ jsxDEV5(CardTitle2, {
666
+ className: "flex items-center gap-2",
667
+ children: [
668
+ /* @__PURE__ */ jsxDEV5("span", {
669
+ children: "\uD83D\uDCA1"
670
+ }, undefined, false, undefined, this),
671
+ /* @__PURE__ */ jsxDEV5("span", {
672
+ children: "Tip Status"
673
+ }, undefined, false, undefined, this)
674
+ ]
675
+ }, undefined, true, undefined, this)
676
+ }, undefined, false, undefined, this),
677
+ /* @__PURE__ */ jsxDEV5(CardContent3, {
678
+ children: /* @__PURE__ */ jsxDEV5("div", {
679
+ className: "space-y-3",
680
+ children: track.steps.map((step) => {
681
+ const isCompleted = progress.completedStepIds.includes(step.id);
682
+ return /* @__PURE__ */ jsxDEV5("div", {
683
+ className: "flex items-center justify-between rounded-lg border p-3",
684
+ children: [
685
+ /* @__PURE__ */ jsxDEV5("div", {
686
+ className: "flex items-center gap-3",
687
+ children: [
688
+ /* @__PURE__ */ jsxDEV5("span", {
689
+ className: isCompleted ? "text-green-500" : "text-amber-500",
690
+ children: isCompleted ? "✓" : "○"
691
+ }, undefined, false, undefined, this),
692
+ /* @__PURE__ */ jsxDEV5("span", {
693
+ className: isCompleted ? "text-muted-foreground" : "text-foreground",
694
+ children: step.title
695
+ }, undefined, false, undefined, this)
696
+ ]
697
+ }, undefined, true, undefined, this),
698
+ /* @__PURE__ */ jsxDEV5("span", {
699
+ className: `text-sm ${isCompleted ? "text-green-500" : "text-muted-foreground"}`,
700
+ children: isCompleted ? "Actioned" : "Pending"
701
+ }, undefined, false, undefined, this)
702
+ ]
703
+ }, step.id, true, undefined, this);
704
+ })
705
+ }, undefined, false, undefined, this)
706
+ }, undefined, false, undefined, this)
707
+ ]
708
+ }, undefined, true, undefined, this)
709
+ ]
710
+ }, undefined, true, undefined, this);
711
+ }
712
+ // src/components/TipFeed.tsx
713
+ import { cn as cn2 } from "@contractspec/lib.ui-kit-web/ui/utils";
714
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
715
+ "use client";
716
+ var TIP_ICONS2 = {
717
+ cash_buffer_too_high: "\uD83D\uDCB0",
718
+ no_savings_goal: "\uD83C\uDFAF",
719
+ irregular_savings: "\uD83D\uDCC5",
720
+ noise_late_evening: "\uD83D\uDD07",
721
+ guest_frequency_high: "\uD83D\uDC65",
722
+ shared_space_conflicts: "\uD83C\uDFE0",
723
+ default: "\uD83D\uDCA1"
724
+ };
725
+ function TipFeed({ items }) {
726
+ if (items.length === 0) {
727
+ return /* @__PURE__ */ jsxDEV6("div", {
728
+ className: "text-muted-foreground py-8 text-center",
729
+ children: "No tips yet. Start engaging with coaching tips!"
730
+ }, undefined, false, undefined, this);
731
+ }
732
+ return /* @__PURE__ */ jsxDEV6("div", {
733
+ className: "relative",
734
+ children: [
735
+ /* @__PURE__ */ jsxDEV6("div", {
736
+ className: "bg-border absolute top-0 left-4 h-full w-0.5"
737
+ }, undefined, false, undefined, this),
738
+ /* @__PURE__ */ jsxDEV6("div", {
739
+ className: "space-y-4",
740
+ children: items.map((item) => {
741
+ const tipId = item.step.metadata?.tipId ?? "default";
742
+ const icon = TIP_ICONS2[tipId] ?? TIP_ICONS2.default;
743
+ return /* @__PURE__ */ jsxDEV6("div", {
744
+ className: "relative flex gap-4 pl-2",
745
+ children: [
746
+ /* @__PURE__ */ jsxDEV6("div", {
747
+ className: cn2("relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm", item.isCompleted ? "bg-green-500 text-white" : "bg-muted text-muted-foreground"),
748
+ children: item.isCompleted ? "✓" : icon
749
+ }, undefined, false, undefined, this),
750
+ /* @__PURE__ */ jsxDEV6("div", {
751
+ className: "bg-card flex-1 rounded-lg border p-3",
752
+ children: [
753
+ /* @__PURE__ */ jsxDEV6("div", {
754
+ className: "flex items-start justify-between gap-2",
755
+ children: [
756
+ /* @__PURE__ */ jsxDEV6("div", {
757
+ children: [
758
+ /* @__PURE__ */ jsxDEV6("p", {
759
+ className: "font-medium",
760
+ children: item.step.title
761
+ }, undefined, false, undefined, this),
762
+ /* @__PURE__ */ jsxDEV6("p", {
763
+ className: "text-muted-foreground mt-0.5 text-sm",
764
+ children: item.step.description
765
+ }, undefined, false, undefined, this)
766
+ ]
767
+ }, undefined, true, undefined, this),
768
+ item.step.xpReward && /* @__PURE__ */ jsxDEV6("span", {
769
+ className: cn2("shrink-0 text-xs font-medium", item.isCompleted ? "text-green-500" : "text-muted-foreground"),
770
+ children: [
771
+ "+",
772
+ item.step.xpReward,
773
+ " XP"
774
+ ]
775
+ }, undefined, true, undefined, this)
776
+ ]
777
+ }, undefined, true, undefined, this),
778
+ /* @__PURE__ */ jsxDEV6("div", {
779
+ className: "text-muted-foreground mt-2 flex items-center gap-2 text-xs",
780
+ children: item.isCompleted ? /* @__PURE__ */ jsxDEV6("span", {
781
+ className: "text-green-500",
782
+ children: [
783
+ "✓ Completed",
784
+ item.completedAt && ` • ${item.completedAt}`
785
+ ]
786
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV6("span", {
787
+ children: "Pending action"
788
+ }, undefined, false, undefined, this)
789
+ }, undefined, false, undefined, this)
790
+ ]
791
+ }, undefined, true, undefined, this)
792
+ ]
793
+ }, item.step.id, true, undefined, this);
794
+ })
795
+ }, undefined, false, undefined, this)
796
+ ]
797
+ }, undefined, true, undefined, this);
798
+ }
799
+
800
+ // src/views/Timeline.tsx
801
+ import {
802
+ Card as Card4,
803
+ CardContent as CardContent4,
804
+ CardHeader as CardHeader3,
805
+ CardTitle as CardTitle3
806
+ } from "@contractspec/lib.ui-kit-web/ui/card";
807
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
808
+ "use client";
809
+ function Timeline({ track, progress }) {
810
+ const feedItems = track.steps.map((step) => ({
811
+ step,
812
+ isCompleted: progress.completedStepIds.includes(step.id),
813
+ completedAt: progress.completedStepIds.includes(step.id) ? "Recently" : undefined
814
+ })).sort((a, b) => {
815
+ if (a.isCompleted && !b.isCompleted)
816
+ return -1;
817
+ if (!a.isCompleted && b.isCompleted)
818
+ return 1;
819
+ return 0;
820
+ });
821
+ const completedCount = feedItems.filter((f) => f.isCompleted).length;
822
+ const pendingCount = feedItems.length - completedCount;
823
+ return /* @__PURE__ */ jsxDEV7("div", {
824
+ className: "space-y-6",
825
+ children: [
826
+ /* @__PURE__ */ jsxDEV7("div", {
827
+ className: "text-center",
828
+ children: [
829
+ /* @__PURE__ */ jsxDEV7("h2", {
830
+ className: "text-xl font-bold",
831
+ children: "Activity Timeline"
832
+ }, undefined, false, undefined, this),
833
+ /* @__PURE__ */ jsxDEV7("p", {
834
+ className: "text-muted-foreground",
835
+ children: "Your coaching journey and tip history"
836
+ }, undefined, false, undefined, this)
837
+ ]
838
+ }, undefined, true, undefined, this),
839
+ /* @__PURE__ */ jsxDEV7("div", {
840
+ className: "grid grid-cols-2 gap-4",
841
+ children: [
842
+ /* @__PURE__ */ jsxDEV7(Card4, {
843
+ children: /* @__PURE__ */ jsxDEV7(CardContent4, {
844
+ className: "p-4 text-center",
845
+ children: [
846
+ /* @__PURE__ */ jsxDEV7("div", {
847
+ className: "text-2xl font-bold text-green-500",
848
+ children: completedCount
849
+ }, undefined, false, undefined, this),
850
+ /* @__PURE__ */ jsxDEV7("div", {
851
+ className: "text-muted-foreground text-sm",
852
+ children: "Tips Actioned"
853
+ }, undefined, false, undefined, this)
854
+ ]
855
+ }, undefined, true, undefined, this)
856
+ }, undefined, false, undefined, this),
857
+ /* @__PURE__ */ jsxDEV7(Card4, {
858
+ children: /* @__PURE__ */ jsxDEV7(CardContent4, {
859
+ className: "p-4 text-center",
860
+ children: [
861
+ /* @__PURE__ */ jsxDEV7("div", {
862
+ className: "text-2xl font-bold text-amber-500",
863
+ children: pendingCount
864
+ }, undefined, false, undefined, this),
865
+ /* @__PURE__ */ jsxDEV7("div", {
866
+ className: "text-muted-foreground text-sm",
867
+ children: "Tips Pending"
868
+ }, undefined, false, undefined, this)
869
+ ]
870
+ }, undefined, true, undefined, this)
871
+ }, undefined, false, undefined, this)
872
+ ]
873
+ }, undefined, true, undefined, this),
874
+ /* @__PURE__ */ jsxDEV7(Card4, {
875
+ children: [
876
+ /* @__PURE__ */ jsxDEV7(CardHeader3, {
877
+ children: /* @__PURE__ */ jsxDEV7(CardTitle3, {
878
+ className: "flex items-center gap-2",
879
+ children: [
880
+ /* @__PURE__ */ jsxDEV7("span", {
881
+ children: "\uD83D\uDCDD"
882
+ }, undefined, false, undefined, this),
883
+ /* @__PURE__ */ jsxDEV7("span", {
884
+ children: "Coaching Feed"
885
+ }, undefined, false, undefined, this)
886
+ ]
887
+ }, undefined, true, undefined, this)
888
+ }, undefined, false, undefined, this),
889
+ /* @__PURE__ */ jsxDEV7(CardContent4, {
890
+ children: /* @__PURE__ */ jsxDEV7(TipFeed, {
891
+ items: feedItems
892
+ }, undefined, false, undefined, this)
893
+ }, undefined, false, undefined, this)
894
+ ]
895
+ }, undefined, true, undefined, this),
896
+ /* @__PURE__ */ jsxDEV7(Card4, {
897
+ children: [
898
+ /* @__PURE__ */ jsxDEV7(CardHeader3, {
899
+ children: /* @__PURE__ */ jsxDEV7(CardTitle3, {
900
+ className: "flex items-center gap-2",
901
+ children: [
902
+ /* @__PURE__ */ jsxDEV7("span", {
903
+ children: "\uD83D\uDCC8"
904
+ }, undefined, false, undefined, this),
905
+ /* @__PURE__ */ jsxDEV7("span", {
906
+ children: "Journey Stats"
907
+ }, undefined, false, undefined, this)
908
+ ]
909
+ }, undefined, true, undefined, this)
910
+ }, undefined, false, undefined, this),
911
+ /* @__PURE__ */ jsxDEV7(CardContent4, {
912
+ children: /* @__PURE__ */ jsxDEV7("div", {
913
+ className: "space-y-4",
914
+ children: [
915
+ /* @__PURE__ */ jsxDEV7("div", {
916
+ className: "flex items-center justify-between",
917
+ children: [
918
+ /* @__PURE__ */ jsxDEV7("span", {
919
+ className: "text-muted-foreground",
920
+ children: "Total Tips"
921
+ }, undefined, false, undefined, this),
922
+ /* @__PURE__ */ jsxDEV7("span", {
923
+ className: "font-semibold",
924
+ children: track.steps.length
925
+ }, undefined, false, undefined, this)
926
+ ]
927
+ }, undefined, true, undefined, this),
928
+ /* @__PURE__ */ jsxDEV7("div", {
929
+ className: "flex items-center justify-between",
930
+ children: [
931
+ /* @__PURE__ */ jsxDEV7("span", {
932
+ className: "text-muted-foreground",
933
+ children: "Completed"
934
+ }, undefined, false, undefined, this),
935
+ /* @__PURE__ */ jsxDEV7("span", {
936
+ className: "font-semibold text-green-500",
937
+ children: completedCount
938
+ }, undefined, false, undefined, this)
939
+ ]
940
+ }, undefined, true, undefined, this),
941
+ /* @__PURE__ */ jsxDEV7("div", {
942
+ className: "flex items-center justify-between",
943
+ children: [
944
+ /* @__PURE__ */ jsxDEV7("span", {
945
+ className: "text-muted-foreground",
946
+ children: "XP Earned"
947
+ }, undefined, false, undefined, this),
948
+ /* @__PURE__ */ jsxDEV7("span", {
949
+ className: "font-semibold text-orange-500",
950
+ children: progress.xpEarned
951
+ }, undefined, false, undefined, this)
952
+ ]
953
+ }, undefined, true, undefined, this),
954
+ /* @__PURE__ */ jsxDEV7("div", {
955
+ className: "flex items-center justify-between",
956
+ children: [
957
+ /* @__PURE__ */ jsxDEV7("span", {
958
+ className: "text-muted-foreground",
959
+ children: "Current Streak"
960
+ }, undefined, false, undefined, this),
961
+ /* @__PURE__ */ jsxDEV7("span", {
962
+ className: "font-semibold",
963
+ children: progress.streakDays > 0 ? `\uD83D\uDD25 ${progress.streakDays} days` : "Start today!"
964
+ }, undefined, false, undefined, this)
965
+ ]
966
+ }, undefined, true, undefined, this)
967
+ ]
968
+ }, undefined, true, undefined, this)
969
+ }, undefined, false, undefined, this)
970
+ ]
971
+ }, undefined, true, undefined, this)
972
+ ]
973
+ }, undefined, true, undefined, this);
974
+ }
975
+
976
+ // src/CoachingMiniApp.tsx
977
+ import { useState, useCallback } from "react";
978
+ import { Card as Card5, CardContent as CardContent5 } from "@contractspec/lib.ui-kit-web/ui/card";
979
+ import {
980
+ ViewTabs,
981
+ useLearningProgress
982
+ } from "@contractspec/example.learning-journey-ui-shared";
983
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
984
+ "use client";
985
+ function CoachingMiniApp({
986
+ track,
987
+ progress: externalProgress,
988
+ onStepComplete: externalOnStepComplete,
989
+ onViewChange,
990
+ initialView = "overview"
991
+ }) {
992
+ const [currentView, setCurrentView] = useState(initialView);
993
+ const { progress: internalProgress, completeStep: internalCompleteStep } = useLearningProgress(track);
994
+ const progress = externalProgress ?? internalProgress;
995
+ const handleViewChange = useCallback((view) => {
996
+ setCurrentView(view);
997
+ onViewChange?.(view);
998
+ }, [onViewChange]);
999
+ const handleStepComplete = useCallback((stepId) => {
1000
+ if (externalOnStepComplete) {
1001
+ externalOnStepComplete(stepId);
1002
+ } else {
1003
+ internalCompleteStep(stepId);
1004
+ }
1005
+ }, [externalOnStepComplete, internalCompleteStep]);
1006
+ const handleStartFromOverview = useCallback(() => {
1007
+ setCurrentView("steps");
1008
+ onViewChange?.("steps");
1009
+ }, [onViewChange]);
1010
+ const renderView = () => {
1011
+ const viewProps = {
1012
+ track,
1013
+ progress,
1014
+ onStepComplete: handleStepComplete
1015
+ };
1016
+ switch (currentView) {
1017
+ case "overview":
1018
+ return /* @__PURE__ */ jsxDEV8(Overview, {
1019
+ ...viewProps,
1020
+ onStart: handleStartFromOverview
1021
+ }, undefined, false, undefined, this);
1022
+ case "steps":
1023
+ return /* @__PURE__ */ jsxDEV8(Steps, {
1024
+ ...viewProps
1025
+ }, undefined, false, undefined, this);
1026
+ case "progress":
1027
+ return /* @__PURE__ */ jsxDEV8(ProgressView, {
1028
+ ...viewProps
1029
+ }, undefined, false, undefined, this);
1030
+ case "timeline":
1031
+ return /* @__PURE__ */ jsxDEV8(Timeline, {
1032
+ ...viewProps
1033
+ }, undefined, false, undefined, this);
1034
+ default:
1035
+ return /* @__PURE__ */ jsxDEV8(Overview, {
1036
+ ...viewProps,
1037
+ onStart: handleStartFromOverview
1038
+ }, undefined, false, undefined, this);
1039
+ }
1040
+ };
1041
+ return /* @__PURE__ */ jsxDEV8("div", {
1042
+ className: "space-y-6",
1043
+ children: [
1044
+ /* @__PURE__ */ jsxDEV8(Card5, {
1045
+ children: /* @__PURE__ */ jsxDEV8(CardContent5, {
1046
+ className: "p-4",
1047
+ children: /* @__PURE__ */ jsxDEV8(ViewTabs, {
1048
+ currentView,
1049
+ onViewChange: handleViewChange
1050
+ }, undefined, false, undefined, this)
1051
+ }, undefined, false, undefined, this)
1052
+ }, undefined, false, undefined, this),
1053
+ renderView()
1054
+ ]
1055
+ }, undefined, true, undefined, this);
1056
+ }
1057
+ // src/docs/learning-journey-ui-coaching.docblock.ts
1058
+ import { registerDocBlocks } from "@contractspec/lib.contracts/docs";
1059
+ var blocks = [
1060
+ {
1061
+ id: "docs.examples.learning-journey-ui-coaching",
1062
+ title: "Learning Journey UI — Coaching",
1063
+ summary: "UI mini-app components for coaching: tips, engagement, progress.",
1064
+ kind: "reference",
1065
+ visibility: "public",
1066
+ route: "/docs/examples/learning-journey-ui-coaching",
1067
+ tags: ["learning", "ui", "coaching"],
1068
+ body: `## Includes
1069
+ - Coaching mini-app shell
1070
+ - Views: overview, steps, progress, timeline
1071
+ - Components: tip card, engagement meter, tip feed
1072
+
1073
+ ## Notes
1074
+ - Compose using design system components.
1075
+ - Keep accessibility and mobile-friendly tap targets.`
1076
+ }
1077
+ ];
1078
+ registerDocBlocks(blocks);
1079
+ // src/example.ts
1080
+ import { defineExample } from "@contractspec/lib.contracts";
1081
+ var example = defineExample({
1082
+ meta: {
1083
+ key: "learning-journey-ui-coaching",
1084
+ version: "1.0.0",
1085
+ title: "Learning Journey UI — Coaching",
1086
+ description: "UI mini-app for coaching patterns: tips, engagement meter, progress.",
1087
+ kind: "ui",
1088
+ visibility: "public",
1089
+ stability: "experimental",
1090
+ owners: ["@platform.core"],
1091
+ tags: ["learning", "ui", "coaching"]
1092
+ },
1093
+ docs: {
1094
+ rootDocId: "docs.examples.learning-journey-ui-coaching"
1095
+ },
1096
+ entrypoints: {
1097
+ packageName: "@contractspec/example.learning-journey-ui-coaching",
1098
+ docs: "./docs"
1099
+ },
1100
+ surfaces: {
1101
+ templates: true,
1102
+ sandbox: { enabled: true, modes: ["playground", "markdown"] },
1103
+ studio: { enabled: true, installable: true },
1104
+ mcp: { enabled: true }
1105
+ }
1106
+ });
1107
+ var example_default = example;
1108
+ export {
1109
+ example_default as example,
1110
+ TipFeed,
1111
+ TipCard,
1112
+ Timeline,
1113
+ Steps,
1114
+ ProgressView as Progress,
1115
+ Overview,
1116
+ EngagementMeter,
1117
+ CoachingMiniApp
1118
+ };