"use client" import { useMemo } from "react" import { type ColumnDef, getCoreRowModel, useReactTable, } from "@tanstack/react-table" import type { HomeRouter, JumpHost, WanJhLeg } from "@/lib/route-optimizer-data" import { Flag } from "@/components/flag" import { cn } from "@/lib/utils" import { DataGridShell } from "@/components/data-grids/shared/data-grid-shell" import { DATA_GRID_CELL_PAD, DATA_GRID_CELL_PAD_FIRST, DATA_GRID_CELL_PAD_LAST, } from "@/components/data-grids/shared/data-grid-layout" import { WifiIcon } from "lucide-react" function LossChip({ loss }: { loss: number }) { if (loss === 0) return 0% return ( 1 ? "text-red-500" : "text-amber-500")}> {loss}% ) } interface RouteOptimizerWanMatrixDataGridProps { home: HomeRouter legs: WanJhLeg[] jumpHosts: JumpHost[] } function RouteOptimizerWanMatrixDataGrid({ home, legs, jumpHosts, }: RouteOptimizerWanMatrixDataGridProps) { const bestScore = legs.length ? Math.max(...legs.map((l) => l.score)) : 0 const columns = useMemo[]>(() => { const base: ColumnDef[] = [ { id: "wan", accessorKey: "name", header: () => WAN-аплинк, cell: ({ row }) => { const wan = row.original return ( {wan.name} {wan.iface} ) }, meta: { headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST }, }, { id: "isp", header: () => ISP / IP, cell: ({ row }) => { const wan = row.original return ( {wan.isp} {wan.ip} ) }, meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD }, }, { id: "bandwidth", header: () => ( Макс. полоса ), cell: ({ row }) => { const wan = row.original return ( ↓{wan.maxDl} ↑{wan.maxUl} Мбит ) }, meta: { headerClassName: cn(DATA_GRID_CELL_PAD, "text-right"), cellClassName: cn(DATA_GRID_CELL_PAD, "text-right"), }, }, ] const jhCols: ColumnDef[] = jumpHosts.map((jh) => ({ id: `jh-${jh.id}`, header: () => ( {jh.label} {jh.site} · {jh.ip} ), cell: ({ row }) => { const wan = row.original const leg = legs.find((l) => l.wanId === wan.id && l.jhId === jh.id) if (!leg) return — const isBest = leg.score === bestScore return ( {isBest && ( ★ ЛУЧШИЙ )} {leg.pingMs} мс ↓{leg.dlMbps} ↑{leg.ulMbps} score {leg.score} {leg.loss > 0 && } ) }, meta: { headerClassName: cn(DATA_GRID_CELL_PAD, "min-w-[130px] text-center"), cellClassName: cn(DATA_GRID_CELL_PAD, "min-w-[130px]"), }, })) const last = jhCols[jhCols.length - 1] if (last?.meta) { last.meta.headerClassName = cn(last.meta.headerClassName, DATA_GRID_CELL_PAD_LAST.replace("py-3", "")) last.meta.cellClassName = DATA_GRID_CELL_PAD_LAST } return [...base, ...jhCols] }, [bestScore, jumpHosts, legs]) const table = useReactTable({ data: home.wans, columns, getCoreRowModel: getCoreRowModel(), getRowId: (row) => row.id, }) return ( ) } export { RouteOptimizerWanMatrixDataGrid, type RouteOptimizerWanMatrixDataGridProps }
{wan.name}
{wan.iface}
{wan.isp}
{wan.ip}
↓{wan.maxDl}
↑{wan.maxUl} Мбит