@burdenoff/microfe-planmagnet 2026.1001.5 → 2026.1001.7

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 (126) hide show
  1. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoutes.js +10 -6
  3. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  4. package/dist/planmagnet/automation/automationRuleTypes.d.ts +31 -19
  5. package/dist/planmagnet/automation/automationRuleTypes.d.ts.map +1 -1
  6. package/dist/planmagnet/automation/automationRuleTypes.js +4 -8
  7. package/dist/planmagnet/automation/automationRuleTypes.js.map +1 -1
  8. package/dist/planmagnet/controls/CompetitorControls.d.ts +71 -0
  9. package/dist/planmagnet/controls/CompetitorControls.d.ts.map +1 -1
  10. package/dist/planmagnet/controls/CompetitorControls.js +346 -12
  11. package/dist/planmagnet/controls/CompetitorControls.js.map +1 -1
  12. package/dist/planmagnet/controls/FeatureControls.d.ts +23 -1
  13. package/dist/planmagnet/controls/FeatureControls.d.ts.map +1 -1
  14. package/dist/planmagnet/controls/FeatureControls.js +431 -229
  15. package/dist/planmagnet/controls/FeatureControls.js.map +1 -1
  16. package/dist/planmagnet/controls/FeedbackControls.d.ts +70 -0
  17. package/dist/planmagnet/controls/FeedbackControls.d.ts.map +1 -0
  18. package/dist/planmagnet/controls/FeedbackControls.js +153 -0
  19. package/dist/planmagnet/controls/FeedbackControls.js.map +1 -0
  20. package/dist/planmagnet/controls/Pickers.d.ts +15 -0
  21. package/dist/planmagnet/controls/Pickers.d.ts.map +1 -1
  22. package/dist/planmagnet/controls/Pickers.js +61 -1
  23. package/dist/planmagnet/controls/Pickers.js.map +1 -1
  24. package/dist/planmagnet/controls/PrioritizationControls.d.ts +36 -0
  25. package/dist/planmagnet/controls/PrioritizationControls.d.ts.map +1 -1
  26. package/dist/planmagnet/controls/PrioritizationControls.js +118 -1
  27. package/dist/planmagnet/controls/PrioritizationControls.js.map +1 -1
  28. package/dist/planmagnet/controls/SyncControls.d.ts.map +1 -1
  29. package/dist/planmagnet/controls/SyncControls.js +1 -0
  30. package/dist/planmagnet/controls/SyncControls.js.map +1 -1
  31. package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts +47 -0
  32. package/dist/planmagnet/controls/WebhookSubscriptionControls.d.ts.map +1 -0
  33. package/dist/planmagnet/controls/WebhookSubscriptionControls.js +542 -0
  34. package/dist/planmagnet/controls/WebhookSubscriptionControls.js.map +1 -0
  35. package/dist/planmagnet/dashboards/DashboardUI.js +8 -8
  36. package/dist/planmagnet/dashboards/cards/RiskSeverityCard.js +4 -4
  37. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.d.ts.map +1 -1
  38. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js +67 -59
  39. package/dist/planmagnet/dashboards/cards/SprintCapacityCard.js.map +1 -1
  40. package/dist/planmagnet/forecast/DeliveryForecastCard.js +8 -8
  41. package/dist/planmagnet/forecast/ProjectOutlookCard.js +10 -10
  42. package/dist/planmagnet/forecast/ProjectRiskSummaryCard.js +9 -9
  43. package/dist/planmagnet/forecast/ResourceForecastCard.js +6 -6
  44. package/dist/planmagnet/integrations/syncTypes.d.ts +2 -1
  45. package/dist/planmagnet/integrations/syncTypes.d.ts.map +1 -1
  46. package/dist/planmagnet/integrations/syncTypes.js +19 -9
  47. package/dist/planmagnet/integrations/syncTypes.js.map +1 -1
  48. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -1
  49. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +290 -283
  50. package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  51. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.d.ts.map +1 -1
  52. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js +126 -63
  53. package/dist/planmagnet/pages/CompetitorsCompetitorDetailPagePage.js.map +1 -1
  54. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.d.ts.map +1 -1
  55. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js +14 -0
  56. package/dist/planmagnet/pages/CompetitorsCompetitorsPagePage.js.map +1 -1
  57. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.d.ts.map +1 -1
  58. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js +93 -57
  59. package/dist/planmagnet/pages/CompetitorsCreateCompetitorPagePage.js.map +1 -1
  60. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.d.ts.map +1 -1
  61. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js +125 -83
  62. package/dist/planmagnet/pages/CompetitorsEditCompetitorPagePage.js.map +1 -1
  63. package/dist/planmagnet/pages/DashboardDashboardPagePage.js +23 -23
  64. package/dist/planmagnet/pages/DocsDocDetailPagePage.d.ts.map +1 -1
  65. package/dist/planmagnet/pages/DocsDocDetailPagePage.js +340 -248
  66. package/dist/planmagnet/pages/DocsDocDetailPagePage.js.map +1 -1
  67. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.d.ts.map +1 -1
  68. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js +172 -167
  69. package/dist/planmagnet/pages/IntegrationsSyncDetailPagePage.js.map +1 -1
  70. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.d.ts.map +1 -1
  71. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js +92 -83
  72. package/dist/planmagnet/pages/IntegrationsSyncsPagePage.js.map +1 -1
  73. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts +2 -0
  74. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.d.ts.map +1 -0
  75. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js +175 -0
  76. package/dist/planmagnet/pages/IntegrationsWebhooksPagePage.js.map +1 -0
  77. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.d.ts.map +1 -1
  78. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js +226 -126
  79. package/dist/planmagnet/pages/PortfoliosPortfolioDetailPagePage.js.map +1 -1
  80. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -1
  81. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js +151 -126
  82. package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.js.map +1 -1
  83. package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -1
  84. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +169 -122
  85. package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
  86. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -1
  87. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +165 -109
  88. package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
  89. package/dist/planmagnet/pages/ProductsProductsPagePage.js +13 -13
  90. package/dist/planmagnet/pages/ProjectsAtRiskPagePage.js +9 -9
  91. package/dist/planmagnet/pages/ProjectsBudgetsPagePage.js +8 -8
  92. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  93. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +15 -3
  94. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  95. package/dist/planmagnet/pages/ProjectsProjectsPagePage.js +12 -12
  96. package/dist/planmagnet/pages/ReportsReportsPagePage.js +23 -23
  97. package/dist/planmagnet/pages/TasksMyDashboardPagePage.js +18 -18
  98. package/dist/planmagnet/pages/TasksMyWorkPagePage.js +10 -10
  99. package/dist/planmagnet/pages/TasksTimeEntriesPagePage.js +5 -5
  100. package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -1
  101. package/dist/planmagnet/pages/TeamTeamPagePage.js +59 -53
  102. package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
  103. package/dist/planmagnet/pages/analytics/DeliveryHealthCards.js +8 -8
  104. package/dist/planmagnet/pages/analytics/DeliveryKpisCard.js +6 -6
  105. package/dist/planmagnet/pages/analytics/MetricsCard.d.ts +8 -0
  106. package/dist/planmagnet/pages/analytics/MetricsCard.d.ts.map +1 -0
  107. package/dist/planmagnet/pages/analytics/MetricsCard.js +164 -0
  108. package/dist/planmagnet/pages/analytics/MetricsCard.js.map +1 -0
  109. package/dist/planmagnet/pages/analytics/QualityMetricsCard.js +6 -6
  110. package/dist/planmagnet/pages/analytics/SprintDeliveryCards.js +8 -8
  111. package/dist/planmagnet/pages/analytics/StatusFlowCard.js +7 -7
  112. package/dist/planmagnet/pages/analytics/ThroughputCard.js +7 -7
  113. package/dist/planmagnet/pages/analytics/WorkBreakdownCard.js +7 -7
  114. package/dist/planmagnet/people/People.d.ts +14 -0
  115. package/dist/planmagnet/people/People.d.ts.map +1 -1
  116. package/dist/planmagnet/people/People.js +36 -22
  117. package/dist/planmagnet/people/People.js.map +1 -1
  118. package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts +2 -0
  119. package/dist/planmagnet/team/UnmatchedCrewIdentities.d.ts.map +1 -0
  120. package/dist/planmagnet/team/UnmatchedCrewIdentities.js +155 -0
  121. package/dist/planmagnet/team/UnmatchedCrewIdentities.js.map +1 -0
  122. package/dist/planmagnet/webhooks/webhookTypes.d.ts +54 -0
  123. package/dist/planmagnet/webhooks/webhookTypes.d.ts.map +1 -0
  124. package/dist/planmagnet/webhooks/webhookTypes.js +17 -0
  125. package/dist/planmagnet/webhooks/webhookTypes.js.map +1 -0
  126. package/package.json +1 -1
@@ -1,15 +1,17 @@
1
1
  import { usePlanMagnetNavigate as e } from "../providers/PlanMagnetProvider.js";
2
- import { throwOnError as t } from "../utils/mutationResult.js";
3
- import { detailPath as n } from "../utils/rowNavigation.js";
4
- import { useMemo as r, useState as i } from "react";
5
- import { ArrowLeft as a, Loader2 as o, Save as s } from "lucide-react";
6
- import { useParams as c } from "react-router";
7
- import { gql as l } from "@apollo/client";
8
- import { useMutation as u, useQuery as d } from "@apollo/client/react";
9
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
10
- import { Button as m, Card as h, CardContent as g, CardHeader as _, CardTitle as v, Input as y } from "@burdenoff/fe-libs/ui";
2
+ import { mutationErrorMessage as t } from "../utils/graphqlErrors.js";
3
+ import { throwOnError as n } from "../utils/mutationResult.js";
4
+ import { detailPath as r } from "../utils/rowNavigation.js";
5
+ import { JsonKeyValueEditor as i, StringListEditor as a, cleanStringList as o, competitorListValid as s, jsonRowsToObject as c, jsonRowsValid as l, jsonToRows as u } from "../controls/CompetitorControls.js";
6
+ import { useMemo as d, useState as f } from "react";
7
+ import { ArrowLeft as ee, Loader2 as p, Save as m } from "lucide-react";
8
+ import { useParams as te } from "react-router";
9
+ import { gql as h } from "@apollo/client";
10
+ import { useMutation as g, useQuery as _ } from "@apollo/client/react";
11
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
12
+ import { Button as b, Card as x, CardContent as S, CardHeader as C, CardTitle as w, Input as T } from "@burdenoff/fe-libs/ui";
11
13
  //#region src/planmagnet/pages/CompetitorsEditCompetitorPagePage.tsx
12
- var b = l`
14
+ var ne = h`
13
15
  query GetCompetitorForEdit($id: ID!) {
14
16
  planmagnetCompetitor(id: $id) {
15
17
  id
@@ -17,9 +19,13 @@ var b = l`
17
19
  website
18
20
  description
19
21
  tags
22
+ strengths
23
+ weaknesses
24
+ pricing
25
+ features
20
26
  }
21
27
  }
22
- `, x = l`
28
+ `, re = h`
23
29
  mutation UpdateCompetitor($id: ID!, $input: PlanmagnetUpdateCompetitorInput!) {
24
30
  planmagnetUpdateCompetitor(id: $id, input: $input) {
25
31
  id
@@ -27,15 +33,19 @@ var b = l`
27
33
  website
28
34
  description
29
35
  tags
36
+ strengths
37
+ weaknesses
38
+ pricing
39
+ features
30
40
  updatedAt
31
41
  }
32
42
  }
33
43
  `;
34
- function S() {
35
- let l = e(), S = c().id ?? "", { data: C, loading: w, error: T } = d(b, {
36
- variables: { id: S },
37
- skip: !S
38
- }), [E, { loading: D }] = u(x, {
44
+ function E() {
45
+ let h = e(), E = te().id ?? "", { data: D, loading: O, error: k } = _(ne, {
46
+ variables: { id: E },
47
+ skip: !E
48
+ }), [A, { loading: j }] = g(re, {
39
49
  refetchQueries: [
40
50
  "ListCompetitors",
41
51
  "GetCompetitorForEdit",
@@ -43,139 +53,171 @@ function S() {
43
53
  "PickerCompetitors"
44
54
  ],
45
55
  awaitRefetchQueries: !0
46
- }), [O, k] = i(null), [A, j] = i(!1), M = C?.planmagnetCompetitor, N = r(() => ({
47
- name: M?.name ?? "",
48
- website: M?.website ?? "",
49
- description: M?.description ?? "",
50
- tags: M?.tags?.join(", ") ?? ""
51
- }), [M]), [P, F] = i({}), I = {
52
- ...N,
53
- ...P
54
- }, L = (e) => F(e);
55
- return w && !C ? /* @__PURE__ */ f("div", {
56
+ }), [M, N] = f(null), [ie, P] = f(!1), F = D?.planmagnetCompetitor, I = d(() => ({
57
+ name: F?.name ?? "",
58
+ website: F?.website ?? "",
59
+ description: F?.description ?? "",
60
+ tags: F?.tags?.join(", ") ?? ""
61
+ }), [F]), [ae, oe] = f({}), L = {
62
+ ...I,
63
+ ...ae
64
+ }, R = (e) => oe(e), z = d(() => F?.strengths ?? [], [F]), B = d(() => F?.weaknesses ?? [], [F]), V = d(() => u(F?.pricing), [F]), H = d(() => u(F?.features), [F]), [U, W] = f(null), [G, K] = f(null), [q, se] = f(null), [J, ce] = f(null), Y = U ?? z, X = G ?? B, Z = q ?? V, Q = J ?? H, $ = s(Y) && s(X) && l(Z) && l(Q);
65
+ return O && !D ? /* @__PURE__ */ v("div", {
56
66
  className: "flex items-center justify-center p-12",
57
- children: /* @__PURE__ */ f(o, { className: "h-8 w-8 animate-spin text-muted-foreground" })
58
- }) : T ? /* @__PURE__ */ p("div", {
67
+ children: /* @__PURE__ */ v(p, { className: "h-8 w-8 animate-spin text-muted-foreground" })
68
+ }) : k ? /* @__PURE__ */ y("div", {
59
69
  className: "p-6 text-destructive",
60
- children: ["Failed to load competitor: ", T.message]
61
- }) : M ? /* @__PURE__ */ p("div", {
70
+ children: ["Failed to load competitor: ", k.message]
71
+ }) : F ? /* @__PURE__ */ y("div", {
62
72
  className: "space-y-6 p-6 max-w-4xl",
63
73
  children: [
64
- /* @__PURE__ */ p("div", {
74
+ /* @__PURE__ */ y("div", {
65
75
  className: "flex items-center justify-between",
66
- children: [/* @__PURE__ */ p("div", {
76
+ children: [/* @__PURE__ */ y("div", {
67
77
  className: "flex items-center gap-3",
68
- children: [/* @__PURE__ */ f(m, {
78
+ children: [/* @__PURE__ */ v(b, {
69
79
  variant: "ghost",
70
80
  size: "sm",
71
81
  "aria-label": "Back to the competitor",
72
- onClick: () => l(n("/products/competitor-detail-page", S)),
73
- children: /* @__PURE__ */ f(a, { className: "h-4 w-4" })
74
- }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
82
+ onClick: () => h(r("/products/competitor-detail-page", E)),
83
+ children: /* @__PURE__ */ v(ee, { className: "h-4 w-4" })
84
+ }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h1", {
75
85
  className: "text-2xl font-semibold",
76
86
  children: "Edit Competitor"
77
- }), /* @__PURE__ */ f("p", {
87
+ }), /* @__PURE__ */ v("p", {
78
88
  className: "text-sm text-muted-foreground",
79
- children: M.name
89
+ children: F.name
80
90
  })] })]
81
- }), /* @__PURE__ */ p(m, {
91
+ }), /* @__PURE__ */ y(b, {
82
92
  size: "sm",
83
93
  onClick: async () => {
84
- if (!M || !I.name.trim()) return;
85
- let e = (e) => e.split(",").map((e) => e.trim()).filter(Boolean), n = {
86
- name: I.name.trim(),
94
+ if (!F || !L.name.trim() || !$) return;
95
+ let e = (e) => e.split(",").map((e) => e.trim()).filter(Boolean), r = {
96
+ name: L.name.trim(),
97
+ website: L.website.trim() || null,
98
+ description: L.description.trim() || null,
99
+ tags: e(L.tags)
100
+ }, i = {
101
+ name: I.name,
87
102
  website: I.website.trim() || null,
88
103
  description: I.description.trim() || null,
89
104
  tags: e(I.tags)
90
- }, r = {
91
- name: N.name,
92
- website: N.website.trim() || null,
93
- description: N.description.trim() || null,
94
- tags: e(N.tags)
95
- }, i = Object.fromEntries(Object.entries(n).filter(([e, t]) => JSON.stringify(t) !== JSON.stringify(r[e])));
96
- if (k(null), j(!1), Object.keys(i).length === 0) {
97
- j(!0);
105
+ };
106
+ U !== null && (r.strengths = o(Y), i.strengths = o(z)), G !== null && (r.weaknesses = o(X), i.weaknesses = o(B)), q !== null && (r.pricing = c(Z), i.pricing = F.pricing ?? null), J !== null && (r.features = c(Q), i.features = F.features ?? null);
107
+ let a = Object.fromEntries(Object.entries(r).filter(([e, t]) => JSON.stringify(t) !== JSON.stringify(i[e])));
108
+ if (N(null), P(!1), Object.keys(a).length === 0) {
109
+ P(!0);
98
110
  return;
99
111
  }
100
112
  try {
101
- await t(E({ variables: {
102
- id: S,
103
- input: i
104
- } })), j(!0);
113
+ await n(A({ variables: {
114
+ id: E,
115
+ input: a
116
+ } })), P(!0);
105
117
  } catch (e) {
106
- k(e instanceof Error ? e.message : "The competitor could not be saved.");
118
+ N(t(e, "The competitor could not be saved."));
107
119
  }
108
120
  },
109
- disabled: D || !I.name.trim(),
110
- children: [D ? /* @__PURE__ */ f(o, { className: "mr-1 h-4 w-4 animate-spin" }) : /* @__PURE__ */ f(s, { className: "mr-1 h-4 w-4" }), "Save Changes"]
121
+ disabled: j || !L.name.trim() || !$,
122
+ children: [j ? /* @__PURE__ */ v(p, { className: "mr-1 h-4 w-4 animate-spin" }) : /* @__PURE__ */ v(m, { className: "mr-1 h-4 w-4" }), "Save Changes"]
111
123
  })]
112
124
  }),
113
- A && /* @__PURE__ */ f("div", {
125
+ ie && /* @__PURE__ */ v("div", {
114
126
  role: "status",
115
127
  className: "p-3 bg-muted text-status-success-text rounded-md text-sm",
116
128
  children: "Changes saved."
117
129
  }),
118
- O && /* @__PURE__ */ f("div", {
130
+ M && /* @__PURE__ */ v("div", {
119
131
  role: "alert",
120
132
  className: "p-3 rounded-md bg-destructive/10 text-destructive text-sm",
121
- children: O
133
+ children: M
122
134
  }),
123
- /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ f(_, { children: /* @__PURE__ */ f(v, { children: "Competitor Details" }) }), /* @__PURE__ */ p(g, {
135
+ /* @__PURE__ */ y(x, { children: [/* @__PURE__ */ v(C, { children: /* @__PURE__ */ v(w, { children: "Competitor Details" }) }), /* @__PURE__ */ y(S, {
124
136
  className: "space-y-4",
125
137
  children: [
126
- /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
138
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
127
139
  className: "text-sm font-medium",
128
140
  children: "Name"
129
- }), /* @__PURE__ */ f(y, {
130
- value: I.name,
131
- onChange: (e) => L({
132
- ...I,
141
+ }), /* @__PURE__ */ v(T, {
142
+ value: L.name,
143
+ onChange: (e) => R({
144
+ ...L,
133
145
  name: e.target.value
134
146
  }),
135
147
  className: "mt-1"
136
148
  })] }),
137
- /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
149
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
138
150
  className: "text-sm font-medium",
139
151
  children: "Website"
140
- }), /* @__PURE__ */ f(y, {
141
- value: I.website,
142
- onChange: (e) => L({
143
- ...I,
152
+ }), /* @__PURE__ */ v(T, {
153
+ value: L.website,
154
+ onChange: (e) => R({
155
+ ...L,
144
156
  website: e.target.value
145
157
  }),
146
158
  className: "mt-1"
147
159
  })] }),
148
- /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
160
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
149
161
  className: "text-sm font-medium",
150
162
  children: "Description / Notes"
151
- }), /* @__PURE__ */ f("textarea", {
163
+ }), /* @__PURE__ */ v("textarea", {
152
164
  className: "mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]",
153
- value: I.description,
154
- onChange: (e) => L({
155
- ...I,
165
+ value: L.description,
166
+ onChange: (e) => R({
167
+ ...L,
156
168
  description: e.target.value
157
169
  })
158
170
  })] }),
159
- /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
171
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
160
172
  className: "text-sm font-medium",
161
173
  children: "Tags (comma-separated)"
162
- }), /* @__PURE__ */ f(y, {
163
- value: I.tags,
164
- onChange: (e) => L({
165
- ...I,
174
+ }), /* @__PURE__ */ v(T, {
175
+ value: L.tags,
176
+ onChange: (e) => R({
177
+ ...L,
166
178
  tags: e.target.value
167
179
  }),
168
180
  className: "mt-1"
169
181
  })] })
170
182
  ]
183
+ })] }),
184
+ /* @__PURE__ */ y(x, { children: [/* @__PURE__ */ v(C, { children: /* @__PURE__ */ v(w, { children: "Strengths & Weaknesses" }) }), /* @__PURE__ */ y(S, {
185
+ className: "space-y-4",
186
+ children: [/* @__PURE__ */ v(a, {
187
+ label: "Strengths",
188
+ values: Y,
189
+ onChange: W,
190
+ placeholder: "e.g. Strong enterprise SSO",
191
+ testId: "competitor-strengths"
192
+ }), /* @__PURE__ */ v(a, {
193
+ label: "Weaknesses",
194
+ values: X,
195
+ onChange: K,
196
+ placeholder: "e.g. No mobile app",
197
+ testId: "competitor-weaknesses"
198
+ })]
199
+ })] }),
200
+ /* @__PURE__ */ y(x, { children: [/* @__PURE__ */ v(C, { children: /* @__PURE__ */ v(w, { children: "Pricing & Feature Comparison" }) }), /* @__PURE__ */ y(S, {
201
+ className: "space-y-4",
202
+ children: [/* @__PURE__ */ v(i, {
203
+ label: "Pricing",
204
+ rows: Z,
205
+ onChange: se,
206
+ testId: "competitor-pricing"
207
+ }), /* @__PURE__ */ v(i, {
208
+ label: "Features",
209
+ rows: Q,
210
+ onChange: ce,
211
+ testId: "competitor-features"
212
+ })]
171
213
  })] })
172
214
  ]
173
- }) : /* @__PURE__ */ f("div", {
215
+ }) : /* @__PURE__ */ v("div", {
174
216
  className: "p-6 text-muted-foreground",
175
217
  children: "Competitor not found."
176
218
  });
177
219
  }
178
220
  //#endregion
179
- export { S as CompetitorsEditCompetitorPagePage };
221
+ export { E as CompetitorsEditCompetitorPagePage };
180
222
 
181
223
  //# sourceMappingURL=CompetitorsEditCompetitorPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CompetitorsEditCompetitorPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/CompetitorsEditCompetitorPagePage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, ArrowLeft, Loader2 } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { throwOnError } from '../utils/mutationResult';\n\nconst GET_COMPETITOR = gql`\n query GetCompetitorForEdit($id: ID!) {\n planmagnetCompetitor(id: $id) {\n id\n name\n website\n description\n tags\n }\n }\n`;\n\nconst UPDATE_COMPETITOR = gql`\n mutation UpdateCompetitor($id: ID!, $input: PlanmagnetUpdateCompetitorInput!) {\n planmagnetUpdateCompetitor(id: $id, input: $input) {\n id\n name\n website\n description\n tags\n updatedAt\n }\n }\n`;\n\nexport function CompetitorsEditCompetitorPagePage() {\n const navigate = usePlanMagnetNavigate();\n const params = useParams<{ id: string }>();\n const competitorId = params.id ?? '';\n\n const { data, loading, error } = useQuery<{\n planmagnetCompetitor: {\n id: string;\n name: string;\n website: string | null;\n description: string | null;\n tags: string[];\n } | null;\n }>(GET_COMPETITOR, { variables: { id: competitorId }, skip: !competitorId });\n\n const [updateCompetitor, { loading: saving }] = useMutation(UPDATE_COMPETITOR, {\n refetchQueries: [\n 'ListCompetitors',\n 'GetCompetitorForEdit',\n 'GetCompetitor',\n 'PickerCompetitors',\n ],\n awaitRefetchQueries: true,\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n\n const competitor = data?.planmagnetCompetitor;\n\n const defaultForm = useMemo(\n () => ({\n name: competitor?.name ?? '',\n website: competitor?.website ?? '',\n description: competitor?.description ?? '',\n tags: competitor?.tags?.join(', ') ?? '',\n }),\n [competitor]\n );\n\n const [formOverrides, setFormOverrides] = useState<Record<string, string>>({});\n const form = { ...defaultForm, ...formOverrides };\n const setForm = (val: Record<string, string>) => setFormOverrides(val);\n\n const handleSave = async () => {\n if (!competitor || !form.name.trim()) return;\n const tagList = (v: string) =>\n v\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const next: Record<string, unknown> = {\n name: form.name.trim(),\n website: form.website.trim() || null,\n description: form.description.trim() || null,\n tags: tagList(form.tags),\n };\n const before: Record<string, unknown> = {\n name: defaultForm.name,\n website: defaultForm.website.trim() || null,\n description: defaultForm.description.trim() || null,\n tags: tagList(defaultForm.tags),\n };\n const input = Object.fromEntries(\n Object.entries(next).filter(([k, v]) => JSON.stringify(v) !== JSON.stringify(before[k]))\n );\n setSaveError(null);\n setSaved(false);\n if (Object.keys(input).length === 0) {\n setSaved(true);\n return;\n }\n try {\n await throwOnError(updateCompetitor({ variables: { id: competitorId, input } }));\n setSaved(true);\n } catch (e) {\n setSaveError(e instanceof Error ? e.message : 'The competitor could not be saved.');\n }\n };\n\n // Only before the first load: a refetch must not blank the page (it unmounts every component on it and\n // loses their state).\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load competitor: {error.message}</div>;\n }\n\n if (!competitor) return <div className=\"p-6 text-muted-foreground\">Competitor not found.</div>;\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Back to the competitor\"\n onClick={() => navigate(detailPath('/products/competitor-detail-page', competitorId))}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold\">Edit Competitor</h1>\n <p className=\"text-sm text-muted-foreground\">{competitor.name}</p>\n </div>\n </div>\n <Button size=\"sm\" onClick={handleSave} disabled={saving || !form.name.trim()}>\n {saving ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"mr-1 h-4 w-4\" />\n )}\n Save Changes\n </Button>\n </div>\n\n {saved && (\n <div role=\"status\" className=\"p-3 bg-muted text-status-success-text rounded-md text-sm\">\n Changes saved.\n </div>\n )}\n {saveError && (\n <div role=\"alert\" className=\"p-3 rounded-md bg-destructive/10 text-destructive text-sm\">\n {saveError}\n </div>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>Competitor Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Website</label>\n <Input\n value={form.website}\n onChange={(e) => setForm({ ...form, website: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description / Notes</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Tags (comma-separated)</label>\n <Input\n value={form.tags}\n onChange={(e) => setForm({ ...form, tags: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CompetitorsEditCompetitorPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/CompetitorsEditCompetitorPagePage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, ArrowLeft, Loader2 } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { detailPath } from '../utils/rowNavigation';\nimport { throwOnError } from '../utils/mutationResult';\nimport { mutationErrorMessage } from '../utils/graphqlErrors';\nimport {\n JsonKeyValueEditor,\n StringListEditor,\n cleanStringList,\n competitorListValid,\n jsonRowsToObject,\n jsonRowsValid,\n jsonToRows,\n type JsonKeyValueRow,\n} from '../controls/CompetitorControls';\n\nconst GET_COMPETITOR = gql`\n query GetCompetitorForEdit($id: ID!) {\n planmagnetCompetitor(id: $id) {\n id\n name\n website\n description\n tags\n strengths\n weaknesses\n pricing\n features\n }\n }\n`;\n\nconst UPDATE_COMPETITOR = gql`\n mutation UpdateCompetitor($id: ID!, $input: PlanmagnetUpdateCompetitorInput!) {\n planmagnetUpdateCompetitor(id: $id, input: $input) {\n id\n name\n website\n description\n tags\n strengths\n weaknesses\n pricing\n features\n updatedAt\n }\n }\n`;\n\nexport function CompetitorsEditCompetitorPagePage() {\n const navigate = usePlanMagnetNavigate();\n const params = useParams<{ id: string }>();\n const competitorId = params.id ?? '';\n\n const { data, loading, error } = useQuery<{\n planmagnetCompetitor: {\n id: string;\n name: string;\n website: string | null;\n description: string | null;\n tags: string[];\n strengths: string[];\n weaknesses: string[];\n pricing: unknown;\n features: unknown;\n } | null;\n }>(GET_COMPETITOR, { variables: { id: competitorId }, skip: !competitorId });\n\n const [updateCompetitor, { loading: saving }] = useMutation(UPDATE_COMPETITOR, {\n refetchQueries: [\n 'ListCompetitors',\n 'GetCompetitorForEdit',\n 'GetCompetitor',\n 'PickerCompetitors',\n ],\n awaitRefetchQueries: true,\n });\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n\n const competitor = data?.planmagnetCompetitor;\n\n const defaultForm = useMemo(\n () => ({\n name: competitor?.name ?? '',\n website: competitor?.website ?? '',\n description: competitor?.description ?? '',\n tags: competitor?.tags?.join(', ') ?? '',\n }),\n [competitor]\n );\n\n const [formOverrides, setFormOverrides] = useState<Record<string, string>>({});\n const form = { ...defaultForm, ...formOverrides };\n const setForm = (val: Record<string, string>) => setFormOverrides(val);\n\n // PRM-31 — array/object fields can't live in the plain string `form` above; same \"null override = still\n // following the loaded record\" shape, just per-field instead of merged into one object.\n const defaultStrengths = useMemo(() => competitor?.strengths ?? [], [competitor]);\n const defaultWeaknesses = useMemo(() => competitor?.weaknesses ?? [], [competitor]);\n const defaultPricingRows = useMemo(() => jsonToRows(competitor?.pricing), [competitor]);\n const defaultFeaturesRows = useMemo(() => jsonToRows(competitor?.features), [competitor]);\n const [strengthsOverride, setStrengthsOverride] = useState<string[] | null>(null);\n const [weaknessesOverride, setWeaknessesOverride] = useState<string[] | null>(null);\n const [pricingOverride, setPricingOverride] = useState<JsonKeyValueRow[] | null>(null);\n const [featuresOverride, setFeaturesOverride] = useState<JsonKeyValueRow[] | null>(null);\n const strengths = strengthsOverride ?? defaultStrengths;\n const weaknesses = weaknessesOverride ?? defaultWeaknesses;\n const pricingRows = pricingOverride ?? defaultPricingRows;\n const featuresRows = featuresOverride ?? defaultFeaturesRows;\n\n const fieldsValid =\n competitorListValid(strengths) &&\n competitorListValid(weaknesses) &&\n jsonRowsValid(pricingRows) &&\n jsonRowsValid(featuresRows);\n\n const handleSave = async () => {\n if (!competitor || !form.name.trim() || !fieldsValid) return;\n const tagList = (v: string) =>\n v\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const next: Record<string, unknown> = {\n name: form.name.trim(),\n website: form.website.trim() || null,\n description: form.description.trim() || null,\n tags: tagList(form.tags),\n };\n const before: Record<string, unknown> = {\n name: defaultForm.name,\n website: defaultForm.website.trim() || null,\n description: defaultForm.description.trim() || null,\n tags: tagList(defaultForm.tags),\n };\n // PRM-31 — only even considered once the user actually opened that editor and changed something: a\n // pricing/features value this editor cannot fully represent (a nested object/array — see jsonToRows) round-\n // trips through its rows as a flattened string, which must never go out as an unrequested side effect of\n // saving some other, unrelated field.\n if (strengthsOverride !== null) {\n next.strengths = cleanStringList(strengths);\n before.strengths = cleanStringList(defaultStrengths);\n }\n if (weaknessesOverride !== null) {\n next.weaknesses = cleanStringList(weaknesses);\n before.weaknesses = cleanStringList(defaultWeaknesses);\n }\n if (pricingOverride !== null) {\n next.pricing = jsonRowsToObject(pricingRows);\n before.pricing = competitor.pricing ?? null;\n }\n if (featuresOverride !== null) {\n next.features = jsonRowsToObject(featuresRows);\n before.features = competitor.features ?? null;\n }\n const input = Object.fromEntries(\n Object.entries(next).filter(([k, v]) => JSON.stringify(v) !== JSON.stringify(before[k]))\n );\n setSaveError(null);\n setSaved(false);\n if (Object.keys(input).length === 0) {\n setSaved(true);\n return;\n }\n try {\n await throwOnError(updateCompetitor({ variables: { id: competitorId, input } }));\n setSaved(true);\n } catch (e) {\n setSaveError(mutationErrorMessage(e, 'The competitor could not be saved.'));\n }\n };\n\n // Only before the first load: a refetch must not blank the page (it unmounts every component on it and\n // loses their state).\n if (loading && !data) {\n return (\n <div className=\"flex items-center justify-center p-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n );\n }\n\n if (error) {\n return <div className=\"p-6 text-destructive\">Failed to load competitor: {error.message}</div>;\n }\n\n if (!competitor) return <div className=\"p-6 text-muted-foreground\">Competitor not found.</div>;\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Back to the competitor\"\n onClick={() => navigate(detailPath('/products/competitor-detail-page', competitorId))}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <h1 className=\"text-2xl font-semibold\">Edit Competitor</h1>\n <p className=\"text-sm text-muted-foreground\">{competitor.name}</p>\n </div>\n </div>\n <Button\n size=\"sm\"\n onClick={handleSave}\n disabled={saving || !form.name.trim() || !fieldsValid}\n >\n {saving ? (\n <Loader2 className=\"mr-1 h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"mr-1 h-4 w-4\" />\n )}\n Save Changes\n </Button>\n </div>\n\n {saved && (\n <div role=\"status\" className=\"p-3 bg-muted text-status-success-text rounded-md text-sm\">\n Changes saved.\n </div>\n )}\n {saveError && (\n <div role=\"alert\" className=\"p-3 rounded-md bg-destructive/10 text-destructive text-sm\">\n {saveError}\n </div>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>Competitor Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Website</label>\n <Input\n value={form.website}\n onChange={(e) => setForm({ ...form, website: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description / Notes</label>\n <textarea\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm min-h-[80px]\"\n value={form.description}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Tags (comma-separated)</label>\n <Input\n value={form.tags}\n onChange={(e) => setForm({ ...form, tags: e.target.value })}\n className=\"mt-1\"\n />\n </div>\n </CardContent>\n </Card>\n\n {/* PRM-31 */}\n <Card>\n <CardHeader>\n <CardTitle>Strengths &amp; Weaknesses</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <StringListEditor\n label=\"Strengths\"\n values={strengths}\n onChange={setStrengthsOverride}\n placeholder=\"e.g. Strong enterprise SSO\"\n testId=\"competitor-strengths\"\n />\n <StringListEditor\n label=\"Weaknesses\"\n values={weaknesses}\n onChange={setWeaknessesOverride}\n placeholder=\"e.g. No mobile app\"\n testId=\"competitor-weaknesses\"\n />\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Pricing &amp; Feature Comparison</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <JsonKeyValueEditor\n label=\"Pricing\"\n rows={pricingRows}\n onChange={setPricingOverride}\n testId=\"competitor-pricing\"\n />\n <JsonKeyValueEditor\n label=\"Features\"\n rows={featuresRows}\n onChange={setFeaturesOverride}\n testId=\"competitor-features\"\n />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -9,8 +9,8 @@ import { AlertTriangle as m, ArrowUpRight as h, Calendar as g, CheckSquare as _,
9
9
  import { gql as C } from "@apollo/client";
10
10
  import { useQuery as w } from "@apollo/client/react";
11
11
  import { Fragment as T, jsx as E, jsxs as D } from "react/jsx-runtime";
12
- import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
- import { Badge as k, Card as A, CardContent as j, CardHeader as M, CardTitle as N } from "@burdenoff/fe-libs/ui";
12
+ import { Badge as O, Card as k, CardContent as A, CardHeader as j, CardTitle as M } from "@burdenoff/fe-libs/ui";
13
+ import { useI18n as N } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
14
14
  //#region src/planmagnet/pages/DashboardDashboardPagePage.tsx
15
15
  var P = [
16
16
  "GetDashboardData",
@@ -121,7 +121,7 @@ var P = [
121
121
  }
122
122
  `;
