feat: Sprint 4 — scenario planner, report builder, comments, dashboard widgets

What-If Scenario Planner (G5):
- New /projects/[id]/scenario page with side-by-side baseline vs scenario
- simulate mutation: pure cost/hours/headcount/utilization computation
- apply mutation: creates real PROPOSED assignments from scenario
- Impact cards: cost delta, hours delta, headcount, skill coverage %
- Per-resource utilization impact table with over-allocation warnings
- "What-If" button added to project detail page

Custom Report Builder (G7):
- New /reports/builder page with full config panel
- Entity selector (resource/project/assignment), column picker, filter builder
- Dynamic Prisma query with eq/neq/gt/lt/contains/in operators
- Sortable results table with pagination (50/page)
- CSV export via exportReport mutation
- Sidebar nav link under Analytics

Collaboration Layer (G8):
- Comment model in Prisma (entityType/entityId, replies, @mentions, resolved)
- comment router: list, count, create, resolve, delete
- @mention parsing with notification creation + SSE delivery
- CommentInput with @mention autocomplete (arrow nav, Enter/Tab confirm)
- CommentThread with avatar, timestamp, reply, resolve, delete
- Integrated as "Comments" tab in estimate workspace with count badge

Dashboard Widgets:
- BudgetForecastWidget: progress bars per project, burn rate, exhaustion date
- SkillGapWidget: supply vs demand per skill, shortage/surplus indicators
- ProjectHealthWidget: 3-dimension health circles + composite score
- 3 new application use-cases + dashboard router queries
- All registered in widget-registry with lazy imports

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-03-19 21:47:47 +01:00
parent 6f34659587
commit e1368c7ef7
27 changed files with 3889 additions and 1 deletions
@@ -77,6 +77,9 @@ export const dashboardWidgetConfigSchemas = {
"top-value-resources": topValueWidgetConfigSchema,
"chargeability-overview": chargeabilityWidgetConfigSchema,
"my-projects": myProjectsWidgetConfigSchema,
"budget-forecast": z.object({}),
"skill-gap": z.object({}),
"project-health": z.object({}),
} as const;
type DashboardWidgetConfigSchemaMap = typeof dashboardWidgetConfigSchemas;
+39
View File
@@ -42,6 +42,12 @@ export interface MyProjectsWidgetConfig {
showResponsible?: boolean;
}
export interface BudgetForecastWidgetConfig {}
export interface SkillGapWidgetConfig {}
export interface ProjectHealthWidgetConfig {}
export interface DashboardWidgetConfigMap {
"stat-cards": StatCardsWidgetConfig;
"resource-table": ResourceTableWidgetConfig;
@@ -51,6 +57,9 @@ export interface DashboardWidgetConfigMap {
"top-value-resources": TopValueResourcesWidgetConfig;
"chargeability-overview": ChargeabilityOverviewWidgetConfig;
"my-projects": MyProjectsWidgetConfig;
"budget-forecast": BudgetForecastWidgetConfig;
"skill-gap": SkillGapWidgetConfig;
"project-health": ProjectHealthWidgetConfig;
}
export const DASHBOARD_WIDGET_TYPES = [
@@ -62,6 +71,9 @@ export const DASHBOARD_WIDGET_TYPES = [
"top-value-resources",
"chargeability-overview",
"my-projects",
"budget-forecast",
"skill-gap",
"project-health",
] as const;
export type DashboardWidgetType = (typeof DASHBOARD_WIDGET_TYPES)[number];
@@ -182,4 +194,31 @@ export const DASHBOARD_WIDGET_CATALOG = [
showResponsible: true,
},
},
{
type: "budget-forecast",
label: "Budget Forecast",
description: "Budget burn rate and projected exhaustion per active project",
icon: "💰",
defaultSize: { w: 6, h: 5 },
minSize: { w: 4, h: 4 },
defaultConfig: {},
},
{
type: "skill-gap",
label: "Skill Gap Analysis",
description: "Top skill shortages: open demand vs available supply",
icon: "🎯",
defaultSize: { w: 6, h: 5 },
minSize: { w: 4, h: 4 },
defaultConfig: {},
},
{
type: "project-health",
label: "Project Health",
description: "Composite health score per project: budget, staffing, timeline",
icon: "🏥",
defaultSize: { w: 6, h: 5 },
minSize: { w: 4, h: 4 },
defaultConfig: {},
},
] as const satisfies readonly DashboardWidgetCatalogEntry[];