Configuración IA: añade condiciones de cobertura por compañía (palabra clave + texto)

This commit is contained in:
2026-08-28 20:54:25 +00:00
parent 07999f3218
commit 272994ea08

View File

@@ -243,6 +243,22 @@
<textarea id="ai_custom_prompt" rows="3" class="w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm p-2" placeholder="Escribe aquí las reglas personalizadas..."></textarea>
</div>
<div class="p-4 border-b border-slate-100 mb-2 bg-slate-50">
<label class="block text-sm font-medium text-gray-700">Condiciones de Cobertura por Compañía (Opcional)</label>
<p class="text-xs text-gray-500 mb-2">Cuando el cliente pregunte por costes, materiales o qué cubre el seguro, la IA usará el texto de la compañía que coincida con el expediente. La palabra clave se busca dentro del campo "Compañía" del expediente (sin importar mayúsculas ni el resto del texto alrededor).</p>
<div id="detectedCompaniesBox" class="hidden mb-3 p-3 bg-white border border-slate-200 rounded-lg">
<p class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-2">Compañías vistas en tus expedientes (pulsa para añadir)</p>
<div id="detectedCompaniesList" class="flex flex-wrap gap-1.5"></div>
</div>
<div id="coverageRulesList" class="space-y-3"></div>
<button type="button" onclick="addCoverageRule()" class="mt-2 text-xs font-bold text-blue-600 hover:text-blue-800 flex items-center gap-1">
<i data-lucide="plus-circle" class="w-4 h-4"></i> Añadir compañía
</button>
</div>
<div class="p-4 hover:bg-slate-50 transition-colors flex items-center justify-between border-b border-slate-100">
<div>
<p class="font-bold text-slate-700 text-sm">Modo "Escribiendo..."</p>
@@ -973,6 +989,7 @@
showTab('templates');
loadTemplates();
loadWaSettings();
loadDetectedCompanies();
});
// ==========================================
@@ -1170,6 +1187,9 @@
document.getElementById('ai_custom_prompt').value = s.ai_custom_prompt || "";
}
document.getElementById('coverageRulesList').innerHTML = "";
(s.coverage_rules || []).forEach(r => addCoverageRule(r.keyword, r.text));
document.getElementById('cfg_delay').checked = s.wa_delay_enabled !== false;
document.getElementById('cfg_evt_welcome').checked = s.wa_evt_welcome || false;
document.getElementById('cfg_evt_assigned').checked = s.wa_evt_assigned || false;
@@ -1180,10 +1200,62 @@
} catch(e) { console.error("Error cargando ajustes WA", e); }
}
// 🧾 Condiciones de cobertura por compañía: cada fila es { keyword, text }. La IA
// busca esta "keyword" (sin mayúsculas ni tildes) DENTRO del campo Compañía del
// expediente, así que da igual si viene envuelta en texto de Multiasistencia,
// HomeServe, etc. — con que contenga la palabra clave (ej. "santander") es suficiente.
function addCoverageRule(keyword = "", text = "") {
const wrap = document.createElement('div');
wrap.className = "coverage-rule-row bg-white border border-slate-200 rounded-lg p-3 space-y-2";
wrap.innerHTML = `
<div class="flex items-center gap-2">
<input type="text" class="cr-keyword flex-1 border-gray-300 rounded-md shadow-sm text-sm p-2 font-bold" placeholder="Palabra clave (ej: santander)">
<button type="button" onclick="this.closest('.coverage-rule-row').remove()" class="text-rose-500 hover:text-rose-700 p-1 shrink-0"><i data-lucide="trash-2" class="w-4 h-4"></i></button>
</div>
<textarea class="cr-text w-full border-gray-300 rounded-md shadow-sm text-xs p-2" rows="2" placeholder="Condiciones de cobertura (ej: Cubre hasta 30€ en materiales y 2h de mano de obra. A partir de ahí lo paga el cliente)"></textarea>
`;
document.getElementById('coverageRulesList').appendChild(wrap);
wrap.querySelector('.cr-keyword').value = keyword;
wrap.querySelector('.cr-text').value = text;
if (window.lucide) lucide.createIcons();
}
// Saca las compañías tal cual aparecen en tus expedientes recientes, para que
// puedas pulsarlas y usarlas como palabra clave sin tener que adivinar el formato.
async function loadDetectedCompanies() {
try {
const res = await fetch(`${API_URL}/services/active`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
const data = await res.json();
if (!data.ok) return;
const seen = new Set();
(data.services || []).forEach(s => {
const raw = s.raw_data || {};
const c = (raw["Compañía"] || raw["COMPAÑIA"] || "").toString().trim();
if (c) seen.add(c);
});
const box = document.getElementById('detectedCompaniesBox');
const list = document.getElementById('detectedCompaniesList');
if (seen.size === 0) { box.classList.add('hidden'); return; }
list.innerHTML = [...seen].sort().map(c => `
<button type="button" onclick='addCoverageRule(${JSON.stringify(c)})' class="text-[11px] font-bold bg-slate-100 hover:bg-blue-100 hover:text-blue-700 text-slate-600 px-2.5 py-1 rounded-lg transition-colors">${c}</button>
`).join('');
box.classList.remove('hidden');
if (window.lucide) lucide.createIcons();
} catch (e) { console.error("Error cargando compañías detectadas", e); }
}
async function saveWaSettings() {
const coverageRules = [...document.querySelectorAll('#coverageRulesList .coverage-rule-row')]
.map(row => ({
keyword: row.querySelector('.cr-keyword').value.trim(),
text: row.querySelector('.cr-text').value.trim()
}))
.filter(r => r.keyword && r.text);
const settings = {
wa_ai_enabled: document.getElementById('cfg_ai_enabled').checked,
ai_custom_prompt: document.getElementById('ai_custom_prompt') ? document.getElementById('ai_custom_prompt').value : "",
coverage_rules: coverageRules,
wa_delay_enabled: document.getElementById('cfg_delay').checked,
wa_evt_welcome: document.getElementById('cfg_evt_welcome').checked,
wa_evt_assigned: document.getElementById('cfg_evt_assigned').checked,