import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { memo, useMemo } from "react"
import { cn, formatShortDate, chartMargin, toFixedFloat, formatBytes, decimalString } from "@/lib/utils"
// import Spinner from '../spinner'
import { useStore } from "@nanostores/react"
import { $containerFilter, $userSettings } from "@/lib/stores"
import { ChartData } from "@/types"
import { Separator } from "../ui/separator"
import { ChartType, Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
export default memo(function ContainerChart({
dataKey,
chartData,
chartType,
chartConfig,
unit = "%",
}: {
dataKey: string
chartData: ChartData
chartType: ChartType
chartConfig: ChartConfig
unit?: string
}) {
const filter = useStore($containerFilter)
const userSettings = useStore($userSettings)
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
const { containerData } = chartData
const isNetChart = chartType === ChartType.Network
const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => {
const obj = {} as {
toolTipFormatter: (item: any, key: string) => React.ReactNode | string
dataFunction: (key: string, data: any) => number | null
tickFormatter: (value: any) => string
}
// tick formatter
if (chartType === ChartType.CPU) {
obj.tickFormatter = (value) => {
const val = toFixedFloat(value, 2) + unit
return updateYAxisWidth(val)
}
} else {
const chartUnit = isNetChart ? userSettings.unitNet : Unit.Bytes
obj.tickFormatter = (val) => {
const { value, unit } = formatBytes(val, isNetChart, chartUnit, true)
return updateYAxisWidth(toFixedFloat(value, value >= 10 ? 0 : 1) + " " + unit)
}
}
// tooltip formatter
if (isNetChart) {
obj.toolTipFormatter = (item: any, key: string) => {
try {
const sent = item?.payload?.[key]?.ns ?? 0
const received = item?.payload?.[key]?.nr ?? 0
const { value: receivedValue, unit: receivedUnit } = formatBytes(received, true, userSettings.unitNet, true)
const { value: sentValue, unit: sentUnit } = formatBytes(sent, true, userSettings.unitNet, true)
return (
{decimalString(receivedValue)} {receivedUnit}
rx
{decimalString(sentValue)} {sentUnit}
tx
)
} catch (e) {
return null
}
}
} else if (chartType === ChartType.Memory) {
obj.toolTipFormatter = (item: any) => {
const { value, unit } = formatBytes(item.value, false, Unit.Bytes, true)
return decimalString(value) + " " + unit
}
} else {
obj.toolTipFormatter = (item: any) => decimalString(item.value) + unit
}
// data function
if (isNetChart) {
obj.dataFunction = (key: string, data: any) => (data[key] ? data[key].nr + data[key].ns : null)
} else {
obj.dataFunction = (key: string, data: any) => data[key]?.[dataKey] ?? null
}
return obj
}, [])
// Filter with set lookup
const filteredKeys = useMemo(() => {
if (!filter) {
return new Set()
}
const filterLower = filter.toLowerCase()
return new Set(Object.keys(chartConfig).filter((key) => !key.toLowerCase().includes(filterLower)))
}, [chartConfig, filter])
// console.log('rendered at', new Date())
if (containerData.length === 0) {
return null
}
return (
{xAxis(chartData)}
formatShortDate(data[0].payload.created)}
// @ts-ignore
itemSorter={(a, b) => b.value - a.value}
content={}
/>
{Object.keys(chartConfig).map((key) => {
const filtered = filteredKeys.has(key)
const fillOpacity = filtered ? 0.05 : 0.4
const strokeOpacity = filtered ? 0.1 : 1
return (
)
})}
)
})