@burdenoff/microfe-planmagnet 2026.1001.1 → 2026.1001.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 (122) hide show
  1. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoot.js +163 -150
  3. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  4. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  5. package/dist/planmagnet/PlanMagnetRoutes.js +124 -108
  6. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  7. package/dist/planmagnet/comments/CommentThread.js +36 -36
  8. package/dist/planmagnet/comments/RoadmapComments.js +21 -21
  9. package/dist/planmagnet/controls/AutomationRuleControls.js +24 -24
  10. package/dist/planmagnet/controls/FeatureControls.js +60 -60
  11. package/dist/planmagnet/controls/MilestoneControls.d.ts +2 -0
  12. package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -1
  13. package/dist/planmagnet/controls/MilestoneControls.js +89 -72
  14. package/dist/planmagnet/controls/MilestoneControls.js.map +1 -1
  15. package/dist/planmagnet/controls/SyncControls.js +59 -59
  16. package/dist/planmagnet/discussion/WorkItemDiscussionPanel.js +15 -15
  17. package/dist/planmagnet/docs/DocSuggestionsPanel.js +12 -12
  18. package/dist/planmagnet/docs/DocVersionCompare.js +3 -3
  19. package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts +12 -0
  20. package/dist/planmagnet/forecast/DeliveryForecastCard.d.ts.map +1 -0
  21. package/dist/planmagnet/forecast/DeliveryForecastCard.js +208 -0
  22. package/dist/planmagnet/forecast/DeliveryForecastCard.js.map +1 -0
  23. package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts +5 -0
  24. package/dist/planmagnet/forecast/ProjectOutlookCard.d.ts.map +1 -0
  25. package/dist/planmagnet/forecast/ProjectOutlookCard.js +190 -0
  26. package/dist/planmagnet/forecast/ProjectOutlookCard.js.map +1 -0
  27. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts +5 -0
  28. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.d.ts.map +1 -0
  29. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +99 -0
  30. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js.map +1 -0
  31. package/dist/planmagnet/forecast/ResourceForecastCard.d.ts +8 -0
  32. package/dist/planmagnet/forecast/ResourceForecastCard.d.ts.map +1 -0
  33. package/dist/planmagnet/forecast/ResourceForecastCard.js +185 -0
  34. package/dist/planmagnet/forecast/ResourceForecastCard.js.map +1 -0
  35. package/dist/planmagnet/forecast/riskFlags.d.ts +35 -0
  36. package/dist/planmagnet/forecast/riskFlags.d.ts.map +1 -0
  37. package/dist/planmagnet/forecast/riskFlags.js +37 -0
  38. package/dist/planmagnet/forecast/riskFlags.js.map +1 -0
  39. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts +17 -0
  40. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts.map +1 -0
  41. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js +218 -0
  42. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js.map +1 -0
  43. package/dist/planmagnet/meetings/MeetingsCard.d.ts +7 -0
  44. package/dist/planmagnet/meetings/MeetingsCard.d.ts.map +1 -0
  45. package/dist/planmagnet/meetings/MeetingsCard.js +108 -0
  46. package/dist/planmagnet/meetings/MeetingsCard.js.map +1 -0
  47. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts +9 -0
  48. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts.map +1 -0
  49. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js +232 -0
  50. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js.map +1 -0
  51. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts +19 -0
  52. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts.map +1 -0
  53. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js +226 -0
  54. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js.map +1 -0
  55. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts +14 -0
  56. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts.map +1 -0
  57. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js +81 -0
  58. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js.map +1 -0
  59. package/dist/planmagnet/meetings/meetingActions.d.ts +57 -0
  60. package/dist/planmagnet/meetings/meetingActions.d.ts.map +1 -0
  61. package/dist/planmagnet/meetings/meetingActions.js +51 -0
  62. package/dist/planmagnet/meetings/meetingActions.js.map +1 -0
  63. package/dist/planmagnet/meetings/meetingGraphql.d.ts +29 -0
  64. package/dist/planmagnet/meetings/meetingGraphql.d.ts.map +1 -0
  65. package/dist/planmagnet/meetings/meetingGraphql.js +166 -0
  66. package/dist/planmagnet/meetings/meetingGraphql.js.map +1 -0
  67. package/dist/planmagnet/meetings/meetingModel.d.ts +74 -0
  68. package/dist/planmagnet/meetings/meetingModel.d.ts.map +1 -0
  69. package/dist/planmagnet/meetings/meetingModel.js +88 -0
  70. package/dist/planmagnet/meetings/meetingModel.js.map +1 -0
  71. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
  72. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +216 -182
  73. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  74. package/dist/planmagnet/pages/AutomationAutomationRuleDetailPagePage.js +11 -11
  75. package/dist/planmagnet/pages/AutomationCreateAutomationRulePagePage.js +4 -4
  76. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +163 -163
  77. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  78. package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js +165 -165
  79. package/dist/planmagnet/pages/IntegrationsNewSyncPagePage.js.map +1 -1
  80. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts +2 -0
  81. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts.map +1 -0
  82. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js +197 -0
  83. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js.map +1 -0
  84. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts +2 -0
  85. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts.map +1 -0
  86. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js +173 -0
  87. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js.map +1 -0
  88. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts +2 -0
  89. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.d.ts.map +1 -0
  90. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +234 -0
  91. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js.map +1 -0
  92. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
  93. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +73 -52
  94. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
  95. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  96. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +205 -190
  97. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  98. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  99. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +211 -182
  100. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  101. package/dist/planmagnet/pages/ReportsReportPagePage.js +22 -22
  102. package/dist/planmagnet/pages/ReportsReportPagePage.js.map +1 -1
  103. package/dist/planmagnet/pages/ReportsReportsPagePage.js +21 -21
  104. package/dist/planmagnet/pages/TeamTeamDetailPagePage.d.ts.map +1 -1
  105. package/dist/planmagnet/pages/TeamTeamDetailPagePage.js +88 -83
  106. package/dist/planmagnet/pages/TeamTeamDetailPagePage.js.map +1 -1
  107. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.d.ts.map +1 -1
  108. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +139 -112
  109. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js.map +1 -1
  110. package/dist/planmagnet/pages/analytics/StatusFlowCard.js +21 -21
  111. package/dist/planmagnet/product/ProductControls.js +91 -91
  112. package/dist/planmagnet/reports/SchedulesPanel.js +33 -33
  113. package/dist/planmagnet/reports/ShareDialog.js +76 -76
  114. package/dist/planmagnet/reports/ShareDialog.js.map +1 -1
  115. package/dist/planmagnet/reports/sharedReportRoute.d.ts +3 -2
  116. package/dist/planmagnet/reports/sharedReportRoute.d.ts.map +1 -1
  117. package/dist/planmagnet/reports/sharedReportRoute.js.map +1 -1
  118. package/dist/planmagnet/roadmaps/RoadmapControls.js +60 -60
  119. package/dist/planmagnet/roadmaps/RoadmapNowNextLater.js +30 -30
  120. package/dist/planmagnet/roadmaps/RoadmapReviewPanel.js +21 -21
  121. package/dist/planmagnet/roadmaps/RoadmapVersionsPanel.js +22 -22
  122. package/package.json +1 -1
@@ -3,20 +3,21 @@ import { Tooltip as t } from "../../../node_modules/recharts/es6/component/Toolt
3
3
  import { ResponsiveContainer as n } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
4
4
  import { Bar as r } from "../../../node_modules/recharts/es6/cartesian/Bar.js";
5
5
  import { ReferenceLine as i } from "../../../node_modules/recharts/es6/cartesian/ReferenceLine.js";
6
- import { CartesianGrid as a } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
7
- import { Line as o } from "../../../node_modules/recharts/es6/cartesian/Line.js";
8
- import { XAxis as s } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
9
- import { YAxis as c } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
10
- import { LineChart as l } from "../../../node_modules/recharts/es6/chart/LineChart.js";
11
- import { BarChart as u } from "../../../node_modules/recharts/es6/chart/BarChart.js";
12
- import { BarChart3 as d, TrendingUp as f } from "lucide-react";
13
- import { gql as p } from "@apollo/client";
14
- import { useQuery as m } from "@apollo/client/react";
15
- import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
16
- import { useI18n as v } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
17
- import { Card as y, CardContent as b, CardHeader as x, CardTitle as S } from "@burdenoff/fe-libs/ui";
6
+ import { ReferenceArea as a } from "../../../node_modules/recharts/es6/cartesian/ReferenceArea.js";
7
+ import { CartesianGrid as o } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
8
+ import { Line as s } from "../../../node_modules/recharts/es6/cartesian/Line.js";
9
+ import { XAxis as c } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
10
+ import { YAxis as l } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
11
+ import { LineChart as u } from "../../../node_modules/recharts/es6/chart/LineChart.js";
12
+ import { BarChart as d } from "../../../node_modules/recharts/es6/chart/BarChart.js";
13
+ import { BarChart3 as f, TrendingUp as p } from "lucide-react";
14
+ import { gql as m } from "@apollo/client";
15
+ import { useQuery as h } from "@apollo/client/react";
16
+ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
17
+ import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
18
+ import { Card as b, CardContent as x, CardHeader as S, CardTitle as C } from "@burdenoff/fe-libs/ui";
18
19
  //#region src/planmagnet/pages/analytics/SprintDeliveryCards.tsx
