auditoría.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import { createApp, reactive } from 'https://unpkg.com/petite-vue?module';
  2. const store = reactive({
  3. loading: false,
  4. current: {
  5. comentario: '',
  6. clase_vista: null,
  7. empty: '',
  8. page: 1,
  9. maxPages: 10,
  10. perPage: 10,
  11. modal_state: "Cargando datos...",
  12. },
  13. facultades: {
  14. data: [],
  15. async fetch() {
  16. this.data = [];
  17. const res = await fetch('action/action_facultad.php');
  18. this.data = await res.json();
  19. },
  20. },
  21. filters: {
  22. facultad_id: null,
  23. fecha: null,
  24. fecha_inicio: null,
  25. fecha_fin: null,
  26. profesor: null,
  27. periodo_id: null,
  28. bloque_horario: null,
  29. sin_registro: false,
  30. estados: [],
  31. switchFecha: false,
  32. async switchFechas() {
  33. const periodo = await fetch('action/periodo_datos.php');
  34. const periodo_data = await periodo.json();
  35. // console.log(`Fecha inicio: ${periodo_data.periodo_fecha_inicio} Fecha fin: ${periodo_data.fecha_final}`);
  36. $(function () {
  37. store.filters.fecha_inicio = store.filters.fecha_fin = store.filters.fecha = null;
  38. $("#fecha, #fecha_inicio, #fecha_fin").datepicker({
  39. minDate: new Date(`${periodo_data.periodo_fecha_inicio}:00:00:00`),
  40. maxDate: new Date(`${periodo_data.fecha_final}:00:00:00`),
  41. dateFormat: "yy-mm-dd",
  42. showAnim: "slide",
  43. });
  44. const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin");
  45. inicio.on("change", function () {
  46. store.filters.fecha_inicio = inicio.val();
  47. fin.datepicker("option", "minDate", inicio.val());
  48. });
  49. fin.on("change", function () {
  50. store.filters.fecha_fin = fin.val();
  51. inicio.datepicker("option", "maxDate", fin.val());
  52. });
  53. fecha.on("change", function () {
  54. store.filters.fecha = fecha.val();
  55. });
  56. });
  57. }
  58. },
  59. estados: {
  60. data: [],
  61. async fetch() {
  62. this.data = [];
  63. const res = await fetch('action/action_estado_supervisor.php');
  64. this.data = await res.json();
  65. },
  66. getEstado(id) {
  67. return this.data.find((estado) => estado.estado_supervisor_id === id);
  68. },
  69. printEstados() {
  70. if (store.filters.estados.length > 0)
  71. document.querySelector('#estados').innerHTML = store.filters.estados.map((estado) => `<span class="mx-2 badge badge-${store.estados.getEstado(estado).estado_color}">
  72. <i class="${store.estados.getEstado(estado).estado_icon}"></i> ${store.estados.getEstado(estado).nombre}
  73. </span>`).join('');
  74. else
  75. document.querySelector('#estados').innerHTML = `Todos los registros`;
  76. }
  77. },
  78. bloques_horario: {
  79. data: [],
  80. async fetch() {
  81. this.data = [];
  82. const res = await fetch('action/action_grupo_horario.php');
  83. this.data = await res.json();
  84. if (this.data.every((bloque) => !bloque.selected))
  85. this.data[0].selected = true;
  86. },
  87. },
  88. toggle(arr, element) {
  89. const newArray = arr.includes(element) ? arr.filter((item) => item !== element) : [...arr, element];
  90. // if all are selected, then unselect all
  91. if (newArray.length === this.estados.data.length) {
  92. setTimeout(() => {
  93. document.querySelectorAll('#dlAsistencia>ul>li.selected').forEach(element => element.classList.remove('selected'));
  94. }, 100);
  95. return [];
  96. }
  97. return newArray;
  98. },
  99. });
  100. $('div.modal#cargando').modal({
  101. backdrop: 'static',
  102. keyboard: false,
  103. show: false,
  104. });
  105. createApp({
  106. store,
  107. get clase_vista() {
  108. return store.current.clase_vista;
  109. },
  110. registros: {
  111. data: [],
  112. async fetch() {
  113. // if (!store.filters.facultad_id || !store.filters.periodo_id) return
  114. this.loading = true;
  115. this.data = [];
  116. const params = {
  117. facultad_id: 19,
  118. periodo_id: 2,
  119. };
  120. const paramsUrl = new URLSearchParams(params).toString();
  121. const res = await fetch(`action/action_auditoria.php?${paramsUrl}`, {
  122. method: 'GET',
  123. });
  124. this.data = await res.json();
  125. this.loading = false;
  126. },
  127. invertir() {
  128. this.data = this.data.reverse();
  129. },
  130. mostrarComentario(registro_id) {
  131. const registro = this.data.find((registro) => registro.registro_id === registro_id);
  132. store.current.comentario = registro.comentario;
  133. $('#ver-comentario').modal('show');
  134. },
  135. get relevant() {
  136. /*
  137. facultad_id: null,
  138. fecha: null,
  139. fecha_inicio: null,
  140. fecha_fin: null,
  141. profesor: null,
  142. asistencia: null,
  143. estado_id: null,
  144. if one of the filters is null, then it is not relevant
  145. */
  146. const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] || store.filters[filtro]?.length > 0);
  147. /*
  148. store.current
  149. page: 1,
  150. maxPages: 10,
  151. perPage: 10,
  152. */
  153. return this.data.filter((registro) => {
  154. if (store.filters.sin_registro && !registro.registro_fecha_supervisor)
  155. return true;
  156. else if (store.filters.sin_registro)
  157. return false;
  158. return filters.every((filtro) => {
  159. switch (filtro) {
  160. case 'fecha':
  161. return registro.registro_fecha_ideal === store.filters[filtro];
  162. case 'fecha_inicio':
  163. return registro.registro_fecha_ideal >= store.filters[filtro];
  164. case 'fecha_fin':
  165. return registro.registro_fecha_ideal <= store.filters[filtro];
  166. case 'profesor':
  167. const textoFiltro = store.filters[filtro].toLowerCase();
  168. if (/^\([^)]+\)\s[\s\S]+$/.test(textoFiltro)) {
  169. const clave = registro.profesor_clave.toLowerCase();
  170. const filtroClave = textoFiltro.match(/\((.*?)\)/)?.[1];
  171. // console.log(clave, filtroClave);
  172. return clave.includes(filtroClave);
  173. }
  174. else {
  175. const nombre = registro.profesor_nombre.toLowerCase();
  176. return nombre.includes(textoFiltro);
  177. }
  178. case 'facultad_id':
  179. return registro.facultad_id === store.filters[filtro];
  180. case 'estados':
  181. if (store.filters[filtro].length === 0)
  182. return true;
  183. return store.filters[filtro].includes(registro.estado_supervisor_id);
  184. case 'bloque_horario':
  185. const bloque = store.bloques_horario.data.find((bloque) => bloque.id === store.filters[filtro]);
  186. return registro.horario_hora <= bloque.hora_fin && registro.horario_fin >= bloque.hora_inicio;
  187. default:
  188. return true;
  189. }
  190. });
  191. });
  192. },
  193. async descargar() {
  194. store.current.modal_state = 'Generando reporte en Excel...';
  195. $('div.modal#cargando').modal('show');
  196. this.loading = true;
  197. if (this.relevant.length === 0)
  198. return;
  199. try {
  200. const res = await fetch('export/supervisor_excel.php', {
  201. method: 'POST',
  202. headers: {
  203. 'Content-Type': 'application/json'
  204. },
  205. body: JSON.stringify(this.relevant)
  206. });
  207. const blob = await res.blob();
  208. window.saveAs(blob, `auditoria_${new Date().toISOString().slice(0, 10)}.xlsx`);
  209. }
  210. catch (error) {
  211. if (error.response && error.response.status === 413) {
  212. alert('Your request is too large! Please reduce the data size and try again.');
  213. }
  214. else {
  215. alert('An error occurred: ' + error.message);
  216. }
  217. }
  218. finally {
  219. $('#cargando').modal('hide');
  220. this.loading = false;
  221. }
  222. },
  223. loading: false,
  224. get pages() {
  225. return Math.ceil(this.relevant.length / store.current.perPage);
  226. }
  227. },
  228. get profesores() {
  229. return this.registros.data
  230. .map((registro) => ({
  231. profesor_id: registro.profesor_id,
  232. profesor_nombre: registro.profesor_nombre,
  233. profesor_correo: registro.profesor_correo,
  234. profesor_clave: registro.profesor_clave,
  235. profesor_grado: registro.profesor_grado,
  236. }))
  237. .reduce((acc, current) => {
  238. if (!acc.some(item => item.profesor_id === current.profesor_id)) {
  239. acc.push(current);
  240. }
  241. return acc;
  242. }, [])
  243. .sort((a, b) => a.profesor_nombre.localeCompare(b.profesor_nombre));
  244. },
  245. async mounted() {
  246. $('div.modal#cargando').modal('show');
  247. await this.registros.fetch();
  248. await store.facultades.fetch();
  249. await store.estados.fetch();
  250. await store.bloques_horario.fetch();
  251. await store.filters.switchFechas();
  252. $('div.modal#cargando').modal('hide');
  253. }
  254. }).mount('#app');