|
@@ -1,135 +1,135 @@
|
|
|
-const compareHours = (hora1, hora2) => {
|
|
|
- const [h1, m1] = hora1.split(":").map(Number);
|
|
|
- const [h2, m2] = hora2.split(":").map(Number);
|
|
|
- if (h1 !== h2) {
|
|
|
- return h1 > h2 ? 1 : -1;
|
|
|
- }
|
|
|
- if (m1 !== m2) {
|
|
|
- return m1 > m2 ? 1 : -1;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-};
|
|
|
-let horarios = [];
|
|
|
-const table = document.querySelector("table");
|
|
|
-if (!(table instanceof HTMLTableElement)) {
|
|
|
- triggerMessage("No se ha encontrado la tabla", "Error", "error");
|
|
|
- throw new Error("No se ha encontrado la tabla");
|
|
|
-}
|
|
|
-[...Array(16).keys()].map(x => x + 7).forEach(hora => {
|
|
|
- // add 7 rows for each hour
|
|
|
- [0, 15, 30, 45].map((minute) => `${minute}`.padStart(2, '0')).forEach((minute) => {
|
|
|
- const tr = document.createElement("tr");
|
|
|
- tr.id = `hora-${hora}:${minute}`;
|
|
|
- tr.classList.add(hora > 13 ? "tarde" : "mañana");
|
|
|
- if (minute == "00") {
|
|
|
- const th = document.createElement("th");
|
|
|
- th.classList.add("text-center");
|
|
|
- th.scope = "row";
|
|
|
- th.rowSpan = 4;
|
|
|
- th.innerText = `${hora}:00`;
|
|
|
- th.style.verticalAlign = "middle";
|
|
|
- tr.appendChild(th);
|
|
|
- }
|
|
|
- ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"].forEach(día => {
|
|
|
- const td = document.createElement("td");
|
|
|
- td.id = `hora-${hora}:${minute}-${día}`;
|
|
|
- tr.appendChild(td);
|
|
|
- });
|
|
|
- const tbody = document.querySelector("tbody#horario");
|
|
|
- if (!(tbody instanceof HTMLTableSectionElement)) {
|
|
|
- throw new Error("No se ha encontrado el tbody");
|
|
|
- }
|
|
|
- tbody.appendChild(tr);
|
|
|
- });
|
|
|
-});
|
|
|
-const empty_table = table.cloneNode(true);
|
|
|
-document.querySelectorAll('.hidden').forEach((element) => {
|
|
|
- element.style.display = "none";
|
|
|
-});
|
|
|
-// hide the table
|
|
|
-table.style.display = "none";
|
|
|
-function moveHorario(id, día, hora) {
|
|
|
- const formData = new FormData();
|
|
|
- formData.append("id", id);
|
|
|
- formData.append("hora", hora);
|
|
|
- formData.append("día", día);
|
|
|
- fetch("action/action_horario_update.php", {
|
|
|
- method: "POST",
|
|
|
- body: formData
|
|
|
- }).then(res => res.json()).then(response => {
|
|
|
- if (response.status == "success") {
|
|
|
- triggerMessage("Horario movido", "Éxito", "success");
|
|
|
- }
|
|
|
- else {
|
|
|
- triggerMessage(response.message, "Error");
|
|
|
- }
|
|
|
- }).then(() => {
|
|
|
- renderHorario();
|
|
|
- }).catch(err => {
|
|
|
- triggerMessage(err, "Error");
|
|
|
- });
|
|
|
-}
|
|
|
-function renderHorario() {
|
|
|
- if (horarios.length == 0) {
|
|
|
- triggerMessage("Este profesor hay horarios para mostrar", "Error", "info");
|
|
|
- table.style.display = "none";
|
|
|
- document.querySelectorAll('.hidden').forEach((element) => element.style.display = "none");
|
|
|
- return;
|
|
|
- }
|
|
|
- // show the table
|
|
|
- table.style.display = "table";
|
|
|
- document.querySelectorAll('.hidden').forEach((element) => element.style.display = "block");
|
|
|
- // clear the table
|
|
|
- table.innerHTML = empty_table.outerHTML;
|
|
|
- function conflicts(horario1, horario2) {
|
|
|
- const { hora: hora_inicio1, hora_final: hora_final1, dia: dia1 } = horario1;
|
|
|
- const { hora: hora_inicio2, hora_final: hora_final2, dia: dia2 } = horario2;
|
|
|
- if (dia1 !== dia2) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- const compareInicios = compareHours(hora_inicio1, hora_inicio2);
|
|
|
- const compareFinales = compareHours(hora_final1, hora_final2);
|
|
|
- if (compareInicios >= 0 && compareInicios <= compareFinales ||
|
|
|
- compareFinales >= 0 && compareFinales <= -compareInicios) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- // remove the next 5 cells
|
|
|
- function removeNextCells(horas, minutos, dia, cells = 5) {
|
|
|
- for (let i = 1; i <= cells; i++) {
|
|
|
- const minute = minutos + i * 15;
|
|
|
- const nextMinute = (minute % 60).toString().padStart(2, "0");
|
|
|
- const nextHour = horas + Math.floor(minute / 60);
|
|
|
- const cellId = `hora-${nextHour}:${nextMinute}-${dia}`;
|
|
|
- const cellElement = document.getElementById(cellId);
|
|
|
- if (cellElement) {
|
|
|
- cellElement.remove();
|
|
|
- }
|
|
|
- else {
|
|
|
- console.log(`No se ha encontrado la celda ${cellId}`);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- function newBlock(horario, edit = false) {
|
|
|
- function move(horario, cells = 5) {
|
|
|
- const [horas, minutos] = horario.hora.split(":").map(Number);
|
|
|
- const cell = document.getElementById(`hora-${horas}:${minutos.toString().padStart(2, "0")}-${horario.dia}`);
|
|
|
- const { top, left } = cell.getBoundingClientRect();
|
|
|
- const block = document.getElementById(`block-${horario.id}`);
|
|
|
- block.style.top = `${top}px`;
|
|
|
- block.style.left = `${left}px`;
|
|
|
- removeNextCells(horas, minutos, horario.dia, cells);
|
|
|
- }
|
|
|
- const [horas, minutos] = horario.hora.split(":").map(x => parseInt(x));
|
|
|
- const hora = `${horas}:${minutos.toString().padStart(2, "0")}`;
|
|
|
- horario.hora = hora;
|
|
|
- const cell = document.getElementById(`hora-${horario.hora}-${horario.dia}`);
|
|
|
- if (!cell)
|
|
|
- return;
|
|
|
- cell.dataset.ids = `${horario.id}`;
|
|
|
- const float_menu = edit ?
|
|
|
+const compareHours = (hora1, hora2) => {
|
|
|
+ const [h1, m1] = hora1.split(":").map(Number);
|
|
|
+ const [h2, m2] = hora2.split(":").map(Number);
|
|
|
+ if (h1 !== h2) {
|
|
|
+ return h1 > h2 ? 1 : -1;
|
|
|
+ }
|
|
|
+ if (m1 !== m2) {
|
|
|
+ return m1 > m2 ? 1 : -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+};
|
|
|
+let horarios = [];
|
|
|
+const table = document.querySelector("table");
|
|
|
+if (!(table instanceof HTMLTableElement)) {
|
|
|
+ triggerMessage("No se ha encontrado la tabla", "Error", "error");
|
|
|
+ throw new Error("No se ha encontrado la tabla");
|
|
|
+}
|
|
|
+[...Array(16).keys()].map(x => x + 7).forEach(hora => {
|
|
|
+ // add 7 rows for each hour
|
|
|
+ [0, 15, 30, 45].map((minute) => `${minute}`.padStart(2, '0')).forEach((minute) => {
|
|
|
+ const tr = document.createElement("tr");
|
|
|
+ tr.id = `hora-${hora}:${minute}`;
|
|
|
+ tr.classList.add(hora > 13 ? "tarde" : "mañana");
|
|
|
+ if (minute == "00") {
|
|
|
+ const th = document.createElement("th");
|
|
|
+ th.classList.add("text-center");
|
|
|
+ th.scope = "row";
|
|
|
+ th.rowSpan = 4;
|
|
|
+ th.innerText = `${hora}:00`;
|
|
|
+ th.style.verticalAlign = "middle";
|
|
|
+ tr.appendChild(th);
|
|
|
+ }
|
|
|
+ ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"].forEach(día => {
|
|
|
+ const td = document.createElement("td");
|
|
|
+ td.id = `hora-${hora}:${minute}-${día}`;
|
|
|
+ tr.appendChild(td);
|
|
|
+ });
|
|
|
+ const tbody = document.querySelector("tbody#horario");
|
|
|
+ if (!(tbody instanceof HTMLTableSectionElement)) {
|
|
|
+ throw new Error("No se ha encontrado el tbody");
|
|
|
+ }
|
|
|
+ tbody.appendChild(tr);
|
|
|
+ });
|
|
|
+});
|
|
|
+const empty_table = table.cloneNode(true);
|
|
|
+document.querySelectorAll('.hidden').forEach((element) => {
|
|
|
+ element.style.display = "none";
|
|
|
+});
|
|
|
+// hide the table
|
|
|
+table.style.display = "none";
|
|
|
+function moveHorario(id, día, hora) {
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append("id", id);
|
|
|
+ formData.append("hora", hora);
|
|
|
+ formData.append("día", día);
|
|
|
+ fetch("action/action_horario_update.php", {
|
|
|
+ method: "POST",
|
|
|
+ body: formData
|
|
|
+ }).then(res => res.json()).then(response => {
|
|
|
+ if (response.status == "success") {
|
|
|
+ triggerMessage("Horario movido", "Éxito", "success");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ triggerMessage(response.message, "Error");
|
|
|
+ }
|
|
|
+ }).then(() => {
|
|
|
+ renderHorario();
|
|
|
+ }).catch(err => {
|
|
|
+ triggerMessage(err, "Error");
|
|
|
+ });
|
|
|
+}
|
|
|
+function renderHorario() {
|
|
|
+ if (horarios.length == 0) {
|
|
|
+ triggerMessage("Este profesor hay horarios para mostrar", "Error", "info");
|
|
|
+ table.style.display = "none";
|
|
|
+ document.querySelectorAll('.hidden').forEach((element) => element.style.display = "none");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // show the table
|
|
|
+ table.style.display = "table";
|
|
|
+ document.querySelectorAll('.hidden').forEach((element) => element.style.display = "block");
|
|
|
+ // clear the table
|
|
|
+ table.innerHTML = empty_table.outerHTML;
|
|
|
+ function conflicts(horario1, horario2) {
|
|
|
+ const { hora: hora_inicio1, hora_final: hora_final1, dia: dia1 } = horario1;
|
|
|
+ const { hora: hora_inicio2, hora_final: hora_final2, dia: dia2 } = horario2;
|
|
|
+ if (dia1 !== dia2) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const compareInicios = compareHours(hora_inicio1, hora_inicio2);
|
|
|
+ const compareFinales = compareHours(hora_final1, hora_final2);
|
|
|
+ if (compareInicios >= 0 && compareInicios <= compareFinales ||
|
|
|
+ compareFinales >= 0 && compareFinales <= -compareInicios) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // remove the next 5 cells
|
|
|
+ function removeNextCells(horas, minutos, dia, cells = 5) {
|
|
|
+ for (let i = 1; i <= cells; i++) {
|
|
|
+ const minute = minutos + i * 15;
|
|
|
+ const nextMinute = (minute % 60).toString().padStart(2, "0");
|
|
|
+ const nextHour = horas + Math.floor(minute / 60);
|
|
|
+ const cellId = `hora-${nextHour}:${nextMinute}-${dia}`;
|
|
|
+ const cellElement = document.getElementById(cellId);
|
|
|
+ if (cellElement) {
|
|
|
+ cellElement.remove();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.log(`No se ha encontrado la celda ${cellId}`);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function newBlock(horario, edit = false) {
|
|
|
+ function move(horario, cells = 5) {
|
|
|
+ const [horas, minutos] = horario.hora.split(":").map(Number);
|
|
|
+ const cell = document.getElementById(`hora-${horas}:${minutos.toString().padStart(2, "0")}-${horario.dia}`);
|
|
|
+ const { top, left } = cell.getBoundingClientRect();
|
|
|
+ const block = document.getElementById(`block-${horario.id}`);
|
|
|
+ block.style.top = `${top}px`;
|
|
|
+ block.style.left = `${left}px`;
|
|
|
+ removeNextCells(horas, minutos, horario.dia, cells);
|
|
|
+ }
|
|
|
+ const [horas, minutos] = horario.hora.split(":").map(x => parseInt(x));
|
|
|
+ const hora = `${horas}:${minutos.toString().padStart(2, "0")}`;
|
|
|
+ horario.hora = hora;
|
|
|
+ const cell = document.getElementById(`hora-${horario.hora}-${horario.dia}`);
|
|
|
+ if (!cell)
|
|
|
+ return;
|
|
|
+ cell.dataset.ids = `${horario.id}`;
|
|
|
+ const float_menu = edit ?
|
|
|
`<div class="menu-flotante p-2" style="opacity: .7;">
|
|
|
<a class="mx-2" href="#" data-toggle="modal" data-target="#modal-editar">
|
|
|
<i class="ing-editar ing"></i>
|
|
@@ -137,9 +137,9 @@ function renderHorario() {
|
|
|
<a class="mx-2" href="#" data-toggle="modal" data-target="#modal-borrar">
|
|
|
<i class="ing-basura ing"></i>
|
|
|
</a>
|
|
|
- </div>`
|
|
|
- : '';
|
|
|
- cell.innerHTML =
|
|
|
+ </div>`
|
|
|
+ : '';
|
|
|
+ cell.innerHTML =
|
|
|
`<div style="overflow-y: auto; overflow-x: hidden; height: 100%;" id="block-${horario.id}" class="position-absolute w-100 h-100">
|
|
|
<small class="text-gray">${horario.hora}</small>
|
|
|
<b class="title">${horario.materia}</b> <br>
|
|
@@ -148,27 +148,27 @@ function renderHorario() {
|
|
|
${horario.profesores.map((profesor) => ` <span class="ing ing-formacion mx-1"></span>${profesor.grado ?? ''} ${profesor.profesor}`).join("<br>")}
|
|
|
</small>
|
|
|
</div>
|
|
|
- ${float_menu}`;
|
|
|
- cell.classList.add("bloque-clase", "position-relative");
|
|
|
- cell.rowSpan = horario.bloques;
|
|
|
- // draggable
|
|
|
- cell.draggable = write;
|
|
|
- if (horario.bloques > 0) {
|
|
|
- removeNextCells(horas, minutos, horario.dia, horario.bloques - 1);
|
|
|
- }
|
|
|
- }
|
|
|
- function newConflictBlock(horarios, edit = false) {
|
|
|
- const first_horario = horarios[0];
|
|
|
- const [horas, minutos] = first_horario.hora.split(":").map(x => parseInt(x));
|
|
|
- const hora = `${horas}:${minutos.toString().padStart(2, "0")}`;
|
|
|
- const ids = horarios.map(horario => horario.id);
|
|
|
- const cell = document.getElementById(`hora-${hora}-${first_horario.dia}`);
|
|
|
- if (cell == null) {
|
|
|
- console.error(`Error: No se encontró la celda: hora-${hora}-${first_horario.dia}`);
|
|
|
- return;
|
|
|
- }
|
|
|
- cell.dataset.ids = ids.join(",");
|
|
|
- // replace the content of the cell
|
|
|
+ ${float_menu}`;
|
|
|
+ cell.classList.add("bloque-clase", "position-relative");
|
|
|
+ cell.rowSpan = horario.bloques;
|
|
|
+ // draggable
|
|
|
+ cell.draggable = write;
|
|
|
+ if (horario.bloques > 0) {
|
|
|
+ removeNextCells(horas, minutos, horario.dia, horario.bloques - 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function newConflictBlock(horarios, edit = false) {
|
|
|
+ const first_horario = horarios[0];
|
|
|
+ const [horas, minutos] = first_horario.hora.split(":").map(x => parseInt(x));
|
|
|
+ const hora = `${horas}:${minutos.toString().padStart(2, "0")}`;
|
|
|
+ const ids = horarios.map(horario => horario.id);
|
|
|
+ const cell = document.getElementById(`hora-${hora}-${first_horario.dia}`);
|
|
|
+ if (cell == null) {
|
|
|
+ console.error(`Error: No se encontró la celda: hora-${hora}-${first_horario.dia}`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ cell.dataset.ids = ids.join(",");
|
|
|
+ // replace the content of the cell
|
|
|
cell.innerHTML = `
|
|
|
<small class='text-danger'>
|
|
|
${hora}
|
|
@@ -183,17 +183,17 @@ function renderHorario() {
|
|
|
<i class="text-danger">Ver horarios …</i>
|
|
|
</div>
|
|
|
</div>
|
|
|
- `;
|
|
|
- // Add classes and attributes
|
|
|
- cell.classList.add("conflict", "bloque-clase");
|
|
|
- cell.setAttribute("role", "button");
|
|
|
- // Add event listener for the cell
|
|
|
- cell.addEventListener("click", () => {
|
|
|
- $("#modal-choose").modal("show");
|
|
|
- const ids = cell.getAttribute("data-ids").split(",").map(x => parseInt(x));
|
|
|
- const tbody = document.querySelector("#modal-choose tbody");
|
|
|
- tbody.innerHTML = "";
|
|
|
- horarios.filter(horario => ids.includes(horario.id)).sort((a, b) => compareHours(a.hora, b.hora)).forEach(horario => {
|
|
|
+ `;
|
|
|
+ // Add classes and attributes
|
|
|
+ cell.classList.add("conflict", "bloque-clase");
|
|
|
+ cell.setAttribute("role", "button");
|
|
|
+ // Add event listener for the cell
|
|
|
+ cell.addEventListener("click", () => {
|
|
|
+ $("#modal-choose").modal("show");
|
|
|
+ const ids = cell.getAttribute("data-ids").split(",").map(x => parseInt(x));
|
|
|
+ const tbody = document.querySelector("#modal-choose tbody");
|
|
|
+ tbody.innerHTML = "";
|
|
|
+ horarios.filter(horario => ids.includes(horario.id)).sort((a, b) => compareHours(a.hora, b.hora)).forEach(horario => {
|
|
|
tbody.innerHTML += `
|
|
|
<tr data-ids="${horario.id}">
|
|
|
<td><small>${horario.hora.slice(0, -3)}-${horario.hora_final.slice(0, -3)}</small></td>
|
|
@@ -214,201 +214,201 @@ function renderHorario() {
|
|
|
</button>
|
|
|
</td>
|
|
|
` : ""}
|
|
|
- </tr>`;
|
|
|
- });
|
|
|
- document.querySelectorAll(".dismiss-editar").forEach(btn => {
|
|
|
- btn.addEventListener("click", () => $("#modal-choose").modal("hide"));
|
|
|
- });
|
|
|
- });
|
|
|
- function getDuration(hora_i, hora_f) {
|
|
|
- const [horas_i, minutos_i] = hora_i.split(":").map(x => parseInt(x));
|
|
|
- const [horas_f, minutos_f] = hora_f.split(":").map(x => parseInt(x));
|
|
|
- const date_i = new Date(0, 0, 0, horas_i, minutos_i);
|
|
|
- const date_f = new Date(0, 0, 0, horas_f, minutos_f);
|
|
|
- const diffInMilliseconds = date_f.getTime() - date_i.getTime();
|
|
|
- const diffInMinutes = diffInMilliseconds / (1000 * 60);
|
|
|
- const diffIn15MinuteIntervals = diffInMinutes / 15;
|
|
|
- return Math.floor(diffIn15MinuteIntervals);
|
|
|
- }
|
|
|
- const maxHoraFinal = horarios.reduce((max, horario) => {
|
|
|
- const [horas, minutos] = horario.hora_final.split(":").map(x => parseInt(x));
|
|
|
- const date = new Date(0, 0, 0, horas, minutos);
|
|
|
- return date > max ? date : max;
|
|
|
- }, new Date(0, 0, 0, 0, 0));
|
|
|
- const horaFinalMax = new Date(0, 0, 0, maxHoraFinal.getHours(), maxHoraFinal.getMinutes());
|
|
|
- const blocks = getDuration(first_horario.hora, `${horaFinalMax.getHours()}:${horaFinalMax.getMinutes()}`);
|
|
|
- cell.setAttribute("rowSpan", blocks.toString());
|
|
|
- removeNextCells(horas, minutos, first_horario.dia, blocks - 1);
|
|
|
- }
|
|
|
- const conflictBlocks = horarios.filter((horario, index, arrayHorario) => arrayHorario.filter((_, i) => i != index).some(horario2 => conflicts(horario, horario2)))
|
|
|
- .sort((a, b) => compareHours(a.hora, b.hora));
|
|
|
- const classes = horarios.filter(horario => !conflictBlocks.includes(horario));
|
|
|
- const conflictBlocksPacked = []; // array of sets
|
|
|
- conflictBlocks.forEach(horario => {
|
|
|
- const setIndex = conflictBlocksPacked.findIndex(set => set.some(horario2 => conflicts(horario, horario2)));
|
|
|
- if (setIndex === -1) {
|
|
|
- conflictBlocksPacked.push([horario]);
|
|
|
- }
|
|
|
- else {
|
|
|
- conflictBlocksPacked[setIndex].push(horario);
|
|
|
- }
|
|
|
- });
|
|
|
- classes.forEach(horario => newBlock(horario, write));
|
|
|
- conflictBlocksPacked.forEach(horarios => newConflictBlock(horarios, write));
|
|
|
- // remove the elements that are not in the limits
|
|
|
- let max_hour = Math.max(...horarios.map(horario => {
|
|
|
- const lastMoment = moment(horario.hora, "HH:mm").add(horario.bloques * 15, "minutes");
|
|
|
- const lastHour = moment(`${lastMoment.hours()}:00`, "HH:mm");
|
|
|
- const hourInt = parseInt(lastMoment.format("HH"));
|
|
|
- return lastMoment.isSame(lastHour) ? hourInt - 1 : hourInt;
|
|
|
- }));
|
|
|
- let min_hour = Math.min(...horarios.map(horario => parseInt(horario.hora.split(":")[0])));
|
|
|
- document.querySelectorAll("tbody#horario tr").forEach(hora => {
|
|
|
- const hora_id = parseInt(hora.id.split("-")[1].split(":")[0]);
|
|
|
- (hora_id < min_hour || hora_id > max_hour) ? hora.remove() : null;
|
|
|
- });
|
|
|
- // if there is no sábado, remove the column
|
|
|
- if (!horarios.some(horario => horario.dia == "sábado")) {
|
|
|
- document.querySelectorAll("tbody#horario td").forEach(td => {
|
|
|
- if (td.id.split("-")[2] == "sábado") {
|
|
|
- td.remove();
|
|
|
- }
|
|
|
- });
|
|
|
- // remove the header (the last)
|
|
|
- document.querySelector("#headers").lastElementChild.remove();
|
|
|
- }
|
|
|
- // adjust width
|
|
|
- const ths = document.querySelectorAll("tr#headers th");
|
|
|
- ths.forEach((th, key) => th.style.width = (key == 0) ? "5%" : `${95 / (ths.length - 1)}%`);
|
|
|
- // search item animation
|
|
|
- const menúFlontantes = document.querySelectorAll(".menu-flotante");
|
|
|
- menúFlontantes.forEach((element) => {
|
|
|
- element.classList.add("d-none");
|
|
|
- element.parentElement.addEventListener("mouseover", () => element.classList.remove("d-none"));
|
|
|
- element.parentElement.addEventListener("mouseout", (e) => element.classList.add("d-none"));
|
|
|
- });
|
|
|
- // droppables
|
|
|
- // forall the .bloque-elements add the event listeners for drag and drop
|
|
|
- document.querySelectorAll(".bloque-clase").forEach(element => {
|
|
|
- function dragStart() {
|
|
|
- this.classList.add("dragging");
|
|
|
- }
|
|
|
- function dragEnd() {
|
|
|
- this.classList.remove("dragging");
|
|
|
- }
|
|
|
- element.addEventListener("dragstart", dragStart);
|
|
|
- element.addEventListener("dragend", dragEnd);
|
|
|
- });
|
|
|
- // forall the cells that are not .bloque-clase add the event listeners for drag and drop
|
|
|
- document.querySelectorAll("td:not(.bloque-clase)").forEach(element => {
|
|
|
- function dragOver(e) {
|
|
|
- e.preventDefault();
|
|
|
- this.classList.add("dragging-over");
|
|
|
- }
|
|
|
- function dragLeave() {
|
|
|
- this.classList.remove("dragging-over");
|
|
|
- }
|
|
|
- function drop() {
|
|
|
- this.classList.remove("dragging-over");
|
|
|
- const dragging = document.querySelector(".dragging");
|
|
|
- const id = dragging.getAttribute("data-ids");
|
|
|
- const hora = this.id.split("-")[1];
|
|
|
- const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"];
|
|
|
- let día = this.id.split("-")[2];
|
|
|
- día = días.indexOf(día) + 1;
|
|
|
- // rowspan
|
|
|
- const bloques = parseInt(dragging.getAttribute("rowspan"));
|
|
|
- const horaMoment = moment(hora, "HH:mm");
|
|
|
- const horaFin = horaMoment.add(bloques * 15, "minutes");
|
|
|
- const limit = moment('22:00', 'HH:mm');
|
|
|
- if (horaFin.isAfter(limit)) {
|
|
|
- triggerMessage("No se puede mover el bloque a esa hora", "Error");
|
|
|
- // scroll to the top
|
|
|
- window.scrollTo(0, 0);
|
|
|
- return;
|
|
|
- }
|
|
|
- // get the horario
|
|
|
- // remove the horario
|
|
|
- const bloque = document.querySelector(`.bloque-clase[data-ids="${id}"]`);
|
|
|
- // remove all children
|
|
|
- while (bloque.firstChild) {
|
|
|
- bloque.removeChild(bloque.firstChild);
|
|
|
- }
|
|
|
- // prepend a loading child
|
|
|
+ </tr>`;
|
|
|
+ });
|
|
|
+ document.querySelectorAll(".dismiss-editar").forEach(btn => {
|
|
|
+ btn.addEventListener("click", () => $("#modal-choose").modal("hide"));
|
|
|
+ });
|
|
|
+ });
|
|
|
+ function getDuration(hora_i, hora_f) {
|
|
|
+ const [horas_i, minutos_i] = hora_i.split(":").map(x => parseInt(x));
|
|
|
+ const [horas_f, minutos_f] = hora_f.split(":").map(x => parseInt(x));
|
|
|
+ const date_i = new Date(0, 0, 0, horas_i, minutos_i);
|
|
|
+ const date_f = new Date(0, 0, 0, horas_f, minutos_f);
|
|
|
+ const diffInMilliseconds = date_f.getTime() - date_i.getTime();
|
|
|
+ const diffInMinutes = diffInMilliseconds / (1000 * 60);
|
|
|
+ const diffIn15MinuteIntervals = diffInMinutes / 15;
|
|
|
+ return Math.floor(diffIn15MinuteIntervals);
|
|
|
+ }
|
|
|
+ const maxHoraFinal = horarios.reduce((max, horario) => {
|
|
|
+ const [horas, minutos] = horario.hora_final.split(":").map(x => parseInt(x));
|
|
|
+ const date = new Date(0, 0, 0, horas, minutos);
|
|
|
+ return date > max ? date : max;
|
|
|
+ }, new Date(0, 0, 0, 0, 0));
|
|
|
+ const horaFinalMax = new Date(0, 0, 0, maxHoraFinal.getHours(), maxHoraFinal.getMinutes());
|
|
|
+ const blocks = getDuration(first_horario.hora, `${horaFinalMax.getHours()}:${horaFinalMax.getMinutes()}`);
|
|
|
+ cell.setAttribute("rowSpan", blocks.toString());
|
|
|
+ removeNextCells(horas, minutos, first_horario.dia, blocks - 1);
|
|
|
+ }
|
|
|
+ const conflictBlocks = horarios.filter((horario, index, arrayHorario) => arrayHorario.filter((_, i) => i != index).some(horario2 => conflicts(horario, horario2)))
|
|
|
+ .sort((a, b) => compareHours(a.hora, b.hora));
|
|
|
+ const classes = horarios.filter(horario => !conflictBlocks.includes(horario));
|
|
|
+ const conflictBlocksPacked = []; // array of sets
|
|
|
+ conflictBlocks.forEach(horario => {
|
|
|
+ const setIndex = conflictBlocksPacked.findIndex(set => set.some(horario2 => conflicts(horario, horario2)));
|
|
|
+ if (setIndex === -1) {
|
|
|
+ conflictBlocksPacked.push([horario]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ conflictBlocksPacked[setIndex].push(horario);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ classes.forEach(horario => newBlock(horario, write));
|
|
|
+ conflictBlocksPacked.forEach(horarios => newConflictBlock(horarios, write));
|
|
|
+ // remove the elements that are not in the limits
|
|
|
+ let max_hour = Math.max(...horarios.map(horario => {
|
|
|
+ const lastMoment = moment(horario.hora, "HH:mm").add(horario.bloques * 15, "minutes");
|
|
|
+ const lastHour = moment(`${lastMoment.hours()}:00`, "HH:mm");
|
|
|
+ const hourInt = parseInt(lastMoment.format("HH"));
|
|
|
+ return lastMoment.isSame(lastHour) ? hourInt - 1 : hourInt;
|
|
|
+ }));
|
|
|
+ let min_hour = Math.min(...horarios.map(horario => parseInt(horario.hora.split(":")[0])));
|
|
|
+ document.querySelectorAll("tbody#horario tr").forEach(hora => {
|
|
|
+ const hora_id = parseInt(hora.id.split("-")[1].split(":")[0]);
|
|
|
+ (hora_id < min_hour || hora_id > max_hour) ? hora.remove() : null;
|
|
|
+ });
|
|
|
+ // if there is no sábado, remove the column
|
|
|
+ if (!horarios.some(horario => horario.dia == "sábado")) {
|
|
|
+ document.querySelectorAll("tbody#horario td").forEach(td => {
|
|
|
+ if (td.id.split("-")[2] == "sábado") {
|
|
|
+ td.remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // remove the header (the last)
|
|
|
+ document.querySelector("#headers").lastElementChild.remove();
|
|
|
+ }
|
|
|
+ // adjust width
|
|
|
+ const ths = document.querySelectorAll("tr#headers th");
|
|
|
+ ths.forEach((th, key) => th.style.width = (key == 0) ? "5%" : `${95 / (ths.length - 1)}%`);
|
|
|
+ // search item animation
|
|
|
+ const menúFlontantes = document.querySelectorAll(".menu-flotante");
|
|
|
+ menúFlontantes.forEach((element) => {
|
|
|
+ element.classList.add("d-none");
|
|
|
+ element.parentElement.addEventListener("mouseover", () => element.classList.remove("d-none"));
|
|
|
+ element.parentElement.addEventListener("mouseout", (e) => element.classList.add("d-none"));
|
|
|
+ });
|
|
|
+ // droppables
|
|
|
+ // forall the .bloque-elements add the event listeners for drag and drop
|
|
|
+ document.querySelectorAll(".bloque-clase").forEach(element => {
|
|
|
+ function dragStart() {
|
|
|
+ this.classList.add("dragging");
|
|
|
+ }
|
|
|
+ function dragEnd() {
|
|
|
+ this.classList.remove("dragging");
|
|
|
+ }
|
|
|
+ element.addEventListener("dragstart", dragStart);
|
|
|
+ element.addEventListener("dragend", dragEnd);
|
|
|
+ });
|
|
|
+ // forall the cells that are not .bloque-clase add the event listeners for drag and drop
|
|
|
+ document.querySelectorAll("td:not(.bloque-clase)").forEach(element => {
|
|
|
+ function dragOver(e) {
|
|
|
+ e.preventDefault();
|
|
|
+ this.classList.add("dragging-over");
|
|
|
+ }
|
|
|
+ function dragLeave() {
|
|
|
+ this.classList.remove("dragging-over");
|
|
|
+ }
|
|
|
+ function drop() {
|
|
|
+ this.classList.remove("dragging-over");
|
|
|
+ const dragging = document.querySelector(".dragging");
|
|
|
+ const id = dragging.getAttribute("data-ids");
|
|
|
+ const hora = this.id.split("-")[1];
|
|
|
+ const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"];
|
|
|
+ let día = this.id.split("-")[2];
|
|
|
+ día = días.indexOf(día) + 1;
|
|
|
+ // rowspan
|
|
|
+ const bloques = parseInt(dragging.getAttribute("rowspan"));
|
|
|
+ const horaMoment = moment(hora, "HH:mm");
|
|
|
+ const horaFin = horaMoment.add(bloques * 15, "minutes");
|
|
|
+ const limit = moment('22:00', 'HH:mm');
|
|
|
+ if (horaFin.isAfter(limit)) {
|
|
|
+ triggerMessage("No se puede mover el bloque a esa hora", "Error");
|
|
|
+ // scroll to the top
|
|
|
+ window.scrollTo(0, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // get the horario
|
|
|
+ // remove the horario
|
|
|
+ const bloque = document.querySelector(`.bloque-clase[data-ids="${id}"]`);
|
|
|
+ // remove all children
|
|
|
+ while (bloque.firstChild) {
|
|
|
+ bloque.removeChild(bloque.firstChild);
|
|
|
+ }
|
|
|
+ // prepend a loading child
|
|
|
const loading = `<div class="spinner-border" role="status" style="width: 3rem; height: 3rem;">
|
|
|
<span class="sr-only">Loading...</span>
|
|
|
- </div>`;
|
|
|
- bloque.insertAdjacentHTML("afterbegin", loading);
|
|
|
- // add style vertical-align: middle
|
|
|
- bloque.style.verticalAlign = "middle";
|
|
|
- bloque.classList.add("text-center");
|
|
|
- // remove draggable
|
|
|
- bloque.removeAttribute("draggable");
|
|
|
- moveHorario(id, día, hora);
|
|
|
- }
|
|
|
- element.addEventListener("dragover", dragOver);
|
|
|
- element.addEventListener("dragleave", dragLeave);
|
|
|
- element.addEventListener("drop", drop);
|
|
|
- });
|
|
|
-}
|
|
|
-const form = document.getElementById('form');
|
|
|
-if (!(form instanceof HTMLFormElement)) {
|
|
|
- triggerMessage('No se ha encontrado el formulario', 'Error', 'danger');
|
|
|
- throw new Error("No se ha encontrado el formulario");
|
|
|
-}
|
|
|
-form.querySelector('#clave_profesor').addEventListener('input', function (e) {
|
|
|
- const input = form.querySelector('#clave_profesor');
|
|
|
- const option = form.querySelector(`option[value="${input.value}"]`);
|
|
|
- if (input.value == "") {
|
|
|
- input.classList.remove("is-invalid", "is-valid");
|
|
|
- return;
|
|
|
- }
|
|
|
- if (!option) {
|
|
|
- input.classList.remove("is-valid");
|
|
|
- input.classList.add("is-invalid");
|
|
|
- }
|
|
|
- else {
|
|
|
- const profesor_id = form.querySelector('#profesor_id');
|
|
|
- profesor_id.value = option.dataset.id;
|
|
|
- input.classList.remove("is-invalid");
|
|
|
- input.classList.add("is-valid");
|
|
|
- }
|
|
|
-});
|
|
|
-form.addEventListener('submit', async function (e) {
|
|
|
- e.preventDefault();
|
|
|
- const input = form.querySelector('#clave_profesor');
|
|
|
- if (input.classList.contains("is-invalid")) {
|
|
|
- triggerMessage('El profesor no se encuentra registrado', 'Error', 'danger');
|
|
|
- return;
|
|
|
- }
|
|
|
- const formData = new FormData(form);
|
|
|
- try {
|
|
|
- const buttons = document.querySelectorAll("button");
|
|
|
- buttons.forEach(button => {
|
|
|
- button.disabled = true;
|
|
|
- button.classList.add("disabled");
|
|
|
- });
|
|
|
- const response = await fetch('action/action_horario_profesor.php', {
|
|
|
- method: 'POST',
|
|
|
- body: formData,
|
|
|
- });
|
|
|
- const data = await response.json();
|
|
|
- buttons.forEach(button => {
|
|
|
- button.disabled = false;
|
|
|
- button.classList.remove("disabled");
|
|
|
- });
|
|
|
- if (data.status == 'success') {
|
|
|
- horarios = data.data;
|
|
|
- renderHorario();
|
|
|
- }
|
|
|
- else {
|
|
|
- triggerMessage(data.message, 'Error en la consulta', 'warning');
|
|
|
- }
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- triggerMessage('Fallo al consutar los datos ', 'Error', 'danger');
|
|
|
- console.log(error);
|
|
|
- }
|
|
|
-});
|
|
|
-const input = form.querySelector('#clave_profesor');
|
|
|
-const option = form.querySelector(`option[value="${input.value}"]`);
|
|
|
+ </div>`;
|
|
|
+ bloque.insertAdjacentHTML("afterbegin", loading);
|
|
|
+ // add style vertical-align: middle
|
|
|
+ bloque.style.verticalAlign = "middle";
|
|
|
+ bloque.classList.add("text-center");
|
|
|
+ // remove draggable
|
|
|
+ bloque.removeAttribute("draggable");
|
|
|
+ moveHorario(id, día, hora);
|
|
|
+ }
|
|
|
+ element.addEventListener("dragover", dragOver);
|
|
|
+ element.addEventListener("dragleave", dragLeave);
|
|
|
+ element.addEventListener("drop", drop);
|
|
|
+ });
|
|
|
+}
|
|
|
+const form = document.getElementById('form');
|
|
|
+if (!(form instanceof HTMLFormElement)) {
|
|
|
+ triggerMessage('No se ha encontrado el formulario', 'Error', 'danger');
|
|
|
+ throw new Error("No se ha encontrado el formulario");
|
|
|
+}
|
|
|
+form.querySelector('#clave_profesor').addEventListener('input', function (e) {
|
|
|
+ const input = form.querySelector('#clave_profesor');
|
|
|
+ const option = form.querySelector(`option[value="${input.value}"]`);
|
|
|
+ if (input.value == "") {
|
|
|
+ input.classList.remove("is-invalid", "is-valid");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!option) {
|
|
|
+ input.classList.remove("is-valid");
|
|
|
+ input.classList.add("is-invalid");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ const profesor_id = form.querySelector('#profesor_id');
|
|
|
+ profesor_id.value = option.dataset.id;
|
|
|
+ input.classList.remove("is-invalid");
|
|
|
+ input.classList.add("is-valid");
|
|
|
+ }
|
|
|
+});
|
|
|
+form.addEventListener('submit', async function (e) {
|
|
|
+ e.preventDefault();
|
|
|
+ const input = form.querySelector('#clave_profesor');
|
|
|
+ if (input.classList.contains("is-invalid")) {
|
|
|
+ triggerMessage('El profesor no se encuentra registrado', 'Error', 'danger');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const formData = new FormData(form);
|
|
|
+ try {
|
|
|
+ const buttons = document.querySelectorAll("button");
|
|
|
+ buttons.forEach(button => {
|
|
|
+ button.disabled = true;
|
|
|
+ button.classList.add("disabled");
|
|
|
+ });
|
|
|
+ const response = await fetch('action/action_horario_profesor.php', {
|
|
|
+ method: 'POST',
|
|
|
+ body: formData,
|
|
|
+ });
|
|
|
+ const data = await response.json();
|
|
|
+ buttons.forEach(button => {
|
|
|
+ button.disabled = false;
|
|
|
+ button.classList.remove("disabled");
|
|
|
+ });
|
|
|
+ if (data.status == 'success') {
|
|
|
+ horarios = data.data;
|
|
|
+ renderHorario();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ triggerMessage(data.message, 'Error en la consulta', 'warning');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ triggerMessage('Fallo al consutar los datos ', 'Error', 'danger');
|
|
|
+ console.log(error);
|
|
|
+ }
|
|
|
+});
|
|
|
+const input = form.querySelector('#clave_profesor');
|
|
|
+const option = form.querySelector(`option[value="${input.value}"]`);
|