Agrega Graficos
parent
cc109373b3
commit
a2687861a2
|
@ -11,6 +11,8 @@
|
|||
"@adminkit/core": "^3.4.0",
|
||||
"bootstrap": "^5.3.0",
|
||||
"bootstrap-icons": "^1.10.5",
|
||||
"chart.js": "^3.9.1",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"history": "^5.3.0",
|
||||
"svelte-navigator": "^3.2.2",
|
||||
"svelte-pagination": "^0.0.1",
|
||||
|
@ -37,6 +39,15 @@
|
|||
"simplebar": "5.3.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@adminkit/core/node_modules/chart.js": {
|
||||
"version": "2.9.4",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz",
|
||||
"integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==",
|
||||
"dependencies": {
|
||||
"chartjs-color": "^2.1.0",
|
||||
"moment": "^2.10.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/polyfill": {
|
||||
"version": "7.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz",
|
||||
|
@ -508,13 +519,9 @@
|
|||
"integrity": "sha512-ceOhN1DL7Y4O6M0j9ICgmTYziV89WMd96SvSl0REd8PMgrY0B/WBOPoed5S1KUmJqXgUXh8gzSe6E3ae27upsQ=="
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "2.9.4",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz",
|
||||
"integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==",
|
||||
"dependencies": {
|
||||
"chartjs-color": "^2.1.0",
|
||||
"moment": "^2.10.2"
|
||||
}
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
|
||||
"integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w=="
|
||||
},
|
||||
"node_modules/chartjs-color": {
|
||||
"version": "2.4.1",
|
||||
|
@ -533,6 +540,14 @@
|
|||
"color-name": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chartjs-plugin-datalabels": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
|
||||
"integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
|
||||
"peerDependencies": {
|
||||
"chart.js": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||
|
@ -727,9 +742,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
"@adminkit/core": "^3.4.0",
|
||||
"bootstrap": "^5.3.0",
|
||||
"bootstrap-icons": "^1.10.5",
|
||||
"chart.js": "^3.9.1",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"history": "^5.3.0",
|
||||
"svelte-navigator": "^3.2.2",
|
||||
"svelte-pagination": "^0.0.1",
|
||||
"svelte-qrcode": "^1.0.0",
|
||||
"chart.js": "^3.7.0"
|
||||
"svelte-qrcode": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { getCountByComuna } from '$/services/paraderos';
|
||||
import Chart from 'chart.js/auto';
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||
|
||||
let comunasCounts = [];
|
||||
let chart = null; // Referencia al gráfico
|
||||
|
||||
onMount(() => {
|
||||
getCountByComuna({ vigente: 1 })
|
||||
.then(data => {
|
||||
comunasCounts = data.count_by_comuna.sort((a, b) => a.id_comuna__nombre_comuna.localeCompare(b.id_comuna__nombre_comuna));
|
||||
updateChart(); // Actualizar el gráfico cuando los datos estén listos
|
||||
})
|
||||
.catch(error => console.error("Failed to load comunas counts:", error));
|
||||
});
|
||||
|
||||
function updateChart() {
|
||||
const ctx = document.getElementById('comunasChart').getContext('2d');
|
||||
if (chart) {
|
||||
chart.destroy(); // Destruir el gráfico existente antes de crear uno nuevo
|
||||
}
|
||||
chart = new Chart(ctx, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: comunasCounts.map(c => c.id_comuna__nombre_comuna),
|
||||
datasets: [{
|
||||
label: 'Total Paraderos',
|
||||
data: comunasCounts.map(c => c.total),
|
||||
backgroundColor: comunasCounts.map(() => `hsla(${Math.random() * 360}, 100%, 75%, 0.8)`), // Colores aleatorios con opacidad
|
||||
hoverOffset: 4
|
||||
}]
|
||||
},
|
||||
plugins: [ChartDataLabels],
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
datalabels: {
|
||||
color: '#ffffff',
|
||||
anchor: 'end',
|
||||
align: 'start',
|
||||
font: {
|
||||
size: 14,
|
||||
weight: 'bold',
|
||||
family: 'Arial'
|
||||
},
|
||||
formatter: (value, ctx) => {
|
||||
let sum = ctx.dataset.data.reduce((acc, curr) => acc + curr, 0);
|
||||
let percentage = (value * 100 / sum).toFixed(2) + "%";
|
||||
return ` (${percentage})`;
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(tooltipItem) {
|
||||
let label = tooltipItem.label || '';
|
||||
let value = tooltipItem.raw;
|
||||
let total = tooltipItem.dataset.data.reduce((acc, curr) => acc + curr, 0);
|
||||
let percentage = ((value / total) * 100).toFixed(2) + '%';
|
||||
return `${label}: (${percentage})`;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<table class="table table-striped table-hover table-responsive">
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Paraderos por Comuna </h5>
|
||||
<div class="col-auto">
|
||||
<div class="stat text-primary">
|
||||
<i class="bi bi-map"></i>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Comuna</th>
|
||||
<th>Total Paraderos</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each comunasCounts as { id_comuna__nombre_comuna, total }}
|
||||
<tr>
|
||||
<td>{id_comuna__nombre_comuna}</td>
|
||||
<td>{total}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
<canvas id="comunasChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
import { onMount, createEventDispatcher } from "svelte";
|
||||
import Chart from 'chart.js/auto';
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||
import { getCountRutasBuses } from "$/services/lineas";
|
||||
import { getCount } from "$/services/lineas";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let rutasConGPS = [];
|
||||
let rutasSinGPS = 0;
|
||||
let chart = null;
|
||||
|
||||
onMount(() => {
|
||||
dispatch('loading', true);
|
||||
|
||||
Promise.all([
|
||||
getCountRutasBuses(),
|
||||
getCount({ vigente: 1 })
|
||||
]).then(([dataRutasConGPS, dataTotalRutas]) => {
|
||||
rutasConGPS = dataRutasConGPS;
|
||||
rutasSinGPS = parseInt (dataTotalRutas.count) - parseInt (dataRutasConGPS.count);
|
||||
updateChart();
|
||||
}).catch(error => {
|
||||
console.error('Error fetching counts:', error);
|
||||
}).finally(() => {
|
||||
dispatch('loading', false);
|
||||
});
|
||||
});
|
||||
|
||||
function updateChart() {
|
||||
const ctx = document.getElementById('barChartR').getContext('2d');
|
||||
if (chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
chart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['Rutas con información', 'Rutas sin información'],
|
||||
datasets: [{
|
||||
label: 'Posicionamiento',
|
||||
data: [rutasConGPS.count, rutasSinGPS],
|
||||
backgroundColor: ['rgba(54, 162, 235, 0.8)', 'rgba(255, 99, 132, 0.8)']
|
||||
}]
|
||||
},
|
||||
plugins: [ChartDataLabels],
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Rutas con Informacion de Posicionamiento</h5>
|
||||
<canvas id="barChartR"></canvas>
|
||||
</div>
|
||||
</div>
|
|
@ -3,14 +3,18 @@
|
|||
import CantidadParaderos from "./CantidadParaderos.svelte";
|
||||
import CantidadLineas from "./CantidadLineas.svelte";
|
||||
import CantidadParaderosComuna from "./CantidadParaderosComuna.svelte";
|
||||
import CantidadParaderosComunaGrafico from "./CantidadParaderosComunaGrafico.svelte";
|
||||
import CantidadBusesRecorrido from "./CantidadBusesRecorrido.svelte";
|
||||
import CantidadBusesLinea from "./CantidadBusesLinea.svelte";
|
||||
import RutasCorrectas from "./rutasCorrectas.svelte";
|
||||
import CantidadRutasBuses from "./CantidadRutaBuses.svelte";
|
||||
|
||||
let loading1 = false
|
||||
let loading2 = false
|
||||
let loading3 = false
|
||||
let loading4 = false
|
||||
let loading5 = false
|
||||
let loading6 = false
|
||||
</script>
|
||||
|
||||
<PageTitle
|
||||
|
@ -26,15 +30,30 @@
|
|||
<div class="col">
|
||||
<CantidadParaderos on:loading={ev => loading2 = ev.detail} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<CantidadParaderosComuna on:loading={ev => loading3 = ev.detail} />
|
||||
</div>
|
||||
<div class="col">
|
||||
<CantidadBusesRecorrido on:loading={ev => loading4 = ev.detail} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<RutasCorrectas on:loading={ev => loading5 = ev.detail} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col">
|
||||
<CantidadRutasBuses on:loading={ev => loading6 = ev.detail} />
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<!--<CantidadParaderosComuna on:loading={ev => loading3 = ev.detail} /> -->
|
||||
|
||||
|
||||
<CantidadParaderosComunaGrafico on:loading={ev => loading3 = ev.detail} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import Chart from 'chart.js/auto';
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||
import { getCountLineasCorrectas } from "$/services/lineas";
|
||||
|
||||
let rutas = [];
|
||||
let chart = null;
|
||||
|
||||
onMount(() => {
|
||||
getCountLineasCorrectas().then(data => {
|
||||
rutas = data;
|
||||
updateChart();
|
||||
}).catch(error => console.error('Error fetching line counts:', error));
|
||||
});
|
||||
|
||||
function updateChart() {
|
||||
const ctx = document.getElementById('barChart').getContext('2d');
|
||||
if (chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
|
||||
// Generando colores aleatorios para cada barra
|
||||
const backgroundColors = rutas.map(() => `hsla(${Math.random() * 360}, 70%, 70%, 0.8)`);
|
||||
const borderColors = rutas.map(() => `hsla(${Math.random() * 360}, 70%, 50%, 1)`);
|
||||
|
||||
chart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: rutas.map(ruta => ruta.titulo),
|
||||
datasets: [{
|
||||
label: 'Rutas',
|
||||
data: rutas.map(ruta => ruta.cantidad),
|
||||
backgroundColor: backgroundColors,
|
||||
borderColor: borderColors,
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
plugins: [ChartDataLabels],
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
datalabels: {
|
||||
color: '#444',
|
||||
font: {
|
||||
weight: 'bold'
|
||||
},
|
||||
formatter: (value, ctx) => {
|
||||
let sum = ctx.dataset.data.reduce((a, b) => a + b, 0);
|
||||
let percentage = (value * 100 / sum).toFixed(2) + "%";
|
||||
return value + " (" + percentage + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Rutas Definidas</h5>
|
||||
<canvas id="barChart"></canvas>
|
||||
</div>
|
||||
</div>
|
|
@ -86,6 +86,16 @@ export async function getCountBuses(params) {
|
|||
}
|
||||
|
||||
|
||||
export async function getCountLineasCorrectas(params) {
|
||||
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
|
||||
const res = await fetch(`${base}/lineas/count_lineas_correctas/${query}`, {
|
||||
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
||||
|
||||
export async function getCountBusesRecorridos(params) {
|
||||
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
|
||||
const res = await fetch(`${base}/lineas/count_buses_recorridos/${query}`, {
|
||||
|
@ -94,3 +104,13 @@ export async function getCountBusesRecorridos(params) {
|
|||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
||||
|
||||
export async function getCountRutasBuses(params) {
|
||||
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
|
||||
const res = await fetch(`${base}/lineas/count_rutas_buses/${query}`, {
|
||||
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue