Spaces:
Running
Running
| // SoberanIA Argentina - Main Application JavaScript | |
| // Global variables | |
| let userCount = 1247500; | |
| let redistributedAmount = 45320780000; | |
| let pesoDAmount = 32654892300; | |
| let currentTestimonial = 0; | |
| let cart = []; | |
| let userBalance = 25450; | |
| // Initialize application | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initializeApp(); | |
| }); | |
| function initializeApp() { | |
| setupNavigation(); | |
| setupCounters(); | |
| setupCountdown(); | |
| setupMarketplace(); | |
| setupFintech(); | |
| setupSorteos(); | |
| setupImpacto(); | |
| setupModals(); | |
| setupMobileMenu(); | |
| setupCharts(); | |
| loadInitialData(); | |
| // Update counters every few seconds | |
| setInterval(updateCounters, 3000); | |
| setInterval(updateCountdown, 1000); | |
| } | |
| // Navigation functionality | |
| function setupNavigation() { | |
| const navLinks = document.querySelectorAll('.nav-link'); | |
| const sections = document.querySelectorAll('.section'); | |
| navLinks.forEach(link => { | |
| link.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| const targetId = this.getAttribute('href').substring(1); | |
| // Update active nav link | |
| navLinks.forEach(l => l.classList.remove('active')); | |
| this.classList.add('active'); | |
| // Show target section | |
| sections.forEach(section => { | |
| section.classList.remove('active'); | |
| }); | |
| const targetSection = document.getElementById(targetId); | |
| if (targetSection) { | |
| targetSection.classList.add('active'); | |
| } | |
| }); | |
| }); | |
| } | |
| // Counter functionality | |
| function setupCounters() { | |
| updateCounterDisplay('usuarios-counter', userCount); | |
| updateCounterDisplay('redistribucion-counter', redistributedAmount, true); | |
| updateCounterDisplay('pesod-counter', pesoDAmount, true); | |
| updateCounterDisplay('total-redistribuido', redistributedAmount, true); | |
| } | |
| function updateCounters() { | |
| // Simulate real-time growth | |
| userCount += Math.floor(Math.random() * 5) + 1; | |
| redistributedAmount += Math.floor(Math.random() * 50000) + 10000; | |
| pesoDAmount += Math.floor(Math.random() * 30000) + 5000; | |
| updateCounterDisplay('usuarios-counter', userCount); | |
| updateCounterDisplay('redistribucion-counter', redistributedAmount, true); | |
| updateCounterDisplay('pesod-counter', pesoDAmount, true); | |
| updateCounterDisplay('total-redistribuido', redistributedAmount, true); | |
| } | |
| function updateCounterDisplay(elementId, value, isCurrency = false) { | |
| const element = document.getElementById(elementId); | |
| if (element) { | |
| const formattedValue = isCurrency ? formatCurrency(value) : formatNumber(value); | |
| element.textContent = formattedValue; | |
| element.style.animation = 'none'; | |
| element.offsetHeight; // Trigger reflow | |
| element.style.animation = 'counter-update 0.5s ease-out'; | |
| } | |
| } | |
| function formatNumber(num) { | |
| return num.toLocaleString('es-AR'); | |
| } | |
| function formatCurrency(num) { | |
| return '$' + num.toLocaleString('es-AR'); | |
| } | |
| // Countdown functionality | |
| function setupCountdown() { | |
| updateCountdown(); | |
| } | |
| function updateCountdown() { | |
| const targetDate = new Date('2025-06-15T20:00:00'); | |
| const now = new Date(); | |
| const timeDiff = targetDate - now; | |
| if (timeDiff > 0) { | |
| const days = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); | |
| const hours = Math.floor((timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); | |
| const minutes = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60)); | |
| const seconds = Math.floor((timeDiff % (1000 * 60)) / 1000); | |
| // Update main countdown | |
| const countdownEl = document.getElementById('sorteo-countdown'); | |
| if (countdownEl) { | |
| countdownEl.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`; | |
| } | |
| // Update detailed countdown | |
| updateElement('countdown-days', days); | |
| updateElement('countdown-hours', hours); | |
| updateElement('countdown-minutes', minutes); | |
| updateElement('countdown-seconds', seconds); | |
| } | |
| } | |
| function updateElement(id, value) { | |
| const element = document.getElementById(id); | |
| if (element) { | |
| element.textContent = value.toString().padStart(2, '0'); | |
| } | |
| } | |
| // Marketplace functionality | |
| function setupMarketplace() { | |
| setupSearch(); | |
| setupCategoryFilters(); | |
| setupPublishModal(); | |
| setupCartSidebar(); | |
| setupAddToCart(); | |
| } | |
| function setupSearch() { | |
| const searchForm = document.querySelector('.search-form'); | |
| const searchInput = document.getElementById('search-input'); | |
| if (searchForm) { | |
| searchForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const query = searchInput.value.trim(); | |
| if (query) { | |
| performSearch(query); | |
| } | |
| }); | |
| } | |
| } | |
| function performSearch(query) { | |
| const products = document.querySelectorAll('.product-card'); | |
| let visibleCount = 0; | |
| products.forEach(product => { | |
| const title = product.querySelector('.product-title').textContent.toLowerCase(); | |
| const seller = product.querySelector('.seller-name').textContent.toLowerCase(); | |
| if (title.includes(query.toLowerCase()) || seller.includes(query.toLowerCase())) { | |
| product.style.display = 'block'; | |
| visibleCount++; | |
| } else { | |
| product.style.display = 'none'; | |
| } | |
| }); | |
| showNotification(`Se encontraron ${visibleCount} productos para "${query}"`); | |
| } | |
| function setupCategoryFilters() { | |
| const categoryBtns = document.querySelectorAll('.category-btn'); | |
| categoryBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const category = this.getAttribute('data-category'); | |
| // Update active button | |
| categoryBtns.forEach(b => b.classList.remove('active')); | |
| this.classList.add('active'); | |
| // Filter products | |
| filterProducts(category); | |
| }); | |
| }); | |
| } | |
| function filterProducts(category) { | |
| const products = document.querySelectorAll('.product-card'); | |
| products.forEach(product => { | |
| if (category === 'all' || product.getAttribute('data-category') === category) { | |
| product.style.display = 'block'; | |
| } else { | |
| product.style.display = 'none'; | |
| } | |
| }); | |
| } | |
| function setupPublishModal() { | |
| const publishBtn = document.getElementById('publish-btn'); | |
| const publishModal = document.getElementById('publish-modal'); | |
| const publishForm = document.getElementById('publish-form'); | |
| const cancelBtn = document.getElementById('cancel-publish'); | |
| if (publishBtn && publishModal) { | |
| publishBtn.addEventListener('click', () => { | |
| publishModal.classList.add('active'); | |
| document.getElementById('overlay').classList.add('active'); | |
| }); | |
| if (cancelBtn) { | |
| cancelBtn.addEventListener('click', () => { | |
| publishModal.classList.remove('active'); | |
| document.getElementById('overlay').classList.remove('active'); | |
| }); | |
| } | |
| if (publishForm) { | |
| publishForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| handleProductPublish(); | |
| }); | |
| } | |
| } | |
| } | |
| function handleProductPublish() { | |
| const title = document.getElementById('product-title').value; | |
| const price = document.getElementById('product-price').value; | |
| const category = document.getElementById('product-category').value; | |
| const description = document.getElementById('product-description').value; | |
| if (title && price && category && description) { | |
| showNotification('¡Producto publicado exitosamente! Se agregará al marketplace en breve.'); | |
| document.getElementById('publish-modal').classList.remove('active'); | |
| document.getElementById('overlay').classList.remove('active'); | |
| document.getElementById('publish-form').reset(); | |
| } else { | |
| showNotification('Por favor complete todos los campos requeridos.', 'error'); | |
| } | |
| } | |
| function setupCartSidebar() { | |
| const cartSidebar = document.getElementById('cart-sidebar'); | |
| const closeSidebar = document.querySelector('.close-sidebar'); | |
| if (closeSidebar) { | |
| closeSidebar.addEventListener('click', () => { | |
| cartSidebar.classList.remove('active'); | |
| document.getElementById('overlay').classList.remove('active'); | |
| }); | |
| } | |
| } | |
| function setupAddToCart() { | |
| const addToCartBtns = document.querySelectorAll('.add-to-cart-btn'); | |
| addToCartBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const productCard = this.closest('.product-card'); | |
| const title = productCard.querySelector('.product-title').textContent; | |
| const price = parseInt(productCard.querySelector('.product-price').textContent.replace('$', '').replace(/,/g, '')); | |
| const seller = productCard.querySelector('.seller-name').textContent; | |
| addToCart({ title, price, seller, quantity: 1 }); | |
| showCart(); | |
| }); | |
| }); | |
| } | |
| function addToCart(product) { | |
| const existingItem = cart.find(item => item.title === product.title); | |
| if (existingItem) { | |
| existingItem.quantity += 1; | |
| } else { | |
| cart.push(product); | |
| } | |
| updateCartDisplay(); | |
| showNotification(`${product.title} agregado al carrito`); | |
| } | |
| function showCart() { | |
| const cartSidebar = document.getElementById('cart-sidebar'); | |
| cartSidebar.classList.add('active'); | |
| document.getElementById('overlay').classList.add('active'); | |
| } | |
| function updateCartDisplay() { | |
| const cartItems = document.getElementById('cart-items'); | |
| const cartSubtotal = document.getElementById('cart-subtotal'); | |
| const cartFee = document.getElementById('cart-fee'); | |
| const cartTotal = document.getElementById('cart-total'); | |
| const checkoutBtn = document.getElementById('checkout-btn'); | |
| if (cart.length === 0) { | |
| cartItems.innerHTML = ` | |
| <div class="empty-cart"> | |
| <i class="fas fa-shopping-cart fa-4x"></i> | |
| <p>Tu carrito está vacío</p> | |
| </div> | |
| `; | |
| checkoutBtn.disabled = true; | |
| } else { | |
| let itemsHTML = ''; | |
| let subtotal = 0; | |
| cart.forEach((item, index) => { | |
| const itemTotal = item.price * item.quantity; | |
| subtotal += itemTotal; | |
| itemsHTML += ` | |
| <div class="cart-item"> | |
| <div class="item-details"> | |
| <h4>${item.title}</h4> | |
| <p>Vendedor: ${item.seller}</p> | |
| <p>Precio: ${formatCurrency(item.price)}</p> | |
| </div> | |
| <div class="item-quantity"> | |
| <button onclick="updateCartQuantity(${index}, -1)">-</button> | |
| <span>${item.quantity}</span> | |
| <button onclick="updateCartQuantity(${index}, 1)">+</button> | |
| </div> | |
| <div class="item-total">${formatCurrency(itemTotal)}</div> | |
| </div> | |
| `; | |
| }); | |
| cartItems.innerHTML = itemsHTML; | |
| checkoutBtn.disabled = false; | |
| // SoberanIA has 0% commission | |
| const fee = 0; | |
| const total = subtotal + fee; | |
| cartSubtotal.textContent = formatCurrency(subtotal); | |
| cartFee.textContent = formatCurrency(fee); | |
| cartTotal.textContent = formatCurrency(total); | |
| } | |
| } | |
| function updateCartQuantity(index, change) { | |
| if (cart[index]) { | |
| cart[index].quantity += change; | |
| if (cart[index].quantity <= 0) { | |
| cart.splice(index, 1); | |
| } | |
| updateCartDisplay(); | |
| } | |
| } | |
| // Fintech functionality | |
| function setupFintech() { | |
| setupWalletActions(); | |
| setupTransferForm(); | |
| setupInvestmentCalculator(); | |
| setupCreditCalculator(); | |
| setupSendMoneyModal(); | |
| } | |
| function setupWalletActions() { | |
| const sendMoneyBtn = document.getElementById('send-money-btn'); | |
| const receiveMoneyBtn = document.getElementById('receive-money-btn'); | |
| const exchangeBtn = document.getElementById('exchange-btn'); | |
| if (sendMoneyBtn) { | |
| sendMoneyBtn.addEventListener('click', () => { | |
| document.getElementById('send-money-modal').classList.add('active'); | |
| document.getElementById('overlay').classList.add('active'); | |
| }); | |
| } | |
| if (receiveMoneyBtn) { | |
| receiveMoneyBtn.addEventListener('click', () => { | |
| showNotification('Código QR generado para recibir PESO-D. Compártelo con quien quiera enviarte dinero.'); | |
| }); | |
| } | |
| if (exchangeBtn) { | |
| exchangeBtn.addEventListener('click', () => { | |
| showNotification('Funcionalidad de intercambio próximamente disponible.'); | |
| }); | |
| } | |
| } | |
| function setupTransferForm() { | |
| const transferForm = document.getElementById('transfer-form'); | |
| if (transferForm) { | |
| transferForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const recipient = document.getElementById('transfer-recipient').value; | |
| const amount = parseFloat(document.getElementById('transfer-amount').value); | |
| const concept = document.getElementById('transfer-concept').value; | |
| if (recipient && amount > 0) { | |
| if (amount <= userBalance) { | |
| processTransfer(recipient, amount, concept); | |
| } else { | |
| showNotification('Saldo insuficiente para realizar la transferencia.', 'error'); | |
| } | |
| } else { | |
| showNotification('Por favor complete los campos requeridos.', 'error'); | |
| } | |
| }); | |
| } | |
| } | |
| function processTransfer(recipient, amount, concept) { | |
| userBalance -= amount; | |
| updateWalletBalance(); | |
| showNotification(`Transferencia de ${formatCurrency(amount)} realizada exitosamente a ${recipient}`); | |
| document.getElementById('transfer-form').reset(); | |
| // Add to transaction history (simulation) | |
| addTransactionToHistory('outgoing', `Transferencia a ${recipient}`, amount, concept); | |
| } | |
| function updateWalletBalance() { | |
| const balanceElement = document.querySelector('.balance-amount'); | |
| if (balanceElement) { | |
| balanceElement.textContent = formatCurrency(userBalance); | |
| } | |
| } | |
| function setupInvestmentCalculator() { | |
| const investmentForm = document.getElementById('investment-form'); | |
| const amountInput = document.getElementById('investment-amount'); | |
| const timeInput = document.getElementById('investment-time'); | |
| const typeSelect = document.getElementById('investment-type'); | |
| if (investmentForm && amountInput && timeInput && typeSelect) { | |
| // Update range display | |
| timeInput.addEventListener('input', function() { | |
| document.getElementById('investment-time-value').textContent = this.value; | |
| calculateInvestment(); | |
| }); | |
| amountInput.addEventListener('input', calculateInvestment); | |
| typeSelect.addEventListener('change', calculateInvestment); | |
| investmentForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const amount = parseFloat(amountInput.value); | |
| if (amount <= userBalance) { | |
| processInvestment(amount); | |
| } else { | |
| showNotification('Saldo insuficiente para realizar la inversión.', 'error'); | |
| } | |
| }); | |
| // Initial calculation | |
| calculateInvestment(); | |
| } | |
| } | |
| function calculateInvestment() { | |
| const amount = parseFloat(document.getElementById('investment-amount').value) || 0; | |
| const months = parseInt(document.getElementById('investment-time').value) || 1; | |
| const type = document.getElementById('investment-type').value; | |
| let monthlyRate = 0.03; // Default 3% | |
| switch(type) { | |
| case 'bonds': | |
| monthlyRate = 0.03; | |
| break; | |
| case 'cooperative': | |
| monthlyRate = 0.025; | |
| break; | |
| case 'infrastructure': | |
| monthlyRate = 0.022; | |
| break; | |
| } | |
| const finalAmount = amount * Math.pow(1 + monthlyRate, months); | |
| const interest = finalAmount - amount; | |
| const annualYield = (monthlyRate * 12 * 100); | |
| document.getElementById('investment-final').textContent = formatCurrency(finalAmount); | |
| document.getElementById('investment-interest').textContent = formatCurrency(interest); | |
| document.getElementById('investment-yield').textContent = annualYield.toFixed(1) + '%'; | |
| } | |
| function processInvestment(amount) { | |
| userBalance -= amount; | |
| updateWalletBalance(); | |
| showNotification(`Inversión de ${formatCurrency(amount)} realizada exitosamente. Los rendimientos se acreditarán mensualmente.`); | |
| // Add to transaction history | |
| addTransactionToHistory('neutral', 'Inversión en Bonos Soberanos', amount); | |
| } | |
| function setupCreditCalculator() { | |
| const creditForm = document.getElementById('credit-form'); | |
| const amountInput = document.getElementById('credit-amount'); | |
| const timeInput = document.getElementById('credit-time'); | |
| const purposeSelect = document.getElementById('credit-purpose'); | |
| if (creditForm && amountInput && timeInput && purposeSelect) { | |
| // Update range display | |
| timeInput.addEventListener('input', function() { | |
| document.getElementById('credit-time-value').textContent = this.value; | |
| calculateCredit(); | |
| }); | |
| amountInput.addEventListener('input', calculateCredit); | |
| purposeSelect.addEventListener('change', calculateCredit); | |
| creditForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| processCreditRequest(); | |
| }); | |
| // Initial calculation | |
| calculateCredit(); | |
| } | |
| } | |
| function calculateCredit() { | |
| const amount = parseFloat(document.getElementById('credit-amount').value) || 0; | |
| const months = parseInt(document.getElementById('credit-time').value) || 1; | |
| const purpose = document.getElementById('credit-purpose').value; | |
| let monthlyRate = 0.018; // Default 1.8% | |
| switch(purpose) { | |
| case 'personal': | |
| monthlyRate = 0.018; | |
| break; | |
| case 'productive': | |
| monthlyRate = 0.015; | |
| break; | |
| case 'cooperative': | |
| monthlyRate = 0.012; | |
| break; | |
| } | |
| // Calculate monthly payment using amortization formula | |
| const monthlyPayment = amount * (monthlyRate * Math.pow(1 + monthlyRate, months)) / (Math.pow(1 + monthlyRate, months) - 1); | |
| const totalPayment = monthlyPayment * months; | |
| const annualRate = (Math.pow(1 + monthlyRate, 12) - 1) * 100; | |
| document.getElementById('credit-monthly').textContent = formatCurrency(monthlyPayment); | |
| document.getElementById('credit-total').textContent = formatCurrency(totalPayment); | |
| document.getElementById('credit-rate').textContent = annualRate.toFixed(2) + '%'; | |
| } | |
| function processCreditRequest() { | |
| const amount = parseFloat(document.getElementById('credit-amount').value); | |
| showNotification(`Solicitud de crédito por ${formatCurrency(amount)} enviada. Será evaluada por la comunidad de prestamistas en 24-48 horas.`); | |
| } | |
| function setupSendMoneyModal() { | |
| const sendMoneyModal = document.getElementById('send-money-modal'); | |
| const sendMoneyForm = document.getElementById('send-money-form'); | |
| const cancelSendBtn = document.getElementById('cancel-send'); | |
| if (cancelSendBtn) { | |
| cancelSendBtn.addEventListener('click', () => { | |
| sendMoneyModal.classList.remove('active'); | |
| document.getElementById('overlay').classList.remove('active'); | |
| }); | |
| } | |
| if (sendMoneyForm) { | |
| sendMoneyForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const recipient = document.getElementById('send-recipient').value; | |
| const amount = parseFloat(document.getElementById('send-amount').value); | |
| const concept = document.getElementById('send-concept').value; | |
| if (recipient && amount > 0) { | |
| if (amount <= userBalance) { | |
| processTransfer(recipient, amount, concept); | |
| sendMoneyModal.classList.remove('active'); | |
| document.getElementById('overlay').classList.remove('active'); | |
| sendMoneyForm.reset(); | |
| } else { | |
| showNotification('Saldo insuficiente.', 'error'); | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| function addTransactionToHistory(type, title, amount, concept = '') { | |
| // This would normally update a database, here we just show a notification | |
| const typeText = type === 'incoming' ? 'recibida' : type === 'outgoing' ? 'enviada' : 'procesada'; | |
| showNotification(`Transacción ${typeText}: ${formatCurrency(amount)}`); | |
| } | |
| // Sorteos functionality | |
| function setupSorteos() { | |
| // Sorteo countdown is handled by the global countdown function | |
| // Additional sorteo-specific functionality can be added here | |
| } | |
| // Impacto Social functionality | |
| function setupImpacto() { | |
| setupTestimonialCarousel(); | |
| setupComparisonTabs(); | |
| } | |
| function setupTestimonialCarousel() { | |
| const testimonials = document.querySelectorAll('.testimonial-slide'); | |
| const indicators = document.querySelectorAll('.indicator'); | |
| const prevBtn = document.getElementById('testimonial-prev'); | |
| const nextBtn = document.getElementById('testimonial-next'); | |
| if (prevBtn) { | |
| prevBtn.addEventListener('click', () => { | |
| showTestimonial(currentTestimonial - 1); | |
| }); | |
| } | |
| if (nextBtn) { | |
| nextBtn.addEventListener('click', () => { | |
| showTestimonial(currentTestimonial + 1); | |
| }); | |
| } | |
| indicators.forEach((indicator, index) => { | |
| indicator.addEventListener('click', () => { | |
| showTestimonial(index); | |
| }); | |
| }); | |
| // Auto-advance testimonials | |
| setInterval(() => { | |
| showTestimonial(currentTestimonial + 1); | |
| }, 8000); | |
| } | |
| function showTestimonial(index) { | |
| const testimonials = document.querySelectorAll('.testimonial-slide'); | |
| const indicators = document.querySelectorAll('.indicator'); | |
| if (index >= testimonials.length) { | |
| currentTestimonial = 0; | |
| } else if (index < 0) { | |
| currentTestimonial = testimonials.length - 1; | |
| } else { | |
| currentTestimonial = index; | |
| } | |
| testimonials.forEach((slide, i) => { | |
| slide.classList.toggle('active', i === currentTestimonial); | |
| }); | |
| indicators.forEach((indicator, i) => { | |
| indicator.classList.toggle('active', i === currentTestimonial); | |
| }); | |
| } | |
| function setupComparisonTabs() { | |
| const tabControls = document.querySelectorAll('.tab-control'); | |
| const tabPanes = document.querySelectorAll('.tab-pane'); | |
| tabControls.forEach(control => { | |
| control.addEventListener('click', function() { | |
| const targetTab = this.getAttribute('data-tab'); | |
| // Update active control | |
| tabControls.forEach(c => c.classList.remove('active')); | |
| this.classList.add('active'); | |
| // Show target pane | |
| tabPanes.forEach(pane => { | |
| pane.classList.remove('active'); | |
| }); | |
| const targetPane = document.getElementById(targetTab); | |
| if (targetPane) { | |
| targetPane.classList.add('active'); | |
| } | |
| }); | |
| }); | |
| } | |
| // Modal functionality | |
| function setupModals() { | |
| const modals = document.querySelectorAll('.modal'); | |
| const closeModalBtns = document.querySelectorAll('.close-modal'); | |
| const overlay = document.getElementById('overlay'); | |
| closeModalBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const modal = this.closest('.modal'); | |
| modal.classList.remove('active'); | |
| overlay.classList.remove('active'); | |
| }); | |
| }); | |
| overlay.addEventListener('click', function() { | |
| modals.forEach(modal => modal.classList.remove('active')); | |
| document.querySelectorAll('.sidebar').forEach(sidebar => sidebar.classList.remove('active')); | |
| this.classList.remove('active'); | |
| }); | |
| } | |
| // Mobile menu functionality | |
| function setupMobileMenu() { | |
| const mobileToggle = document.querySelector('.mobile-menu-toggle'); | |
| const mainNav = document.querySelector('.main-nav'); | |
| if (mobileToggle) { | |
| mobileToggle.addEventListener('click', function() { | |
| mainNav.classList.toggle('active'); | |
| this.classList.toggle('active'); | |
| }); | |
| } | |
| } | |
| // Charts functionality | |
| function setupCharts() { | |
| setupUsuariosChart(); | |
| setupDistributionChart(); | |
| setupRedistributionChart(); | |
| } | |
| function setupUsuariosChart() { | |
| const ctx = document.getElementById('usuarios-chart'); | |
| if (ctx) { | |
| new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun'], | |
| datasets: [{ | |
| label: 'Usuarios Registrados', | |
| data: [450000, 620000, 780000, 920000, 1100000, 1247500], | |
| borderColor: '#1FB8CD', | |
| backgroundColor: 'rgba(31, 184, 205, 0.1)', | |
| tension: 0.4, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| ticks: { | |
| callback: function(value) { | |
| return (value / 1000000).toFixed(1) + 'M'; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| function setupDistributionChart() { | |
| const ctx = document.getElementById('distribution-chart'); | |
| if (ctx) { | |
| new Chart(ctx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: ['Jubilados (70%)', 'Vulnerables (20%)', 'General (10%)'], | |
| datasets: [{ | |
| data: [70, 20, 10], | |
| backgroundColor: ['#1FB8CD', '#FFC185', '#B4413C'], | |
| borderWidth: 0 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| position: 'bottom' | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| function setupRedistributionChart() { | |
| const ctx = document.getElementById('redistribution-chart'); | |
| if (ctx) { | |
| new Chart(ctx, { | |
| type: 'bar', | |
| data: { | |
| labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun'], | |
| datasets: [{ | |
| label: 'Redistribuido (Millones ARS)', | |
| data: [2800, 4200, 5900, 7100, 8500, 9800], | |
| backgroundColor: '#1FB8CD', | |
| borderRadius: 4 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| ticks: { | |
| callback: function(value) { | |
| return '$' + value + 'M'; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| // Load initial data | |
| function loadInitialData() { | |
| // Simulate loading products, user data, etc. | |
| updateWalletBalance(); | |
| // Load more products functionality | |
| const loadMoreBtn = document.getElementById('load-more-btn'); | |
| if (loadMoreBtn) { | |
| loadMoreBtn.addEventListener('click', function() { | |
| showNotification('Cargando más productos...'); | |
| // Simulate loading delay | |
| setTimeout(() => { | |
| showNotification('Más productos cargados exitosamente!'); | |
| }, 1000); | |
| }); | |
| } | |
| } | |
| // Utility functions | |
| function showNotification(message, type = 'success') { | |
| // Create notification element | |
| const notification = document.createElement('div'); | |
| notification.className = `notification notification--${type}`; | |
| notification.innerHTML = ` | |
| <div class="notification-content"> | |
| <i class="fas fa-${type === 'success' ? 'check-circle' : type === 'error' ? 'exclamation-circle' : 'info-circle'}"></i> | |
| <span>${message}</span> | |
| </div> | |
| `; | |
| // Add styles for notification | |
| notification.style.cssText = ` | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background: ${type === 'success' ? '#22c55e' : type === 'error' ? '#ef4444' : '#3b82f6'}; | |
| color: white; | |
| padding: 16px 20px; | |
| border-radius: 8px; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); | |
| z-index: 1002; | |
| transform: translateX(100%); | |
| transition: transform 0.3s ease; | |
| max-width: 400px; | |
| font-size: 14px; | |
| `; | |
| const content = notification.querySelector('.notification-content'); | |
| content.style.cssText = ` | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| `; | |
| document.body.appendChild(notification); | |
| // Animate in | |
| setTimeout(() => { | |
| notification.style.transform = 'translateX(0)'; | |
| }, 100); | |
| // Remove after delay | |
| setTimeout(() => { | |
| notification.style.transform = 'translateX(100%)'; | |
| setTimeout(() => { | |
| if (notification.parentNode) { | |
| notification.parentNode.removeChild(notification); | |
| } | |
| }, 300); | |
| }, 3000); | |
| } | |
| // --- FUNCIONES AUXILIARES --- | |
| function showNotification(message, type = 'success') { | |
| // Ejemplo básico de notificación (puedes mejorarlo con un modal o toast) | |
| alert(message); | |
| } | |
| // --- SETUP DEL REGISTRO --- | |
| function setupRegisterModal() { | |
| const registerBtn = document.querySelector('.btn--primary:nth-of-type(1)'); | |
| const registerModal = document.getElementById('register-modal'); | |
| const registerForm = document.getElementById('register-form'); | |
| const closeBtn = registerModal?.querySelector('.close-modal'); | |
| const overlay = document.getElementById('overlay'); | |
| if (!registerBtn || !registerModal || !registerForm) return; | |
| // Abrir modal | |
| registerBtn.addEventListener('click', () => { | |
| registerModal.classList.add('active'); | |
| overlay?.classList.add('active'); | |
| }); | |
| // Cerrar modal | |
| if (closeBtn) { | |
| closeBtn.addEventListener('click', () => { | |
| registerModal.classList.remove('active'); | |
| overlay?.classList.remove('active'); | |
| }); | |
| } | |
| if (overlay) { | |
| overlay.addEventListener('click', () => { | |
| registerModal.classList.remove('active'); | |
| overlay.classList.remove('active'); | |
| }); | |
| } | |
| // Enviar formulario | |
| registerForm.addEventListener('submit', async function(e) { | |
| e.preventDefault(); | |
| const username = document.getElementById('register-username').value; | |
| const password = document.getElementById('register-password').value; | |
| const email = document.getElementById('register-email').value; | |
| const dni = document.getElementById('register-dni').value; | |
| // Hash básico (en producción, usa una librería de hash real y una clave pública) | |
| const passwordHash = window.btoa(unescape(encodeURIComponent(password))); | |
| const dniHash = window.btoa(unescape(encodeURIComponent(dni))); | |
| const userData = { | |
| username, | |
| passwordHash, // Guarda el hash, NO la contraseña en texto plano | |
| email, | |
| dniHash, // Guarda el hash del DNI | |
| role: "user", | |
| activo: "1", | |
| fecha_registro: new Date().toISOString(), | |
| ultimo_acceso: "" | |
| }; | |
| // URL del endpoint de Google Apps Script (¡reemplázala por la tuya!) | |
| const endpoint = "https://script.google.com/macros/s/AKfycb.../exec"; | |
| try { | |
| const response = await fetch(endpoint, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(userData) | |
| }); | |
| const result = await response.json(); | |
| if (result.success) { | |
| showNotification('¡Registro exitoso!'); | |
| registerModal.classList.remove('active'); | |
| overlay?.classList.remove('active'); | |
| registerForm.reset(); | |
| } else { | |
| showNotification('Error al registrarse: ' + (result.error || 'Intente nuevamente'), 'error'); | |
| } | |
| } catch (error) { | |
| showNotification('Error de conexión: ' + error.message, 'error'); | |
| } | |
| }); | |
| } | |
| // --- EJEMPLO DE FUNCIÓN DE INICIALIZACIÓN --- | |
| function initializeApp() { | |
| // Tus funciones de inicialización (pueden ser diferentes) | |
| setupNavigation(); | |
| setupCounters(); | |
| setupCountdown(); | |
| setupMarketplace(); | |
| setupFintech(); | |
| setupSorteos(); | |
| setupImpacto(); | |
| setupModals(); | |
| setupMobileMenu(); | |
| setupCharts(); | |
| loadInitialData(); | |
| setupRegisterModal(); // <-- ¡IMPORTANTE! | |
| } | |
| // Inicializa la app cuando el DOM esté listo | |
| document.addEventListener('DOMContentLoaded', initializeApp); | |
| // Export functions for global access | |
| window.updateCartQuantity = updateCartQuantity; | |
| window.showTestimonial = showTestimonial; | |
| // Handle page visibility change to pause/resume animations | |
| document.addEventListener('visibilitychange', function() { | |
| if (document.hidden) { | |
| // Pause animations when page is not visible | |
| document.body.style.animationPlayState = 'paused'; | |
| } else { | |
| // Resume animations when page becomes visible | |
| document.body.style.animationPlayState = 'running'; | |
| } | |
| }); | |
| // Handle window resize for responsive chart updates | |
| window.addEventListener('resize', function() { | |
| // Charts will automatically handle resize with responsive: true | |
| // Additional responsive logic can be added here if needed | |
| }); | |
| console.log('SoberanIA Argentina application initialized successfully!'); |