Files

217 lines
8.2 KiB
HTML

{% extends "layouts/base.html" %}
{% block title %}Dashboard Predictivo - Edu-Space{% endblock %}
{% block extra_css %}
<style>
.glass-card {
background: rgba(30, 30, 45, 0.6);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 1.5rem;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.glass-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(180, 62, 142, 0.3);
}
.stat-icon-box {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(180, 62, 142, 0.15);
color: #B43E8E;
font-size: 1.5rem;
}
.chart-container {
position: relative;
height: 400px;
width: 100%;
}
/* Animation Delays */
.delay-1 { animation-delay: 0.1s; }
.delay-2 { animation-delay: 0.2s; }
.delay-3 { animation-delay: 0.3s; }
</style>
{% endblock %}
{% block content %}
<div class="row mb-4 fade-in-up">
<div class="col-12">
<h2 class="fw-bold mb-1">Algoritmo Genético & Predicción</h2>
<p class="text-muted">Optimización de asignación de espacios áulicos de UniCABA en tiempo real.</p>
</div>
</div>
<!-- Stats Row -->
<div class="row g-4 mb-4">
<div class="col-md-4 fade-in-up delay-1">
<div class="glass-card p-4 h-100">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="text-muted fw-semibold mb-0 text-uppercase tracking-wide" style="font-size: 0.8rem; letter-spacing: 1px;">Aulas Optimizadas</h6>
<div class="stat-icon-box">
<i class="bi bi-door-open-fill"></i>
</div>
</div>
<h3 class="fw-bold mb-0">142 <span class="fs-6 text-success fw-normal"><i class="bi bi-arrow-up-short"></i>12%</span></h3>
</div>
</div>
<div class="col-md-4 fade-in-up delay-2">
<div class="glass-card p-4 h-100">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="text-muted fw-semibold mb-0 text-uppercase tracking-wide" style="font-size: 0.8rem; letter-spacing: 1px;">Eficiencia Energética</h6>
<div class="stat-icon-box" style="background: rgba(40, 167, 69, 0.15); color: #28a745;">
<i class="bi bi-lightning-charge-fill"></i>
</div>
</div>
<h3 class="fw-bold mb-0">87.4% <span class="fs-6 text-success fw-normal"><i class="bi bi-arrow-up-short"></i>3.2%</span></h3>
</div>
</div>
<div class="col-md-4 fade-in-up delay-3">
<div class="glass-card p-4 h-100">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="text-muted fw-semibold mb-0 text-uppercase tracking-wide" style="font-size: 0.8rem; letter-spacing: 1px;">Colisiones Detectadas</h6>
<div class="stat-icon-box" style="background: rgba(220, 53, 69, 0.15); color: #dc3545;">
<i class="bi bi-exclamation-triangle-fill"></i>
</div>
</div>
<h3 class="fw-bold mb-0">0 <span class="fs-6 text-muted fw-normal">Resueltas al vuelo</span></h3>
</div>
</div>
</div>
<!-- Main Chart Row -->
<div class="row fade-in-up delay-3">
<div class="col-12">
<div class="glass-card p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold mb-0">Proyección de Ocupación por Sede</h5>
<button class="btn btn-sm btn-outline-light rounded-pill px-3">
<i class="bi bi-arrow-clockwise me-1"></i> Recalcular
</button>
</div>
<div class="chart-container">
<canvas id="predictiveChart"></canvas>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Configuramos los colores globales de Chart.js para Dark Mode
Chart.defaults.color = 'rgba(255, 255, 255, 0.6)';
Chart.defaults.font.family = "'Inter', sans-serif";
const ctx = document.getElementById('predictiveChart').getContext('2d');
// Gradiente para el área bajo la curva
const gradient = ctx.createLinearGradient(0, 0, 0, 400);
gradient.addColorStop(0, 'rgba(180, 62, 142, 0.5)'); // brand-primary translúcido
gradient.addColorStop(1, 'rgba(180, 62, 142, 0.0)');
const gradient2 = ctx.createLinearGradient(0, 0, 0, 400);
gradient2.addColorStop(0, 'rgba(104, 44, 173, 0.5)'); // accent-purple translúcido
gradient2.addColorStop(1, 'rgba(104, 44, 173, 0.0)');
new Chart(ctx, {
type: 'line',
data: {
labels: ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
datasets: [
{
label: 'Sede Central (Proyectado)',
data: [65, 82, 90, 85, 70, 30],
borderColor: '#B43E8E',
backgroundColor: gradient,
borderWidth: 3,
pointBackgroundColor: '#B43E8E',
pointBorderColor: '#fff',
pointBorderWidth: 2,
pointRadius: 5,
pointHoverRadius: 7,
fill: true,
tension: 0.4
},
{
label: 'Sede Virtual (Equivalente)',
data: [40, 45, 55, 48, 60, 20],
borderColor: '#682CAD',
backgroundColor: gradient2,
borderWidth: 3,
pointBackgroundColor: '#682CAD',
pointBorderColor: '#fff',
pointBorderWidth: 2,
pointRadius: 5,
pointHoverRadius: 7,
fill: true,
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
usePointStyle: true,
padding: 20,
font: { size: 13, weight: '500' }
}
},
tooltip: {
backgroundColor: 'rgba(20, 20, 30, 0.9)',
titleFont: { size: 14, family: "'Inter', sans-serif" },
bodyFont: { size: 13, family: "'Inter', sans-serif" },
padding: 12,
cornerRadius: 8,
displayColors: true,
borderColor: 'rgba(255,255,255,0.1)',
borderWidth: 1
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(255, 255, 255, 0.05)',
drawBorder: false,
},
ticks: {
callback: function(value) { return value + '%' }
}
},
x: {
grid: {
display: false,
drawBorder: false,
}
}
},
interaction: {
intersect: false,
mode: 'index',
},
}
});
});
</script>
{% endblock %}