@burdenoff/microfe-planmagnet 2026.1001.2 → 2026.1001.4

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 (62) hide show
  1. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoot.js +160 -153
  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 +121 -109
  6. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  7. package/dist/planmagnet/controls/MilestoneControls.d.ts +2 -0
  8. package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -1
  9. package/dist/planmagnet/controls/MilestoneControls.js +89 -72
  10. package/dist/planmagnet/controls/MilestoneControls.js.map +1 -1
  11. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts +17 -0
  12. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts.map +1 -0
  13. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js +218 -0
  14. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js.map +1 -0
  15. package/dist/planmagnet/meetings/MeetingsCard.d.ts +7 -0
  16. package/dist/planmagnet/meetings/MeetingsCard.d.ts.map +1 -0
  17. package/dist/planmagnet/meetings/MeetingsCard.js +108 -0
  18. package/dist/planmagnet/meetings/MeetingsCard.js.map +1 -0
  19. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts +9 -0
  20. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts.map +1 -0
  21. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js +232 -0
  22. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js.map +1 -0
  23. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts +19 -0
  24. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts.map +1 -0
  25. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js +226 -0
  26. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js.map +1 -0
  27. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts +14 -0
  28. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts.map +1 -0
  29. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js +78 -0
  30. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js.map +1 -0
  31. package/dist/planmagnet/meetings/meetingActions.d.ts +58 -0
  32. package/dist/planmagnet/meetings/meetingActions.d.ts.map +1 -0
  33. package/dist/planmagnet/meetings/meetingActions.js +48 -0
  34. package/dist/planmagnet/meetings/meetingActions.js.map +1 -0
  35. package/dist/planmagnet/meetings/meetingGraphql.d.ts +29 -0
  36. package/dist/planmagnet/meetings/meetingGraphql.d.ts.map +1 -0
  37. package/dist/planmagnet/meetings/meetingGraphql.js +166 -0
  38. package/dist/planmagnet/meetings/meetingGraphql.js.map +1 -0
  39. package/dist/planmagnet/meetings/meetingModel.d.ts +74 -0
  40. package/dist/planmagnet/meetings/meetingModel.d.ts.map +1 -0
  41. package/dist/planmagnet/meetings/meetingModel.js +88 -0
  42. package/dist/planmagnet/meetings/meetingModel.js.map +1 -0
  43. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts +2 -0
  44. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts.map +1 -0
  45. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js +197 -0
  46. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js.map +1 -0
  47. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts +2 -0
  48. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts.map +1 -0
  49. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js +173 -0
  50. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js.map +1 -0
  51. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
  52. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +73 -52
  53. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
  54. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  55. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +205 -190
  56. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  57. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  58. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +192 -187
  59. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  60. package/dist/planmagnet/reports/ShareDialog.js +65 -65
  61. package/dist/planmagnet/reports/ShareDialog.js.map +1 -1
  62. package/package.json +1 -1
@@ -1,16 +1,17 @@
1
1
  import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
2
  import { PersonName as n } from "../people/People.js";
3
- import { detailPath as r, rowLinkProps as i } from "../utils/rowNavigation.js";
4
- import { NewMilestoneDialog as a } from "../create/CreateDialogs.js";
5
- import { MilestoneProgressBar as o } from "../milestones/MilestoneControls.js";
6
- import { useState as s } from "react";
7
- import { Calendar as c, Target as l, User as u } from "lucide-react";
8
- import { gql as d } from "@apollo/client";
9
- import { useQuery as f } from "@apollo/client/react";
10
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
11
- import { Badge as h, Card as g, CardContent as _, CardHeader as v, CardTitle as y } from "@burdenoff/fe-libs/ui";
3
+ import { detailPath as r, rowLinkProps as i, stopRowActivation as a } from "../utils/rowNavigation.js";
4
+ import { ScheduleMeetingDialog as o } from "../meetings/ScheduleMeetingDialog.js";
5
+ import { NewMilestoneDialog as s } from "../create/CreateDialogs.js";
6
+ import { MilestoneProgressBar as c } from "../milestones/MilestoneControls.js";
7
+ import { useState as l } from "react";
8
+ import { Calendar as u, Target as d, User as f } from "lucide-react";
9
+ import { gql as p } from "@apollo/client";
10
+ import { useQuery as m } from "@apollo/client/react";
11
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
12
+ import { Badge as _, Card as v, CardContent as y, CardHeader as b, CardTitle as x } from "@burdenoff/fe-libs/ui";
12
13
  //#region src/planmagnet/pages/ProjectsMilestonesPagePage.tsx
