import { useMemo, useState } from "react";
import { AlertIcon, SearchIcon } from "../ui/Icons";
import { Spinner } from "../ui/Spinner";
import { Badge } from "../ui/Badge";
const COLUMNS = [
{ key: "title", label: "Título" },
{ key: "journal", label: "Revista / Fuente" },
{ key: "publication_year", label: "Año" },
{ key: "doi", label: "DOI" },
{ key: "type", label: "Tipo" },
];
function SortIcon({ active, direction }) {
const path =
direction === "asc" || !active ? "M6 8L3 5h6z" : "M6 4l3 3H3z";
return (
);
}
function sortPublications(rows, key, direction) {
const sorted = [...rows].sort((a, b) => {
const va = a[key];
const vb = b[key];
const cmp =
typeof va === "string" ? va.localeCompare(vb) : (va ?? 0) - (vb ?? 0);
return direction === "asc" ? cmp : -cmp;
});
return sorted;
}
/**
* Publications table. Owns only UI-state (filter + sort). Data, loading and
* error states are driven by the parent page so retries and toasts can be
* handled in one place.
*/
export function PublicationsTable({
publications,
loading = false,
error = null,
onRetry,
}) {
const [filter, setFilter] = useState("");
const [sortKey, setSortKey] = useState("publication_year");
const [sortDir, setSortDir] = useState("desc");
const filtered = useMemo(() => {
const needle = filter.trim().toLowerCase();
const rows = needle
? publications.filter(
(p) =>
p.title.toLowerCase().includes(needle) ||
p.journal.toLowerCase().includes(needle) ||
String(p.publication_year).includes(needle),
)
: publications;
return sortPublications(rows, sortKey, sortDir);
}, [publications, filter, sortKey, sortDir]);
function toggleSort(key) {
if (sortKey === key) {
setSortDir((d) => (d === "asc" ? "desc" : "asc"));
} else {
setSortKey(key);
setSortDir("desc");
}
}
return (
{filtered.length} de {publications.length} resultados
Publicaciones
)}
{COLUMNS.map((col) => (
{filtered.length === 0 ? (
toggleSort(col.key)}
className="select-none whitespace-nowrap border-b border-surface-border/60 px-4 py-2.5 text-left text-xs font-medium tracking-wide text-ink-secondary"
>
{col.label.toUpperCase()}
))}
) : (
filtered.map((pub, i) => (
No se encontraron publicaciones con ese filtro.
))
)}
{pub.title}
{pub.journal}
{pub.publication_year}
{pub.doi}
Cargando publicaciones…
No se pudieron cargar las publicaciones
{error?.message ?? "Error desconocido."}