Stable
This commit is contained in:
514
ts/auditoría.ts
514
ts/auditoría.ts
@@ -1,237 +1,277 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
import { text } from 'stream/consumers';
|
||||
type Registro = {
|
||||
carrera: string;
|
||||
carrera_id: number;
|
||||
comentario: null;
|
||||
dia: string;
|
||||
duracion: string;
|
||||
duracion_id: number;
|
||||
estado_supervisor_id: number;
|
||||
facultad: string;
|
||||
facultad_id: number;
|
||||
horario_dia: number;
|
||||
horario_fin: string;
|
||||
horario_grupo: string;
|
||||
horario_hora: string;
|
||||
horario_id: number;
|
||||
materia: string;
|
||||
materia_id: number;
|
||||
nombre: string;
|
||||
periodo: string;
|
||||
periodo_id: number;
|
||||
profesor_clave: string;
|
||||
profesor_correo: string;
|
||||
profesor_grado: null;
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
registro_fecha: null;
|
||||
registro_fecha_ideal: Date;
|
||||
registro_fecha_supervisor: Date;
|
||||
registro_id: number;
|
||||
registro_justificada: null;
|
||||
registro_retardo: null;
|
||||
salon: string;
|
||||
salon_id: number;
|
||||
supervisor_id: number;
|
||||
}
|
||||
|
||||
type Estado = {
|
||||
color: string;
|
||||
icon: string;
|
||||
estado_supervisor_id: number;
|
||||
}
|
||||
|
||||
type Facultad = {
|
||||
clave_dependencia: string;
|
||||
facultad_id: number;
|
||||
facultad_nombre: string;
|
||||
}
|
||||
|
||||
type Filter = {
|
||||
type: string;
|
||||
value: string;
|
||||
icon: string;
|
||||
field: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const store = reactive({
|
||||
loading: false,
|
||||
current: {
|
||||
comentario: '',
|
||||
clase_vista: null,
|
||||
empty: '',
|
||||
},
|
||||
facultades: {
|
||||
data: [] as Facultad[],
|
||||
async fetch() {
|
||||
this.data = [] as Facultad[]
|
||||
const res = await fetch('action/action_facultad.php')
|
||||
this.data = await res.json()
|
||||
},
|
||||
},
|
||||
filters: {
|
||||
facultad_id: null,
|
||||
fecha: null,
|
||||
fecha_inicio: null,
|
||||
fecha_fin: null,
|
||||
profesor: null,
|
||||
estados: [],
|
||||
|
||||
switchFecha: false,
|
||||
switchFechas() {
|
||||
$(function () {
|
||||
store.filters.fecha_inicio = store.filters.fecha_fin = store.filters.fecha = null
|
||||
|
||||
$("#fecha, #fecha_inicio, #fecha_fin").datepicker({
|
||||
minDate: -3,
|
||||
maxDate: new Date(),
|
||||
dateFormat: "yy-mm-dd",
|
||||
showAnim: "slide",
|
||||
});
|
||||
|
||||
const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin")
|
||||
inicio.on("change", function () {
|
||||
store.filters.fecha_inicio = inicio.val()
|
||||
fin.datepicker("option", "minDate", inicio.val());
|
||||
});
|
||||
fin.on("change", function () {
|
||||
store.filters.fecha_fin = fin.val()
|
||||
inicio.datepicker("option", "maxDate", fin.val());
|
||||
});
|
||||
fecha.on("change", function () {
|
||||
store.filters.fecha = fecha.val()
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
estados: {
|
||||
data: [] as Estado[],
|
||||
async fetch() {
|
||||
this.data = [] as Estado[]
|
||||
const res = await fetch('action/action_estado_supervisor.php')
|
||||
this.data = await res.json()
|
||||
},
|
||||
getEstado(id: number): Estado {
|
||||
return this.data.find((estado: Estado) => estado.estado_supervisor_id === id)
|
||||
},
|
||||
printEstados() {
|
||||
if (store.filters.estados.length > 0)
|
||||
document.querySelector('#estados')!.innerHTML = store.filters.estados.map((estado: number) =>
|
||||
`<span class="mx-2 badge badge-${store.estados.getEstado(estado).estado_color}">
|
||||
<i class="${store.estados.getEstado(estado).estado_icon}"></i> ${store.estados.getEstado(estado).nombre}
|
||||
</span>`
|
||||
).join('')
|
||||
else
|
||||
document.querySelector('#estados')!.innerHTML = `Todos los registros`
|
||||
}
|
||||
},
|
||||
toggle(arr: any, element: any) {
|
||||
const newArray = arr.includes(element) ? arr.filter((item: any) => item !== element) : [...arr, element]
|
||||
// if all are selected, then unselect all
|
||||
if (newArray.length === this.estados.data.length) return []
|
||||
return newArray
|
||||
},
|
||||
})
|
||||
|
||||
declare var $: any
|
||||
|
||||
|
||||
|
||||
type Profesor = {
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
profesor_correo: string;
|
||||
profesor_clave: string;
|
||||
profesor_grado: string;
|
||||
}
|
||||
|
||||
createApp({
|
||||
store,
|
||||
get clase_vista() {
|
||||
return store.current.clase_vista
|
||||
},
|
||||
registros: {
|
||||
data: [] as Registro[],
|
||||
async fetch() {
|
||||
this.loading = true
|
||||
this.data = [] as Registro[]
|
||||
const res = await fetch('action/action_auditoria.php')
|
||||
this.data = await res.json()
|
||||
this.loading = false
|
||||
},
|
||||
invertir() {
|
||||
this.data = this.data.reverse()
|
||||
},
|
||||
mostrarComentario(registro_id: number) {
|
||||
const registro = this.data.find((registro: Registro) => registro.registro_id === registro_id)
|
||||
store.current.comentario = registro.comentario
|
||||
$('#ver-comentario').modal('show')
|
||||
},
|
||||
|
||||
get relevant() {
|
||||
/*
|
||||
facultad_id: null,
|
||||
fecha: null,
|
||||
fecha_inicio: null,
|
||||
fecha_fin: null,
|
||||
profesor: null,
|
||||
asistencia: null,
|
||||
estado_id: null,
|
||||
if one of the filters is null, then it is not relevant
|
||||
|
||||
*/
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] || store.filters[filtro]?.length > 0)
|
||||
return this.data.filter((registro: Registro) => {
|
||||
return filters.every((filtro) => {
|
||||
switch (filtro) {
|
||||
case 'fecha':
|
||||
return registro.registro_fecha_ideal === store.filters[filtro];
|
||||
case 'fecha_inicio':
|
||||
return registro.registro_fecha_ideal >= store.filters[filtro];
|
||||
case 'fecha_fin':
|
||||
return registro.registro_fecha_ideal <= store.filters[filtro];
|
||||
case 'profesor':
|
||||
const textoFiltro = store.filters[filtro].toLowerCase();
|
||||
if (/^\([^)]+\)\s[\s\S]+$/.test(textoFiltro)) {
|
||||
const clave = registro.profesor_clave.toLowerCase();
|
||||
const filtroClave = textoFiltro.match(/\((.*?)\)/)?.[1];
|
||||
console.log(clave, filtroClave);
|
||||
return clave.includes(filtroClave);
|
||||
} else {
|
||||
const nombre = registro.profesor_nombre.toLowerCase();
|
||||
return nombre.includes(textoFiltro);
|
||||
}
|
||||
case 'facultad_id':
|
||||
return registro.facultad_id === store.filters[filtro];
|
||||
case 'estados':
|
||||
if (store.filters[filtro].length === 0) return true;
|
||||
return store.filters[filtro].includes(registro.estado_supervisor_id);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
get profesores() {
|
||||
return this.registros.data.map((registro: Registro) => (
|
||||
{
|
||||
profesor_id: registro.profesor_id,
|
||||
profesor_nombre: registro.profesor_nombre,
|
||||
profesor_correo: registro.profesor_correo,
|
||||
profesor_clave: registro.profesor_clave,
|
||||
profesor_grado: registro.profesor_grado,
|
||||
}
|
||||
)).sort((a: Profesor, b: Profesor) =>
|
||||
a.profesor_nombre.localeCompare(b.profesor_nombre)
|
||||
)
|
||||
},
|
||||
async mounted() {
|
||||
await this.registros.fetch()
|
||||
await store.facultades.fetch()
|
||||
await store.estados.fetch()
|
||||
store.filters.switchFechas()
|
||||
}
|
||||
}).mount('#app')
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
type Registro = {
|
||||
carrera: string;
|
||||
carrera_id: number;
|
||||
comentario: null;
|
||||
dia: string;
|
||||
duracion: string;
|
||||
duracion_id: number;
|
||||
estado_supervisor_id: number;
|
||||
facultad: string;
|
||||
facultad_id: number;
|
||||
horario_dia: number;
|
||||
horario_fin: string;
|
||||
horario_grupo: string;
|
||||
horario_hora: string;
|
||||
horario_id: number;
|
||||
materia: string;
|
||||
materia_id: number;
|
||||
nombre: string;
|
||||
periodo: string;
|
||||
periodo_id: number;
|
||||
profesor_clave: string;
|
||||
profesor_correo: string;
|
||||
profesor_grado: null;
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
registro_fecha: null;
|
||||
registro_fecha_ideal: Date;
|
||||
registro_fecha_supervisor: Date;
|
||||
registro_id: number;
|
||||
registro_justificada: null;
|
||||
registro_retardo: null;
|
||||
salon: string;
|
||||
salon_id: number;
|
||||
supervisor_id: number;
|
||||
}
|
||||
|
||||
type Estado = {
|
||||
color: string;
|
||||
icon: string;
|
||||
estado_supervisor_id: number;
|
||||
}
|
||||
|
||||
type Facultad = {
|
||||
clave_dependencia: string;
|
||||
facultad_id: number;
|
||||
facultad_nombre: string;
|
||||
}
|
||||
|
||||
type Bloque_Horario = {
|
||||
hora_fin: string;
|
||||
hora_inicio: string;
|
||||
id: number;
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
|
||||
type Filter = {
|
||||
type: string;
|
||||
value: string;
|
||||
icon: string;
|
||||
field: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const store = reactive({
|
||||
loading: false,
|
||||
current: {
|
||||
comentario: '',
|
||||
clase_vista: null,
|
||||
empty: '',
|
||||
},
|
||||
facultades: {
|
||||
data: [] as Facultad[],
|
||||
async fetch() {
|
||||
this.data = [] as Facultad[]
|
||||
const res = await fetch('action/action_facultad.php')
|
||||
this.data = await res.json()
|
||||
},
|
||||
},
|
||||
filters: {
|
||||
facultad_id: null,
|
||||
fecha: null,
|
||||
fecha_inicio: null,
|
||||
fecha_fin: null,
|
||||
profesor: null,
|
||||
bloque_horario: null,
|
||||
estados: [],
|
||||
|
||||
switchFecha: false,
|
||||
switchFechas() {
|
||||
$(function () {
|
||||
store.filters.fecha_inicio = store.filters.fecha_fin = store.filters.fecha = null
|
||||
|
||||
$("#fecha, #fecha_inicio, #fecha_fin").datepicker({
|
||||
minDate: -3,
|
||||
maxDate: new Date(),
|
||||
dateFormat: "yy-mm-dd",
|
||||
showAnim: "slide",
|
||||
});
|
||||
|
||||
const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin")
|
||||
inicio.on("change", function () {
|
||||
store.filters.fecha_inicio = inicio.val()
|
||||
fin.datepicker("option", "minDate", inicio.val());
|
||||
});
|
||||
fin.on("change", function () {
|
||||
store.filters.fecha_fin = fin.val()
|
||||
inicio.datepicker("option", "maxDate", fin.val());
|
||||
});
|
||||
fecha.on("change", function () {
|
||||
store.filters.fecha = fecha.val()
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
estados: {
|
||||
data: [] as Estado[],
|
||||
async fetch() {
|
||||
this.data = [] as Estado[]
|
||||
const res = await fetch('action/action_estado_supervisor.php')
|
||||
this.data = await res.json()
|
||||
},
|
||||
getEstado(id: number): Estado {
|
||||
return this.data.find((estado: Estado) => estado.estado_supervisor_id === id)
|
||||
},
|
||||
printEstados() {
|
||||
if (store.filters.estados.length > 0)
|
||||
document.querySelector('#estados')!.innerHTML = store.filters.estados.map((estado: number) =>
|
||||
`<span class="mx-2 badge badge-${store.estados.getEstado(estado).estado_color}">
|
||||
<i class="${store.estados.getEstado(estado).estado_icon}"></i> ${store.estados.getEstado(estado).nombre}
|
||||
</span>`
|
||||
).join('')
|
||||
else
|
||||
document.querySelector('#estados')!.innerHTML = `Todos los registros`
|
||||
}
|
||||
},
|
||||
bloques_horario: {
|
||||
data: [] as Bloque_Horario[],
|
||||
async fetch() {
|
||||
this.data = [] as Bloque_Horario[]
|
||||
const res = await fetch('action/action_grupo_horario.php')
|
||||
this.data = await res.json()
|
||||
|
||||
if (this.data.every((bloque: Bloque_Horario) => !bloque.selected))
|
||||
this.data[0].selected = true
|
||||
},
|
||||
},
|
||||
toggle(arr: any, element: any) {
|
||||
const newArray = arr.includes(element) ? arr.filter((item: any) => item !== element) : [...arr, element]
|
||||
// if all are selected, then unselect all
|
||||
if (newArray.length === this.estados.data.length) return []
|
||||
return newArray
|
||||
},
|
||||
})
|
||||
|
||||
declare var $: any
|
||||
|
||||
|
||||
|
||||
type Profesor = {
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
profesor_correo: string;
|
||||
profesor_clave: string;
|
||||
profesor_grado: string;
|
||||
}
|
||||
|
||||
createApp({
|
||||
store,
|
||||
get clase_vista() {
|
||||
return store.current.clase_vista
|
||||
},
|
||||
registros: {
|
||||
data: [] as Registro[],
|
||||
async fetch() {
|
||||
this.loading = true
|
||||
this.data = [] as Registro[]
|
||||
const res = await fetch('action/action_auditoria.php')
|
||||
this.data = await res.json()
|
||||
this.loading = false
|
||||
},
|
||||
invertir() {
|
||||
this.data = this.data.reverse()
|
||||
},
|
||||
mostrarComentario(registro_id: number) {
|
||||
const registro = this.data.find((registro: Registro) => registro.registro_id === registro_id)
|
||||
store.current.comentario = registro.comentario
|
||||
$('#ver-comentario').modal('show')
|
||||
},
|
||||
|
||||
get relevant() {
|
||||
/*
|
||||
facultad_id: null,
|
||||
fecha: null,
|
||||
fecha_inicio: null,
|
||||
fecha_fin: null,
|
||||
profesor: null,
|
||||
asistencia: null,
|
||||
estado_id: null,
|
||||
if one of the filters is null, then it is not relevant
|
||||
|
||||
*/
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] || store.filters[filtro]?.length > 0)
|
||||
return this.data.filter((registro: Registro) => {
|
||||
return filters.every((filtro) => {
|
||||
|
||||
switch (filtro) {
|
||||
case 'fecha':
|
||||
return registro.registro_fecha_ideal === store.filters[filtro];
|
||||
case 'fecha_inicio':
|
||||
return registro.registro_fecha_ideal >= store.filters[filtro];
|
||||
case 'fecha_fin':
|
||||
return registro.registro_fecha_ideal <= store.filters[filtro];
|
||||
case 'profesor':
|
||||
const textoFiltro = store.filters[filtro].toLowerCase();
|
||||
if (/^\([^)]+\)\s[\s\S]+$/.test(textoFiltro)) {
|
||||
const clave = registro.profesor_clave.toLowerCase();
|
||||
const filtroClave = textoFiltro.match(/\((.*?)\)/)?.[1];
|
||||
console.log(clave, filtroClave);
|
||||
return clave.includes(filtroClave);
|
||||
} else {
|
||||
const nombre = registro.profesor_nombre.toLowerCase();
|
||||
return nombre.includes(textoFiltro);
|
||||
}
|
||||
case 'facultad_id':
|
||||
return registro.facultad_id === store.filters[filtro];
|
||||
case 'estados':
|
||||
if (store.filters[filtro].length === 0) return true;
|
||||
return store.filters[filtro].includes(registro.estado_supervisor_id);
|
||||
case 'bloque_horario':
|
||||
const bloque = store.bloques_horario.data.find((bloque: Bloque_Horario) => bloque.id === store.filters[filtro]) as Bloque_Horario;
|
||||
return registro.horario_hora <= bloque.hora_fin && registro.horario_fin >= bloque.hora_inicio;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async descargar() {
|
||||
if (this.relevant.length === 0) return;
|
||||
const res = await fetch('export/supervisor_excel.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(this.relevant)
|
||||
});
|
||||
const blob = await res.blob();
|
||||
(window as any).saveAs(blob, `auditoria_${new Date().toISOString().slice(0, 10)}.xlsx`);
|
||||
}
|
||||
},
|
||||
get profesores() {
|
||||
return this.registros.data.map((registro: Registro) => (
|
||||
{
|
||||
profesor_id: registro.profesor_id,
|
||||
profesor_nombre: registro.profesor_nombre,
|
||||
profesor_correo: registro.profesor_correo,
|
||||
profesor_clave: registro.profesor_clave,
|
||||
profesor_grado: registro.profesor_grado,
|
||||
}
|
||||
)).sort((a: Profesor, b: Profesor) =>
|
||||
a.profesor_nombre.localeCompare(b.profesor_nombre)
|
||||
)
|
||||
},
|
||||
async mounted() {
|
||||
await this.registros.fetch()
|
||||
await store.facultades.fetch()
|
||||
await store.estados.fetch()
|
||||
await store.bloques_horario.fetch()
|
||||
|
||||
store.filters.bloque_horario = store.bloques_horario.data.find((bloque: Bloque_Horario) => bloque.selected)?.id
|
||||
store.filters.switchFechas()
|
||||
}
|
||||
}).mount('#app')
|
||||
|
||||
Reference in New Issue
Block a user