93 lines
3.8 KiB
JavaScript
93 lines
3.8 KiB
JavaScript
// Campanita de alertas: avisa de programas/sedes NO identificados en cartera_junta
|
|
// (valores que no están en el diccionario alias_normalizacion).
|
|
import { useState, useEffect } from "react";
|
|
import { api } from "../lib/api";
|
|
|
|
export default function CampanitaAlertas() {
|
|
const [data, setData] = useState({ programa: [], sede: [] });
|
|
const [abierto, setAbierto] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let activo = true;
|
|
api.alertas()
|
|
.then((r) => { if (activo) setData({ programa: r.programa || [], sede: r.sede || [] }); })
|
|
.catch(() => { if (activo) setData({ programa: [], sede: [] }); });
|
|
return () => { activo = false; };
|
|
}, []);
|
|
|
|
const total = (data.programa?.length || 0) + (data.sede?.length || 0);
|
|
const hay = total > 0;
|
|
|
|
return (
|
|
<div style={{ position: "fixed", right: 18, top: 14, zIndex: 80 }}>
|
|
<button
|
|
onClick={() => setAbierto((v) => !v)}
|
|
title={hay ? `${total} valor(es) sin identificar` : "Sin alertas"}
|
|
style={{
|
|
position: "relative", width: 38, height: 38, borderRadius: 10,
|
|
border: "1px solid " + (hay ? "#f59e0b" : "#334155"),
|
|
background: hay ? "#78350f" : "rgba(15,23,42,0.9)",
|
|
color: hay ? "#fde68a" : "#94a3b8",
|
|
cursor: "pointer", fontSize: 18, lineHeight: 1,
|
|
display: "flex", alignItems: "center", justifyContent: "center",
|
|
boxShadow: "0 2px 8px rgba(0,0,0,0.25)",
|
|
}}
|
|
>
|
|
🔔
|
|
{hay && (
|
|
<span style={{
|
|
position: "absolute", top: -6, right: -6, minWidth: 18, height: 18,
|
|
padding: "0 4px", borderRadius: 999, background: "#dc2626", color: "#fff",
|
|
fontSize: 11, fontWeight: 700, display: "flex", alignItems: "center",
|
|
justifyContent: "center", border: "1px solid #fff",
|
|
}}>{total}</span>
|
|
)}
|
|
</button>
|
|
|
|
{abierto && (
|
|
<div style={{
|
|
position: "absolute", right: 0, top: 46, width: 320, maxHeight: 420,
|
|
overflowY: "auto", background: "#fff", color: "#0f172a",
|
|
border: "1px solid #e2e8f0", borderRadius: 12,
|
|
boxShadow: "0 8px 24px rgba(0,0,0,0.18)", padding: 14, fontSize: 13,
|
|
}}>
|
|
<div style={{ fontWeight: 700, marginBottom: 8 }}>🔔 Alertas de normalización</div>
|
|
{!hay ? (
|
|
<div style={{ color: "#059669", fontWeight: 600 }}>✓ Todo identificado, nada por revisar.</div>
|
|
) : (
|
|
<>
|
|
{(data.programa?.length > 0) && (
|
|
<div style={{ marginBottom: 10 }}>
|
|
<div style={{ fontWeight: 600, color: "#b45309", marginBottom: 4 }}>
|
|
Nuevo programa no identificado:
|
|
</div>
|
|
{data.programa.map((p, i) => (
|
|
<div key={i} style={{ padding: "3px 0", borderBottom: "1px solid #f1f5f9" }}>
|
|
<b>{p.valor || "(vacío)"}</b> <span style={{ color: "#94a3b8" }}>· {p.veces}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
{(data.sede?.length > 0) && (
|
|
<div>
|
|
<div style={{ fontWeight: 600, color: "#b45309", marginBottom: 4 }}>
|
|
Nueva sede no identificada:
|
|
</div>
|
|
{data.sede.map((s, i) => (
|
|
<div key={i} style={{ padding: "3px 0", borderBottom: "1px solid #f1f5f9" }}>
|
|
<b>{s.valor || "(vacío)"}</b> <span style={{ color: "#94a3b8" }}>· {s.veces}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
<div style={{ marginTop: 10, color: "#64748b", fontSize: 12 }}>
|
|
Agrégalos al diccionario (alias_normalizacion) para clasificarlos.
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|