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 (
{value}
{label}
) } 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}
) }