diff --git a/src/components/Roadmap.tsx b/src/components/Roadmap.tsx index e7812dc..ebfb739 100644 --- a/src/components/Roadmap.tsx +++ b/src/components/Roadmap.tsx @@ -1,8 +1,15 @@ +import { useKV } from '@github/spark/hooks' +import { useState } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Separator } from '@/components/ui/separator' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { Textarea } from '@/components/ui/textarea' +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Target, ChartBar, @@ -10,48 +17,18 @@ import { TrendUp, Gauge, ListChecks, - ArrowsOut, CheckCircle, WarningCircle, XCircle, - Circle + Circle, + Plus, + FolderOpen, + Trash, + PencilSimple } from '@phosphor-icons/react' -import { ScrollArea } from '@/components/ui/scroll-area' import { Progress } from '@/components/ui/progress' - -interface Objective { - id: string - category: 'breakthrough' | 'annual' | 'improvement' - description: string - owner: string - targetDate: string - status: 'on-track' | 'at-risk' | 'completed' | 'not-started' - metrics: Metric[] -} - -interface Metric { - id: string - name: string - baseline: number - current: number - target: number - unit: string - frequency: 'monthly' | 'quarterly' | 'annual' - lastUpdated: string - trend: 'improving' | 'stable' | 'declining' -} - -interface BowlingChartData { - objective: string - months: MonthStatus[] -} - -interface MonthStatus { - month: string - status: 'green' | 'yellow' | 'red' | 'not-started' - actual: number - target: number -} +import { toast } from 'sonner' +import type { RoadmapProject, RoadmapObjective, RoadmapMetric, BowlingChartData, StatusType, PriorityType } from '@/types' interface XMatrixItem { id: string @@ -60,93 +37,264 @@ interface XMatrixItem { relationships: string[] } -const mockObjectives: Objective[] = [ - { - id: 'obj-1', - category: 'breakthrough', - description: 'Achieve 25% revenue growth through new market expansion', - owner: 'Chief Growth Officer', - targetDate: '2025-12-31', - status: 'on-track', - metrics: [ - { - id: 'm1', - name: 'Revenue Growth', - baseline: 100, - current: 115, - target: 125, - unit: '%', - frequency: 'quarterly', - lastUpdated: '2025-01-15', - trend: 'improving' - }, - { - id: 'm2', - name: 'New Market Share', - baseline: 0, - current: 12, - target: 20, - unit: '%', - frequency: 'monthly', - lastUpdated: '2025-01-15', - trend: 'improving' - } - ] - }, - { - id: 'obj-2', - category: 'annual', - description: 'Reduce operational costs by 15% while maintaining quality', - owner: 'Chief Operating Officer', - targetDate: '2025-12-31', - status: 'at-risk', - metrics: [ - { - id: 'm3', - name: 'Cost Reduction', - baseline: 100, - current: 92, - target: 85, - unit: '%', - frequency: 'monthly', - lastUpdated: '2025-01-15', - trend: 'stable' - }, - { - id: 'm4', - name: 'Quality Score', - baseline: 85, - current: 87, - target: 90, - unit: 'pts', - frequency: 'monthly', - lastUpdated: '2025-01-15', - trend: 'improving' - } - ] - }, - { - id: 'obj-3', - category: 'improvement', - description: 'Improve customer satisfaction score to 95%', - owner: 'Chief Customer Officer', - targetDate: '2025-06-30', - status: 'on-track', - metrics: [ - { - id: 'm5', - name: 'NPS Score', - baseline: 72, - current: 84, - target: 95, - unit: 'pts', - frequency: 'monthly', - lastUpdated: '2025-01-15', - trend: 'improving' - } - ] +function ProjectsView({ projects, setProjects }: { projects: RoadmapProject[], setProjects: (updater: (prev: RoadmapProject[]) => RoadmapProject[]) => void }) { + const [isAddingProject, setIsAddingProject] = useState(false) + const [editingProject, setEditingProject] = useState(null) + const [newProject, setNewProject] = useState>({ + name: '', + description: '', + owner: '', + status: 'not-started', + priority: 'medium', + startDate: '', + endDate: '', + progress: 0, + objectives: [], + metrics: [] + }) + + const handleAddProject = () => { + if (!newProject.name || !newProject.owner || !newProject.startDate || !newProject.endDate) { + toast.error('Please fill in all required fields') + return + } + + const project: RoadmapProject = { + id: `proj-${Date.now()}`, + name: newProject.name, + description: newProject.description || '', + owner: newProject.owner, + status: newProject.status as StatusType, + priority: newProject.priority as PriorityType, + startDate: newProject.startDate, + endDate: newProject.endDate, + progress: 0, + objectives: [], + metrics: [] + } + + setProjects((prev) => [...prev, project]) + setIsAddingProject(false) + setNewProject({ + name: '', + description: '', + owner: '', + status: 'not-started', + priority: 'medium', + startDate: '', + endDate: '', + progress: 0, + objectives: [], + metrics: [] + }) + toast.success('Project created successfully') } -] + + const handleDeleteProject = (projectId: string) => { + setProjects((prev) => prev.filter(p => p.id !== projectId)) + toast.success('Project deleted') + } + + const statusColors = { + 'not-started': 'bg-muted text-muted-foreground', + 'on-track': 'bg-success/10 text-success border-success/30', + 'at-risk': 'bg-warning/10 text-warning border-warning/30', + 'blocked': 'bg-destructive/10 text-destructive border-destructive/30', + 'completed': 'bg-primary/10 text-primary border-primary/30' + } + + const priorityColors = { + 'critical': 'bg-destructive/10 text-destructive border-destructive/30', + 'high': 'bg-warning/10 text-warning border-warning/30', + 'medium': 'bg-primary/10 text-primary border-primary/30', + 'low': 'bg-muted text-muted-foreground border-muted' + } + + return ( +
+
+
+

Strategic Projects

+

Manage projects with objectives and metrics

+
+ + + + + + + Create New Project + Add a strategic project to track on the roadmap + +
+
+ + setNewProject({ ...newProject, name: e.target.value })} + placeholder="Enter project name" + /> +
+
+ +