Files
factorio-signal-exporter/web/components/ChartCard/TableViz.tsx
2026-06-03 12:52:45 +02:00

76 lines
2.8 KiB
TypeScript

import { useApp } from '@/lib/context';
import { resolveName } from '@/lib/localization';
import { formatSI } from '@/lib/formatNumber';
import { CardShell } from './CardShell';
import type { ChartConfig, SignalRow } from '@/lib/types';
interface Props {
config: ChartConfig;
rows: SignalRow[];
onEdit: () => void;
onDelete: () => void;
}
export default function TableViz({ config, rows, onEdit, onDelete }: Props) {
const { localeMap } = useApp();
const sortCol = config.signal_type === 'red' ? 'red' : 'green';
const latest = new Map<string, { green?: number; red?: number }>();
for (const row of rows) {
latest.set(`${row.combinator}::${row.item_key}`, { green: row.green, red: row.red });
}
const tableRows = [...latest.entries()]
.sort((a, b) => {
const va = a[1][sortCol] ?? 0;
const vb = b[1][sortCol] ?? 0;
switch (config.order_by) {
case 'value_asc':
case 'delta_asc':
return va - vb;
case 'abs_desc':
return Math.abs(vb) - Math.abs(va);
default:
return vb - va;
}
})
.slice(0, config.series_limit);
return (
<CardShell title={config.title} onEdit={onEdit} onDelete={onDelete} empty={rows.length === 0}>
<div className="flex-1 overflow-y-auto">
<table className="w-full text-xs text-gray-300">
<thead className="sticky top-0 bg-gray-800">
<tr>
<th className="text-left px-2 py-1">Item</th>
<th className="text-left px-2 py-1">Combinator</th>
{config.signal_type !== 'red' && <th className="text-right px-2 py-1 text-green-400">Green</th>}
{config.signal_type !== 'green' && <th className="text-right px-2 py-1 text-red-400">Red (NP)</th>}
</tr>
</thead>
<tbody>
{tableRows.map(([key, vals]) => {
const [combinator, item_key] = key.split('::');
return (
<tr key={key} className="border-t border-gray-800 hover:bg-gray-800/50">
<td className="px-2 py-0.5">{resolveName(item_key, localeMap)}</td>
<td className="px-2 py-0.5 text-gray-500">{combinator}</td>
{config.signal_type !== 'red' && (
<td className={`px-2 py-0.5 text-right font-mono ${(vals.green ?? 0) < 0 ? 'text-red-400' : 'text-green-400'}`}>
{vals.green != null ? formatSI(vals.green) : '--'}
</td>
)}
{config.signal_type !== 'green' && (
<td className="px-2 py-0.5 text-right font-mono text-orange-400">
{vals.red != null ? formatSI(vals.red) : '--'}
</td>
)}
</tr>
);
})}
</tbody>
</table>
</div>
</CardShell>
);
}