estadisticas
This commit is contained in:
BIN
Front/bun.lockb
BIN
Front/bun.lockb
Binary file not shown.
@@ -5,6 +5,7 @@
|
||||
<link rel="icon" type="image/png" href="/favicon.svg" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
// Configura el tema desde localStorage antes de cargar la aplicación
|
||||
const savedTheme = localStorage.getItem("theme") || "light";
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"@sveltejs/kit": "^2.7.3",
|
||||
"@sveltestrap/sveltestrap": "^6.2.7",
|
||||
"chartjs": "^0.3.24",
|
||||
"svelte-chartjs": "^3.1.5",
|
||||
"svelte-routing": "^2.13.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,59 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import {
|
||||
Chart,
|
||||
registerables
|
||||
} from "chart.js";
|
||||
|
||||
Chart.register(...registerables);
|
||||
|
||||
export let data;
|
||||
|
||||
let chartCanvas;
|
||||
let chartInstance;
|
||||
|
||||
onMount(() => {
|
||||
if (chartCanvas) {
|
||||
chartInstance = new Chart(chartCanvas, {
|
||||
type: "bar",
|
||||
data: data,
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: "top"
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.destroy();
|
||||
}
|
||||
};
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import Chart from 'chart.js/auto';
|
||||
|
||||
let {chartData, typec='bar'} = $props();
|
||||
|
||||
let chartContainer;
|
||||
let instance;
|
||||
|
||||
|
||||
onDestroy(() => {
|
||||
if (instance) {
|
||||
instance.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
const createChart = () => {
|
||||
if (instance) {
|
||||
instance.destroy();
|
||||
}
|
||||
|
||||
const ctx = chartContainer.getContext('2d');
|
||||
instance = new Chart(ctx, {
|
||||
type: typec,
|
||||
data: {
|
||||
labels: chartData.labels,
|
||||
datasets: chartData.datasets.map(dataset => ({
|
||||
label: dataset.label,
|
||||
data: dataset.data.map(x => String(x)),
|
||||
borderWidth: dataset.borderWidth
|
||||
}))
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
beginAtZero: true,
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="card card-body">
|
||||
<canvas bind:this={chartCanvas}></canvas>
|
||||
</div>
|
||||
};
|
||||
onMount(createChart);
|
||||
$effect(createChart);
|
||||
|
||||
</script>
|
||||
|
||||
<div class="card card-body">
|
||||
<canvas bind:this={chartContainer}></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,35 +4,183 @@
|
||||
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
|
||||
import { Chart } from "chart.js";
|
||||
import FChart from "../Componentes/Estadisticas/fChart.svelte";
|
||||
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
|
||||
import {urlG} from "../stores/urlStore";
|
||||
import type { ChartData } from "../types";
|
||||
import { text } from "@sveltejs/kit";
|
||||
|
||||
let cdata = $state();
|
||||
let token = sessionStorage.getItem("token")||"";
|
||||
let y = $state(2025);
|
||||
|
||||
let myChart;
|
||||
onMount(() => {
|
||||
let cdata:ChartData|any = $state();
|
||||
let aldata:{id:number, ubicacion:string, divisa:string}|any = $state();
|
||||
|
||||
let chartMesesDuracion:ChartData|any = $state();
|
||||
let tablaMesesDuracion:{meses:number, repes:number, semaforizacion:string}|any = $state();
|
||||
|
||||
let modaldata:string = $state("");
|
||||
|
||||
onMount(async() => {
|
||||
await dataAlquileresporAño();
|
||||
});
|
||||
|
||||
async function dataAlquileresporAño(year = 2025) {
|
||||
try{
|
||||
const rep = fetch($urlG+"/api/stats/alquileresIniciados?year="+year, {
|
||||
method : "GET",
|
||||
headers: {
|
||||
"Auth": token,
|
||||
}
|
||||
});
|
||||
const pre = fetch($urlG+"/api/tabla/alquileresIniciados?year="+year, {
|
||||
method : "GET",
|
||||
headers: {
|
||||
"Auth": token,
|
||||
}
|
||||
});
|
||||
let [r,p] = await Promise.all([rep, pre]);
|
||||
|
||||
let data = await r.json();
|
||||
let data2 = await p.json();
|
||||
|
||||
cdata = data;
|
||||
aldata = data2;
|
||||
return;
|
||||
}catch{
|
||||
modaldata="Fallo al intentar alcanzar el servidor";
|
||||
}
|
||||
}
|
||||
|
||||
let visibleMesesDuracion:boolean = $state(false);
|
||||
async function dataMesesDuracion() {
|
||||
try{
|
||||
const p1 = fetch($urlG+"/api/stats/duracionContrato", {
|
||||
method : "GET",
|
||||
headers: {
|
||||
"Auth": token,
|
||||
}
|
||||
});
|
||||
const p2 = fetch($urlG+"/api/tabla/duracionContrato", {
|
||||
method : "GET",
|
||||
headers: {
|
||||
"Auth": token,
|
||||
}
|
||||
});
|
||||
let [r1, r2] = await Promise.all([p1,p2]);
|
||||
let [d1,d2] = await Promise.all([r1.json(), r2.json()])
|
||||
chartMesesDuracion = d1;
|
||||
tablaMesesDuracion = d2;
|
||||
}catch {
|
||||
modaldata="Fallo al intentar alcanzar el servidor";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if modaldata}
|
||||
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")} />
|
||||
{/if}
|
||||
|
||||
<NavBarAutocompletable/>
|
||||
|
||||
<div class="container">
|
||||
<br>
|
||||
<div class="row">
|
||||
<BarraHorizontalConTexto text="Alquileres del ultimo año"/>
|
||||
<div class="col">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-4" >
|
||||
<BarraHorizontalConTexto text="Estadisticas"/>
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="hea1">
|
||||
<button class="accordion-button"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#c1"
|
||||
aria-expanded="true"
|
||||
aria-controls="c1">
|
||||
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Ubicacion</th>
|
||||
<th>Divisa</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col">
|
||||
<FChart data={null}/>
|
||||
Alquileres en el ultimo año
|
||||
</button>
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse show" id="c1" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body row">
|
||||
<div class="col">
|
||||
<div class="d-flex input-group">
|
||||
<input class="form-control" type="number" bind:value={y}>
|
||||
<button class="btn btn-primary" onclick={()=>dataAlquileresporAño(y)}><img src="/zoom.svg" aria-label="Lupa"></button>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Ubicacion</th>
|
||||
<th>Divisa</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each aldata as al}
|
||||
<tr>
|
||||
<td>{al.id}</td>
|
||||
<td>{al.ubicacion}</td>
|
||||
<td>{al.divisa}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col">
|
||||
{#if cdata}
|
||||
<FChart chartData={cdata}/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="hea2">
|
||||
<button class="accordion-button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#c2"
|
||||
onclick={()=>{
|
||||
if(visibleMesesDuracion === true){
|
||||
visibleMesesDuracion=false;
|
||||
return;
|
||||
} else if (visibleMesesDuracion== false){
|
||||
dataMesesDuracion();
|
||||
|
||||
}
|
||||
}}
|
||||
>
|
||||
Meses De Duracion
|
||||
</button>
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse" id="c2" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body row">
|
||||
<div class="col">
|
||||
<p class="text-muted">Objetivo: <i>Mide la longitud de los contratos en meses y cuantos hay por cada longitud. por lo menos 2.</i></p>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Cantidad de meses</th>
|
||||
<th>Repeticiones</th>
|
||||
<th>Semaforización</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each tablaMesesDuracion as mes}
|
||||
<tr>
|
||||
<td>{mes.meses}</td>
|
||||
<td>{mes.repes}</td>
|
||||
<td>{mes.semaforizacion}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{#if chartMesesDuracion}
|
||||
<FChart chartData={chartMesesDuracion} typec="pie"/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
8
Front/src/types.d.ts
vendored
8
Front/src/types.d.ts
vendored
@@ -136,4 +136,12 @@ export type AltaDefectoDto ={
|
||||
pagainquilino:number,
|
||||
iddivisa:number,
|
||||
idcontrato:number
|
||||
}
|
||||
|
||||
export type ChartData = {
|
||||
labels: string[],
|
||||
datasets: [{
|
||||
label: string,
|
||||
data:string[],
|
||||
}]
|
||||
}
|
||||
Reference in New Issue
Block a user