This commit is contained in:
lemuel 2023-02-21 12:26:09 -06:00
parent ee152d9d97
commit b8e873edb1
10 changed files with 523 additions and 3 deletions

View File

@ -0,0 +1,266 @@
<template>
<div>
<div class="columns is-multiline mb-5 is-align-items-flex-end">
<SelectInstitucion
columnSize="is-3"
:deshabilitarOptVacia="false"
:idInstitucionPadre="idInstitucion"
@institucion-seleccionada="
(nuevaInstitucion) => (idInstitucion = nuevaInstitucion)
"
v-if="admin.tipoUsuario.id_tipo_usuario === 2"
/>
<SelectModulo
columnSize="is-3"
:deshabilitarOptVacia="false"
:idInstitucion="
admin.institucion ? admin.institucion.id_institucion : idInstitucion
"
:idModuloPadre="idModulo"
:operador="admin"
@modulo-seleccionado="(nuevoModulo) => (idModulo = nuevoModulo)"
/>
<SelectTipoCarrito
columnSize="is-3"
:deshabilitarOptVacia="false"
:idTipoCarritoPadre="idTipoCarrito"
@tipo-carrito-seleccionado="
(nuevoTipoCarrito) => (idTipoCarrito = nuevoTipoCarrito)
"
/>
<SelectTipoUsuario
columnSize="is-3"
:deshabilitarOptVacia="false"
:idTipoUsuarioPadre="idTipoUsuario"
@tipo-usuario-seleccionado="
(nuevoTipoUsuario) => (idTipoUsuario = nuevoTipoUsuario)
"
/>
<SelectCarrera
columnSize="is-3"
:idInstitucion="
admin.institucion ? admin.institucion.id_institucion : idInstitucion
"
:idInstitucionCarreraPadre="idInstitucionCarrera"
@institucion-carrera-seleccionada="
(nuevaInstitucionCarrera) =>
(idInstitucionCarrera = nuevaInstitucionCarrera)
"
:deshabilitarOptVacia="false"
/>
<InputFecha
columnSize="is-3"
label="Fecha inicio"
:fechaPadre="fechaInicio"
:fechaMaxima="fechaMax"
:fechaMinima="fechaMinInicio"
@fecha="(fechaNueva) => (fechaInicio = fechaNueva)"
/>
<InputFecha
columnSize="is-3"
label="Fecha fin"
:fechaPadre="fechaFin"
:fechaMaxima="fechaMax"
:fechaMinima="fechaMinFin"
@fecha="(fechaNueva) => (fechaFin = fechaNueva)"
/>
<BotonBuscar
columnSize="is-3"
:buscar="obtenerPrestamos"
:disabled="false"
/>
</div>
<Diario :labels="labels" :data="data" />
</div>
</template>
<script>
import axios from 'axios'
import moment from 'moment'
import BotonBuscar from '@/components/botones/BotonBuscar'
import SelectCarrera from '@/components/selects/SelectCarrera'
import SelectInstitucion from '@/components/selects/SelectInstitucion'
import SelectModulo from '@/components/selects/SelectModulo'
import SelectTipoCarrito from '@/components/selects/SelectTipoCarrito'
import SelectTipoUsuario from '@/components/selects/SelectTipoUsuario'
import Diario from '@/components/admin/graficas/Diario'
import InputFecha from '@/components/inputs/InputFecha'
export default {
components: {
BotonBuscar,
SelectCarrera,
SelectInstitucion,
SelectModulo,
SelectTipoCarrito,
SelectTipoUsuario,
Diario,
InputFecha,
},
props: {
updateIsLoading: { type: Function, required: false, default: () => {} },
admin: { type: Object, required: true, default: () => ({}) },
},
data() {
return {
data: [],
labels: [],
idInstitucion: 0,
idInstitucionCarrera: 0,
idModulo: 0,
idTipoCarrito: 0,
idTipoUsuario: 0,
fechaFin: moment().toDate(),
fechaInicio: null,
hoy: moment(),
}
},
methods: {
obtenerPrestamos() {
let query = '?cancelado_operador=false&cancelado_usuario=false'
let fechaInicio = moment(this.fechaInicio)
this.updateIsLoading(true)
this.labels = []
while (fechaInicio.dayOfYear() <= moment(this.fechaFin).dayOfYear()) {
this.labels.push(fechaInicio.format('YYYY-MM-DD'))
fechaInicio.add(1, 'd')
}
if (this.admin.institucion)
query += `&id_institucion=${this.admin.institucion.id_institucion}`
else if (this.idInstitucion)
query += `&id_institucion=${this.idInstitucion}`
if (this.idInstitucionCarrera)
query += `&id_institucion_carrera=${this.idInstitucionCarrera}`
if (this.idModulo) query += `&id_modulo=${this.idModulo}`
if (this.idTipoCarrito) query += `&id_tipo_carrito=${this.idTipoCarrito}`
if (this.idTipoUsuario) query += `&id_tipo_usuario=${this.idTipoUsuario}`
if (this.fechaInicio)
query += `&fechaInicio=${moment(this.fechaInicio).format('YYYY-MM-DD')}`
if (this.fechaFin)
query += `&fechaFin=${moment(this.fechaFin).format('YYYY-MM-DD')}`
this.data = []
return axios
.get(
`${process.env.api}/prestamo/reporte${query}`,
this.$getToken.token()
)
.then((res) => {
const prestamos = []
const tc = res.data.map((value) => value.tipo_carrito)
const tipoCarrito = tc.filter(
(value, index, self) => self.indexOf(value) === index
)
const i = res.data.map((value) => value.institucion)
const instituciones = i.filter((value, index, self) => {
if (self.indexOf(value) === index) {
prestamos.push([res.data[index]])
return true
}
prestamos[prestamos.length - 1].push(res.data[index])
return false
})
console.log(tipoCarrito)
for (let i = 0; i < instituciones.length; i++) {
const dias = []
let m = []
let modulos = []
let k = 0
if (instituciones.length === 1) {
m = prestamos[i].map((value) => value.modulo)
modulos = m.filter(
(value, index, self) => self.indexOf(value) === index
)
m = []
for (let j = 0; j < modulos.length; j++)
m.push({ modulo: modulos[j], dias: [] })
}
for (let j = 0; j < this.labels.length; j++) {
const fecha = moment(this.labels[j])
const p = []
for (; k < prestamos[i].length; k++) {
if (
moment(prestamos[i][k].fecha_inicio).dayOfYear() ===
fecha.dayOfYear()
) {
p.push(prestamos[i][k])
} else break
}
if (instituciones.length === 1) {
for (let k = 0; k < modulos.length; k++) {
const pm = []
for (let l = 0; l < p.length; l++)
if (modulos[k] === p[l].modulo) pm.push(p[l])
m[k].dias.push({ dia: this.labels[j], prestamos: pm })
}
}
dias.push({ dia: this.labels[j], prestamos: p })
}
if (instituciones.length === 1)
this.data.push({
prestamos: prestamos[i].length,
institucion: instituciones[i],
dias,
modulos: m,
})
else
this.data.push({
prestamos: prestamos[i].length,
institucion: instituciones[i],
dias,
})
}
console.log(this.data)
this.updateIsLoading(false)
})
.catch((err) => {
this.updateIsLoading(false)
this.$alertsGenericos.imprimirError(
this.$buefy,
this.$router,
err.response.data
)
})
},
},
computed: {
fechaMax() {
return moment().toDate()
},
fechaMinInicio() {
return moment('2022-08-15').toDate()
},
fechaMinFin() {
let fechaMinFin = moment(this.fechaInicio)
return fechaMinFin.isValid() ? fechaMinFin.toDate() : moment().toDate()
},
},
watch: {
idInstitucion() {
this.idModulo = 0
this.idInstitucionCarrera = 0
},
},
created() {
if (this.hoy < moment(`${this.hoy.year()}-07-01`))
this.fechaInicio = moment(`${this.hoy.year()}-01-01`).toDate()
else this.fechaInicio = moment(`${this.hoy.year()}-07-01`).toDate()
this.obtenerPrestamos()
},
}
</script>

