import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Activity, Cable, CirclePower, Cpu, Lightbulb, ShieldAlert, Sparkles, Wifi } from "lucide-react"; import { useState } from "react"; import { Link } from "react-router-dom"; import { api, mutationId } from "../api/client"; import type { Device, Page, Scene, SystemStatus } from "../api/types"; import { ConfirmDialog } from "../components/ConfirmDialog"; import { useToast } from "../components/Toast"; import { Badge, Button, Card, CardHeader, ErrorPanel, LoadingGrid, PageHeader, Stat, StatusBadge } from "../components/ui"; import { useI18n } from "../lib/i18n"; import { formatDate, hexToColor } from "../lib/utils"; export function OverviewPage() { const { text } = useI18n(); const queryClient = useQueryClient(); const { notify } = useToast(); const [color, setColor] = useState("#5660ff"); const [confirmEmergency, setConfirmEmergency] = useState(false); const system = useQuery({ queryKey: ["system"], queryFn: () => api("/api/v1/system") }); const devices = useQuery({ queryKey: ["devices", "online"], queryFn: () => api>("/api/v1/devices?online=true&limit=500") }); const scenes = useQuery({ queryKey: ["scenes"], queryFn: () => api>("/api/v1/scenes?limit=6") }); const quickColor = useMutation({ mutationFn: async () => { const targets = devices.data?.items.filter((device) => device.capabilities.rgb && !device.read_only && !device.blocked) ?? []; return Promise.allSettled(targets.map((device) => api(`/api/v1/devices/${device.id}/state`, { method: "POST", headers: { "Idempotency-Key": mutationId() }, body: JSON.stringify({ state: { power: true, colors: [hexToColor(color)] } }), }))); }, onSuccess: (results) => { const failed = results.filter((result) => result.status === "rejected").length; notify(failed ? `${results.length - failed} apparaten bijgewerkt; ${failed} mislukt.` : "Kleur toegepast op alle geschikte apparaten.", failed ? "danger" : "success"); void queryClient.invalidateQueries({ queryKey: ["system"] }); }, }); const allOff = useMutation({ mutationFn: (emergency: boolean) => api(`/api/v1/commands/${emergency ? "emergency-stop" : "all-off"}`, { method: "POST" }), onSuccess: (_, emergency) => { notify(emergency ? "Noodstop geactiveerd." : "Alles-uitopdracht voltooid."); void queryClient.invalidateQueries(); }, }); const applyScene = useMutation({ mutationFn: (id: string) => api(`/api/v1/scenes/${id}/apply`, { method: "POST", body: JSON.stringify({ rollback_on_failure: true }) }), onSuccess: () => { notify("Scène toegepast."); void queryClient.invalidateQueries(); }, onError: (error) => notify(error instanceof Error ? error.message : "Scène mislukt.", "danger"), }); if (system.isLoading) return <>; if (system.error || !system.data) return void system.refetch()} />; const status = system.data; const openrgb = status.health.components["openrgb-local"] ?? status.health.components["openrgb-mock"]; return ( <> } /> {status.emergency_stop ?
Globale noodstop actief

Nieuwe hardwareopdrachten worden geblokkeerd totdat je de noodstop in Diagnostiek vrijgeeft.

: null}
} detail={`Gecontroleerd ${formatDate(status.health.checked_at)}`} icon={Activity} /> : "—"} detail={`1.0rc3 · SDK ${status.sdk_protocol}`} icon={Lightbulb} /> key.startsWith("openrgb")).length} detail="Actieve beheerkanalen" icon={Cable} />
setColor(event.target.value)} />
{color.toUpperCase()}{devices.data?.items.length ?? 0} online doelen
{["#5660ff", "#00c2a8", "#ff7a59", "#f5c451", "#f7f7ff"].map((item) =>
{status.active_scene ?
{status.active_scene.name}{formatDate(status.active_scene.last_applied_at)}
Actief
:

Nog geen scène toegepast.

}

Laatst gebruikte scènes

Start een sfeer zonder de pagina te verlaten.

Alle scènes
{scenes.data?.items.map((scene, index) =>

{scene.name}

{scene.item_count ?? 0} onderdelen · v{scene.version}

)} {!scenes.isLoading && !scenes.data?.items.length ?

Leg je huidige toestand vast als eerste scène.

: null}
Alles bekijken} />
{status.recent_commands.slice(0, 5).map((command) =>
{command.action === "set_state" ? "Apparaattoestand gewijzigd" : command.action}{formatDate(command.created_at)}
{command.status}
)}{!status.recent_commands.length ?

Nog geen opdrachten uitgevoerd.

: null}
} /> {status.warnings.length ? status.warnings.map((warning) =>
{warning.title}

{warning.message}

) :
Alles rustig

Er zijn geen open waarschuwingen.

}
setConfirmEmergency(false)} onConfirm={() => { setConfirmEmergency(false); allOff.mutate(true); }} /> ); }