import { useEffect, useState } from 'react'
import api from '../api/client'
import StatusBadge from '../components/StatusBadge'
import AgentPanel from '../components/AgentPanel'
import ProxmoxPanel from '../components/ProxmoxPanel'
import WindowsPanel from '../components/WindowsPanel'
import { Server, HardDrive, Users, Activity, AlertTriangle, Monitor } from 'lucide-react'
export default function Dashboard() {
const [agents, setAgents] = useState([])
const [customers, setCustomers] = useState([])
const [agentDetails, setAgentDetails] = useState({})
const [loading, setLoading] = useState(true)
const [selectedId, setSelectedId] = useState(null)
const [selectedType, setSelectedType] = useState(null) // 'device' | 'proxmox' | 'windows'
const reload = () => {
Promise.all([api.getAgents(), api.getCustomers()])
.then(([a, c]) => {
setAgents(a || [])
setCustomers(c || [])
// Lade Details fuer Typ-Erkennung
;(a || []).forEach((agent) => {
if (!agentDetails[agent.id]) {
api.getAgent(agent.id).then((d) => {
setAgentDetails((prev) => ({ ...prev, [agent.id]: d }))
})
}
})
})
.finally(() => setLoading(false))
}
const isProxmox = (agentId) => {
const d = agentDetails[agentId]
return d?.system_data?.proxmox?.available === true
}
const getAgentType = (agent) => {
if (isProxmox(agent.id)) return 'proxmox'
if (agent.platform === 'windows') return 'windows'
return 'device'
}
useEffect(() => {
reload()
}, [])
if (loading) {
return
Laden...
}
const online = agents.filter((a) => a.status === 'online').length
const offline = agents.filter((a) => a.status === 'offline').length
const stale = agents.filter((a) => a.status === 'stale').length
const unassigned = agents.filter((a) => !a.customer_id).length
// Agents nach Kunde gruppieren
const customerMap = {}
customers.forEach((c) => {
customerMap[c.id] = { ...c, agents: [] }
})
agents.forEach((a) => {
if (a.customer_id && customerMap[a.customer_id]) {
customerMap[a.customer_id].agents.push(a)
}
})
return (
Dashboard
{/* Stats */}
!isProxmox(a.id)).length} color="text-blue-400" />
isProxmox(a.id)).length} color="text-purple-400" />
{/* Agent-Liste nach Kunde */}
{Object.values(customerMap)
.filter((c) => c.agents.length > 0)
.sort((a, b) => a.number.localeCompare(b.number))
.map((customer) => (
{customer.number} — {customer.name}
{customer.agents.length} {customer.agents.length === 1 ? 'Geraet' : 'Geraete'}
{customer.agents.map((agent) => (
{ setSelectedId(agent.id); setSelectedType(getAgentType(agent)) }} selected={selectedId === agent.id} />
))}
))}
{/* Nicht zugewiesene Agents */}
{unassigned > 0 && (
Nicht zugewiesen
{agents
.filter((a) => !a.customer_id)
.map((agent) => (
{ setSelectedId(agent.id); setSelectedType(getAgentType(agent)) }} selected={selectedId === agent.id} />
))}
)}
{/* Detail Panels */}
{selectedId && selectedType === 'proxmox' && (
{ setSelectedId(null); setSelectedType(null) }}
onReload={reload}
/>
)}
{selectedId && selectedType === 'windows' && (
{ setSelectedId(null); setSelectedType(null) }}
onReload={reload}
/>
)}
{selectedId && selectedType === 'device' && (
{ setSelectedId(null); setSelectedType(null) }}
onReload={reload}
/>
)}
)
}
function StatCard({ icon: Icon, label, value, color }) {
return (
)
}
function AgentRow({ agent, isPve, onClick, selected }) {
const lastHB = agent.last_heartbeat
? new Date(agent.last_heartbeat).toLocaleString('de-DE')
: '—'
return (
{agent.platform === 'linux' ? 'LNX' : agent.platform === 'windows' ? 'WIN' : 'OPN'}
{agent.name}
{agent.ip}
{agent.opnsense_version || '—'}
{lastHB}
)
}