Fase 3 (islas): historiales de seguridad y transacciones en React/TSX
Tabla genérica reutilizable HistoryTable (columnas por data-columns, filas por json_script) + entry history_table: - security_history: intentos de conexión (username/status/ip/fecha). Se elimina la caja "actividad" duplicada. Las vistas pasan login_attempts_data serializable. - trans_history: historial de transacciones (StripeLog) con transactions_data. Datos embebidos con json_script (sin endpoint extra). Verificado: check OK, ambas plantillas renderizan la isla con datos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
interface Column {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
columns: Column[]
|
||||
rows: Record<string, unknown>[]
|
||||
emptyText: string
|
||||
}
|
||||
|
||||
/** Tabla genérica de solo lectura para los historiales (seguridad, transacciones, baneos). */
|
||||
export function HistoryTable({ columns, rows, emptyText }: Props) {
|
||||
return (
|
||||
<table className="max-center-table-aligned">
|
||||
<thead>
|
||||
<tr>
|
||||
{columns.map((c) => (
|
||||
<th key={c.key}>{c.label}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.length > 0 ? (
|
||||
rows.map((row, i) => (
|
||||
<tr key={i}>
|
||||
{columns.map((c) => (
|
||||
<td key={c.key}>{String(row[c.key] ?? '')}</td>
|
||||
))}
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={columns.length} className="centered">
|
||||
<span>{emptyText}</span>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user