feat: frontend React+Mantine+sigma.js (grafo/tablas/fichas/agenda/calendario)

Frontend web de lectura del vault osint + agenda/calendario Xandikos.

- Stack: React 19 + Vite 6 + TypeScript + Mantine v9 (React 19 obligatorio para
  que Mantine v9 monte). Grafo con sigma v3 + graphology + forceatlas2 en web
  worker. Markdown con react-markdown, calendario con @mantine/dates.
- AppShell con navbar de 4 secciones + botón global de refresco (POST /api/refresh).
- GraphView: force-directed, color por tipo, tamaño por grado, panel lateral con
  toggles de tipo + dangling + buscador (centra el nodo). Guard de WebGL: si el
  navegador no lo expone, avisa en vez de crashear.
- TablesView: una pestaña por tipo, tabla ordenable/filtrable con columnas del
  frontmatter. Click en fila -> ficha.
- NodeCard (modal): frontmatter clave-valor (fechas europeas), cuerpo Markdown,
  galería de imágenes con lightbox, PDFs/docs como enlace, wikilinks navegables.
- ContactsView: agenda con buscador + detalle (teléfonos, correos, bloque osint,
  nota). CalendarView: mini-calendario con días marcados + eventos agrupados por
  día (hora local).
- Vite proxya /api -> 127.0.0.1:8470. Verificado end-to-end contra el backend
  real: 1199 nodos / 618 aristas, 539 personas en tabla, 1064 contactos, 98
  eventos; grafo renderiza con WebGL y NodeCard abre con frontmatter+body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Egutierrez
2026-06-11 23:15:21 +02:00
parent 59558d43cb
commit 881a1b9716
26 changed files with 4619 additions and 39 deletions
+19
View File
@@ -0,0 +1,19 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { MantineProvider } from "@mantine/core";
import { Notifications } from "@mantine/notifications";
import "@mantine/core/styles.css";
import "@mantine/dates/styles.css";
import "@mantine/notifications/styles.css";
import "./global.css";
import { theme } from "./theme";
import { App } from "./App";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<MantineProvider theme={theme} defaultColorScheme="dark">
<Notifications position="top-right" />
<App />
</MantineProvider>
</StrictMode>,
);