@burdenoff/microfe-planmagnet 2026.1002.2 → 2026.1002.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.
Files changed (154) hide show
  1. package/dist/generated/wspace-operations.d.ts +574 -0
  2. package/dist/generated/wspace-operations.d.ts.map +1 -1
  3. package/dist/generated/wspace-types.d.ts +486 -16
  4. package/dist/generated/wspace-types.d.ts.map +1 -1
  5. package/dist/index.js +8 -8
  6. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  7. package/dist/planmagnet/PlanMagnetRoot.js +174 -168
  8. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  9. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  10. package/dist/planmagnet/PlanMagnetRoutes.js +63 -59
  11. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  12. package/dist/planmagnet/board/BulkActions.d.ts.map +1 -1
  13. package/dist/planmagnet/board/BulkActions.js +106 -55
  14. package/dist/planmagnet/board/BulkActions.js.map +1 -1
  15. package/dist/planmagnet/controls/Pickers.d.ts +3 -3
  16. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  17. package/dist/planmagnet/dashboards/DashboardUI.d.ts +0 -4
  18. package/dist/planmagnet/dashboards/DashboardUI.d.ts.map +1 -1
  19. package/dist/planmagnet/dashboards/DashboardUI.js +6 -13
  20. package/dist/planmagnet/dashboards/DashboardUI.js.map +1 -1
  21. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
  22. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +70 -59
  23. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
  24. package/dist/planmagnet/forecast/ResourceForecastCard.js +1 -1
  25. package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -1
  26. package/dist/planmagnet/index.d.ts +1 -1
  27. package/dist/planmagnet/index.d.ts.map +1 -1
  28. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts +3 -3
  29. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.d.ts.map +1 -1
  30. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js +26 -19
  31. package/dist/planmagnet/pages/DashboardsProjectManagerPagePage.js.map +1 -1
  32. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts +2 -2
  33. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.d.ts.map +1 -1
  34. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js +18 -12
  35. package/dist/planmagnet/pages/DashboardsTeamUtilizationPagePage.js.map +1 -1
  36. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts +2 -0
  37. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.d.ts.map +1 -0
  38. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js +251 -0
  39. package/dist/planmagnet/pages/ProductsCustomerSatisfactionPagePage.js.map +1 -0
  40. package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -1
  41. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +94 -92
  42. package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
  43. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -1
  44. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js +116 -114
  45. package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.js.map +1 -1
  46. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  47. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +174 -159
  48. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  49. package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -1
  50. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js +159 -145
  51. package/dist/planmagnet/pages/TasksCreateTaskPagePage.js.map +1 -1
  52. package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -1
  53. package/dist/planmagnet/pages/TasksEditTaskPagePage.js +161 -143
  54. package/dist/planmagnet/pages/TasksEditTaskPagePage.js.map +1 -1
  55. package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -1
  56. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js +157 -155
  57. package/dist/planmagnet/pages/TasksTaskDetailPagePage.js.map +1 -1
  58. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.d.ts.map +1 -1
  59. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +97 -99
  60. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js.map +1 -1
  61. package/dist/planmagnet/product/FeatureLinkPanels.js +66 -66
  62. package/dist/planmagnet/product/ProductFeatureControls.js +38 -38
  63. package/dist/planmagnet/product/ProductFeatureLinkCard.js +8 -8
  64. package/dist/planmagnet/product/ProductLineControls.js +83 -83
  65. package/dist/planmagnet/product/ProductTeamsPanel.js +6 -6
  66. package/dist/planmagnet/product/routes.d.ts +6 -0
  67. package/dist/planmagnet/product/routes.d.ts.map +1 -1
  68. package/dist/planmagnet/product/routes.js +2 -2
  69. package/dist/planmagnet/product/routes.js.map +1 -1
  70. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts +20 -0
  71. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.d.ts.map +1 -0
  72. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js +55 -0
  73. package/dist/planmagnet/satisfaction/DeliverySatisfactionSection.js.map +1 -0
  74. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts +30 -0
  75. package/dist/planmagnet/satisfaction/SatisfactionFigures.d.ts.map +1 -0
  76. package/dist/planmagnet/satisfaction/SatisfactionFigures.js +282 -0
  77. package/dist/planmagnet/satisfaction/SatisfactionFigures.js.map +1 -0
  78. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts +9 -0
  79. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.d.ts.map +1 -0
  80. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js +390 -0
  81. package/dist/planmagnet/satisfaction/SatisfactionImportDialog.js.map +1 -0
  82. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts +17 -0
  83. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.d.ts.map +1 -0
  84. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js +77 -0
  85. package/dist/planmagnet/satisfaction/SatisfactionLinkFields.js.map +1 -0
  86. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts +18 -0
  87. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.d.ts.map +1 -0
  88. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js +87 -0
  89. package/dist/planmagnet/satisfaction/SatisfactionReleaseSelect.js.map +1 -0
  90. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts +13 -0
  91. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.d.ts.map +1 -0
  92. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js +326 -0
  93. package/dist/planmagnet/satisfaction/SatisfactionResponseDialog.js.map +1 -0
  94. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts +23 -0
  95. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.d.ts.map +1 -0
  96. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js +258 -0
  97. package/dist/planmagnet/satisfaction/SatisfactionResponsesTable.js.map +1 -0
  98. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts +6 -0
  99. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.d.ts.map +1 -0
  100. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js +56 -0
  101. package/dist/planmagnet/satisfaction/SatisfactionSummaryCard.js.map +1 -0
  102. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts +16 -0
  103. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.d.ts.map +1 -0
  104. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js +102 -0
  105. package/dist/planmagnet/satisfaction/SatisfactionWindowPicker.js.map +1 -0
  106. package/dist/planmagnet/satisfaction/satisfaction.d.ts +154 -0
  107. package/dist/planmagnet/satisfaction/satisfaction.d.ts.map +1 -0
  108. package/dist/planmagnet/satisfaction/satisfaction.js +210 -0
  109. package/dist/planmagnet/satisfaction/satisfaction.js.map +1 -0
  110. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts +108 -0
  111. package/dist/planmagnet/satisfaction/satisfactionCsv.d.ts.map +1 -0
  112. package/dist/planmagnet/satisfaction/satisfactionCsv.js +211 -0
  113. package/dist/planmagnet/satisfaction/satisfactionCsv.js.map +1 -0
  114. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts +90 -0
  115. package/dist/planmagnet/satisfaction/satisfactionForm.d.ts.map +1 -0
  116. package/dist/planmagnet/satisfaction/satisfactionForm.js +90 -0
  117. package/dist/planmagnet/satisfaction/satisfactionForm.js.map +1 -0
  118. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts +116 -0
  119. package/dist/planmagnet/satisfaction/satisfactionOperations.d.ts.map +1 -0
  120. package/dist/planmagnet/satisfaction/satisfactionOperations.js +86 -0
  121. package/dist/planmagnet/satisfaction/satisfactionOperations.js.map +1 -0
  122. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts +20 -0
  123. package/dist/planmagnet/satisfaction/useSatisfactionAccess.d.ts.map +1 -0
  124. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js +31 -0
  125. package/dist/planmagnet/satisfaction/useSatisfactionAccess.js.map +1 -0
  126. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts +35 -0
  127. package/dist/planmagnet/skills/RequiredSkillsEditor.d.ts.map +1 -0
  128. package/dist/planmagnet/skills/RequiredSkillsEditor.js +124 -0
  129. package/dist/planmagnet/skills/RequiredSkillsEditor.js.map +1 -0
  130. package/dist/planmagnet/skills/SkillChips.d.ts +30 -0
  131. package/dist/planmagnet/skills/SkillChips.d.ts.map +1 -0
  132. package/dist/planmagnet/skills/SkillChips.js +57 -0
  133. package/dist/planmagnet/skills/SkillChips.js.map +1 -0
  134. package/dist/planmagnet/skills/SkillCoverageCard.d.ts +24 -0
  135. package/dist/planmagnet/skills/SkillCoverageCard.d.ts.map +1 -0
  136. package/dist/planmagnet/skills/SkillCoverageCard.js +256 -0
  137. package/dist/planmagnet/skills/SkillCoverageCard.js.map +1 -0
  138. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts +10 -0
  139. package/dist/planmagnet/skills/WorkItemRequiredSkills.d.ts.map +1 -0
  140. package/dist/planmagnet/skills/WorkItemRequiredSkills.js +65 -0
  141. package/dist/planmagnet/skills/WorkItemRequiredSkills.js.map +1 -0
  142. package/dist/planmagnet/skills/skillOperations.d.ts +52 -0
  143. package/dist/planmagnet/skills/skillOperations.d.ts.map +1 -0
  144. package/dist/planmagnet/skills/skillOperations.js +44 -0
  145. package/dist/planmagnet/skills/skillOperations.js.map +1 -0
  146. package/dist/planmagnet/skills/skillTags.d.ts +103 -0
  147. package/dist/planmagnet/skills/skillTags.d.ts.map +1 -0
  148. package/dist/planmagnet/skills/skillTags.js +115 -0
  149. package/dist/planmagnet/skills/skillTags.js.map +1 -0
  150. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts +28 -0
  151. package/dist/planmagnet/skills/useRequiredSkillsDraft.d.ts.map +1 -0
  152. package/dist/planmagnet/skills/useRequiredSkillsDraft.js +30 -0
  153. package/dist/planmagnet/skills/useRequiredSkillsDraft.js.map +1 -0
  154. package/package.json +1 -1
