import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import { useState } from "react"; export interface TableProps { headings: Heading[]; rows: [][]; } export interface Heading { title: string; type: "blank" | "normal"; sortable: boolean; } /** * @param hopsAway String describing the number of hops away the node is from the current node * @returns number of hopsAway or `0` if hopsAway is 'Direct' */ function numericHops(hopsAway: string): number { if(hopsAway.match(/direct/i)){ return 0; } if ( hopsAway.match(/\d+\s+hop/gi) ) { return Number( hopsAway.match(/(\d+)\s+hop/i)?.[1] ); } return Number.MAX_SAFE_INTEGER; } export const Table = ({ headings, rows }: TableProps) => { const [sortColumn, setSortColumn] = useState("Last Heard"); const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc"); const headingSort = (title: string) => { if (sortColumn === title) { setSortOrder(sortOrder === "asc" ? "desc" : "asc"); } else { setSortColumn(title); setSortOrder("asc"); } }; const sortedRows = rows.slice().sort((a, b) => { if (!sortColumn) return 0; const columnIndex = headings.findIndex((h) => h.title === sortColumn); const aValue = a[columnIndex].props.children; const bValue = b[columnIndex].props.children; // Custom comparison for 'Last Heard' column if (sortColumn === "Last Heard") { const aTimestamp = aValue.props.timestamp ?? 0; const bTimestamp = bValue.props.timestamp ?? 0; if (aTimestamp < bTimestamp) { return sortOrder === "asc" ? -1 : 1; } if (aTimestamp > bTimestamp) { return sortOrder === "asc" ? 1 : -1; } return 0; } // Custom comparison for 'Connection' column if (sortColumn === "Connection") { const aNumHops = numericHops(aValue instanceof Array ? aValue[0] : aValue); const bNumHops = numericHops(bValue instanceof Array ? bValue[0] : bValue); if (aNumHops < bNumHops) { return sortOrder === "asc" ? -1 : 1; } if (aNumHops > bNumHops) { return sortOrder === "asc" ? 1 : -1; } return 0; } // Default comparison for other columns if (aValue < bValue) { return sortOrder === "asc" ? -1 : 1; } if (aValue > bValue) { return sortOrder === "asc" ? 1 : -1; } return 0; }); return ( {headings.map((heading) => ( ))} {sortedRows.map((row, index) => ( // biome-ignore lint/suspicious/noArrayIndexKey: TODO: Once this table is sortable, this should get fixed. {row.map((item, index) => ( index === 0 ? : ))} ))}
heading.sortable && headingSort(heading.title)} onKeyUp={() => heading.sortable && headingSort(heading.title)} >
{heading.title} {sortColumn === heading.title && (sortOrder === "asc" ? : )}
{item} {item}
); };