Refactor: TanStack-Query-Daten-Layer + useDialog (Phase 3b)

- @tanstack/react-query (v5) als zentraler Daten-Layer; QueryClientProvider
  in main.tsx (retry 1, kein refetchOnWindowFocus, staleTime 5s).
- lib/queries.ts: Domänen-Hooks (useHealth/useSystemStatus/useServices/
  useModels/useRouting/useJobs/useTokenStats/useAgentStatus/useUpdates/
  useDiscover/useConnect/useMemory) + zentrale Query-Keys (qk) + invalidate.
  Gleicher Key = eine Anfrage über alle Views (Dedup), einheitliches Polling.
- lib/useDialog.tsx: ein Hook für Alert/Confirm/Prompt statt 5x dupliziertem
  Dialog-State + showAlert/showConfirm.
- api.ts: TokenStats + ModelsResp typisiert.
- Migriert auf Hooks/useDialog: App, SystemView, AgentView, ConnectView,
  MemoryView (manuelles useEffect+setInterval entfernt; Mutationen
  invalidieren gezielt die Query-Keys).

Verifiziert: tsc grün, Build grün, alle migrierten Views ohne Konsolenfehler,
Live-Daten (CPU/RAM/Dienste) rendern korrekt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-26 14:46:26 +02:00
parent 74f64731ab
commit 0266dc9e92
14 changed files with 644 additions and 574 deletions
+55
View File
@@ -0,0 +1,55 @@
// Ein Hook für Alert/Confirm/Prompt-Dialoge — ersetzt die zuvor in jeder View
// duplizierte showAlert/showConfirm-Logik + den lokalen Dialog-State.
//
// Nutzung:
// const { showAlert, showConfirm, showPrompt, dialogElement } = useDialog()
// ...
// showConfirm("Titel", "Wirklich?", () => doIt())
// return (<>{dialogElement}...</>)
import { useCallback, useState } from "react"
import { CustomDialog } from "@/components/CustomDialog"
interface DialogState {
type: "alert" | "confirm" | "prompt"
title: string
message: string
defaultValue?: string
onConfirm: (val?: string) => void
onCancel?: () => void
}
export function useDialog() {
const [dialog, setDialog] = useState<DialogState | null>(null)
const close = useCallback(() => setDialog(null), [])
const showAlert = useCallback((title: string, message: string, onConfirm?: () => void) => {
setDialog({
type: "alert", title, message,
onConfirm: () => { setDialog(null); onConfirm?.() },
})
}, [])
const showConfirm = useCallback(
(title: string, message: string, onConfirm: () => void, onCancel?: () => void) => {
setDialog({
type: "confirm", title, message,
onConfirm: () => { setDialog(null); onConfirm() },
onCancel: () => { setDialog(null); onCancel?.() },
})
}, [])
const showPrompt = useCallback(
(title: string, message: string, defaultValue: string,
onConfirm: (val?: string) => void, onCancel?: () => void) => {
setDialog({
type: "prompt", title, message, defaultValue,
onConfirm: (val) => { setDialog(null); onConfirm(val) },
onCancel: () => { setDialog(null); onCancel?.() },
})
}, [])
const dialogElement = dialog ? <CustomDialog {...dialog} /> : null
return { showAlert, showConfirm, showPrompt, close, dialogElement }
}