"use client" import { CalendarClock, Database } from "lucide-react" import { Badge } from "./ui/badge" import { Progress } from "./ui/progress" import { formatStorage } from "../lib/utils" import { useT, useI18n } from "../lib/i18n/provider" import { PBSProblemMessage } from "./pbs-problem-message" export interface PBSDatastore { name: string path?: string total?: number | null used?: number | null avail?: number | null error?: string error_code?: string "backend-type"?: string "estimated-full-date"?: number "gc-status"?: { upid?: string | null; "removed-bytes"?: number; "pending-bytes"?: number } } export function datastorePercent(store: PBSDatastore): number | null { if (store.total == null || store.used == null || store.total <= 0) return null return (store.used / store.total) * 100 } // Same thresholds and colours as the PVE storage cards. export function usageTone(percent: number): { bar: string; text: string; used: string } { if (percent > 90) return { bar: "[&>div]:bg-red-500", text: "text-red-500", used: "text-red-400" } if (percent > 75) return { bar: "[&>div]:bg-yellow-500", text: "text-yellow-500", used: "text-yellow-400" } return { bar: "[&>div]:bg-blue-500", text: "text-muted-foreground", used: "text-blue-400" } } const gib = (bytes: number) => formatStorage(bytes / 1024 ** 3) // A datastore without a readable capacity keeps its message: it is never shown as empty. export function DatastoreUsageRow({ store, compact = false }: { store: PBSDatastore; compact?: boolean }) { const t = useT() const percent = datastorePercent(store) if (percent == null) { return
{store.name} —
} const tone = usageTone(percent) return
{store.name} {percent.toFixed(1)}%
{!compact &&
{gib(store.used!)} / {gib(store.total!)} {t("pbs.free")}: {gib(store.avail ?? store.total! - store.used!)}
}
} // Same layout as the "Proxmox storage" cards of the PVE Monitor. export function PBSDatastoreCard({ store }: { store: PBSDatastore }) { const t = useT() const { language } = useI18n() const percent = datastorePercent(store) const tone = percent == null ? null : usageTone(percent) const fullDate = store["estimated-full-date"] const type = store["backend-type"] || t("pbs.datastoreType") return

{store.name}

{type}
{store.error ? t("storage.status.error") : t("storage.status.active")} {percent != null && {percent.toFixed(2)}%}
{percent != null && tone ? (

{t("storage.total")}

{gib(store.total!)}

{t("storage.used")}

{gib(store.used!)}

{t("storage.available")}

{gib(store.avail ?? store.total! - store.used!)}

) : ( )} {(store.path || fullDate !== undefined) &&
{store.path && {store.path}} {fullDate !== undefined && {t("pbs.estimatedFull")}: {fullDate > 0 ? new Date(fullDate * 1000).toLocaleDateString(language) : t("pbs.estimatedFullUnknown")} }
}
}