From 8b5f75a2893ad216c27afedbfee2cbd3938483f2 Mon Sep 17 00:00:00 2001 From: Hector Ros Date: Tue, 20 Jan 2026 02:02:24 +0100 Subject: [PATCH] Enhance frontend dashboard with stats, modals, and actions - Add StatsCards component with key metrics (projects, tasks, agents) - Add CreateProjectModal for creating new projects - Add CreateTaskModal for creating new tasks - Add action buttons in dashboard header - Improve Dashboard with stats and modal integration - All components with proper TypeScript types Co-Authored-By: Claude Sonnet 4.5 (1M context) --- src/components/CreateProjectModal.tsx | 108 ++++++++++++++++++++++ src/components/CreateTaskModal.tsx | 127 ++++++++++++++++++++++++++ src/components/StatsCards.tsx | 71 ++++++++++++++ src/pages/Dashboard.tsx | 42 ++++++++- 4 files changed, 345 insertions(+), 3 deletions(-) create mode 100644 src/components/CreateProjectModal.tsx create mode 100644 src/components/CreateTaskModal.tsx create mode 100644 src/components/StatsCards.tsx diff --git a/src/components/CreateProjectModal.tsx b/src/components/CreateProjectModal.tsx new file mode 100644 index 0000000..0d8a696 --- /dev/null +++ b/src/components/CreateProjectModal.tsx @@ -0,0 +1,108 @@ +import React, { useState } from 'react' +import apiClient from '../api/client' + +interface CreateProjectModalProps { + isOpen: boolean + onClose: () => void + onCreated: () => void +} + +export default function CreateProjectModal({ isOpen, onClose, onCreated }: CreateProjectModalProps) { + const [formData, setFormData] = useState({ + name: '', + description: '', + giteaOwner: 'admin', + giteaRepoName: '', + }) + const [loading, setLoading] = useState(false) + const [error, setError] = useState('') + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError('') + + try { + await apiClient.post('/projects', formData) + onCreated() + onClose() + setFormData({ name: '', description: '', giteaOwner: 'admin', giteaRepoName: '' }) + } catch (err: any) { + setError(err.response?.data?.message || 'Failed to create project') + } finally { + setLoading(false) + } + } + + if (!isOpen) return null + + return ( +
+
+

Create New Project

+ + {error && ( +
+ {error} +
+ )} + +
+
+ + setFormData({ ...formData, name: e.target.value })} + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" + required + /> +
+ +
+ +