View File

@ -0,0 +1,79 @@
<template>
<div class="p-2 border border-gray-500 mt-4">
<label class="block mb-2 font-bold"> Coba Chart </label>
<client-only>
<LineChart :data="chartData" />
</client-only>
</div>
</template>
<script>
export default {
props: {
data: { type: Array, required: true, default: () => [] },
labels: { type: Array, required: true, default: () => [] },
},
methods: {
randomRgba() {
let o = Math.round,
r = Math.random,
s = 255
return `rgba(${o(r() * s)}, ${o(r() * s)}, ${o(r() * s)}, 1)`
},
},
computed: {
chartData() {
const datasets = []
const final = []
for (let i = 0; i < this.data.length; i++) {
const data = []
for (let j = 0; j < this.data[i].dias.length; j++) {
data.push(this.data[i].dias[j].prestamos.length)
if (this.data.length > 1) {
if (i === 0) final.push(0)
final[j] += this.data[i].dias[j].prestamos.length
}
}
datasets.push({
label: this.data[i].institucion,
data,
backgroundColor: 'rgba(0, 0, 0, 0)',
borderColor: this.randomRgba(),
borderWidth: 2,
})
}
if (this.data.length === 1) {
for (let i = 0; i < this.data[0].modulos.length; i++) {
const data = []
for (let j = 0; j < this.data[0].modulos[i].dias.length; j++)
data.push(this.data[0].modulos[i].dias[j].prestamos.length)
datasets.push({
label: this.data[0].modulos[i].modulo,
data,
backgroundColor: 'rgba(0, 0, 0, 0)',
borderColor: this.randomRgba(),
borderWidth: 2,
})
}
}
if (this.data.length > 1)
datasets.push({
label: 'Total',
data: final,
backgroundColor: 'rgba(0, 0, 0, 0)',
borderColor: this.randomRgba(),
borderWidth: 2,
})
return {
labels: this.labels,
datasets,
}
},
},
}
</script>

