From 2fef1ed3dd5f0908a86c7db534a27dbaaa312b3e Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 22 Feb 2026 21:08:48 +0000 Subject: [PATCH] Actualizar configuracion.html --- configuracion.html | 314 +++++++++++++++++++++------------------------ 1 file changed, 148 insertions(+), 166 deletions(-) diff --git a/configuracion.html b/configuracion.html index b15a2dc..9f7a825 100644 --- a/configuracion.html +++ b/configuracion.html @@ -497,7 +497,6 @@
-

Escribe palabras clave separadas por comas. Si el robot detecta alguna de ellas en la descripción del servicio, lo asignará a este gremio automáticamente.

@@ -514,73 +513,102 @@ let cachedTemplates = {}; let currentTemplateType = null; let localGuilds = []; - let currentCompanyConfig = {}; // <--- ALMACENA TODA LA CONFIG GLOBAL + let globalConfig = null; // Para guardar la configuración de la base de datos document.addEventListener("DOMContentLoaded", () => { if (!localStorage.getItem("token")) window.location.href = "index.html"; showTab('templates'); loadTemplates(); loadWaSettings(); - loadGlobalCompanyConfig(); // <--- CARGA GLOBAL PARA EVITAR ERRORES + loadGlobalConfig(); // Cargar portal y app al iniciar }); // ========================================== - // CARGA GLOBAL DE DATOS (ANTI-ERROR 500) + // Carga y Guardado Unificado (Evita Error 500) // ========================================== - async function loadGlobalCompanyConfig() { + async function loadGlobalConfig() { try { const res = await fetch(`${API_URL}/config/company`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); + if (data.ok && data.config) { - currentCompanyConfig = data.config; + globalConfig = data.config; - // Llenar datos Pestaña Portal - document.getElementById('confCompanyName').value = data.config.full_name || ""; - if (data.config.company_logo) { - document.getElementById('confLogoBase64').value = data.config.company_logo; - document.getElementById('logoPreview').innerHTML = ``; + // Rellenar Portal + document.getElementById('confCompanyName').value = globalConfig.full_name || ""; + if (globalConfig.company_logo) { + document.getElementById('confLogoBase64').value = globalConfig.company_logo; + document.getElementById('logoPreview').innerHTML = ``; + } + if (globalConfig.portal_settings) { + const s = globalConfig.portal_settings; + if(s.m_start) document.getElementById('mStart').value = s.m_start; + if(s.m_end) document.getElementById('mEnd').value = s.m_end; + if(s.a_start) document.getElementById('aStart').value = s.a_start; + if(s.a_end) document.getElementById('aEnd').value = s.a_end; + } + + // Rellenar App Operario (si existe en la BD) + if (globalConfig.app_settings) { + const apps = globalConfig.app_settings; + document.getElementById('color-primary').value = apps.primary || "#2563EB"; + document.getElementById('color-primary-hex').value = apps.primary || "#2563EB"; + document.getElementById('color-secondary').value = apps.secondary || "#F59E0B"; + document.getElementById('color-secondary-hex').value = apps.secondary || "#F59E0B"; + document.getElementById('color-bg').value = apps.bg || "#F4F7F9"; + document.getElementById('color-bg-hex').value = apps.bg || "#F4F7F9"; + updateAppPreview(); } - const ps = data.config.portal_settings || {}; - if(ps.m_start) document.getElementById('mStart').value = ps.m_start; - if(ps.m_end) document.getElementById('mEnd').value = ps.m_end; - if(ps.a_start) document.getElementById('aStart').value = ps.a_start; - if(ps.a_end) document.getElementById('aEnd').value = ps.a_end; - - // Llenar datos Pestaña App - const apps = ps.app_settings || {}; - document.getElementById('color-primary').value = apps.primary || "#2563EB"; - document.getElementById('color-primary-hex').value = apps.primary || "#2563EB"; - document.getElementById('color-secondary').value = apps.secondary || "#F59E0B"; - document.getElementById('color-secondary-hex').value = apps.secondary || "#F59E0B"; - document.getElementById('color-bg').value = apps.bg || "#F4F7F9"; - document.getElementById('color-bg-hex').value = apps.bg || "#F4F7F9"; - updateAppPreview(); } - } catch(e) { console.error("Error config global"); } + } catch (e) { console.error("Error cargando configuración global"); } } - // UNIFICADOR DE PAYLOAD (Evita enviar datos vacíos a la BD y crashear PostgreSQL) - function getCompanyPayload() { - const portalSettings = currentCompanyConfig.portal_settings || {}; - - portalSettings.m_start = document.getElementById('mStart').value || "09:00"; - portalSettings.m_end = document.getElementById('mEnd').value || "14:00"; - portalSettings.a_start = document.getElementById('aStart').value || "16:00"; - portalSettings.a_end = document.getElementById('aEnd').value || "19:00"; + async function saveConfigUnified(isPortal) { + let btnId = isPortal ? 'btnSavePortal' : 'btnSaveApp'; + const btn = document.getElementById(btnId); + const original = btn.innerHTML; + btn.innerHTML = ' Guardando...'; + lucide.createIcons(); - portalSettings.app_settings = { - primary: document.getElementById('color-primary').value || "#2563EB", - secondary: document.getElementById('color-secondary').value || "#F59E0B", - bg: document.getElementById('color-bg').value || "#F4F7F9" + // Construir el objeto con TODO lo que espera el servidor + const payload = { + company_name: document.getElementById('confCompanyName').value || globalConfig?.full_name || "Mi Empresa", + company_logo: document.getElementById('confLogoBase64').value || globalConfig?.company_logo || "", + portal_settings: { + m_start: document.getElementById('mStart').value || "09:00", + m_end: document.getElementById('mEnd').value || "14:00", + a_start: document.getElementById('aStart').value || "16:00", + a_end: document.getElementById('aEnd').value || "19:00" + }, + app_settings: { + primary: document.getElementById('color-primary').value || "#2563EB", + secondary: document.getElementById('color-secondary').value || "#F59E0B", + bg: document.getElementById('color-bg').value || "#F4F7F9" + } }; - return { - company_name: document.getElementById('confCompanyName').value || "", - company_logo: document.getElementById('confLogoBase64').value || "", - portal_settings: portalSettings - }; + try { + const res = await fetch(`${API_URL}/config/company`, { + method: 'POST', + headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, + body: JSON.stringify(payload) + }); + const data = await res.json(); + + if (data.ok) { + showToast(isPortal ? "✅ Portal Guardado" : "✅ Colores de la App Actualizados"); + if(document.getElementById("headerUserName")) document.getElementById("headerUserName").innerText = payload.company_name; + localStorage.setItem('app_theme', JSON.stringify(payload.app_settings)); // Guardar en caché para la app móvil + } else { + showToast("❌ Error del servidor", true); + } + } catch (e) { showToast("Error de conexión", true); } + finally { btn.innerHTML = original; lucide.createIcons(); } } + function savePortalConfig() { saveConfigUnified(true); } + function saveAppConfig() { saveConfigUnified(false); } + function showTab(tabId) { document.querySelectorAll('.tab-content').forEach(el => el.classList.add('hidden')); document.getElementById(`view-${tabId}`).classList.remove('hidden'); @@ -601,21 +629,13 @@ } // ========================================== - // LÓGICA PORTAL OPERARIO (COLORES) + // LÓGICA PORTAL OPERARIO (PREVIEW COLORES) // ========================================== ['primary', 'secondary', 'bg'].forEach(type => { const picker = document.getElementById(`color-${type}`); const text = document.getElementById(`color-${type}-hex`); - picker.addEventListener('input', (e) => { - text.value = e.target.value.toUpperCase(); - updateAppPreview(); - }); - text.addEventListener('input', (e) => { - if(/^#[0-9A-F]{6}$/i.test(e.target.value)) { - picker.value = e.target.value; - updateAppPreview(); - } - }); + picker.addEventListener('input', (e) => { text.value = e.target.value.toUpperCase(); updateAppPreview(); }); + text.addEventListener('input', (e) => { if(/^#[0-9A-F]{6}$/i.test(e.target.value)) { picker.value = e.target.value; updateAppPreview(); } }); }); function updateAppPreview() { @@ -628,34 +648,6 @@ document.getElementById('app-preview').style.backgroundColor = b; } - async function saveAppConfig() { - const btn = document.getElementById('btnSaveApp'); - const original = btn.innerHTML; - btn.innerHTML = ' Aplicando...'; - lucide.createIcons(); - - const payload = getCompanyPayload(); - - try { - const res = await fetch(`${API_URL}/config/company`, { - method: 'POST', - headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, - body: JSON.stringify(payload) - }); - const data = await res.json(); - if (data.ok) { - showToast("✅ Colores de la App actualizados"); - localStorage.setItem('app_theme', JSON.stringify(payload.portal_settings.app_settings)); - } else { - showToast("❌ Error al guardar", true); - } - } catch (e) { showToast("Error de conexión", true); } - finally { btn.innerHTML = original; lucide.createIcons(); } - } - - // ========================================== - // LÓGICA PORTAL CLIENTE - // ========================================== function encodeLogo(input) { const file = input.files[0]; if (!file || file.size > 1024 * 1024) { alert("Máximo 1MB"); return; } @@ -667,30 +659,51 @@ reader.readAsDataURL(file); } - async function savePortalConfig() { - const btn = document.getElementById('btnSavePortal'); - const original = btn.innerHTML; - btn.innerHTML = ' Guardando...'; - lucide.createIcons(); - - const payload = getCompanyPayload(); - + // ========================================== + // LÓGICA WHATSAPP + // ========================================== + async function loadWaSettings() { try { - const res = await fetch(`${API_URL}/config/company`, { - method: 'POST', - headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, - body: JSON.stringify(payload) - }); + const res = await fetch(`${API_URL}/whatsapp/settings`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); - if (data.ok) { - showToast("✅ Configuración del Portal guardada"); - const nameEl = document.getElementById("headerUserName"); - if (nameEl && payload.company_name) nameEl.innerText = payload.company_name; - } else { - showToast("❌ Error al guardar", true); - } - } catch (e) { showToast("Error de conexión", true); } - finally { btn.innerHTML = original; lucide.createIcons(); } + const s = data.settings || {}; + 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; + 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_finished').checked = s.wa_evt_finished || false; + document.getElementById('cfg_evt_survey').checked = s.wa_evt_survey || false; + } catch(e) {} + } + + async function saveWaSettings() { + const settings = { + 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, + 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 + }; + try { + const res = await fetch(`${API_URL}/whatsapp/settings`, { method: 'POST', headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify(settings) }); + if (res.ok) showToast("✅ Ajustes WhatsApp guardados"); + } catch(e) {} + } + + async function checkWhatsappStatus() { + const container = document.getElementById('waStatusContainer'); + container.innerHTML = `
`; + try { + const res = await fetch(`${API_URL}/whatsapp/status`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); + const data = await res.json(); + if (data.state === "open") container.innerHTML = `
Conectado
`; + else if (data.qr) container.innerHTML = ``; + else container.innerHTML = `

