auditoría.js 9.5 KB

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