@@ -0,0 +1,282 @@
1
+ import { useTr as e } from "../../shared/hooks/useTr.js";
2
+ import { cn as t } from "../utils/cn.js";
3
+ import { formatCsat as n, formatNps as r, formatUtcDay as i, shareOf as a } from "./satisfaction.js";
4
+ import { Gauge as o, Smile as s } from "lucide-react";
5
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
+ import { Card as u, CardContent as d, CardHeader as f, CardTitle as p } from "@burdenoff/fe-libs/ui";
7
+ //#region src/planmagnet/satisfaction/SatisfactionFigures.tsx
8
+ function m(e, t) {
9
+ return t === 0 ? e("planmagnet.satisfaction.responses.none", "No responses") : t === 1 ? e("planmagnet.satisfaction.responses.one", "1 response") : e("planmagnet.satisfaction.responses.many", "{{count}} responses", { count: t });
10
+ }
11
+ function h(e, t) {
12
+ let n = e("planmagnet.satisfaction.window.span", "{{from}} – {{to}}", {
13
+ from: i(t.from),
14
+ to: i(t.to)
15
+ });
16
+ return t.preset === "CUSTOM" ? n : e("planmagnet.satisfaction.window.presetWithSpan", "{{preset}} ({{span}})", {
17
+ preset: g(e, t.preset),
18
+ span: n
19
+ });
20
+ }
21
+ function g(e, t) {
22
+ switch (t) {
23
+ case "LAST_30_DAYS": return e("planmagnet.satisfaction.window.last30", "Last 30 days");
24
+ case "LAST_90_DAYS": return e("planmagnet.satisfaction.window.last90", "Last 90 days");
25
+ case "LAST_180_DAYS": return e("planmagnet.satisfaction.window.last180", "Last 180 days");
26
+ case "LAST_365_DAYS": return e("planmagnet.satisfaction.window.last365", "Last 365 days");
27
+ default: return e("planmagnet.satisfaction.window.custom", "Custom");
28
+ }
29
+ }
30
+ function _(e, t) {
31
+ return e("planmagnet.satisfaction.notEnoughDetail", "{{count}} so far — a score needs at least {{minimum}} responses.", {
32
+ count: t.responseCount,
33
+ minimum: t.minimumResponses
34
+ });
35
+ }
36
+ var v = {
37
+ satisfied: "bg-status-success-bg-subtle text-status-success-text",
38
+ promoter: "bg-status-success-bg-subtle text-status-success-text",
39
+ passive: "bg-status-warning-bg-subtle text-foreground",
40
+ notSatisfied: "bg-status-error-bg-subtle text-status-error-text",
41
+ detractor: "bg-status-error-bg-subtle text-status-error-text"
42
+ };
43
+ function y(e, t) {
44
+ switch (t) {
45
+ case "satisfied": return e("planmagnet.satisfaction.category.satisfied", "Satisfied");
46
+ case "notSatisfied": return e("planmagnet.satisfaction.category.notSatisfied", "Not satisfied");
47
+ case "promoter": return e("planmagnet.satisfaction.category.promoter", "Promoter");
48
+ case "passive": return e("planmagnet.satisfaction.category.passive", "Passive");
49
+ default: return e("planmagnet.satisfaction.category.detractor", "Detractor");
50
+ }
51
+ }
52
+ function b({ nps: n }) {
53
+ let r = e(), i = [
54
+ {
55
+ key: "promoters",
56
+ label: r("planmagnet.satisfaction.nps.promoters", "Promoters (9–10)"),
57
+ count: n.promoterCount,
58
+ bar: "bg-status-success-bg"
59
+ },
60
+ {
61
+ key: "passives",
62
+ label: r("planmagnet.satisfaction.nps.passives", "Passives (7–8)"),
63
+ count: n.passiveCount,
64
+ bar: "bg-status-warning-bg"
65
+ },
66
+ {
67
+ key: "detractors",
68
+ label: r("planmagnet.satisfaction.nps.detractors", "Detractors (0–6)"),
69
+ count: n.detractorCount,
70
+ bar: "bg-status-error-bg"
71
+ }
72
+ ], o = !n.notEnoughResponses && n.responseCount > 0;
73
+ return /* @__PURE__ */ l("div", {
74
+ className: "space-y-2",
75
+ "data-testid": "satisfaction-nps-split",
76
+ children: [o && /* @__PURE__ */ c("div", {
77
+ className: "flex h-2 w-full overflow-hidden rounded-full bg-muted",
78
+ "aria-hidden": !0,
79
+ children: i.map((e) => /* @__PURE__ */ c("div", {
80
+ className: e.bar,
81
+ style: { width: `${e.count * 100 / n.responseCount}%` }
82
+ }, e.key))
83
+ }), /* @__PURE__ */ c("dl", {
84
+ className: "grid grid-cols-3 gap-2 text-xs",
85
+ children: i.map((e) => /* @__PURE__ */ l("div", {
86
+ className: "min-w-0",
87
+ children: [/* @__PURE__ */ l("dt", {
88
+ className: "flex items-center gap-1.5 text-muted-foreground",
89
+ children: [/* @__PURE__ */ c("span", {
90
+ className: t("h-2 w-2 shrink-0 rounded-full", e.bar),
91
+ "aria-hidden": !0
92
+ }), /* @__PURE__ */ c("span", {
93
+ className: "truncate",
94
+ children: e.label
95
+ })]
96
+ }), /* @__PURE__ */ c("dd", {
97
+ className: "mt-0.5 font-medium tabular-nums",
98
+ children: o ? r("planmagnet.satisfaction.nps.countWithShare", "{{count}} ({{share}}%)", {
99
+ count: e.count,
100
+ share: a(e.count, n.responseCount)
101
+ }) : e.count
102
+ })]
103
+ }, e.key))
104
+ })]
105
+ });
106
+ }
107
+ function x({ value: t, notEnough: n, testId: r }) {
108
+ let i = e();
109
+ return n || t === null ? /* @__PURE__ */ c("p", {
110
+ className: "text-lg font-semibold text-muted-foreground",
111
+ "data-testid": r,
112
+ children: i("planmagnet.satisfaction.notEnough", "Not enough responses")
113
+ }) : /* @__PURE__ */ c("p", {
114
+ className: "text-3xl font-semibold tabular-nums",
115
+ "data-testid": r,
116
+ children: t
117
+ });
118
+ }
119
+ function S({ csat: t, window: r }) {
120
+ let i = e();
121
+ return /* @__PURE__ */ l(u, {
122
+ "data-testid": "satisfaction-csat-card",
123
+ children: [/* @__PURE__ */ l(f, {
124
+ className: "pb-2",
125
+ children: [/* @__PURE__ */ l(p, {
126
+ className: "flex items-center gap-2 text-base",
127
+ children: [/* @__PURE__ */ c(s, {
128
+ className: "h-4 w-4",
129
+ "aria-hidden": !0
130
+ }), i("planmagnet.satisfaction.csat.title", "CSAT")]
131
+ }), /* @__PURE__ */ c("p", {
132
+ className: "text-xs text-muted-foreground",
133
+ children: i("planmagnet.satisfaction.csat.subtitle", "Customer satisfaction: the share of answers that were a 4 or a 5 on a 1–5 scale. The default delivery KPI.")
134
+ })]
135
+ }), /* @__PURE__ */ l(d, {
136
+ className: "space-y-2",
137
+ children: [
138
+ /* @__PURE__ */ c(x, {
139
+ value: n(t.score),
140
+ notEnough: t.notEnoughResponses,
141
+ testId: "satisfaction-csat-value"
142
+ }),
143
+ /* @__PURE__ */ c("p", {
144
+ className: "text-sm text-muted-foreground",
145
+ children: t.notEnoughResponses ? _(i, t) : i("planmagnet.satisfaction.csat.satisfied", "{{satisfied}} of {{count}} answers were a 4 or a 5.", {
146
+ satisfied: t.satisfiedCount,
147
+ count: t.responseCount
148
+ })
149
+ }),
150
+ /* @__PURE__ */ l("p", {
151
+ className: "text-xs text-muted-foreground",
152
+ "data-testid": "satisfaction-csat-basis",
153
+ children: [
154
+ m(i, t.responseCount),
155
+ " · ",
156
+ h(i, r)
157
+ ]
158
+ })
159
+ ]
160
+ })]
161
+ });
162
+ }
163
+ function C({ nps: t, window: n }) {
164
+ let i = e();
165
+ return /* @__PURE__ */ l(u, {
166
+ "data-testid": "satisfaction-nps-card",
167
+ children: [/* @__PURE__ */ l(f, {
168
+ className: "pb-2",
169
+ children: [/* @__PURE__ */ l(p, {
170
+ className: "flex items-center gap-2 text-base",
171
+ children: [/* @__PURE__ */ c(o, {
172
+ className: "h-4 w-4",
173
+ "aria-hidden": !0
174
+ }), i("planmagnet.satisfaction.nps.title", "NPS")]
175
+ }), /* @__PURE__ */ c("p", {
176
+ className: "text-xs text-muted-foreground",
177
+ children: i("planmagnet.satisfaction.nps.subtitle", "Net Promoter Score: % promoters (9–10) minus % detractors (0–6) on a 0–10 scale, from −100 to +100.")
178
+ })]
179
+ }), /* @__PURE__ */ l(d, {
180
+ className: "space-y-3",
181
+ children: [
182
+ /* @__PURE__ */ c(x, {
183
+ value: r(t.score),
184
+ notEnough: t.notEnoughResponses,
185
+ testId: "satisfaction-nps-value"
186
+ }),
187
+ t.notEnoughResponses && /* @__PURE__ */ c("p", {
188
+ className: "text-sm text-muted-foreground",
189
+ children: _(i, t)
190
+ }),
191
+ /* @__PURE__ */ c(b, { nps: t }),
192
+ /* @__PURE__ */ l("p", {
193
+ className: "text-xs text-muted-foreground",
194
+ "data-testid": "satisfaction-nps-basis",
195
+ children: [
196
+ m(i, t.responseCount),
197
+ " · ",
198
+ h(i, n)
199
+ ]
200
+ })
201
+ ]
202
+ })]
203
+ });
204
+ }
205
+ function w({ summary: e }) {
206
+ return /* @__PURE__ */ l("div", {
207
+ className: "grid gap-4 md:grid-cols-2",
208
+ "data-testid": "satisfaction-figures",
209
+ children: [/* @__PURE__ */ c(S, {
210
+ csat: e.csat,
211
+ window: e.window
212
+ }), /* @__PURE__ */ c(C, {
213
+ nps: e.nps,
214
+ window: e.window
215
+ })]
216
+ });
217
+ }
218
+ function T({ label: t, value: n, notEnough: r, responseCount: i, testId: a }) {
219
+ let o = e();
220
+ return /* @__PURE__ */ l("div", {
221
+ className: "rounded-md border p-3",
222
+ "data-testid": a,
223
+ children: [
224
+ /* @__PURE__ */ c("p", {
225
+ className: "text-xs text-muted-foreground",
226
+ children: t
227
+ }),
228
+ r || n === null ? /* @__PURE__ */ c("p", {
229
+ className: "mt-1 text-sm font-semibold text-muted-foreground",
230
+ children: o("planmagnet.satisfaction.notEnough", "Not enough responses")
231
+ }) : /* @__PURE__ */ c("p", {
232
+ className: "mt-1 text-2xl font-semibold tabular-nums",
233
+ children: n
234
+ }),
235
+ /* @__PURE__ */ c("p", {
236
+ className: "mt-0.5 text-xs text-muted-foreground",
237
+ children: m(o, i)
238
+ })
239
+ ]
240
+ });
241
+ }
242
+ function E({ summary: t }) {
243
+ let i = e(), { csat: a, nps: o } = t;
244
+ return /* @__PURE__ */ l("div", {
245
+ className: "space-y-2",
246
+ children: [
247
+ /* @__PURE__ */ l("div", {
248
+ className: "grid grid-cols-2 gap-3",
249
+ children: [/* @__PURE__ */ c(T, {
250
+ label: i("planmagnet.satisfaction.csat.compactLabel", "CSAT (% of answers 4–5)"),
251
+ value: n(a.score),
252
+ notEnough: a.notEnoughResponses,
253
+ responseCount: a.responseCount,
254
+ testId: "satisfaction-compact-csat"
255
+ }), /* @__PURE__ */ c(T, {
256
+ label: i("planmagnet.satisfaction.nps.compactLabel", "NPS"),
257
+ value: r(o.score),
258
+ notEnough: o.notEnoughResponses,
259
+ responseCount: o.responseCount,
260
+ testId: "satisfaction-compact-nps"
261
+ })]
262
+ }),
263
+ !o.notEnoughResponses && /* @__PURE__ */ c("p", {
264
+ className: "text-xs text-muted-foreground",
265
+ children: i("planmagnet.satisfaction.nps.compactSplit", "NPS: {{promoters}} promoters · {{passives}} passives · {{detractors}} detractors", {
266
+ promoters: o.promoterCount,
267
+ passives: o.passiveCount,
268
+ detractors: o.detractorCount
269
+ })
270
+ }),
271
+ /* @__PURE__ */ c("p", {
272
+ className: "text-xs text-muted-foreground",
273
+ "data-testid": "satisfaction-compact-window",
274
+ children: h(i, t.window)
275
+ })
276
+ ]
277
+ });
278
+ }
279
+ //#endregion
280
+ export { v as CATEGORY_CLASS, E as CompactSatisfactionFigures, w as SatisfactionFigureCards, y as categoryLabel, g as windowPresetLabel };
281
+
282
+ //# sourceMappingURL=SatisfactionFigures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SatisfactionFigures.js","names":[],"sources":["../../../src/planmagnet/satisfaction/SatisfactionFigures.tsx"],"sourcesContent":["import { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { Gauge, Smile } from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { cn } from '../utils/cn';\nimport { formatCsat, formatNps, formatUtcDay, shareOf, type ScoreCategory } from './satisfaction';\nimport type {\n CsatFigure,\n CustomerSatisfactionSummary,\n NpsFigure,\n SatisfactionWindowEcho,\n} from './satisfactionOperations';\n\n/**\n * ANR-21 figures. Every figure carries its response count and the window it covers (owner decision 2026-10-02), and\n * a metric below its minimum responses reads \"Not enough responses\" — never 0 and never a score computed from too few\n * answers. CSAT and NPS are counted separately: twelve NPS answers never lend a score to four CSAT answers.\n */\n\ntype Tr = ReturnType<typeof useTr>;\n\nexport function responseCountText(tr: Tr, count: number): string {\n if (count === 0) return tr('planmagnet.satisfaction.responses.none', 'No responses');\n return count === 1\n ? tr('planmagnet.satisfaction.responses.one', '1 response')\n : tr('planmagnet.satisfaction.responses.many', '{{count}} responses', { count });\n}\n\nexport function windowText(tr: Tr, window: SatisfactionWindowEcho): string {\n const span = tr('planmagnet.satisfaction.window.span', '{{from}} – {{to}}', {\n from: formatUtcDay(window.from),\n to: formatUtcDay(window.to),\n });\n if (window.preset === 'CUSTOM') return span;\n return tr('planmagnet.satisfaction.window.presetWithSpan', '{{preset}} ({{span}})', {\n preset: windowPresetLabel(tr, window.preset),\n span,\n });\n}\n\nexport function windowPresetLabel(tr: Tr, preset: SatisfactionWindowEcho['preset']): string {\n switch (preset) {\n case 'LAST_30_DAYS':\n return tr('planmagnet.satisfaction.window.last30', 'Last 30 days');\n case 'LAST_90_DAYS':\n return tr('planmagnet.satisfaction.window.last90', 'Last 90 days');\n case 'LAST_180_DAYS':\n return tr('planmagnet.satisfaction.window.last180', 'Last 180 days');\n case 'LAST_365_DAYS':\n return tr('planmagnet.satisfaction.window.last365', 'Last 365 days');\n default:\n return tr('planmagnet.satisfaction.window.custom', 'Custom');\n }\n}\n\nfunction notEnoughText(tr: Tr, figure: { responseCount: number; minimumResponses: number }) {\n return tr(\n 'planmagnet.satisfaction.notEnoughDetail',\n '{{count}} so far — a score needs at least {{minimum}} responses.',\n { count: figure.responseCount, minimum: figure.minimumResponses }\n );\n}\n\n/**\n * Badge colours for one answer's category — semantic status tokens only, and only those the host shells' Tailwind\n * theme maps (planmagnet-app styles.css @theme): `bg-status-*-bg`, `bg-status-*-bg-subtle`, `text-status-success-text`,\n * `text-status-error-text`. A token missing there generates no CSS at all.\n */\nexport const CATEGORY_CLASS: Record<ScoreCategory, string> = {\n satisfied: 'bg-status-success-bg-subtle text-status-success-text',\n promoter: 'bg-status-success-bg-subtle text-status-success-text',\n // The shells' Tailwind theme maps no warning TEXT colour (only its backgrounds), so a passive reads in the body colour.\n passive: 'bg-status-warning-bg-subtle text-foreground',\n notSatisfied: 'bg-status-error-bg-subtle text-status-error-text',\n detractor: 'bg-status-error-bg-subtle text-status-error-text',\n};\n\nexport function categoryLabel(tr: Tr, category: ScoreCategory): string {\n switch (category) {\n case 'satisfied':\n return tr('planmagnet.satisfaction.category.satisfied', 'Satisfied');\n case 'notSatisfied':\n return tr('planmagnet.satisfaction.category.notSatisfied', 'Not satisfied');\n case 'promoter':\n return tr('planmagnet.satisfaction.category.promoter', 'Promoter');\n case 'passive':\n return tr('planmagnet.satisfaction.category.passive', 'Passive');\n default:\n return tr('planmagnet.satisfaction.category.detractor', 'Detractor');\n }\n}\n\n/** Promoters / passives / detractors as a bar (only once there is a score) and as counts (always). */\nfunction NpsSplit({ nps }: { nps: NpsFigure }) {\n const tr = useTr();\n const parts = [\n {\n key: 'promoters',\n label: tr('planmagnet.satisfaction.nps.promoters', 'Promoters (9–10)'),\n count: nps.promoterCount,\n bar: 'bg-status-success-bg',\n },\n {\n key: 'passives',\n label: tr('planmagnet.satisfaction.nps.passives', 'Passives (7–8)'),\n count: nps.passiveCount,\n bar: 'bg-status-warning-bg',\n },\n {\n key: 'detractors',\n label: tr('planmagnet.satisfaction.nps.detractors', 'Detractors (0–6)'),\n count: nps.detractorCount,\n bar: 'bg-status-error-bg',\n },\n ];\n const showShares = !nps.notEnoughResponses && nps.responseCount > 0;\n return (\n <div className=\"space-y-2\" data-testid=\"satisfaction-nps-split\">\n {showShares && (\n <div className=\"flex h-2 w-full overflow-hidden rounded-full bg-muted\" aria-hidden={true}>\n {parts.map((part) => (\n <div\n key={part.key}\n className={part.bar}\n style={{ width: `${(part.count * 100) / nps.responseCount}%` }}\n />\n ))}\n </div>\n )}\n <dl className=\"grid grid-cols-3 gap-2 text-xs\">\n {parts.map((part) => (\n <div key={part.key} className=\"min-w-0\">\n <dt className=\"flex items-center gap-1.5 text-muted-foreground\">\n <span className={cn('h-2 w-2 shrink-0 rounded-full', part.bar)} aria-hidden={true} />\n <span className=\"truncate\">{part.label}</span>\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums\">\n {showShares\n ? tr('planmagnet.satisfaction.nps.countWithShare', '{{count}} ({{share}}%)', {\n count: part.count,\n share: shareOf(part.count, nps.responseCount),\n })\n : part.count}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n );\n}\n\nfunction FigureValue({\n value,\n notEnough,\n testId,\n}: {\n value: string | null;\n notEnough: boolean;\n testId: string;\n}) {\n const tr = useTr();\n if (notEnough || value === null) {\n return (\n <p className=\"text-lg font-semibold text-muted-foreground\" data-testid={testId}>\n {tr('planmagnet.satisfaction.notEnough', 'Not enough responses')}\n </p>\n );\n }\n return (\n <p className=\"text-3xl font-semibold tabular-nums\" data-testid={testId}>\n {value}\n </p>\n );\n}\n\nfunction CsatCard({ csat, window }: { csat: CsatFigure; window: SatisfactionWindowEcho }) {\n const tr = useTr();\n return (\n <Card data-testid=\"satisfaction-csat-card\">\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Smile className=\"h-4 w-4\" aria-hidden={true} />\n {tr('planmagnet.satisfaction.csat.title', 'CSAT')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {tr(\n 'planmagnet.satisfaction.csat.subtitle',\n 'Customer satisfaction: the share of answers that were a 4 or a 5 on a 1–5 scale. The default delivery KPI.'\n )}\n </p>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <FigureValue\n value={formatCsat(csat.score)}\n notEnough={csat.notEnoughResponses}\n testId=\"satisfaction-csat-value\"\n />\n <p className=\"text-sm text-muted-foreground\">\n {csat.notEnoughResponses\n ? notEnoughText(tr, csat)\n : tr(\n 'planmagnet.satisfaction.csat.satisfied',\n '{{satisfied}} of {{count}} answers were a 4 or a 5.',\n { satisfied: csat.satisfiedCount, count: csat.responseCount }\n )}\n </p>\n <p className=\"text-xs text-muted-foreground\" data-testid=\"satisfaction-csat-basis\">\n {responseCountText(tr, csat.responseCount)} · {windowText(tr, window)}\n </p>\n </CardContent>\n </Card>\n );\n}\n\nfunction NpsCard({ nps, window }: { nps: NpsFigure; window: SatisfactionWindowEcho }) {\n const tr = useTr();\n return (\n <Card data-testid=\"satisfaction-nps-card\">\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Gauge className=\"h-4 w-4\" aria-hidden={true} />\n {tr('planmagnet.satisfaction.nps.title', 'NPS')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {tr(\n 'planmagnet.satisfaction.nps.subtitle',\n 'Net Promoter Score: % promoters (9–10) minus % detractors (0–6) on a 0–10 scale, from −100 to +100.'\n )}\n </p>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <FigureValue\n value={formatNps(nps.score)}\n notEnough={nps.notEnoughResponses}\n testId=\"satisfaction-nps-value\"\n />\n {nps.notEnoughResponses && (\n <p className=\"text-sm text-muted-foreground\">{notEnoughText(tr, nps)}</p>\n )}\n <NpsSplit nps={nps} />\n <p className=\"text-xs text-muted-foreground\" data-testid=\"satisfaction-nps-basis\">\n {responseCountText(tr, nps.responseCount)} · {windowText(tr, window)}\n </p>\n </CardContent>\n </Card>\n );\n}\n\n/** The page's two figure cards, side by side. */\nexport function SatisfactionFigureCards({ summary }: { summary: CustomerSatisfactionSummary }) {\n return (\n <div className=\"grid gap-4 md:grid-cols-2\" data-testid=\"satisfaction-figures\">\n <CsatCard csat={summary.csat} window={summary.window} />\n <NpsCard nps={summary.nps} window={summary.window} />\n </div>\n );\n}\n\nfunction CompactTile({\n label,\n value,\n notEnough,\n responseCount,\n testId,\n}: {\n label: string;\n value: string | null;\n notEnough: boolean;\n responseCount: number;\n testId: string;\n}) {\n const tr = useTr();\n return (\n <div className=\"rounded-md border p-3\" data-testid={testId}>\n <p className=\"text-xs text-muted-foreground\">{label}</p>\n {notEnough || value === null ? (\n <p className=\"mt-1 text-sm font-semibold text-muted-foreground\">\n {tr('planmagnet.satisfaction.notEnough', 'Not enough responses')}\n </p>\n ) : (\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">{value}</p>\n )}\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{responseCountText(tr, responseCount)}</p>\n </div>\n );\n}\n\n/** CSAT and NPS as two small tiles with their counts, and the window under them — for cards on other pages. */\nexport function CompactSatisfactionFigures({ summary }: { summary: CustomerSatisfactionSummary }) {\n const tr = useTr();\n const { csat, nps } = summary;\n return (\n <div className=\"space-y-2\">\n <div className=\"grid grid-cols-2 gap-3\">\n <CompactTile\n label={tr('planmagnet.satisfaction.csat.compactLabel', 'CSAT (% of answers 4–5)')}\n value={formatCsat(csat.score)}\n notEnough={csat.notEnoughResponses}\n responseCount={csat.responseCount}\n testId=\"satisfaction-compact-csat\"\n />\n <CompactTile\n label={tr('planmagnet.satisfaction.nps.compactLabel', 'NPS')}\n value={formatNps(nps.score)}\n notEnough={nps.notEnoughResponses}\n responseCount={nps.responseCount}\n testId=\"satisfaction-compact-nps\"\n />\n </div>\n {!nps.notEnoughResponses && (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\n 'planmagnet.satisfaction.nps.compactSplit',\n 'NPS: {{promoters}} promoters · {{passives}} passives · {{detractors}} detractors',\n {\n promoters: nps.promoterCount,\n passives: nps.passiveCount,\n detractors: nps.detractorCount,\n }\n )}\n </p>\n )}\n <p className=\"text-xs text-muted-foreground\" data-testid=\"satisfaction-compact-window\">\n {windowText(tr, summary.window)}\n </p>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { DefaultLinks } from './satisfactionCsv';
2
+ import { ImportCustomerSatisfactionResult } from './satisfactionOperations';
3
+
4
+ export declare function SatisfactionImportDialog({ links, onImported, }: {
5
+ /** Starting links for rows that name none — the page's product / release / project filters. */
6
+ links: DefaultLinks;
7
+ onImported: (result: ImportCustomerSatisfactionResult) => void;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=SatisfactionImportDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SatisfactionImportDialog.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/satisfaction/SatisfactionImportDialog.tsx"],"names":[],"mappings":"AA+BA,OAAO,EAQL,KAAK,YAAY,EAOlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGL,KAAK,gCAAgC,EACtC,MAAM,0BAA0B,CAAC;AAkPlC,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,UAAU,GACX,EAAE;IACD,+FAA+F;IAC/F,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,gCAAgC,KAAK,IAAI,CAAC;CAChE,2CA8aA"}