// SoberanIA Argentina 2025 - App.js // Ecosistema Fintech Cooperativo // Datos de la aplicación const appData = { usuarios: { total: 783173, jubilados: 274211, vulnerables: 195793, generales: 313169 }, redistribucion: { total_acumulado: 45320780000, mes_actual: 8500000 }, transacciones: { volumen_mensual: 32654892300, p2p: 45, marketplace: 35, inversiones: 15, creditos: 5 }, sorteos: { fondo_actual: 12500000, ganadores_mes: { jubilados: 23, vulnerables: 8, generales: 5 }, proximo_sorteo: "2025-06-15T20:00:00" }, impacto: { soberania_economica: 45, inclusion_financiera: 67, mejora_jubilados: 73, ahorro_comisiones: 4500000000 }, cooperativas: { comercios_adheridos: 8742, provincias_activas: 24, municipios_participantes: 1247 } }; // DOM Elements const domElements = { // Navegación navLinks: document.querySelectorAll('.nav__link'), navToggle: document.getElementById('navToggle'), navMenu: document.getElementById('navMenu'), // Secciones sections: document.querySelectorAll('.section'), // Tema themeToggle: document.getElementById('themeToggle'), // Login loginBtn: document.getElementById('loginBtn'), registerBtn: document.getElementById('registerBtn'), loginModal: document.getElementById('loginModal'), closeModal: document.getElementById('closeModal'), biometricLogin: document.getElementById('biometricLogin'), // Contadores counters: document.querySelectorAll('.metric-card__number'), // Simulador de inversiones investmentAmount: document.getElementById('investmentAmount'), investmentTerm: document.getElementById('investmentTerm'), simulateBtn: document.getElementById('simulateBtn'), simulationResult: document.getElementById('simulationResult'), estimatedReturn: document.getElementById('estimatedReturn'), annualRate: document.getElementById('annualRate'), totalReturn: document.getElementById('totalReturn'), // Sorteo Countdown days: document.getElementById('days'), hours: document.getElementById('hours'), minutes: document.getElementById('minutes'), seconds: document.getElementById('seconds'), sorteoCountdown: document.getElementById('sorteoCountdown'), // Calculadora de probabilidades userCategory: document.getElementById('userCategory'), // Contenedor de notificaciones notificationContainer: document.getElementById('notificationContainer'), // Aprendizaje learnMoreBtn: document.getElementById('learnMoreBtn') }; // Inicialización de la aplicación document.addEventListener('DOMContentLoaded', () => { // Inicializar navegación initNavigation(); // Inicializar tema initTheme(); // Inicializar contadores initCounters(); // Inicializar simulador initSimulator(); // Inicializar cuenta regresiva initCountdown(); // Inicializar modales initModals(); // Inicializar calculadora de probabilidades initProbabilityCalculator(); // Inicializar funcionalidades del marketplace initMarketplace(); // Inicializar funcionalidades del DAO initDAO(); // Mostrar notificación de bienvenida después de 3 segundos setTimeout(() => { showNotification({ type: 'success', title: '¡Bienvenido a SoberanIA Argentina 2025!', message: 'Juntos construimos la primera economía digitalmente soberana' }); }, 3000); }); // Función para inicializar la navegación function initNavigation() { // Manejar clic en enlaces de navegación domElements.navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); // Remover clase activa de todos los enlaces domElements.navLinks.forEach(item => item.classList.remove('active')); // Agregar clase activa al enlace clickeado link.classList.add('active'); // Obtener el ID de la sección a mostrar const targetId = link.getAttribute('href').substring(1); // Ocultar todas las secciones domElements.sections.forEach(section => { section.classList.remove('section--active'); }); // Mostrar la sección seleccionada document.getElementById(targetId).classList.add('section--active'); // Si el menú móvil está abierto, cerrarlo if (domElements.navMenu && domElements.navMenu.classList.contains('active')) { domElements.navMenu.classList.remove('active'); toggleHamburgerIcon(); } // Scroll al inicio de la sección window.scrollTo({ top: 0, behavior: 'smooth' }); }); }); // Manejar toggle del menú en móvil if (domElements.navToggle) { domElements.navToggle.addEventListener('click', () => { if (domElements.navMenu) { domElements.navMenu.classList.toggle('active'); toggleHamburgerIcon(); } }); } // Función para animar el ícono hamburguesa function toggleHamburgerIcon() { if (!domElements.navToggle) return; const spans = domElements.navToggle.querySelectorAll('span'); spans.forEach(span => span.classList.toggle('active')); if (spans[0].classList.contains('active')) { spans[0].style.transform = 'rotate(45deg) translate(5px, 5px)'; spans[1].style.opacity = '0'; spans[2].style.transform = 'rotate(-45deg) translate(7px, -7px)'; } else { spans[0].style.transform = 'none'; spans[1].style.opacity = '1'; spans[2].style.transform = 'none'; } } } // Función para inicializar el tema function initTheme() { if (!domElements.themeToggle) return; // Verificar si hay un tema guardado en localStorage const savedTheme = 'light'; // Por defecto usamos claro debido a las restricciones de localStorage // Aplicar tema guardado o detectar preferencia del sistema if (savedTheme) { document.documentElement.setAttribute('data-color-scheme', savedTheme); updateThemeIcon(savedTheme); } else { // Detectar preferencia del sistema const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; const theme = prefersDarkMode ? 'dark' : 'light'; document.documentElement.setAttribute('data-color-scheme', theme); updateThemeIcon(theme); } // Manejar cambio de tema domElements.themeToggle.addEventListener('click', () => { const currentTheme = document.documentElement.getAttribute('data-color-scheme'); const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-color-scheme', newTheme); updateThemeIcon(newTheme); // Simulación de guardado en localStorage (no usado realmente por las restricciones) console.log(`Tema cambiado a: ${newTheme}`); // Mostrar notificación showNotification({ type: 'info', title: 'Tema cambiado', message: `Has cambiado al tema ${newTheme === 'dark' ? 'oscuro' : 'claro'}` }); }); // Actualizar ícono según el tema function updateThemeIcon(theme) { if (theme === 'dark') { domElements.themeToggle.innerHTML = ''; } else { domElements.themeToggle.innerHTML = ''; } } } // Función para inicializar los contadores animados function initCounters() { domElements.counters.forEach(counter => { if (!counter) return; const target = parseInt(counter.getAttribute('data-target').replace(/,/g, '')); const prefix = counter.getAttribute('data-prefix') || ''; const suffix = counter.getAttribute('data-suffix') || ''; const formatter = new Intl.NumberFormat('es-AR'); // Duración de la animación en ms const duration = 2000; const frameRate = 1000 / 60; // 60 fps const frames = duration / frameRate; // Incremento por frame const increment = target / frames; let currentCount = 0; // Función de animación function animate() { currentCount += increment; if (currentCount < target) { counter.textContent = prefix + formatter.format(Math.floor(currentCount)) + suffix; requestAnimationFrame(animate); } else { counter.textContent = prefix + formatter.format(target) + suffix; } } // Iniciar animación cuando el elemento esté en el viewport const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { animate(); observer.disconnect(); } }); }, { threshold: 0.1 }); observer.observe(counter); }); } // Función para inicializar el simulador de inversiones function initSimulator() { if (!domElements.simulateBtn) return; domElements.simulateBtn.addEventListener('click', () => { const amount = parseFloat(domElements.investmentAmount.value); const term = parseInt(domElements.investmentTerm.value); // Validación if (isNaN(amount) || amount <= 0) { showNotification({ type: 'error', title: 'Error en la simulación', message: 'Ingrese un monto válido para la inversión' }); return; } // Tasas de interés según plazo (simuladas) const rates = { 30: 65, // 65% anual para 30 días 90: 70, // 70% anual para 90 días 180: 75, // 75% anual para 180 días 365: 80 // 80% anual para 365 días }; const annualRate = rates[term]; const periodRate = annualRate * (term / 365); const interest = amount * (periodRate / 100); const total = amount + interest; // Formatear valores const formatter = new Intl.NumberFormat('es-AR', { style: 'currency', currency: 'ARS' }); // Actualizar resultados if (domElements.estimatedReturn) { domElements.estimatedReturn.textContent = formatter.format(interest); } if (domElements.annualRate) { domElements.annualRate.textContent = annualRate + '%'; } if (domElements.totalReturn) { domElements.totalReturn.textContent = formatter.format(total); } // Mostrar resultados if (domElements.simulationResult) { domElements.simulationResult.style.display = 'block'; } // Mostrar notificación showNotification({ type: 'success', title: 'Simulación completa', message: `Rendimiento estimado: ${formatter.format(interest)}` }); }); } // Función para inicializar la cuenta regresiva del sorteo function initCountdown() { // Fecha del próximo sorteo desde los datos const targetDate = new Date(appData.sorteos.proximo_sorteo); // Actualizar la cuenta regresiva cada segundo function updateCountdown() { const currentDate = new Date(); const difference = targetDate - currentDate; // Calcular días, horas, minutos y segundos const days = Math.floor(difference / (1000 * 60 * 60 * 24)); const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((difference % (1000 * 60)) / 1000); // Actualizar elementos DOM if (domElements.days) domElements.days.textContent = days; if (domElements.hours) domElements.hours.textContent = hours; if (domElements.minutes) domElements.minutes.textContent = minutes; if (domElements.seconds) domElements.seconds.textContent = seconds; // Formato compacto para el contador pequeño if (domElements.sorteoCountdown) { domElements.sorteoCountdown.innerHTML = `${days}d ${hours}h ${minutes}m`; } // Continuar actualizando if (difference > 0) { setTimeout(updateCountdown, 1000); } } // Iniciar cuenta regresiva updateCountdown(); } // Función para inicializar modales function initModals() { // Modal de login if (domElements.loginBtn && domElements.loginModal) { // Abrir modal domElements.loginBtn.addEventListener('click', () => { domElements.loginModal.classList.add('active'); }); // También abrir con el botón de registro if (domElements.registerBtn) { domElements.registerBtn.addEventListener('click', () => { domElements.loginModal.classList.add('active'); }); } // Cerrar modal if (domElements.closeModal) { domElements.closeModal.addEventListener('click', () => { domElements.loginModal.classList.remove('active'); }); } // Cerrar al hacer clic fuera del contenido domElements.loginModal.addEventListener('click', (e) => { if (e.target === domElements.loginModal) { domElements.loginModal.classList.remove('active'); } }); // Simulación de autenticación biométrica if (domElements.biometricLogin) { domElements.biometricLogin.addEventListener('click', () => { const scannerCircle = document.querySelector('.scanner-circle'); scannerCircle.classList.add('scanning'); domElements.biometricLogin.disabled = true; domElements.biometricLogin.innerHTML = ' Escaneando...'; // Simular proceso de escaneo setTimeout(() => { scannerCircle.classList.remove('scanning'); domElements.biometricLogin.disabled = false; domElements.biometricLogin.innerHTML = ' Autenticar'; // Cerrar modal domElements.loginModal.classList.remove('active'); // Mostrar notificación de éxito showNotification({ type: 'success', title: '¡Autenticación exitosa!', message: 'Bienvenido de nuevo, Usuario' }); // Simulación de usuario logueado if (domElements.loginBtn) { domElements.loginBtn.innerHTML = ' Mi Cuenta'; } }, 3000); }); } } // Modal de aprendizaje if (domElements.learnMoreBtn) { domElements.learnMoreBtn.addEventListener('click', () => { showNotification({ type: 'info', title: 'Video explicativo', message: 'El video tutorial se está cargando...' }); // Simular carga de video setTimeout(() => { const targetSection = document.getElementById('impacto'); // Cambiar a la sección de impacto domElements.sections.forEach(section => { section.classList.remove('section--active'); }); targetSection.classList.add('section--active'); // Actualizar navegación domElements.navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href') === '#impacto') { link.classList.add('active'); } }); // Scroll al inicio de la sección window.scrollTo({ top: 0, behavior: 'smooth' }); showNotification({ type: 'success', title: 'Conoce nuestro impacto', message: 'Descubre cómo estamos transformando Argentina' }); }, 1500); }); } } // Función para inicializar la calculadora de probabilidades function initProbabilityCalculator() { if (!domElements.userCategory) return; // Actualizar probabilidad al cambiar la categoría domElements.userCategory.addEventListener('change', updateProbability); // Actualizar inicialmente updateProbability(); function updateProbability() { const category = domElements.userCategory.value; let probability, boost; switch (category) { case 'jubilado': probability = '1 en 4,608'; boost = '70% mayor que usuarios generales'; break; case 'vulnerable': probability = '1 en 9,790'; boost = '20% mayor que usuarios generales'; break; case 'general': probability = '1 en 15,658'; boost = '0%'; break; default: probability = '1 en 12,000'; boost = 'estándar'; } // Actualizar en la interfaz const probabilityNumber = document.querySelector('.probability-number'); const probabilityBoost = document.querySelector('.probability-boost'); if (probabilityNumber) { probabilityNumber.textContent = probability; } if (probabilityBoost) { probabilityBoost.innerHTML = category !== 'general' ? ` ${boost}` : ` Probabilidad estándar`; } } } // Función para inicializar funcionalidades del marketplace function initMarketplace() { // Filtros del marketplace const filterTags = document.querySelectorAll('.filter-tag'); if (filterTags) { filterTags.forEach(tag => { tag.addEventListener('click', () => { // Eliminar la clase active de todos los filtros filterTags.forEach(t => t.classList.remove('active')); // Agregar la clase active al filtro seleccionado tag.classList.add('active'); // Filtrar productos (simulado) showNotification({ type: 'info', title: 'Filtro aplicado', message: `Mostrando productos: ${tag.textContent}` }); }); }); } // Acciones de productos const productBtns = document.querySelectorAll('.product-card__actions .btn'); if (productBtns) { productBtns.forEach(btn => { btn.addEventListener('click', (e) => { const action = btn.textContent.trim(); const productName = btn.closest('.product-card').querySelector('h4').textContent; showNotification({ type: 'success', title: `Acción: ${action}`, message: `Has seleccionado: ${productName}` }); }); }); } // Búsqueda en el marketplace const searchBtn = document.querySelector('.search-btn'); if (searchBtn) { searchBtn.addEventListener('click', () => { const searchInput = document.querySelector('.search-input'); if (searchInput && searchInput.value.trim()) { showNotification({ type: 'info', title: 'Búsqueda inteligente', message: `Buscando: "${searchInput.value}"` }); } else { showNotification({ type: 'warning', title: 'Búsqueda vacía', message: 'Ingresa un término para buscar' }); } }); } } // Función para inicializar funcionalidades del DAO function initDAO() { // Botones de votación const voteButtons = document.querySelectorAll('.proposal-actions .btn'); if (voteButtons) { voteButtons.forEach(btn => { btn.addEventListener('click', () => { const isInFavor = btn.textContent.includes('A Favor'); const proposalTitle = btn.closest('.proposal-card').querySelector('h4').textContent; // Deshabilitar botones de votación para esa propuesta const buttons = btn.closest('.proposal-actions').querySelectorAll('.btn'); buttons.forEach(b => { b.disabled = true; b.classList.add('btn--disabled'); }); // Actualizar barra de votación (simulado) const voteBar = btn.closest('.proposal-card').querySelector( isInFavor ? '.vote-option--for .vote-fill' : '.vote-option--against .vote-fill' ); if (voteBar) { const currentWidth = parseFloat(voteBar.style.width); voteBar.style.width = (currentWidth + 2) + '%'; // Actualizar porcentaje const percentageElem = btn.closest('.proposal-card').querySelector( isInFavor ? '.vote-option--for .vote-percentage' : '.vote-option--against .vote-percentage' ); if (percentageElem) { const currentPercentage = parseInt(percentageElem.textContent); percentageElem.textContent = (currentPercentage + 2) + '%'; // Actualizar porcentaje opuesto const oppositeElem = btn.closest('.proposal-card').querySelector( isInFavor ? '.vote-option--against .vote-percentage' : '.vote-option--for .vote-percentage' ); if (oppositeElem) { const oppositePercentage = parseInt(oppositeElem.textContent); oppositeElem.textContent = (oppositePercentage - 2) + '%'; // Actualizar barra opuesta const oppositeBar = btn.closest('.proposal-card').querySelector( isInFavor ? '.vote-option--against .vote-fill' : '.vote-option--for .vote-fill' ); if (oppositeBar) { const oppositeWidth = parseFloat(oppositeBar.style.width); oppositeBar.style.width = (oppositeWidth - 2) + '%'; } } } } // Mostrar notificación showNotification({ type: 'success', title: 'Voto registrado', message: `Has votado ${isInFavor ? 'a favor' : 'en contra'} de: "${proposalTitle}"` }); }); }); } } // Función para mostrar notificaciones function showNotification(options) { if (!domElements.notificationContainer) return; const { type, title, message } = options; // Crear elemento de notificación const notification = document.createElement('div'); notification.className = `notification notification--${type}`; // Iconos según tipo let icon; switch (type) { case 'success': icon = 'check-circle'; break; case 'error': icon = 'exclamation-circle'; break; case 'warning': icon = 'exclamation-triangle'; break; case 'info': default: icon = 'info-circle'; } // Estructura de la notificación notification.innerHTML = `