/** * View-Model-Vertrag. * * Wortgleicher Spiegel von `VMState` aus `@hivegrid/view-models` in HiveGrid * Cloud (`packages/view-models/src/index.ts`). Beim Einbau wird dieser Import * gegen das echte Paket getauscht, die Seiten selbst ändern sich dabei nicht. * * Warum das hier überhaupt steht: Die Cloud trennt strikt zwischen Route und * Screen. Die Route besitzt Loader, Actions und Realtime; die Screen-Komponente * ist rein und bekommt alles als Prop (``). Eine * Komponente, die sich ihre Daten selbst aus einem Store holt, muss beim Einbau * auseinandergenommen werden, genau das soll dieser Prototyp ersparen. */ export type VMStatus = "idle" | "loading" | "ready" | "empty" | "error"; export type VMState = | { status: "idle"; data?: undefined; error?: undefined } | { status: "loading"; data?: T; error?: undefined } | { status: "ready"; data: T; error?: undefined } | { status: "empty"; data?: undefined; error?: undefined } | { status: "error"; data?: T; error: { messageKey: string; code?: string } }; /** Kurzform für den Normalfall im Prototyp: Daten liegen vor. */ export function bereit(data: T): VMState { return { status: "ready", data }; } /** Kein Datensatz für die aktuelle Auswahl, nicht dasselbe wie ein Fehler. */ export function leer(): VMState { return { status: "empty" }; } /** * Aktionen einer Seite. * * Im Prototyp lösen sie einen Hinweis-Toast aus; in der Software werden daraus * Navigationen und Schreibpfade. Wichtig ist die Form: Der Screen ruft einen * Callback auf, er kennt weder Router noch Fetcher. */ export interface SeitenAktionen { /** Absprung in eine Arbeitsliste, z. B. aus dem Handlungsbedarf. */ readonly onAbsprung?: (ziel: string, kontext?: string) => void; /** Datensatz in der Tabelle geöffnet. */ readonly onZeileOeffnen?: (id: string) => void; /** Ansicht neu laden. */ readonly onAktualisieren?: () => void; }