import type { Server } from "../types/Server";
interface Props {
servers: Server[];
loading: boolean;
error: string | null;
page: number;
pageSize: number;
totalPages: number;
totalItems: number;
hideSensitive: boolean;
onPageChange: (page: number) => void;
onPageSizeChange: (size: number) => void;
}
const PAGE_SIZE_OPTIONS = [5, 10, 20, 50];
export const ServersTable = ({
servers,
loading,
error,
page,
pageSize,
totalPages,
totalItems,
hideSensitive,
onPageChange,
onPageSizeChange,
}: Props) => {
const showingFrom = totalItems === 0 ? 0 : page * pageSize + 1;
const showingTo = totalItems === 0 ? 0 : Math.min((page + 1) * pageSize, totalItems);
const hasResults = servers.length > 0;
const isInitialLoad = loading && !hasResults;
const showOverlay = loading && hasResults;
const formatSensitiveValue = (value: string | number) => (hideSensitive ? "••••" : value);
return (
{isInitialLoad &&
Carregando servidores...
}
{error &&
{error}
}
{!loading && !error && servers.length === 0 && (
Nenhum servidor encontrado.
)}
{hasResults && (
{showOverlay && (
Atualizando lista...
)}
| Nome |
IP |
Porta |
Usuário |
Senha |
Tipo |
Aplicação |
Banco |
{servers.map((server) => (
| {server.name} |
{formatSensitiveValue(server.ip)} |
{formatSensitiveValue(server.port)} |
{formatSensitiveValue(server.user)} |
{hideSensitive ? "••••" : server.password}
|
{server.type.toLowerCase()} |
{server.application.toLowerCase()} |
{server.dbType.toLowerCase()} |
))}
Mostrando {showingFrom} - {showingTo} de {totalItems}
Página {page + 1} de {Math.max(totalPages, 1)}
)}
);
};
const Styles = {
card: "overflow-hidden rounded-lg border border-cardBorder bg-card shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:shadow-slate-900/40",
status: "p-4 text-sm text-text-secondary dark:text-slate-400",
error: "p-4 text-sm text-red-600 dark:text-red-400",
tableWrapper: "overflow-x-auto rounded-lg border border-cardBorder shadow-sm dark:border-slate-800 dark:bg-slate-950/40",
table: "min-w-full table-auto divide-y divide-cardBorder dark:divide-slate-800",
tableHead: "sticky top-0 bg-gray-50 dark:bg-slate-800",
tableHeadRow: "text-left text-text dark:text-slate-200",
tableHeadCell: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-text-secondary dark:text-slate-300",
tableBody: "divide-y divide-cardBorder bg-white dark:divide-slate-800 dark:bg-slate-900",
tableRow: "transition-colors even:bg-gray-50/50 hover:bg-gray-50 dark:even:bg-slate-900 dark:hover:bg-slate-800",
rowCell: "px-4 py-3 text-sm text-text dark:text-slate-100",
password: "rounded bg-gray-100 px-2 py-1 text-xs dark:bg-slate-800 dark:text-slate-100",
pagination: "flex flex-col gap-2 border-t border-cardBorder bg-white px-4 py-3 dark:border-slate-800 dark:bg-slate-900 sm:flex-row sm:items-center sm:justify-between",
pageInfo: "text-sm text-text-secondary dark:text-slate-400",
paginationControls: "flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4",
pageSizeLabel: "text-sm text-text dark:text-slate-100 flex items-center gap-2",
pageSizeSelect: "rounded-md border border-cardBorder bg-white px-2 py-1 text-sm text-text outline-none focus:border-accent focus:ring-1 focus:ring-accent dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100",
pageButtons: "flex items-center gap-3",
pageButton: "rounded-md border border-cardBorder px-3 py-1.5 text-sm font-medium text-text transition-colors hover:bg-bg disabled:opacity-50 disabled:hover:bg-transparent dark:border-slate-700 dark:text-slate-100 dark:hover:bg-slate-800",
pageIndicator: "text-sm text-text-secondary dark:text-slate-400",
footerSpacer: "h-4",
loadingOverlay: "absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-white/70 text-sm font-medium text-text backdrop-blur-sm dark:bg-slate-900/80 dark:text-slate-100",
};