A
Anonymous

Resumen Financiero

<!DOCTYPE html> <html lang="es ES"> <head> <meta charset="UTF 8"> <meta name="viewport" content="width=device width, initial scale=1.0"> <title>Panel Financiero</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="bg gray 50"> <div class="max w screen sm mx auto px 4 py 6"> <h1 class="text 2xl font bold text gray 800 mb 6 text center">Resumen Financiero</h1> <! Saldo General > <div class="mb 6 bg gradient to r from blue 500 to blue 600 rounded lg shadow p 6 text white"> <h2 class="text xl font semibold mb 3">Saldo General</h2> <div class="flex items center justify between"> <div> <p id="totalBalance" class="text 4xl font bold">¥0,00</p> <p class="text sm mt 1 text blue 100">Saldo disponible</p> </div> <div class="p 3 bg white/20 rounded full"> <svg class="h 10 w 10" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke linecap="round" stroke linejoin="round" stroke width="2" d="M12 8c 1.657 0 3 .895 3 2s1.343 2 3 2 3 .895 3 2 1.343 2 3 2m0 8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0 1c 1.11 0 2.08 .402 2.599 1M21 12a9 9 0 11 18 0 9 9 0 0118 0z" /> </svg> </div> </div> </div> <! Categorías > <div id="categoryCards" class="grid grid cols 2 gap 4"></div> </div> <! Modal > <div id="detailsModal" class="fixed inset 0 bg gray 800 bg opacity 75 flex items center justify center hidden"> <div class="bg white rounded lg shadow lg p 6 max w md w full"> <h2 id="modalCategory" class="text xl font semibold mb 4">Detalles de la Categoría</h2> <p id="modalTotal" class="text 2xl font bold mb 4">¥0,00</p> <ul id="modalSubcategories" class="list disc list inside"></ul> <button onclick="closeModal()" class="mt 4 bg blue 500 text white px 4 py 2 rounded">Cerrar</button> </div> </div> <script> const sheetUrl = "https://sheets.googleapis.com/v4/spreadsheets/1zie5dgzPmCqyxmCsSk85sRx2zpuiLZfo aOLA8kbVwo/values/Finanzas!A2:G?key=AIzaSyCqWowXx5GonkiHTwLcDz9E1VtXZzVCfv0"; document.addEventListener('DOMContentLoaded', async () => { const data = await fetchData(); renderSummary(data); renderCategoryCards(data); }); async function fetchData() { try { const response = await fetch(sheetUrl); if (!response.ok) throw new Error(`HTTP Error: ${response.status}`); const json = await response.json(); return json.values || []; } catch (error) { console.error('Error fetching data:', error); return []; } } function formatCurrency(amount) { return new Intl.NumberFormat('es ES', { style: 'currency', currency: 'CNY', minimumFractionDigits: 2 }).format(amount); } function renderSummary(data) { let totalExpenses = 0; let totalIncome = 0; data.forEach(row => { const [ , type, , , , amount] = row; const parsedAmount = parseFloat(amount); if (type === 'Gasto') totalExpenses += parsedAmount; if (type === 'Ingreso') totalIncome += parsedAmount; }); const balance = totalIncome totalExpenses; document.getElementById('totalBalance').textContent = formatCurrency(balance); } function renderCategoryCards(data) { const categories = {}; data.forEach(row => { const [ , type, category, subcategory, , amount] = row; const parsedAmount = parseFloat(amount); if (!categories[category]) categories[category] = { total: 0, subcategories: {} }; categories[category].total += parsedAmount * (type === 'Gasto' ? 1 : 1); if (!categories[category].subcategories[subcategory]) categories[category].subcategories[subcategory] = 0; categories[category].subcategories[subcategory] += parsedAmount * (type === 'Gasto' ? 1 : 1); }); const categoryCards = Object.entries(categories).map(([category, { total, subcategories }]) => ` <div class="bg white rounded lg shadow p 4 flex justify between items center hover:shadow lg"> <div> <h2 class="text lg font semibold text gray 700">${category}</h2> <p class="text 2xl font bold ${total < 0 ? 'text red 500' : 'text green 500'}">${formatCurrency(total)}</p> <button onclick="showDetails('${category}', ${total}, ${JSON.stringify(subcategories).replace(/"/g, '&quot;')})" class="mt 2 bg blue 500 text white px 4 py 2 rounded">Ver detalles</button> </div> <span class="p 2 ${total < 0 ? 'bg red 100' : 'bg green 100'} rounded full"> <svg class="h 6 w 6 ${total < 0 ? 'text red 500' : 'text green 500'}" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke linecap="round" stroke linejoin="round" stroke width="2" d="${total < 0 ? 'M19 14l 7 7m0 0l 7 7m7 7V3' : 'M5 10l7 7m0 0l7 7m 7 7v18'}" /> </svg> </span> </div> `).join(''); document.getElementById('categoryCards').innerHTML = categoryCards; } function showDetails(category, total, subcategories) { document.getElementById('modalCategory').textContent = `Detalles de ${category}`; document.getElementById('modalTotal').textContent = formatCurrency(total); const subcategoryList = Object.entries(subcategories).map(([subcategory, amount]) => ` <li>${subcategory}: ${formatCurrency(amount)}</li> `).join(''); document.getElementById('modalSubcategories').innerHTML = subcategoryList; document.getElementById('detailsModal').classList.remove('hidden'); } function closeModal() { document.getElementById('detailsModal').classList.add('hidden'); } </script> </body> </html> mejoralo

Prompt
Component Preview

About

Gestiona y visualiza tu saldo, gastos e ingresos con nuestro panel financiero intuitivo y fácil de usar. Mantén el control de tus finanzas desde cualquier lugar.

Share

Last updated 1 month ago