'use client'; /** * Small shared client helpers for the admin tables: a clickable sortable * column header and a CSV-download trigger. Kept dependency-free and * dark-theme consistent with globals.css. */ export type SortOrder = 'asc' | 'desc'; export function SortHeader({ label, col, sort, order, onSort, className, }: { label: string; col: string; sort: string; order: SortOrder; onSort: (col: string) => void; className?: string; }) { const active = sort === col; const indicator = active ? (order === 'asc' ? '▲' : '▼') : '↕'; return ( onSort(col)} role="button" tabIndex={0} aria-sort={active ? (order === 'asc' ? 'ascending' : 'descending') : 'none'} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSort(col); } }} > {label} ); } /** * Triggers a browser download of a same-origin URL. The server sets * Content-Disposition: attachment, so the cookie-authenticated GET streams the * CSV straight to a file. */ export function downloadUrl(url: string): void { const a = document.createElement('a'); a.href = url; a.rel = 'noopener'; document.body.appendChild(a); a.click(); a.remove(); }