diff --git a/js/auditoría.js b/js/auditoría.js index 8f225b2..58cbb67 100644 --- a/js/auditoría.js +++ b/js/auditoría.js @@ -1,404 +1,404 @@ -import { createApp, reactive } from 'https://unpkg.com/petite-vue@0.4.1/dist/petite-vue.es.js'; -$('div.modal#cargando').modal({ - backdrop: 'static', - keyboard: false, - show: false, -}); -const store = reactive({ - loading: false, - perido: null, - current: { - comentario: '', - clase_vista: null, - empty: '', - page: 1, - maxPages: 10, - perPage: 10, - modal_state: "Cargando datos...", - justificada: null, - fechas_clicked: false, - observaciones: false, - }, - facultades: { - data: [], - async fetch() { - this.data = []; - 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, - periodo_id: null, - bloque_horario: null, - estados: [], - switchFecha: false, - async switchFechas() { - const periodo = await fetch('action/periodo_datos.php'); - const periodo_data = await periodo.json(); - if (!store.filters.switchFecha) { - $('div.modal#cargando').modal('show'); - await store.registros.fetch(); - $('div.modal#cargando').modal('hide'); - } - $(function () { - store.filters.fecha_inicio = store.filters.fecha_fin = store.filters.fecha = null; - $("#fecha, #fecha_inicio, #fecha_fin").datepicker({ - // minDate: new Date(`${periodo_data.periodo_fecha_inicio}:00:00:00`), - maxDate: new Date(), - dateFormat: "yy-mm-dd", - showAnim: "slideDown", - beforeShowDay: (date) => [(date.getDay() != 0), ""] - }); - const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin"); - fecha.datepicker("setDate", new Date()); - inicio.on("change", function () { - store.current.fechas_clicked = false; - store.filters.fecha_inicio = inicio.val(); - fin.datepicker("option", "minDate", inicio.val()); - }); - fin.on("change", function () { - store.current.fechas_clicked = false; - store.filters.fecha_fin = fin.val(); - inicio.datepicker("option", "maxDate", fin.val()); - }); - fecha.on("change", async function () { - store.filters.fecha = fecha.val(); - $('div.modal#cargando').modal('show'); - await store.registros.fetch(store.filters.fecha); - $('div.modal#cargando').modal('hide'); - }); - }); - }, - async fetchByDate() { - store.current.fechas_clicked = true; - $('div.modal#cargando').modal('show'); - await store.registros.fetch(undefined, store.filters.fecha_inicio, store.filters.fecha_fin); - store.current.page = 1; - $('div.modal#cargando').modal('hide'); - } - }, - estados: { - data: [], - async fetch() { - this.data = []; - const res = await fetch('action/action_estado_supervisor.php'); - this.data = await res.json(); - }, - getEstado(id) { - return this.data.find((estado) => estado.estado_supervisor_id === id) ?? { - estado_color: 'dark', - estado_icon: 'ing-cancelar', - nombre: 'Sin registro', - estado_supervisor_id: -1, - }; - }, - printEstados() { - if (store.filters.estados.length > 0) - document.querySelector('#estados').innerHTML = store.filters.estados.map((estado) => ` - ${store.estados.getEstado(estado).nombre} - `).join(''); - else - document.querySelector('#estados').innerHTML = `Todos los registros`; - } - }, - bloques_horario: { - data: [], - async fetch() { - this.data = []; - const res = await fetch('action/action_grupo_horario.php'); - this.data = await res.json(); - if (this.data.every((bloque) => !bloque.selected)) - this.data[0].selected = true; - }, - }, - toggle(arr, element) { - const newArray = arr.includes(element) ? arr.filter((item) => item !== element) : [...arr, element]; - // if all are selected, then unselect all - if (newArray.length === (this.estados.data.length + 1)) { - setTimeout(() => { - document.querySelectorAll('#dlAsistencia>ul>li.selected').forEach(element => element.classList.remove('selected')); - }, 100); - return []; - } - return newArray; - }, - async justificar() { - if (!store.current.justificada) - return; - store.current.justificada.registro_justificada = true; - let data; - try { - const res = await fetch('action/justificar.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(store.current.justificada) - }); - - data = await res.json(); - } - catch (error) { - alert('Error al justificar'); - store.current.justificada = store.current.clone_justificada; - } - finally { - delete store.current.clone_justificada; - } - store.current.justificada.justificador_nombre = data.justificador_nombre; - store.current.justificada.justificador_clave = data.justificador_clave; - store.current.justificada.justificador_facultad = data.justificador_facultad; - store.current.justificada.justificador_rol = data.justificador_rol; - store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion; - }, - async justificarBloque(fecha, bloques, justificacion) { - if (bloques.length === 0) { - alert('No se ha seleccionado ningún bloque'); - return; - } - if (!justificacion) { - alert('No se ha ingresado ninguna observación'); - return; - } - try { - const res = await fetch('action/action_justificar.php', { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - fecha, - bloques, - justificacion, - }) - }); - const resData = await res.json(); - if (resData.status === 'success') { - alert('Se ha justificado el bloque'); - store.current.modal_state = 'Cargando datos...'; - $('div.modal#cargando').modal('show'); - await store.registros.fetch(); - $('div.modal#cargando').modal('hide'); - } - else { - alert('No se ha podido justificar el bloque'); - } - } - catch (error) { - alert('Error al justificar'); - } - }, - registros: { - data: [], - async fetch(fecha, fecha_inicio, fecha_fin) { - // if (!store.filters.facultad_id || !store.filters.periodo_id) return - this.loading = true; - this.data = []; - const params = {}; - if (fecha) - params['fecha'] = fecha; - if (fecha_inicio) - params['fecha_inicio'] = fecha_inicio; - if (fecha_fin) - params['fecha_fin'] = fecha_fin; - params['periodo_id'] = store.filters.todos_los_periodos ? 0 : store.periodo.periodo_id; - // console.log(store.periodo); - const paramsUrl = new URLSearchParams(params).toString(); - try { - const res = await fetch(`action/action_auditoria.php?${paramsUrl}`, { - method: 'GET', - }); - this.data = await res.json(); - } - catch (error) { - alert('Error al cargar los datos'); - } - this.loading = false; - store.current.page = 1; - }, - invertir() { - this.data = this.data.reverse(); - }, - mostrarComentario(registro_id) { - const registro = this.data.find((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] !== null || store.filters[filtro]?.length > 0); - return this.data.filter((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; - else if (store.filters[filtro].includes(-1) && registro.estado_supervisor_id === null) - return true; - return store.filters[filtro].includes(registro.estado_supervisor_id); - case 'bloque_horario': - const bloque = store.bloques_horario.data.find((bloque) => bloque.id === store.filters[filtro]); - return registro.horario_hora < bloque.hora_fin && registro.horario_fin > bloque.hora_inicio; - default: return true; - } - }); - }); - }, - async descargar() { - store.current.modal_state = 'Generando reporte en Excel...'; - $('div.modal#cargando').modal('show'); - this.loading = true; - if (this.relevant.length === 0) - return; - try { - const res = await fetch('export/supervisor_excel.php', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - 'facultad_id': store.filters.facultad_id, - 'estados': store.filters.estados, - 'profesor': store.filters.profesor, - 'bloque_horario': store.bloques_horario?.data.find((bloque) => bloque.id === store.filters['bloque_horario']), - }) - }); - const blob = await res.blob(); - window.saveAs(blob, `auditoria_${new Date().toISOString().slice(0, 10)}.xlsx`); - } - catch (error) { - if (error.response && error.response.status === 413) { - alert('Your request is too large! Please reduce the data size and try again.'); - } - else { - alert('An error occurred: ' + error.message); - } - } - finally { - $('#cargando').modal('hide'); - this.loading = false; - } - }, - loading: false, - get pages() { - return Math.ceil(this.relevant.length / store.current.perPage); - } - }, -}); - -const detalle = reactive({ - correo: null, - facultad: null, - materia: null, - carrera: null, - nivel: null, - horario_grupo: null, - - reset() { - this.correo = null - this.facultad = null - this.materia = null - this.carrera = null - this.nivel = null - this.horario_grupo = null - }, - - async obtener_detalle(horario_id, profesor_id, registro_fecha_ideal) { - detalle.reset(); - - $('div.modal#cargando').modal('show'); - try { - const resultado = await (await fetch(`action/action_auditoria_detalle.php?${new URLSearchParams({ horario_id, profesor_id, registro_fecha_ideal })}`)).json(); - - this.correo = resultado.profesor_correo; - this.facultad = resultado.facultad; - this.materia = resultado.materia; - this.carrera = resultado.carrera; - this.nivel = resultado.nivel; - this.horario_grupo = resultado.horario_grupo; - - this.registro_fecha = - store.current.clase_vista = resultado - store.current.clase_vista.supervisor_hora = resultado - } - catch (error) { - console.log('Error:', error) - } - finally { - $('div.modal#cargando').modal('hide'); - } - } -}); - -createApp({ - store, - detalle, - messages: [], - get clase_vista() { - return store.current.clase_vista; - }, - set_justificar(horario_id, profesor_id, registro_fecha_ideal) { - store.current.justificada = store.registros.relevant.find((registro) => registro.horario_id === horario_id && registro.profesor_id === profesor_id && registro.registro_fecha_ideal === registro_fecha_ideal); - store.current.clone_justificada = JSON.parse(JSON.stringify(store.current.justificada)); - store.current.observaciones = false; - }, - cancelar_justificacion() { - Object.assign(store.current.justificada, store.current.clone_justificada); - delete store.current.clone_justificada; - }, - profesores: [], - async mounted() { - $('div.modal#cargando').modal('show'); - try { - store.periodo = await fetch('action/periodo_datos.php').then(res => res.json()); - // await store.registros.fetch() - await store.facultades.fetch(); - await store.estados.fetch(); - await store.bloques_horario.fetch(); - await store.filters.switchFechas(); - this.profesores = await (await fetch('action/action_profesor.php')).json(); - this.messages.push({ title: 'Datos cargados', text: 'Los datos se han cargado correctamente', type: 'success', timestamp: new Date() }); - } - catch (error) { - this.messages.push({ title: 'Error al cargar datos', text: 'No se pudieron cargar los datos', type: 'danger', timestamp: new Date() }); - } - finally { - $('div.modal#cargando').modal('hide'); - } - } -}).mount('#app'); +import { createApp, reactive } from 'https://unpkg.com/petite-vue@0.4.1/dist/petite-vue.es.js'; +$('div.modal#cargando').modal({ + backdrop: 'static', + keyboard: false, + show: false, +}); +const store = reactive({ + loading: false, + perido: null, + current: { + comentario: '', + clase_vista: null, + empty: '', + page: 1, + maxPages: 10, + perPage: 10, + modal_state: "Cargando datos...", + justificada: null, + fechas_clicked: false, + observaciones: false, + }, + facultades: { + data: [], + async fetch() { + this.data = []; + 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, + periodo_id: null, + bloque_horario: null, + estados: [], + switchFecha: false, + async switchFechas() { + const periodo = await fetch('action/periodo_datos.php'); + const periodo_data = await periodo.json(); + if (!store.filters.switchFecha) { + $('div.modal#cargando').modal('show'); + await store.registros.fetch(); + $('div.modal#cargando').modal('hide'); + } + $(function () { + store.filters.fecha_inicio = store.filters.fecha_fin = store.filters.fecha = null; + $("#fecha, #fecha_inicio, #fecha_fin").datepicker({ + // minDate: new Date(`${periodo_data.periodo_fecha_inicio}:00:00:00`), + maxDate: new Date(), + dateFormat: "yy-mm-dd", + showAnim: "slideDown", + beforeShowDay: (date) => [(date.getDay() != 0), ""] + }); + const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin"); + fecha.datepicker("setDate", new Date()); + inicio.on("change", function () { + store.current.fechas_clicked = false; + store.filters.fecha_inicio = inicio.val(); + fin.datepicker("option", "minDate", inicio.val()); + }); + fin.on("change", function () { + store.current.fechas_clicked = false; + store.filters.fecha_fin = fin.val(); + inicio.datepicker("option", "maxDate", fin.val()); + }); + fecha.on("change", async function () { + store.filters.fecha = fecha.val(); + $('div.modal#cargando').modal('show'); + await store.registros.fetch(store.filters.fecha); + $('div.modal#cargando').modal('hide'); + }); + }); + }, + async fetchByDate() { + store.current.fechas_clicked = true; + $('div.modal#cargando').modal('show'); + await store.registros.fetch(undefined, store.filters.fecha_inicio, store.filters.fecha_fin); + store.current.page = 1; + $('div.modal#cargando').modal('hide'); + } + }, + estados: { + data: [], + async fetch() { + this.data = []; + const res = await fetch('action/action_estado_supervisor.php'); + this.data = await res.json(); + }, + getEstado(id) { + return this.data.find((estado) => estado.estado_supervisor_id === id) ?? { + estado_color: 'dark', + estado_icon: 'ing-cancelar', + nombre: 'Sin registro', + estado_supervisor_id: -1, + }; + }, + printEstados() { + if (store.filters.estados.length > 0) + document.querySelector('#estados').innerHTML = store.filters.estados.map((estado) => ` + ${store.estados.getEstado(estado).nombre} + `).join(''); + else + document.querySelector('#estados').innerHTML = `Todos los registros`; + } + }, + bloques_horario: { + data: [], + async fetch() { + this.data = []; + const res = await fetch('action/action_grupo_horario.php'); + this.data = await res.json(); + if (this.data.every((bloque) => !bloque.selected)) + this.data[0].selected = true; + }, + }, + toggle(arr, element) { + const newArray = arr.includes(element) ? arr.filter((item) => item !== element) : [...arr, element]; + // if all are selected, then unselect all + if (newArray.length === (this.estados.data.length + 1)) { + setTimeout(() => { + document.querySelectorAll('#dlAsistencia>ul>li.selected').forEach(element => element.classList.remove('selected')); + }, 100); + return []; + } + return newArray; + }, + async justificar() { + if (!store.current.justificada) + return; + store.current.justificada.registro_justificada = true; + let data; + try { + const res = await fetch('action/justificar.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(store.current.justificada) + }); + + data = await res.json(); + } + catch (error) { + alert('Error al justificar'); + store.current.justificada = store.current.clone_justificada; + } + finally { + delete store.current.clone_justificada; + } + store.current.justificada.justificador_nombre = data.justificador_nombre; + store.current.justificada.justificador_clave = data.justificador_clave; + store.current.justificada.justificador_facultad = data.justificador_facultad; + store.current.justificada.justificador_rol = data.justificador_rol; + store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion; + }, + async justificarBloque(fecha, bloques, justificacion) { + if (bloques.length === 0) { + alert('No se ha seleccionado ningún bloque'); + return; + } + if (!justificacion) { + alert('No se ha ingresado ninguna observación'); + return; + } + try { + const res = await fetch('action/action_justificar.php', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + fecha, + bloques, + justificacion, + }) + }); + const resData = await res.json(); + if (resData.status === 'success') { + alert('Se ha justificado el bloque'); + store.current.modal_state = 'Cargando datos...'; + $('div.modal#cargando').modal('show'); + await store.registros.fetch(); + $('div.modal#cargando').modal('hide'); + } + else { + alert('No se ha podido justificar el bloque'); + } + } + catch (error) { + alert('Error al justificar'); + } + }, + registros: { + data: [], + async fetch(fecha, fecha_inicio, fecha_fin) { + // if (!store.filters.facultad_id || !store.filters.periodo_id) return + this.loading = true; + this.data = []; + const params = {}; + if (fecha) + params['fecha'] = fecha; + if (fecha_inicio) + params['fecha_inicio'] = fecha_inicio; + if (fecha_fin) + params['fecha_fin'] = fecha_fin; + // params['periodo_id'] = store.filters.todos_los_periodos ? 0 : store.periodo.periodo_id; + // console.log(store.periodo); + const paramsUrl = new URLSearchParams(params).toString(); + try { + const res = await fetch(`action/action_auditoria.php?${paramsUrl}`, { + method: 'GET', + }); + this.data = await res.json(); + } + catch (error) { + alert('Error al cargar los datos'); + } + this.loading = false; + store.current.page = 1; + }, + invertir() { + this.data = this.data.reverse(); + }, + mostrarComentario(registro_id) { + const registro = this.data.find((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] !== null || store.filters[filtro]?.length > 0); + return this.data.filter((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; + else if (store.filters[filtro].includes(-1) && registro.estado_supervisor_id === null) + return true; + return store.filters[filtro].includes(registro.estado_supervisor_id); + case 'bloque_horario': + const bloque = store.bloques_horario.data.find((bloque) => bloque.id === store.filters[filtro]); + return registro.horario_hora < bloque.hora_fin && registro.horario_fin > bloque.hora_inicio; + default: return true; + } + }); + }); + }, + async descargar() { + store.current.modal_state = 'Generando reporte en Excel...'; + $('div.modal#cargando').modal('show'); + this.loading = true; + if (this.relevant.length === 0) + return; + try { + const res = await fetch('export/supervisor_excel.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + 'facultad_id': store.filters.facultad_id, + 'estados': store.filters.estados, + 'profesor': store.filters.profesor, + 'bloque_horario': store.bloques_horario?.data.find((bloque) => bloque.id === store.filters['bloque_horario']), + }) + }); + const blob = await res.blob(); + window.saveAs(blob, `auditoria_${new Date().toISOString().slice(0, 10)}.xlsx`); + } + catch (error) { + if (error.response && error.response.status === 413) { + alert('Your request is too large! Please reduce the data size and try again.'); + } + else { + alert('An error occurred: ' + error.message); + } + } + finally { + $('#cargando').modal('hide'); + this.loading = false; + } + }, + loading: false, + get pages() { + return Math.ceil(this.relevant.length / store.current.perPage); + } + }, +}); + +const detalle = reactive({ + correo: null, + facultad: null, + materia: null, + carrera: null, + nivel: null, + horario_grupo: null, + + reset() { + this.correo = null + this.facultad = null + this.materia = null + this.carrera = null + this.nivel = null + this.horario_grupo = null + }, + + async obtener_detalle(horario_id, profesor_id, registro_fecha_ideal) { + detalle.reset(); + + $('div.modal#cargando').modal('show'); + try { + const resultado = await (await fetch(`action/action_auditoria_detalle.php?${new URLSearchParams({ horario_id, profesor_id, registro_fecha_ideal })}`)).json(); + + this.correo = resultado.profesor_correo; + this.facultad = resultado.facultad; + this.materia = resultado.materia; + this.carrera = resultado.carrera; + this.nivel = resultado.nivel; + this.horario_grupo = resultado.horario_grupo; + + this.registro_fecha = + store.current.clase_vista = resultado + store.current.clase_vista.supervisor_hora = resultado + } + catch (error) { + console.log('Error:', error) + } + finally { + $('div.modal#cargando').modal('hide'); + } + } +}); + +createApp({ + store, + detalle, + messages: [], + get clase_vista() { + return store.current.clase_vista; + }, + set_justificar(horario_id, profesor_id, registro_fecha_ideal) { + store.current.justificada = store.registros.relevant.find((registro) => registro.horario_id === horario_id && registro.profesor_id === profesor_id && registro.registro_fecha_ideal === registro_fecha_ideal); + store.current.clone_justificada = JSON.parse(JSON.stringify(store.current.justificada)); + store.current.observaciones = false; + }, + cancelar_justificacion() { + Object.assign(store.current.justificada, store.current.clone_justificada); + delete store.current.clone_justificada; + }, + profesores: [], + async mounted() { + $('div.modal#cargando').modal('show'); + try { + store.periodo = await fetch('action/periodo_datos.php').then(res => res.json()); + // await store.registros.fetch() + await store.facultades.fetch(); + await store.estados.fetch(); + await store.bloques_horario.fetch(); + await store.filters.switchFechas(); + this.profesores = await (await fetch('action/action_profesor.php')).json(); + this.messages.push({ title: 'Datos cargados', text: 'Los datos se han cargado correctamente', type: 'success', timestamp: new Date() }); + } + catch (error) { + this.messages.push({ title: 'Error al cargar datos', text: 'No se pudieron cargar los datos', type: 'danger', timestamp: new Date() }); + } + finally { + $('div.modal#cargando').modal('hide'); + } + } +}).mount('#app');