Files
mission-control-v2/frontend/src/lib/navigation.ts
T

97 lines
3.9 KiB
TypeScript

import { useRouterState } from "@tanstack/react-router"
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"
// 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: SeitenPfad
label: string
Icon: LucideIcon
ort: Ort
/** Zeigt die Zahl offener Updates des Bereichs. */
zaehlt?: boolean
}
export const SEITEN: Seite[] = [
{ 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: "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 }).replace(/\/+$/, "") || "/"
return SEITEN.find((s) => s.to === pfad) ?? SEITEN[0]
}
export type Verbindung = "online" | "verbinde" | "getrennt" | "fehlt"
export interface BereichStand {
verbindung: Verbindung
/** Updates, die per Knopf bereitstehen. */
updates: number
}
/**
* Verbindung und offene Updates je Bereich. Die Instanz, die die Seite ausliefert, meldet sich über den
* Live-Strom; die andere über die Partner-Prüfung (/api/partner).
*/
export function useBereichStand(): Record<Bereich, BereichStand> {
const instanz = useInstanz()
const partner = usePartner()
const strom = useStromLage()
const hier: Bereich = instanz.data?.rolle === "homelab" ? "homelab" : "box"
const eigen: Verbindung = strom === "live" ? "online" : strom
const p = partner.data
const fremd: Verbindung = !p ? "verbinde" : !p.eingerichtet ? "fehlt" : p.erreichbar ? "online" : "getrennt"
const verbindung: Record<Bereich, Verbindung> = hier === "box"
? { box: eigen, homelab: fremd }
: { box: fremd, homelab: eigen }
const box = useBoxZiele()
const homelab = useHomelab(verbindung.homelab === "online")
const boxUpdates = (box.data?.ziele ?? []).reduce(
(n, z) => n + z.bausteine.filter((b) => b.zustand === "neu" && b.aktion).length, 0,
)
const homelabUpdates = offeneUpdates(homelab.data?.ziele ?? []).filter((u) => u.baustein.aktion).length
return {
box: { verbindung: verbindung.box, updates: boxUpdates },
homelab: { verbindung: verbindung.homelab, updates: homelabUpdates },
}
}