"use client" import { useState, useEffect } from "react" import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from "recharts" import { Loader2 } from "lucide-react" interface NetworkMetricsData { time: string timestamp: number netIn: number netOut: number } interface NetworkTrafficChartProps { timeframe: string onTotalsCalculated?: (totals: { received: number; sent: number }) => void } const CustomNetworkTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { return (

{label}

{payload.map((entry: any, index: number) => (
{entry.name}: {entry.value.toFixed(3)} GB
))}
) } return null } export function NetworkTrafficChart({ timeframe, onTotalsCalculated }: NetworkTrafficChartProps) { const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [visibleLines, setVisibleLines] = useState({ netIn: true, netOut: true, }) useEffect(() => { fetchMetrics() }, [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/node/metrics?timeframe=${timeframe}` const response = await fetch(apiUrl) if (!response.ok) { throw new Error(`Failed to fetch node metrics: ${response.status}`) } const result = await response.json() if (!result.data || !Array.isArray(result.data)) { throw new Error("Invalid data format received from server") } if (result.data.length === 0) { setData([]) setLoading(false) return } // RRD data contains rate (bytes/second), we need to calculate traffic per interval const transformedData = result.data.map((item: any, index: number) => { 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", hour12: false, }) } else if (timeframe === "year") { timeLabel = date.toLocaleString("en-US", { month: "short", day: "numeric", year: "numeric", }) } else { timeLabel = date.toLocaleString("en-US", { month: "short", day: "numeric", }) } // Calculate time interval between data points (in seconds) let intervalSeconds = 60 // Default to 1 minute if (index > 0) { intervalSeconds = item.time - result.data[index - 1].time } // Convert rate (bytes/second) to traffic in this interval (GB) // netin and netout are in bytes/second, multiply by interval to get total bytes const netInBytes = (item.netin || 0) * intervalSeconds const netOutBytes = (item.netout || 0) * intervalSeconds return { time: timeLabel, timestamp: item.time, netIn: Number((netInBytes / 1024 / 1024 / 1024).toFixed(4)), netOut: Number((netOutBytes / 1024 / 1024 / 1024).toFixed(4)), } }) setData(transformedData) const totalReceived = transformedData.reduce((sum: number, item: NetworkMetricsData) => sum + item.netIn, 0) const totalSent = transformedData.reduce((sum: number, item: NetworkMetricsData) => sum + item.netOut, 0) if (onTotalsCalculated) { onTotalsCalculated({ received: totalReceived, sent: totalSent }) } } catch (err: any) { console.error("[v0] Error fetching network metrics:", err) setError(err.message || "Error loading metrics") } finally { setLoading(false) } } const tickInterval = Math.ceil(data.length / 8) const handleLegendClick = (dataKey: string) => { setVisibleLines((prev) => ({ ...prev, [dataKey]: !prev[dataKey as keyof typeof prev], })) } const renderLegend = (props: any) => { const { payload } = props return (
{payload.map((entry: any, index: number) => { const isVisible = visibleLines[entry.dataKey as keyof typeof visibleLines] return (
handleLegendClick(entry.dataKey)} style={{ opacity: isVisible ? 1 : 0.4 }} >
{entry.value}
) })}
) } if (loading) { return (
) } if (error) { return (

Network metrics not available yet

{error}

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

No network metrics available

) } return ( } /> ) }