zenit-sdk 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  sendMessageStream,
38
38
  useSendMessage,
39
39
  useSendMessageStream
40
- } from "./chunk-3M57OBM6.mjs";
40
+ } from "./chunk-TH7D3ECH.mjs";
41
41
 
42
42
  // src/http/HttpClient.ts
43
43
  var HttpClient = class {
@@ -691,49 +691,146 @@ function useGeolocation(options) {
691
691
  var import_leaflet2 = __toESM(require("leaflet"));
692
692
 
693
693
  // src/config/modalWhitelist.ts
694
- var SECTOR_MODAL_WHITELIST = [
695
- { key: "Sector", label: "Sector" },
696
- { key: "Promotor", label: "Promotor" },
697
- { key: "Capital Total", label: "Capital Total" },
698
- { key: "Total Capital Mora", label: "Capital en Mora" },
699
- { key: "Tendencia Mora", label: "Tendencia de Mora", hint: "trend_icon" },
700
- { key: "Tendencia Capital", label: "Tendencia de Capital", hint: "trend_icon" },
701
- { key: "Tendencia Castigos", label: "Tendencia de Castigos", hint: "trend_icon" },
702
- { key: "Impacto Sector", label: "Impacto del Sector" },
703
- { key: "Total Clientes Sector", label: "Total de Clientes" },
704
- { key: "Total Clientes Sanos", label: "Clientes Sanos" },
705
- { key: "Total Clientes Morosos", label: "Clientes en Mora" },
706
- { key: "Total Clientes Castigados", label: "Clientes Castigados" },
707
- { key: "Total Clientes Nuevos", label: "Clientes Nuevos" },
708
- { key: "Total Clientes Salidos", label: "Clientes Salidos" },
709
- { key: "Insights", label: "An\xE1lisis IA", hint: "collapsible" },
710
- { key: "Recomendaciones", label: "Recomendaciones IA", hint: "collapsible" }
711
- ];
694
+ function normalizeKey(value) {
695
+ return value.normalize("NFD").replace(/\p{Diacritic}/gu, "").replace(/[_\s-]+/g, "").toLowerCase().trim();
696
+ }
712
697
  var CLIENTE_MODAL_WHITELIST = [
713
- { key: "nombre del cliente", label: "Nombre del Cliente" },
714
- { key: "dpi", label: "DPI" },
715
- { key: "kpi", label: "Estado", hint: "kpi_badge" },
716
- { key: "tel principal", label: "Tel\xE9fono", hint: "phone_link" },
717
- { key: "capital concedido", label: "Capital Concedido" },
718
- { key: "mora", label: "Monto en Mora", hint: "mora_alert" },
719
- { key: "etapa", label: "Etapa del Cr\xE9dito" },
720
- { key: "prestamo", label: "No. de Pr\xE9stamo" },
721
- { key: "sucursal", label: "Sucursal", aliases: ["nombre sucursal"] }
698
+ {
699
+ id: "nombre_cliente",
700
+ label: "Nombre del Cliente",
701
+ aliases: ["nombre_del_cliente", "nombre cliente", "nombre_del_cliente ", "NOMBRE_CLIENTE"]
702
+ },
703
+ {
704
+ id: "dpi",
705
+ label: "DPI",
706
+ aliases: ["dpi", "DPI"]
707
+ },
708
+ {
709
+ id: "kpi",
710
+ label: "Estado",
711
+ aliases: ["kpi", "KPI"],
712
+ hint: "kpi_badge"
713
+ },
714
+ {
715
+ id: "tel_principal",
716
+ label: "Tel\xE9fono",
717
+ aliases: ["tel_principal", "tel principal", "telefono", "telefono_principal", "TEL_PRINCIPAL"],
718
+ hint: "phone_link"
719
+ },
720
+ {
721
+ id: "capital_concedido",
722
+ label: "Capital Concedido",
723
+ aliases: ["capital_concedido", "capital concedido", "CAPITAL_CONCEDIDO"]
724
+ },
725
+ {
726
+ id: "mora",
727
+ label: "Monto en Mora",
728
+ aliases: ["mora", "MORA"],
729
+ hint: "mora_alert"
730
+ },
731
+ {
732
+ id: "etapa",
733
+ label: "Etapa del Cr\xE9dito",
734
+ aliases: ["etapa", "ETAPA"]
735
+ },
736
+ {
737
+ id: "prestamo",
738
+ label: "No. de Pr\xE9stamo",
739
+ aliases: ["prestamo", "prestamo_id", "no_prestamo", "numero_prestamo", "PRESTAMO"]
740
+ },
741
+ {
742
+ id: "sucursal",
743
+ label: "Sucursal",
744
+ aliases: ["sucursal", "nombre_sucursal", "nombre sucursal", "SUCURSAL"]
745
+ }
746
+ ];
747
+ var SECTOR_MODAL_WHITELIST = [
748
+ { id: "sector", label: "Sector", aliases: ["nom_sector", "NOM_SECTOR", "sector", "SECTOR"] },
749
+ { id: "promotor", label: "Promotor", aliases: ["promotor", "PROMOTOR"] },
750
+ { id: "capital_total", label: "Capital Total", aliases: ["capital_total", "capital total", "CAPITAL_TOTAL"] },
751
+ {
752
+ id: "total_capital_mora",
753
+ label: "Total Capital Mora",
754
+ aliases: ["total_capital_mora", "total capital mora", "TOTAL_CAPITAL_MORA"]
755
+ },
756
+ {
757
+ id: "tendencia_mora",
758
+ label: "Tendencia Mora",
759
+ aliases: ["tendencia_mora", "tendencia mora", "TENDENCIA_MORA"],
760
+ hint: "trend_icon"
761
+ },
762
+ {
763
+ id: "tendencia_capital",
764
+ label: "Tendencia Capital",
765
+ aliases: ["tendencia_capital", "tendencia capital", "TENDENCIA_CAPITAL"],
766
+ hint: "trend_icon"
767
+ },
768
+ {
769
+ id: "tendencia_castigos",
770
+ label: "Tendencia Castigos",
771
+ aliases: ["tendencia_castigos", "tendencia castigos", "TENDENCIA_CASTIGOS"],
772
+ hint: "trend_icon"
773
+ },
774
+ {
775
+ id: "impacto_sector",
776
+ label: "Impacto Sector",
777
+ aliases: ["impacto_sector", "impacto sector", "IMPACTO_SECTOR"]
778
+ },
779
+ {
780
+ id: "total_clientes_sector",
781
+ label: "Total Clientes Sector",
782
+ aliases: ["total_clientes_sector", "total clientes sector", "TOTAL_CLIENTES_SECTOR"]
783
+ },
784
+ {
785
+ id: "total_clientes_sanos",
786
+ label: "Total Clientes Sanos",
787
+ aliases: ["total_clientes_sanos", "total clientes sanos", "TOTAL_CLIENTES_SANOS"]
788
+ },
789
+ {
790
+ id: "total_clientes_morosos",
791
+ label: "Total Clientes Morosos",
792
+ aliases: ["total_clientes_morosos", "total clientes morosos", "TOTAL_CLIENTES_MOROSOS"]
793
+ },
794
+ {
795
+ id: "total_clientes_castigados",
796
+ label: "Total Clientes Castigados",
797
+ aliases: ["total_clientes_castigados", "total clientes castigados", "TOTAL_CLIENTES_CASTIGADOS"]
798
+ },
799
+ {
800
+ id: "total_clientes_nuevos",
801
+ label: "Total Clientes Nuevos",
802
+ aliases: ["total_clientes_nuevos", "total clientes nuevos", "TOTAL_CLIENTES_NUEVOS"]
803
+ },
804
+ {
805
+ id: "total_clientes_salidos",
806
+ label: "Total Clientes Salidos",
807
+ aliases: ["total_clientes_salidos", "total clientes salidos", "TOTAL_CLIENTES_SALIDOS"]
808
+ },
809
+ { id: "insights", label: "Insights", aliases: ["insights", "INSIGHTS"], hint: "collapsible" },
810
+ {
811
+ id: "recomendaciones",
812
+ label: "Recomendaciones",
813
+ aliases: ["recomendaciones", "RECOMENDACIONES"],
814
+ hint: "collapsible"
815
+ }
722
816
  ];
723
817
  function applyModalWhitelist(rawData, whitelist) {
724
- const keys = Object.keys(rawData ?? {});
725
- return whitelist.map(({ key, label, hint, aliases = [] }) => {
726
- const keysToTry = [key, ...aliases];
727
- let value = void 0;
728
- for (const k of keysToTry) {
729
- const match = keys.find((rawKey) => rawKey.toLowerCase() === k.toLowerCase());
730
- if (match !== void 0 && rawData[match] !== null && rawData[match] !== void 0) {
731
- value = rawData[match];
732
- break;
733
- }
818
+ const keyByNormalized = /* @__PURE__ */ new Map();
819
+ Object.keys(rawData ?? {}).forEach((rawKey) => {
820
+ const normalized = normalizeKey(rawKey);
821
+ if (!normalized || keyByNormalized.has(normalized)) return;
822
+ keyByNormalized.set(normalized, rawKey);
823
+ });
824
+ return whitelist.map(({ id, label, hint, aliases }) => {
825
+ const candidates = [...aliases, id];
826
+ for (const candidate of candidates) {
827
+ const matchedKey = keyByNormalized.get(normalizeKey(candidate));
828
+ if (!matchedKey) continue;
829
+ const value = rawData[matchedKey];
830
+ if (value === null || value === void 0) continue;
831
+ return { id, label, value, hint: hint ?? null, matchedKey };
734
832
  }
735
- if (value === void 0) return null;
736
- return { label, value, hint: hint ?? null };
833
+ return null;
737
834
  }).filter((entry) => Boolean(entry));
738
835
  }
739
836
 
@@ -974,10 +1071,6 @@ function shouldIncludePopupEntry(key, value) {
974
1071
  return true;
975
1072
  }
976
1073
  function createPopupContent(properties) {
977
- const whitelistedRows = buildWhitelistedRows(properties);
978
- if (whitelistedRows) {
979
- return whitelistedRows;
980
- }
981
1074
  const header = findHeaderProperties(properties);
982
1075
  const headerText = header.title?.value ?? extractPopupHeader(properties);
983
1076
  const usedKeys = new Set([header.title?.key, header.badge?.key, header.description?.key].filter(Boolean));
@@ -1001,6 +1094,10 @@ function createPopupContent(properties) {
1001
1094
  const descriptionHtml = header.description ? `<div style="margin-bottom:10px; padding:8px 10px; background:#f8fafc; border-left:3px solid #38bdf8; border-radius:6px; color:#334155; font-size:12px;">${escapeHtml(
1002
1095
  header.description.value
1003
1096
  )}</div>` : "";
1097
+ const whitelistedRows = buildWhitelistedRows(properties, { colorBar, headerHtml, descriptionHtml });
1098
+ if (whitelistedRows) {
1099
+ return whitelistedRows;
1100
+ }
1004
1101
  const rowsHtml = entries.map(([key, value]) => {
1005
1102
  const label = escapeHtml(formatLabel(key));
1006
1103
  const normalizedKey = key.trim().toLowerCase();
@@ -1017,13 +1114,37 @@ function createPopupContent(properties) {
1017
1114
  }).join("");
1018
1115
  return `<div>${colorBar}${headerHtml}${descriptionHtml}${rowsHtml}</div>`;
1019
1116
  }
1020
- function buildWhitelistedRows(properties) {
1021
- const whitelist = selectModalWhitelist(properties);
1022
- if (!whitelist) return null;
1117
+ function buildWhitelistedRows(properties, headerSections) {
1118
+ const selection = selectModalWhitelist(properties);
1119
+ if (!selection) {
1120
+ logModalWhitelistDebug({
1121
+ modalType: "generic",
1122
+ properties,
1123
+ entries: [],
1124
+ whitelist: null,
1125
+ fallbackToGeneric: true
1126
+ });
1127
+ return null;
1128
+ }
1129
+ const { whitelist, modalType } = selection;
1023
1130
  const entries = applyModalWhitelist(properties, whitelist);
1024
1131
  if (entries.length === 0) {
1025
- return '<div style="padding:8px 0; color:#64748b; text-align:center;">Sin datos disponibles</div>';
1132
+ logModalWhitelistDebug({
1133
+ modalType,
1134
+ properties,
1135
+ entries,
1136
+ whitelist,
1137
+ fallbackToGeneric: true
1138
+ });
1139
+ return null;
1026
1140
  }
1141
+ logModalWhitelistDebug({
1142
+ modalType,
1143
+ properties,
1144
+ entries,
1145
+ whitelist,
1146
+ fallbackToGeneric: false
1147
+ });
1027
1148
  const rowsHtml = entries.map(({ label, value }) => {
1028
1149
  const valueHtml = renderPopupValue(value);
1029
1150
  return `
@@ -1033,20 +1154,33 @@ function buildWhitelistedRows(properties) {
1033
1154
  </div>
1034
1155
  `;
1035
1156
  }).join("");
1036
- return `<div>${rowsHtml}</div>`;
1157
+ return `<div>${headerSections.colorBar}${headerSections.headerHtml}${headerSections.descriptionHtml}${rowsHtml}</div>`;
1037
1158
  }
1038
- function countWhitelistMatches(properties, whitelist) {
1039
- const keys = Object.keys(properties).map((key) => key.toLowerCase());
1040
- return whitelist.reduce((count, item) => {
1041
- const candidates = [item.key, ...item.aliases ?? []].map((candidate) => candidate.toLowerCase());
1042
- return candidates.some((candidate) => keys.includes(candidate)) ? count + 1 : count;
1043
- }, 0);
1159
+ function hasAnyKey(properties, candidates) {
1160
+ const normalizedKeys = new Set(Object.keys(properties).map((key) => normalizeKey(key)));
1161
+ return candidates.some((candidate) => normalizedKeys.has(normalizeKey(candidate)));
1044
1162
  }
1045
1163
  function selectModalWhitelist(properties) {
1046
- const sectorMatches = countWhitelistMatches(properties, SECTOR_MODAL_WHITELIST);
1047
- const clienteMatches = countWhitelistMatches(properties, CLIENTE_MODAL_WHITELIST);
1048
- if (sectorMatches === 0 && clienteMatches === 0) return null;
1049
- return sectorMatches >= clienteMatches ? SECTOR_MODAL_WHITELIST : CLIENTE_MODAL_WHITELIST;
1164
+ if (hasAnyKey(properties, ["nombre_del_cliente", "dpi", "capital_concedido", "kpi"])) {
1165
+ return { modalType: "cliente", whitelist: CLIENTE_MODAL_WHITELIST };
1166
+ }
1167
+ if (hasAnyKey(properties, ["nom_sector", "NOM_SECTOR", "total_clientes_sector", "capital_total", "impacto_sector"])) {
1168
+ return { modalType: "sector", whitelist: SECTOR_MODAL_WHITELIST };
1169
+ }
1170
+ return null;
1171
+ }
1172
+ function logModalWhitelistDebug(options) {
1173
+ if (process.env.NODE_ENV === "production") return;
1174
+ const { modalType, properties, entries, whitelist, fallbackToGeneric } = options;
1175
+ const matchedIds = new Set(entries.map((entry) => entry.id));
1176
+ const missingFields = (whitelist ?? []).filter((item) => !matchedIds.has(item.id)).map((item) => item.id);
1177
+ console.info("[modal-whitelist]", {
1178
+ modalType,
1179
+ keys: Object.keys(properties),
1180
+ matchedFields: entries.map((entry) => ({ id: entry.id, matchedKey: entry.matchedKey })),
1181
+ missingFields,
1182
+ fallbackToGeneric
1183
+ });
1050
1184
  }
1051
1185
  function isPolygonType(layerType, geometryType) {
1052
1186
  const candidate = (layerType ?? geometryType ?? "").toLowerCase();