1→import { useEffect, useState } from 'react' 2→import { useProjectStore } from '../stores/projectStore' 3→import { useAgentStore } from '../stores/agentStore' 4→import { useToastStore } from '../components/Toast' 5→import { 6→ FolderOpen, 7→ CheckCircle, 8→ Clock, 9→ AlertTriangle, 10→ Activity, 11→ Trash2, 12→ Pencil, 13→ Check, 14→ Palette, 15→ X, 16→} from 'lucide-react' 17→import * as AlertDialog from '@radix-ui/react-alert-dialog' 18→import * as Dialog from '@radix-ui/react-dialog' 19→ 20→interface TaskStats { 21→ completed: number 22→ inProgress: number 23→ blocked: number 24→ backlog: number 25→ qa: number 26→} 27→ 28→export default function Dashboard() { 29→ const { currentProject, fetchProjects, deleteProject, updateProject } = useProjectStore() 30→ const { activeSessions, fetchActiveSessions } = useAgentStore() 31→ const { addToast } = useToastStore() 32→ const [showDeleteDialog, setShowDeleteDialog] = useState(false) 33→ const [isDeleting, setIsDeleting] = useState(false) 34→ const [showEditDialog, setShowEditDialog] = useState(false) 35→ const [editName, setEditName] = useState('') 36→ const [editDescription, setEditDescription] = useState('') 37→ const [editDesignMode, setEditDesignMode] = useState<'mvp' | 'finished'>('mvp') 38→ const [isSaving, setIsSaving] = useState(false) 39→ const [saveSuccess, setSaveSuccess] = useState(false) 40→ const [taskStats, setTaskStats] = useState({ 41→ completed: 0, 42→ inProgress: 0, 43→ blocked: 0, 44→ backlog: 0, 45→ qa: 0, 46→ }) 47→ 48→ useEffect(() => { 49→ fetchProjects() 50→ fetchActiveSessions() 51→ }, [fetchProjects, fetchActiveSessions]) 52→ 53→ // Fetch task statistics when current project changes 54→ useEffect(() => { 55→ const fetchTaskStats = async () => { 56→ if (!currentProject) return 57→ 58→ try { 59→ const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}/tasks`) 60→ if (!response.ok) return 61→ 62→ const tasks = await response.json() 63→ const stats: TaskStats = { 64→ completed: 0, 65→ inProgress: 0, 66→ blocked: 0, 67→ backlog: 0, 68→ qa: 0, 69→ } 70→ 71→ tasks.forEach((task: { status: string }) => { 72→ switch (task.status) { 73→ case 'done': 74→ stats.completed++ 75→ break 76→ case 'in_progress': 77→ stats.inProgress++ 78→ break 79→ case 'blocked': 80→ stats.blocked++ 81→ break 82→ case 'backlog': 83→ stats.backlog++ 84→ break 85→ case 'qa': 86→ stats.qa++ 87→ break 88→ } 89→ }) 90→ 91→ setTaskStats(stats) 92→ } catch (error) { 93→ console.error('Failed to fetch task stats:', error) 94→ } 95→ } 96→ 97→ fetchTaskStats() 98→ }, [currentProject]) 99→ 100→ const handleDeleteProject = async () => { 101→ if (!currentProject) return 102→ setIsDeleting(true) 103→ try { 104→ await deleteProject(currentProject.id) 105→ setShowDeleteDialog(false) 106→ } catch (error) { 107→ console.error('Failed to delete project:', error) 108→ addToast('error', 'Delete Failed', `Failed to delete project "${currentProject.name}". Please try again.`) 109→ } finally { 110→ setIsDeleting(false) 111→ } 112→ } 113→ 114→ const handleOpenEditDialog = () => { 115→ if (currentProject) { 116→ setEditName(currentProject.name) 117→ setEditDescription(currentProject.description || '') 118→ setEditDesignMode((currentProject.design_mode as 'mvp' | 'finished') || 'mvp') 119→ setSaveSuccess(false) 120→ setShowEditDialog(true) 121→ } 122→ } 123→ 124→ const handleSaveProject = async () => { 125→ if (!currentProject) return 126→ setIsSaving(true) 127→ setSaveSuccess(false) 128→ try { 129→ const response = await fetch(`http://localhost:8000/api/projects/${currentProject.id}`, { 130→ method: 'PUT', 131→ headers: { 'Content-Type': 'application/json' }, 132→ body: JSON.stringify({ name: editName, description: editDescription, design_mode: editDesignMode }), 133→ }) 134→ if (!response.ok) { 135→ const errorData = await response.json().catch(() => ({})) 136→ throw new Error(errorData.detail || 'Failed to update project') 137→ } 138→ const updated = await response.json() 139→ updateProject(currentProject.id, updated) 140→ setSaveSuccess(true) 141→ setTimeout(() => { 142→ setShowEditDialog(false) 143→ setSaveSuccess(false) 144→ }, 1000) 145→ } catch (error) { 146→ console.error('Failed to save project:', error) 147→ const message = error instanceof Error ? error.message : 'Failed to save project' 148→ addToast('error', 'Save Failed', message) 149→ } finally { 150→ setIsSaving(false) 151→ } 152→ } 153→ 154→ if (!currentProject) { 155→ return ( 156→
157→ 158→

159→ No Project Selected 160→

161→

162→ Select a project from the sidebar or create a new one to get started. 163→

164→
165→ ) 166→ } 167→ 168→ const stats = [ 169→ { 170→ label: 'Tasks Completed', 171→ value: taskStats.completed, 172→ icon: CheckCircle, 173→ color: 'text-green-400', 174→ }, 175→ { 176→ label: 'Tasks In Progress', 177→ value: taskStats.inProgress, 178→ icon: Clock, 179→ color: 'text-accent', 180→ }, 181→ { 182→ label: 'Blocked Tasks', 183→ value: taskStats.blocked, 184→ icon: AlertTriangle, 185→ color: 'text-warning', 186→ }, 187→ { 188→ label: 'Active Agents', 189→ value: activeSessions.filter((s) => s.status === 'running').length, 190→ icon: Activity, 191→ color: 'text-primary-400', 192→ }, 193→ ] 194→ 195→ return ( 196→
197→ {/* Project Header */} 198→
199→
200→
201→

{currentProject.name}

202→ {/* Design Mode Badge */} 203→ 210→ 211→ {currentProject.design_mode === 'finished' ? 'Finished Mode' : 'MVP Mode'} 212→ 213→
214→ {currentProject.description && ( 215→

{currentProject.description}

216→ )} 217→
218→
219→ {/* Edit Button and Dialog */} 220→ 221→ 222→ 230→ 231→ 232→ 233→ 234→
235→ 236→ Edit Project Settings 237→ 238→ 239→ 242→ 243→
244→ 245→ Update your project name, description, and design mode. 246→ 247→
248→
249→ 250→ setEditName(e.target.value)} 254→ className="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent" 255→ placeholder="Enter project name" 256→ /> 257→
258→
259→ 260→