"use client" import { useState, useEffect } from "react" import { Card, CardContent, CardHeader, CardTitle } from "./ui/card" import { Progress } from "./ui/progress" import { Badge } from "./ui/badge" import { HardDrive, Database, Archive, AlertTriangle, CheckCircle, Activity, AlertCircle, Thermometer, } from "lucide-react" interface StorageData { total: number used: number available: number disks: DiskInfo[] } interface DiskInfo { name: string mountpoint: string fstype: string total: number used: number available: number usage_percent: number health: string temperature: number disk_type?: string } const TEMP_THRESHOLDS = { HDD: { safe: 45, warning: 55 }, SSD: { safe: 55, warning: 65 }, NVMe: { safe: 60, warning: 70 }, } const getTempStatus = (temp: number, diskType: string): "safe" | "warning" | "critical" => { const thresholds = TEMP_THRESHOLDS[diskType as keyof typeof TEMP_THRESHOLDS] || TEMP_THRESHOLDS.HDD if (temp <= thresholds.safe) return "safe" if (temp <= thresholds.warning) return "warning" return "critical" } const getTempColor = (status: "safe" | "warning" | "critical"): string => { switch (status) { case "safe": return "text-green-500" case "warning": return "text-yellow-500" case "critical": return "text-red-500" default: return "text-muted-foreground" } } const getDiskTypeBadgeColor = (diskType: string): string => { switch (diskType) { case "HDD": return "bg-blue-500/10 text-blue-500 border-blue-500/20" case "SSD": return "bg-purple-500/10 text-purple-500 border-purple-500/20" case "NVMe": return "bg-orange-500/10 text-orange-500 border-orange-500/20" default: return "bg-gray-500/10 text-gray-500 border-gray-500/20" } } const fetchStorageData = async (): Promise => { try { const response = await fetch("/api/storage", { method: "GET", headers: { "Content-Type": "application/json", }, signal: AbortSignal.timeout(5000), }) if (!response.ok) { throw new Error(`Flask server responded with status: ${response.status}`) } const data = await response.json() return data } catch (error) { console.error("Failed to fetch storage data from Flask server:", error) return null } } export function StorageMetrics() { const [storageData, setStorageData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { const fetchData = async () => { setLoading(true) setError(null) const result = await fetchStorageData() if (!result) { setError("Flask server not available. Please ensure the server is running.") } else { setStorageData(result) } setLoading(false) } fetchData() const interval = setInterval(fetchData, 60000) return () => clearInterval(interval) }, []) if (loading) { return (
Loading storage data...
) } if (error || !storageData) { return (
Flask Server Not Available
{error || "Unable to connect to the Flask server. Please ensure the server is running and try again."}
) } const usagePercent = storageData.total > 0 ? (storageData.used / storageData.total) * 100 : 0 const disksByType = storageData.disks.reduce( (acc, disk) => { const type = disk.disk_type || "Unknown" if (!acc[type]) { acc[type] = [] } acc[type].push(disk) return acc }, {} as Record, ) const tempByType = Object.entries(disksByType) .map(([type, disks]) => { const avgTemp = disks.reduce((sum, disk) => sum + disk.temperature, 0) / disks.length const status = getTempStatus(avgTemp, type) return { type, avgTemp: Math.round(avgTemp), status, count: disks.length } }) .filter((item) => item.type !== "Unknown") // Filter out unknown types return (
{/* Storage Overview Cards */}
Total Storage
{storageData.total.toFixed(1)} GB

{storageData.used.toFixed(1)} GB used • {storageData.available.toFixed(1)} GB available

Used Storage
{storageData.used.toFixed(1)} GB

{usagePercent.toFixed(1)}% of total space

Available
{storageData.available.toFixed(1)} GB
{((storageData.available / storageData.total) * 100).toFixed(1)}% Free

Available space

Disks
{storageData.disks.length}
{storageData.disks.filter((d) => d.health === "healthy").length} Healthy

Storage devices

{tempByType.length > 0 && (
{tempByType.map(({ type, avgTemp, status, count }) => (
Avg Temperature
{type}
{avgTemp}°C

{count} {type} disk{count > 1 ? "s" : ""}

{status === "safe" ? "Optimal" : status === "warning" ? "Warning" : "Critical"}
))}
)} {/* Disk Details */} Storage Devices
{storageData.disks.map((disk, index) => { const diskType = disk.disk_type || "HDD" const tempStatus = getTempStatus(disk.temperature, diskType) return (
{disk.name} {disk.disk_type && ( {disk.disk_type} )}
{disk.fstype} • {disk.mountpoint}
{disk.used.toFixed(1)} GB / {disk.total.toFixed(1)} GB
Temp
{disk.temperature}°C
{disk.health === "healthy" ? ( ) : ( )} {disk.health}
) })}
) }