217 lines
8.2 KiB
HTML
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 %}
|