import React, { useEffect, useState } from 'react'; import { useAuth } from '../context/AuthContext'; import api from '../api'; import { useNavigate } from 'react-router-dom'; import { CheckCircle, XCircle, Clock, AlertCircle, Plus, LogOut, Search, Filter, Menu } from 'lucide-react'; import clsx from 'clsx'; interface Job { id: number; branch_name: string; status: string; duration: string; result_path: string; created_at: string; scenarios: string[]; environment: string; test_mode: string; } const Dashboard: React.FC = () => { const { logout, user } = useAuth(); const [jobs, setJobs] = useState([]); const [selectedJob, setSelectedJob] = useState(null); const navigate = useNavigate(); useEffect(() => { fetchJobs(); const wsUrl = import.meta.env.VITE_API_URL ? import.meta.env.VITE_API_URL.replace('http', 'ws') + '/ws/jobs' : 'ws://localhost:8000/ws/jobs'; const socket = new WebSocket(wsUrl); socket.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'job_update') { updateJobStatus(data.job_id, data.status); } }; return () => socket.close(); }, []); const fetchJobs = async () => { try { const response = await api.get('/jobs'); setJobs(response.data); } catch (error) { console.error("Failed to fetch jobs", error); } }; const updateJobStatus = (jobId: number, status: string) => { setJobs(prev => prev.map(job => job.id === jobId ? { ...job, status } : job )); if (selectedJob?.id === jobId) { setSelectedJob(prev => prev ? { ...prev, status } : null); } }; const handleAbort = async (jobId: number) => { try { await api.post(`/jobs/${jobId}/abort`); fetchJobs(); } catch (error) { console.error("Failed to abort job", error); } }; const getStatusIcon = (status: string) => { switch (status) { case 'passed': return ; case 'failed': return ; case 'running': return ; case 'aborted': return ; default: return ; } }; return (
{/* Header */}
Welcome, {user?.username}
{/* Sub-header / Filters */}
FILTERS
{/* Main Content */}
{/* Left Panel: Job List */}
TEST REQUESTS
{jobs.map(job => ( setSelectedJob(job)} className={clsx( "cursor-pointer border-b border-gray-100 hover:bg-blue-50 transition-colors", selectedJob?.id === job.id && "bg-blue-50 border-l-4 border-l-accent" )} > ))}
ID STATUS BRANCH
#{job.id} {getStatusIcon(job.status)} {job.branch_name}
{/* Right Panel: Job Details */}
TEST INFO
{selectedJob ? (

Test Request #{selectedJob.id}

Submitted on {new Date(selectedJob.created_at).toLocaleString()}

{selectedJob.status === 'running' && ( )} {selectedJob.result_path && ( View Results )}
Status: {getStatusIcon(selectedJob.status)} {selectedJob.status}
Duration: {selectedJob.duration || '-'}
Branch: {selectedJob.branch_name}
Environment: {selectedJob.environment}
Test Mode: {selectedJob.test_mode}

Selected Scenarios

{selectedJob.scenarios.map(s => ( {s} ))}
) : (
Select a job from the list to view details
)}
); }; export default Dashboard;