@burdenoff/microfe-planmagnet 2026.525.1 → 2026.715.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.
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/planmagnet/PlanMagnetRoot.d.ts +5 -0
- package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -0
- package/dist/planmagnet/PlanMagnetRoutes.d.ts +2 -0
- package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -0
- package/dist/planmagnet/index.d.ts +5 -0
- package/dist/planmagnet/index.d.ts.map +1 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js +4 -4
- package/dist/planmagnet/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.js +1 -1
- package/dist/planmagnet/pages/CollaborationCollaborationPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationCreateChannelPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationFilesPagePage.js +1 -1
- package/dist/planmagnet/pages/CollaborationFilesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.js +1 -1
- package/dist/planmagnet/pages/CollaborationMessagesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.js +1 -1
- package/dist/planmagnet/pages/CollaborationNewDiscussionPagePage.js.map +1 -1
- package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/DashboardDashboardPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.js +2 -2
- package/dist/planmagnet/pages/MeetingsScheduleMeetingPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCreateProductPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsCreateRoadmapPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsEditProductPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsEditReleasePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsFeatureAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeatureDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsFeaturesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsNewFeaturePagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js +2 -2
- package/dist/planmagnet/pages/ProductsProductDetailPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsProductsPagePage.js +3 -3
- package/dist/planmagnet/pages/ProductsProductsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsReleaseDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsReleasesPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js +1 -1
- package/dist/planmagnet/pages/ProductsRoadmapsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsActiveProjectsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsCreateProjectPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsEditProjectPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsMilestoneDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningEditPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsPlanningPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ProjectsProjectsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js +1 -1
- package/dist/planmagnet/pages/ReportsCreateReportPagePage.js.map +1 -1
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/ReportsReportsPagePage.js +3 -3
- package/dist/planmagnet/pages/ReportsReportsPagePage.js.map +1 -1
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js +2 -2
- package/dist/planmagnet/pages/SprintsStartSprintPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksCreateTaskPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksEditTaskPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTaskDetailPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TasksTasksPagePage.js +1 -1
- package/dist/planmagnet/pages/TasksTasksPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js +1 -1
- package/dist/planmagnet/pages/TeamCreateTeamPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js +1 -1
- package/dist/planmagnet/pages/TeamInviteMemberPagePage.js.map +1 -1
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts +2 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.d.ts.map +1 -0
- package/dist/planmagnet/pages/TeamTeamPagePage.js +2 -2
- package/dist/planmagnet/pages/TeamTeamPagePage.js.map +1 -1
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.d.ts +2 -0
- package/dist/planmagnet/pages/WorkspaceCreateWorkspacePagePage.d.ts.map +1 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.d.ts +31 -0
- package/dist/planmagnet/providers/PlanMagnetProvider.d.ts.map +1 -0
- package/dist/planmagnet/store/planmagnetStore.d.ts +30 -0
- package/dist/planmagnet/store/planmagnetStore.d.ts.map +1 -0
- package/dist/planmagnet/types/index.d.ts +317 -0
- package/dist/planmagnet/types/index.d.ts.map +1 -0
- package/dist/planmagnet/utils/cn.d.ts +4 -0
- package/dist/planmagnet/utils/cn.d.ts.map +1 -0
- package/dist/planmagnet/utils/navigation.d.ts +2 -0
- package/dist/planmagnet/utils/navigation.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductsRoadmapAnalyticsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { TrendingUp, Target, CheckCircle, AlertTriangle, BarChart3, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router-dom';\n\nconst GET_ROADMAP_ANALYTICS = gql`\n query GetRoadmapAnalytics($id: ID!) {\n planmagnetRoadmap(id: $id) {\n id\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 swimlane\n }\n }\n }\n`;\n\nconst LIST_FEATURE_REQUESTS_FOR_ANALYTICS = gql`\n query ListFeatureRequestsForRoadmapAnalytics($workspaceId: ID!, $pagination: PaginationInput) {\n planmagnetFeatureRequests(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n status\n voteCount\n businessValue\n priorityScore\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 swimlane: string | null;\n}\n\nexport function ProductsRoadmapAnalyticsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const roadmapId = params.id ?? '';\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_ROADMAP_ANALYTICS, {\n variables: { id: roadmapId },\n skip: !roadmapId,\n });\n\n const {\n data: featuresData,\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_FEATURE_REQUESTS_FOR_ANALYTICS, {\n variables: { workspaceId, pagination: { first: 100 } },\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 analytics: {error.message}</div>;\n }\n\n const roadmap = data?.planmagnetRoadmap;\n if (!roadmap) return <div className=\"p-6 text-muted-foreground\">Roadmap not found.</div>;\n\n const items: RoadmapItemNode[] = roadmap.items ?? [];\n const allFeatures = featuresData?.featureRequests?.items ?? [];\n\n const completedItems = items.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE');\n const progress = items.length > 0 ? Math.round((completedItems.length / items.length) * 100) : 0;\n\n // Items by status\n const itemsByStatus: Record<string, number> = {};\n for (const item of items) {\n itemsByStatus[item.status] = (itemsByStatus[item.status] || 0) + 1;\n }\n\n // Feature status distribution\n const featuresByStatus: Record<string, number> = {};\n for (const f of allFeatures) {\n featuresByStatus[f.status] = (featuresByStatus[f.status] || 0) + 1;\n }\n\n // Items by swimlane\n const itemsBySwimlane: Record<string, number> = {};\n for (const item of items) {\n const lane = item.swimlane ?? 'Uncategorized';\n itemsBySwimlane[lane] = (itemsBySwimlane[lane] || 0) + 1;\n }\n\n // Items with overdue end dates\n const now = new Date();\n const overdueItems = items.filter(\n (i) => i.endDate && new Date(i.endDate) < now && i.status !== 'COMPLETED' && i.status !== 'DONE'\n );\n\n // Health score based on progress and overdue items\n const healthScore = Math.max(\n 0,\n Math.round(progress * 0.7 + (1 - overdueItems.length / Math.max(items.length, 1)) * 30)\n );\n\n // Monthly velocity (items completed by month based on endDate)\n const velocityMap: Record<string, { planned: number; completed: number }> = {};\n for (const item of items) {\n if (item.endDate) {\n const month = new Date(item.endDate).toLocaleDateString('en-US', {\n month: 'short',\n year: '2-digit',\n });\n if (!velocityMap[month]) velocityMap[month] = { planned: 0, completed: 0 };\n velocityMap[month].planned += 1;\n if (item.status === 'COMPLETED' || item.status === 'DONE') {\n velocityMap[month].completed += 1;\n }\n }\n }\n const velocityData = Object.entries(velocityMap)\n .map(([month, vals]) => ({ month, ...vals }))\n .slice(-6);\n const maxVal = Math.max(...velocityData.map((d) => Math.max(d.planned, d.completed)), 1);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Roadmap Analytics</h1>\n <p className=\"text-sm text-muted-foreground\">\n {roadmap.name} - {roadmap.type.toLowerCase()}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <Target className=\"h-4 w-4\" />\n Health Score\n </div>\n <p className=\"text-2xl font-bold mt-1\">{healthScore}/100</p>\n <div className=\"w-full h-2 rounded-full bg-muted mt-2 overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-green-500\"\n style={{ width: `${healthScore}%` }}\n />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <TrendingUp className=\"h-4 w-4\" />\n Progress\n </div>\n <p className=\"text-2xl font-bold mt-1\">{progress}%</p>\n <p className=\"text-xs text-muted-foreground mt-1\">{items.length} items total</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <CheckCircle className=\"h-4 w-4\" />\n Completed\n </div>\n <p className=\"text-2xl font-bold mt-1\">{completedItems.length}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">items completed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <AlertTriangle className=\"h-4 w-4\" />\n Overdue\n </div>\n <p className=\"text-2xl font-bold mt-1\">{overdueItems.length}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">items past end date</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Item Velocity\n </CardTitle>\n </CardHeader>\n <CardContent>\n {velocityData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-8\">\n No timeline data available\n </p>\n ) : (\n <div className=\"flex items-end gap-2 h-48\">\n {velocityData.map((d) => (\n <div key={d.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <div className=\"flex gap-0.5 items-end w-full justify-center h-40\">\n <div\n className=\"w-3 bg-primary/30 rounded-t\"\n style={{ height: `${(d.planned / maxVal) * 100}%` }}\n title={`Planned: ${d.planned}`}\n />\n <div\n className=\"w-3 bg-primary rounded-t\"\n style={{ height: `${(d.completed / maxVal) * 100}%` }}\n title={`Completed: ${d.completed}`}\n />\n </div>\n <span className=\"text-xs text-muted-foreground\">{d.month}</span>\n </div>\n ))}\n </div>\n )}\n <div className=\"flex gap-4 justify-center mt-3 text-xs\">\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded bg-primary/30\" />\n Planned\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded bg-primary\" />\n Completed\n </span>\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Item Status Breakdown</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(itemsByStatus).map(([status, count]) => {\n const total = items.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n const colors: Record<string, string> = {\n TODO: 'bg-gray-400',\n PLANNED: 'bg-yellow-400',\n IN_PROGRESS: 'bg-blue-400',\n BLOCKED: 'bg-red-400',\n DONE: 'bg-green-400',\n COMPLETED: 'bg-green-400',\n };\n return (\n <div key={status}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span className=\"capitalize\">{status.toLowerCase().replace('_', ' ')}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${colors[status] ?? 'bg-gray-300'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle>Feature Request Status</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(featuresByStatus).length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n No feature request data\n </p>\n ) : (\n Object.entries(featuresByStatus).map(([status, count]) => {\n const total = allFeatures.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n const colors: Record<string, string> = {\n SUBMITTED: 'bg-gray-400',\n UNDER_REVIEW: 'bg-yellow-400',\n PLANNED: 'bg-blue-400',\n IN_PROGRESS: 'bg-purple-400',\n COMPLETED: 'bg-green-400',\n DECLINED: 'bg-red-400',\n };\n return (\n <div key={status}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span className=\"capitalize\">{status.toLowerCase().replace('_', ' ')}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${colors[status] ?? 'bg-gray-300'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Swimlane Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(itemsBySwimlane).length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-4\">No swimlane data</p>\n ) : (\n Object.entries(itemsBySwimlane).map(([lane, count]) => {\n const total = items.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n return (\n <div key={lane}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span>{lane}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-primary\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })\n )}\n </CardContent>\n </Card>\n </div>\n\n {overdueItems.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Overdue Items</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {overdueItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n <p className=\"text-xs text-muted-foreground\">\n Due: {item.endDate ? new Date(item.endDate).toLocaleDateString() : 'N/A'}\n </p>\n </div>\n <span className=\"text-xs px-2 py-0.5 rounded-full bg-red-100 text-red-800 capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductsRoadmapAnalyticsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ProductsRoadmapAnalyticsPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { TrendingUp, Target, CheckCircle, AlertTriangle, BarChart3, Loader2 } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\nimport { useParams } from 'react-router-dom';\n\nconst GET_ROADMAP_ANALYTICS = gql`\n query GetRoadmapAnalytics($id: ID!) {\n planmagnetRoadmap(id: $id) {\n id\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 swimlane\n }\n }\n }\n`;\n\nconst LIST_FEATURE_REQUESTS_FOR_ANALYTICS = gql`\n query ListFeatureRequestsForRoadmapAnalytics($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetFeatureRequests(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n status\n voteCount\n businessValue\n priorityScore\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 swimlane: string | null;\n}\n\nexport function ProductsRoadmapAnalyticsPagePage() {\n const { workspaceId } = usePlanMagnet();\n const params = useParams<{ id: string }>();\n const roadmapId = params.id ?? '';\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_ROADMAP_ANALYTICS, {\n variables: { id: roadmapId },\n skip: !roadmapId,\n });\n\n const {\n data: featuresData,\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_FEATURE_REQUESTS_FOR_ANALYTICS, {\n variables: { workspaceId, pagination: { first: 100 } },\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 analytics: {error.message}</div>;\n }\n\n const roadmap = data?.planmagnetRoadmap;\n if (!roadmap) return <div className=\"p-6 text-muted-foreground\">Roadmap not found.</div>;\n\n const items: RoadmapItemNode[] = roadmap.items ?? [];\n const allFeatures = featuresData?.featureRequests?.items ?? [];\n\n const completedItems = items.filter((i) => i.status === 'COMPLETED' || i.status === 'DONE');\n const progress = items.length > 0 ? Math.round((completedItems.length / items.length) * 100) : 0;\n\n // Items by status\n const itemsByStatus: Record<string, number> = {};\n for (const item of items) {\n itemsByStatus[item.status] = (itemsByStatus[item.status] || 0) + 1;\n }\n\n // Feature status distribution\n const featuresByStatus: Record<string, number> = {};\n for (const f of allFeatures) {\n featuresByStatus[f.status] = (featuresByStatus[f.status] || 0) + 1;\n }\n\n // Items by swimlane\n const itemsBySwimlane: Record<string, number> = {};\n for (const item of items) {\n const lane = item.swimlane ?? 'Uncategorized';\n itemsBySwimlane[lane] = (itemsBySwimlane[lane] || 0) + 1;\n }\n\n // Items with overdue end dates\n const now = new Date();\n const overdueItems = items.filter(\n (i) => i.endDate && new Date(i.endDate) < now && i.status !== 'COMPLETED' && i.status !== 'DONE'\n );\n\n // Health score based on progress and overdue items\n const healthScore = Math.max(\n 0,\n Math.round(progress * 0.7 + (1 - overdueItems.length / Math.max(items.length, 1)) * 30)\n );\n\n // Monthly velocity (items completed by month based on endDate)\n const velocityMap: Record<string, { planned: number; completed: number }> = {};\n for (const item of items) {\n if (item.endDate) {\n const month = new Date(item.endDate).toLocaleDateString('en-US', {\n month: 'short',\n year: '2-digit',\n });\n if (!velocityMap[month]) velocityMap[month] = { planned: 0, completed: 0 };\n velocityMap[month].planned += 1;\n if (item.status === 'COMPLETED' || item.status === 'DONE') {\n velocityMap[month].completed += 1;\n }\n }\n }\n const velocityData = Object.entries(velocityMap)\n .map(([month, vals]) => ({ month, ...vals }))\n .slice(-6);\n const maxVal = Math.max(...velocityData.map((d) => Math.max(d.planned, d.completed)), 1);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Roadmap Analytics</h1>\n <p className=\"text-sm text-muted-foreground\">\n {roadmap.name} - {roadmap.type.toLowerCase()}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <Target className=\"h-4 w-4\" />\n Health Score\n </div>\n <p className=\"text-2xl font-bold mt-1\">{healthScore}/100</p>\n <div className=\"w-full h-2 rounded-full bg-muted mt-2 overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-green-500\"\n style={{ width: `${healthScore}%` }}\n />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <TrendingUp className=\"h-4 w-4\" />\n Progress\n </div>\n <p className=\"text-2xl font-bold mt-1\">{progress}%</p>\n <p className=\"text-xs text-muted-foreground mt-1\">{items.length} items total</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <CheckCircle className=\"h-4 w-4\" />\n Completed\n </div>\n <p className=\"text-2xl font-bold mt-1\">{completedItems.length}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">items completed</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-xs\">\n <AlertTriangle className=\"h-4 w-4\" />\n Overdue\n </div>\n <p className=\"text-2xl font-bold mt-1\">{overdueItems.length}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">items past end date</p>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Item Velocity\n </CardTitle>\n </CardHeader>\n <CardContent>\n {velocityData.length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-8\">\n No timeline data available\n </p>\n ) : (\n <div className=\"flex items-end gap-2 h-48\">\n {velocityData.map((d) => (\n <div key={d.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <div className=\"flex gap-0.5 items-end w-full justify-center h-40\">\n <div\n className=\"w-3 bg-primary/30 rounded-t\"\n style={{ height: `${(d.planned / maxVal) * 100}%` }}\n title={`Planned: ${d.planned}`}\n />\n <div\n className=\"w-3 bg-primary rounded-t\"\n style={{ height: `${(d.completed / maxVal) * 100}%` }}\n title={`Completed: ${d.completed}`}\n />\n </div>\n <span className=\"text-xs text-muted-foreground\">{d.month}</span>\n </div>\n ))}\n </div>\n )}\n <div className=\"flex gap-4 justify-center mt-3 text-xs\">\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded bg-primary/30\" />\n Planned\n </span>\n <span className=\"flex items-center gap-1\">\n <span className=\"h-2 w-2 rounded bg-primary\" />\n Completed\n </span>\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Item Status Breakdown</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(itemsByStatus).map(([status, count]) => {\n const total = items.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n const colors: Record<string, string> = {\n TODO: 'bg-gray-400',\n PLANNED: 'bg-yellow-400',\n IN_PROGRESS: 'bg-blue-400',\n BLOCKED: 'bg-red-400',\n DONE: 'bg-green-400',\n COMPLETED: 'bg-green-400',\n };\n return (\n <div key={status}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span className=\"capitalize\">{status.toLowerCase().replace('_', ' ')}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${colors[status] ?? 'bg-gray-300'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle>Feature Request Status</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(featuresByStatus).length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-4\">\n No feature request data\n </p>\n ) : (\n Object.entries(featuresByStatus).map(([status, count]) => {\n const total = allFeatures.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n const colors: Record<string, string> = {\n SUBMITTED: 'bg-gray-400',\n UNDER_REVIEW: 'bg-yellow-400',\n PLANNED: 'bg-blue-400',\n IN_PROGRESS: 'bg-purple-400',\n COMPLETED: 'bg-green-400',\n DECLINED: 'bg-red-400',\n };\n return (\n <div key={status}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span className=\"capitalize\">{status.toLowerCase().replace('_', ' ')}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={`h-full rounded-full ${colors[status] ?? 'bg-gray-300'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Swimlane Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(itemsBySwimlane).length === 0 ? (\n <p className=\"text-sm text-muted-foreground text-center py-4\">No swimlane data</p>\n ) : (\n Object.entries(itemsBySwimlane).map(([lane, count]) => {\n const total = items.length;\n const pct = total > 0 ? Math.round((count / total) * 100) : 0;\n return (\n <div key={lane}>\n <div className=\"flex justify-between text-sm mb-1\">\n <span>{lane}</span>\n <span className=\"font-medium\">\n {count} ({pct}%)\n </span>\n </div>\n <div className=\"w-full h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-primary\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })\n )}\n </CardContent>\n </Card>\n </div>\n\n {overdueItems.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Overdue Items</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {overdueItems.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between border rounded-md p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{item.title}</p>\n <p className=\"text-xs text-muted-foreground\">\n Due: {item.endDate ? new Date(item.endDate).toLocaleDateString() : 'N/A'}\n </p>\n </div>\n <span className=\"text-xs px-2 py-0.5 rounded-full bg-red-100 text-red-800 capitalize\">\n {item.status.toLowerCase().replace('_', ' ')}\n </span>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsRoadmapDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsRoadmapDetailPagePage.tsx"],"names":[],"mappings":"AA6DA,wBAAgB,6BAA6B,4CAuL5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductsRoadmapsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProductsRoadmapsPagePage.tsx"],"names":[],"mappings":"AA8DA,wBAAgB,wBAAwB,4CAiKvC"}
|
|
@@ -7,7 +7,7 @@ import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
|
7
7
|
import { Badge as d, Button as f, Card as p, CardContent as m, CardHeader as h, CardTitle as g } from "@burdenoff/fe-libs/ui";
|
|
8
8
|
//#region src/planmagnet/pages/ProductsRoadmapsPagePage.tsx
|
|
9
9
|
var _ = s`
|
|
10
|
-
query ListRoadmapsPage($workspaceId: ID!, $filter: RoadmapFilter, $pagination:
|
|
10
|
+
query ListRoadmapsPage($workspaceId: ID!, $filter: RoadmapFilter, $pagination: PlanmagnetPaginationInput) {
|
|
11
11
|
planmagnetRoadmaps(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
|
|
12
12
|
items {
|
|
13
13
|
id
|
|
@@ -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 } from '../providers/PlanMagnetProvider';\n\nconst LIST_ROADMAPS = gql`\n query ListRoadmapsPage($workspaceId: ID!, $filter: RoadmapFilter, $pagination: PaginationInput) {\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 { 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\">\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 } from '../providers/PlanMagnetProvider';\n\nconst LIST_ROADMAPS = gql`\n query ListRoadmapsPage($workspaceId: ID!, $filter: RoadmapFilter, $pagination: PlanmagnetPaginationInput) {\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 { 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\">\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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsActiveProjectsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsActiveProjectsPagePage.tsx"],"names":[],"mappings":"AA0CA,wBAAgB,8BAA8B,4CAuF7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsCreateProjectPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsCreateProjectPagePage.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,6BAA6B,4CA4J5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsEditProjectPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsEditProjectPagePage.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,2BAA2B,4CAwJ1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsMilestoneDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsMilestoneDetailPagePage.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,+BAA+B,4CAuH9C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsMilestonesPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsMilestonesPagePage.tsx"],"names":[],"mappings":"AA4CA,wBAAgB,0BAA0B,4CAkGzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningDetailPagePage.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,8BAA8B,4CA2K7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningEditPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningEditPagePage.tsx"],"names":[],"mappings":"AA8CA,wBAAgB,4BAA4B,4CA+K3C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsPlanningPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsPlanningPagePage.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,wBAAwB,4CAuHvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsProjectDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsProjectDetailPagePage.tsx"],"names":[],"mappings":"AAuEA,wBAAgB,6BAA6B,4CAyS5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectsProjectsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ProjectsProjectsPagePage.tsx"],"names":[],"mappings":"AAyCA,wBAAgB,wBAAwB,4CA6JvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReportsCreateReportPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ReportsCreateReportPagePage.tsx"],"names":[],"mappings":"AAgCA,wBAAgB,2BAA2B,4CA8I1C"}
|
|
@@ -7,7 +7,7 @@ import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
|
7
7
|
import { Button as u, Card as d, CardContent as f, CardHeader as p, CardTitle as m, Input as h } from "@burdenoff/fe-libs/ui";
|
|
8
8
|
//#region src/planmagnet/pages/ReportsCreateReportPagePage.tsx
|
|
9
9
|
var g = o`
|
|
10
|
-
query GetProjectsForReport($workspaceId: ID!, $pagination:
|
|
10
|
+
query GetProjectsForReport($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {
|
|
11
11
|
planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {
|
|
12
12
|
items {
|
|
13
13
|
id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsCreateReportPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsCreateReportPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, BarChart3 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_REPORT = gql`\n query GetProjectsForReport($workspaceId: ID!, $pagination:
|
|
1
|
+
{"version":3,"file":"ReportsCreateReportPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsCreateReportPagePage.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, Button, Input } from '@burdenoff/fe-libs/ui';\nimport { Save, X, BarChart3 } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_PROJECTS_FOR_REPORT = gql`\n query GetProjectsForReport($workspaceId: ID!, $pagination: PlanmagnetPaginationInput) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $pagination) {\n items {\n id\n name\n key\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n}\n\ninterface ProjectsData {\n projects: { items: ProjectNode[]; totalCount: number };\n}\n\nexport function ReportsCreateReportPagePage() {\n const { workspaceId } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n\n const { data, loading, error } = useQuery<ProjectsData>(GET_PROJECTS_FOR_REPORT, {\n variables: {\n workspaceId,\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const [form, setForm] = useState({\n name: '',\n description: '',\n type: 'velocity',\n projectId: '',\n schedule: 'weekly',\n });\n const types = [\n 'velocity',\n 'burndown',\n 'burnup',\n 'cumulative_flow',\n 'cycle_time',\n 'lead_time',\n 'custom',\n ] as const;\n const schedules = ['daily', 'weekly', 'monthly'] as const;\n\n const projects = data?.planmagnetProjects?.items ?? [];\n\n const handleCreate = () => {\n if (!form.name.trim()) return;\n navigate('/reports');\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 return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Create Report</h1>\n <p className=\"text-sm text-muted-foreground\">Configure a new automated report.</p>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/reports')}>\n <X className=\"mr-1 h-4 w-4\" />\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleCreate}>\n <Save className=\"mr-1 h-4 w-4\" />\n Create Report\n </Button>\n </div>\n </div>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4\" />\n Report Configuration\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div>\n <label className=\"text-sm font-medium\">Report Name</label>\n <Input\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"mt-1\"\n placeholder=\"e.g. Sprint Velocity Report\"\n />\n </div>\n <div>\n <label className=\"text-sm font-medium\">Description</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 placeholder=\"What does this report track?\"\n />\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <div>\n <label className=\"text-sm font-medium\">Type</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.type}\n onChange={(e) => setForm({ ...form, type: e.target.value })}\n >\n {types.map((t) => (\n <option key={t} value={t}>\n {t.replace('_', ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Project (optional)</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.projectId}\n onChange={(e) => setForm({ ...form, projectId: e.target.value })}\n >\n <option value=\"\">All projects</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.key})\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"text-sm font-medium\">Schedule</label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={form.schedule}\n onChange={(e) => setForm({ ...form, schedule: e.target.value })}\n >\n {schedules.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReportsReportsPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.tsx"],"names":[],"mappings":"AA6FA,wBAAgB,sBAAsB,4CAoKrC"}
|
|
@@ -9,9 +9,9 @@ import { Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as
|
|
|
9
9
|
var g = s`
|
|
10
10
|
query GetReportsData(
|
|
11
11
|
$workspaceId: ID!
|
|
12
|
-
$projectPagination:
|
|
13
|
-
$sprintPagination:
|
|
14
|
-
$workItemPagination:
|
|
12
|
+
$projectPagination: PlanmagnetPaginationInput
|
|
13
|
+
$sprintPagination: PlanmagnetPaginationInput
|
|
14
|
+
$workItemPagination: PlanmagnetPaginationInput
|
|
15
15
|
) {
|
|
16
16
|
planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {
|
|
17
17
|
items {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport { BarChart3, Plus, Clock, Calendar } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_REPORTS_DATA = gql`\n query GetReportsData(\n $workspaceId: ID!\n $projectPagination: PaginationInput\n $sprintPagination: PaginationInput\n $workItemPagination: PaginationInput\n ) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {\n items {\n id\n name\n key\n status\n methodology\n startDate\n endDate\n }\n totalCount\n }\n planmagnetSprints(workspaceId: $workspaceId, pagination: $sprintPagination) {\n items {\n id\n name\n status\n velocity\n startDate\n endDate\n }\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {\n items {\n id\n status\n storyPoints\n createdAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n status: string;\n methodology: string | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface SprintNode {\n id: string;\n name: string;\n status: string;\n velocity: number | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface WorkItemNode {\n id: string;\n status: string;\n storyPoints: number | null;\n createdAt: string;\n}\n\ninterface ReportsData {\n projects: { items: ProjectNode[]; totalCount: number };\n sprints: { items: SprintNode[]; totalCount: number };\n workItems: { items: WorkItemNode[]; totalCount: number };\n}\n\nconst typeColor: Record<string, string> = {\n velocity: 'bg-blue-100 text-blue-800',\n burndown: 'bg-orange-100 text-orange-800',\n burnup: 'bg-green-100 text-green-800',\n cumulative_flow: 'bg-purple-100 text-purple-800',\n cycle_time: 'bg-yellow-100 text-yellow-800',\n lead_time: 'bg-pink-100 text-pink-800',\n project_status: 'bg-gray-100 text-gray-800',\n};\n\nexport function ReportsReportsPagePage() {\n const { workspaceId, currentUser } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [typeFilter, setTypeFilter] = useState<string>('all');\n\n const { data, loading, error } = useQuery<ReportsData>(GET_REPORTS_DATA, {\n variables: {\n workspaceId,\n projectPagination: { first: 100 },\n sprintPagination: { first: 100 },\n workItemPagination: { first: 500 },\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 projects = data?.planmagnetProjects?.items ?? [];\n const sprints = data?.planmagnetSprints?.items ?? [];\n const workItems = data?.planmagnetWorkItems?.items ?? [];\n\n const completedSprints = sprints.filter((s) => s.status === 'COMPLETED');\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n const creatorName = currentUser?.name ?? currentUser?.firstName ?? 'System';\n\n const reports = [\n ...completedSprints.map((sprint) => ({\n id: `velocity-${sprint.id}`,\n name: `${sprint.name} Velocity Report`,\n description: `Velocity analysis for ${sprint.name} (${sprint.velocity ?? 0} pts)`,\n type: 'velocity',\n createdBy: creatorName,\n lastRun: sprint.endDate ?? '',\n schedule: null as string | null,\n })),\n ...activeSprints.map((sprint) => ({\n id: `burndown-${sprint.id}`,\n name: `${sprint.name} Burndown`,\n description: `Active burndown tracking for ${sprint.name}`,\n type: 'burndown',\n createdBy: creatorName,\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'daily' as string | null,\n })),\n ...projects\n .filter((p) => p.status === 'ACTIVE')\n .map((project) => ({\n id: `status-${project.id}`,\n name: `${project.name} Status Report`,\n description: `Project status overview for ${project.key}`,\n type: 'project_status',\n createdBy: creatorName,\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'weekly' as string | null,\n })),\n ];\n\n const types = ['all', ...new Set(reports.map((r) => r.type))];\n const filtered = typeFilter === 'all' ? reports : reports.filter((r) => r.type === typeFilter);\n\n const scheduledCount = reports.filter((r) => r.schedule).length;\n const todayStr = new Date().toISOString().split('T')[0];\n const runTodayCount = reports.filter((r) => r.lastRun === todayStr).length;\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\">Reports</h1>\n <p className=\"text-sm text-muted-foreground\">{reports.length} reports configured</p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/reports/create')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Report\n </Button>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Reports</p>\n <p className=\"text-xl font-bold\">{reports.length}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Scheduled</p>\n <p className=\"text-xl font-bold\">{scheduledCount}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Run Today</p>\n <p className=\"text-xl font-bold\">{runTodayCount}</p>\n </CardContent>\n </Card>\n </div>\n <div className=\"flex gap-1\">\n {types.map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {t === 'all' ? 'All' : t.replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((report) => (\n <Card key={report.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-primary\" />\n {report.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${typeColor[report.type] ?? 'bg-gray-100'}`}\n >\n {report.type.replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{report.description}</p>\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n {report.schedule && (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n {report.schedule}\n </span>\n )}\n {report.lastRun && (\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n Last: {report.lastRun}\n </span>\n )}\n <span className=\"flex items-center gap-1\">{report.createdBy}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n {filtered.length === 0 && (\n <div className=\"col-span-2 text-center py-12\">\n <BarChart3 className=\"h-12 w-12 text-muted-foreground mx-auto mb-3\" />\n <p className=\"text-sm text-muted-foreground\">\n No reports found for the selected filter.\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ReportsReportsPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/ReportsReportsPagePage.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, Button } from '@burdenoff/fe-libs/ui';\nimport { BarChart3, Plus, Clock, Calendar } from 'lucide-react';\nimport { usePlanMagnet, usePlanMagnetNavigate } from '../providers/PlanMagnetProvider';\n\nconst GET_REPORTS_DATA = gql`\n query GetReportsData(\n $workspaceId: ID!\n $projectPagination: PlanmagnetPaginationInput\n $sprintPagination: PlanmagnetPaginationInput\n $workItemPagination: PlanmagnetPaginationInput\n ) {\n planmagnetProjects(workspaceId: $workspaceId, pagination: $projectPagination) {\n items {\n id\n name\n key\n status\n methodology\n startDate\n endDate\n }\n totalCount\n }\n planmagnetSprints(workspaceId: $workspaceId, pagination: $sprintPagination) {\n items {\n id\n name\n status\n velocity\n startDate\n endDate\n }\n totalCount\n }\n planmagnetWorkItems(workspaceId: $workspaceId, pagination: $workItemPagination) {\n items {\n id\n status\n storyPoints\n createdAt\n }\n totalCount\n }\n }\n`;\n\ninterface ProjectNode {\n id: string;\n name: string;\n key: string;\n status: string;\n methodology: string | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface SprintNode {\n id: string;\n name: string;\n status: string;\n velocity: number | null;\n startDate: string | null;\n endDate: string | null;\n}\n\ninterface WorkItemNode {\n id: string;\n status: string;\n storyPoints: number | null;\n createdAt: string;\n}\n\ninterface ReportsData {\n projects: { items: ProjectNode[]; totalCount: number };\n sprints: { items: SprintNode[]; totalCount: number };\n workItems: { items: WorkItemNode[]; totalCount: number };\n}\n\nconst typeColor: Record<string, string> = {\n velocity: 'bg-blue-100 text-blue-800',\n burndown: 'bg-orange-100 text-orange-800',\n burnup: 'bg-green-100 text-green-800',\n cumulative_flow: 'bg-purple-100 text-purple-800',\n cycle_time: 'bg-yellow-100 text-yellow-800',\n lead_time: 'bg-pink-100 text-pink-800',\n project_status: 'bg-gray-100 text-gray-800',\n};\n\nexport function ReportsReportsPagePage() {\n const { workspaceId, currentUser } = usePlanMagnet();\n const navigate = usePlanMagnetNavigate();\n const [typeFilter, setTypeFilter] = useState<string>('all');\n\n const { data, loading, error } = useQuery<ReportsData>(GET_REPORTS_DATA, {\n variables: {\n workspaceId,\n projectPagination: { first: 100 },\n sprintPagination: { first: 100 },\n workItemPagination: { first: 500 },\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 projects = data?.planmagnetProjects?.items ?? [];\n const sprints = data?.planmagnetSprints?.items ?? [];\n const workItems = data?.planmagnetWorkItems?.items ?? [];\n\n const completedSprints = sprints.filter((s) => s.status === 'COMPLETED');\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n const creatorName = currentUser?.name ?? currentUser?.firstName ?? 'System';\n\n const reports = [\n ...completedSprints.map((sprint) => ({\n id: `velocity-${sprint.id}`,\n name: `${sprint.name} Velocity Report`,\n description: `Velocity analysis for ${sprint.name} (${sprint.velocity ?? 0} pts)`,\n type: 'velocity',\n createdBy: creatorName,\n lastRun: sprint.endDate ?? '',\n schedule: null as string | null,\n })),\n ...activeSprints.map((sprint) => ({\n id: `burndown-${sprint.id}`,\n name: `${sprint.name} Burndown`,\n description: `Active burndown tracking for ${sprint.name}`,\n type: 'burndown',\n createdBy: creatorName,\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'daily' as string | null,\n })),\n ...projects\n .filter((p) => p.status === 'ACTIVE')\n .map((project) => ({\n id: `status-${project.id}`,\n name: `${project.name} Status Report`,\n description: `Project status overview for ${project.key}`,\n type: 'project_status',\n createdBy: creatorName,\n lastRun: new Date().toISOString().split('T')[0],\n schedule: 'weekly' as string | null,\n })),\n ];\n\n const types = ['all', ...new Set(reports.map((r) => r.type))];\n const filtered = typeFilter === 'all' ? reports : reports.filter((r) => r.type === typeFilter);\n\n const scheduledCount = reports.filter((r) => r.schedule).length;\n const todayStr = new Date().toISOString().split('T')[0];\n const runTodayCount = reports.filter((r) => r.lastRun === todayStr).length;\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\">Reports</h1>\n <p className=\"text-sm text-muted-foreground\">{reports.length} reports configured</p>\n </div>\n <Button size=\"sm\" onClick={() => navigate('/reports/create')}>\n <Plus className=\"mr-1 h-4 w-4\" />\n New Report\n </Button>\n </div>\n <div className=\"grid grid-cols-3 gap-4\">\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Total Reports</p>\n <p className=\"text-xl font-bold\">{reports.length}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Scheduled</p>\n <p className=\"text-xl font-bold\">{scheduledCount}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"pt-4\">\n <p className=\"text-xs text-muted-foreground\">Run Today</p>\n <p className=\"text-xl font-bold\">{runTodayCount}</p>\n </CardContent>\n </Card>\n </div>\n <div className=\"flex gap-1\">\n {types.map((t) => (\n <button\n key={t}\n onClick={() => setTypeFilter(t)}\n className={`px-3 py-1.5 text-sm rounded-md capitalize ${typeFilter === t ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {t === 'all' ? 'All' : t.replace('_', ' ')}\n </button>\n ))}\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((report) => (\n <Card key={report.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-primary\" />\n {report.name}\n </CardTitle>\n <span\n className={`text-xs px-2 py-0.5 rounded-full capitalize ${typeColor[report.type] ?? 'bg-gray-100'}`}\n >\n {report.type.replace('_', ' ')}\n </span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{report.description}</p>\n <div className=\"flex gap-3 text-xs text-muted-foreground\">\n {report.schedule && (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n {report.schedule}\n </span>\n )}\n {report.lastRun && (\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n Last: {report.lastRun}\n </span>\n )}\n <span className=\"flex items-center gap-1\">{report.createdBy}</span>\n </div>\n </CardContent>\n </Card>\n ))}\n {filtered.length === 0 && (\n <div className=\"col-span-2 text-center py-12\">\n <BarChart3 className=\"h-12 w-12 text-muted-foreground mx-auto mb-3\" />\n <p className=\"text-sm text-muted-foreground\">\n No reports found for the selected filter.\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SprintsStartSprintPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"names":[],"mappings":"AAkFA,wBAAgB,0BAA0B,4CAiNzC"}
|
|
@@ -6,7 +6,7 @@ import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
|
6
6
|
import { Badge as u, Button as d, Card as f, CardContent as p, CardHeader as m, CardTitle as h } from "@burdenoff/fe-libs/ui";
|
|
7
7
|
//#region src/planmagnet/pages/SprintsStartSprintPagePage.tsx
|
|
8
8
|
var g = a`
|
|
9
|
-
query GetSprints($workspaceId: ID!, $filter: SprintFilter, $pagination:
|
|
9
|
+
query GetSprints($workspaceId: ID!, $filter: SprintFilter, $pagination: PlanmagnetPaginationInput) {
|
|
10
10
|
planmagnetSprints(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
|
|
11
11
|
items {
|
|
12
12
|
id
|
|
@@ -29,7 +29,7 @@ var g = a`
|
|
|
29
29
|
query GetSprintWorkItems(
|
|
30
30
|
$workspaceId: ID!
|
|
31
31
|
$filter: WorkItemFilter
|
|
32
|
-
$pagination:
|
|
32
|
+
$pagination: PlanmagnetPaginationInput
|
|
33
33
|
) {
|
|
34
34
|
planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
|
|
35
35
|
items {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SprintsStartSprintPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { Zap, Calendar, Users, Play } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\nconst GET_SPRINTS = gql`\n query GetSprints($workspaceId: ID!, $filter: SprintFilter, $pagination: PaginationInput) {\n planmagnetSprints(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n goal\n status\n startDate\n endDate\n totalPoints\n completedPoints\n tasksTotal\n tasksCompleted\n velocity\n teamMemberIds\n }\n totalCount\n }\n }\n`;\n\nconst GET_SPRINT_WORK_ITEMS = gql`\n query GetSprintWorkItems(\n $workspaceId: ID!\n $filter: WorkItemFilter\n $pagination: PaginationInput\n ) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n status\n storyPoints\n sprintId\n }\n totalCount\n }\n }\n`;\n\nconst START_SPRINT = gql`\n mutation StartSprint($workspaceId: ID!, $sprintId: ID!) {\n planmagnetStartSprint(workspaceId: $workspaceId, id: $sprintId) {\n id\n status\n startDate\n }\n }\n`;\n\ninterface SprintNode {\n id: string;\n name: string;\n goal: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n totalPoints: number;\n completedPoints: number;\n tasksTotal: number;\n tasksCompleted: number;\n velocity: number;\n teamMemberIds: string[];\n}\n\ninterface SprintWorkItem {\n id: string;\n title: string;\n status: string;\n storyPoints: number | null;\n sprintId: string | null;\n}\n\nexport function SprintsStartSprintPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n const {\n data: sprintData,\n loading: sprintsLoading,\n error: sprintsError,\n } = useQuery<{\n sprints: { items: SprintNode[]; totalCount: number };\n }>(GET_SPRINTS, {\n variables: { workspaceId, pagination: { first: 50 } },\n skip: !workspaceId,\n });\n\n const sprints = sprintData?.sprints?.items ?? [];\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n const planningSprints = sprints.filter((s) => s.status === 'PLANNING');\n\n // Fetch work items for active sprints\n const activeSprintIds = activeSprints.map((s) => s.id);\n const { data: workItemsData } = useQuery<{\n workItems: { items: SprintWorkItem[]; totalCount: number };\n }>(GET_SPRINT_WORK_ITEMS, {\n variables: {\n workspaceId,\n filter: { sprintIds: activeSprintIds },\n pagination: { first: 200 },\n },\n skip: !workspaceId || activeSprintIds.length === 0,\n });\n\n const sprintWorkItems = workItemsData?.workItems?.items ?? [];\n\n const [startSprint, { loading: startingSprintLoading }] = useMutation(START_SPRINT, {\n refetchQueries: ['GetSprints'],\n });\n\n const handleStartSprint = async (sprintId: string) => {\n if (!workspaceId) return;\n await startSprint({ variables: { workspaceId, sprintId } });\n };\n\n if (sprintsLoading) {\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 (sprintsError) {\n return <div className=\"p-6 text-red-500\">Error: {sprintsError.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Sprint Management</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprints.length} sprints total · {activeSprints.length} active\n </p>\n </div>\n\n {activeSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Active Sprints</h2>\n {activeSprints.map((sprint) => {\n const tasksForSprint = sprintWorkItems.filter((t) => t.sprintId === sprint.id);\n const pctDone =\n sprint.totalPoints > 0\n ? Math.round((sprint.completedPoints / sprint.totalPoints) * 100)\n : 0;\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Zap className=\"h-4 w-4 text-primary\" />\n {sprint.name}\n </CardTitle>\n <Badge>Active</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {sprint.teamMemberIds.length} members\n </span>\n </div>\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {sprint.completedPoints}/{sprint.totalPoints}\n </p>\n <p className=\"text-xs text-muted-foreground\">Points</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {sprint.tasksCompleted}/{sprint.tasksTotal}\n </p>\n <p className=\"text-xs text-muted-foreground\">Tasks</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">{sprint.velocity}</p>\n <p className=\"text-xs text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Sprint Progress</span>\n <span className=\"font-medium\">{pctDone}%</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: `${pctDone}%` }}\n />\n </div>\n </div>\n {tasksForSprint.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Sprint Backlog\n </p>\n <div className=\"space-y-1\">\n {tasksForSprint.map((t) => (\n <div\n key={t.id}\n className=\"flex items-center justify-between border rounded p-2 text-sm\"\n >\n <span>{t.title}</span>\n <div className=\"flex gap-1\">\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {t.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {t.storyPoints ?? 0}pts\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Team</p>\n <div className=\"flex gap-2\">\n {sprint.teamMemberIds.map((memberId) => (\n <div\n key={memberId}\n className=\"h-7 w-7 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-medium text-primary\"\n title={memberId}\n >\n {memberId.slice(0, 2).toUpperCase()}\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n\n {planningSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Planning</h2>\n {planningSprints.map((sprint) => (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{sprint.name}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\">Planning</Badge>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartSprint(sprint.id)}\n disabled={startingSprintLoading}\n >\n <Play className=\"mr-1 h-3 w-3\" />\n Start Sprint\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span>{sprint.totalPoints} points planned</span>\n <span>{sprint.teamMemberIds.length} members</span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SprintsStartSprintPagePage.js","names":[],"sources":["../../../src/planmagnet/pages/SprintsStartSprintPagePage.tsx"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\nimport { gql } from '@apollo/client';\nimport { useQuery, useMutation } from '@apollo/client/react';\nimport { Card, CardContent, CardHeader, CardTitle, Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { Zap, Calendar, Users, Play } from 'lucide-react';\nimport { usePlanMagnet } from '../providers/PlanMagnetProvider';\n\nconst GET_SPRINTS = gql`\n query GetSprints($workspaceId: ID!, $filter: SprintFilter, $pagination: PlanmagnetPaginationInput) {\n planmagnetSprints(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n name\n goal\n status\n startDate\n endDate\n totalPoints\n completedPoints\n tasksTotal\n tasksCompleted\n velocity\n teamMemberIds\n }\n totalCount\n }\n }\n`;\n\nconst GET_SPRINT_WORK_ITEMS = gql`\n query GetSprintWorkItems(\n $workspaceId: ID!\n $filter: WorkItemFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetWorkItems(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n status\n storyPoints\n sprintId\n }\n totalCount\n }\n }\n`;\n\nconst START_SPRINT = gql`\n mutation StartSprint($workspaceId: ID!, $sprintId: ID!) {\n planmagnetStartSprint(workspaceId: $workspaceId, id: $sprintId) {\n id\n status\n startDate\n }\n }\n`;\n\ninterface SprintNode {\n id: string;\n name: string;\n goal: string | null;\n status: string;\n startDate: string | null;\n endDate: string | null;\n totalPoints: number;\n completedPoints: number;\n tasksTotal: number;\n tasksCompleted: number;\n velocity: number;\n teamMemberIds: string[];\n}\n\ninterface SprintWorkItem {\n id: string;\n title: string;\n status: string;\n storyPoints: number | null;\n sprintId: string | null;\n}\n\nexport function SprintsStartSprintPagePage() {\n const { workspaceId } = usePlanMagnet();\n\n const {\n data: sprintData,\n loading: sprintsLoading,\n error: sprintsError,\n } = useQuery<{\n sprints: { items: SprintNode[]; totalCount: number };\n }>(GET_SPRINTS, {\n variables: { workspaceId, pagination: { first: 50 } },\n skip: !workspaceId,\n });\n\n const sprints = sprintData?.sprints?.items ?? [];\n const activeSprints = sprints.filter((s) => s.status === 'ACTIVE');\n const planningSprints = sprints.filter((s) => s.status === 'PLANNING');\n\n // Fetch work items for active sprints\n const activeSprintIds = activeSprints.map((s) => s.id);\n const { data: workItemsData } = useQuery<{\n workItems: { items: SprintWorkItem[]; totalCount: number };\n }>(GET_SPRINT_WORK_ITEMS, {\n variables: {\n workspaceId,\n filter: { sprintIds: activeSprintIds },\n pagination: { first: 200 },\n },\n skip: !workspaceId || activeSprintIds.length === 0,\n });\n\n const sprintWorkItems = workItemsData?.workItems?.items ?? [];\n\n const [startSprint, { loading: startingSprintLoading }] = useMutation(START_SPRINT, {\n refetchQueries: ['GetSprints'],\n });\n\n const handleStartSprint = async (sprintId: string) => {\n if (!workspaceId) return;\n await startSprint({ variables: { workspaceId, sprintId } });\n };\n\n if (sprintsLoading) {\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 (sprintsError) {\n return <div className=\"p-6 text-red-500\">Error: {sprintsError.message}</div>;\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Sprint Management</h1>\n <p className=\"text-sm text-muted-foreground\">\n {sprints.length} sprints total · {activeSprints.length} active\n </p>\n </div>\n\n {activeSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Active Sprints</h2>\n {activeSprints.map((sprint) => {\n const tasksForSprint = sprintWorkItems.filter((t) => t.sprintId === sprint.id);\n const pctDone =\n sprint.totalPoints > 0\n ? Math.round((sprint.completedPoints / sprint.totalPoints) * 100)\n : 0;\n return (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Zap className=\"h-4 w-4 text-primary\" />\n {sprint.name}\n </CardTitle>\n <Badge>Active</Badge>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {sprint.teamMemberIds.length} members\n </span>\n </div>\n <div className=\"grid grid-cols-3 gap-4 text-center\">\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {sprint.completedPoints}/{sprint.totalPoints}\n </p>\n <p className=\"text-xs text-muted-foreground\">Points</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">\n {sprint.tasksCompleted}/{sprint.tasksTotal}\n </p>\n <p className=\"text-xs text-muted-foreground\">Tasks</p>\n </div>\n <div className=\"p-3 bg-muted rounded-md\">\n <p className=\"text-lg font-bold\">{sprint.velocity}</p>\n <p className=\"text-xs text-muted-foreground\">Velocity</p>\n </div>\n </div>\n <div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-muted-foreground\">Sprint Progress</span>\n <span className=\"font-medium\">{pctDone}%</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: `${pctDone}%` }}\n />\n </div>\n </div>\n {tasksForSprint.length > 0 && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Sprint Backlog\n </p>\n <div className=\"space-y-1\">\n {tasksForSprint.map((t) => (\n <div\n key={t.id}\n className=\"flex items-center justify-between border rounded p-2 text-sm\"\n >\n <span>{t.title}</span>\n <div className=\"flex gap-1\">\n <Badge variant=\"secondary\" className=\"text-xs capitalize\">\n {t.status.toLowerCase().replace('_', ' ')}\n </Badge>\n <span className=\"text-xs text-muted-foreground\">\n {t.storyPoints ?? 0}pts\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-1\">Team</p>\n <div className=\"flex gap-2\">\n {sprint.teamMemberIds.map((memberId) => (\n <div\n key={memberId}\n className=\"h-7 w-7 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-medium text-primary\"\n title={memberId}\n >\n {memberId.slice(0, 2).toUpperCase()}\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n )}\n\n {planningSprints.length > 0 && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-medium\">Planning</h2>\n {planningSprints.map((sprint) => (\n <Card key={sprint.id}>\n <CardHeader className=\"pb-2\">\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{sprint.name}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\">Planning</Badge>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartSprint(sprint.id)}\n disabled={startingSprintLoading}\n >\n <Play className=\"mr-1 h-3 w-3\" />\n Start Sprint\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground\">{sprint.goal ?? ''}</p>\n <div className=\"flex gap-4 text-xs text-muted-foreground\">\n <span>\n {sprint.startDate ?? '?'} - {sprint.endDate ?? '?'}\n </span>\n <span>{sprint.totalPoints} points planned</span>\n <span>{sprint.teamMemberIds.length} members</span>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TasksCreateTaskPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksCreateTaskPagePage.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,uBAAuB,4CAuKtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TasksEditTaskPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksEditTaskPagePage.tsx"],"names":[],"mappings":"AA8DA,wBAAgB,qBAAqB,4CAoLpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TasksTaskDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/TasksTaskDetailPagePage.tsx"],"names":[],"mappings":"AAuEA,wBAAgB,uBAAuB,4CA8JtC"}
|