Backend (@backend-dev): - Add ReportService with PDF/CSV generation (reportlab, pandas) - Implement Report API endpoints (POST, GET, DELETE, download) - Add ReportRepository and schemas - Configure storage with auto-cleanup (30 days) - Rate limiting: 10 downloads/minute - Professional PDF templates with charts support Frontend (@frontend-dev): - Integrate Recharts for data visualization - Add CostBreakdown, TimeSeries, ComparisonBar charts - Implement scenario comparison page with multi-select - Add dark/light mode toggle with ThemeProvider - Create Reports page with generation form and list - Add new UI components: checkbox, dialog, tabs, label, skeleton - Implement useComparison and useReports hooks QA (@qa-engineer): - Setup Playwright E2E testing framework - Create 7 test spec files with 94 test cases - Add visual regression testing with baselines - Configure multi-browser testing (Chrome, Firefox, WebKit) - Add mobile responsive tests - Create test fixtures and helpers - Setup GitHub Actions CI workflow Documentation (@spec-architect): - Create detailed kanban-v0.4.0.md with 27 tasks - Update progress.md with v0.4.0 tracking - Create v0.4.0 planning prompt Features: ✅ PDF/CSV Report Generation ✅ Interactive Charts (Pie, Area, Bar) ✅ Scenario Comparison (2-4 scenarios) ✅ Dark/Light Mode Toggle ✅ E2E Test Suite (94 tests) Dependencies added: - Backend: reportlab, pandas, slowapi - Frontend: recharts, date-fns, @radix-ui/react-checkbox/dialog/tabs - Testing: @playwright/test 27 tasks completed, 100% v0.4.0 implementation
34 lines
993 B
TypeScript
34 lines
993 B
TypeScript
import { NavLink } from 'react-router-dom';
|
|
import { LayoutDashboard, List, BarChart3 } from 'lucide-react';
|
|
|
|
const navItems = [
|
|
{ to: '/', label: 'Dashboard', icon: LayoutDashboard },
|
|
{ to: '/scenarios', label: 'Scenarios', icon: List },
|
|
{ to: '/compare', label: 'Compare', icon: BarChart3 },
|
|
];
|
|
|
|
export function Sidebar() {
|
|
return (
|
|
<aside className="w-64 border-r bg-card min-h-[calc(100vh-4rem)] hidden md:block">
|
|
<nav className="p-4 space-y-2">
|
|
{navItems.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-3 px-4 py-2 rounded-lg transition-colors ${
|
|
isActive
|
|
? 'bg-primary text-primary-foreground'
|
|
: 'hover:bg-muted'
|
|
}`
|
|
}
|
|
>
|
|
<item.icon className="h-5 w-5" />
|
|
{item.label}
|
|
</NavLink>
|
|
))}
|
|
</nav>
|
|
</aside>
|
|
);
|
|
}
|