Iniciando...

`; + lucide.createIcons(); + } catch(e) { container.innerHTML = `

Error servidor

`; } } // ========================================== @@ -736,7 +749,6 @@ }); lucide.createIcons(); } catch (e) { - console.error("Error cargando reglas IA:", e); list.innerHTML = '

Error al cargar las reglas de IA.

'; } } @@ -762,69 +774,39 @@ body: JSON.stringify({ keywords: keywordsArray }) }); if (res.ok) { - showToast("✅ Reglas de IA guardadas correctamente."); + showToast("✅ Reglas de IA guardadas."); closeIaModal(); loadIaRules(); - } else { showToast("❌ Error al guardar las reglas.", true); } + } else { showToast("❌ Error al guardar reglas.", true); } } catch (e) { showToast("❌ Error de conexión.", true); } } - async function loadWaSettings() { - try { - const res = await fetch(`${API_URL}/whatsapp/settings`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); - const data = await res.json(); - const s = data.settings || {}; - 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; - 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_finished').checked = s.wa_evt_finished || false; - document.getElementById('cfg_evt_survey').checked = s.wa_evt_survey || false; - } catch(e) {} - } - - async function saveWaSettings() { - const settings = { - 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, - 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 - }; - try { - const res = await fetch(`${API_URL}/whatsapp/settings`, { method: 'POST', headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify(settings) }); - if (res.ok) showToast("✅ Ajustes WhatsApp guardados"); - } catch(e) {} - } - - async function checkWhatsappStatus() { - const container = document.getElementById('waStatusContainer'); - container.innerHTML = `
`; - try { - const res = await fetch(`${API_URL}/whatsapp/status`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); - const data = await res.json(); - if (data.state === "open") container.innerHTML = `
Conectado
`; - else if (data.qr) container.innerHTML = ``; - else container.innerHTML = `

Iniciando...

`; - lucide.createIcons(); - } catch(e) { container.innerHTML = `

Error servidor

`; } - } - + // ========================================== + // LÓGICA PLANTILLAS + // ========================================== async function loadTemplates() { try { const res = await fetch(`${API_URL}/templates`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); - if(data.ok) { data.templates.forEach(t => { cachedTemplates[t.type] = t.content; }); if (!currentTemplateType) document.querySelector('.tpl-btn').click(); } + if(data.ok) { + data.templates.forEach(t => { cachedTemplates[t.type] = t.content; }); + if (!currentTemplateType) document.querySelector('.tpl-btn').click(); + } } catch(e) {} } function selectTemplate(type, btn) { currentTemplateType = type; - document.querySelectorAll('.tpl-btn').forEach(b => b.classList.remove('bg-blue-50', 'ring-1', 'ring-blue-200')); + document.querySelectorAll('.tpl-btn').forEach(b => { + b.classList.remove('bg-blue-50', 'ring-1', 'ring-blue-200'); + const span = b.querySelector('span'); + if (span.classList.contains('bg-blue-600')) span.classList.replace('bg-blue-600', 'bg-blue-100'), span.classList.replace('text-white', 'text-blue-600'); + if (span.classList.contains('bg-orange-600')) span.classList.replace('bg-orange-600', 'bg-orange-100'), span.classList.replace('text-white', 'text-orange-600'); + }); btn.classList.add('bg-blue-50', 'ring-1', 'ring-blue-200'); + const activeSpan = btn.querySelector('span'); + if (activeSpan.classList.contains('bg-blue-100')) activeSpan.classList.replace('bg-blue-100', 'bg-blue-600'), activeSpan.classList.replace('text-blue-600', 'text-white'); + else if (activeSpan.classList.contains('bg-orange-100')) activeSpan.classList.replace('bg-orange-100', 'bg-orange-600'), activeSpan.classList.replace('text-orange-600', 'text-white'); document.getElementById('editorTitle').innerText = btn.innerText.trim(); document.getElementById('tplContent').value = cachedTemplates[type] || ""; } @@ -843,6 +825,9 @@ showToast("Guardado"); } + // ========================================== + // LÓGICA OTROS Y PROVEEDORES + // ========================================== async function loadCompanies() { const res = await fetch(`${API_URL}/companies`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); @@ -850,13 +835,11 @@ data.companies.forEach(c => { list.innerHTML += `
${c.name}
`; }); lucide.createIcons(); } - async function addCompany() { const name = document.getElementById('newCompanyInput').value; await fetch(`${API_URL}/companies`, { method: 'POST', headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify({ name }) }); document.getElementById('newCompanyInput').value = ""; loadCompanies(); } - async function deleteCompany(id) { if(confirm("Borrar?")) { await fetch(`${API_URL}/companies/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); loadCompanies(); } } async function loadStatusesConfig() { @@ -866,23 +849,24 @@ data.statuses.forEach(s => { list.innerHTML += `
${s.name}
${s.is_system ? '' : ``}
`; }); lucide.createIcons(); } - async function addStatus() { - const name = document.getElementById('newStatusInput').value; - const color = document.getElementById('newStatusColor').value; + const name = document.getElementById('newStatusInput').value, color = document.getElementById('newStatusColor').value; await fetch(`${API_URL}/statuses`, { method: 'POST', headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify({ name, color }) }); document.getElementById('newStatusInput').value = ""; loadStatusesConfig(); } - async function deleteStatus(id) { if(confirm("Borrar?")) { await fetch(`${API_URL}/statuses/${id}`, { method: 'DELETE', headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); loadStatusesConfig(); } } async function loadProviderCredentials() { const res = await fetch(`${API_URL}/providers/credentials`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } }); const data = await res.json(); - data.credentials.forEach(c => { - const inp = document.getElementById(`user_${c.provider.toLowerCase()}`); - if(inp) inp.value = c.username; - }); + data.credentials.forEach(c => { const inp = document.getElementById(`user_${c.provider.toLowerCase()}`); if(inp) inp.value = c.username; }); + } + async function saveProviderCreds(event, provider) { + event.preventDefault(); + const username = document.getElementById(`user_${provider}`).value, password = document.getElementById(`pass_${provider}`).value; + if(!username || !password) return showToast("Faltan datos", true); + await fetch(`${API_URL}/providers/credentials`, { method: 'POST', headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }, body: JSON.stringify({ provider, username, password }) }); + showToast(`✅ Acceso a ${provider} guardado`); } function showToast(msg, isError = false) { @@ -891,8 +875,6 @@ m.innerText = msg; setTimeout(() => t.className += " opacity-0 translate-y-20", 3000); } - - function logout() { localStorage.clear(); window.location.href = "index.html"; } \ No newline at end of file