"use client" import { useState, useEffect } from "react" import { Button } from "@/components/ui/button" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { ArrowLeft, Loader2 } from "lucide-react" import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from "recharts" interface MetricsViewProps { vmid: number vmName: string vmType: "qemu" | "lxc" onBack: () => void } const TIMEFRAME_OPTIONS = [ { value: "hour", label: "1 Hour" }, { value: "day", label: "24 Hours" }, { value: "week", label: "7 Days" }, { value: "month", label: "30 Days" }, { value: "year", label: "1 Year" }, ] export function MetricsView({ vmid, vmName, vmType, onBack }: MetricsViewProps) { const [timeframe, setTimeframe] = useState("week") const [data, setData] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { fetchMetrics() }, [vmid, timeframe]) const fetchMetrics = async () => { setLoading(true) setError(null) try { const baseUrl = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.hostname}:8008` : "" const apiUrl = `${baseUrl}/api/vms/${vmid}/metrics?timeframe=${timeframe}` const response = await fetch(apiUrl) if (!response.ok) { const errorData = await response.json() throw new Error(errorData.error || "Failed to fetch metrics") } const result = await response.json() const transformedData = result.data.map((item: any) => { const date = new Date(item.time * 1000) let timeLabel = "" if (timeframe === "hour") { timeLabel = date.toLocaleString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false, }) } else if (timeframe === "day") { timeLabel = date.toLocaleString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false, }) } else if (timeframe === "week") { timeLabel = date.toLocaleString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: false, }) } else if (timeframe === "month") { timeLabel = date.toLocaleString("en-US", { month: "short", day: "numeric", }) } else { timeLabel = date.toLocaleString("en-US", { month: "short", year: "numeric", }) } return { time: timeLabel, timestamp: item.time, cpu: item.cpu ? Number((item.cpu * 100).toFixed(2)) : 0, memory: item.mem ? Number(((item.mem / item.maxmem) * 100).toFixed(2)) : 0, memoryMB: item.mem ? Number((item.mem / 1024 / 1024).toFixed(0)) : 0, maxMemoryMB: item.maxmem ? Number((item.maxmem / 1024 / 1024).toFixed(0)) : 0, netin: item.netin ? Number((item.netin / 1024 / 1024).toFixed(2)) : 0, netout: item.netout ? Number((item.netout / 1024 / 1024).toFixed(2)) : 0, diskread: item.diskread ? Number((item.diskread / 1024 / 1024).toFixed(2)) : 0, diskwrite: item.diskwrite ? Number((item.diskwrite / 1024 / 1024).toFixed(2)) : 0, } }) setData(transformedData) } catch (err: any) { setError(err.message || "Error loading metrics") } finally { setLoading(false) } } const formatXAxisTick = (tick: any) => { return tick } const renderAllCharts = () => { if (loading) { return (
) } if (error) { return (

{error}

) } if (data.length === 0) { return (

No data available

) } const tickInterval = Math.ceil(data.length / 8) return (
{/* CPU Chart */}

CPU Usage

Math.ceil(dataMax * 1.15)]} />
{/* Memory Chart */}

Memory Usage

Math.ceil(dataMax * 1.15)]} />
{/* Disk I/O Chart */}

Disk I/O

Math.ceil(dataMax * 1.15)]} />
{/* Network I/O Chart */}

Network I/O

Math.ceil(dataMax * 1.15)]} />
) } return (
{/* Fixed Header */}

Metrics - {vmName}

VMID: {vmid} • Type: {vmType.toUpperCase()}

{/* Scrollable Content with all charts */}
{renderAllCharts()}
) }