Actualizar configuracion.html
This commit is contained in:
@@ -83,39 +83,130 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="view-whatsapp" class="tab-content hidden h-full fade-in">
|
<div id="view-whatsapp" class="tab-content hidden h-full fade-in overflow-y-auto scroller pb-10">
|
||||||
<div class="max-w-2xl mx-auto mt-10">
|
<div class="max-w-5xl mx-auto mt-6">
|
||||||
<div class="bg-white rounded-xl shadow-lg border border-gray-100 p-8 flex flex-col items-center text-center">
|
<div class="mb-8">
|
||||||
<div class="w-16 h-16 bg-blue-50 rounded-full flex items-center justify-center mb-6">
|
<h2 class="text-2xl font-black text-slate-800 tracking-tight flex items-center gap-3">
|
||||||
<i data-lucide="smartphone" class="w-8 h-8 text-blue-600"></i>
|
<span class="bg-green-100 p-2.5 rounded-xl text-green-600 shadow-sm"><i data-lucide="message-circle"></i></span>
|
||||||
</div>
|
Centro de Notificaciones Automáticas
|
||||||
<h2 class="text-2xl font-bold text-gray-800 mb-2">Conexión con WhatsApp</h2>
|
</h2>
|
||||||
<p class="text-gray-500 mb-8 max-w-md">Escanea el código QR para vincular tu número de empresa.</p>
|
<p class="text-sm text-slate-500 mt-2 font-medium">Vincula tu número y decide qué eventos disparan un mensaje al cliente.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||||
|
|
||||||
|
<div class="bg-white rounded-3xl shadow-sm border border-slate-100 p-8 flex flex-col h-fit">
|
||||||
|
<h3 class="text-lg font-bold text-slate-800 border-b border-slate-100 pb-4 mb-6 flex items-center gap-2">
|
||||||
|
<i data-lucide="smartphone" class="w-5 h-5 text-blue-600"></i> Estado del Dispositivo
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div id="waStatusContainer" class="w-full flex flex-col items-center justify-center min-h-[200px] bg-slate-50 rounded-2xl border-2 border-dashed border-slate-200 p-6 mb-6">
|
||||||
|
<div class="animate-pulse flex flex-col items-center">
|
||||||
|
<div class="w-10 h-10 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin mb-4"></div>
|
||||||
|
<span class="text-sm font-bold text-slate-400">Iniciando instancia...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onclick="checkWhatsappStatus()" class="w-full bg-slate-800 hover:bg-slate-700 text-white font-bold py-3 px-6 rounded-xl transition shadow-md flex items-center justify-center gap-2">
|
||||||
|
<i data-lucide="refresh-cw" class="w-4 h-4"></i> Actualizar Estado de Conexión
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white rounded-3xl shadow-sm border border-slate-100 overflow-hidden flex flex-col h-fit">
|
||||||
|
<div class="p-6 border-b border-slate-100 bg-slate-50/50 flex justify-between items-center">
|
||||||
|
<h3 class="text-lg font-bold text-slate-800 flex items-center gap-2">
|
||||||
|
<i data-lucide="zap" class="w-5 h-5 text-amber-500"></i> Reglas de Envío
|
||||||
|
</h3>
|
||||||
|
<button onclick="saveWaSettings()" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-xs font-bold shadow-md transition-all active:scale-95 flex items-center gap-2">
|
||||||
|
<i data-lucide="save" class="w-3.5 h-3.5"></i> Guardar Ajustes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-2">
|
||||||
|
<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>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Añade un retraso natural antes de enviar.</p>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_delay" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_delay" 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="flex items-start gap-3">
|
||||||
|
<div class="bg-blue-100 p-2 rounded-lg text-blue-600 mt-0.5"><i data-lucide="user-plus" class="w-4 h-4"></i></div>
|
||||||
|
<div>
|
||||||
|
<p class="font-bold text-slate-700 text-sm">Mensaje de Bienvenida</p>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Al registrar el servicio en el sistema.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_evt_welcome" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_evt_welcome" 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="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>
|
||||||
|
<p class="font-bold text-slate-700 text-sm">Cambio de Cita</p>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Cuando se agenda o modifica la fecha de visita.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_evt_date" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_evt_date" 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="flex items-start gap-3">
|
||||||
|
<div class="bg-amber-100 p-2 rounded-lg text-amber-600 mt-0.5"><i data-lucide="car" class="w-4 h-4"></i></div>
|
||||||
|
<div>
|
||||||
|
<p class="font-bold text-slate-700 text-sm">Técnico de Camino</p>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Avisa al cliente minutos antes de llegar.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_evt_onway" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_evt_onway" 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="flex items-start gap-3">
|
||||||
|
<div class="bg-emerald-100 p-2 rounded-lg text-emerald-600 mt-0.5"><i data-lucide="check-circle" class="w-4 h-4"></i></div>
|
||||||
|
<div>
|
||||||
|
<p class="font-bold text-slate-700 text-sm">Servicio Finalizado</p>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Notifica el cierre de la avería.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_evt_finished" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_evt_finished" 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">
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<div class="bg-rose-100 p-2 rounded-lg text-rose-600 mt-0.5"><i data-lucide="star" class="w-4 h-4"></i></div>
|
||||||
|
<div>
|
||||||
|
<p class="font-bold text-slate-700 text-sm">Encuesta de Calidad</p>
|
||||||
|
<p class="text-xs text-slate-400 mt-0.5">Se envía automáticamente tras finalizar.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="relative inline-block w-12 align-middle select-none">
|
||||||
|
<input type="checkbox" id="cfg_evt_survey" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
||||||
|
<label for="cfg_evt_survey" class="toggle-label block overflow-hidden h-6 rounded-full bg-slate-200 cursor-pointer"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="waStatusContainer" class="w-full flex flex-col items-center justify-center min-h-[250px] bg-gray-50 rounded-xl border-2 border-dashed border-gray-200 p-6 mb-6">
|
|
||||||
<div class="animate-pulse flex flex-col items-center">
|
|
||||||
<div class="w-10 h-10 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin mb-4"></div>
|
|
||||||
<span class="text-sm font-bold text-gray-400">Iniciando instancia segura...</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onclick="checkWhatsappStatus()" class="bg-slate-800 hover:bg-slate-700 text-white font-bold py-3 px-8 rounded-xl transition shadow-lg flex items-center gap-2 mb-8">
|
|
||||||
<i data-lucide="refresh-cw" class="w-4 h-4"></i> Actualizar Estado
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="w-full border-t border-gray-100 pt-6 mt-2 flex items-center justify-between px-4">
|
|
||||||
<div class="text-left">
|
|
||||||
<h4 class="font-bold text-gray-800 flex items-center gap-2">
|
|
||||||
<i data-lucide="bot" class="w-4 h-4 text-blue-600"></i> Modo "Escribiendo..."
|
|
||||||
</h4>
|
|
||||||
<p class="text-xs text-gray-500 mt-1 max-w-[250px]">Simula que un humano está tecleando el mensaje. Si lo desactivas, los mensajes llegarán de forma instantánea.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative inline-block w-12 mr-2 align-middle select-none transition duration-200 ease-in">
|
|
||||||
<input type="checkbox" name="toggle" id="waDelayToggle" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer"/>
|
|
||||||
<label for="waDelayToggle" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -224,18 +315,55 @@
|
|||||||
showTab('templates');
|
showTab('templates');
|
||||||
loadTemplates();
|
loadTemplates();
|
||||||
|
|
||||||
// Cargar preferencia de delay de WhatsApp
|
// Cargar configuración de eventos de WhatsApp al inicio
|
||||||
const toggle = document.getElementById('waDelayToggle');
|
loadWaSettings();
|
||||||
const savedSetting = localStorage.getItem('wa_delay_enabled');
|
|
||||||
// Por defecto activo si no hay ajuste guardado
|
|
||||||
toggle.checked = savedSetting === null ? true : savedSetting === 'true';
|
|
||||||
|
|
||||||
toggle.addEventListener('change', (e) => {
|
|
||||||
localStorage.setItem('wa_delay_enabled', e.target.checked);
|
|
||||||
showToast(`Modo "Escribiendo" ${e.target.checked ? 'Activado' : 'Desactivado'}`);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function loadWaSettings() {
|
||||||
|
// Lee del LocalStorage.
|
||||||
|
// TODO: En el futuro, cambiar esto por un fetch a la BD (ej. /config/whatsapp)
|
||||||
|
const getCfg = (key, defaultVal) => {
|
||||||
|
const val = localStorage.getItem(key);
|
||||||
|
return val === null ? defaultVal : val === 'true';
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('cfg_delay').checked = getCfg('wa_delay_enabled', true);
|
||||||
|
document.getElementById('cfg_evt_welcome').checked = getCfg('wa_evt_welcome', true);
|
||||||
|
document.getElementById('cfg_evt_date').checked = getCfg('wa_evt_date', true);
|
||||||
|
document.getElementById('cfg_evt_onway').checked = getCfg('wa_evt_onway', true);
|
||||||
|
document.getElementById('cfg_evt_finished').checked = getCfg('wa_evt_finished', false);
|
||||||
|
document.getElementById('cfg_evt_survey').checked = getCfg('wa_evt_survey', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveWaSettings() {
|
||||||
|
// Guarda los valores actuales de los switches
|
||||||
|
const settings = {
|
||||||
|
wa_delay_enabled: document.getElementById('cfg_delay').checked,
|
||||||
|
wa_evt_welcome: document.getElementById('cfg_evt_welcome').checked,
|
||||||
|
wa_evt_date: document.getElementById('cfg_evt_date').checked,
|
||||||
|
wa_evt_onway: document.getElementById('cfg_evt_onway').checked,
|
||||||
|
wa_evt_finished: document.getElementById('cfg_evt_finished').checked,
|
||||||
|
wa_evt_survey: document.getElementById('cfg_evt_survey').checked
|
||||||
|
};
|
||||||
|
|
||||||
|
// Guarda en LocalStorage
|
||||||
|
for (const [key, value] of Object.entries(settings)) {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Aquí pondrías la llamada al Backend para guardar en PostgreSQL
|
||||||
|
/*
|
||||||
|
await fetch(`${API_URL}/config/whatsapp`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` },
|
||||||
|
body: JSON.stringify(settings)
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
showToast("Ajustes de WhatsApp guardados");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function showTab(tabId) {
|
function showTab(tabId) {
|
||||||
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
|
document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden'));
|
||||||
document.getElementById(`view-${tabId}`).classList.remove('hidden');
|
document.getElementById(`view-${tabId}`).classList.remove('hidden');
|
||||||
@@ -298,7 +426,7 @@
|
|||||||
|
|
||||||
async function checkWhatsappStatus() {
|
async function checkWhatsappStatus() {
|
||||||
const container = document.getElementById('waStatusContainer');
|
const container = document.getElementById('waStatusContainer');
|
||||||
container.innerHTML = `<div class="flex flex-col items-center animate-pulse"><i data-lucide="loader-2" class="w-8 h-8 text-blue-500 animate-spin mb-3"></i><span class="text-sm text-blue-600 font-medium">Verificando instancia...</span></div>`;
|
container.innerHTML = `<div class="flex flex-col items-center animate-pulse"><div class="w-10 h-10 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin mb-4"></div><span class="text-sm font-bold text-slate-400">Verificando instancia...</span></div>`;
|
||||||
lucide.createIcons();
|
lucide.createIcons();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -308,10 +436,10 @@
|
|||||||
if (!data.ok) throw new Error(data.error || "Error desconocido");
|
if (!data.ok) throw new Error(data.error || "Error desconocido");
|
||||||
|
|
||||||
if (data.state === "open") {
|
if (data.state === "open") {
|
||||||
container.innerHTML = `<div class="flex flex-col items-center"><div class="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mb-4 shadow-sm border border-green-200"><i data-lucide="check" class="w-10 h-10 text-green-600"></i></div><h4 class="text-xl font-bold text-green-700">Conectado</h4><p class="text-sm text-green-600 mt-1 font-medium">Instancia: ${data.instanceName}</p></div>`;
|
container.innerHTML = `<div class="flex flex-col items-center"><div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mb-4 shadow-sm border border-green-200"><i data-lucide="check" class="w-8 h-8 text-green-600"></i></div><h4 class="text-xl font-bold text-green-700">Conectado</h4><p class="text-xs text-green-600 mt-1 font-medium bg-green-50 px-2 py-1 rounded">Instancia: ${data.instanceName}</p></div>`;
|
||||||
} else if (data.qr) {
|
} else if (data.qr) {
|
||||||
container.innerHTML = `<div class="flex flex-col items-center w-full"><div id="qrcode" class="bg-white p-3 border rounded-lg shadow-sm"></div><p class="text-xs text-orange-500 mt-4 font-bold animate-pulse">Esperando escaneo...</p></div>`;
|
container.innerHTML = `<div class="flex flex-col items-center w-full"><div id="qrcode" class="bg-white p-3 border rounded-xl shadow-sm"></div><p class="text-xs text-orange-500 mt-4 font-bold animate-pulse">Esperando escaneo...</p></div>`;
|
||||||
if(data.qr.startsWith('data:image')) { document.getElementById('qrcode').innerHTML = `<img src="${data.qr}" class="w-48 h-48">`; }
|
if(data.qr.startsWith('data:image')) { document.getElementById('qrcode').innerHTML = `<img src="${data.qr}" class="w-48 h-48 rounded-lg">`; }
|
||||||
else { new QRCode(document.getElementById("qrcode"), { text: data.qr, width: 180, height: 180 }); }
|
else { new QRCode(document.getElementById("qrcode"), { text: data.qr, width: 180, height: 180 }); }
|
||||||
} else { container.innerHTML = `<p class="text-orange-500 font-bold">Iniciando... intenta de nuevo en unos segundos.</p>`; }
|
} else { container.innerHTML = `<p class="text-orange-500 font-bold">Iniciando... intenta de nuevo en unos segundos.</p>`; }
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user