Actualizar configuracion.html

This commit is contained in:
2026-02-12 22:59:19 +00:00
parent 83d487d167
commit 1ae1328390

View File

@@ -84,31 +84,83 @@
<div class="w-16 h-16 bg-blue-50 rounded-full flex items-center justify-center mb-6"> <div class="w-16 h-16 bg-blue-50 rounded-full flex items-center justify-center mb-6">
<i data-lucide="smartphone" class="w-8 h-8 text-blue-600"></i> <i data-lucide="smartphone" class="w-8 h-8 text-blue-600"></i>
</div> </div>
<h2 class="text-2xl font-bold text-gray-800 mb-2">Conexión con WhatsApp</h2> <h2 class="text-2xl font-bold text-gray-800 mb-2">Conexión con WhatsApp</h2>
<p class="text-gray-500 mb-8 max-w-md">Escanea el código QR para vincular tu número de empresa. Esto permitirá enviar notificaciones automáticas.</p> <p class="text-gray-500 mb-8 max-w-md">Escanea el código QR para vincular tu número de empresa.</p>
<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 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="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> <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> <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"> <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">
<i data-lucide="refresh-cw" class="w-4 h-4"></i> Actualizar Estado <i data-lucide="refresh-cw" class="w-4 h-4"></i> Actualizar Estado
</button> </button>
<p class="text-[10px] text-gray-400 mt-6">Instancia segura gestionada automáticamente por el servidor.</p> <p class="text-[10px] text-gray-400 mt-6">Instancia segura gestionada automáticamente por el servidor.</p>
</div> </div>
</div> </div>
</div> </div>
<div id="view-providers" class="tab-content hidden h-full fade-in"> <div id="view-providers" class="tab-content hidden h-full fade-in">
<div class="bg-white rounded-xl shadow p-10 text-center border border-gray-100"> <div class="max-w-4xl mx-auto">
<i data-lucide="truck" class="w-16 h-16 text-gray-200 mx-auto mb-4"></i> <div class="text-center mb-10">
<h3 class="text-xl font-bold text-gray-700">Proveedores</h3> <h2 class="text-2xl font-bold text-gray-800">Conexión con Aseguradoras</h2>
<p class="text-gray-500 mt-2">Próximamente</p> <p class="text-gray-500 text-sm">Configura tus accesos para que el robot descargue los servicios automáticamente.</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="bg-white rounded-xl shadow border border-gray-200 p-6 relative overflow-hidden group hover:border-blue-300 transition-colors">
<div class="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition">
<i data-lucide="shield" class="w-24 h-24 text-blue-600"></i>
</div>
<div class="flex items-center gap-3 mb-6">
<div class="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center text-blue-700 font-bold text-xl shadow-sm">M</div>
<div>
<h3 class="font-bold text-gray-800 text-lg">Multiasistencia</h3>
<p class="text-xs text-gray-500">Conexión Web</p>
</div>
</div>
<form onsubmit="saveProviderCreds(event, 'multiasistencia')" class="space-y-4 relative z-10">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">Usuario / Código</label>
<input type="text" id="user_multiasistencia" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Ej: 123456">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">Contraseña</label>
<input type="password" id="pass_multiasistencia" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 outline-none" placeholder="••••••••">
</div>
<button type="submit" class="w-full bg-blue-600 text-white font-bold py-2 rounded-lg hover:bg-blue-700 transition shadow-md flex justify-center gap-2">
<i data-lucide="save" class="w-4 h-4"></i> Guardar Acceso
</button>
</form>
</div>
<div class="bg-white rounded-xl shadow border border-gray-200 p-6 relative overflow-hidden group hover:border-red-300 transition-colors">
<div class="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition">
<i data-lucide="home" class="w-24 h-24 text-red-600"></i>
</div>
<div class="flex items-center gap-3 mb-6">
<div class="w-12 h-12 bg-red-100 rounded-xl flex items-center justify-center text-red-700 font-bold text-xl shadow-sm">H</div>
<div>
<h3 class="font-bold text-gray-800 text-lg">HomeServe</h3>
<p class="text-xs text-gray-500">Conexión Web</p>
</div>
</div>
<form onsubmit="saveProviderCreds(event, 'homeserve')" class="space-y-4 relative z-10">
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">Código Proveedor</label>
<input type="text" id="user_homeserve" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-red-500 outline-none" placeholder="Ej: P-9999">
</div>
<div>
<label class="block text-xs font-bold text-gray-600 mb-1">Contraseña</label>
<input type="password" id="pass_homeserve" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-red-500 outline-none" placeholder="••••••••">
</div>
<button type="submit" class="w-full bg-red-600 text-white font-bold py-2 rounded-lg hover:bg-red-700 transition shadow-md flex justify-center gap-2">
<i data-lucide="save" class="w-4 h-4"></i> Guardar Acceso
</button>
</form>
</div>
</div>
<p class="text-center text-xs text-gray-400 mt-8">Tus credenciales se guardan encriptadas y solo se usan para la sincronización automática.</p>
</div> </div>
</div> </div>
@@ -167,59 +219,75 @@
if(tabId === 'others') { loadCompanies(); loadStatusesConfig(); } if(tabId === 'others') { loadCompanies(); loadStatusesConfig(); }
if(tabId === 'whatsapp') { checkWhatsappStatus(); } if(tabId === 'whatsapp') { checkWhatsappStatus(); }
if(tabId === 'providers') { loadProviderCredentials(); } // Cargar credenciales
}
// --- GESTIÓN DE PROVEEDORES (NUEVO) ---
async function loadProviderCredentials() {
try {
const res = await fetch(`${API_URL}/providers/credentials`, {
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
});
const data = await res.json();
if (data.ok && data.credentials) {
data.credentials.forEach(cred => {
const inputUser = document.getElementById(`user_${cred.provider}`);
const inputPass = document.getElementById(`pass_${cred.provider}`);
if(inputUser) inputUser.value = cred.username;
// No rellenamos la contraseña por seguridad, solo el usuario
if(inputPass) inputPass.placeholder = "•••••••• (Guardada)";
});
}
} catch(e) { console.error("Error loading credentials", e); }
}
async function saveProviderCreds(event, provider) {
event.preventDefault();
const username = document.getElementById(`user_${provider}`).value;
const password = document.getElementById(`pass_${provider}`).value;
if(!username || !password) {
showToast("Rellena usuario y contraseña", true);
return;
}
try {
const res = await fetch(`${API_URL}/providers/credentials`, {
method: 'POST',
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` },
body: JSON.stringify({ provider, username, password })
});
if(res.ok) {
showToast(`✅ Acceso a ${provider} guardado`);
} else {
showToast("Error al guardar", true);
}
} catch(e) { showToast("Error de conexión", true); }
} }
// --- WHATSAPP STATUS (AUTOMÁTICO) --- // --- WHATSAPP STATUS (AUTOMÁTICO) ---
async function checkWhatsappStatus() { async function checkWhatsappStatus() {
const container = document.getElementById('waStatusContainer'); const container = document.getElementById('waStatusContainer');
container.innerHTML = ` 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>`;
<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>`;
lucide.createIcons(); lucide.createIcons();
try { try {
// Llamamos a NUESTRO backend, que gestiona todo con Evolution const res = await fetch(`${API_URL}/whatsapp/status`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
const res = await fetch(`${API_URL}/whatsapp/status`, {
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
});
const data = await res.json(); const data = await res.json();
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 = ` 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>`;
<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>`;
} else if (data.qr) { } else if (data.qr) {
container.innerHTML = ` 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>`;
<div class="flex flex-col items-center w-full"> if(data.qr.startsWith('data:image')) { document.getElementById('qrcode').innerHTML = `<img src="${data.qr}" class="w-48 h-48">`; }
<div id="qrcode" class="bg-white p-3 border rounded-lg shadow-sm"></div> else { new QRCode(document.getElementById("qrcode"), { text: data.qr, width: 180, height: 180 }); }
<p class="text-xs text-orange-500 mt-4 font-bold animate-pulse">Esperando escaneo...</p> } else { container.innerHTML = `<p class="text-orange-500 font-bold">Iniciando... intenta de nuevo en unos segundos.</p>`; }
</div>`;
if(data.qr.startsWith('data:image')) {
document.getElementById('qrcode').innerHTML = `<img src="${data.qr}" class="w-48 h-48">`;
} 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>`;
}
} catch(e) { } catch(e) {
container.innerHTML = ` container.innerHTML = `<div class="text-center text-red-500 p-4"><i data-lucide="alert-triangle" class="w-10 h-10 mx-auto mb-2 opacity-80"></i><p class="font-bold">Error de conexión</p><p class="text-xs mt-1 bg-red-50 p-2 rounded">${e.message}</p></div>`;
<div class="text-center text-red-500 p-4">
<i data-lucide="alert-triangle" class="w-10 h-10 mx-auto mb-2 opacity-80"></i>
<p class="font-bold">Error de conexión</p>
<p class="text-xs mt-1 bg-red-50 p-2 rounded">${e.message}</p>
</div>`;
} }
lucide.createIcons(); lucide.createIcons();
} }