// ────────────────────────────────────────────────────────────────── // datos.jsx — leer un catálogo compartido, para ventanas de cualquier módulo. // // Tres módulos necesitaban un dato que vivía dentro de una ventana de otro: // Programación quería los canales (definidos en la ventana de Canales, de // Comercial) y Contabilización quería los elementos de venta y saber si un // elemento es "de derechos" (definidos en las ventanas de CRM y de Productos). // // Cargar esas ventanas enteras para leer una tabla es lo que tenía a `core/` con // 982 KB. Acá va el DATO, no la ventana. // // Y no se mudaron las tres implementaciones a medida: las tres hacían lo mismo // —leer una tabla de localStorage con estado de React— así que queda UN primitivo // y los tres nombres históricos encima, para no tocar las ventanas que ya los // llaman. // // Publica window.SCDatos, y por compatibilidad useCanalesDistribucion, // useElementos, esProductoDerechos y esElementoDerechos. // ────────────────────────────────────────────────────────────────── (function () { "use strict"; function leer(clave) { try { const raw = localStorage.getItem(clave); if (!raw) return []; const v = JSON.parse(raw); return Array.isArray(v) ? v : []; } catch (e) { return []; } } // Estado de React sobre una tabla del bootstrap. Devuelve [filas, setFilas], // que es la forma que ya esperan las ventanas. // // Sin semilla a propósito: en la maqueta estos hooks caían a datos de demo // cuando la tabla venía vacía, y eso ahora sería mentir — las tablas llegan del // bootstrap, y vacío significa vacío. function useTabla(clave) { const [filas, setFilas] = React.useState(() => leer(clave)); // Otra ventana de la misma pestaña puede reescribir la tabla; el evento // `storage` sólo avisa entre pestañas, así que se relee al enfocar. React.useEffect(() => { const refrescar = () => setFilas(leer(clave)); window.addEventListener("focus", refrescar); window.addEventListener("storage", refrescar); return () => { window.removeEventListener("focus", refrescar); window.removeEventListener("storage", refrescar); }; }, [clave]); return [filas, setFilas]; } // ── Un elemento de venta "es de derechos" ──────────────────────────────── // Su producto es de derechos, o tiene un elem_derecho_contenido que lo respalda // aunque su producto esté vacío. const DERECHOS_AREAS = ["AM6", "AM7"]; function esProductoDerechos(id_producto) { if (!id_producto) return false; const p = leer("sc.producto").find((x) => x.id === id_producto); return !!p && DERECHOS_AREAS.indexOf(p.id_monetizacion) !== -1; } function esElementoDerechos(el) { if (!el) return false; if (esProductoDerechos(el.id_producto)) return true; return leer("sc.elem_derecho_contenido").some((v) => v.id_elemento_venta === el.id); } window.SCDatos = { leer, useTabla, esProductoDerechos, esElementoDerechos, DERECHOS_AREAS }; // Nombres históricos: las ventanas que ya los llaman siguen funcionando sin // tocarlas. Las ventanas dueñas (Canales, CRM, Productos) los redefinen cuando // están cargadas, con el mismo comportamiento. window.useCanalesDistribucion = () => useTabla("sc.canal_distribucion"); window.useElementos = () => useTabla("sc.elemento_venta"); window.esProductoDerechos = esProductoDerechos; window.esElementoDerechos = esElementoDerechos; window.DERECHOS_AREAS = DERECHOS_AREAS; })();