oberflaeche v4: Uebersicht als Startseite, KI-Box und Homelab mit Monitoring, Homelab-Updates je Geraet mit Alle aktualisieren, Protokoll, Einstellungsseite, neues Tab-Symbol

- Startseite "Alles auf einen Blick": Gesamtlage, je Bereich Messwerte mit Verlauf, wer welche Updates hat
  (Kurzform, Klick fuehrt in den Bereich), Hinweise, als Naechstes und zuletzt eingespielt
- Menue: Uebersicht, KI-Box (Cockpit, Updates, Modelle, Monitoring), Homelab (Cockpit, Updates, Monitoring,
  Protokoll), Einstellungen; Bereichsfarben Indigo und Violett; alte Adressen /updates und /modelle leiten weiter
- Homelab-Updates je Geraet: App-Version laeuft -> neu (mit Grund, wenn sie wartet), Pakete, Rueckweg, Knoepfe;
  Alle aktualisieren mit Plan in der Rueckfrage und Fortschritt; Cockpit zeigt die Gesundheit der Geraete
- Einstellungen als Seite: KI-Box, Homelab (Arcane-Schluessel, Docker echt/Probelauf, Ausfuehrer), Meldungen,
  Software-Stand
- Diagramme: Verlauf mit Fadenkreuz, Legende und Tabellenansicht, Kennzahlen mit Linie; Farben geprueft
- Tab-Symbol: favicon.ico/.svg, apple-touch-icon, Manifest-Icons

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-24 22:18:56 +02:00
co-authored by Claude Opus 5.5
parent bf1153cb66
commit 1104200a30
37 changed files with 2244 additions and 493 deletions
+31 -11
View File
@@ -1,41 +1,61 @@
import { useRouterState } from "@tanstack/react-router"
import { Cpu, LayoutDashboard, type LucideIcon, RefreshCw } from "lucide-react"
import {
Activity, Cpu, Gauge, LayoutGrid, type LucideIcon, RefreshCw, ScrollText, Settings,
} from "lucide-react"
import { useBoxZiele, useHomelab, useInstanz, usePartner } from "@/lib/abfragen"
import { offeneUpdates } from "@/lib/homelab"
import { useStromLage } from "@/lib/strom"
// Zwei Bereiche, sauber getrennt: die KI-Box (Box-Wart) und das Homelab (Proxmox-PC). Jeder hat seine
// eigenen Seiten und seine eigene Verbindungsanzeige; keine Seite zeigt etwas aus dem anderen Bereich.
// Oben die Übersicht über alles, darunter zwei sauber getrennte Bereiche — die KI-Box (Box-Wart) und das
// Homelab (Proxmox-PC) —, jeder mit eigenen Seiten und eigener Verbindungsanzeige, unten die Einstellungen.
export type Bereich = "box" | "homelab"
export type Ort = Bereich | "uebersicht" | "system"
export const BEREICHE: { id: Bereich; name: string }[] = [
{ id: "box", name: "KI-Box" },
{ id: "homelab", name: "Homelab" },
]
export type SeitenPfad =
| "/" | "/box" | "/box/updates" | "/box/modelle" | "/box/monitoring"
| "/homelab" | "/homelab/updates" | "/homelab/monitoring" | "/homelab/protokoll" | "/einstellungen"
export interface Seite {
to: "/" | "/updates" | "/modelle" | "/homelab" | "/homelab/updates"
to: SeitenPfad
label: string
Icon: LucideIcon
bereich: Bereich
ort: Ort
/** Zeigt die Zahl offener Updates des Bereichs. */
zaehlt?: boolean
}
export const SEITEN: Seite[] = [
{ to: "/", label: "Cockpit", Icon: LayoutDashboard, bereich: "box" },
{ to: "/updates", label: "Updates", Icon: RefreshCw, bereich: "box", zaehlt: true },
{ to: "/modelle", label: "Modelle", Icon: Cpu, bereich: "box" },
{ to: "/homelab", label: "Cockpit", Icon: LayoutDashboard, bereich: "homelab" },
{ to: "/homelab/updates", label: "Updates", Icon: RefreshCw, bereich: "homelab", zaehlt: true },
{ to: "/", label: "Übersicht", Icon: LayoutGrid, ort: "uebersicht" },
{ to: "/box", label: "Cockpit", Icon: Gauge, ort: "box" },
{ to: "/box/updates", label: "Updates", Icon: RefreshCw, ort: "box", zaehlt: true },
{ to: "/box/modelle", label: "Modelle", Icon: Cpu, ort: "box" },
{ to: "/box/monitoring", label: "Monitoring", Icon: Activity, ort: "box" },
{ to: "/homelab", label: "Cockpit", Icon: Gauge, ort: "homelab" },
{ to: "/homelab/updates", label: "Updates", Icon: RefreshCw, ort: "homelab", zaehlt: true },
{ to: "/homelab/monitoring", label: "Monitoring", Icon: Activity, ort: "homelab" },
{ to: "/homelab/protokoll", label: "Protokoll", Icon: ScrollText, ort: "homelab" },
{ to: "/einstellungen", label: "Einstellungen", Icon: Settings, ort: "system" },
]
/** Was über dem Seitentitel steht. */
export const ORT_NAME: Record<Ort, string> = {
uebersicht: "Alles auf einen Blick",
box: "KI-Box",
homelab: "Homelab",
system: "Beide Instanzen",
}
export const bereichName = (b: Bereich) => BEREICHE.find((x) => x.id === b)?.name ?? b
/** Welche Seite gerade offen ist — für die Überschrift oben. */
export function useAktuelleSeite(): Seite {
const pfad = useRouterState({ select: (s) => s.location.pathname })
const pfad = useRouterState({ select: (s) => s.location.pathname }).replace(/\/+$/, "") || "/"
return SEITEN.find((s) => s.to === pfad) ?? SEITEN[0]
}