import { memo, useEffect, useState } from 'react' import { Activity, RotateCw } from 'lucide-react' import { useTranslation } from 'react-i18next' import { cn } from '@/lib/utils' import { Button } from '@/components/ui/button' import { ScrollArea } from '@/components/ui/scroll-area' import { getUptimeStatus } from '@/features/dashboard/api' import type { UptimeGroupResult, UptimeMonitor, } from '@/features/dashboard/types' import { PanelWrapper } from '../ui/panel-wrapper' const STATUS_COLOR_MAP: Record = { 1: 'bg-emerald-500', 0: 'bg-red-500', 2: 'bg-amber-500', 3: 'bg-blue-500', } const DEFAULT_STATUS_COLOR = 'bg-muted-foreground/40' const StatusDot = memo(function StatusDot(props: { status: number }) { const color = STATUS_COLOR_MAP[props.status] ?? DEFAULT_STATUS_COLOR return }) export function UptimePanel() { const { t } = useTranslation() const [groups, setGroups] = useState([]) const [loading, setLoading] = useState(true) const [refreshing, setRefreshing] = useState(false) useEffect(() => { const abortController = new AbortController() getUptimeStatus() .then((res) => { if (abortController.signal.aborted) return setGroups(res?.data || []) }) .catch(() => { if (abortController.signal.aborted) return setGroups([]) }) .finally(() => { if (!abortController.signal.aborted) { setLoading(false) } }) return () => { abortController.abort() } }, []) const handleRefresh = () => { const abortController = new AbortController() setRefreshing(true) getUptimeStatus() .then((res) => { if (abortController.signal.aborted) return setGroups(res?.data || []) }) .catch(() => { if (abortController.signal.aborted) return setGroups([]) }) .finally(() => { if (!abortController.signal.aborted) { setRefreshing(false) } }) } return ( {t('Uptime')} } description={t('Grouped monitor status from Uptime Kuma')} loading={loading} empty={!groups.length} emptyMessage={t('No uptime monitoring configured')} height='h-80' contentClassName='p-0' headerActions={ } >
{groups.map((group, groupIdx) => (

{group.categoryName}

{group.monitors?.length || 0}
{group.monitors?.map( (monitor: UptimeMonitor, monitorIdx: number) => (
{monitor.name} {monitor.group && ( ({monitor.group}) )}
{((monitor.uptime ?? 0) * 100).toFixed(2)}%
) )}
))}
) }