185 lines
6.8 KiB
TypeScript
185 lines
6.8 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useAuth } from './contexts/AuthContext'
|
|
|
|
interface Agent {
|
|
id: string
|
|
name: string
|
|
status: 'active' | 'inactive' | 'error'
|
|
lastRun: string
|
|
dataCollected: number
|
|
}
|
|
|
|
export default function DashboardPage() {
|
|
const { user, logout } = useAuth()
|
|
const [agents, setAgents] = useState<Agent[]>([
|
|
{
|
|
id: '1',
|
|
name: 'News Collector',
|
|
status: 'active',
|
|
lastRun: '2024-01-03 10:30:00',
|
|
dataCollected: 1250
|
|
},
|
|
{
|
|
id: '2',
|
|
name: 'Social Media Monitor',
|
|
status: 'inactive',
|
|
lastRun: '2024-01-02 15:45:00',
|
|
dataCollected: 890
|
|
},
|
|
{
|
|
id: '3',
|
|
name: 'Market Data Scraper',
|
|
status: 'error',
|
|
lastRun: '2024-01-01 09:00:00',
|
|
dataCollected: 567
|
|
}
|
|
])
|
|
|
|
const toggleAgentStatus = (id: string) => {
|
|
setAgents(prev => prev.map(agent => {
|
|
if (agent.id === id) {
|
|
const newStatus = agent.status === 'active' ? 'inactive' : 'active'
|
|
return { ...agent, status: newStatus }
|
|
}
|
|
return agent
|
|
}))
|
|
}
|
|
|
|
const getStatusColor = (status: Agent['status']) => {
|
|
switch (status) {
|
|
case 'active': return 'text-green-500'
|
|
case 'inactive': return 'text-gray-500'
|
|
case 'error': return 'text-red-500'
|
|
}
|
|
}
|
|
|
|
const getStatusBg = (status: Agent['status']) => {
|
|
switch (status) {
|
|
case 'active': return 'bg-green-100 dark:bg-green-900'
|
|
case 'inactive': return 'bg-gray-100 dark:bg-gray-900'
|
|
case 'error': return 'bg-red-100 dark:bg-red-900'
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-zinc-50 font-sans dark:bg-black">
|
|
<header className="bg-white shadow-sm dark:bg-black">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between items-center py-4">
|
|
<h1 className="text-2xl font-bold text-black dark:text-zinc-50">
|
|
Agent Dashboard
|
|
</h1>
|
|
<div className="flex items-center space-x-4">
|
|
<span className="text-black dark:text-zinc-50">
|
|
Welcome, {user?.username}
|
|
</span>
|
|
<button
|
|
onClick={logout}
|
|
className="rounded-md bg-red-500 px-4 py-2 text-white transition-colors hover:bg-red-600"
|
|
>
|
|
Logout
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<div className="mb-8">
|
|
<h2 className="text-xl font-semibold text-black dark:text-zinc-50 mb-4">
|
|
Information Collection Agents
|
|
</h2>
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
{agents.map((agent) => (
|
|
<div
|
|
key={agent.id}
|
|
className="rounded-lg bg-white p-6 shadow-md dark:bg-black"
|
|
>
|
|
<div className="flex justify-between items-start mb-4">
|
|
<h3 className="text-lg font-medium text-black dark:text-zinc-50">
|
|
{agent.name}
|
|
</h3>
|
|
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getStatusBg(agent.status)} ${getStatusColor(agent.status)}`}>
|
|
{agent.status}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="space-y-2 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600 dark:text-gray-400">Last Run:</span>
|
|
<span className="text-black dark:text-zinc-50">{agent.lastRun}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600 dark:text-gray-400">Data Collected:</span>
|
|
<span className="text-black dark:text-zinc-50">{agent.dataCollected}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4 flex space-x-2">
|
|
<button
|
|
onClick={() => toggleAgentStatus(agent.id)}
|
|
className={`flex-1 rounded-md px-3 py-2 text-sm font-medium transition-colors ${
|
|
agent.status === 'active'
|
|
? 'bg-red-500 text-white hover:bg-red-600'
|
|
: 'bg-green-500 text-white hover:bg-green-600'
|
|
}`}
|
|
>
|
|
{agent.status === 'active' ? 'Stop' : 'Start'}
|
|
</button>
|
|
<button className="flex-1 rounded-md bg-blue-500 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600">
|
|
Configure
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
<div className="rounded-lg bg-white p-6 shadow-md dark:bg-black">
|
|
<h3 className="text-lg font-medium text-black dark:text-zinc-50 mb-4">
|
|
Quick Actions
|
|
</h3>
|
|
<div className="space-y-3">
|
|
<button className="w-full rounded-md bg-blue-500 px-4 py-2 text-white transition-colors hover:bg-blue-600">
|
|
Add New Agent
|
|
</button>
|
|
<button className="w-full rounded-md bg-green-500 px-4 py-2 text-white transition-colors hover:bg-green-600">
|
|
Run All Agents
|
|
</button>
|
|
<button className="w-full rounded-md bg-gray-500 px-4 py-2 text-white transition-colors hover:bg-gray-600">
|
|
Export Data
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="rounded-lg bg-white p-6 shadow-md dark:bg-black">
|
|
<h3 className="text-lg font-medium text-black dark:text-zinc-50 mb-4">
|
|
System Overview
|
|
</h3>
|
|
<div className="space-y-3 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600 dark:text-gray-400">Total Agents:</span>
|
|
<span className="text-black dark:text-zinc-50">{agents.length}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600 dark:text-gray-400">Active Agents:</span>
|
|
<span className="text-green-500">
|
|
{agents.filter(a => a.status === 'active').length}
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600 dark:text-gray-400">Total Data Points:</span>
|
|
<span className="text-black dark:text-zinc-50">
|
|
{agents.reduce((sum, a) => sum + a.dataCollected, 0)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
)
|
|
} |