@burdenoff/microfe-planmagnet 2026.830.1 → 2026.923.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsRoadmapsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapsPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport { Map, Calendar, Plus, Filter, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst LIST_ROADMAPS = gql`\n query ListRoadmapsPage(\n $workspaceId: ID!\n $filter: PlanmagnetRoadmapFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetRoadmaps(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n type\n isPublic\n ownerId\n createdAt\n updatedAt\n items {\n id\n title\n status\n startDate\n endDate\n }\n }\n totalCount\n }\n }\n`;\n\ninterface RoadmapItemNode {\n id: string;\n title: string;\n status: string;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface RoadmapNode {\n id: string;\n name: string;\n description: string | null;\n type: string;\n isPublic: boolean;\n ownerId: string;\n createdAt: string;\n updatedAt: string;\n items: RoadmapItemNode[];\n}\n\nconst typeColor: Record<string, string> = {\n TIMELINE: 'bg-purple-100 text-purple-800',\n GANTT: 'bg-orange-100 text-orange-800',\n SWIMLANE: 'bg-green-100 text-green-800',\n CUSTOM: 'bg-blue-100 text-blue-800',\n};\n\nexport function ProductsRoadmapsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [typeFilter, setTypeFilter] = useState<string>('all');\n const [visFilter, setVisFilter] = 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>>(LIST_ROADMAPS, {\n variables: {\n workspaceId,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n if (loading) {\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 roadmaps: {error.message}</div>;\n }\n\n const roadmaps: RoadmapNode[] = data?.planmagnetRoadmaps?.items ?? [];\n const totalCount = data?.planmagnetRoadmaps?.totalCount ?? 0;\n\n const types = ['all', ...new Set(roadmaps.map((r) => r.type))];\n const visibilities = ['all', 'public', 'private'];\n\n const filtered = roadmaps.filter(\n (r) =>\n (typeFilter === 'all' || r.type === typeFilter) &&\n (visFilter === 'all' ||\n (visFilter === 'public' && r.isPublic) ||\n (visFilter === 'private' && !r.isPublic))\n );\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\">Roadmaps</h1>\n <p className=\"text-sm text-muted-foreground\">{totalCount} roadmaps across all products</p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/create-roadmap-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Roadmap\n </Button>\n </div>\n\n <div className=\"flex gap-4 flex-wrap\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-sm text-muted-foreground\">Type:</span>\n {types.map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {t === 'all' ? 'All' : t.toLowerCase()}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">Visibility:</span>\n {visibilities.map((v) => (\n <button\n key={v}\n onClick={() => setVisFilter(v)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${visFilter === v ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {v}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((rm) => {\n const itemCount = rm.items?.length ?? 0;\n const completedItems =\n rm.items?.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE').length ?? 0;\n const progress = itemCount > 0 ? Math.round((completedItems / itemCount) * 100) : 0;\n const startDates = rm.items?.map((i) => i.startDate).filter(Boolean) ?? [];\n const endDates = rm.items?.map((i) => i.endDate).filter(Boolean) ?? [];\n const earliestStart = startDates.length > 0 ? startDates.sort()[0] : null;\n const latestEnd = endDates.length > 0 ? endDates.sort().reverse()[0] : null;\n\n return (\n <Card key={rm.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{rm.name}</CardTitle>\n <Badge variant={rm.isPublic ? 'default' : 'secondary'} className=\"capitalize\">\n {rm.isPublic ? 'public' : 'private'}\n </Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {rm.description ?? 'No description'}\n </p>\n <div className=\"flex items-center gap-2\">\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${typeColor[rm.type] ?? 'bg-gray-100'}`}\n >\n {rm.type.toLowerCase()}\n </span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {rm.isPublic ? 'public' : 'private'}\n </Badge>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Progress</span>\n <span className=\"font-medium\">{progress}%</span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </div>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Map className=\"h-3 w-3\" />\n {itemCount} items\n </span>\n </div>\n <div className=\"flex items-center justify-between text-xs text-muted-foreground border-t pt-2\">\n <span>Owner: {rm.ownerId}</span>\n {earliestStart && latestEnd && (\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {new Date(earliestStart).toLocaleDateString()} -{' '}\n {new Date(latestEnd).toLocaleDateString()}\n </span>\n )}\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n {filtered.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n No roadmaps match the selected filters.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProductsRoadmapsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapsPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport { Map, Calendar, Plus, Filter, Loader2 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps, detailPath } from '../utils/rowNavigation';\n\nconst LIST_ROADMAPS = gql`\n query ListRoadmapsPage(\n $workspaceId: ID!\n $filter: PlanmagnetRoadmapFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetRoadmaps(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n workspaceId\n name\n description\n type\n isPublic\n ownerId\n createdAt\n updatedAt\n items {\n id\n title\n status\n startDate\n endDate\n }\n }\n totalCount\n }\n }\n`;\n\ninterface RoadmapItemNode {\n id: string;\n title: string;\n status: string;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface RoadmapNode {\n id: string;\n name: string;\n description: string | null;\n type: string;\n isPublic: boolean;\n ownerId: string;\n createdAt: string;\n updatedAt: string;\n items: RoadmapItemNode[];\n}\n\nconst typeColor: Record<string, string> = {\n TIMELINE: 'bg-purple-100 text-purple-800',\n GANTT: 'bg-orange-100 text-orange-800',\n SWIMLANE: 'bg-green-100 text-green-800',\n CUSTOM: 'bg-blue-100 text-blue-800',\n};\n\nexport function ProductsRoadmapsPagePage() {\n const navigate = usePlanMagnetNavigate();\n const { workspaceId } = usePlanMagnet();\n const [typeFilter, setTypeFilter] = useState<string>('all');\n const [visFilter, setVisFilter] = 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>>(LIST_ROADMAPS, {\n variables: {\n workspaceId,\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n if (loading) {\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 roadmaps: {error.message}</div>;\n }\n\n const roadmaps: RoadmapNode[] = data?.planmagnetRoadmaps?.items ?? [];\n const totalCount = data?.planmagnetRoadmaps?.totalCount ?? 0;\n\n const types = ['all', ...new Set(roadmaps.map((r) => r.type))];\n const visibilities = ['all', 'public', 'private'];\n\n const filtered = roadmaps.filter(\n (r) =>\n (typeFilter === 'all' || r.type === typeFilter) &&\n (visFilter === 'all' ||\n (visFilter === 'public' && r.isPublic) ||\n (visFilter === 'private' && !r.isPublic))\n );\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\">Roadmaps</h1>\n <p className=\"text-sm text-muted-foreground\">{totalCount} roadmaps across all products</p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/products/create-roadmap-page')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Roadmap\n </Button>\n </div>\n\n <div className=\"flex gap-4 flex-wrap\">\n <div className=\"flex items-center gap-2\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n <span className=\"text-sm text-muted-foreground\">Type:</span>\n {types.map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {t === 'all' ? 'All' : t.toLowerCase()}\n </button>\n ))}\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">Visibility:</span>\n {visibilities.map((v) => (\n <button\n key={v}\n onClick={() => setVisFilter(v)}\n className={`px-2 py-1 text-xs rounded-md capitalize ${visFilter === v ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {v}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((rm) => {\n const itemCount = rm.items?.length ?? 0;\n const completedItems =\n rm.items?.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE').length ?? 0;\n const progress = itemCount > 0 ? Math.round((completedItems / itemCount) * 100) : 0;\n const startDates = rm.items?.map((i) => i.startDate).filter(Boolean) ?? [];\n const endDates = rm.items?.map((i) => i.endDate).filter(Boolean) ?? [];\n const earliestStart = startDates.length > 0 ? startDates.sort()[0] : null;\n const latestEnd = endDates.length > 0 ? endDates.sort().reverse()[0] : null;\n\n return (\n <Card\n key={rm.id}\n {...rowLinkProps(\n () => navigate(detailPath('/products/roadmap-detail-page', rm.id)),\n rm.name\n )}\n >\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{rm.name}</CardTitle>\n <Badge variant={rm.isPublic ? 'default' : 'secondary'} className=\"capitalize\">\n {rm.isPublic ? 'public' : 'private'}\n </Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-muted-foreground\">\n {rm.description ?? 'No description'}\n </p>\n <div className=\"flex items-center gap-2\">\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${typeColor[rm.type] ?? 'bg-gray-100'}`}\n >\n {rm.type.toLowerCase()}\n </span>\n <Badge variant=\"outline\" className=\"text-xs capitalize\">\n {rm.isPublic ? 'public' : 'private'}\n </Badge>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Progress</span>\n <span className=\"font-medium\">{progress}%</span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full bg-primary rounded-full\"\n style={{ width: `${progress}%` }}\n />\n </div>\n </div>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Map className=\"h-3 w-3\" />\n {itemCount} items\n </span>\n </div>\n <div className=\"flex items-center justify-between text-xs text-muted-foreground border-t pt-2\">\n <span>Owner: {rm.ownerId}</span>\n {earliestStart && latestEnd && (\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {new Date(earliestStart).toLocaleDateString()} -{' '}\n {new Date(latestEnd).toLocaleDateString()}\n </span>\n )}\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n {filtered.length === 0 && (\n <p className=\"text-center text-muted-foreground py-8\">\n No roadmaps match the selected filters.\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksTasksPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksTasksPagePage.tsx"],"names":[],"mappings":"AA2FA,wBAAgB,kBAAkB,4CA6HjC"}
1
+ {"version":3,"file":"TasksTasksPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksTasksPagePage.tsx"],"names":[],"mappings":"AA4FA,wBAAgB,kBAAkB,4CAqIjC"}
@@ -1,12 +1,13 @@
1
- import { usePlanMagnet as e } from "../providers/PlanMagnetProvider.js";
2
- import { useState as t } from "react";
3
- import { Filter as n } from "lucide-react";
4
- import { gql as r } from "@apollo/client";
5
- import { useQuery as i } from "@apollo/client/react";
6
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
- import { Card as s, CardContent as c } from "@burdenoff/fe-libs/ui";
1
+ import { usePlanMagnet as e, usePlanMagnetNavigate as t } from "../providers/PlanMagnetProvider.js";
2
+ import { rowLinkProps as n } from "../utils/rowNavigation.js";
3
+ import { useState as r } from "react";
4
+ import { Filter as i } from "lucide-react";
5
+ import { gql as a } from "@apollo/client";
6
+ import { useQuery as o } from "@apollo/client/react";
7
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
8
+ import { Card as l, CardContent as u } from "@burdenoff/fe-libs/ui";
8
9
  //#region src/planmagnet/pages/TasksTasksPagePage.tsx
9
- var l = r`
10
+ var d = a`
10
11
  query GetWorkItems(
11
12
  $workspaceId: ID!
12
13
  $filter: PlanmagnetWorkItemFilter
@@ -33,74 +34,74 @@ var l = r`
33
34
  totalCount
34
35
  }
35
36
  }
36
- `, u = [
37
+ `, f = [
37
38
  "BACKLOG",
38
39
  "TODO",
39
40
  "IN_PROGRESS",
40
41
  "IN_REVIEW",
41
42
  "TESTING",
42
43
  "DONE"
43
- ], d = {
44
+ ], p = {
44
45
  BACKLOG: "Backlog",
45
46
  TODO: "To Do",
46
47
  IN_PROGRESS: "In Progress",
47
48
  IN_REVIEW: "In Review",
48
49
  TESTING: "Testing",
49
50
  DONE: "Done"
50
- }, f = {
51
+ }, m = {
51
52
  BACKLOG: "border-t-gray-400",
52
53
  TODO: "border-t-blue-400",
53
54
  IN_PROGRESS: "border-t-yellow-400",
54
55
  IN_REVIEW: "border-t-purple-400",
55
56
  TESTING: "border-t-teal-400",
56
57
  DONE: "border-t-green-400"
57
- }, p = {
58
+ }, h = {
58
59
  LOW: "bg-gray-100 text-gray-700",
59
60
  MEDIUM: "bg-blue-100 text-blue-700",
60
61
  HIGH: "bg-orange-100 text-orange-700",
61
62
  CRITICAL: "bg-red-100 text-red-700"
62
- }, m = {
63
+ }, g = {
63
64
  STORY: "bg-green-100 text-green-700",
64
65
  BUG: "bg-red-100 text-red-700",
65
66
  TASK: "bg-blue-100 text-blue-700",
66
67
  EPIC: "bg-purple-100 text-purple-700",
67
68
  SUBTASK: "bg-gray-100 text-gray-700"
68
69
  };
69
- function h() {
70
- let { workspaceId: r } = e(), [h, g] = t("all"), [_, v] = t("all"), { data: y, loading: b, error: x } = i(l, {
70
+ function _() {
71
+ let { workspaceId: a } = e(), _ = t(), [v, y] = r("all"), [b, x] = r("all"), { data: S, loading: C, error: w } = o(d, {
71
72
  variables: {
72
- workspaceId: r,
73
+ workspaceId: a,
73
74
  pagination: { first: 200 }
74
75
  },
75
- skip: !r
76
+ skip: !a
76
77
  });
77
- if (b) return /* @__PURE__ */ a("div", {
78
+ if (C) return /* @__PURE__ */ s("div", {
78
79
  className: "flex items-center justify-center p-12",
79
- children: /* @__PURE__ */ a("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
80
+ children: /* @__PURE__ */ s("div", { className: "animate-spin h-8 w-8 border-2 border-primary border-t-transparent rounded-full" })
80
81
  });
81
- if (x) return /* @__PURE__ */ o("div", {
82
+ if (w) return /* @__PURE__ */ c("div", {
82
83
  className: "p-6 text-red-500",
83
- children: ["Error: ", x.message]
84
+ children: ["Error: ", w.message]
84
85
  });
85
- let S = y?.planmagnetWorkItems?.items ?? [], C = S.filter((e) => (h === "all" || e.priority === h.toUpperCase()) && (_ === "all" || e.type === _.toUpperCase()));
86
- return /* @__PURE__ */ o("div", {
86
+ let T = S?.planmagnetWorkItems?.items ?? [], E = T.filter((e) => (v === "all" || e.priority === v.toUpperCase()) && (b === "all" || e.type === b.toUpperCase()));
87
+ return /* @__PURE__ */ c("div", {
87
88
  className: "space-y-4 p-6",
88
89
  children: [
89
- /* @__PURE__ */ a("div", {
90
+ /* @__PURE__ */ s("div", {
90
91
  className: "flex items-center justify-between",
91
- children: /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h1", {
92
+ children: /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("h1", {
92
93
  className: "text-2xl font-semibold",
93
94
  children: "Task Board"
94
- }), /* @__PURE__ */ o("p", {
95
+ }), /* @__PURE__ */ c("p", {
95
96
  className: "text-sm text-muted-foreground",
96
- children: [S.length, " tasks across all projects"]
97
+ children: [T.length, " tasks across all projects"]
97
98
  })] })
98
99
  }),
99
- /* @__PURE__ */ o("div", {
100
+ /* @__PURE__ */ c("div", {
100
101
  className: "flex gap-4 items-center flex-wrap",
101
102
  children: [
102
- /* @__PURE__ */ a(n, { className: "h-4 w-4 text-muted-foreground" }),
103
- /* @__PURE__ */ a("div", {
103
+ /* @__PURE__ */ s(i, { className: "h-4 w-4 text-muted-foreground" }),
104
+ /* @__PURE__ */ s("div", {
104
105
  className: "flex gap-1",
105
106
  children: [
106
107
  "all",
@@ -108,13 +109,13 @@ function h() {
108
109
  "medium",
109
110
  "high",
110
111
  "critical"
111
- ].map((e) => /* @__PURE__ */ a("button", {
112
- onClick: () => g(e),
113
- className: `px-2 py-1 text-xs rounded capitalize ${h === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
112
+ ].map((e) => /* @__PURE__ */ s("button", {
113
+ onClick: () => y(e),
114
+ className: `px-2 py-1 text-xs rounded capitalize ${v === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
114
115
  children: e
115
116
  }, e))
116
117
  }),
117
- /* @__PURE__ */ a("div", {
118
+ /* @__PURE__ */ s("div", {
118
119
  className: "flex gap-1",
119
120
  children: [
120
121
  "all",
@@ -122,76 +123,76 @@ function h() {
122
123
  "bug",
123
124
  "task",
124
125
  "epic"
125
- ].map((e) => /* @__PURE__ */ a("button", {
126
- onClick: () => v(e),
127
- className: `px-2 py-1 text-xs rounded capitalize ${_ === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
126
+ ].map((e) => /* @__PURE__ */ s("button", {
127
+ onClick: () => x(e),
128
+ className: `px-2 py-1 text-xs rounded capitalize ${b === e ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"}`,
128
129
  children: e
129
130
  }, e))
130
131
  })
131
132
  ]
132
133
  }),
133
- /* @__PURE__ */ a("div", {
134
+ /* @__PURE__ */ s("div", {
134
135
  className: "grid grid-cols-6 gap-3 overflow-x-auto",
135
- children: u.map((e) => {
136
- let t = C.filter((t) => t.status === e);
137
- return /* @__PURE__ */ o("div", {
136
+ children: f.map((e) => {
137
+ let t = E.filter((t) => t.status === e);
138
+ return /* @__PURE__ */ c("div", {
138
139
  className: "min-w-[200px]",
139
- children: [/* @__PURE__ */ a("div", {
140
- className: `border-t-2 ${f[e]} rounded-t-md p-2 bg-muted/50`,
141
- children: /* @__PURE__ */ o("div", {
140
+ children: [/* @__PURE__ */ s("div", {
141
+ className: `border-t-2 ${m[e]} rounded-t-md p-2 bg-muted/50`,
142
+ children: /* @__PURE__ */ c("div", {
142
143
  className: "flex justify-between items-center",
143
- children: [/* @__PURE__ */ a("span", {
144
+ children: [/* @__PURE__ */ s("span", {
144
145
  className: "text-sm font-medium",
145
- children: d[e]
146
- }), /* @__PURE__ */ a("span", {
146
+ children: p[e]
147
+ }), /* @__PURE__ */ s("span", {
147
148
  className: "text-xs bg-muted rounded-full px-1.5",
148
149
  children: t.length
149
150
  })]
150
151
  })
151
- }), /* @__PURE__ */ a("div", {
152
+ }), /* @__PURE__ */ s("div", {
152
153
  className: "space-y-2 mt-2",
153
- children: t.map((e) => /* @__PURE__ */ a(s, {
154
- className: "shadow-sm",
155
- children: /* @__PURE__ */ o(c, {
154
+ children: t.map((e) => /* @__PURE__ */ s(l, {
155
+ ...n(() => _(`/tasks/task-detail-page?taskId=${encodeURIComponent(e.id)}`), e.title),
156
+ children: /* @__PURE__ */ c(u, {
156
157
  className: "p-3 space-y-2",
157
158
  children: [
158
- /* @__PURE__ */ a("p", {
159
+ /* @__PURE__ */ s("p", {
159
160
  className: "text-sm font-medium leading-tight",
160
161
  children: e.title
161
162
  }),
162
- /* @__PURE__ */ a("p", {
163
+ /* @__PURE__ */ s("p", {
163
164
  className: "text-xs text-muted-foreground",
164
165
  children: e.key
165
166
  }),
166
- /* @__PURE__ */ o("div", {
167
+ /* @__PURE__ */ c("div", {
167
168
  className: "flex gap-1 flex-wrap",
168
- children: [/* @__PURE__ */ a("span", {
169
- className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${p[e.priority] ?? ""}`,
169
+ children: [/* @__PURE__ */ s("span", {
170
+ className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${h[e.priority] ?? ""}`,
170
171
  children: e.priority.toLowerCase()
171
- }), /* @__PURE__ */ a("span", {
172
- className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${m[e.type] ?? ""}`,
172
+ }), /* @__PURE__ */ s("span", {
173
+ className: `text-[10px] px-1.5 py-0.5 rounded-full capitalize ${g[e.type] ?? ""}`,
173
174
  children: e.type.toLowerCase()
174
175
  })]
175
176
  }),
176
- /* @__PURE__ */ o("div", {
177
+ /* @__PURE__ */ c("div", {
177
178
  className: "flex items-center justify-between",
178
- children: [/* @__PURE__ */ a("div", {
179
+ children: [/* @__PURE__ */ s("div", {
179
180
  className: "flex gap-1",
180
- children: (e.labels ?? []).slice(0, 2).map((e) => /* @__PURE__ */ a("span", {
181
+ children: (e.labels ?? []).slice(0, 2).map((e) => /* @__PURE__ */ s("span", {
181
182
  className: "text-[9px] px-1 py-0.5 rounded bg-muted",
182
183
  children: e
183
184
  }, e))
184
- }), /* @__PURE__ */ a("div", {
185
+ }), /* @__PURE__ */ s("div", {
185
186
  className: "flex items-center gap-1",
186
- children: /* @__PURE__ */ a("span", {
187
+ children: /* @__PURE__ */ s("span", {
187
188
  className: "text-[10px] font-medium bg-primary/10 text-primary rounded-full h-5 w-5 flex items-center justify-center",
188
189
  children: e.storyPoints ?? 0
189
190
  })
190
191
  })]
191
192
  }),
192
- /* @__PURE__ */ o("div", {
193
+ /* @__PURE__ */ c("div", {
193
194
  className: "flex justify-between text-[10px] text-muted-foreground",
194
- children: [/* @__PURE__ */ a("span", { children: e.assigneeId ?? "Unassigned" }), /* @__PURE__ */ a("span", { children: e.dueDate ?? "" })]
195
+ children: [/* @__PURE__ */ s("span", { children: e.assigneeId ?? "Unassigned" }), /* @__PURE__ */ s("span", { children: e.dueDate ?? "" })]
195
196
  })
196
197
  ]
197
198
  })
@@ -204,6 +205,6 @@ function h() {
204
205
  });
205
206
  }
206
207
  //#endregion
207
- export { h as TasksTasksPagePage };
208
+ export { _ as TasksTasksPagePage };
208
209
 
209
210
  //# sourceMappingURL=TasksTasksPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TasksTasksPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksTasksPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Filter } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\nconst GET_WORK_ITEMS = gql`\n query GetWorkItems(\n $workspaceId: ID!\n $filter: PlanmagnetWorkItemFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n type\n status\n priority\n key\n assigneeId\n reporterId\n sprintId\n storyPoints\n estimateMinutes\n dueDate\n labels\n tags\n createdAt\n }\n totalCount\n }\n }\n`;\n\ninterface WorkItemNode {\n id: string;\n title: string;\n type: string;\n status: string;\n priority: string;\n key: string;\n assigneeId: string | null;\n reporterId: string | null;\n sprintId: string | null;\n storyPoints: number | null;\n estimateMinutes: number | null;\n dueDate: string | null;\n labels: string[];\n tags: string[];\n createdAt: string;\n}\n\nconst columns = ['BACKLOG', 'TODO', 'IN_PROGRESS', 'IN_REVIEW', 'TESTING', 'DONE'] as const;\n\nconst colLabel: Record<string, string> = {\n BACKLOG: 'Backlog',\n TODO: 'To Do',\n IN_PROGRESS: 'In Progress',\n IN_REVIEW: 'In Review',\n TESTING: 'Testing',\n DONE: 'Done',\n};\n\nconst colColor: Record<string, string> = {\n BACKLOG: 'border-t-gray-400',\n TODO: 'border-t-blue-400',\n IN_PROGRESS: 'border-t-yellow-400',\n IN_REVIEW: 'border-t-purple-400',\n TESTING: 'border-t-teal-400',\n DONE: 'border-t-green-400',\n};\n\nconst priorityColor: Record<string, string> = {\n LOW: 'bg-gray-100 text-gray-700',\n MEDIUM: 'bg-blue-100 text-blue-700',\n HIGH: 'bg-orange-100 text-orange-700',\n CRITICAL: 'bg-red-100 text-red-700',\n};\n\nconst typeColor: Record<string, string> = {\n STORY: 'bg-green-100 text-green-700',\n BUG: 'bg-red-100 text-red-700',\n TASK: 'bg-blue-100 text-blue-700',\n EPIC: 'bg-purple-100 text-purple-700',\n SUBTASK: 'bg-gray-100 text-gray-700',\n};\n\nexport function TasksTasksPagePage() {\n const { workspaceId } = usePlanMagnet();\n const [priorityFilter, setPriorityFilter] = useState<string>('all');\n const [typeFilter, setTypeFilter] = useState<string>('all');\n\n const { data, loading, error } = useQuery<{\n planmagnetWorkItems: { items: WorkItemNode[]; totalCount: number };\n }>(GET_WORK_ITEMS, {\n variables: {\n workspaceId,\n pagination: { first: 200 },\n },\n skip: !workspaceId,\n });\n\n if (loading) {\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 }\n\n if (error) {\n return <div className=\"p-6 text-red-500\">Error: {error.message}</div>;\n }\n\n const tasks = data?.planmagnetWorkItems?.items ?? [];\n\n const filtered = tasks.filter(\n (t) =>\n (priorityFilter === 'all' || t.priority === priorityFilter.toUpperCase()) &&\n (typeFilter === 'all' || t.type === typeFilter.toUpperCase())\n );\n\n return (\n <div className=\"space-y-4 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Task Board</h1>\n <p className=\"text-sm text-muted-foreground\">{tasks.length} tasks across all projects</p>\n </div>\n </div>\n <div className=\"flex gap-4 items-center flex-wrap\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n <div className=\"flex gap-1\">\n {['all', 'low', 'medium', 'high', 'critical'].map((p) => (\n <button\n key={p}\n onClick={() => setPriorityFilter(p)}\n className={`px-2 py-1 text-xs rounded capitalize ${priorityFilter === p ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {p}\n </button>\n ))}\n </div>\n <div className=\"flex gap-1\">\n {['all', 'story', 'bug', 'task', 'epic'].map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-2 py-1 text-xs rounded capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {t}\n </button>\n ))}\n </div>\n </div>\n <div className=\"grid grid-cols-6 gap-3 overflow-x-auto\">\n {columns.map((col) => {\n const colTasks = filtered.filter((t) => t.status === col);\n return (\n <div key={col} className=\"min-w-[200px]\">\n <div className={`border-t-2 ${colColor[col]} rounded-t-md p-2 bg-muted/50`}>\n <div className=\"flex justify-between items-center\">\n <span className=\"text-sm font-medium\">{colLabel[col]}</span>\n <span className=\"text-xs bg-muted rounded-full px-1.5\">{colTasks.length}</span>\n </div>\n </div>\n <div className=\"space-y-2 mt-2\">\n {colTasks.map((task) => (\n <Card key={task.id} className=\"shadow-sm\">\n <CardContent className=\"p-3 space-y-2\">\n <p className=\"text-sm font-medium leading-tight\">{task.title}</p>\n <p className=\"text-xs text-muted-foreground\">{task.key}</p>\n <div className=\"flex gap-1 flex-wrap\">\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${priorityColor[task.priority] ?? ''}`}\n >\n {task.priority.toLowerCase()}\n </span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${typeColor[task.type] ?? ''}`}\n >\n {task.type.toLowerCase()}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex gap-1\">\n {(task.labels ?? []).slice(0, 2).map((l) => (\n <span key={l} className=\"text-[9px] px-1 py-0.5 rounded bg-muted\">\n {l}\n </span>\n ))}\n </div>\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] font-medium bg-primary/10 text-primary rounded-full h-5 w-5 flex items-center justify-center\">\n {task.storyPoints ?? 0}\n </span>\n </div>\n </div>\n <div className=\"flex justify-between text-[10px] text-muted-foreground\">\n <span>{task.assigneeId ?? 'Unassigned'}</span>\n <span>{task.dueDate ?? ''}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AASA,IAAM,IAAiB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CpB,IAAU;CAAC;CAAW;CAAQ;CAAe;CAAa;CAAW;CAAO,EAE5E,IAAmC;CACvC,SAAS;CACT,MAAM;CACN,aAAa;CACb,WAAW;CACX,SAAS;CACT,MAAM;CACP,EAEK,IAAmC;CACvC,SAAS;CACT,MAAM;CACN,aAAa;CACb,WAAW;CACX,SAAS;CACT,MAAM;CACP,EAEK,IAAwC;CAC5C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,UAAU;CACX,EAEK,IAAoC;CACxC,OAAO;CACP,KAAK;CACL,MAAM;CACN,MAAM;CACN,SAAS;CACV;AAED,SAAgB,IAAqB;CACnC,IAAM,EAAE,mBAAgB,GAAe,EACjC,CAAC,GAAgB,KAAqB,EAAiB,MAAM,EAC7D,CAAC,GAAY,KAAiB,EAAiB,MAAM,EAErD,EAAE,SAAM,YAAS,aAAU,EAE9B,GAAgB;EACjB,WAAW;GACT;GACA,YAAY,EAAE,OAAO,KAAK;GAC3B;EACD,MAAM,CAAC;EACR,CAAC;AAEF,KAAI,EACF,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;EAC9F,CAAA;AAIV,KAAI,EACF,QAAO,kBAAC,OAAD;EAAK,WAAU;YAAf,CAAkC,WAAQ,EAAM,QAAc;;CAGvE,IAAM,IAAQ,GAAM,qBAAqB,SAAS,EAAE,EAE9C,IAAW,EAAM,QACpB,OACE,MAAmB,SAAS,EAAE,aAAa,EAAe,aAAa,MACvE,MAAe,SAAS,EAAE,SAAS,EAAW,aAAa,EAC/D;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eAAyB;KAAe,CAAA,EACtD,kBAAC,KAAD;KAAG,WAAU;eAAb,CAA8C,EAAM,QAAO,6BAA8B;OACrF,EAAA,CAAA;IACF,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAQ,WAAU,iCAAkC,CAAA;KACpD,kBAAC,OAAD;MAAK,WAAU;gBACZ;OAAC;OAAO;OAAO;OAAU;OAAQ;OAAW,CAAC,KAAK,MACjD,kBAAC,UAAD;OAEE,eAAe,EAAkB,EAAE;OACnC,WAAW,wCAAwC,MAAmB,IAAI,uCAAuC;iBAEhH;OACM,EALF,EAKE,CACT;MACE,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBACZ;OAAC;OAAO;OAAS;OAAO;OAAQ;OAAO,CAAC,KAAK,MAC5C,kBAAC,UAAD;OAEE,eAAe,EAAc,EAAE;OAC/B,WAAW,wCAAwC,MAAe,IAAI,uCAAuC;iBAE5G;OACM,EALF,EAKE,CACT;MACE,CAAA;KACF;;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAQ,KAAK,MAAQ;KACpB,IAAM,IAAW,EAAS,QAAQ,MAAM,EAAE,WAAW,EAAI;AACzD,YACE,kBAAC,OAAD;MAAe,WAAU;gBAAzB,CACE,kBAAC,OAAD;OAAK,WAAW,cAAc,EAAS,GAAK;iBAC1C,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAuB,EAAS;SAAY,CAAA,EAC5D,kBAAC,QAAD;SAAM,WAAU;mBAAwC,EAAS;SAAc,CAAA,CAC3E;;OACF,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAS,KAAK,MACb,kBAAC,GAAD;QAAoB,WAAU;kBAC5B,kBAAC,GAAD;SAAa,WAAU;mBAAvB;UACE,kBAAC,KAAD;WAAG,WAAU;qBAAqC,EAAK;WAAU,CAAA;UACjE,kBAAC,KAAD;WAAG,WAAU;qBAAiC,EAAK;WAAQ,CAAA;UAC3D,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,QAAD;YACE,WAAW,qDAAqD,EAAc,EAAK,aAAa;sBAE/F,EAAK,SAAS,aAAa;YACvB,CAAA,EACP,kBAAC,QAAD;YACE,WAAW,qDAAqD,EAAU,EAAK,SAAS;sBAEvF,EAAK,KAAK,aAAa;YACnB,CAAA,CACH;;UACN,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,OAAD;YAAK,WAAU;uBACX,EAAK,UAAU,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,MACpC,kBAAC,QAAD;aAAc,WAAU;uBACrB;aACI,EAFI,EAEJ,CACP;YACE,CAAA,EACN,kBAAC,OAAD;YAAK,WAAU;sBACb,kBAAC,QAAD;aAAM,WAAU;uBACb,EAAK,eAAe;aAChB,CAAA;YACH,CAAA,CACF;;UACN,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,QAAD,EAAA,UAAO,EAAK,cAAc,cAAoB,CAAA,EAC9C,kBAAC,QAAD,EAAA,UAAO,EAAK,WAAW,IAAU,CAAA,CAC7B;;UACM;;QACT,EAnCI,EAAK,GAmCT,CACP;OACE,CAAA,CACF;QA/CI,EA+CJ;MAER;IACE,CAAA;GACF"}
1
+ {"version":3,"file":"TasksTasksPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/TasksTasksPagePage.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 } from '@burdenoff/fe-libs/ui';\nimport { Filter } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\nimport { rowLinkProps } from '../utils/rowNavigation';\n\nconst GET_WORK_ITEMS = gql`\n query GetWorkItems(\n $workspaceId: ID!\n $filter: PlanmagnetWorkItemFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n type\n status\n priority\n key\n assigneeId\n reporterId\n sprintId\n storyPoints\n estimateMinutes\n dueDate\n labels\n tags\n createdAt\n }\n totalCount\n }\n }\n`;\n\ninterface WorkItemNode {\n id: string;\n title: string;\n type: string;\n status: string;\n priority: string;\n key: string;\n assigneeId: string | null;\n reporterId: string | null;\n sprintId: string | null;\n storyPoints: number | null;\n estimateMinutes: number | null;\n dueDate: string | null;\n labels: string[];\n tags: string[];\n createdAt: string;\n}\n\nconst columns = ['BACKLOG', 'TODO', 'IN_PROGRESS', 'IN_REVIEW', 'TESTING', 'DONE'] as const;\n\nconst colLabel: Record<string, string> = {\n BACKLOG: 'Backlog',\n TODO: 'To Do',\n IN_PROGRESS: 'In Progress',\n IN_REVIEW: 'In Review',\n TESTING: 'Testing',\n DONE: 'Done',\n};\n\nconst colColor: Record<string, string> = {\n BACKLOG: 'border-t-gray-400',\n TODO: 'border-t-blue-400',\n IN_PROGRESS: 'border-t-yellow-400',\n IN_REVIEW: 'border-t-purple-400',\n TESTING: 'border-t-teal-400',\n DONE: 'border-t-green-400',\n};\n\nconst priorityColor: Record<string, string> = {\n LOW: 'bg-gray-100 text-gray-700',\n MEDIUM: 'bg-blue-100 text-blue-700',\n HIGH: 'bg-orange-100 text-orange-700',\n CRITICAL: 'bg-red-100 text-red-700',\n};\n\nconst typeColor: Record<string, string> = {\n STORY: 'bg-green-100 text-green-700',\n BUG: 'bg-red-100 text-red-700',\n TASK: 'bg-blue-100 text-blue-700',\n EPIC: 'bg-purple-100 text-purple-700',\n SUBTASK: 'bg-gray-100 text-gray-700',\n};\n\nexport function TasksTasksPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [priorityFilter, setPriorityFilter] = useState<string>('all');\n const [typeFilter, setTypeFilter] = useState<string>('all');\n\n const { data, loading, error } = useQuery<{\n planmagnetWorkItems: { items: WorkItemNode[]; totalCount: number };\n }>(GET_WORK_ITEMS, {\n variables: {\n workspaceId,\n pagination: { first: 200 },\n },\n skip: !workspaceId,\n });\n\n if (loading) {\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 }\n\n if (error) {\n return <div className=\"p-6 text-red-500\">Error: {error.message}</div>;\n }\n\n const tasks = data?.planmagnetWorkItems?.items ?? [];\n\n const filtered = tasks.filter(\n (t) =>\n (priorityFilter === 'all' || t.priority === priorityFilter.toUpperCase()) &&\n (typeFilter === 'all' || t.type === typeFilter.toUpperCase())\n );\n\n return (\n <div className=\"space-y-4 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Task Board</h1>\n <p className=\"text-sm text-muted-foreground\">{tasks.length} tasks across all projects</p>\n </div>\n </div>\n <div className=\"flex gap-4 items-center flex-wrap\">\n <Filter className=\"h-4 w-4 text-muted-foreground\" />\n <div className=\"flex gap-1\">\n {['all', 'low', 'medium', 'high', 'critical'].map((p) => (\n <button\n key={p}\n onClick={() => setPriorityFilter(p)}\n className={`px-2 py-1 text-xs rounded capitalize ${priorityFilter === p ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {p}\n </button>\n ))}\n </div>\n <div className=\"flex gap-1\">\n {['all', 'story', 'bug', 'task', 'epic'].map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-2 py-1 text-xs rounded capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground'}`}\n >\n {t}\n </button>\n ))}\n </div>\n </div>\n <div className=\"grid grid-cols-6 gap-3 overflow-x-auto\">\n {columns.map((col) => {\n const colTasks = filtered.filter((t) => t.status === col);\n return (\n <div key={col} className=\"min-w-[200px]\">\n <div className={`border-t-2 ${colColor[col]} rounded-t-md p-2 bg-muted/50`}>\n <div className=\"flex justify-between items-center\">\n <span className=\"text-sm font-medium\">{colLabel[col]}</span>\n <span className=\"text-xs bg-muted rounded-full px-1.5\">{colTasks.length}</span>\n </div>\n </div>\n <div className=\"space-y-2 mt-2\">\n {colTasks.map((task) => (\n <Card\n key={task.id}\n {...rowLinkProps(\n () =>\n navigate(`/tasks/task-detail-page?taskId=${encodeURIComponent(task.id)}`),\n task.title\n )}\n >\n <CardContent className=\"p-3 space-y-2\">\n <p className=\"text-sm font-medium leading-tight\">{task.title}</p>\n <p className=\"text-xs text-muted-foreground\">{task.key}</p>\n <div className=\"flex gap-1 flex-wrap\">\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${priorityColor[task.priority] ?? ''}`}\n >\n {task.priority.toLowerCase()}\n </span>\n <span\n className={`text-[10px] px-1.5 py-0.5 rounded-full capitalize ${typeColor[task.type] ?? ''}`}\n >\n {task.type.toLowerCase()}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex gap-1\">\n {(task.labels ?? []).slice(0, 2).map((l) => (\n <span key={l} className=\"text-[9px] px-1 py-0.5 rounded bg-muted\">\n {l}\n </span>\n ))}\n </div>\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] font-medium bg-primary/10 text-primary rounded-full h-5 w-5 flex items-center justify-center\">\n {task.storyPoints ?? 0}\n </span>\n </div>\n </div>\n <div className=\"flex justify-between text-[10px] text-muted-foreground\">\n <span>{task.assigneeId ?? 'Unassigned'}</span>\n <span>{task.dueDate ?? ''}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { KeyboardEvent, MouseEvent } from 'react';
2
+
3
+ /**
4
+ * Props that turn a non-interactive container (a Card, a table row) into an
5
+ * activatable one, so a list row can open its detail page by click OR keyboard.
6
+ *
7
+ * Kept as a props factory rather than a wrapper component so it can be spread onto
8
+ * whatever element a given list already renders, without changing that list's layout.
9
+ */
10
+ export declare function rowLinkProps(onActivate: () => void, label?: string): {
11
+ role: "button";
12
+ tabIndex: number;
13
+ 'aria-label': string | undefined;
14
+ className: string;
15
+ onClick: () => void;
16
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
17
+ };
18
+ /**
19
+ * Stops a click on a nested control (a button, a menu) from also activating the row
20
+ * it sits inside. Spread onto the nested control, not the row.
21
+ */
22
+ export declare function stopRowActivation(event: MouseEvent<HTMLElement>): void;
23
+ /**
24
+ * Builds the path to a detail page that reads its id from a ":id" route segment.
25
+ * Returns the bare path when no id is available, so a missing id degrades to the
26
+ * list-style page rather than producing a path ending in "undefined".
27
+ */
28
+ export declare function detailPath(route: string, id: string | null | undefined): string;
29
+ //# sourceMappingURL=rowNavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rowNavigation.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/utils/rowNavigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM;;;;;;uBAS5C,aAAa,CAAC,WAAW,CAAC;EAOhD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,QAE/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAE/E"}
@@ -0,0 +1,20 @@
1
+ //#region src/planmagnet/utils/rowNavigation.ts
2
+ function e(e, t) {
3
+ return {
4
+ role: "button",
5
+ tabIndex: 0,
6
+ "aria-label": t,
7
+ className: "cursor-pointer transition-shadow hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
8
+ onClick: () => e(),
9
+ onKeyDown: (t) => {
10
+ t.key !== "Enter" && t.key !== " " || (t.preventDefault(), e());
11
+ }
12
+ };
13
+ }
14
+ function t(e, t) {
15
+ return t ? `${e}/${encodeURIComponent(t)}` : e;
16
+ }
17
+ //#endregion
18
+ export { t as detailPath, e as rowLinkProps };
19
+
20
+ //# sourceMappingURL=rowNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rowNavigation.js","names":[],"sources":["../../../src/planmagnet/utils/rowNavigation.ts"],"sourcesContent":["import type { KeyboardEvent, MouseEvent } from 'react';\n\n/**\n * Props that turn a non-interactive container (a Card, a table row) into an\n * activatable one, so a list row can open its detail page by click OR keyboard.\n *\n * Kept as a props factory rather than a wrapper component so it can be spread onto\n * whatever element a given list already renders, without changing that list's layout.\n */\nexport function rowLinkProps(onActivate: () => void, label?: string) {\n return {\n role: 'button' as const,\n tabIndex: 0,\n 'aria-label': label,\n className:\n 'cursor-pointer transition-shadow hover:shadow-md focus-visible:outline-none ' +\n 'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n onClick: () => onActivate(),\n onKeyDown: (event: KeyboardEvent<HTMLElement>) => {\n // Enter and Space are the two activation keys a role=\"button\" must honour.\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n onActivate();\n },\n };\n}\n\n/**\n * Stops a click on a nested control (a button, a menu) from also activating the row\n * it sits inside. Spread onto the nested control, not the row.\n */\nexport function stopRowActivation(event: MouseEvent<HTMLElement>) {\n event.stopPropagation();\n}\n\n/**\n * Builds the path to a detail page that reads its id from a \":id\" route segment.\n * Returns the bare path when no id is available, so a missing id degrades to the\n * list-style page rather than producing a path ending in \"undefined\".\n */\nexport function detailPath(route: string, id: string | null | undefined): string {\n return id ? `${route}/${encodeURIComponent(id)}` : route;\n}\n"],"mappings":";AASA,SAAgB,EAAa,GAAwB,GAAgB;AACnE,QAAO;EACL,MAAM;EACN,UAAU;EACV,cAAc;EACd,WACE;EAEF,eAAe,GAAY;EAC3B,YAAY,MAAsC;AAE5C,KAAM,QAAQ,WAAW,EAAM,QAAQ,QAC3C,EAAM,gBAAgB,EACtB,GAAY;;EAEf;;AAgBH,SAAgB,EAAW,GAAe,GAAuC;AAC/E,QAAO,IAAK,GAAG,EAAM,GAAG,mBAAmB,EAAG,KAAK"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-planmagnet",
3
- "version": "2026.830.1",
3
+ "version": "2026.923.1",
4
4
  "description": "Burdenoff PlanMagnet Microfrontend",
5
5
  "type": "module",
6
6
  "files": [