'use client'; import { useState, useEffect, useMemo } from 'react'; import { ServiceStatus } from '@/src/types/service'; import { AppConfig, Service } from '@/src/lib/config'; import { ServiceCard } from './ServiceCard'; import { DashboardFilters } from './dashboard-filters'; interface ServiceCheckResult { id: string; status: 'online' | 'warning' | 'offline'; responseTimeMs: number; httpStatus: number | null; checkedAt: string; } interface DashboardClientProps { initialServices: Service[]; config: AppConfig; } export function DashboardClient({ initialServices, config }: DashboardClientProps) { const [results, setResults] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [error, setError] = useState(null); const [lastUpdated, setLastUpdated] = useState(null); // Filter states const [searchQuery, setSearchQuery] = useState(''); const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedStatus, setSelectedStatus] = useState('all'); const fetchStatus = async (isManualRefresh = false) => { try { if (isManualRefresh) { setRefreshing(true); } else { setError(null); } const response = await fetch('/api/status'); if (!response.ok) { throw new Error('Failed to fetch status'); } const data: ServiceCheckResult[] = await response.json(); setResults(data); setLastUpdated(new Date().toISOString()); } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error'); } finally { setLoading(false); setRefreshing(false); } }; useEffect(() => { fetchStatus(); const interval = setInterval(() => fetchStatus(), config.refreshInterval); return () => clearInterval(interval); }, [config.refreshInterval]); // Get unique categories from config const categories = useMemo(() => { return config.categories; }, [config.categories]); // Filter services based on search, category, and status const filteredServices = useMemo(() => { return initialServices.filter((service) => { const result = results.find(r => r.id === service.id); // Search filter (case-insensitive) const matchesSearch = searchQuery === '' || service.name.toLowerCase().includes(searchQuery.toLowerCase()) || service.description.toLowerCase().includes(searchQuery.toLowerCase()); // Category filter const matchesCategory = selectedCategory === 'all' || service.category === selectedCategory; // Status filter const matchesStatus = selectedStatus === 'all' || (result && result.status === selectedStatus); return matchesSearch && matchesCategory && matchesStatus; }); }, [initialServices, results, searchQuery, selectedCategory, selectedStatus]); const getResultForService = (serviceId: string): ServiceCheckResult | undefined => { return results.find(result => result.id === serviceId); }; const handleManualRefresh = () => { fetchStatus(true); }; return (
{/* Header */}

{config.title}

{loading ? ( 'Lade Status...' ) : refreshing ? ( 'Aktualisiere...' ) : ( `Automatische Aktualisierung: ${Math.round(config.refreshInterval / 1000)}s` )}

{config.subtitle}

{/* Main Content */}
{error && (
Fehler beim Laden der Status-Daten: {error}
)} {/* Filters */} {/* Services Grid */}
{filteredServices.map((service) => ( ))}
{/* No results message */} {filteredServices.length === 0 && !loading && (

Keine Dienste gefunden

Versuche andere Suchbegriffe oder Filtereinstellungen.

)}
); }