19
- var C = p`
20
+ var w = m`
20
21
  query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {
21
22
  planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {
22
23
  sprintId
@@ -29,7 +30,7 @@ var C = p`
29
30
  }
30
31
  }
31
32
  }
32
- `, w = p`
33
+ `, T = m`
33
34
  query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {
34
35
  planmagnetVelocity(
35
36
  workspaceId: $workspaceId
@@ -39,6 +40,11 @@ var C = p`
39
40
  projectId
40
41
  averageVelocity
41
42
  forecastNextSprintPoints
43
+ forecastRange {
44
+ p15
45
+ p85
46
+ }
47
+ insufficientHistory
42
48
  sprints {
43
49
  sprintId
44
50
  sprintName
@@ -49,171 +55,192 @@ var C = p`
49
55
  }
50
56
  }
51
57
  `;
52
- function T(e) {
58
+ function E(e) {
53
59
  let t = new Date(e);
54
60
  return `${t.getUTCMonth() + 1}/${t.getUTCDate()}`;
55
61
  }
56
- function E({ workspaceId: r, sprintId: i }) {
57
- let { t: u } = v(), { data: f, loading: p, error: h } = m(C, {
62
+ function D({ workspaceId: r, sprintId: i }) {
63
+ let { t: a } = y(), { data: d, loading: p, error: m } = h(w, {
58
64
  variables: {
59
65
  workspaceId: r,
60
66
  sprintId: i
61
67
  },
62
68
  skip: !r || !i
63
- }), w = (f?.planmagnetSprintBurndown?.points ?? []).map((e) => ({
64
- day: T(e.date),
69
+ }), g = (d?.planmagnetSprintBurndown?.points ?? []).map((e) => ({
70
+ day: E(e.date),
65
71
  remaining: e.remainingPoints,
66
72
  completed: e.completedPoints
67
73
  }));
68
- return /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ _(x, { children: [/* @__PURE__ */ _(S, {
74
+ return /* @__PURE__ */ v(b, { children: [/* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(C, {
69
75
  className: "flex items-center gap-2",
70
- children: [/* @__PURE__ */ g(d, { className: "h-4 w-4" }), u("planmagnet.dashboards.burndown.title", "Sprint burndown")]
71
- }), /* @__PURE__ */ g("p", {
76
+ children: [/* @__PURE__ */ _(f, { className: "h-4 w-4" }), a("planmagnet.dashboards.burndown.title", "Sprint burndown")]
77
+ }), /* @__PURE__ */ _("p", {
72
78
  className: "text-xs text-muted-foreground",
73
- children: u("planmagnet.dashboards.burndown.subtitle", "Remaining vs. completed story points, by day of the sprint.")
74
- })] }), /* @__PURE__ */ g(b, { children: i ? p && !f ? /* @__PURE__ */ g("p", {
79
+ children: a("planmagnet.dashboards.burndown.subtitle", "Remaining vs. completed story points, by day of the sprint.")
80
+ })] }), /* @__PURE__ */ _(x, { children: i ? p && !d ? /* @__PURE__ */ _("p", {
75
81
  className: "text-sm text-muted-foreground",
76
- children: u("planmagnet.dashboards.loading", "Loading…")
77
- }) : h ? /* @__PURE__ */ _("p", {
82
+ children: a("planmagnet.dashboards.loading", "Loading…")
83
+ }) : m ? /* @__PURE__ */ v("p", {
78
84
  className: "text-sm text-status-error-text",
79
85
  children: [
80
- u("planmagnet.dashboards.burndown.error", "Burndown could not be loaded"),
86
+ a("planmagnet.dashboards.burndown.error", "Burndown could not be loaded"),
81
87
  ":",
82
88
  " ",
83
- h.message
89
+ m.message
84
90
  ]
85
- }) : w.length === 0 ? /* @__PURE__ */ g("p", {
91
+ }) : g.length === 0 ? /* @__PURE__ */ _("p", {
86
92
  className: "text-sm text-muted-foreground",
87
- children: u("planmagnet.dashboards.burndown.empty", "The active sprint has no work items yet.")
88
- }) : /* @__PURE__ */ g(n, {
93
+ children: a("planmagnet.dashboards.burndown.empty", "The active sprint has no work items yet.")
94
+ }) : /* @__PURE__ */ _(n, {
89
95
  width: "100%",
90
96
  height: 220,
91
- children: /* @__PURE__ */ _(l, {
92
- data: w,
97
+ children: /* @__PURE__ */ v(u, {
98
+ data: g,
93
99
  children: [
94
- /* @__PURE__ */ g(a, {
100
+ /* @__PURE__ */ _(o, {
95
101
  strokeDasharray: "3 3",
96
102
  opacity: .2
97
103
  }),
98
- /* @__PURE__ */ g(s, {
104
+ /* @__PURE__ */ _(c, {
99
105
  dataKey: "day",
100
106
  tick: { fontSize: 11 }
101
107
  }),
102
- /* @__PURE__ */ g(c, {
108
+ /* @__PURE__ */ _(l, {
103
109
  tick: { fontSize: 11 },
104
110
  allowDecimals: !1
105
111
  }),
106
- /* @__PURE__ */ g(t, {}),
107
- /* @__PURE__ */ g(e, { wrapperStyle: { fontSize: 12 } }),
108
- /* @__PURE__ */ g(o, {
112
+ /* @__PURE__ */ _(t, {}),
113
+ /* @__PURE__ */ _(e, { wrapperStyle: { fontSize: 12 } }),
114
+ /* @__PURE__ */ _(s, {
109
115
  type: "monotone",
110
116
  dataKey: "remaining",
111
- name: u("planmagnet.dashboards.burndown.remaining", "Remaining points"),
117
+ name: a("planmagnet.dashboards.burndown.remaining", "Remaining points"),
112
118
  stroke: "#f59e0b",
113
119
  strokeWidth: 2,
114
120
  dot: { r: 2 }
115
121
  }),
116
- /* @__PURE__ */ g(o, {
122
+ /* @__PURE__ */ _(s, {
117
123
  type: "monotone",
118
124
  dataKey: "completed",
119
- name: u("planmagnet.dashboards.burndown.completed", "Completed points"),
125
+ name: a("planmagnet.dashboards.burndown.completed", "Completed points"),
120
126
  stroke: "#22c55e",
121
127
  strokeWidth: 2,
122
128
  dot: { r: 2 }
123
129
  })
124
130
  ]
125
131
  })
126
- }) : /* @__PURE__ */ g("p", {
132
+ }) : /* @__PURE__ */ _("p", {
127
133
  className: "text-sm text-muted-foreground",
128
- children: u("planmagnet.dashboards.burndown.noSprint", "No active sprint for this project.")
134
+ children: a("planmagnet.dashboards.burndown.noSprint", "No active sprint for this project.")
129
135
  }) })] });
130
136
  }
131
- function D({ workspaceId: o, projectId: l, trailingSprintCount: d = 6 }) {
132
- let { t: p } = v(), { data: C, loading: T, error: E } = m(w, {
137
+ function O({ workspaceId: s, projectId: u, trailingSprintCount: f = 6 }) {
138
+ let { t: m } = y(), { data: w, loading: E, error: D } = h(T, {
133
139
  variables: {
134
- workspaceId: o,
135
- projectId: l,
136
- trailingSprintCount: d
140
+ workspaceId: s,
141
+ projectId: u,
142
+ trailingSprintCount: f
137
143
  },
138
- skip: !o || !l
139
- }), D = C?.planmagnetVelocity, O = D?.sprints.map((e) => ({
144
+ skip: !s || !u
145
+ }), O = w?.planmagnetVelocity, k = O?.sprints.map((e) => ({
140
146
  name: e.sprintName,
141
147
  completed: e.completedPoints,
142
148
  planned: e.plannedPoints ?? void 0
143
- })) ?? [], k = D ? Math.round(D.averageVelocity) : 0;
144
- return /* @__PURE__ */ _(y, { children: [/* @__PURE__ */ _(x, { children: [/* @__PURE__ */ _(S, {
149
+ })) ?? [], A = O ? Math.round(O.averageVelocity) : 0, j = O ? Math.round(O.forecastNextSprintPoints) : 0, M = O?.forecastRange ?? null, N = O?.insufficientHistory ?? !1;
150
+ return /* @__PURE__ */ v(b, { children: [/* @__PURE__ */ v(S, { children: [/* @__PURE__ */ v(C, {
145
151
  className: "flex items-center gap-2",
146
- children: [/* @__PURE__ */ g(f, { className: "h-4 w-4" }), p("planmagnet.dashboards.velocity.title", "Sprint velocity")]
147
- }), /* @__PURE__ */ g("p", {
152
+ children: [/* @__PURE__ */ _(p, { className: "h-4 w-4" }), m("planmagnet.dashboards.velocity.title", "Sprint velocity")]
153
+ }), /* @__PURE__ */ _("p", {
148
154
  className: "text-xs text-muted-foreground",
149
- children: p("planmagnet.dashboards.velocity.subtitle", "Completed story points per sprint, across the trailing {{count}} completed sprints.", { count: d })
150
- })] }), /* @__PURE__ */ g(b, { children: l ? T && !C ? /* @__PURE__ */ g("p", {
155
+ children: m("planmagnet.dashboards.velocity.subtitle", "Completed story points per sprint, across the trailing {{count}} completed sprints.", { count: f })
156
+ })] }), /* @__PURE__ */ _(x, { children: u ? E && !w ? /* @__PURE__ */ _("p", {
151
157
  className: "text-sm text-muted-foreground",
152
- children: p("planmagnet.dashboards.loading", "Loading…")
153
- }) : E ? /* @__PURE__ */ _("p", {
158
+ children: m("planmagnet.dashboards.loading", "Loading…")
159
+ }) : D ? /* @__PURE__ */ v("p", {
154
160
  className: "text-sm text-status-error-text",
155
161
  children: [
156
- p("planmagnet.dashboards.velocity.error", "Velocity could not be loaded"),
162
+ m("planmagnet.dashboards.velocity.error", "Velocity could not be loaded"),
157
163
  ":",
158
164
  " ",
159
- E.message
165
+ D.message
160
166
  ]
161
- }) : O.length === 0 ? /* @__PURE__ */ g("p", {
167
+ }) : k.length === 0 ? /* @__PURE__ */ _("p", {
162
168
  className: "text-sm text-muted-foreground",
163
- children: p("planmagnet.dashboards.velocity.empty", "No completed sprints yet for this project.")
164
- }) : /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(n, {
165
- width: "100%",
166
- height: 190,
167
- children: /* @__PURE__ */ _(u, {
168
- data: O,
169
- children: [
170
- /* @__PURE__ */ g(a, {
171
- strokeDasharray: "3 3",
172
- opacity: .2
173
- }),
174
- /* @__PURE__ */ g(s, {
175
- dataKey: "name",
176
- tick: { fontSize: 11 }
177
- }),
178
- /* @__PURE__ */ g(c, {
179
- tick: { fontSize: 11 },
180
- allowDecimals: !1
181
- }),
182
- /* @__PURE__ */ g(t, {}),
183
- /* @__PURE__ */ g(e, { wrapperStyle: { fontSize: 12 } }),
184
- /* @__PURE__ */ g(r, {
185
- dataKey: "planned",
186
- name: p("planmagnet.dashboards.velocity.planned", "Planned"),
187
- fill: "#cbd5e1"
188
- }),
189
- /* @__PURE__ */ g(r, {
190
- dataKey: "completed",
191
- name: p("planmagnet.dashboards.velocity.completed", "Completed"),
192
- fill: "#6366f1"
193
- }),
194
- /* @__PURE__ */ g(i, {
195
- y: k,
196
- stroke: "#22c55e",
197
- strokeDasharray: "4 4",
198
- label: {
199
- value: p("planmagnet.dashboards.velocity.avgLabel", "avg"),
200
- fontSize: 10
201
- }
202
- })
203
- ]
204
- })
205
- }), /* @__PURE__ */ g("p", {
206
- className: "mt-2 text-center text-xs text-muted-foreground",
207
- children: p("planmagnet.dashboards.velocity.trailingAverage", "Average of the last {{count}} completed sprints: {{points}} pts per sprint", {
208
- count: O.length,
209
- points: k
169
+ children: m("planmagnet.dashboards.velocity.empty", "No completed sprints yet for this project.")
170
+ }) : /* @__PURE__ */ v(g, { children: [
171
+ /* @__PURE__ */ _(n, {
172
+ width: "100%",
173
+ height: 190,
174
+ children: /* @__PURE__ */ v(d, {
175
+ data: k,
176
+ children: [
177
+ /* @__PURE__ */ _(o, {
178
+ strokeDasharray: "3 3",
179
+ opacity: .2
180
+ }),
181
+ /* @__PURE__ */ _(c, {
182
+ dataKey: "name",
183
+ tick: { fontSize: 11 }
184
+ }),
185
+ /* @__PURE__ */ _(l, {
186
+ tick: { fontSize: 11 },
187
+ allowDecimals: !1
188
+ }),
189
+ /* @__PURE__ */ _(t, {}),
190
+ /* @__PURE__ */ _(e, { wrapperStyle: { fontSize: 12 } }),
191
+ M && /* @__PURE__ */ _(a, {
192
+ y1: M.p15,
193
+ y2: M.p85,
194
+ fill: "var(--color-chart-2)",
195
+ fillOpacity: .12,
196
+ stroke: "none"
197
+ }),
198
+ /* @__PURE__ */ _(r, {
199
+ dataKey: "planned",
200
+ name: m("planmagnet.dashboards.velocity.planned", "Planned"),
201
+ fill: "#cbd5e1"
202
+ }),
203
+ /* @__PURE__ */ _(r, {
204
+ dataKey: "completed",
205
+ name: m("planmagnet.dashboards.velocity.completed", "Completed"),
206
+ fill: "#6366f1"
207
+ }),
208
+ /* @__PURE__ */ _(i, {
209
+ y: A,
210
+ stroke: "#22c55e",
211
+ strokeDasharray: "4 4",
212
+ label: {
213
+ value: m("planmagnet.dashboards.velocity.avgLabel", "avg"),
214
+ fontSize: 10
215
+ }
216
+ })
217
+ ]
218
+ })
219
+ }),
220
+ /* @__PURE__ */ v("p", {
221
+ className: "mt-2 text-center text-xs text-muted-foreground",
222
+ children: [m("planmagnet.dashboards.velocity.trailingAverage", "Median of the last {{count}} completed sprints: {{points}} pts per sprint", {
223
+ count: k.length,
224
+ points: j
225
+ }), M && ` · ${m("planmagnet.dashboards.velocity.range", "likely range (p15–p85): {{low}}–{{high}} pts", {
226
+ low: Math.round(M.p15),
227
+ high: Math.round(M.p85)
228
+ })}`]
229
+ }),
230
+ N && /* @__PURE__ */ _("p", {
231
+ className: "mt-1 text-center text-xs text-status-warning-text",
232
+ children: m("planmagnet.dashboards.velocity.insufficientHistory", "Fewer than 3 sprints with completed points — this forecast is low-confidence.")
233
+ }),
234
+ /* @__PURE__ */ _("p", {
235
+ className: "mt-1 text-center text-xs text-muted-foreground",
236
+ children: m("planmagnet.dashboards.velocity.methodLabel", "Statistical forecast (not AI-generated).")
210
237
  })
211
- })] }) : /* @__PURE__ */ g("p", {
238
+ ] }) : /* @__PURE__ */ _("p", {
212
239
  className: "text-sm text-muted-foreground",
213
- children: p("planmagnet.dashboards.velocity.noProject", "Select a project to see its velocity.")
240
+ children: m("planmagnet.dashboards.velocity.noProject", "Select a project to see its velocity.")
214
241
  }) })] });
215
242
  }
216
243
  //#endregion
217
- export { E as SprintBurndownCard, D as SprintVelocityCard };
244
+ export { D as SprintBurndownCard, O as SprintVelocityCard };
218
245
 
219
246
  //# sourceMappingURL=SprintDeliveryCards.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SprintDeliveryCards.js","names":[],"sources":["../../../../src/planmagnet/pages/analytics/SprintDeliveryCards.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, TrendingUp } from 'lucide-react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\n\n/**\n * Sprint burndown and velocity, as their own cards (BOFF-4447's server-computed\n * `planmagnetSprintBurndown` / `planmagnetVelocity`). Extracted out of\n * `pages/AnalyticsAnalyticsPagePage.tsx`, where this same chart code lived inline, so the\n * role dashboards (`dashboards/project-manager-page`) can import the chart rather than\n * duplicating it — same reasoning as `CycleTimeCard`/`BudgetPerformanceCard` alongside\n * them in `DeliveryHealthCards.tsx`. Each card owns its query, so neither can land a hook\n * after an early return in the host page.\n *\n * recharts' `stroke`/`fill` render as literal SVG paint attributes, not Tailwind\n * classNames — they cannot consume semantic `bg-*`/`text-*` tokens, the same documented\n * exception `AnalyticsAnalyticsPagePage.tsx`'s cumulative-flow chart carries.\n */\n\nconst GET_SPRINT_BURNDOWN = gql`\n query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {\n planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {\n sprintId\n totalPoints\n totalCount\n points {\n date\n remainingPoints\n completedPoints\n }\n }\n }\n`;\n\nconst GET_VELOCITY = gql`\n query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {\n planmagnetVelocity(\n workspaceId: $workspaceId\n projectId: $projectId\n trailingSprintCount: $trailingSprintCount\n ) {\n projectId\n averageVelocity\n forecastNextSprintPoints\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedPoints\n plannedPoints\n }\n }\n }\n`;\n\ninterface BurndownData {\n planmagnetSprintBurndown: {\n sprintId: string;\n totalPoints: number;\n totalCount: number;\n points: { date: string; remainingPoints: number; completedPoints: number }[];\n } | null;\n}\n\ninterface VelocityData {\n planmagnetVelocity: {\n projectId: string;\n averageVelocity: number;\n forecastNextSprintPoints: number;\n sprints: {\n sprintId: string;\n sprintName: string;\n sequenceNumber: number;\n completedPoints: number;\n plannedPoints: number | null;\n }[];\n };\n}\n\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;\n}\n\nexport function SprintBurndownCard({\n workspaceId,\n sprintId,\n}: {\n workspaceId?: string | null;\n sprintId: string;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<BurndownData>(GET_SPRINT_BURNDOWN, {\n variables: { workspaceId, sprintId },\n skip: !workspaceId || !sprintId,\n });\n const points = data?.planmagnetSprintBurndown?.points ?? [];\n const chartData = points.map((p) => ({\n day: formatDay(p.date),\n remaining: p.remainingPoints,\n completed: p.completedPoints,\n }));\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.burndown.title', 'Sprint burndown')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.burndown.subtitle',\n 'Remaining vs. completed story points, by day of the sprint.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!sprintId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.noSprint', 'No active sprint for this project.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.burndown.error', 'Burndown could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.empty', 'The active sprint has no work items yet.')}\n </p>\n ) : (\n <ResponsiveContainer width=\"100%\" height={220}>\n <LineChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"day\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Line\n type=\"monotone\"\n dataKey=\"remaining\"\n name={t('planmagnet.dashboards.burndown.remaining', 'Remaining points')}\n stroke=\"#f59e0b\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.burndown.completed', 'Completed points')}\n stroke=\"#22c55e\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport function SprintVelocityCard({\n workspaceId,\n projectId,\n trailingSprintCount = 6,\n}: {\n workspaceId?: string | null;\n projectId: string;\n trailingSprintCount?: number;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<VelocityData>(GET_VELOCITY, {\n variables: { workspaceId, projectId, trailingSprintCount },\n skip: !workspaceId || !projectId,\n });\n const velocity = data?.planmagnetVelocity;\n const chartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n const avgVelocity = velocity ? Math.round(velocity.averageVelocity) : 0;\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <TrendingUp className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.velocity.title', 'Sprint velocity')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.subtitle',\n 'Completed story points per sprint, across the trailing {{count}} completed sprints.',\n { count: trailingSprintCount }\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!projectId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.velocity.noProject', 'Select a project to see its velocity.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.velocity.error', 'Velocity could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.empty',\n 'No completed sprints yet for this project.'\n )}\n </p>\n ) : (\n <>\n <ResponsiveContainer width=\"100%\" height={190}>\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.dashboards.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n <ReferenceLine\n y={avgVelocity}\n stroke=\"#22c55e\"\n strokeDasharray=\"4 4\"\n label={{\n value: t('planmagnet.dashboards.velocity.avgLabel', 'avg'),\n fontSize: 10,\n }}\n />\n </BarChart>\n </ResponsiveContainer>\n <p className=\"mt-2 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.trailingAverage',\n 'Average of the last {{count}} completed sprints: {{points}} pts per sprint',\n { count: chartData.length, points: avgVelocity }\n )}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SprintDeliveryCards.js","names":[],"sources":["../../../../src/planmagnet/pages/analytics/SprintDeliveryCards.tsx"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, TrendingUp } from 'lucide-react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceArea,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\n\n/**\n * Sprint burndown and velocity, as their own cards (BOFF-4447's server-computed\n * `planmagnetSprintBurndown` / `planmagnetVelocity`). Extracted out of\n * `pages/AnalyticsAnalyticsPagePage.tsx`, where this same chart code lived inline, so the\n * role dashboards (`dashboards/project-manager-page`) can import the chart rather than\n * duplicating it — same reasoning as `CycleTimeCard`/`BudgetPerformanceCard` alongside\n * them in `DeliveryHealthCards.tsx`. Each card owns its query, so neither can land a hook\n * after an early return in the host page.\n *\n * recharts' `stroke`/`fill` render as literal SVG paint attributes, not Tailwind\n * classNames — they cannot consume semantic `bg-*`/`text-*` tokens, the same documented\n * exception `AnalyticsAnalyticsPagePage.tsx`'s cumulative-flow chart carries.\n */\n\nconst GET_SPRINT_BURNDOWN = gql`\n query DashboardSprintBurndown($workspaceId: ID!, $sprintId: ID!) {\n planmagnetSprintBurndown(workspaceId: $workspaceId, sprintId: $sprintId) {\n sprintId\n totalPoints\n totalCount\n points {\n date\n remainingPoints\n completedPoints\n }\n }\n }\n`;\n\nconst GET_VELOCITY = gql`\n query DashboardVelocity($workspaceId: ID!, $projectId: ID!, $trailingSprintCount: Int) {\n planmagnetVelocity(\n workspaceId: $workspaceId\n projectId: $projectId\n trailingSprintCount: $trailingSprintCount\n ) {\n projectId\n averageVelocity\n forecastNextSprintPoints\n forecastRange {\n p15\n p85\n }\n insufficientHistory\n sprints {\n sprintId\n sprintName\n sequenceNumber\n completedPoints\n plannedPoints\n }\n }\n }\n`;\n\ninterface BurndownData {\n planmagnetSprintBurndown: {\n sprintId: string;\n totalPoints: number;\n totalCount: number;\n points: { date: string; remainingPoints: number; completedPoints: number }[];\n } | null;\n}\n\ninterface VelocityData {\n planmagnetVelocity: {\n projectId: string;\n averageVelocity: number;\n forecastNextSprintPoints: number;\n forecastRange: { p15: number; p85: number } | null;\n insufficientHistory: boolean;\n sprints: {\n sprintId: string;\n sprintName: string;\n sequenceNumber: number;\n completedPoints: number;\n plannedPoints: number | null;\n }[];\n };\n}\n\nfunction formatDay(iso: string): string {\n const d = new Date(iso);\n return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;\n}\n\nexport function SprintBurndownCard({\n workspaceId,\n sprintId,\n}: {\n workspaceId?: string | null;\n sprintId: string;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<BurndownData>(GET_SPRINT_BURNDOWN, {\n variables: { workspaceId, sprintId },\n skip: !workspaceId || !sprintId,\n });\n const points = data?.planmagnetSprintBurndown?.points ?? [];\n const chartData = points.map((p) => ({\n day: formatDay(p.date),\n remaining: p.remainingPoints,\n completed: p.completedPoints,\n }));\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.burndown.title', 'Sprint burndown')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.burndown.subtitle',\n 'Remaining vs. completed story points, by day of the sprint.'\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!sprintId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.noSprint', 'No active sprint for this project.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.burndown.error', 'Burndown could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.burndown.empty', 'The active sprint has no work items yet.')}\n </p>\n ) : (\n <ResponsiveContainer width=\"100%\" height={220}>\n <LineChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"day\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n <Line\n type=\"monotone\"\n dataKey=\"remaining\"\n name={t('planmagnet.dashboards.burndown.remaining', 'Remaining points')}\n stroke=\"#f59e0b\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.burndown.completed', 'Completed points')}\n stroke=\"#22c55e\"\n strokeWidth={2}\n dot={{ r: 2 }}\n />\n </LineChart>\n </ResponsiveContainer>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport function SprintVelocityCard({\n workspaceId,\n projectId,\n trailingSprintCount = 6,\n}: {\n workspaceId?: string | null;\n projectId: string;\n trailingSprintCount?: number;\n}) {\n const { t } = useI18n();\n const { data, loading, error } = useQuery<VelocityData>(GET_VELOCITY, {\n variables: { workspaceId, projectId, trailingSprintCount },\n skip: !workspaceId || !projectId,\n });\n const velocity = data?.planmagnetVelocity;\n const chartData =\n velocity?.sprints.map((s) => ({\n name: s.sprintName,\n completed: s.completedPoints,\n planned: s.plannedPoints ?? undefined,\n })) ?? [];\n const avgVelocity = velocity ? Math.round(velocity.averageVelocity) : 0;\n const forecastNextSprint = velocity ? Math.round(velocity.forecastNextSprintPoints) : 0;\n const forecastRange = velocity?.forecastRange ?? null;\n const insufficientHistory = velocity?.insufficientHistory ?? false;\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <TrendingUp className=\"h-4 w-4\" />\n {t('planmagnet.dashboards.velocity.title', 'Sprint velocity')}\n </CardTitle>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.subtitle',\n 'Completed story points per sprint, across the trailing {{count}} completed sprints.',\n { count: trailingSprintCount }\n )}\n </p>\n </CardHeader>\n <CardContent>\n {!projectId ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.velocity.noProject', 'Select a project to see its velocity.')}\n </p>\n ) : loading && !data ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('planmagnet.dashboards.loading', 'Loading…')}\n </p>\n ) : error ? (\n <p className=\"text-sm text-status-error-text\">\n {t('planmagnet.dashboards.velocity.error', 'Velocity could not be loaded')}:{' '}\n {error.message}\n </p>\n ) : chartData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.empty',\n 'No completed sprints yet for this project.'\n )}\n </p>\n ) : (\n <>\n <ResponsiveContainer width=\"100%\" height={190}>\n <BarChart data={chartData}>\n <CartesianGrid strokeDasharray=\"3 3\" opacity={0.2} />\n <XAxis dataKey=\"name\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} allowDecimals={false} />\n <Tooltip />\n <Legend wrapperStyle={{ fontSize: 12 }} />\n {/* ANR-02: the empirical p15-p85 band around next sprint's forecast — full-width (no\n x1/x2) since it isn't tied to any historical sprint's x position. */}\n {forecastRange && (\n <ReferenceArea\n y1={forecastRange.p15}\n y2={forecastRange.p85}\n fill=\"var(--color-chart-2)\"\n fillOpacity={0.12}\n stroke=\"none\"\n />\n )}\n <Bar\n dataKey=\"planned\"\n name={t('planmagnet.dashboards.velocity.planned', 'Planned')}\n fill=\"#cbd5e1\"\n />\n <Bar\n dataKey=\"completed\"\n name={t('planmagnet.dashboards.velocity.completed', 'Completed')}\n fill=\"#6366f1\"\n />\n <ReferenceLine\n y={avgVelocity}\n stroke=\"#22c55e\"\n strokeDasharray=\"4 4\"\n label={{\n value: t('planmagnet.dashboards.velocity.avgLabel', 'avg'),\n fontSize: 10,\n }}\n />\n </BarChart>\n </ResponsiveContainer>\n {/* Accessible text restatement of the shaded band, for screen readers. */}\n <p className=\"mt-2 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.trailingAverage',\n 'Median of the last {{count}} completed sprints: {{points}} pts per sprint',\n { count: chartData.length, points: forecastNextSprint }\n )}\n {forecastRange &&\n ` · ${t(\n 'planmagnet.dashboards.velocity.range',\n 'likely range (p15–p85): {{low}}–{{high}} pts',\n { low: Math.round(forecastRange.p15), high: Math.round(forecastRange.p85) }\n )}`}\n </p>\n {insufficientHistory && (\n <p className=\"mt-1 text-center text-xs text-status-warning-text\">\n {t(\n 'planmagnet.dashboards.velocity.insufficientHistory',\n 'Fewer than 3 sprints with completed points — this forecast is low-confidence.'\n )}\n </p>\n )}\n <p className=\"mt-1 text-center text-xs text-muted-foreground\">\n {t(\n 'planmagnet.dashboards.velocity.methodLabel',\n 'Statistical forecast (not AI-generated).'\n )}\n </p>\n </>\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { Tooltip as e } from "../../../node_modules/recharts/es6/component/Tooltip.js";
2
2
  import { ResponsiveContainer as t } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
3
3
  import { Sankey as n } from "../../../node_modules/recharts/es6/chart/Sankey.js";
4
- import { WORK_ITEM_STATUSES as r, enumLabel as i } from "../../controls/WorkItemControls.js";
5
- import { statusVisual as a } from "../../utils/statusColor.js";
6
- import { isForbidden as o } from "../../utils/graphqlErrors.js";
4
+ import { isForbidden as r } from "../../utils/graphqlErrors.js";
5
+ import { WORK_ITEM_STATUSES as i, enumLabel as a } from "../../controls/WorkItemControls.js";
6
+ import { statusVisual as o } from "../../utils/statusColor.js";
7
7
  import { useMemo as s } from "react";
8
8
  import { Workflow as c } from "lucide-react";
9
9
  import { gql as l } from "@apollo/client";
@@ -39,19 +39,19 @@ function x(e, t) {
39
39
  };
40
40
  }
41
41
  function S(e) {
42
- let t = r.filter((t) => e.some((e) => e.fromStatus === t)), n = r.filter((t) => e.some((e) => e.toStatus === t)), a = new Map(t.map((e, t) => [e, t])), o = new Map(n.map((e, n) => [e, t.length + n]));
42
+ let t = i.filter((t) => e.some((e) => e.fromStatus === t)), n = i.filter((t) => e.some((e) => e.toStatus === t)), r = new Map(t.map((e, t) => [e, t])), o = new Map(n.map((e, n) => [e, t.length + n]));
43
43
  return {
44
44
  nodes: [...t.map((e) => ({
45
- name: i(e),
45
+ name: a(e),
46
46
  status: e,
47
47
  side: "from"
48
48
  })), ...n.map((e) => ({
49
- name: i(e),
49
+ name: a(e),
50
50
  status: e,
51
51
  side: "to"
52
52
  }))],
53
53
  links: e.flatMap((e) => {
54
- let t = a.get(e.fromStatus), n = o.get(e.toStatus);
54
+ let t = r.get(e.fromStatus), n = o.get(e.toStatus);
55
55
  return t === void 0 || n === void 0 ? [] : [{
56
56
  source: t,
57
57
  target: n,
@@ -61,7 +61,7 @@ function S(e) {
61
61
  };
62
62
  }
63
63
  function C({ x: e, y: t, width: n, height: r, payload: i }) {
64
- let o = a(i.status), s = i.side === "from";
64
+ let a = o(i.status), s = i.side === "from";
65
65
  return /* @__PURE__ */ f("g", { children: [/* @__PURE__ */ d("rect", {
66
66
  x: e,
67
67
  y: t,
@@ -69,8 +69,8 @@ function C({ x: e, y: t, width: n, height: r, payload: i }) {
69
69
  height: r,
70
70
  rx: 2,
71
71
  style: {
72
- fill: o.color,
73
- stroke: o.color
72
+ fill: a.color,
73
+ stroke: a.color
74
74
  },
75
75
  strokeWidth: 1
76
76
  }), /* @__PURE__ */ d("text", {
@@ -82,25 +82,25 @@ function C({ x: e, y: t, width: n, height: r, payload: i }) {
82
82
  children: i.name
83
83
  })] });
84
84
  }
85
- function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourceControlX: i, targetControlX: o, linkWidth: s, payload: c }) {
86
- let l = a(c.source.status);
85
+ function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourceControlX: i, targetControlX: a, linkWidth: s, payload: c }) {
86
+ let l = o(c.source.status);
87
87
  return /* @__PURE__ */ d("path", {
88
- d: `M${e},${t} C${i},${t} ${o},${r} ${n},${r}`,
88
+ d: `M${e},${t} C${i},${t} ${a},${r} ${n},${r}`,
89
89
  style: { stroke: l.color },
90
90
  strokeWidth: Math.max(s, 1),
91
91
  strokeOpacity: .45,
92
92
  fill: "none"
93
93
  });
94
94
  }
95
- function T({ workspaceId: r, projectId: a, startDate: l, endDate: b }) {
95
+ function T({ workspaceId: i, projectId: o, startDate: l, endDate: b }) {
96
96
  let { t: T } = p(), E = s(() => x(l, b), [l, b]), { data: D, loading: O, error: k } = u(v, {
97
97
  variables: {
98
- workspaceId: r,
99
- projectId: a,
98
+ workspaceId: i,
99
+ projectId: o,
100
100
  from: E.from,
101
101
  to: E.to
102
102
  },
103
- skip: !r || !a
103
+ skip: !i || !o
104
104
  }), A = D?.planmagnetStatusFlow ?? [], { nodes: j, links: M } = S(A), N = [...A].sort((e, t) => t.count - e.count);
105
105
  return /* @__PURE__ */ f(m, {
106
106
  "data-testid": "status-flow-card",
@@ -120,12 +120,12 @@ function T({ workspaceId: r, projectId: a, startDate: l, endDate: b }) {
120
120
  from: E.from.slice(0, 10)
121
121
  })
122
122
  })
123
- ] }), /* @__PURE__ */ d(h, { children: a ? O && !D ? /* @__PURE__ */ d("div", {
123
+ ] }), /* @__PURE__ */ d(h, { children: o ? O && !D ? /* @__PURE__ */ d("div", {
124
124
  className: "flex justify-center py-12",
125
125
  children: /* @__PURE__ */ d("div", { className: "animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full" })
126
126
  }) : k ? /* @__PURE__ */ d("p", {
127
127
  className: "text-sm text-status-error-text",
128
- children: o(k) ? T("planmagnet.analytics.statusFlow.forbidden", "You do not have access to status flow for this project.") : `${T("planmagnet.analytics.statusFlow.error", "Status flow could not be loaded")}: ${k.message}`
128
+ children: r(k) ? T("planmagnet.analytics.statusFlow.forbidden", "You do not have access to status flow for this project.") : `${T("planmagnet.analytics.statusFlow.error", "Status flow could not be loaded")}: ${k.message}`
129
129
  }) : A.length === 0 ? /* @__PURE__ */ d("p", {
130
130
  className: "text-sm text-muted-foreground py-8 text-center",
131
131
  children: T("planmagnet.analytics.statusFlow.empty", "No status changes recorded for this project in the selected range.")
@@ -208,11 +208,11 @@ function T({ workspaceId: r, projectId: a, startDate: l, endDate: b }) {
208
208
  children: [
209
209
  /* @__PURE__ */ d("td", {
210
210
  className: "py-1.5 pr-2",
211
- children: i(e.fromStatus)
211
+ children: a(e.fromStatus)
212
212
  }),
213
213
  /* @__PURE__ */ d("td", {
214
214
  className: "py-1.5 pr-2",
215
- children: i(e.toStatus)
215
+ children: a(e.toStatus)
216
216
  }),
217
217
  /* @__PURE__ */ d("td", {
218
218
  className: "py-1.5 text-right tabular-nums",