Actualizar configuracion.html

This commit is contained in:
2026-02-20 22:09:12 +00:00
parent ee6369001c
commit 283bc1e3c0

View File

@@ -59,6 +59,7 @@
<div class="p-4 bg-gray-50 border-b border-gray-200 font-bold text-gray-700 text-sm uppercase tracking-wide">Tipos de Mensaje</div> <div class="p-4 bg-gray-50 border-b border-gray-200 font-bold text-gray-700 text-sm uppercase tracking-wide">Tipos de Mensaje</div>
<div class="flex-1 overflow-y-auto p-2 space-y-1"> <div class="flex-1 overflow-y-auto p-2 space-y-1">
<button onclick="selectTemplate('welcome', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-blue-100 text-blue-600 p-1.5 rounded-md group-hover:bg-blue-200 transition"><i data-lucide="hand" class="w-4 h-4"></i></span> Bienvenida / Alta</button> <button onclick="selectTemplate('welcome', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-blue-100 text-blue-600 p-1.5 rounded-md group-hover:bg-blue-200 transition"><i data-lucide="hand" class="w-4 h-4"></i></span> Bienvenida / Alta</button>
<button onclick="selectTemplate('assigned', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-orange-100 text-orange-600 p-1.5 rounded-md group-hover:bg-orange-200 transition"><i data-lucide="user-check" class="w-4 h-4"></i></span> Asignado a Operario</button>
<button onclick="selectTemplate('no_contact', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-orange-100 text-orange-600 p-1.5 rounded-md group-hover:bg-orange-200 transition"><i data-lucide="phone-off" class="w-4 h-4"></i></span> Cliente No Localizado</button> <button onclick="selectTemplate('no_contact', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-orange-100 text-orange-600 p-1.5 rounded-md group-hover:bg-orange-200 transition"><i data-lucide="phone-off" class="w-4 h-4"></i></span> Cliente No Localizado</button>
<button onclick="selectTemplate('appointment', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-green-100 text-green-600 p-1.5 rounded-md group-hover:bg-green-200 transition"><i data-lucide="calendar-check" class="w-4 h-4"></i></span> Cita Creada</button> <button onclick="selectTemplate('appointment', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-green-100 text-green-600 p-1.5 rounded-md group-hover:bg-green-200 transition"><i data-lucide="calendar-check" class="w-4 h-4"></i></span> Cita Creada</button>
<button onclick="selectTemplate('update', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-purple-100 text-purple-600 p-1.5 rounded-md group-hover:bg-purple-200 transition"><i data-lucide="refresh-cw" class="w-4 h-4"></i></span> Modificación de Servicio</button> <button onclick="selectTemplate('update', this)" class="tpl-btn w-full text-left p-3 rounded-lg hover:bg-blue-50 text-sm font-medium text-gray-600 transition-colors flex items-center gap-3 group"><span class="bg-purple-100 text-purple-600 p-1.5 rounded-md group-hover:bg-purple-200 transition"><i data-lucide="refresh-cw" class="w-4 h-4"></i></span> Modificación de Servicio</button>
@@ -79,6 +80,7 @@
<button onclick="insertVar('{{HORA}}')" class="var-btn">{{HORA}}</button> <button onclick="insertVar('{{HORA}}')" class="var-btn">{{HORA}}</button>
<button onclick="insertVar('{{COMPANIA}}')" class="var-btn">{{COMPANIA}}</button> <button onclick="insertVar('{{COMPANIA}}')" class="var-btn">{{COMPANIA}}</button>
<button onclick="insertVar('{{REFERENCIA}}')" class="var-btn">{{REFERENCIA}}</button> <button onclick="insertVar('{{REFERENCIA}}')" class="var-btn">{{REFERENCIA}}</button>
<button onclick="insertVar('{{ENLACE}}')" class="var-btn text-purple-600 border-purple-200 hover:border-purple-400 bg-purple-50">{{ENLACE}}</button>
</div> </div>
<textarea id="tplContent" class="flex-1 p-6 outline-none resize-none text-sm leading-relaxed text-gray-700 font-sans" placeholder="Selecciona un tipo de mensaje a la izquierda..."></textarea> <textarea id="tplContent" class="flex-1 p-6 outline-none resize-none text-sm leading-relaxed text-gray-700 font-sans" placeholder="Selecciona un tipo de mensaje a la izquierda..."></textarea>
</div> </div>
@@ -149,6 +151,20 @@
</div> </div>
</div> </div>
<div class="p-4 hover:bg-slate-50 transition-colors flex items-center justify-between border-b border-slate-100">
<div class="flex items-start gap-3">
<div class="bg-orange-100 p-2 rounded-lg text-orange-600 mt-0.5"><i data-lucide="user-check" class="w-4 h-4"></i></div>
<div>
<p class="font-bold text-slate-700 text-sm">Asignado a Operario</p>
<p class="text-xs text-slate-400 mt-0.5">Se envía cuando asignas un técnico al servicio.</p>
</div>
</div>
<div class="relative inline-block w-12 align-middle select-none">
<input type="checkbox" id="cfg_evt_assigned" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
<label for="cfg_evt_assigned" class="toggle-label block overflow-hidden h-6 rounded-full bg-slate-200 cursor-pointer"></label>
</div>
</div>
<div class="p-4 hover:bg-slate-50 transition-colors flex items-center justify-between border-b border-slate-100"> <div class="p-4 hover:bg-slate-50 transition-colors flex items-center justify-between border-b border-slate-100">
<div class="flex items-start gap-3"> <div class="flex items-start gap-3">
<div class="bg-purple-100 p-2 rounded-lg text-purple-600 mt-0.5"><i data-lucide="calendar-clock" class="w-4 h-4"></i></div> <div class="bg-purple-100 p-2 rounded-lg text-purple-600 mt-0.5"><i data-lucide="calendar-clock" class="w-4 h-4"></i></div>
@@ -468,22 +484,17 @@
} }
} }
// ==========================================
// RESTO DE FUNCIONES (INTACTAS)
// ==========================================
async function loadWaSettings() { async function loadWaSettings() {
try { try {
// 1. Pedimos al servidor cómo están los botones (ON/OFF)
const res = await fetch(`${API_URL}/whatsapp/settings`, { const res = await fetch(`${API_URL}/whatsapp/settings`, {
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
}); });
const data = await res.json(); const data = await res.json();
const s = data.settings || {}; const s = data.settings || {};
// 2. Colocamos los interruptores según lo que diga la base de datos document.getElementById('cfg_delay').checked = s.wa_delay_enabled !== false;
document.getElementById('cfg_delay').checked = s.wa_delay_enabled !== false; // Por defecto ON
document.getElementById('cfg_evt_welcome').checked = s.wa_evt_welcome || false; document.getElementById('cfg_evt_welcome').checked = s.wa_evt_welcome || false;
document.getElementById('cfg_evt_assigned').checked = s.wa_evt_assigned || false; // NUEVO
document.getElementById('cfg_evt_date').checked = s.wa_evt_date || false; document.getElementById('cfg_evt_date').checked = s.wa_evt_date || false;
document.getElementById('cfg_evt_onway').checked = s.wa_evt_onway || false; document.getElementById('cfg_evt_onway').checked = s.wa_evt_onway || false;
document.getElementById('cfg_evt_finished').checked = s.wa_evt_finished || false; document.getElementById('cfg_evt_finished').checked = s.wa_evt_finished || false;
@@ -492,17 +503,16 @@
} }
async function saveWaSettings() { async function saveWaSettings() {
// 1. Leemos cómo has dejado los botones en la pantalla
const settings = { const settings = {
wa_delay_enabled: document.getElementById('cfg_delay').checked, wa_delay_enabled: document.getElementById('cfg_delay').checked,
wa_evt_welcome: document.getElementById('cfg_evt_welcome').checked, wa_evt_welcome: document.getElementById('cfg_evt_welcome').checked,
wa_evt_assigned: document.getElementById('cfg_evt_assigned').checked, // NUEVO
wa_evt_date: document.getElementById('cfg_evt_date').checked, wa_evt_date: document.getElementById('cfg_evt_date').checked,
wa_evt_onway: document.getElementById('cfg_evt_onway').checked, wa_evt_onway: document.getElementById('cfg_evt_onway').checked,
wa_evt_finished: document.getElementById('cfg_evt_finished').checked, wa_evt_finished: document.getElementById('cfg_evt_finished').checked,
wa_evt_survey: document.getElementById('cfg_evt_survey').checked wa_evt_survey: document.getElementById('cfg_evt_survey').checked
}; };
// 2. Se lo enviamos al servidor para que lo guarde en la base de datos
try { try {
const res = await fetch(`${API_URL}/whatsapp/settings`, { const res = await fetch(`${API_URL}/whatsapp/settings`, {
method: 'POST', method: 'POST',
@@ -574,19 +584,31 @@
} }
} catch(e) { console.error("Error templates"); } } catch(e) { console.error("Error templates"); }
} }
function selectTemplate(type, btn) { function selectTemplate(type, btn) {
currentTemplateType = type; currentTemplateType = type;
document.querySelectorAll('.tpl-btn').forEach(b => { document.querySelectorAll('.tpl-btn').forEach(b => {
b.classList.remove('bg-blue-50', 'ring-1', 'ring-blue-200'); b.classList.remove('bg-blue-50', 'ring-1', 'ring-blue-200');
b.querySelector('span').classList.replace('bg-blue-600', 'bg-blue-100'); b.querySelector('span').classList.replace('bg-blue-600', 'bg-blue-100');
b.querySelector('span').classList.replace('text-white', 'text-blue-600'); b.querySelector('span').classList.replace('text-white', 'text-blue-600');
if (b.querySelector('span').classList.contains('bg-orange-600')) {
b.querySelector('span').classList.replace('bg-orange-600', 'bg-orange-100');
b.querySelector('span').classList.replace('text-white', 'text-orange-600');
}
}); });
btn.classList.add('bg-blue-50', 'ring-1', 'ring-blue-200'); btn.classList.add('bg-blue-50', 'ring-1', 'ring-blue-200');
btn.querySelector('span').classList.replace('bg-blue-100', 'bg-blue-600'); const span = btn.querySelector('span');
btn.querySelector('span').classList.replace('text-blue-600', 'text-white'); if (span.classList.contains('bg-blue-100')) {
span.classList.replace('bg-blue-100', 'bg-blue-600');
span.classList.replace('text-blue-600', 'text-white');
} else if (span.classList.contains('bg-orange-100')) {
span.classList.replace('bg-orange-100', 'bg-orange-600');
span.classList.replace('text-orange-600', 'text-white');
}
document.getElementById('editorTitle').innerText = btn.innerText.trim(); document.getElementById('editorTitle').innerText = btn.innerText.trim();
document.getElementById('tplContent').value = cachedTemplates[type] || ""; document.getElementById('tplContent').value = cachedTemplates[type] || "";
} }
function insertVar(text) { function insertVar(text) {
const textarea = document.getElementById('tplContent'); const textarea = document.getElementById('tplContent');
if (!textarea) return; if (!textarea) return;
@@ -597,6 +619,7 @@
textarea.focus(); textarea.focus();
textarea.selectionStart = textarea.selectionEnd = start + text.length; textarea.selectionStart = textarea.selectionEnd = start + text.length;
} }
async function saveTemplate() { async function saveTemplate() {
if(!currentTemplateType) { showToast("Selecciona plantilla", true); return; } if(!currentTemplateType) { showToast("Selecciona plantilla", true); return; }
const content = document.getElementById('tplContent').value; const content = document.getElementById('tplContent').value;
@@ -626,6 +649,7 @@
lucide.createIcons(); lucide.createIcons();
} catch(e) { list.innerHTML = '<p class="text-red-500 text-xs text-center">Error</p>'; } } catch(e) { list.innerHTML = '<p class="text-red-500 text-xs text-center">Error</p>'; }
} }
async function addCompany() { async function addCompany() {
const input = document.getElementById('newCompanyInput'); const input = document.getElementById('newCompanyInput');
const name = input.value.trim(); const name = input.value.trim();
@@ -635,15 +659,13 @@
if(res.ok) { showToast("Añadido"); input.value = ""; loadCompanies(); } if(res.ok) { showToast("Añadido"); input.value = ""; loadCompanies(); }
} catch(e) { showToast("Error", true); } } catch(e) { showToast("Error", true); }
} }
async function deleteCompany(id) { async function deleteCompany(id) {
if(!confirm("¿Borrar?")) return; if(!confirm("¿Borrar?")) return;
await fetch(`${API_URL}/companies/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); await fetch(`${API_URL}/companies/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
loadCompanies(); loadCompanies();
} }
// ==========================================
// CARGA DE ESTADOS Y GESTIÓN DE SEGURIDAD
// ==========================================
async function loadStatusesConfig() { async function loadStatusesConfig() {
const list = document.getElementById('listStatuses'); const list = document.getElementById('listStatuses');
list.innerHTML = '<p class="text-center text-xs text-gray-400 mt-10">Cargando...</p>'; list.innerHTML = '<p class="text-center text-xs text-gray-400 mt-10">Cargando...</p>';
@@ -654,8 +676,6 @@
data.statuses.forEach(s => { data.statuses.forEach(s => {
const div = document.createElement('div'); const div = document.createElement('div');
div.className = "p-3 border border-gray-100 rounded-lg bg-gray-50 flex justify-between items-center group hover:border-blue-200 transition-colors"; div.className = "p-3 border border-gray-100 rounded-lg bg-gray-50 flex justify-between items-center group hover:border-blue-200 transition-colors";
// SI ES DEL SISTEMA, PONEMOS UN CANDADO. SI NO, LA PAPELERA.
const actionBtn = s.is_system const actionBtn = s.is_system
? `<i data-lucide="lock" class="w-4 h-4 text-slate-300" title="Estado del sistema (Imborrable)"></i>` ? `<i data-lucide="lock" class="w-4 h-4 text-slate-300" title="Estado del sistema (Imborrable)"></i>`
: `<button onclick="deleteStatus(${s.id})" class="text-gray-300 hover:text-red-500"><i data-lucide="trash-2" class="w-4 h-4"></i></button>`; : `<button onclick="deleteStatus(${s.id})" class="text-gray-300 hover:text-red-500"><i data-lucide="trash-2" class="w-4 h-4"></i></button>`;
@@ -698,14 +718,12 @@
} catch(e) { showToast("Error de conexión", true); } } catch(e) { showToast("Error de conexión", true); }
} }
function showToast(msg, isError = false) { function showToast(msg, isError = false) {
const t = document.getElementById('toast'), m = document.getElementById('toastMsg'); const t = document.getElementById('toast'), m = document.getElementById('toastMsg');
t.className = `fixed bottom-5 right-5 px-6 py-3 rounded-lg shadow-xl transition-all duration-300 z-50 flex items-center gap-3 ${isError ? 'bg-red-600' : 'bg-slate-800'} text-white font-medium`; t.className = `fixed bottom-5 right-5 px-6 py-3 rounded-lg shadow-xl transition-all duration-300 z-50 flex items-center gap-3 ${isError ? 'bg-red-600' : 'bg-slate-800'} text-white font-medium`;
m.innerText = msg; t.classList.remove('translate-y-20', 'opacity-0'); m.innerText = msg; t.classList.remove('translate-y-20', 'opacity-0');
setTimeout(() => t.classList.add('translate-y-20', 'opacity-0'), 3000); setTimeout(() => t.classList.add('translate-y-20', 'opacity-0'), 3000);
} }
</script> </script>
</body> </body>
</html> </html>