import { useState, useMemo } from "react"; import { Radio, ChevronDown, ChevronUp, Zap, ZapOff } from "lucide-react"; import type { MqttData, MqttEntity } from "../api"; interface Props { data: MqttData; } export default function MqttCard({ data }: Props) { const [expanded, setExpanded] = useState(false); const [filter, setFilter] = useState(null); // Group entities by category const grouped = useMemo(() => { const map: Record = {}; for (const e of data.entities) { const cat = e.category || "other"; if (!map[cat]) map[cat] = []; map[cat].push(e); } return map; }, [data.entities]); const categories = Object.keys(grouped).sort(); const filtered = filter ? grouped[filter] || [] : data.entities; const shown = expanded ? filtered : filtered.slice(0, 8); return (
{/* Header */}

MQTT

{data.entities.length}
{data.connected ? ( ) : ( )} {data.connected ? "Verbunden" : "Getrennt"}
{/* Category filter tabs */} {categories.length > 1 && (
{categories.map((cat) => ( ))}
)} {/* Entity list */} {data.entities.length === 0 ? (

{data.connected ? "Warte auf Nachrichten..." : "Nicht konfiguriert"}

) : (
{shown.map((entity) => ( ))}
)} {/* Expand/collapse */} {filtered.length > 8 && ( )}
); } function EntityRow({ entity }: { entity: MqttEntity }) { const age = Math.round(Date.now() / 1000 - entity.timestamp); const ageStr = age < 60 ? `${age}s` : age < 3600 ? `${Math.floor(age / 60)}m` : `${Math.floor(age / 3600)}h`; const displayValue = formatValue(entity.value); const isNumeric = typeof entity.value === "number"; return (

{entity.name}

{entity.topic}

{displayValue} {(entity as any).unit && ( {(entity as any).unit} )} {ageStr}
); } function formatValue(value: any): string { if (value === null || value === undefined) return "\u2014"; if (typeof value === "boolean") return value ? "ON" : "OFF"; if (typeof value === "number") { return Number.isInteger(value) ? value.toString() : value.toFixed(1); } if (typeof value === "object") { return JSON.stringify(value).slice(0, 40); } const str = String(value); if (str === "on" || str === "ON") return "ON"; if (str === "off" || str === "OFF") return "OFF"; if (str === "online") return "Online"; if (str === "offline") return "Offline"; return str.length > 30 ? str.slice(0, 30) + "\u2026" : str; }