"use client" import { useEffect, useRef, useState } from "react" import { Thermometer } from "lucide-react" import { Badge } from "./ui/badge" import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts" import { fetchApi } from "@/lib/api-config" import { useDiskTempThresholds } from "@/lib/health-thresholds" interface TempPoint { timestamp: number value: number } interface DiskTemperatureCardProps { diskName: string liveTemperature: number /** Disk class — "HDD" | "SSD" | "NVMe" | "SAS". Drives the threshold colors. */ diskType: string /** Click handler — opens the full timeframe-selector modal as drill-down. */ onOpenDetail?: () => void } // Disk-temperature thresholds come from the user-configurable backend // (lib/health-thresholds.ts). The classifier here takes the resolved // pair so the consumer can read it from the hook once per render. function statusFor(temp: number, t: { warn: number; hot: number }) { if (temp <= 0) return { label: "N/A", className: "bg-gray-500/10 text-gray-500 border-gray-500/20", color: "#6b7280" } if (temp >= t.hot) return { label: "Hot", className: "bg-red-500/10 text-red-500 border-red-500/20", color: "#ef4444" } if (temp >= t.warn) return { label: "Warm", className: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20", color: "#f59e0b" } return { label: "Normal", className: "bg-green-500/10 text-green-500 border-green-500/20", color: "#22c55e" } } const MiniTooltip = ({ active, payload }: any) => { if (active && payload && payload.length) { const ts = payload[0].payload?.timestamp const date = ts ? new Date(ts * 1000) : null return (
{date && (

{date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}

)}

{payload[0].value}°C

) } return null } export function DiskTemperatureCard({ diskName, liveTemperature, diskType, onOpenDetail, }: DiskTemperatureCardProps) { const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const cancelled = useRef(false) useEffect(() => { cancelled.current = false const fetchHistory = async () => { setLoading(true) try { const result = await fetchApi<{ data: TempPoint[] }>( `/api/disk/${encodeURIComponent(diskName)}/temperature/history?timeframe=hour`, ) if (cancelled.current) return setData(result?.data || []) } catch { if (!cancelled.current) setData([]) } finally { if (!cancelled.current) setLoading(false) } } fetchHistory() // Refresh once a minute so the inline chart tracks the collector // without needing the user to reopen the modal. const id = setInterval(fetchHistory, 60_000) return () => { cancelled.current = true clearInterval(id) } }, [diskName]) const allThresholds = useDiskTempThresholds() const dt = (() => { const t = (diskType || "").toUpperCase() if (t === "HDD") return allThresholds.HDD if (t === "NVME") return allThresholds.NVMe if (t === "SAS") return allThresholds.SAS return allThresholds.SSD })() const status = statusFor(liveTemperature, dt) const lineColor = status.color const tempDisplay = liveTemperature > 0 ? `${liveTemperature}°C` : "N/A" const samples = data.length const interactive = !!onOpenDetail const Wrapper: any = interactive ? "button" : "div" return (

Temperature

{tempDisplay}

{status.label}
{loading ? (
) : samples < 2 ? (
Collecting samples — chart populates after ~2 minutes
) : ( } cursor={{ stroke: lineColor, strokeOpacity: 0.3, strokeWidth: 1 }} /> )}
) }