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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { HistoryTable } from '../components/HistoryTable'
|
||||
|
||||
// Entry genérico para los historiales de solo lectura. La plantilla define las
|
||||
// columnas en data-columns (JSON) y las filas en un json_script.
|
||||
const el = document.getElementById('history-table-app')
|
||||
if (el) {
|
||||
const dEl = document.getElementById('history-table-data')
|
||||
const rows = dEl ? JSON.parse(dEl.textContent || '[]') : []
|
||||
const columns = JSON.parse(el.dataset.columns || '[]')
|
||||
createRoot(el).render(
|
||||
<StrictMode>
|
||||
<HistoryTable columns={columns} rows={rows} emptyText={el.dataset.emptyText || 'No hay datos'} />
|
||||
</StrictMode>,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user