"use client" import { useState, useEffect } from "react" import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select" import { Badge } from "./ui/badge" import { Thermometer, TrendingDown, TrendingUp, Minus } from "lucide-react" import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts" import { useIsMobile } from "../hooks/use-mobile" import { fetchApi } from "@/lib/api-config" const TIMEFRAME_OPTIONS = [ { value: "hour", label: "1 Hour" }, { value: "day", label: "24 Hours" }, { value: "week", label: "7 Days" }, { value: "month", label: "30 Days" }, ] interface TempHistoryPoint { timestamp: number value: number min?: number max?: number } interface TempStats { min: number max: number avg: number current: number } interface TemperatureDetailModalProps { open: boolean onOpenChange: (open: boolean) => void liveTemperature?: number } const CustomTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { return (

{label}

{payload.map((entry: any, index: number) => (
{entry.name}: {entry.value}°C
))}
) } return null } const getStatusColor = (temp: number) => { if (temp >= 75) return "#ef4444" if (temp >= 60) return "#f59e0b" return "#22c55e" } const getStatusInfo = (temp: number) => { if (temp === 0) return { status: "N/A", color: "bg-gray-500/10 text-gray-500 border-gray-500/20" } if (temp < 60) return { status: "Normal", color: "bg-green-500/10 text-green-500 border-green-500/20" } if (temp < 75) return { status: "Warm", color: "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" } return { status: "Hot", color: "bg-red-500/10 text-red-500 border-red-500/20" } } export function TemperatureDetailModal({ open, onOpenChange, liveTemperature }: TemperatureDetailModalProps) { const [timeframe, setTimeframe] = useState("hour") const [data, setData] = useState([]) const [stats, setStats] = useState({ min: 0, max: 0, avg: 0, current: 0 }) const [loading, setLoading] = useState(true) const isMobile = useIsMobile() useEffect(() => { if (open) { fetchHistory() } }, [open, timeframe]) const fetchHistory = async () => { setLoading(true) try { const result = await fetchApi<{ data: TempHistoryPoint[]; stats: TempStats }>( `/api/temperature/history?timeframe=${timeframe}` ) if (result && result.data) { setData(result.data) setStats(result.stats) } } catch (err) { console.error("[v0] Failed to fetch temperature history:", err) } finally { setLoading(false) } } const formatTime = (timestamp: number) => { const date = new Date(timestamp * 1000) if (timeframe === "hour") { return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) } else if (timeframe === "day") { return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) } else { return date.toLocaleDateString([], { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) } } const chartData = data.map((d) => ({ ...d, time: formatTime(d.timestamp), })) // Use live temperature from the overview card (real-time) instead of last DB record const currentTemp = liveTemperature && liveTemperature > 0 ? Math.round(liveTemperature * 10) / 10 : stats.current const currentStatus = getStatusInfo(currentTemp) const chartColor = getStatusColor(currentTemp) // Calculate Y axis domain based on plotted data values only. // Stats cards already show the real historical min/max separately. // Using only graphed values keeps the chart readable and avoids // large empty gaps caused by momentary spikes that get averaged out. const values = data.map((d) => d.value) const yMin = values.length > 0 ? Math.max(0, Math.floor(Math.min(...values) - 3)) : 0 const yMax = values.length > 0 ? Math.ceil(Math.max(...values) + 3) : 100 return (
CPU Temperature
{/* Stats bar */}
Current
{currentTemp}°C
Min
{stats.min}°C
Avg
{stats.avg}°C
Max
{stats.max}°C
{/* Chart */}
{loading ? (
) : chartData.length === 0 ? (

No temperature data available for this period

Data is collected every 60 seconds

) : ( `${v}°`} width={isMobile ? 40 : 45} /> } /> )}
) }