Created
December 28, 2025 17:33
-
-
Save Jcbertorello/51b4a5fc7486a851ec61500a15cb0056 to your computer and use it in GitHub Desktop.
Dashboard Ajonjolí - 2025-12-28 17:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Dashboard Octubre 2025 - Rendimiento de Películas y Distribuidoras - Cinexo</title> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| :root { | |
| --color-primary: #60B99A; | |
| --color-primary-light: #7FCDB2; | |
| --color-primary-dark: #4A9D80; | |
| --color-secondary: #1F3B4D; | |
| --color-secondary-light: #2D5066; | |
| --color-dark: #1e293b; | |
| --color-dark-soft: #334155; | |
| --color-muted: #64748b; | |
| --color-light: #94a3b8; | |
| --color-bg: #f8fafc; | |
| --color-bg-alt: #f1f5f9; | |
| --color-card: #ffffff; | |
| --color-border: #e2e8f0; | |
| --color-success: #16a34a; | |
| --color-success-bg: #dcfce7; | |
| --color-danger: #dc2626; | |
| --color-danger-bg: #fee2e2; | |
| --color-warning: #FFB74D; | |
| --color-warning-bg: #fff7ed; | |
| --color-boleteria: #60B99A; | |
| --color-candy: #FFB74D; | |
| --color-ocupacion-alta: #16a34a; | |
| --color-ocupacion-media: #FFB74D; | |
| --color-ocupacion-baja: #dc2626; | |
| } | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| body { | |
| font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; | |
| background-color: var(--color-bg); | |
| color: var(--color-dark); | |
| line-height: 1.6; | |
| min-height: 100vh; | |
| } | |
| .dashboard { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 32px 24px; | |
| } | |
| .action-buttons { | |
| display: flex; | |
| gap: 12px; | |
| margin-bottom: 24px; | |
| } | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 8px; | |
| padding: 12px 24px; | |
| border-radius: 12px; | |
| font-weight: 600; | |
| font-size: 0.95rem; | |
| cursor: pointer; | |
| border: none; | |
| transition: all 0.2s ease; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%); | |
| color: white; | |
| box-shadow: 0 4px 12px -2px rgba(96, 185, 154, 0.4); | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 16px -2px rgba(96, 185, 154, 0.5); | |
| } | |
| .btn-secondary { | |
| background-color: var(--color-card); | |
| color: var(--color-dark); | |
| border: 1px solid var(--color-border); | |
| } | |
| .btn-secondary:hover { | |
| background-color: var(--color-bg-alt); | |
| border-color: var(--color-primary); | |
| } | |
| .header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| margin-bottom: 32px; | |
| flex-wrap: wrap; | |
| gap: 20px; | |
| } | |
| .header-left { | |
| display: flex; | |
| align-items: center; | |
| gap: 16px; | |
| } | |
| .logo { | |
| width: 56px; | |
| height: 56px; | |
| background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%); | |
| border-radius: 16px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 1.5rem; | |
| font-weight: 800; | |
| box-shadow: 0 8px 20px -4px rgba(96, 185, 154, 0.4); | |
| } | |
| .header-title { | |
| font-size: 1.75rem; | |
| font-weight: 800; | |
| color: var(--color-dark); | |
| margin-bottom: 4px; | |
| } | |
| .header-subtitle { | |
| font-size: 0.95rem; | |
| color: var(--color-muted); | |
| } | |
| .header-date { | |
| font-size: 0.85rem; | |
| color: var(--color-light); | |
| text-align: right; | |
| } | |
| .info-bar { | |
| background: var(--color-card); | |
| border: 1px solid var(--color-border); | |
| border-left: 4px solid var(--color-primary); | |
| border-radius: 12px; | |
| padding: 16px 20px; | |
| margin-bottom: 24px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| gap: 12px; | |
| } | |
| .info-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| font-size: 0.875rem; | |
| color: var(--color-muted); | |
| } | |
| .info-item strong { color: var(--color-dark); } | |
| .card { | |
| background-color: var(--color-card); | |
| border: 1px solid var(--color-border); | |
| border-radius: 20px; | |
| padding: 24px; | |
| margin-bottom: 24px; | |
| box-shadow: 0 4px 20px -4px rgba(30, 41, 59, 0.08); | |
| transition: box-shadow 0.3s ease, transform 0.3s ease; | |
| break-inside: avoid; | |
| page-break-inside: avoid; | |
| } | |
| .card:hover { | |
| box-shadow: 0 8px 30px -4px rgba(30, 41, 59, 0.12); | |
| transform: translateY(-2px); | |
| } | |
| .card-title { | |
| font-size: 1.1rem; | |
| font-weight: 700; | |
| color: var(--color-dark); | |
| margin-bottom: 4px; | |
| } | |
| .card-subtitle { | |
| font-size: 0.85rem; | |
| color: var(--color-muted); | |
| margin-bottom: 20px; | |
| } | |
| .kpi-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 20px; | |
| margin-bottom: 32px; | |
| } | |
| .kpi-card { | |
| background-color: var(--color-card); | |
| border: 1px solid var(--color-border); | |
| border-radius: 20px; | |
| padding: 24px; | |
| text-align: center; | |
| box-shadow: 0 4px 20px -4px rgba(30, 41, 59, 0.08); | |
| transition: all 0.3s ease; | |
| break-inside: avoid; | |
| page-break-inside: avoid; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .kpi-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 4px; | |
| background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light)); | |
| } | |
| .kpi-card.total::before { | |
| background: linear-gradient(90deg, var(--color-secondary), var(--color-secondary-light)); | |
| } | |
| .kpi-card:hover { | |
| transform: translateY(-4px); | |
| box-shadow: 0 12px 30px -4px rgba(30, 41, 59, 0.15); | |
| } | |
| .kpi-icon { font-size: 2rem; margin-bottom: 12px; } | |
| .kpi-label { | |
| font-size: 0.7rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 0.12em; | |
| color: var(--color-muted); | |
| margin-bottom: 12px; | |
| } | |
| .kpi-value { | |
| font-size: 2rem; | |
| font-weight: 800; | |
| color: var(--color-dark); | |
| line-height: 1.1; | |
| margin-bottom: 8px; | |
| } | |
| .kpi-detail { | |
| font-size: 0.85rem; | |
| color: var(--color-muted); | |
| } | |
| .grid-2 { | |
| display: grid; | |
| grid-template-columns: repeat(2, 1fr); | |
| gap: 24px; | |
| margin-bottom: 24px; | |
| } | |
| .chart-container { | |
| height: 300px; | |
| position: relative; | |
| } | |
| .chart-container.large { height: 350px; } | |
| .table-wrapper { overflow-x: auto; } | |
| .data-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| font-size: 0.9rem; | |
| } | |
| .data-table thead { background-color: var(--color-bg-alt); } | |
| .data-table th { | |
| padding: 14px 16px; | |
| text-align: left; | |
| font-weight: 700; | |
| color: var(--color-muted); | |
| text-transform: uppercase; | |
| font-size: 0.7rem; | |
| letter-spacing: 0.08em; | |
| border-bottom: 2px solid var(--color-border); | |
| } | |
| .data-table th.text-right { text-align: right; } | |
| .data-table td { | |
| padding: 14px 16px; | |
| border-bottom: 1px solid var(--color-border); | |
| color: var(--color-dark); | |
| vertical-align: middle; | |
| } | |
| .data-table td.text-right { text-align: right; } | |
| .data-table td.font-bold { font-weight: 700; } | |
| .data-table tr:hover { background-color: var(--color-bg); } | |
| .data-table tr:last-child td { border-bottom: none; } | |
| .rank-badge { | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 10px; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: 800; | |
| font-size: 0.85rem; | |
| } | |
| .rank-1 { background: linear-gradient(135deg, #FFD700, #FFA500); color: white; } | |
| .rank-2 { background: linear-gradient(135deg, #C0C0C0, #A0A0A0); color: white; } | |
| .rank-3 { background: linear-gradient(135deg, #CD7F32, #B8860B); color: white; } | |
| .rank-default { background-color: var(--color-bg-alt); color: var(--color-muted); } | |
| .badge { | |
| display: inline-flex; | |
| align-items: center; | |
| padding: 4px 10px; | |
| border-radius: 20px; | |
| font-size: 0.7rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| margin-right: 4px; | |
| margin-bottom: 4px; | |
| } | |
| .badge-2d { background: #e0f2fe; color: #0369a1; } | |
| .badge-3d { background: #fef3c7; color: #b45309; } | |
| .badge-imax { background: #fce7f3; color: #be185d; } | |
| .badge-4dx { background: #f3e8ff; color: #7c3aed; } | |
| .footer { | |
| text-align: center; | |
| padding: 32px 24px; | |
| margin-top: 32px; | |
| border-top: 1px solid var(--color-border); | |
| } | |
| .footer-content { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 12px; | |
| color: var(--color-light); | |
| font-size: 0.9rem; | |
| } | |
| .footer-logo { | |
| width: 32px; | |
| height: 32px; | |
| background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-size: 0.9rem; | |
| font-weight: 800; | |
| } | |
| .footer-text { text-align: left; } | |
| .footer-text small { display: block; font-size: 0.75rem; color: var(--color-light); } | |
| @media (max-width: 900px) { | |
| .grid-2, .grid-3 { grid-template-columns: 1fr; } | |
| .kpi-grid { grid-template-columns: repeat(2, 1fr); } | |
| .header { flex-direction: column; } | |
| .header-date { text-align: left; } | |
| } | |
| @media (max-width: 500px) { | |
| .kpi-grid { grid-template-columns: 1fr; } | |
| .dashboard { padding: 20px 16px; } | |
| .info-bar { flex-direction: column; align-items: flex-start; } | |
| } | |
| @media print { | |
| body { | |
| background-color: white !important; | |
| -webkit-print-color-adjust: exact !important; | |
| print-color-adjust: exact !important; | |
| } | |
| .action-buttons { display: none !important; } | |
| .card, .kpi-card { | |
| break-inside: avoid !important; | |
| page-break-inside: avoid !important; | |
| box-shadow: none !important; | |
| border: 1px solid #e0e0e0 !important; | |
| } | |
| .card:hover, .kpi-card:hover { transform: none !important; } | |
| .dashboard { padding: 16px !important; max-width: 100% !important; } | |
| .kpi-card::before { background: var(--color-primary) !important; } | |
| .kpi-card.total::before { background: var(--color-secondary) !important; } | |
| .logo, .footer-logo { background: var(--color-primary) !important; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="dashboard" id="dashboard-content"> | |
| <div class="action-buttons"> | |
| <button class="btn btn-primary" onclick="downloadPDF()">📥 Descargar PDF</button> | |
| <button class="btn btn-secondary" onclick="window.print()">🖨️ Imprimir</button> | |
| </div> | |
| <div class="header"> | |
| <div class="header-left"> | |
| <div class="logo">C</div> | |
| <div> | |
| <h1 class="header-title" id="dashboardTitle"></h1> | |
| <p class="header-subtitle" id="dashboardSubtitle"></p> | |
| </div> | |
| </div> | |
| <div class="header-date" id="generationDate"></div> | |
| </div> | |
| <div class="info-bar"> | |
| <div class="info-item">📅 <strong>Período:</strong> <span id="periodDetail"></span></div> | |
| <div class="info-item">🎬 <strong>Espectadores:</strong> <span id="totalSpectatorsInfo"></span></div> | |
| <div class="info-item">📊 <strong>Tipo:</strong> Reporte de Películas y Distribuidoras</div> | |
| </div> | |
| <div class="kpi-grid" id="kpi-grid-container"></div> | |
| <div class="grid-2"> | |
| <div class="card"> | |
| <div class="card-title">Top 5 Películas por Recaudación</div> | |
| <div class="card-subtitle">Ingresos generados por las películas más taquilleras</div> | |
| <div class="chart-container"> | |
| <canvas id="chartRecaudacion"></canvas> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">Distribución de Espectadores por Formato</div> | |
| <div class="card-subtitle">Preferencia de formatos de proyección del público</div> | |
| <div class="chart-container"> | |
| <canvas id="chartFormatos"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">Recaudación por Distribuidora (Top 5)</div> | |
| <div class="card-subtitle">Market share de las principales distribuidoras</div> | |
| <div class="chart-container large"> | |
| <canvas id="chartDistribuidoras"></canvas> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">🎬 Ranking de Películas por Espectadores</div> | |
| <div class="card-subtitle">Top 10 películas del período</div> | |
| <div class="table-wrapper"> | |
| <table class="data-table"> | |
| <thead> | |
| <tr> | |
| <th>#</th> | |
| <th>Película</th> | |
| <th>Formatos</th> | |
| <th class="text-right">Espectadores</th> | |
| <th class="text-right">Recaudación</th> | |
| <th class="text-right">Ticket Prom.</th> | |
| </tr> | |
| </thead> | |
| <tbody id="movie-ranking-table"> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| <div class="footer-content"> | |
| <div class="footer-logo">M</div> | |
| <div class="footer-text"> | |
| <strong>Powered by MostachIA</strong> | |
| <small>Procesos inteligentes, resultados superiores</small> | |
| </div> | |
| <span>•</span> | |
| <span id="footerDate"></span> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script> | |
| <script> | |
| const jsonData = { | |
| "dashboardType": "pelicula", | |
| "dashboardTitle": "Dashboard Octubre 2025 - Rendimiento de Películas y Distribuidoras", | |
| "clientName": "Cinexo", | |
| "periodo": { "desde": "2025-10-01", "hasta": "2025-10-31", "descripcion": "Octubre 2025" }, | |
| "topPeliculasPorEspectadores": [ | |
| {"pelicula": "El Conjuro: Los Ultimos Ritos 2D 4D", "espectadores": 999, "recaudacion": 5123000}, | |
| {"pelicula": "Los tipos malos 2 3D", "espectadores": 765, "recaudacion": 3605000}, | |
| {"pelicula": "Homo argentum", "espectadores": 603, "recaudacion": 2568000}, | |
| {"pelicula": "TRON: Ares 3D+4D", "espectadores": 523, "recaudacion": 3134500}, | |
| {"pelicula": "Avatar: El camino del agua (RE) 3D+4D", "espectadores": 490, "recaudacion": 2493000}, | |
| {"pelicula": "La casa de muñecas de Gabby: La película", "espectadores": 434, "recaudacion": 1936000}, | |
| {"pelicula": "Los 4 Fantásticos: Primeros pasos 3D+4D", "espectadores": 368, "recaudacion": 2140000}, | |
| {"pelicula": "Teléfono negro 2 ATMOS", "espectadores": 365, "recaudacion": 1740000}, | |
| {"pelicula": "TRON: Ares 3D+4D", "espectadores": 173, "recaudacion": 979000}, | |
| {"pelicula": "Mascotas al rescate", "espectadores": 167, "recaudacion": 744000} | |
| ], | |
| "topPeliculasPorRecaudacion": [ | |
| {"pelicula": "El Conjuro: Los Ultimos Ritos 2D 4D", "espectadores": 999, "recaudacion": 5123000}, | |
| {"pelicula": "Los tipos malos 2 3D", "espectadores": 765, "recaudacion": 3605000}, | |
| {"pelicula": "TRON: Ares 3D+4D", "espectadores": 523, "recaudacion": 3134500}, | |
| {"pelicula": "Homo argentum", "espectadores": 603, "recaudacion": 2568000}, | |
| {"pelicula": "Avatar: El camino del agua (RE) 3D+4D", "espectadores": 490, "recaudacion": 2493000}, | |
| {"pelicula": "Los 4 Fantásticos: Primeros pasos 3D+4D", "espectadores": 368, "recaudacion": 2140000}, | |
| {"pelicula": "La casa de muñecas de Gabby: La película", "espectadores": 434, "recaudacion": 1936000}, | |
| {"pelicula": "Teléfono negro 2 ATMOS", "espectadores": 365, "recaudacion": 1740000}, | |
| {"pelicula": "TRON: Ares 3D+4D", "espectadores": 173, "recaudacion": 979000}, | |
| {"pelicula": "TRON: Ares 2D+4D", "espectadores": 141, "recaudacion": 786000} | |
| ], | |
| "espectadoresPorFormato": [ | |
| {"formato": "4D", "espectadores": 3093}, | |
| {"formato": "2D", "espectadores": 2609}, | |
| {"formato": "3D", "espectadores": 992} | |
| ], | |
| "distribucionPorDistribuidora": [ | |
| {"distribuidora": "THE WALT DISNEY COMPANY SA", "espectadores": 2606, "recaudacion": 13533500}, | |
| {"distribuidora": "UNITED INTERNATIONAL PICTURES SRL", "espectadores": 2085, "recaudacion": 9813500}, | |
| {"distribuidora": "WARNER BROS", "espectadores": 1319, "recaudacion": 6639000}, | |
| {"distribuidora": "BF PARIS SRL.", "espectadores": 446, "recaudacion": 1987000}, | |
| {"distribuidora": "DIAMOND FILMS", "espectadores": 100, "recaudacion": 428000}, | |
| {"distribuidora": "LUPINO FILMS SRL", "espectadores": 65, "recaudacion": 244000}, | |
| {"distribuidora": "CINEMARK ARGENTINA S.R.L", "espectadores": 49, "recaudacion": 200000}, | |
| {"distribuidora": "CDI COMPANIA DISTRIBUIDORA INDEPENDIENTE SA", "espectadores": 19, "recaudacion": 98000}, | |
| {"distribuidora": "TRAPECIO CINE S.R.L", "espectadores": 5, "recaudacion": 28000} | |
| ] | |
| }; | |
| document.addEventListener('DOMContentLoaded', () => { | |
| populateDashboard(jsonData); | |
| }); | |
| function populateDashboard(data) { | |
| Chart.defaults.font.family = "'Segoe UI', system-ui, sans-serif"; | |
| Chart.defaults.font.size = 12; | |
| Chart.defaults.color = '#64748b'; | |
| Chart.defaults.plugins.legend.labels.usePointStyle = true; | |
| Chart.defaults.plugins.legend.labels.padding = 20; | |
| Chart.defaults.plugins.legend.position = 'bottom'; | |
| const chartColors = { | |
| primary: '#60B99A', | |
| palette: ['#60B99A', '#1F3B4D', '#7FCDB2', '#2D5066', '#4A9D80', '#FFB74D', '#5A7A8A', '#A8D5C2'] | |
| }; | |
| const formatCurrency = (value) => '$' + value.toLocaleString('es-AR', { maximumFractionDigits: 0 }); | |
| const formatNumber = (value) => value.toLocaleString('es-AR', { maximumFractionDigits: 0 }); | |
| const formatDate = (dateString) => new Date(dateString + 'T00:00:00').toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit', year: 'numeric' }); | |
| const currentDate = new Date().toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit', year: 'numeric' }); | |
| document.getElementById('dashboardTitle').textContent = data.dashboardTitle; | |
| document.getElementById('dashboardSubtitle').textContent = `${data.clientName} • ${data.periodo.descripcion}`; | |
| document.getElementById('generationDate').textContent = `Generado: ${currentDate}`; | |
| document.getElementById('footerDate').textContent = currentDate; | |
| document.getElementById('periodDetail').textContent = `${formatDate(data.periodo.desde)} al ${formatDate(data.periodo.hasta)}`; | |
| const totalEspectadores = data.distribucionPorDistribuidora.reduce((sum, item) => sum + item.espectadores, 0); | |
| const totalRecaudacion = data.distribucionPorDistribuidora.reduce((sum, item) => sum + item.recaudacion, 0); | |
| const ticketPromedio = totalEspectadores > 0 ? totalRecaudacion / totalEspectadores : 0; | |
| const peliculaTop = data.topPeliculasPorRecaudacion[0]; | |
| document.getElementById('totalSpectatorsInfo').textContent = formatNumber(totalEspectadores); | |
| const kpis = [ | |
| { icon: '💰', label: 'Ingresos Totales', value: formatCurrency(totalRecaudacion), detail: 'Suma de toda la boletería', class: 'total' }, | |
| { icon: '🎬', label: 'Total Espectadores', value: formatNumber(totalEspectadores), detail: `en ${data.periodo.descripcion}` }, | |
| { icon: '🎫', label: 'Ticket Promedio', value: formatCurrency(ticketPromedio), detail: 'Ingreso por espectador' }, | |
| { icon: '🏆', label: 'Película Top', value: peliculaTop.pelicula.split(' ').slice(0, 3).join(' '), detail: `Recaudó ${formatCurrency(peliculaTop.recaudacion)}` } | |
| ]; | |
| const kpiContainer = document.getElementById('kpi-grid-container'); | |
| kpiContainer.innerHTML = kpis.map(kpi => ` | |
| <div class="kpi-card ${kpi.class || ''}"> | |
| <div class="kpi-icon">${kpi.icon}</div> | |
| <div class="kpi-label">${kpi.label}</div> | |
| <div class="kpi-value">${kpi.value}</div> | |
| <div class="kpi-detail">${kpi.detail}</div> | |
| </div> | |
| `).join(''); | |
| const getFormatBadges = (title) => { | |
| let badges = ''; | |
| if (/\b2D\b/i.test(title)) badges += '<span class="badge badge-2d">2D</span>'; | |
| if (/\b3D\b/i.test(title)) badges += '<span class="badge badge-3d">3D</span>'; | |
| if (/\b4D\b/i.test(title)) badges += '<span class="badge badge-4dx">4D</span>'; | |
| if (/\bIMAX\b/i.test(title)) badges += '<span class="badge badge-imax">IMAX</span>'; | |
| return badges.trim() || '-'; | |
| }; | |
| const tableBody = document.getElementById('movie-ranking-table'); | |
| tableBody.innerHTML = data.topPeliculasPorEspectadores.map((p, index) => { | |
| const rank = index + 1; | |
| const rankClass = rank === 1 ? 'rank-1' : rank === 2 ? 'rank-2' : rank === 3 ? 'rank-3' : 'rank-default'; | |
| const ticketProm = p.espectadores > 0 ? p.recaudacion / p.espectadores : 0; | |
| return ` | |
| <tr> | |
| <td><span class="rank-badge ${rankClass}">${rank}</span></td> | |
| <td class="font-bold">${p.pelicula}</td> | |
| <td>${getFormatBadges(p.pelicula)}</td> | |
| <td class="text-right">${formatNumber(p.espectadores)}</td> | |
| <td class="text-right font-bold">${formatCurrency(p.recaudacion)}</td> | |
| <td class="text-right">${formatCurrency(ticketProm)}</td> | |
| </tr>`; | |
| }).join(''); | |
| new Chart(document.getElementById('chartRecaudacion'), { | |
| type: 'bar', | |
| data: { | |
| labels: data.topPeliculasPorRecaudacion.slice(0, 5).map(p => p.pelicula.length > 25 ? p.pelicula.substring(0,22)+'...' : p.pelicula), | |
| datasets: [{ | |
| label: 'Recaudación', | |
| data: data.topPeliculasPorRecaudacion.slice(0, 5).map(p => p.recaudacion), | |
| backgroundColor: chartColors.palette, | |
| borderRadius: 8, | |
| }] | |
| }, | |
| options: { | |
| responsive: true, maintainAspectRatio: false, | |
| plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => formatCurrency(ctx.raw) } } }, | |
| scales: { | |
| y: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { callback: value => '$' + (value/1000000).toFixed(1) + 'M' } }, | |
| x: { grid: { display: false } } | |
| } | |
| } | |
| }); | |
| new Chart(document.getElementById('chartFormatos'), { | |
| type: 'doughnut', | |
| data: { | |
| labels: data.espectadoresPorFormato.map(f => f.formato), | |
| datasets: [{ | |
| data: data.espectadoresPorFormato.map(f => f.espectadores), | |
| backgroundColor: [chartColors.palette[0], chartColors.palette[1], chartColors.palette[3]], | |
| borderWidth: 0, hoverOffset: 10 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, maintainAspectRatio: false, cutout: '60%', | |
| plugins: { | |
| legend: { position: 'right' }, | |
| tooltip: { callbacks: { label: ctx => `${ctx.label}: ${formatNumber(ctx.raw)} esp.` } } | |
| } | |
| } | |
| }); | |
| new Chart(document.getElementById('chartDistribuidoras'), { | |
| type: 'bar', | |
| data: { | |
| labels: data.distribucionPorDistribuidora.slice(0, 5).map(d => d.distribuidora.replace(/ S\.?A\.?| S\.?R\.?L\.?| C\.?I\.?A\.?/gi, '').trim()), | |
| datasets: [{ | |
| label: 'Recaudación', | |
| data: data.distribucionPorDistribuidora.slice(0, 5).map(d => d.recaudacion), | |
| backgroundColor: chartColors.primary, | |
| borderRadius: 8, | |
| borderSkipped: false, | |
| }] | |
| }, | |
| options: { | |
| indexAxis: 'y', responsive: true, maintainAspectRatio: false, | |
| plugins: { legend: { display: false }, tooltip: { callbacks: { label: ctx => formatCurrency(ctx.raw) } } }, | |
| scales: { | |
| x: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { callback: value => '$' + (value / 1000000).toFixed(0) + 'M' } }, | |
| y: { grid: { display: false } } | |
| } | |
| } | |
| }); | |
| } | |
| function downloadPDF() { | |
| const buttons = document.querySelector('.action-buttons'); | |
| buttons.style.display = 'none'; | |
| const element = document.getElementById('dashboard-content'); | |
| const title = document.getElementById('dashboardTitle')?.textContent || 'Dashboard'; | |
| const date = new Date().toISOString().split('T')[0]; | |
| const filename = 'cinexo-' + title.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') + '-' + date + '.pdf'; | |
| const opt = { | |
| margin: [8, 8, 8, 8], filename: filename, | |
| image: { type: 'jpeg', quality: 0.95 }, | |
| html2canvas: { scale: 2, useCORS: true, logging: false, backgroundColor: '#ffffff', windowWidth: 1200 }, | |
| jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, | |
| pagebreak: { mode: ['avoid-all', 'css', 'legacy'], avoid: '.card, .kpi-card' } | |
| }; | |
| html2pdf().set(opt).from(element).save().then(() => { | |
| buttons.style.display = 'flex'; | |
| }).catch(() => { | |
| buttons.style.display = 'flex'; | |
| alert('Error al generar PDF. Intentá con Imprimir.'); | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment