| Server IP : 127.0.0.1 / Your IP : 216.73.216.109 Web Server : Apache/2.4.54 (Win64) OpenSSL/1.1.1q PHP/8.1.10 System : Windows NT DESKTOP-E5T4RUN 10.0 build 19045 (Windows 10) AMD64 User : SERVERWEB ( 0) PHP Version : 8.1.10 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/laragon/www/modules/e-gamq/ |
Upload File : |
function initializeChatbot() {
const chatbotContainer = document.getElementById('chatbot-container');
const chatbotToggle = document.getElementById('chatbot-toggle');
const chatbotClose = document.getElementById('chatbot-close');
const chatbotMessages = document.getElementById('chatbot-messages');
const chatbotOptions = document.getElementById('chatbot-options');
const chatbotInput = document.getElementById('chatbot-input');
const chatbotSend = document.getElementById('chatbot-send');
if (!chatbotContainer || !chatbotToggle || !chatbotClose || !chatbotMessages || !chatbotOptions || !chatbotInput || !chatbotSend) {
return;
}
if (chatbotContainer.dataset.initialized === 'true') {
return;
}
chatbotContainer.dataset.initialized = 'true';
let navigationStack = ['main'];
let isInitialized = false;
let hasUserAskedQuestion = false;
const siteRootUrl = getSiteRootUrl();
const knowledgeCache = {
systems: null,
news: null,
pages: {}
};
const unitPages = [
{ id: 'agricola', name: 'Agrícola', url: 'modules/unidades/index-Agricola.html', keywords: ['agricola', 'agrícola', 'agricultura'] },
{ id: 'cultura', name: 'Cultura', url: 'modules/unidades/index-Cultura.html', keywords: ['cultura', 'cultural'] },
{ id: 'educacion', name: 'Educación', url: 'modules/unidades/index-Educacion.html', keywords: ['educacion', 'educación', 'colegio', 'escuela'] },
{ id: 'turismo', name: 'Turismo', url: 'modules/unidades/index-Turismo.html', keywords: ['turismo', 'turistica', 'turística'] },
{ id: 'zoonosis', name: 'Zoonosis', url: 'modules/unidades/index-Zoonosis.html', keywords: ['zoonosis', 'vacunacion', 'vacunación', 'esterilizacion', 'esterilización', 'animal'] },
{ id: 'pecuaria', name: 'Pecuaria', url: 'modules/unidades/index-Pecuaria.html', keywords: ['pecuaria', 'ganado'] },
{ id: 'riegos', name: 'Riegos', url: 'modules/unidades/index-Riegos.html', keywords: ['riegos', 'riego', 'agua'] },
{ id: 'red-monica', name: 'Red Mónica', url: 'modules/unidades/index-Red-Monica.html', keywords: ['red monica', 'red mónica', 'monica', 'mónica', 'aire'] },
{ id: 'preservacion-ambiental', name: 'Preservación Ambiental', url: 'modules/unidades/index-Preservacion-ambiental.html', keywords: ['preservacion', 'preservación', 'ambiental', 'medio ambiente'] },
{ id: 'recursos-naturales', name: 'Recursos Naturales', url: 'modules/unidades/index-Recursos-naturales.html', keywords: ['recursos naturales', 'naturales'] },
{ id: 'parques-jardines', name: 'Parques y Jardines', url: 'modules/unidades/index-Parques-jardines.html', keywords: ['parques', 'jardines', 'parques y jardines'] },
{ id: 'forestal', name: 'Forestal', url: 'modules/unidades/index-Forestal.html', keywords: ['forestal', 'arboles', 'árboles'] },
{ id: 'tdi', name: 'TDI - Sistemas', url: 'modules/unidades/index-TDI.html', keywords: ['tdi', 'sistemas', 'tecnologia', 'tecnología'] },
{ id: 'ugr', name: 'UGR', url: 'modules/unidades/index-UGR.html', keywords: ['ugr', 'riesgos', 'emergencia'] },
{ id: 'dio', name: 'DIO', url: 'modules/unidades/index-DIO.html', keywords: ['dio', 'defensoria', 'defensoría'] }
];
function getSiteRootUrl() {
const pathname = window.location.pathname;
const unidadesIndex = pathname.toLowerCase().indexOf('/modules/unidades/');
if (unidadesIndex !== -1) {
return `${window.location.origin}${pathname.slice(0, unidadesIndex + 1)}`;
}
return new URL('./', window.location.href).href;
}
function siteUrl(path) {
if (/^https?:\/\//i.test(path)) {
return path;
}
return new URL(path.replace(/^\/+/, ''), siteRootUrl).href;
}
function normalizeText(value) {
return String(value || '')
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.toLowerCase()
.replace(/\s+/g, ' ')
.trim();
}
function cleanText(value) {
return String(value || '').replace(/\s+/g, ' ').trim();
}
function escapeHtml(value) {
const div = document.createElement('div');
div.textContent = value || '';
return div.innerHTML;
}
function addBotHtml(html) {
const messageDiv = document.createElement('div');
messageDiv.className = 'chatbot-message bot-message';
const shouldCollapse = html.length > 900 || (html.match(/<br>/g) || []).length > 10;
messageDiv.innerHTML = `
<div class="chatbot-rich-content ${shouldCollapse ? 'is-collapsed' : ''}">${html}</div>
${shouldCollapse ? '<button class="chatbot-read-more" type="button">Ver más</button>' : ''}
`;
chatbotMessages.appendChild(messageDiv);
const readMore = messageDiv.querySelector('.chatbot-read-more');
if (readMore) {
readMore.addEventListener('click', function() {
const content = messageDiv.querySelector('.chatbot-rich-content');
content.classList.toggle('is-collapsed');
readMore.textContent = content.classList.contains('is-collapsed') ? 'Ver más' : 'Ver menos';
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
});
}
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
}
function renderOptions(html, mode = 'panel') {
chatbotOptions.dataset.mode = mode;
chatbotOptions.innerHTML = html;
}
function minimizeOptions() {
chatbotOptions.dataset.mode = 'minimized';
chatbotOptions.innerHTML = '<button class="chatbot-topic-toggle" type="button">Ver otros temas</button>';
const toggle = chatbotOptions.querySelector('.chatbot-topic-toggle');
if (toggle) {
toggle.addEventListener('click', showMainOptions);
}
}
function getQueryTokens(message) {
const stopWords = new Set(['que', 'cual', 'cuales', 'como', 'donde', 'para', 'sobre', 'tiene', 'hay', 'los', 'las', 'del', 'una', 'uno', 'con', 'por', 'ese', 'esa', 'este', 'esta', 'sistema', 'sistemas', 'unidad', 'unidades']);
return normalizeText(message)
.split(/[^a-z0-9]+/)
.filter(token => token.length > 2 && !stopWords.has(token));
}
function scoreText(text, tokens) {
const normalized = normalizeText(text);
return tokens.reduce((score, token) => score + (normalized.includes(token) ? 1 : 0), 0);
}
function isContactIntent(message) {
return normalizeText(message).match(/\b(contacto|contactos|telefono|telefonos|celular|whatsapp|correo|email|llamar|contactar)\b/);
}
function isAddressIntent(message) {
return normalizeText(message).match(/\b(direccion|direcciones|ubicacion|ubicaciones|oficina|oficinas|donde queda|donde estan|mapa)\b/);
}
function isNewsIntent(message) {
return normalizeText(message).match(/\b(noticia|noticias|anuncio|anuncios|comunicado|comunicados|novedad|novedades|actualidad|ultimo|ultimos|ultima|ultimas|reciente|recientes)\b/);
}
async function loadHtmlDocument(pathOrUrl) {
const absoluteUrl = /^https?:\/\//i.test(pathOrUrl) ? pathOrUrl : siteUrl(pathOrUrl);
const response = await fetch(absoluteUrl, { cache: 'no-store' });
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const html = await response.text();
return {
url: absoluteUrl,
doc: new DOMParser().parseFromString(html, 'text/html')
};
}
function resolvePageUrl(basePathOrUrl, href) {
return new URL(href, /^https?:\/\//i.test(basePathOrUrl) ? basePathOrUrl : siteUrl(basePathOrUrl)).href;
}
function extractRelevantLines(doc, keywords = []) {
const normalizedKeywords = keywords.map(normalizeText);
return Array.from(doc.querySelectorAll('h1, h2, h3, h4, h5, p, li, .desc, .column_attr'))
.map(element => cleanText(element.textContent))
.filter(text => {
if (text.length < 4 || /lorem ipsum|your name|your e-mail|subject|message/i.test(text)) {
return false;
}
const normalized = normalizeText(text);
const hasContactData = /(\+?\(?591\)?|[67]\d{7}|\b\d{7,}\b|@|direccion|dirección|ubicacion|ubicación|oficina|celular|telefono|teléfono|whatsapp|plaza)/i.test(text);
return hasContactData || normalizedKeywords.some(keyword => normalized.includes(keyword));
})
.filter((text, index, lines) => lines.indexOf(text) === index)
.slice(0, 8);
}
async function loadGovernmentSystems() {
if (knowledgeCache.systems) {
return knowledgeCache.systems;
}
try {
const response = await fetch(siteUrl('sections/section-apps.php'), { cache: 'no-store' });
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const html = await response.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
const cards = Array.from(doc.querySelectorAll('.app-card'));
knowledgeCache.systems = cards.map(card => ({
name: cleanText(card.querySelector('.app-title')?.textContent),
description: cleanText(card.querySelector('.app-description')?.textContent),
status: cleanText(card.querySelector('.app-status')?.textContent),
url: card.dataset.url || '',
categories: card.dataset.category || ''
})).filter(system => system.name);
} catch (error) {
console.warn('No se pudo cargar la lista de sistemas:', error);
knowledgeCache.systems = [];
}
return knowledgeCache.systems;
}
async function loadPageSummary(path) {
const absoluteUrl = siteUrl(path);
if (knowledgeCache.pages[absoluteUrl]) {
return knowledgeCache.pages[absoluteUrl];
}
const { doc } = await loadHtmlDocument(absoluteUrl);
doc.querySelectorAll('script, style, nav, footer, header, #chatbot-container, #chatbot-toggle').forEach(element => element.remove());
const title = cleanText(doc.querySelector('h1, h2, title')?.textContent);
const fragments = Array.from(doc.querySelectorAll('h1, h2, h3, h4, h5, p, li'))
.map(element => cleanText(element.textContent))
.filter(text => text.length > 35 && !/lorem ipsum/i.test(text))
.slice(0, 8);
const summary = {
title,
text: fragments.join(' '),
url: absoluteUrl
};
knowledgeCache.pages[absoluteUrl] = summary;
return summary;
}
function findRequestedUnit(message) {
const normalizedMessage = normalizeText(message);
return unitPages.find(unit => unit.keywords.some(keyword => normalizedMessage.includes(normalizeText(keyword))));
}
async function loadUnitContactInfo(unit, message) {
const wantsAddress = isAddressIntent(message);
const { doc: unitDoc } = await loadHtmlDocument(unit.url);
const contactLink = Array.from(unitDoc.querySelectorAll('a[href]'))
.map(anchor => ({
href: anchor.getAttribute('href'),
text: cleanText(anchor.textContent)
}))
.find(link => normalizeText(`${link.text} ${link.href}`).match(/\b(contacto|contactos|contact|contacts|contact-us|contactanos|contáctanos|contact-and-help)\b/));
let sourceUrl = siteUrl(unit.url);
let sourceDoc = unitDoc;
if (contactLink && contactLink.href && !contactLink.href.startsWith('#')) {
sourceUrl = resolvePageUrl(unit.url, contactLink.href);
sourceDoc = (await loadHtmlDocument(sourceUrl)).doc;
}
sourceDoc.querySelectorAll('script, style, nav, footer, header, form, #chatbot-container, #chatbot-toggle').forEach(element => element.remove());
const lines = extractRelevantLines(sourceDoc, wantsAddress ? ['direccion', 'ubicacion', 'oficina'] : ['contacto', 'celular', 'telefono', 'correo']);
return {
lines,
url: sourceUrl
};
}
async function answerUnitContactQuestion(message) {
const unit = findRequestedUnit(message);
if (!unit || (!isContactIntent(message) && !isAddressIntent(message))) {
return false;
}
try {
const contact = await loadUnitContactInfo(unit, message);
if (contact.lines.length) {
addBotHtml(`<strong>${escapeHtml(isAddressIntent(message) ? `Dirección / ubicación de ${unit.name}` : `Contactos de ${unit.name}`)}</strong><br>${contact.lines.map(line => `• ${escapeHtml(line)}`).join('<br>')}<br><a href="${escapeHtml(contact.url)}">Ver página de contacto</a>`);
} else {
addBotHtml(`No encontré datos específicos de contacto para ${escapeHtml(unit.name)} en su página, pero puedes revisar aquí:<br><a href="${escapeHtml(contact.url)}">Ver página de ${escapeHtml(unit.name)}</a>`);
}
} catch (error) {
addBotHtml(`No pude leer los contactos actualizados de ${escapeHtml(unit.name)} en este momento. Puedes abrir su página aquí:<br><a href="${escapeHtml(siteUrl(unit.url))}">Ver página de ${escapeHtml(unit.name)}</a>`);
}
return true;
}
async function answerGeneralContactQuestion(message) {
if (!isContactIntent(message) && !isAddressIntent(message)) {
return false;
}
try {
const { doc, url } = await loadHtmlDocument('pages/contact.html');
doc.querySelectorAll('script, style, nav, footer, header, form').forEach(element => element.remove());
const lines = extractRelevantLines(doc, ['direccion', 'contacto', 'telefono', 'correo', 'email', 'oficina']);
if (!lines.length) {
return false;
}
addBotHtml(`<strong>Contactos del GAMQ</strong><br>${lines.map(line => `• ${escapeHtml(line)}`).join('<br>')}<br><a href="${escapeHtml(url)}">Ver página de contacto</a>`);
return true;
} catch (error) {
addBotHtml(`Puedes ver los contactos del GAMQ aquí:<br><a href="${escapeHtml(siteUrl('pages/contact.html'))}">Página de contacto</a>`);
return true;
}
}
async function loadLatestNews() {
if (knowledgeCache.news) {
return knowledgeCache.news;
}
try {
const { doc } = await loadHtmlDocument('sections/section-news.php');
knowledgeCache.news = Array.from(doc.querySelectorAll('.post-item')).map(item => ({
title: cleanText(item.querySelector('.entry-title a, h3 a, h3')?.textContent),
date: cleanText(item.querySelector('.date, .date_label')?.textContent),
category: cleanText(item.querySelector('.post-categories a')?.textContent),
url: item.querySelector('.entry-title a, h3 a, .image_links a')?.getAttribute('href') || ''
})).filter(news => news.title).slice(0, 5);
} catch (error) {
console.warn('No se pudieron cargar las últimas noticias:', error);
knowledgeCache.news = [];
}
return knowledgeCache.news;
}
async function answerNewsQuestion(message) {
if (!isNewsIntent(message)) {
return false;
}
const news = await loadLatestNews();
if (!news.length) {
addBotHtml(`No pude cargar las noticias actualizadas en este momento. Puedes revisarlas aquí:<br><a href="${escapeHtml(siteUrl('pages/news.html'))}">Ver noticias</a>`);
return true;
}
const rows = news.map(item => {
const link = item.url ? ` - <a href="${escapeHtml(item.url)}" target="_blank" rel="noopener">ver</a>` : '';
const meta = [item.date, item.category].filter(Boolean).join(' · ');
return `• <strong>${escapeHtml(item.title)}</strong>${meta ? `<br><small>${escapeHtml(meta)}</small>` : ''}${link}`;
}).join('<br>');
addBotHtml(`<strong>Últimas noticias y anuncios</strong><br>${rows}<br><a href="${escapeHtml(siteUrl('pages/news.html'))}">Ver todas las noticias</a>`);
return true;
}
async function answerGovernmentSystemsQuestion(message) {
const systems = await loadGovernmentSystems();
if (!systems.length) {
return false;
}
const tokens = getQueryTokens(message);
const wantsList = normalizeText(message).match(/\b(lista|listar|sistemas|aplicaciones|apps|gobierno electronico|gobierno electrónico)\b/);
const matches = systems
.map(system => ({
system,
score: scoreText(`${system.name} ${system.description} ${system.categories}`, tokens)
}))
.filter(item => item.score > 0)
.sort((a, b) => b.score - a.score);
if (!wantsList && matches.length === 0) {
return false;
}
if (matches.length === 1 && matches[0].score >= 1 && !wantsList) {
const system = matches[0].system;
const link = system.url ? `<br><a href="${escapeHtml(system.url)}" target="_blank" rel="noopener">Abrir ${escapeHtml(system.name)}</a>` : '<br>Este sistema no tiene enlace público registrado.';
addBotHtml(`<strong>${escapeHtml(system.name)}</strong><br>${escapeHtml(system.description)}<br>Estado: ${escapeHtml(system.status || 'No especificado')}.${link}`);
return true;
}
const list = (matches.length ? matches : systems)
.slice(0, 8)
.map(item => item.system || item)
.map(system => {
const link = system.url ? ` - <a href="${escapeHtml(system.url)}" target="_blank" rel="noopener">abrir</a>` : '';
return `• <strong>${escapeHtml(system.name)}</strong>: ${escapeHtml(system.description)}${link}`;
})
.join('<br>');
addBotHtml(`Estos son algunos sistemas de Gobierno Electrónico disponibles:<br>${list}<br><br>También puedes preguntar por uno específico, por ejemplo: ODECO, FISQUI, SIGECEM, Deportes o Trámites.`);
return true;
}
async function answerUnitQuestion(message) {
const unit = findRequestedUnit(message);
if (!unit) {
return false;
}
try {
const summary = await loadPageSummary(unit.url);
const sentences = summary.text.match(/[^.!?]+[.!?]?/g) || [summary.text];
const usefulText = sentences.slice(0, 3).join(' ').slice(0, 420);
addBotHtml(`<strong>${escapeHtml(unit.name)}</strong><br>${escapeHtml(usefulText || 'Tengo registrada esta unidad en el portal del GAMQ.')}<br><a href="${escapeHtml(summary.url)}">Ver página de ${escapeHtml(unit.name)}</a>`);
} catch (error) {
addBotHtml(`No pude leer la página actualizada de ${escapeHtml(unit.name)} en este momento, pero puedes abrirla aquí:<br><a href="${escapeHtml(siteUrl(unit.url))}">Ver página de ${escapeHtml(unit.name)}</a>`);
}
return true;
}
function answerCurrentPageQuestion(message) {
const normalizedMessage = normalizeText(message);
if (!normalizedMessage.match(/\b(esta pagina|pagina actual|aqui|este sitio|informacion de esta)\b/)) {
return false;
}
const clone = document.body.cloneNode(true);
clone.querySelectorAll('script, style, nav, footer, header, #chatbot-container, #chatbot-toggle').forEach(element => element.remove());
const fragments = Array.from(clone.querySelectorAll('h1, h2, h3, h4, p, li'))
.map(element => cleanText(element.textContent))
.filter(text => text.length > 40 && !/lorem ipsum/i.test(text))
.slice(0, 4);
if (!fragments.length) {
return false;
}
addBotHtml(`En esta página encontré esta información:<br>${fragments.map(fragment => `• ${escapeHtml(fragment)}`).join('<br>')}`);
return true;
}
async function answerFromKnowledge(message) {
const normalizedMessage = normalizeText(message);
if (await answerUnitContactQuestion(message)) {
return true;
}
if (await answerGeneralContactQuestion(message)) {
return true;
}
if (await answerNewsQuestion(message)) {
return true;
}
if (answerCurrentPageQuestion(message)) {
return true;
}
if (await answerUnitQuestion(message)) {
return true;
}
if (normalizedMessage.match(/\b(gobierno electronico|gobierno electrónico|sistema|sistemas|aplicacion|aplicaciones|app|apps|odeco|fisqui|sigecem|parqui|provegaq|presqui|matadero|biblioteca|taskboard|tramites|trámites)\b/)) {
return answerGovernmentSystemsQuestion(message);
}
return false;
}
chatbotToggle.addEventListener('click', function() {
chatbotContainer.style.display = 'flex';
chatbotToggle.style.display = 'none';
if (!isInitialized) {
initializeChat();
isInitialized = true;
}
chatbotInput.focus();
});
chatbotClose.addEventListener('click', function(event) {
event.preventDefault();
event.stopPropagation();
chatbotContainer.style.display = 'none';
chatbotToggle.style.display = 'flex';
});
function initializeChat() {
chatbotMessages.innerHTML = '';
addMessage("¡Hola! Soy tu asistente virtual del Gobierno Autónomo Municipal de Quillacollo. Estoy aquí para ayudarte con:", 'bot');
showMainOptions();
}
function sendMessage() {
const message = chatbotInput.value.trim();
if (message) {
hasUserAskedQuestion = true;
if (chatbotOptions.dataset.mode === 'main') {
showMainOptions();
}
addMessage(message, 'user');
chatbotInput.value = '';
setTimeout(() => {
processUserMessage(message);
}, 500);
}
}
chatbotSend.addEventListener('click', sendMessage);
chatbotInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
function addMessage(text, type) {
const messageDiv = document.createElement('div');
messageDiv.className = `chatbot-message ${type}-message`;
messageDiv.innerHTML = `<p>${text}</p>`;
chatbotMessages.appendChild(messageDiv);
chatbotMessages.scrollTop = chatbotMessages.scrollHeight;
}
async function processUserMessage(message) {
const lowerMessage = message.toLowerCase();
if (lowerMessage.match(/\b(hola|buenas|buenos dias|buenas tardes|saludos|hey)\b/)) {
addMessage("¡Hola! ¿En qué puedo ayudarte hoy?", 'bot');
showMainOptions();
return;
}
if (lowerMessage.match(/\b(gracias|agradecido|agradecida|muchas gracias)\b/)) {
addMessage("¡De nada! Fue un placer ayudarte. Si necesitas algo más, aquí estoy.", 'bot');
showMainOptions();
return;
}
if (lowerMessage.match(/\b(adios|chao|hasta luego|nos vemos)\b/)) {
addMessage("¡Hasta pronto! Que tengas un excelente día. Estoy aquí cuando me necesites.", 'bot');
return;
}
if (await answerFromKnowledge(message)) {
return;
}
if (lowerMessage.match(/\b(unidad|unidades|departamento|sección|área)\b/)) {
navigationStack.push('unidades');
showUnidadesOptions();
return;
}
if (lowerMessage.match(/\b(noticia|noticias|novedad|novedades|actualidad)\b/)) {
redirectToNoticias();
return;
}
if (lowerMessage.match(/\b(quillacollo|municipio|información|info|sobre)\b/)) {
redirectToInfo();
return;
}
if (lowerMessage.match(/\b(denuncia|reclamo|queja|problema|seguimiento|seguir|estado|progreso|avance|track|tracking)\b/)) {
navigationStack.push('denuncia-reclamo');
showDenunciaReclamoOptions();
return;
}
if (lowerMessage.match(/\b(contacto|contactar|equipo|whatsapp|teléfono|llamar)\b/)) {
redirectToContacto();
return;
}
if (lowerMessage.match(/\b(ruat|deuda|deudas|consulta|impuesto|impuestos|vehiculo|vehiculos|inmueble|inmuebles|actividad economica)\b/)) {
navigationStack.push('consultas');
showConsultasOptions();
return;
}
if (lowerMessage.match(/\b(deporte|deportes|reserva|reservar|cancha|canchas|complejo|complejos|deportivo|deportivos)\b/)) {
redirectToDeportes();
return;
}
if (lowerMessage.match(/\b(seguimiento|seguir|estado|progreso|avance|track|tracking|código|número de caso|referencia)\b/)) {
navigationStack.push('seguimiento');
showSeguimientoOptions();
return;
}
addMessage("Entiendo que tienes una consulta. Para brindarte mejor asistencia, puedes seleccionar una de las opciones disponibles o escribir sobre:", 'bot');
addMessage("• Unidades del GAMQ\n• Consulta de deudas (RUAT)\n• Reservas deportivas\n• Noticias y novedades\n• Denuncias o reclamos\n• Seguimiento de casos\n• Contacto", 'bot');
showMainOptions();
}
function showMainOptions(forceExpanded = false) {
navigationStack = ['main'];
const isCompact = hasUserAskedQuestion && !forceExpanded;
const titleText = isCompact ? 'Más opciones' : 'Opciones disponibles';
const titleAction = isCompact ? 'expand-options' : 'collapse-options';
const titleLabel = isCompact ? 'Expandir opciones' : 'Contraer opciones';
const titleIcon = isCompact ? '▲' : '▼';
const optionsTitleHTML = `
<div class="chatbot-options-title">
<div class="chatbot-options-title-text">${titleText}</div>
${hasUserAskedQuestion ? `<button class="chatbot-expand-options" type="button" data-action="${titleAction}" aria-label="${titleLabel}">${titleIcon}</button>` : ''}
</div>
`;
const mainOptionsHTML = isCompact ? optionsTitleHTML : `
${optionsTitleHTML}
<div class="quick-options-row">
<button class="option-button" data-option="contacto">
<span class="option-icon">
<i class="fab fa-whatsapp"></i>
</span>
<span class="option-text">Contactar</span>
</button>
<button class="option-button" data-option="denuncia-reclamo">
<span class="option-icon">⚠️</span>
<span class="option-text">Denuncia o Reclamo</span>
</button>
<button class="option-button" data-option="consultas">
<span class="option-icon">💳</span>
<span class="option-text">Deudas RUAT</span>
</button>
<button class="option-button" data-option="deportes">
<span class="option-icon">⚽</span>
<span class="option-text">Reservas Deportivas</span>
</button>
<button class="option-button" data-option="quillacollo">
<span class="option-icon">ℹ️</span>
<span class="option-text">Sobre Quillacollo</span>
</button>
</div>
`;
// <button class="option-button" data-option="sistemas">
// <span class="option-icon">💻</span>
// <span class="option-text">Gobierno Electrónico</span>
// </button>
// <button class="option-button" data-option="unidades">
// <span class="option-icon">📋</span>
// <span class="option-text">Unidades</span>
// </button>
// <button class="option-button" data-option="noticias">
// <span class="option-icon">📰</span>
// <span class="option-text">Noticias</span>
// </button>
renderOptions(mainOptionsHTML, isCompact ? 'main-compact' : 'main');
const expandButton = chatbotOptions.querySelector('[data-action="expand-options"]');
if (expandButton) {
expandButton.addEventListener('click', function() {
showMainOptions(true);
});
}
const collapseButton = chatbotOptions.querySelector('[data-action="collapse-options"]');
if (collapseButton) {
collapseButton.addEventListener('click', function() {
showMainOptions(false);
});
}
chatbotOptions.querySelectorAll('.option-button').forEach(button => {
button.addEventListener('click', function() {
const option = this.getAttribute('data-option');
handleOptionSelection(option);
});
});
}
function showUnidadesOptions() {
addMessage("Selecciona la unidad sobre la que deseas información:", 'bot');
const unidadesHTML = `
<div class="options-grid">
<button class="option-button" data-unidad="agricola">
<span class="option-icon">🌱</span>
<span class="option-text">Agrícola</span>
</button>
<button class="option-button" data-unidad="cultura">
<span class="option-icon">🎭</span>
<span class="option-text">Cultura</span>
</button>
<button class="option-button" data-unidad="educacion">
<span class="option-icon">🎓</span>
<span class="option-text">Educación</span>
</button>
<button class="option-button" data-unidad="turismo">
<span class="option-icon">🏞️</span>
<span class="option-text">Turismo</span>
</button>
<button class="option-button" data-unidad="zoonosis">
<span class="option-icon">🐾</span>
<span class="option-text">Zoonosis</span>
</button>
<button class="option-button" data-unidad="pecuaria">
<span class="option-icon">🐄</span>
<span class="option-text">Pecuaria</span>
</button>
<button class="option-button" data-unidad="riegos">
<span class="option-icon">💧</span>
<span class="option-text">Riegos</span>
</button>
<button class="option-button" data-unidad="red-monica">
<span class="option-icon">🌬️</span>
<span class="option-text">Red Mónica</span>
</button>
<button class="option-button" data-unidad="preservacion-ambiental">
<span class="option-icon">🌿</span>
<span class="option-text">Preservación Ambiental</span>
</button>
<button class="option-button" data-unidad="recursos-naturales">
<span class="option-icon">🌳</span>
<span class="option-text">Recursos Naturales</span>
</button>
<button class="option-button" data-unidad="parques-jardines">
<span class="option-icon">🌷</span>
<span class="option-text">Parques y Jardines</span>
</button>
<button class="option-button" data-unidad="forestal">
<span class="option-icon">🌲</span>
<span class="option-text">Forestal</span>
</button>
<button class="option-button" data-unidad="tdi">
<span class="option-icon">💻</span>
<span class="option-text">TDI - Sistemas</span>
</button>
<button class="option-button" data-unidad="ugr">
<span class="option-icon">🚧</span>
<span class="option-text">UGR</span>
</button>
<button class="option-button" data-unidad="dio">
<span class="option-icon">👥</span>
<span class="option-text">DIO</span>
</button>
</div>
<button class="option-button back-button" data-action="back">
<span class="option-icon">⬅️</span>
<span class="option-text">Volver al menú principal</span>
</button>
`;
renderOptions(unidadesHTML);
document.querySelectorAll('[data-unidad]').forEach(button => {
button.addEventListener('click', function() {
const unidad = this.getAttribute('data-unidad');
redirectToUnidad(unidad);
});
});
addBackButtonListener();
}
function showDenunciaReclamoOptions() {
addMessage("Puedes realizar una denuncia o reclamo a través de nuestro sistema ODECO. Selecciona el tipo:", 'bot');
const denunciaHTML = `
<button class="option-button" data-tipo="DENUNCIA">
<span class="option-icon">🚨</span>
<span class="option-text">Realizar Denuncia</span>
</button>
<button class="option-button" data-tipo="RECLAMO">
<span class="option-icon">📝</span>
<span class="option-text">Realizar Reclamo</span>
</button>
<button class="option-button" data-tipo="SEGUIMIENTO">
<span class="option-icon">📊</span>
<span class="option-text">Realizar Seguimiento</span>
</button>
<button class="option-button back-button" data-action="back">
<span class="option-icon">⬅️</span>
<span class="option-text">Volver al menú principal</span>
</button>
`;
renderOptions(denunciaHTML);
document.querySelectorAll('[data-tipo]').forEach(button => {
button.addEventListener('click', function() {
const tipo = this.getAttribute('data-tipo');
redirectToOdeco(tipo);
});
});
addBackButtonListener();
}
function showConsultasOptions() {
addMessage("Puedes consultar tus deudas a través del sistema RUAT. Selecciona el tipo de consulta:", 'bot');
const consultasHTML = `
<button class="option-button" data-consulta="actividades">
<span class="option-icon">🏢</span>
<span class="option-text">Actividades Económicas</span>
</button>
<button class="option-button" data-consulta="vehiculos">
<span class="option-icon">🚗</span>
<span class="option-text">Deuda Vehículos</span>
</button>
<button class="option-button" data-consulta="inmuebles">
<span class="option-icon">🏠</span>
<span class="option-text">Deuda Inmuebles</span>
</button>
<button class="option-button back-button" data-action="back">
<span class="option-icon">⬅️</span>
<span class="option-text">Volver al menú principal</span>
</button>
`;
renderOptions(consultasHTML);
document.querySelectorAll('[data-consulta]').forEach(button => {
button.addEventListener('click', function() {
const consulta = this.getAttribute('data-consulta');
redirectToConsulta(consulta);
});
});
addBackButtonListener();
}
async function showGovernmentSystemsOptions() {
addMessage("Estoy consultando la lista actualizada de sistemas de Gobierno Electrónico...", 'bot');
const systems = await loadGovernmentSystems();
if (!systems.length) {
addMessage("No pude cargar la lista de sistemas en este momento. Intenta nuevamente en unos segundos.", 'bot');
return;
}
const systemsHTML = systems.slice(0, 10).map(system => `
<button class="option-button" data-system-url="${escapeHtml(system.url)}" data-system-name="${escapeHtml(system.name)}">
<span class="option-icon">💻</span>
<span class="option-text">${escapeHtml(system.name)} - ${escapeHtml(system.status || 'Disponible')}</span>
</button>
`).join('') + `
<button class="option-button back-button" data-action="back">
<span class="option-icon">⬅️</span>
<span class="option-text">Volver al menú principal</span>
</button>
`;
renderOptions(systemsHTML);
document.querySelectorAll('[data-system-url]').forEach(button => {
button.addEventListener('click', function() {
const url = this.getAttribute('data-system-url');
const name = this.getAttribute('data-system-name');
if (url) {
addMessage(`Abriendo ${name}...`, 'bot');
window.open(url, '_blank');
} else {
addMessage(`${name} no tiene enlace público registrado.`, 'bot');
}
});
});
addBackButtonListener();
}
function showSeguimientoOptions() {
addMessage("Para hacer seguimiento de un caso, puedes ingresar al sistema ODECO y usar tu código o referencia.", 'bot');
const seguimientoHTML = `
<button class="option-button" data-tipo="SEGUIMIENTO">
<span class="option-icon">📊</span>
<span class="option-text">Abrir seguimiento ODECO</span>
</button>
<button class="option-button back-button" data-action="back">
<span class="option-icon">⬅️</span>
<span class="option-text">Volver al menú principal</span>
</button>
`;
renderOptions(seguimientoHTML);
document.querySelectorAll('[data-tipo]').forEach(button => {
button.addEventListener('click', function() {
redirectToOdeco(this.getAttribute('data-tipo'));
});
});
addBackButtonListener();
}
function addBackButtonListener() {
const backButton = document.querySelector('[data-action="back"]');
if (backButton) {
backButton.addEventListener('click', function() {
goBack();
});
}
}
function goBack() {
if (navigationStack.length > 1) {
navigationStack.pop();
}
const previousPage = navigationStack[navigationStack.length - 1];
switch(previousPage) {
case 'main':
addMessage("¿En qué más puedo ayudarte?", 'bot');
showMainOptions();
break;
case 'unidades':
showUnidadesOptions();
break;
case 'denuncia-reclamo':
showDenunciaReclamoOptions();
break;
case 'consultas':
showConsultasOptions();
break;
}
}
function handleOptionSelection(option) {
switch(option) {
case 'unidades':
navigationStack.push('unidades');
showUnidadesOptions();
break;
case 'consultas':
navigationStack.push('consultas');
showConsultasOptions();
break;
case 'sistemas':
navigationStack.push('sistemas');
showGovernmentSystemsOptions();
break;
case 'deportes':
redirectToApp('deportes', 'Redirigiendo al sistema de reservas deportivas...');
break;
case 'noticias':
redirectToNoticias();
break;
case 'quillacollo':
redirectToInfo();
break;
case 'denuncia-reclamo':
navigationStack.push('denuncia-reclamo');
showDenunciaReclamoOptions();
break;
case 'contacto':
redirectToContacto();
break;
}
}
function redirectToUnidad(unidad) {
const unidadNames = {
'agricola': 'Agrícola',
'cultura': 'Cultura',
'educacion': 'Educación',
'turismo': 'Turismo',
'zoonosis': 'Zoonosis',
'pecuaria': 'Pecuaria',
'riegos': 'Riegos',
'red-monica': 'Red Mónica',
'preservacion-ambiental': 'Preservación Ambiental',
'recursos-naturales': 'Recursos Naturales',
'parques-jardines': 'Parques y Jardines',
'forestal': 'Forestal',
'tdi': 'TDI - Sistemas',
'ugr': 'UGR',
'dio': 'DIO'
};
const urls = {
'agricola': 'modules/unidades/index-Agricola.html',
'cultura': 'modules/unidades/index-Cultura.html',
'educacion': 'modules/unidades/index-Educacion.html',
'turismo': 'modules/unidades/index-Turismo.html',
'zoonosis': 'modules/unidades/index-Zoonosis.html',
'pecuaria': 'modules/unidades/index-Pecuaria.html',
'riegos': 'modules/unidades/index-Riegos.html',
'red-monica': 'modules/unidades/index-Red-Monica.html',
'preservacion-ambiental': 'modules/unidades/index-Preservacion-ambiental.html',
'recursos-naturales': 'modules/unidades/index-Recursos-naturales.html',
'parques-jardines': 'modules/unidades/index-Parques-jardines.html',
'forestal': 'modules/unidades/index-Forestal.html',
'tdi': 'modules/unidades/index-TDI.html',
'ugr': 'modules/unidades/index-UGR.html',
'dio': 'modules/unidades/index-DIO.html'
};
const url = urls[unidad] || 'modules/unidades/';
const name = unidadNames[unidad] || unidad;
addMessage(`Redirigiendo a la unidad de ${name}...`, 'bot');
setTimeout(() => {
window.location.href = siteUrl(url);
}, 1000);
}
function redirectToNoticias() {
addMessage("Redirigiendo a las últimas noticias del GAMQ...", 'bot');
setTimeout(() => {
window.location.href = siteUrl('pages/news.html');
}, 1000);
}
function redirectToInfo() {
addMessage("Redirigiendo a la información sobre Quillacollo...", 'bot');
setTimeout(() => {
window.location.href = siteUrl('pages/about.html');
}, 1000);
}
function redirectToOdeco(tipo) {
addMessage(`Redirigiendo al formulario de ${tipo.toLowerCase()}...`, 'bot');
setTimeout(() => {
window.location.href = `/app/odeco?tipo=${tipo}`;
}, 1000);
}
function redirectToContacto() {
addMessage("Te conectaré con nuestro equipo de atención a través de WhatsApp...", 'bot');
setTimeout(() => {
window.open('https://wa.me/59169528883?text=Hola,%20necesito%20información%20sobre%20los%20servicios%20del%20GAMQ', '_blank');
}, 1000);
}
function redirectToConsulta(tipo) {
const consultaInfo = {
'actividades': {
name: 'Actividades Económicas',
url: 'https://www.ruat.gob.bo/actividadeseconomicas/MenuActividadesEconomicas.jsf',
description: 'Consulta pagos QR, deudas, datos técnicos y más'
},
'vehiculos': {
name: 'Deuda de Vehículos',
url: 'https://www.ruat.gob.bo/vehiculos/MenuVehiculos.jsf',
description: 'Consulta deudas, infracciones, ITV y pagos de vehículos'
},
'inmuebles': {
name: 'Deuda de Inmuebles',
url: 'https://www.ruat.gob.bo/inmuebles/MenuInmuebles.jsf',
description: 'Consulta deudas de propiedades e inmuebles'
}
};
const info = consultaInfo[tipo];
addMessage(`Redirigiendo a la consulta de ${info.name}. ${info.description}.`, 'bot');
setTimeout(() => {
window.open(info.url, '_blank');
}, 1500);
}
function redirectToDeportes() {
addMessage("Redirigiendo al sistema de reservas deportivas. Podrás reservar canchas y complejos deportivos del municipio...", 'bot');
setTimeout(() => {
window.open('/app/deportes', '_blank');
}, 1500);
}
function redirectToApp(app, message = null, params = {}) {
if (message) {
addMessage(message, 'bot');
}
const query = new URLSearchParams(params).toString();
const url = `/app/${app}` + (query ? `?${query}` : '');
setTimeout(() => {
window.location.href = url;
}, 1000);
}
showMainOptions();
}
document.addEventListener('DOMContentLoaded', function() {
if (document.getElementById('chatbot-container')) {
initializeChatbot();
}
});