145 lines
4.6 KiB
HTML
145 lines
4.6 KiB
HTML
{% extends "pxy_dashboard/partials/base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Urban Digital Twin{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include "pxy_dashboard/partials/dashboard/kpi_row.html" %}
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-4">
|
|
<label for="subdivisionSelect" class="form-label">Selecciona una subdivisión:</label>
|
|
<select id="subdivisionSelect" class="form-select">
|
|
{% for s in subdivisions %}
|
|
<option value="{{ s }}" {% if s == selected_subdivision %}selected{% endif %}>{{ s }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Column Chart -->
|
|
<div class="card mb-4">
|
|
<div class="card-header"><h5 class="mb-0">Column Chart: Cuartiles por Fecha y Vehículo</h5></div>
|
|
<div class="card-body">
|
|
<div id="chart-bar"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Heatmap -->
|
|
<div class="card mb-4">
|
|
<div class="card-header"><h5 class="mb-0">Heatmap: Distribución de Cuartiles</h5></div>
|
|
<div class="card-body">
|
|
<div id="chart-heatmap"></div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
// Datos desde Django
|
|
const rawData = {{ scatter_data_json|safe }};
|
|
const vehicles = {{ vehicle_categories|safe }};
|
|
const subdivision = "{{ selected_subdivision|escapejs }}";
|
|
|
|
// Escala de color para z
|
|
const colorScale = {1:"#FF4136",2:"#FF851B",3:"#FFDC00",4:"#2ECC40",5:"#0074D9"};
|
|
|
|
// Fechas únicas y ordenadas
|
|
const dates = [...new Set(rawData.map(p => p.x))].sort();
|
|
|
|
// Función para extraer solo dígitos del string "Vehículo X"
|
|
function extractVehicleId(label) {
|
|
const m = label.match(/\d+/);
|
|
return m ? m[0] : label;
|
|
}
|
|
|
|
// --- Column Chart Series ---
|
|
const seriesBar = vehicles.map(veh => ({
|
|
name: veh,
|
|
data: dates.map(d => {
|
|
const rec = rawData.find(p => p.x === d && p.y === veh);
|
|
return rec ? rec.z : 0;
|
|
})
|
|
}));
|
|
|
|
// Render Column Chart con click
|
|
new ApexCharts(document.querySelector("#chart-bar"), {
|
|
chart: {
|
|
type: 'bar',
|
|
height: 350,
|
|
events: {
|
|
dataPointSelection: function(_, __, { seriesIndex, dataPointIndex }) {
|
|
const vehLabel = vehicles[seriesIndex];
|
|
const vehId = extractVehicleId(vehLabel);
|
|
const url = `/city/virtual/reality/digital/twin/waste/${encodeURIComponent(subdivision)}/${encodeURIComponent(vehId)}/`;
|
|
window.open(url, "_blank");
|
|
}
|
|
}
|
|
},
|
|
plotOptions: { bar: { horizontal: false, columnWidth: '50%' } },
|
|
dataLabels: { enabled: false },
|
|
series: seriesBar,
|
|
xaxis: { categories: dates, title: { text: 'Fecha' } },
|
|
yaxis: { title: { text: 'Cuartiles únicos' } },
|
|
legend: { position: 'bottom' },
|
|
title: { text: `Cuartiles únicos por Fecha en ${subdivision}` }
|
|
}).render();
|
|
|
|
|
|
// --- Heatmap Series ---
|
|
const seriesHeat = vehicles.map(veh => ({
|
|
name: veh,
|
|
data: dates.map(d => {
|
|
const rec = rawData.find(p => p.x === d && p.y === veh);
|
|
return { x: d, y: rec ? rec.z : 0 };
|
|
})
|
|
}));
|
|
|
|
// Render Heatmap con click
|
|
new ApexCharts(document.querySelector("#chart-heatmap"), {
|
|
chart: {
|
|
type: 'heatmap',
|
|
height: 350,
|
|
events: {
|
|
dataPointSelection: function(_, __, { seriesIndex, dataPointIndex }) {
|
|
const vehLabel = vehicles[seriesIndex];
|
|
const vehId = extractVehicleId(vehLabel);
|
|
const url = `/city/virtual/reality/digital/twin/waste/${encodeURIComponent(subdivision)}/${encodeURIComponent(vehId)}/`;
|
|
window.open(url, "_blank");
|
|
}
|
|
}
|
|
},
|
|
series: seriesHeat,
|
|
plotOptions: {
|
|
heatmap: {
|
|
shadeIntensity: 0.5,
|
|
colorScale: {
|
|
ranges: [
|
|
{ from: 0, to: 0, name: '0', color: '#f2f2f2' },
|
|
{ from: 1, to: 1, name: '1', color: '#FF4136' },
|
|
{ from: 2, to: 2, name: '2', color: '#FF851B' },
|
|
{ from: 3, to: 3, name: '3', color: '#FFDC00' },
|
|
{ from: 4, to: 4, name: '4', color: '#2ECC40' },
|
|
{ from: 5, to: 5, name: '5+', color: '#0074D9' }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
dataLabels: { enabled: false },
|
|
xaxis: { type: 'category', categories: dates, title: { text: 'Fecha' } },
|
|
yaxis: { title: { text: 'Vehículo' } },
|
|
title: { text: `Heatmap de Cuartiles en ${subdivision}` }
|
|
}).render();
|
|
|
|
// Recarga al cambiar subdivisión
|
|
document.getElementById("subdivisionSelect")
|
|
.addEventListener("change", function(){
|
|
const q = new URLSearchParams({ subdivision: this.value }).toString();
|
|
location.search = q;
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|