13
- var b = d`
14
+ var S = p`
14
15
  query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {
15
16
  planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {
16
17
  items {
@@ -38,13 +39,13 @@ var b = d`
38
39
  totalCount
39
40
  }
40
41
  }
41
- `, x = {
42
+ `, C = {
42
43
  PENDING: "bg-gray-100 text-gray-800",
43
44
  IN_PROGRESS: "bg-blue-100 text-blue-800",
44
45
  COMPLETED: "bg-green-100 text-green-800",
45
46
  MISSED: "bg-red-100 text-red-800",
46
47
  CANCELLED: "bg-red-100 text-red-800"
47
- }, S = [
48
+ }, w = [
48
49
  "all",
49
50
  "PENDING",
50
51
  "IN_PROGRESS",
@@ -52,93 +53,113 @@ var b = d`
52
53
  "MISSED",
53
54
  "CANCELLED"
54
55
  ];
55
- function C() {
56
- let { workspaceId: d } = e(), C = t(), [w, T] = s("all"), { data: E, loading: D, error: O } = f(b, { variables: {
57
- workspaceId: d ?? "default",
58
- filter: w === "all" ? void 0 : { status: w }
56
+ function T() {
57
+ let { workspaceId: p } = e(), T = t(), [E, D] = l("all"), { data: O, loading: k, error: A } = m(S, { variables: {
58
+ workspaceId: p ?? "default",
59
+ filter: E === "all" ? void 0 : { status: E }
59
60
  } });
60
- if (D && !E) return /* @__PURE__ */ p("div", {
61
+ if (k && !O) return /* @__PURE__ */ h("div", {
61
62
  className: "flex items-center justify-center p-12",
62
- children: /* @__PURE__ */ p("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
63
+ children: /* @__PURE__ */ h("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
63
64
  });
64
- let k = E?.planmagnetMilestones?.items ?? [], A = E?.planmagnetMilestones?.totalCount ?? 0;
65
- return /* @__PURE__ */ m("div", {
65
+ let j = O?.planmagnetMilestones?.items ?? [], M = O?.planmagnetMilestones?.totalCount ?? 0;
66
+ return /* @__PURE__ */ g("div", {
66
67
  className: "space-y-6 p-6",
67
68
  children: [
68
- /* @__PURE__ */ m("div", {
69
+ /* @__PURE__ */ g("div", {
69
70
  className: "flex items-center justify-between",
70
- children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h1", {
71
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h1", {
71
72
  className: "text-2xl font-semibold",
72
73
  children: "Milestones"
73
- }), /* @__PURE__ */ p("p", {
74
+ }), /* @__PURE__ */ h("p", {
74
75
  className: "text-sm text-muted-foreground",
75
- children: w === "all" ? `${A} milestones across all projects` : `${A} ${w.toLowerCase().replace("_", " ")} milestones`
76
- })] }), /* @__PURE__ */ p(a, { onCreated: (e) => C(r("/projects/milestone-detail-page", e)) })]
76
+ children: E === "all" ? `${M} milestones across all projects` : `${M} ${E.toLowerCase().replace("_", " ")} milestones`
77
+ })] }), /* @__PURE__ */ h(s, { onCreated: (e) => T(r("/projects/milestone-detail-page", e)) })]
77
78
  }),
78
- /* @__PURE__ */ p("div", {
79
+ /* @__PURE__ */ h("div", {
79
80
  className: "flex gap-1",
80
- children: S.map((e) => /* @__PURE__ */ p("button", {
81
- onClick: () => T(e),
82
- className: `px-3 py-1.5 text-sm rounded-md capitalize ${w === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
81
+ children: w.map((e) => /* @__PURE__ */ h("button", {
82
+ onClick: () => D(e),
83
+ className: `px-3 py-1.5 text-sm rounded-md capitalize ${E === e ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"}`,
83
84
  children: e === "all" ? "All" : e.toLowerCase().replace("_", " ")
84
85
  }, e))
85
86
  }),
86
- O && /* @__PURE__ */ m("div", {
87
+ A && /* @__PURE__ */ g("div", {
87
88
  role: "alert",
88
89
  className: "rounded-md border border-destructive/40 p-4 text-sm text-destructive",
89
- children: ["Milestones could not be loaded: ", O.message]
90
+ children: ["Milestones could not be loaded: ", A.message]
90
91
  }),
91
- /* @__PURE__ */ p("div", {
92
+ /* @__PURE__ */ h("div", {
92
93
  className: "grid grid-cols-1 md:grid-cols-2 gap-4",
93
- children: k.map((e) => /* @__PURE__ */ m(g, {
94
- ...i(() => C(r("/projects/milestone-detail-page", e.id)), e.name),
95
- children: [/* @__PURE__ */ p(v, {
94
+ children: j.map((e) => /* @__PURE__ */ g(v, {
95
+ ...i(() => T(r("/projects/milestone-detail-page", e.id)), e.name),
96
+ children: [/* @__PURE__ */ h(b, {
96
97
  className: "pb-2",
97
- children: /* @__PURE__ */ m("div", {
98
+ children: /* @__PURE__ */ g("div", {
98
99
  className: "flex items-center justify-between",
99
- children: [/* @__PURE__ */ m(y, {
100
+ children: [/* @__PURE__ */ g(x, {
100
101
  className: "text-base flex items-center gap-2",
101
- children: [/* @__PURE__ */ p(l, { className: "h-4 w-4 text-primary" }), e.name]
102
- }), /* @__PURE__ */ p("span", {
103
- className: `text-xs px-2 py-0.5 rounded-full capitalize ${x[e.status] ?? "bg-gray-100"}`,
102
+ children: [/* @__PURE__ */ h(d, { className: "h-4 w-4 text-primary" }), e.name]
103
+ }), /* @__PURE__ */ h("span", {
104
+ className: `text-xs px-2 py-0.5 rounded-full capitalize ${C[e.status] ?? "bg-gray-100"}`,
104
105
  children: e.status.toLowerCase().replace("_", " ")
105
106
  })]
106
107
  })
107
- }), /* @__PURE__ */ m(_, {
108
+ }), /* @__PURE__ */ g(y, {
108
109
  className: "space-y-3",
109
110
  children: [
110
- /* @__PURE__ */ p("p", {
111
+ /* @__PURE__ */ h("p", {
111
112
  className: "text-sm text-muted-foreground",
112
113
  children: e.description ?? "No description"
113
114
  }),
114
- e.workItemProgress && /* @__PURE__ */ p(o, { progress: e.workItemProgress }),
115
- /* @__PURE__ */ m("div", {
115
+ e.workItemProgress && /* @__PURE__ */ h(c, { progress: e.workItemProgress }),
116
+ /* @__PURE__ */ g("div", {
116
117
  className: "flex gap-3 text-xs text-muted-foreground",
117
118
  children: [
118
- /* @__PURE__ */ m("span", {
119
+ /* @__PURE__ */ g("span", {
119
120
  className: "flex items-center gap-1",
120
- children: [/* @__PURE__ */ p(c, { className: "h-3 w-3" }), e.dueDate ? new Date(e.dueDate).toLocaleDateString() : "No due date"]
121
+ children: [/* @__PURE__ */ h(u, { className: "h-3 w-3" }), e.dueDate ? new Date(e.dueDate).toLocaleDateString() : "No due date"]
121
122
  }),
122
- e.isOverdue && /* @__PURE__ */ p(h, {
123
+ e.isOverdue && /* @__PURE__ */ h(_, {
123
124
  variant: "destructive",
124
125
  "data-testid": "milestone-overdue",
125
126
  children: "Overdue"
126
127
  }),
127
- e.ownerId && /* @__PURE__ */ m("span", {
128
+ e.ownerId && /* @__PURE__ */ g("span", {
128
129
  className: "flex items-center gap-1",
129
- children: [/* @__PURE__ */ p(u, { className: "h-3 w-3" }), /* @__PURE__ */ p(n, { id: e.ownerId })]
130
+ children: [/* @__PURE__ */ h(f, { className: "h-3 w-3" }), /* @__PURE__ */ h(n, { id: e.ownerId })]
130
131
  })
131
132
  ]
132
133
  }),
133
- /* @__PURE__ */ m("div", {
134
+ /* @__PURE__ */ g("div", {
134
135
  className: "text-xs text-muted-foreground",
135
136
  children: ["Project: ", e.project?.name ?? "not available"]
137
+ }),
138
+ /* @__PURE__ */ g("div", {
139
+ className: "flex flex-wrap gap-2 border-t pt-2",
140
+ onClick: a,
141
+ "data-testid": "milestone-schedule-actions",
142
+ children: [/* @__PURE__ */ h(o, {
143
+ projectId: e.projectId,
144
+ milestoneId: e.id,
145
+ defaultKind: "MILESTONE_CELEBRATION",
146
+ lockKind: !0,
147
+ defaultTitle: `${e.name} celebration`,
148
+ triggerLabel: "Celebration"
149
+ }), /* @__PURE__ */ h(o, {
150
+ projectId: e.projectId,
151
+ milestoneId: e.id,
152
+ defaultKind: "DEMO",
153
+ lockKind: !0,
154
+ defaultTitle: `${e.name} demo`,
155
+ triggerLabel: "Demo"
156
+ })]
136
157
  })
137
158
  ]
138
159
  })]
139
160
  }, e.id))
140
161
  }),
141
- !O && k.length === 0 && /* @__PURE__ */ p("p", {
162
+ !A && j.length === 0 && /* @__PURE__ */ h("p", {
142
163
  className: "text-center text-muted-foreground py-8",
143
164
  children: "No milestones found."
144
165
  })
@@ -146,6 +167,6 @@ function C() {
146
167
  });
147
168
  }
148
169
  //#endregion
149
- export { C as ProjectsMilestonesPagePage };
170
+ export { T as ProjectsMilestonesPagePage };
150
171
 
151
172
  //# sourceMappingURL=ProjectsMilestonesPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsMilestonesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsMilestonesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Target, Calendar, User } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewMilestoneDialog } from '../create/CreateDialogs';\nimport { type MilestoneProgress, MilestoneProgressBar } from '../milestones/MilestoneControls';\n\nconst GET_MILESTONES = gql`\n query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {\n planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {\n items {\n id\n name\n description\n projectId\n project {\n id\n name\n }\n status\n dueDate\n isOverdue\n ownerId\n createdAt\n workItemProgress {\n total\n done\n cancelled\n open\n percentComplete\n }\n }\n totalCount\n }\n }\n`;\n\nconst statusColor: Record<string, string> = {\n PENDING: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n COMPLETED: 'bg-green-100 text-green-800',\n MISSED: 'bg-red-100 text-red-800',\n CANCELLED: 'bg-red-100 text-red-800',\n};\n\nconst milestoneStatuses = [\n 'all',\n 'PENDING',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'MISSED',\n 'CANCELLED',\n] as const;\n\nexport function ProjectsMilestonesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [filter, setFilter] = useState<string>('all');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_MILESTONES, {\n variables: {\n workspaceId: workspaceId ?? 'default',\n filter: filter !== 'all' ? { status: filter } : undefined,\n },\n });\n\n // Only before the first load: a refetch after a create must not blank the page.\n if (loading && !data)\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n // A failed load is shown INSIDE the list area: an early return here replaced the whole page, so the status tabs\n // and New Milestone vanished and a failing tab could not be left (BOFF-7942).\n\n const milestones = data?.planmagnetMilestones?.items ?? [];\n const totalCount = data?.planmagnetMilestones?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Milestones</h1>\n <p className=\"text-sm text-muted-foreground\">\n {/* The count follows the tab: it is the filtered total, so do not call it \"all\". */}\n {filter === 'all'\n ? `${totalCount} milestones across all projects`\n : `${totalCount} ${filter.toLowerCase().replace('_', ' ')} milestones`}\n </p>\n </div>\n <NewMilestoneDialog\n onCreated={(id) => navigate(detailPath('/projects/milestone-detail-page', id))}\n />\n </div>\n <div className=\"flex gap-1\">\n {milestoneStatuses.map((s) => (\n <button\n key={s}\n onClick={() => setFilter(s)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${filter === s ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/40 p-4 text-sm text-destructive\"\n >\n Milestones could not be loaded: {error.message}\n </div>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {milestones.map(\n (ms: {\n id: string;\n name: string;\n description: string | null;\n projectId: string;\n project: { id: string; name: string } | null;\n status: string;\n dueDate: string | null;\n isOverdue: boolean;\n ownerId: string | null;\n workItemProgress: MilestoneProgress | null;\n }) => (\n <Card\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Target className=\"h-4 w-4 text-primary\" />\n {ms.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[ms.status] ?? 'bg-gray-100'}`}\n >\n {ms.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {ms.description ?? 'No description'}\n </p>\n {ms.workItemProgress && <MilestoneProgressBar progress={ms.workItemProgress} />}\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : 'No due date'}\n </span>\n {ms.isOverdue && (\n <Badge variant=\"destructive\" data-testid=\"milestone-overdue\">\n Overdue\n </Badge>\n )}\n {ms.ownerId && (\n <span className=\"flex items-center gap-1\">\n <User className=\"h-3 w-3\" />\n <PersonName id={ms.ownerId} />\n </span>\n )}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Project: {ms.project?.name ?? 'not available'}\n </div>\n </CardContent>\n </Card>\n )\n )}\n </div>\n {!error && milestones.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No milestones found.</p>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAaA,IAAM,IAAiB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BpB,IAAsC;CAC1C,SAAS;CACT,aAAa;CACb,WAAW;CACX,QAAQ;CACR,WAAW;CACZ,EAEK,IAAoB;CACxB;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,IAA6B;CAC3C,IAAM,EAAE,mBAAgB,GAAe,EACjC,IAAW,GAAuB,EAClC,CAAC,GAAQ,KAAa,EAAiB,MAAM,EAE7C,EACJ,SACA,YACA,aAGA,EAA8B,GAAgB,EAC5C,WAAW;EACT,aAAa,KAAe;EAC5B,QAAQ,MAAW,QAA6B,KAAA,IAArB,EAAE,QAAQ,GAAQ;EAC9C,EACF,CAAC;AAGJ,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA;CAKV,IAAM,IAAa,GAAM,sBAAsB,SAAS,EAAE,EACpD,IAAa,GAAM,sBAAsB,cAAc;AAE7D,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAe,CAAA,EACtD,kBAAC,KAAD;KAAG,WAAU;eAEV,MAAW,QACR,GAAG,EAAW,mCACd,GAAG,EAAW,GAAG,EAAO,aAAa,CAAC,QAAQ,KAAK,IAAI,CAAC;KAC1D,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD,EACE,YAAY,MAAO,EAAS,EAAW,mCAAmC,EAAG,CAAC,EAC9E,CAAA,CACE;;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAkB,KAAK,MACtB,kBAAC,UAAD;KAEE,eAAe,EAAU,EAAE;KAC3B,WAAW,6CAA6C,MAAW,IAAI,uCAAuC;eAE7G,MAAM,QAAQ,QAAQ,EAAE,aAAa,CAAC,QAAQ,KAAK,IAAI;KACjD,EALF,EAKE,CACT;IACE,CAAA;GACL,KACC,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAFZ,CAGC,oCACkC,EAAM,QACnC;;GAER,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAW,KACT,MAYC,kBAAC,GAAD;KAEE,GAAI,QACI,EAAS,EAAW,mCAAmC,EAAG,GAAG,CAAC,EACpE,EAAG,KACJ;eALH,CAOE,kBAAC,GAAD;MAAY,WAAU;gBACpB,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAW,WAAU;kBAArB,CACE,kBAAC,GAAD,EAAQ,WAAU,wBAAyB,CAAA,EAC1C,EAAG,KACM;WACZ,kBAAC,QAAD;QACE,WAAW,+CAA+C,EAAY,EAAG,WAAW;kBAEnF,EAAG,OAAO,aAAa,CAAC,QAAQ,KAAK,IAAI;QACrC,CAAA,CACH;;MACK,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAG,eAAe;QACjB,CAAA;OACH,EAAG,oBAAoB,kBAAC,GAAD,EAAsB,UAAU,EAAG,kBAAoB,CAAA;OAC/E,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,EAAG,UAAU,IAAI,KAAK,EAAG,QAAQ,CAAC,oBAAoB,GAAG,cACrD;;SACN,EAAG,aACF,kBAAC,GAAD;UAAO,SAAQ;UAAc,eAAY;oBAAoB;UAErD,CAAA;SAET,EAAG,WACF,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC5B,kBAAC,GAAD,EAAY,IAAI,EAAG,SAAW,CAAA,CACzB;;SAEL;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CAA+C,aACnC,EAAG,SAAS,QAAQ,gBAC1B;;OACM;QACT;OA7CA,EAAG,GA6CH,CAEV;IACG,CAAA;GACL,CAAC,KAAS,EAAW,WAAW,KAC/B,kBAAC,KAAD;IAAG,WAAU;cAAyC;IAAwB,CAAA;GAE5E"}
1
+ {"version":3,"file":"ProjectsMilestonesPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProjectsMilestonesPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { useState } from 'react';\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge } from '@burdenoff/fe-libs/ui';\nimport { Target, Calendar, User } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath, stopRowActivation } from '../utils/rowNavigation';\nimport { PersonName } from '../people/People';\nimport { NewMilestoneDialog } from '../create/CreateDialogs';\nimport { type MilestoneProgress, MilestoneProgressBar } from '../milestones/MilestoneControls';\nimport { ScheduleMeetingDialog } from '../meetings/ScheduleMeetingDialog';\n\nconst GET_MILESTONES = gql`\n query GetMilestones($workspaceId: ID!, $filter: PlanmagnetMilestoneFilter) {\n planmagnetMilestones(workspaceId: $workspaceId, filter: $filter, pagination: { first: 100 }) {\n items {\n id\n name\n description\n projectId\n project {\n id\n name\n }\n status\n dueDate\n isOverdue\n ownerId\n createdAt\n workItemProgress {\n total\n done\n cancelled\n open\n percentComplete\n }\n }\n totalCount\n }\n }\n`;\n\nconst statusColor: Record<string, string> = {\n PENDING: 'bg-gray-100 text-gray-800',\n IN_PROGRESS: 'bg-blue-100 text-blue-800',\n COMPLETED: 'bg-green-100 text-green-800',\n MISSED: 'bg-red-100 text-red-800',\n CANCELLED: 'bg-red-100 text-red-800',\n};\n\nconst milestoneStatuses = [\n 'all',\n 'PENDING',\n 'IN_PROGRESS',\n 'COMPLETED',\n 'MISSED',\n 'CANCELLED',\n] as const;\n\nexport function ProjectsMilestonesPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [filter, setFilter] = useState<string>('all');\n\n const {\n data,\n loading,\n error,\n } = // eslint-disable-next-line @typescript-eslint/no-explicit-any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useQuery<Record<string, any>>(GET_MILESTONES, {\n variables: {\n workspaceId: workspaceId ?? 'default',\n filter: filter !== 'all' ? { status: filter } : undefined,\n },\n });\n\n // Only before the first load: a refetch after a create must not blank the page.\n if (loading && !data)\n return (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full\" />\n </div>\n );\n // A failed load is shown INSIDE the list area: an early return here replaced the whole page, so the status tabs\n // and New Milestone vanished and a failing tab could not be left (BOFF-7942).\n\n const milestones = data?.planmagnetMilestones?.items ?? [];\n const totalCount = data?.planmagnetMilestones?.totalCount ?? 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Milestones</h1>\n <p className=\"text-sm text-muted-foreground\">\n {/* The count follows the tab: it is the filtered total, so do not call it \"all\". */}\n {filter === 'all'\n ? `${totalCount} milestones across all projects`\n : `${totalCount} ${filter.toLowerCase().replace('_', ' ')} milestones`}\n </p>\n </div>\n <NewMilestoneDialog\n onCreated={(id) => navigate(detailPath('/projects/milestone-detail-page', id))}\n />\n </div>\n <div className=\"flex gap-1\">\n {milestoneStatuses.map((s) => (\n <button\n key={s}\n onClick={() => setFilter(s)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${filter === s ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {s === 'all' ? 'All' : s.toLowerCase().replace('_', ' ')}\n </button>\n ))}\n </div>\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/40 p-4 text-sm text-destructive\"\n >\n Milestones could not be loaded: {error.message}\n </div>\n )}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {milestones.map(\n (ms: {\n id: string;\n name: string;\n description: string | null;\n projectId: string;\n project: { id: string; name: string } | null;\n status: string;\n dueDate: string | null;\n isOverdue: boolean;\n ownerId: string | null;\n workItemProgress: MilestoneProgress | null;\n }) => (\n <Card\n key={ms.id}\n {...rowLinkProps(\n () => navigate(detailPath('/projects/milestone-detail-page', ms.id)),\n ms.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Target className=\"h-4 w-4 text-primary\" />\n {ms.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${statusColor[ms.status] ?? 'bg-gray-100'}`}\n >\n {ms.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {ms.description ?? 'No description'}\n </p>\n {ms.workItemProgress && <MilestoneProgressBar progress={ms.workItemProgress} />}\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {ms.dueDate ? new Date(ms.dueDate).toLocaleDateString() : 'No due date'}\n </span>\n {ms.isOverdue && (\n <Badge variant=\"destructive\" data-testid=\"milestone-overdue\">\n Overdue\n </Badge>\n )}\n {ms.ownerId && (\n <span className=\"flex items-center gap-1\">\n <User className=\"h-3 w-3\" />\n <PersonName id={ms.ownerId} />\n </span>\n )}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Project: {ms.project?.name ?? 'not available'}\n </div>\n <div\n className=\"flex flex-wrap gap-2 border-t pt-2\"\n onClick={stopRowActivation}\n data-testid=\"milestone-schedule-actions\"\n >\n <ScheduleMeetingDialog\n projectId={ms.projectId}\n milestoneId={ms.id}\n defaultKind=\"MILESTONE_CELEBRATION\"\n lockKind\n defaultTitle={`${ms.name} celebration`}\n triggerLabel=\"Celebration\"\n />\n <ScheduleMeetingDialog\n projectId={ms.projectId}\n milestoneId={ms.id}\n defaultKind=\"DEMO\"\n lockKind\n defaultTitle={`${ms.name} demo`}\n triggerLabel=\"Demo\"\n />\n </div>\n </CardContent>\n </Card>\n )\n )}\n </div>\n {!error && milestones.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">No milestones found.</p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AA4FA,wBAAgB,8BAA8B,4CAwU7C"}
1
+ {"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AA8FA,wBAAgB,8BAA8B,4CA+V7C"}