View File

@ -42,6 +42,9 @@ export default {
this.fecha = this.fechaPadre
},
},
created() {
if (this.fechaPadre) this.fecha = this.fechaPadre
},
}
</script>

View File

@ -139,6 +139,13 @@
/>
</template>
<b-menu-item
label="Gráficas"
:disabled="activo('/admin/administrador/graficas')"
:icon="icono('/admin/administrador/graficas')"
@click="opcionMenu('/admin/administrador/graficas')"
/>
<b-menu-item
label="Administradores"
:disabled="activo('/admin/administrador/admins')"

View File

@ -103,6 +103,7 @@
/>
<SelectCarrera
columnSize="is-3"
:idInstitucion="
operador.institucion
? operador.institucion.id_institucion
@ -140,7 +141,7 @@
<InputFecha
columnSize="is-3"
label="Fecha inicio"
fechaPadre="fechaInicio"
:fechaPadre="fechaInicio"
:fechaMaxima="fechaMax"
:fechaMinima="fechaMinInicio"
@fecha="(fechaNueva) => (fechaInicio = fechaNueva)"
@ -150,7 +151,7 @@
<InputFecha
columnSize="is-3"
label="Fecha fin"
fechaPadre="fechaFin"
:fechaPadre="fechaFin"
:fechaMaxima="fechaMax"
:fechaMinima="fechaMinFin"
@fecha="(fechaNueva) => (fechaFin = fechaNueva)"

View File

