1import { useMemo } from "react";
2import { useSearchParams } from "react-router-dom";
3import {
4 flexRender,
5 getCoreRowModel,
6 useReactTable,
7 getSortedRowModel,
8} from "@tanstack/react-table";
9import { BenchmarkResult } from "../../../types";
10import { columns } from "./columns";
11import { BenchmarkCharts } from "../charts/BenchmarkCharts";
12import { exportToCsv } from "../export/csvExport";
14interface BenchmarkTableProps {
15 results: BenchmarkResult[];
16}
18export function BenchmarkTable({ results }: BenchmarkTableProps) {
19 const [searchParams, setSearchParams] = useSearchParams();
20 const selectedDataset = searchParams.get("dataset") || "";
21 const availableDatasets = useMemo(() => {
22 return Array.from(new Set(results.map((result) => result.dataset))).sort();
23 }, [results]);
25 // Memoize filtered data to prevent unnecessary recalculations
26 const filteredData = useMemo(() => {
27 if (!selectedDataset) return results;
28 return results.filter((row) => row.dataset === selectedDataset);
29 }, [results, selectedDataset]);
31 const table = useReactTable({
32 data: filteredData || [],
33 columns,
34 getCoreRowModel: getCoreRowModel(),
35 getSortedRowModel: getSortedRowModel(),
36 });
38 // Prepare data for bar charts when a dataset is selected
39 const chartData = useMemo(() => {
40 if (!selectedDataset) return [];
41 return results
42 .filter((row: BenchmarkResult) => row.dataset === selectedDataset)
43 .map((row: BenchmarkResult) => ({
44 algorithm: row.algorithm,
45 compression_ratio: row.compression_ratio,
46 encode_speed: row.encode_mb_per_sec,
47 decode_speed: row.decode_mb_per_sec,
48 }));
49 }, [results, selectedDataset]);
51 return (
52 <div className="table-container">
53 <div
54 style={{
55 marginBottom: "20px",
56 display: "flex",
57 alignItems: "center",
58 gap: "10px",
59 justifyContent: "space-between",
60 }}
61 >
62 <div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
63 <label htmlFor="dataset-select">Dataset:</label>
64 <select
65 id="dataset-select"
66 value={selectedDataset}
67 onChange={(e) => {
68 if (e.target.value) {
69 setSearchParams({ dataset: e.target.value });
70 } else {
71 setSearchParams({});
72 }
73 }}
74 style={{
75 padding: "8px",
76 borderRadius: "4px",
77 border: "1px solid #ccc",
78 minWidth: "200px",
79 backgroundColor: "#fff",
80 }}
81 >
82 <option value="">All Datasets</option>
83 {availableDatasets.map((dataset) => (
84 <option key={dataset} value={dataset}>
85 {dataset}
86 </option>
87 ))}
88 </select>
89 </div>
90 <button
91 onClick={() => exportToCsv(filteredData, selectedDataset)}
92 style={{
93 padding: "8px 16px",
94 backgroundColor: "#4CAF50",
95 color: "white",
96 border: "none",
97 borderRadius: "4px",
98 cursor: "pointer",
99 display: "flex",
100 alignItems: "center",
101 gap: "8px",
102 }}
103 >
104 <svg
105 width="16"
106 height="16"
107 viewBox="0 0 16 16"
108 fill="none"
109 xmlns="http://www.w3.org/2000/svg"
110 >
111 <path d="M8 12L3 7H6V1H10V7H13L8 12Z" fill="currentColor" />
112 <path d="M2 14V15H14V14H2Z" fill="currentColor" />
113 </svg>
114 Download CSV
115 </button>
116 </div>
118 {selectedDataset && chartData.length > 0 && (
119 <BenchmarkCharts chartData={chartData} />
120 )}
122 <table>
123 <thead>
124 {table.getHeaderGroups().map((headerGroup) => (
125 <tr key={headerGroup.id}>
126 {headerGroup.headers.map((header) => (
127 <th
128 key={header.id}
129 onClick={header.column.getToggleSortingHandler()}
130 style={{ cursor: "pointer" }}
131 >
132 {flexRender(
133 header.column.columnDef.header,
134 header.getContext(),
135 )}
136 {header.column.getIsSorted() && (
137 <span style={{ marginLeft: "4px" }}>
138 {header.column.getIsSorted() === "asc" ? "↑" : "↓"}
139 </span>
140 )}
141 </th>
142 ))}
143 </tr>
144 ))}
145 </thead>
146 <tbody>
147 {table.getRowModel().rows.map((row) => (
148 <tr key={row.id}>
149 {row.getVisibleCells().map((cell) => (
150 <td key={cell.id}>
151 {flexRender(cell.column.columnDef.cell, cell.getContext())}
152 </td>
153 ))}
154 </tr>
155 ))}
156 </tbody>
157 </table>
158 </div>
159 );
160}