123
123
  function I() {
124
- let { workspaceId: C } = e(), { t: I } = O(), { data: L, loading: R, error: z } = w(F, { variables: {
124
+ let { workspaceId: C } = e(), { t: I } = N(), { data: L, loading: R, error: z } = w(F, { variables: {
125
125
  workspaceId: C ?? "default",
126
126
  today: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
127
127
  } }), B = i(), V = a(), H = t(), U = f({
@@ -181,16 +181,16 @@ function I() {
181
181
  }),
182
182
  /* @__PURE__ */ E("div", {
183
183
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
184
- children: Y.map((e) => /* @__PURE__ */ D(A, {
184
+ children: Y.map((e) => /* @__PURE__ */ D(k, {
185
185
  "data-testid": "dashboard-tile-link",
186
186
  ...l(() => H(`/analytics/analytics-page${u(d("30"))}`), `${e.label}: ${e.value}. ${I("planmagnet.dashboard.metrics.openAnalytics", "Open in Analytics")}`),
187
- children: [/* @__PURE__ */ D(M, {
187
+ children: [/* @__PURE__ */ D(j, {
188
188
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
189
- children: [/* @__PURE__ */ E(N, {
189
+ children: [/* @__PURE__ */ E(M, {
190
190
  className: "text-sm font-medium",
191
191
  children: e.label
192
192
  }), /* @__PURE__ */ E(b, { className: "h-4 w-4 text-muted-foreground" })]
193
- }), /* @__PURE__ */ D(j, { children: [/* @__PURE__ */ E("div", {
193
+ }), /* @__PURE__ */ D(A, { children: [/* @__PURE__ */ E("div", {
194
194
  className: "text-2xl font-bold",
195
195
  children: e.value
196
196
  }), /* @__PURE__ */ E("p", {
@@ -201,12 +201,12 @@ function I() {
201
201
  }),
202
202
  /* @__PURE__ */ D("div", {
203
203
  className: "grid gap-6 lg:grid-cols-12",
204
- children: [/* @__PURE__ */ D(A, {
204
+ children: [/* @__PURE__ */ D(k, {
205
205
  className: "lg:col-span-8",
206
- children: [/* @__PURE__ */ E(M, { children: /* @__PURE__ */ D(N, {
206
+ children: [/* @__PURE__ */ E(j, { children: /* @__PURE__ */ D(M, {
207
207
  className: "flex items-center gap-2 text-base",
208
208
  children: [/* @__PURE__ */ E(S, { className: "h-5 w-5 text-blue-500" }), I("planmagnet.dashboard.activeSprints.title", "Active Sprints")]
209
- }) }), /* @__PURE__ */ D(j, {
209
+ }) }), /* @__PURE__ */ D(A, {
210
210
  className: "space-y-4",
211
211
  children: [K.map((e) => {
212
212
  let t = e.workItems.reduce((e, t) => e + (t.storyPoints ?? 0), 0), n = e.workItems.filter((e) => e.status === "DONE").reduce((e, t) => e + (t.storyPoints ?? 0), 0), r = e.workItems.length, i = e.workItems.filter((e) => e.status === "DONE").length, a = o(e.workItems) ?? 0;
@@ -231,7 +231,7 @@ function I() {
231
231
  " ",
232
232
  e.project?.name ?? I("planmagnet.dashboard.shared.projectUnavailable", "not available")
233
233
  ] })
234
- })] }), /* @__PURE__ */ D(k, {
234
+ })] }), /* @__PURE__ */ D(O, {
235
235
  variant: "secondary",
236
236
  children: [
237
237
  n,
@@ -273,25 +273,25 @@ function I() {
273
273
  })]
274
274
  }), /* @__PURE__ */ D("div", {
275
275
  className: "lg:col-span-4 space-y-6",
276
- children: [G.length > 0 && /* @__PURE__ */ D(A, { children: [/* @__PURE__ */ E(M, { children: /* @__PURE__ */ D(N, {
276
+ children: [G.length > 0 && /* @__PURE__ */ D(k, { children: [/* @__PURE__ */ E(j, { children: /* @__PURE__ */ D(M, {
277
277
  className: "flex items-center gap-2 text-base",
278
278
  children: [/* @__PURE__ */ E(m, { className: "h-5 w-5 text-orange-500" }), I("planmagnet.dashboard.onHoldProjects.title", "On-Hold Projects")]
279
- }) }), /* @__PURE__ */ E(j, {
279
+ }) }), /* @__PURE__ */ E(A, {
280
280
  className: "space-y-3",
281
281
  children: G.map((e) => /* @__PURE__ */ D("div", {
282
282
  className: "flex items-center justify-between rounded border p-2",
283
283
  children: [/* @__PURE__ */ E("div", { children: /* @__PURE__ */ E("p", {
284
284
  className: "text-sm font-medium",
285
285
  children: e.name
286
- }) }), /* @__PURE__ */ E(k, {
286
+ }) }), /* @__PURE__ */ E(O, {
287
287
  variant: "destructive",
288
288
  children: e.status.toLowerCase().replace("_", " ")
289
289
  })]
290
290
  }, e.id))
291
- })] }), /* @__PURE__ */ D(A, { children: [/* @__PURE__ */ E(M, { children: /* @__PURE__ */ D(N, {
291
+ })] }), /* @__PURE__ */ D(k, { children: [/* @__PURE__ */ E(j, { children: /* @__PURE__ */ D(M, {
292
292
  className: "flex items-center gap-2 text-base",
293
293
  children: [/* @__PURE__ */ E(g, { className: "h-5 w-5 text-green-500" }), I("planmagnet.dashboard.upcomingMilestones.title", "Upcoming Milestones")]
294
- }) }), /* @__PURE__ */ D(j, {
294
+ }) }), /* @__PURE__ */ D(A, {
295
295
  className: "space-y-3",
296
296
  children: [q.map((e) => /* @__PURE__ */ D("div", {
297
297
  ...l(() => H(c("/projects/milestone-detail-page", e.id)), e.name),
@@ -321,7 +321,7 @@ function I() {
321
321
  ]
322
322
  })
323
323
  ]
324
- }), /* @__PURE__ */ E(k, {
324
+ }), /* @__PURE__ */ E(O, {
325
325
  variant: "secondary",
326
326
  className: "text-xs flex-shrink-0 capitalize",
327
327
  children: e.status.toLowerCase().replace("_", " ")
@@ -335,10 +335,10 @@ function I() {
335
335
  }),
336
336
  /* @__PURE__ */ D("div", {
337
337
  className: "grid gap-6 lg:grid-cols-2",
338
- children: [/* @__PURE__ */ D(A, { children: [/* @__PURE__ */ E(M, { children: /* @__PURE__ */ D(N, {
338
+ children: [/* @__PURE__ */ D(k, { children: [/* @__PURE__ */ E(j, { children: /* @__PURE__ */ D(M, {
339
339
  className: "flex items-center gap-2 text-base",
340
340
  children: [/* @__PURE__ */ E(_, { className: "h-5 w-5 text-purple-500" }), I("planmagnet.dashboard.recentWorkItems.title", "Recent Work Items")]
341
- }) }), /* @__PURE__ */ D(j, {
341
+ }) }), /* @__PURE__ */ D(A, {
342
342
  className: "space-y-3",
343
343
  children: [J.map((e) => /* @__PURE__ */ D("div", {
344
344
  ...l(() => H(`/tasks/task-detail-page?taskId=${encodeURIComponent(e.id)}`), `${e.key} ${e.title}`),
@@ -361,7 +361,7 @@ function I() {
361
361
  })]
362
362
  }), /* @__PURE__ */ D("div", {
363
363
  className: "flex items-center gap-2 flex-shrink-0",
364
- children: [/* @__PURE__ */ D(k, {
364
+ children: [/* @__PURE__ */ D(O, {
365
365
  variant: "outline",
366
366
  className: "text-xs",
367
367
  children: [
@@ -369,7 +369,7 @@ function I() {
369
369
  " ",
370
370
  I("planmagnet.dashboard.shared.pointsShort", "pts")
371
371
  ]
372
- }), /* @__PURE__ */ E(k, {
372
+ }), /* @__PURE__ */ E(O, {
373
373
  variant: "secondary",
374
374
  className: "text-xs capitalize",
375
375
  children: e.status.toLowerCase().replace("_", " ")
@@ -379,10 +379,10 @@ function I() {
379
379
  className: "text-sm text-muted-foreground text-center py-4",
380
380
  children: I("planmagnet.dashboard.recentWorkItems.empty", "No work items yet.")
381
381
  })]
382
- })] }), /* @__PURE__ */ D(A, { children: [/* @__PURE__ */ E(M, { children: /* @__PURE__ */ D(N, {
382
+ })] }), /* @__PURE__ */ D(k, { children: [/* @__PURE__ */ E(j, { children: /* @__PURE__ */ D(M, {
383
383
  className: "flex items-center gap-2 text-base",
384
384
  children: [/* @__PURE__ */ E(v, { className: "h-5 w-5 text-cyan-500" }), I("planmagnet.dashboard.projectStatus.title", "Project Status")]
385
- }) }), /* @__PURE__ */ D(j, {
385
+ }) }), /* @__PURE__ */ D(A, {
386
386
  className: "space-y-3",
387
387
  children: [W.map((e) => /* @__PURE__ */ D("div", {
388
388
  ...l(() => H(c("/projects/project-detail-page", e.id)), e.name),
@@ -1 +1 @@
1
- {"version":3,"file":"DocsDocDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/DocsDocDetailPagePage.tsx"],"names":[],"mappings":"AAiRA,wBAAgB,qBAAqB,4CAsrBpC"}
1
+ {"version":3,"file":"DocsDocDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/DocsDocDetailPagePage.tsx"],"names":[],"mappings":"AAwTA,wBAAgB,qBAAqB,4CA+wBpC"}