'use client'; import Link from 'next/link'; import { useTranslations } from 'next-intl'; import { useEffect, useMemo, useState } from 'react'; import type { WidgetProps } from '@/components/dashboard/widget-registry'; import { HealthBar } from '@/components/proxmox/HealthBar'; import { summarizeHealth } from '@/components/proxmox/proxmox-status'; import { HEALTH_STYLE } from '@/components/proxmox/status-styles'; // T-I8V-02: aus dem Proxmox-Klienten NUR die Leseabfrage des Zwischenlagers. // Die manuelle Abfrage (POST .../poll) gehoert der Modulseite und darf hier // nie auftauchen — sonst loeste jede Kachel je Benutzer Live-Abfragen aus. import { listServers, type ProxmoxServer } from '@/lib/proxmox-api'; import { useAuthStore } from '@/lib/stores/auth-store'; import { healthSummary } from './proxmox-widget-model'; /** * ProxmoxWidget (quick-260924-i8v) — die erste Modul-Kachel. Zeigt den * Zustand der Proxmox-Server in der Statussprache der Modulseite: kompakter * Gesundheitsbalken und darunter die Zusammenfassung in Worten. * * Liest ausschliesslich das Zwischenlager (`GET /modules/proxmox/servers`), * das `@UseModule('proxmox')` serverseitig schuetzt. */ export function ProxmoxWidget({ isEditMode }: WidgetProps) { const t = useTranslations('widgets'); const tp = useTranslations('proxmox'); const user = useAuthStore((s) => s.user); const isAdmin = user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN'; const [servers, setServers] = useState(null); // Fehler als Flag, nicht als Text: `t` gehoert nicht in die Effekt- // Abhaengigkeiten (Befund 14 aus favorites-widget). const [loadFailed, setLoadFailed] = useState(false); const [now, setNow] = useState(() => Date.now()); useEffect(() => { let cancelled = false; listServers() .then((list) => { if (cancelled) return; setServers(list); setLoadFailed(false); setNow(Date.now()); }) .catch(() => { if (!cancelled) setLoadFailed(true); }); return () => { cancelled = true; }; }, []); const counts = useMemo(() => summarizeHealth(servers ?? [], now), [servers, now]); const summary = useMemo(() => healthSummary(counts), [counts]); if (servers === null && loadFailed) { return (

{tp('loadError')}

); } if (servers === null) { return (
{tp('loading')}
); } if (servers.length === 0) { return (

{t('proxmox.empty')}

{isAdmin && (isEditMode ? ( {tp('card.settingsLink')} ) : ( {tp('card.settingsLink')} ))}
); } const summaryText = summary.allOk ? t('proxmox.allOk') : summary.entries .map((e) => `${e.count} ${tp(`legend.${e.health}`, { count: e.count })}`) .join(', '); const summaryColor = summary.allOk ? HEALTH_STYLE.ok.text : summary.worst ? HEALTH_STYLE[summary.worst].text : 'text-muted-foreground'; return (

{summaryText}

); }