@ -15,7 +15,7 @@ export default {
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
css: [],
plugins: ['~/plugins/inject.js'],
plugins: ['~/plugins/inject.js', '~/plugins/chart.js'],
components: true,
buildModules: [],
modules: ['@nuxtjs/axios', 'nuxt-buefy', '@nuxtjs/pwa', 'nuxt-socket-io'],

99
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@hcaptcha/vue-hcaptcha": "^0.3.2",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/pwa": "^3.3.5",
"chart.js": "^2.7.1",
"convert-array-to-csv": "^2.0.0",
"core-js": "^3.24.1",
"js-file-download": "^0.4.12",
@ -20,6 +21,7 @@
"nuxt-buefy": "^0.4.23",
"nuxt-socket-io": "^2.0.3",
"validator": "^13.7.0",
"vue-chartjs": "^3.4.0",
"vue-qrcode-reader": "^3.1.0"
},
"devDependencies": {
@ -4445,6 +4447,45 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
"node_modules/chart.js": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.1.tgz",
"integrity": "sha512-pX1oQAY86MiuyZ2hY593Acbl4MLHKrBBhhmZ1YqSadzQbbsBE2rnd6WISoHjIsdf0WDeC0hbePYCz2ZxkV8L+g==",
"dependencies": {
"chartjs-color": "~2.2.0",
"moment": "~2.18.0"
}
},
"node_modules/chart.js/node_modules/moment": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
"integrity": "sha512-QGcnVKRSEhbWy2i0pqFhjWMCczL/YU5ICMB3maUavFcyUqBszRnzsswvOaGOqSfWZ/R+dMnb9gGBuRT4LMTdVQ==",
"engines": {
"node": "*"
}
},
"node_modules/chartjs-color": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz",
"integrity": "sha512-lmrNe4fRXbMK+9Iwuhx+pH686RGZZRZKJuJ5xUctCqtRDgoluqxEe3TiDstWfuppDt1LTSEMR6bU4xW5IYdwNA==",
"dependencies": {
"chartjs-color-string": "^0.5.0",
"color-convert": "^0.5.3"
}
},
"node_modules/chartjs-color-string": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz",
"integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==",
"dependencies": {
"color-name": "^1.0.0"
}
},
"node_modules/chartjs-color/node_modules/color-convert": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
"integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling=="
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@ -13658,6 +13699,18 @@
"csstype": "^3.1.0"
}
},
"node_modules/vue-chartjs": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-3.4.0.tgz",
"integrity": "sha512-uikAXl66g49rawH7Uto3gKh/7vxflcd5xyYbnQVGKSYEh9VI9JGMZ1KNPAEr+8ViRd2FX1hPDVevKBONK6v1fw==",
"engines": {
"node": ">=6.9.0",
"npm": ">= 3.0.0"
},
"peerDependencies": {
"chart.js": "2.7.x"
}
},
"node_modules/vue-client-only": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/vue-client-only/-/vue-client-only-2.1.0.tgz",
@ -18563,6 +18616,46 @@
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
"chart.js": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.1.tgz",
"integrity": "sha512-pX1oQAY86MiuyZ2hY593Acbl4MLHKrBBhhmZ1YqSadzQbbsBE2rnd6WISoHjIsdf0WDeC0hbePYCz2ZxkV8L+g==",
"requires": {
"chartjs-color": "~2.2.0",
"moment": "~2.18.0"
},
"dependencies": {
"moment": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
"integrity": "sha512-QGcnVKRSEhbWy2i0pqFhjWMCczL/YU5ICMB3maUavFcyUqBszRnzsswvOaGOqSfWZ/R+dMnb9gGBuRT4LMTdVQ=="
}
}
},
"chartjs-color": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz",
"integrity": "sha512-lmrNe4fRXbMK+9Iwuhx+pH686RGZZRZKJuJ5xUctCqtRDgoluqxEe3TiDstWfuppDt1LTSEMR6bU4xW5IYdwNA==",
"requires": {
"chartjs-color-string": "^0.5.0",
"color-convert": "^0.5.3"
},
"dependencies": {
"color-convert": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
"integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling=="
}
}
},
"chartjs-color-string": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz",
"integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==",
"requires": {
"color-name": "^1.0.0"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@ -25705,6 +25798,12 @@
"csstype": "^3.1.0"
}
},
"vue-chartjs": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-3.4.0.tgz",
"integrity": "sha512-uikAXl66g49rawH7Uto3gKh/7vxflcd5xyYbnQVGKSYEh9VI9JGMZ1KNPAEr+8ViRd2FX1hPDVevKBONK6v1fw==",
"requires": {}
},
"vue-client-only": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/vue-client-only/-/vue-client-only-2.1.0.tgz",

View File

@ -12,6 +12,7 @@
"@hcaptcha/vue-hcaptcha": "^0.3.2",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/pwa": "^3.3.5",
"chart.js": "^2.7.1",
"convert-array-to-csv": "^2.0.0",
"core-js": "^3.24.1",
"js-file-download": "^0.4.12",
@ -21,6 +22,7 @@
"nuxt-buefy": "^0.4.23",
"nuxt-socket-io": "^2.0.3",
"validator": "^13.7.0",
"vue-chartjs": "^3.4.0",
"vue-qrcode-reader": "^3.1.0"
},
"devDependencies": {

View File

@ -0,0 +1,37 @@
<template>
<section>
<Title title="Gráficas" :operador="admin" />
<Graficas :admin="admin" :updateIsLoading="updateIsLoading" />
<b-loading :can-cancel="false" v-model="isLoading" is-full-page />
</section>
</template>
<script>
import jwt_decode from 'jwt-decode'
import Graficas from '@/components/admin/Graficas'
import Title from '@/components/layouts/Title'
export default {
components: { Graficas, Title },
data() {
return { admin: {}, isLoading: false }
},
methods: {
updateIsLoading(valorBooleano) {
this.isLoading = valorBooleano
},
},
created() {
this.admin = jwt_decode(this.$getToken.tokenStr()).Operador
if (
this.admin.tipoUsuario.id_tipo_usuario != 2 &&
this.admin.tipoUsuario.id_tipo_usuario != 3
)
this.$router.push('/prestamo_devolucion')
},
}
</script>
<style></style>

26
plugins/chart.js Normal file
View File

@ -0,0 +1,26 @@
import Vue from 'vue'
import { Line } from 'vue-chartjs'
Vue.component('LineChart', {
extends: Line,
props: {
data: { type: Object, required: true },
options: {
type: Object,
required: false,
default: () => ({
responsive: true,
maintainAspectRatio: false,
legend: { display: true },
}),
},
},
watch: {
data() {
this.renderChart(this.data, this.options)
},
},
mounted() {
this.renderChart(this.data, this.options)
},
})