From ec382e989a8ae236060483b7c70beae21161e0c6 Mon Sep 17 00:00:00 2001 From: Alejandro Rosales Date: Tue, 8 Aug 2023 17:04:21 +0000 Subject: [PATCH] Stable --- action/action_asistencias.php | 86 +- action/action_asistencias_excel.php | 200 +- action/action_auditoria.php | 112 +- action/action_avisos_delete.php | 16 +- action/action_avisos_insert.php | 54 +- action/action_avisos_update.php | 102 +- action/action_carreras.php | 48 +- action/action_carreras_insert.php | 38 +- action/action_carreras_select.php | 32 +- action/action_carreras_update.php | 36 +- action/action_diasfestivos_borra.php | 30 +- action/action_diasfestivos_insert.php | 96 +- action/action_diasfestivos_select.php | 38 +- action/action_diasfestivos_update.php | 62 +- action/action_estado_supervisor.php | 82 +- action/action_facultad.php | 100 +- action/action_facultades_insert.php | 46 +- action/action_facultades_select.php | 30 +- action/action_facultades_update.php | 34 +- action/action_fechas_clase.php | 52 +- action/action_grupo.php | 46 +- action/action_grupo_horario.php | 56 +- action/action_horario.php | 68 +- action/action_horario_create.php | 82 +- action/action_horario_delete.php | 74 +- action/action_horario_excel.php | 102 +- action/action_horario_profesor.php | 76 +- action/action_horario_update.php | 96 +- action/action_justificar.php | 66 +- action/action_login.php | 83 +- action/action_materias.php | 50 +- action/action_materias_select.php | 14 +- action/action_materias_update.php | 20 +- action/action_new_horario.php | 32 +- action/action_periodos_insert.php | 32 +- action/action_periodos_select.php | 14 +- action/action_periodos_update.php | 34 +- action/action_periodousuario_update.php | 54 +- action/action_permisos_update.php | 78 +- action/action_profesor.php | 26 +- action/action_profesor_faltas.php | 78 +- action/action_profesores_borra.php | 12 +- action/action_profesores_insert.php | 148 +- action/action_profesores_select.php | 20 +- action/action_profesores_update.php | 70 +- action/action_reposiciones.php | 108 +- action/action_revisar_excel.php | 100 +- action/action_roles_insert.php | 20 +- action/action_roles_select.php | 20 +- action/action_roles_update.php | 20 +- action/action_tiempos_update.php | 72 +- action/action_usuario.php | 44 +- action/action_usuarios_insert.php | 42 +- action/action_usuarios_select.php | 14 +- action/action_usuarios_update.php | 28 +- action/carrera_find.php | 18 +- action/force_session.php | 72 +- action/registro_supervisor.php | 118 +- action/rutas.php | 54 +- action/rutas_salón_horario.php | 144 +- action/schemas/registro_supervisor.json | 48 +- action/usuario_find.php | 50 +- alta_de_horario.php | 570 ++-- auditoría.php | 797 +++--- avisos.php | 528 ++-- avisos_crear.php | 868 +++--- avisos_editar.php | 872 +++--- base.php | 114 +- bypass.php | 276 +- carreras.php | 1624 ++++++------ class/c_logasistencia.php | 146 +- class/c_login.php | 271 +- class/c_menu.php | 28 +- class/connection.php | 112 +- consultar_horario.php | 3224 +++++++++++------------ css/checador.css | 92 +- css/custominputfile.min.css | 18 +- css/richtext.css | 378 +-- demo.html | 468 ++-- días_festivos.php | 684 ++--- editar_horario.php | 220 +- excel_horario.php | 416 +-- facultades.php | 564 ++-- horario_profesor.php | 268 +- import/html_css_files.php | 10 +- import/html_footer.php | 208 +- import/html_forms.php | 42 +- import/html_forms_asistencia.php | 276 +- import/html_forms_justificacion.php | 220 +- import/html_forms_vista.php | 324 +-- import/html_header.php | 309 ++- import/html_header_index.php | 63 +- import/html_navtoggle.php | 92 +- import/html_scroll.php | 82 +- import/periodo.php | 127 +- include/bd_pdo.php | 126 +- include/func_excel.php | 330 +-- include/func_string.php | 20 +- include/lastbackup.tar | Bin 9437184 -> 0 bytes include/nocache.php | 26 +- index.php | 144 +- js/auditoría.js | 349 +-- js/barra.js | 80 +- js/client.js | 240 +- js/consulta_horarios.js | 576 ++-- js/consultar_horarios.js | 1960 +++++++------- js/custominputfile.min-es.js | 148 +- js/date_functions.js | 28 +- js/fetchlib.js | 86 +- js/horario_profesor.js | 828 +++--- js/jquery-ui.touch-punch.min.js | 20 +- js/messages.js | 70 +- js/messages.php | 76 +- js/moment.js | 2 +- js/reposiciones.js | 356 +-- js/scrollables.js | 62 +- js/vista_forms.js | 128 +- justificar_asistencias.php | 664 ++--- main.php | 235 +- materias.php | 560 ++-- module/messages.js | 70 +- package-lock.json | 13 + package.json | 1 + permisos.php | 276 +- profesores.php | 828 +++--- reposiciones.php | 566 ++-- roles.php | 402 +-- salir.php | 8 +- sample/rutas.json | 1604 +++++------ script/query_6-10-2022.sql | 302 +-- selector_rutas.php | 446 ++-- service/auto.php | 52 +- service/backend/carreras.php | 150 +- service/backend/periodos.php | 118 +- service/client.html | 308 +-- service/horarios.php | 160 +- service/periodos.v1.php | 68 +- service/periodos.v2.php | 72 +- supervisor.php | 1466 +++++------ test.php | 60 +- ts/auditoría.ts | 514 ++-- ts/client.ts | 296 +-- ts/horario_profesor.ts | 1064 ++++---- ts/reposiciones.ts | 542 ++-- tsconfig.json | 26 +- usuarios.php | 899 ++++--- vista_profesor.php | 856 +++--- 147 files changed, 18206 insertions(+), 18063 deletions(-) delete mode 100644 include/lastbackup.tar diff --git a/action/action_asistencias.php b/action/action_asistencias.php index 6ecb53f..9a7a464 100644 --- a/action/action_asistencias.php +++ b/action/action_asistencias.php @@ -1,43 +1,43 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); - -extract($_POST); - -$initial_date = DateTime::createFromFormat('d/m/Y', $fecha_inicial); -$final_date = DateTime::createFromFormat('d/m/Y', $fecha_final); - -if ($initial_date > $final_date) { - echo json_encode(['error' => 'La fecha inicial no puede ser mayor a la fecha final']); - die; -} -// Nombre del profesor es opcional -$params = [ - ':carrera' => empty($carrera) ? null : $carrera, - ':periodo' => $periodo, - ':nombre' => empty($nombre) ? null : $nombre, - ':clave' => empty($clave) ? null : $clave, - ':initial_date' => $initial_date->format('Y-m-d'), - ':final_date' => $final_date->format('Y-m-d'), - ':facultad' => $facultad, -]; - -$response = json_encode( - [ - "retardo" => query("SELECT FS_HAS_RETARDO(:facultad) retardo", [ - 'facultad' => $facultad - ]), - "reporte" => queryAll( - "SELECT * FROM fs_asistencia_reporte(:carrera, :periodo, :clave, :nombre, :facultad, :initial_date, :final_date) where total > 0", - $params - ) - ] -); -$user->print_to_log("Genera reporte de asistencias", old: $params); -echo $response; + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); + +extract($_POST); + +$initial_date = DateTime::createFromFormat('d/m/Y', $fecha_inicial); +$final_date = DateTime::createFromFormat('d/m/Y', $fecha_final); + +if ($initial_date > $final_date) { + echo json_encode(['error' => 'La fecha inicial no puede ser mayor a la fecha final']); + die; +} +// Nombre del profesor es opcional +$params = [ + ':carrera' => empty($carrera) ? null : $carrera, + ':periodo' => $periodo, + ':nombre' => empty($nombre) ? null : $nombre, + ':clave' => empty($clave) ? null : $clave, + ':initial_date' => $initial_date->format('Y-m-d'), + ':final_date' => $final_date->format('Y-m-d'), + ':facultad' => $facultad, +]; + +$response = json_encode( + [ + "retardo" => query("SELECT FS_HAS_RETARDO(:facultad) retardo", [ + 'facultad' => $facultad + ]), + "reporte" => queryAll( + "SELECT * FROM fs_asistencia_reporte(:carrera, :periodo, :clave, :nombre, :facultad, :initial_date, :final_date) where total > 0", + $params + ) + ] +); +$user->print_to_log("Genera reporte de asistencias", old: $params); +echo $response; diff --git a/action/action_asistencias_excel.php b/action/action_asistencias_excel.php index e6aa2e8..222597d 100644 --- a/action/action_asistencias_excel.php +++ b/action/action_asistencias_excel.php @@ -1,100 +1,100 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$user->print_to_log('Genera excel de asistencias'); - -use PhpOffice\PhpSpreadsheet\Spreadsheet; - -$spreadsheet = new Spreadsheet(); -$sheet = $spreadsheet->getActiveSheet(); - -//crea imagen -$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); -$drawing->setName('La Salle'); -$drawing->setDescription('La Salle'); -$drawing->setPath('../imagenes/logo.png'); // put your path and image here -$drawing->setCoordinates('A1'); -$drawing->setHeight(100); -$drawing->setOffsetX(10); -//agrega imagen -$drawing->setWorksheet($spreadsheet->getActiveSheet()); - - -// In POST -/** Array - * * nombre - * * clave - * * id - * * total - * * asistencias - * * faltas - * * justificaciones - * * retardos - */ - -$retardo = query("SELECT COALESCE(FS_HAS_RETARDO(:facultad), FALSE) AS retardo", [':facultad' => $user->facultad['facultad_id']])['retardo']; -extract($_POST); - -$row = 6; - -$sheet->setCellValue("A$row", 'Clave'); -$sheet->setCellValue("B$row", 'Profesor'); -$sheet->setCellValue("C$row", 'Asistencias'); -$sheet->setCellValue("D$row", 'Faltas'); -$sheet->setCellValue("E$row", 'Justificaciones'); -$sheet->setCellValue("F$row", 'Retardos'); -$sheet->setCellValue("G$row", 'Total'); - -// $row++; -$col = 0; -# die(print_r($asistencias, true)); -foreach (json_decode($asistencias, true) as $profesor) { - $row++; - $sheet->setCellValue("A$row", $profesor['profesor_clave']); - $sheet->setCellValue("B$row", $profesor['profesor_nombre']); - $sheet->setCellValue("C$row", $profesor['asistencias']); - $sheet->setCellValue("D$row", $profesor['faltas']); - $sheet->setCellValue("E$row", $profesor['justificaciones']); - $sheet->setCellValue("F$row", $profesor['retardos']); - $sheet->setCellValue("G$row", $profesor['total']); -} - -# Style -$sheet->getStyle("A6:G$row")->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); -$sheet->getStyle("A6:G$row")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); -$sheet->getStyle("A6:G$row")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); -$sheet->getStyle("A6:G$row")->getAlignment()->setWrapText(true); -$sheet->getStyle("A6:G$row")->getFont()->setSize(12); -$sheet->getStyle("A6:G$row")->getFont()->setName('Indivisa Sans'); -# Autosize columns -foreach (range('A', 'G') as $column) { - $sheet->getColumnDimension($column)->setAutoSize(true); -} -# filters in the column -$sheet->setAutoFilter("A6:G6"); - -if (!$retardo) # hide column - $sheet->getColumnDimension('F')->setVisible(false); - -#$writer = new Xlsx($spreadsheet); -$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); -# $writer->save('asistencias.xlsx'); - -// download -header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); -header('Content-Disposition: attachment;filename="asistencias.xlsx"'); -header('Cache-Control: max-age=0'); - -// cache expires in 60 seconds (1 minute) -header('Expires: mon 26 jul 1997 05:00:00 gmt'); -header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); -header('Cache-Control: cache, must-revalidate'); -header('Pragma: public'); - -$writer->save('php://output'); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$user->print_to_log('Genera excel de asistencias'); + +use PhpOffice\PhpSpreadsheet\Spreadsheet; + +$spreadsheet = new Spreadsheet(); +$sheet = $spreadsheet->getActiveSheet(); + +//crea imagen +$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); +$drawing->setName('La Salle'); +$drawing->setDescription('La Salle'); +$drawing->setPath('../imagenes/logo.png'); // put your path and image here +$drawing->setCoordinates('A1'); +$drawing->setHeight(100); +$drawing->setOffsetX(10); +//agrega imagen +$drawing->setWorksheet($spreadsheet->getActiveSheet()); + + +// In POST +/** Array + * * nombre + * * clave + * * id + * * total + * * asistencias + * * faltas + * * justificaciones + * * retardos + */ + +$retardo = query("SELECT COALESCE(FS_HAS_RETARDO(:facultad), FALSE) AS retardo", [':facultad' => $user->facultad['facultad_id']])['retardo']; +extract($_POST); + +$row = 6; + +$sheet->setCellValue("A$row", 'Clave'); +$sheet->setCellValue("B$row", 'Profesor'); +$sheet->setCellValue("C$row", 'Asistencias'); +$sheet->setCellValue("D$row", 'Faltas'); +$sheet->setCellValue("E$row", 'Justificaciones'); +$sheet->setCellValue("F$row", 'Retardos'); +$sheet->setCellValue("G$row", 'Total'); + +// $row++; +$col = 0; +# die(print_r($asistencias, true)); +foreach (json_decode($asistencias, true) as $profesor) { + $row++; + $sheet->setCellValue("A$row", $profesor['profesor_clave']); + $sheet->setCellValue("B$row", $profesor['profesor_nombre']); + $sheet->setCellValue("C$row", $profesor['asistencias']); + $sheet->setCellValue("D$row", $profesor['faltas']); + $sheet->setCellValue("E$row", $profesor['justificaciones']); + $sheet->setCellValue("F$row", $profesor['retardos']); + $sheet->setCellValue("G$row", $profesor['total']); +} + +# Style +$sheet->getStyle("A6:G$row")->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN); +$sheet->getStyle("A6:G$row")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); +$sheet->getStyle("A6:G$row")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); +$sheet->getStyle("A6:G$row")->getAlignment()->setWrapText(true); +$sheet->getStyle("A6:G$row")->getFont()->setSize(12); +$sheet->getStyle("A6:G$row")->getFont()->setName('Indivisa Sans'); +# Autosize columns +foreach (range('A', 'G') as $column) { + $sheet->getColumnDimension($column)->setAutoSize(true); +} +# filters in the column +$sheet->setAutoFilter("A6:G6"); + +if (!$retardo) # hide column + $sheet->getColumnDimension('F')->setVisible(false); + +#$writer = new Xlsx($spreadsheet); +$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); +# $writer->save('asistencias.xlsx'); + +// download +header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); +header('Content-Disposition: attachment;filename="asistencias.xlsx"'); +header('Cache-Control: max-age=0'); + +// cache expires in 60 seconds (1 minute) +header('Expires: mon 26 jul 1997 05:00:00 gmt'); +header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); +header('Cache-Control: cache, must-revalidate'); +header('Pragma: public'); + +$writer->save('php://output'); diff --git a/action/action_auditoria.php b/action/action_auditoria.php index 5ee4c21..0852b62 100644 --- a/action/action_auditoria.php +++ b/action/action_auditoria.php @@ -1,57 +1,57 @@ - [ - #'periodo_id', - ], -]; -$ruta = "../"; -require_once "../class/c_login.php"; -// check method -try { - - - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - array_walk($information['GET'], function ($value) { - if (!array_key_exists($value, $_GET)) { - http_response_code(400); - echo json_encode(['error' => "$value is required"]); - exit; - } - }); - - $data = $db->query("SELECT *, horario_view.facultad_id FROM registro - JOIN horario_view USING (horario_id) - LEFT JOIN estado_supervisor USING (estado_supervisor_id) - LEFT JOIN profesor USING (profesor_id) - LEFT JOIN usuario ON usuario.usuario_id = registro.supervisor_id - ORDER BY registro_fecha_ideal DESC, horario_hora ASC, registro_fecha_supervisor ASC"); - - $last_query = [ - 'query' => $db->getLastQuery(), - ]; - - echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } else { - http_response_code(405); - echo json_encode(['error' => 'method not allowed']); - exit; - - } - -} catch (PDOException $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - 'query' => $db->getLastQuery(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; -} catch (Exception $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; + [ + #'periodo_id', + ], +]; +$ruta = "../"; +require_once "../class/c_login.php"; +// check method +try { + + + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + array_walk($information['GET'], function ($value) { + if (!array_key_exists($value, $_GET)) { + http_response_code(400); + echo json_encode(['error' => "$value is required"]); + exit; + } + }); + + $data = $db->query("SELECT *, horario_view.facultad_id, horario_view.periodo_id FROM registro + JOIN horario_view USING (horario_id) + LEFT JOIN estado_supervisor USING (estado_supervisor_id) + LEFT JOIN profesor USING (profesor_id) + LEFT JOIN usuario ON usuario.usuario_id = registro.supervisor_id + ORDER BY registro_fecha_ideal DESC, horario_hora ASC, registro_fecha_supervisor ASC"); + + $last_query = [ + 'query' => $db->getLastQuery(), + ]; + + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } else { + http_response_code(405); + echo json_encode(['error' => 'method not allowed']); + exit; + + } + +} catch (PDOException $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + 'query' => $db->getLastQuery(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} catch (Exception $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; } \ No newline at end of file diff --git a/action/action_avisos_delete.php b/action/action_avisos_delete.php index e504322..e4409f6 100644 --- a/action/action_avisos_delete.php +++ b/action/action_avisos_delete.php @@ -1,9 +1,9 @@ - $_POST['id']]; -echo json_encode(query($sql, $params, false)); + $_POST['id']]; +echo json_encode(query($sql, $params, false)); ?> \ No newline at end of file diff --git a/action/action_avisos_insert.php b/action/action_avisos_insert.php index 26019e1..dfb6fec 100644 --- a/action/action_avisos_insert.php +++ b/action/action_avisos_insert.php @@ -1,28 +1,28 @@ - $tipo], false); - foreach($profesores_carrera as $profesor){ - array_push($profesores, $profesor['profesor_id']); - } - - } -} -$sql = "SELECT fi_aviso(:fecha_inicial, :fecha_final, :texto, :facultad)"; -$params = [':fecha_inicial' => $_POST['fecha_inicial'], ':fecha_final' => $_POST['fecha_final'], ':texto' => $_POST['texto'], ':facultad' => $_POST['facultad']]; -$aviso_id = query($sql, $params, true); - -$sql = "SELECT fi_aviso_profesor(:aviso_id, :profesor_id)"; -foreach($profesores as $profesor_id){ - $params = [':aviso_id' => $aviso_id['fi_aviso'], ':profesor_id' => $profesor_id]; - query($sql, $params, false); -} -header("Location: ../avisos.php"); -exit(); + $tipo], false); + foreach($profesores_carrera as $profesor){ + array_push($profesores, $profesor['profesor_id']); + } + + } +} +$sql = "SELECT fi_aviso(:fecha_inicial, :fecha_final, :texto, :facultad)"; +$params = [':fecha_inicial' => $_POST['fecha_inicial'], ':fecha_final' => $_POST['fecha_final'], ':texto' => $_POST['texto'], ':facultad' => $_POST['facultad']]; +$aviso_id = query($sql, $params, true); + +$sql = "SELECT fi_aviso_profesor(:aviso_id, :profesor_id)"; +foreach($profesores as $profesor_id){ + $params = [':aviso_id' => $aviso_id['fi_aviso'], ':profesor_id' => $profesor_id]; + query($sql, $params, false); +} +header("Location: ../avisos.php"); +exit(); ?> \ No newline at end of file diff --git a/action/action_avisos_update.php b/action/action_avisos_update.php index 88b4bb2..6f6bf24 100644 --- a/action/action_avisos_update.php +++ b/action/action_avisos_update.php @@ -1,52 +1,52 @@ - $_POST['aviso_id']], true); -if(isset($_POST['fecha_final'])){ - $fecha_fin = $_POST['fecha_final']; -}else{ - $fecha_fin = $aviso['aviso_fecha_final']; -} -if(isset($_POST['texto'])){ - $texto = $_POST['texto']; -}else{ - $texto = $aviso['aviso_texto']; -} -if(isset($_POST['fecha_inicial'])){ - $fecha_inicio = $_POST['fecha_inicial']; -}else{ - $fecha_inicio = $aviso['aviso_fecha_inicial']; -} - -$sql = "SELECT fu_update_aviso(:id, :fecha_fin, :texto, :fecha_inicio)"; -$params = [':id' => $_POST['aviso_id'], ':fecha_fin' => $fecha_fin, ':texto' => $texto, ':fecha_inicio' => $fecha_inicio]; -query($sql, $params, true); - -query("SELECT fd_aviso_profesor(:aviso_id)", [':aviso_id' => $_POST['aviso_id']], false); - -$profesores = []; -if(isset($_POST['tipo'])){ - foreach($_POST['tipo'] as $tipo){ - $profesores_carrera = query("SELECT profesor_id FROM fs_profesor_carrera(:carrera_id)", [':carrera_id' => $tipo], false); - foreach($profesores_carrera as $profesor){ - array_push($profesores, $profesor['profesor_id']); - } - - } -} - - -foreach($_POST['usuario'] as $profesor){ - array_push($profesores, $profesor); -} -$sql = "SELECT fi_aviso_profesor(:aviso_id, :profesor_id)"; -foreach($profesores as $profesor_id){ - $params = [':aviso_id' => $_POST['aviso_id'], ':profesor_id' => $profesor_id]; - query($sql, $params, false); -} - -header("Location: ../avisos.php"); -exit(); + $_POST['aviso_id']], true); +if(isset($_POST['fecha_final'])){ + $fecha_fin = $_POST['fecha_final']; +}else{ + $fecha_fin = $aviso['aviso_fecha_final']; +} +if(isset($_POST['texto'])){ + $texto = $_POST['texto']; +}else{ + $texto = $aviso['aviso_texto']; +} +if(isset($_POST['fecha_inicial'])){ + $fecha_inicio = $_POST['fecha_inicial']; +}else{ + $fecha_inicio = $aviso['aviso_fecha_inicial']; +} + +$sql = "SELECT fu_update_aviso(:id, :fecha_fin, :texto, :fecha_inicio)"; +$params = [':id' => $_POST['aviso_id'], ':fecha_fin' => $fecha_fin, ':texto' => $texto, ':fecha_inicio' => $fecha_inicio]; +query($sql, $params, true); + +query("SELECT fd_aviso_profesor(:aviso_id)", [':aviso_id' => $_POST['aviso_id']], false); + +$profesores = []; +if(isset($_POST['tipo'])){ + foreach($_POST['tipo'] as $tipo){ + $profesores_carrera = query("SELECT profesor_id FROM fs_profesor_carrera(:carrera_id)", [':carrera_id' => $tipo], false); + foreach($profesores_carrera as $profesor){ + array_push($profesores, $profesor['profesor_id']); + } + + } +} + + +foreach($_POST['usuario'] as $profesor){ + array_push($profesores, $profesor); +} +$sql = "SELECT fi_aviso_profesor(:aviso_id, :profesor_id)"; +foreach($profesores as $profesor_id){ + $params = [':aviso_id' => $_POST['aviso_id'], ':profesor_id' => $profesor_id]; + query($sql, $params, false); +} + +header("Location: ../avisos.php"); +exit(); ?> \ No newline at end of file diff --git a/action/action_carreras.php b/action/action_carreras.php index 05d21e3..8ce5109 100644 --- a/action/action_carreras.php +++ b/action/action_carreras.php @@ -1,24 +1,24 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); - -$ruta = "../"; -require_once "../include/bd_pdo.php"; - -$nivel = $db->where("id", $_POST['periodo'])->getOne("fs_periodo", "nivel_id"); -$carreras = $db - ->where("nivel", $nivel) - ->where("facultad", $_POST['facultad']) - ->get("fs_carrera", null, "id, carrera"); - -$user->print_to_log("Crea carrera", old: $_POST); - -die(json_encode($carreras)); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); + +$ruta = "../"; +require_once "../include/bd_pdo.php"; + +$nivel = $db->where("id", $_POST['periodo'])->getOne("fs_periodo", "nivel_id"); +$carreras = $db + ->where("nivel", $nivel) + ->where("facultad", $_POST['facultad']) + ->get("fs_carrera", null, "id, carrera"); + +$user->print_to_log("Crea carrera", old: $_POST); + +die(json_encode($carreras)); diff --git a/action/action_carreras_insert.php b/action/action_carreras_insert.php index 82b03c8..00e1681 100644 --- a/action/action_carreras_insert.php +++ b/action/action_carreras_insert.php @@ -1,19 +1,19 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -$sql = "SELECT fi_carrera(:nombre, :idfacultad, :idnivel, true, :estado)"; -$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':idfacultad' => $_POST['facultad'], ':idnivel' => $_POST['nivel'], ':estado' => $_POST['estado']]; - -print_r($_POST); -echo json_encode(query($sql, $params, true)); -$user->print_to_log("Crea carrera", new: $params); -header("Location: ../carreras.php?facultad=" . $_POST['facultad']); -exit(); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +$sql = "SELECT fi_carrera(:nombre, :idfacultad, :idnivel, true, :estado)"; +$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':idfacultad' => $_POST['facultad'], ':idnivel' => $_POST['nivel'], ':estado' => $_POST['estado']]; + +print_r($_POST); +echo json_encode(query($sql, $params, true)); +$user->print_to_log("Crea carrera", new: $params); +header("Location: ../carreras.php?facultad=" . $_POST['facultad']); +exit(); diff --git a/action/action_carreras_select.php b/action/action_carreras_select.php index 2316cde..cb50027 100644 --- a/action/action_carreras_select.php +++ b/action/action_carreras_select.php @@ -1,16 +1,16 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -$sql = "SELECT * FROM fs_carreras(:idfacultad, :idcarrera, null)"; -$params = [':idfacultad' => $_POST['idfacultad'], ':idcarrera' => $_POST['idcarrera']]; -$user->print_to_log("Crea carrera", old: $params); -echo json_encode(query($sql, $params, true)); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +$sql = "SELECT * FROM fs_carreras(:idfacultad, :idcarrera, null)"; +$params = [':idfacultad' => $_POST['idfacultad'], ':idcarrera' => $_POST['idcarrera']]; +$user->print_to_log("Crea carrera", old: $params); +echo json_encode(query($sql, $params, true)); diff --git a/action/action_carreras_update.php b/action/action_carreras_update.php index 9cd0bb5..5197440 100644 --- a/action/action_carreras_update.php +++ b/action/action_carreras_update.php @@ -1,19 +1,19 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -$old = query("SELECT * FROM FS_CARRERA WHERE ID = :id", [':id' => $_POST['id']]); -$sql = "SELECT fu_updatecarrera(:idcarrera, :nombre, :activa, :idnivel)"; -print_r($_POST); -$params = [':idcarrera' => $_POST['id'], ':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado'], ':idnivel' => $_POST['nivel']]; -query($sql, $params, true); -$user->print_to_log("Actualiza carrera.", old: $old, new: $params); -header("Location: ../carreras.php?facultad=" . $_POST['facultad']); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +$old = query("SELECT * FROM FS_CARRERA WHERE ID = :id", [':id' => $_POST['id']]); +$sql = "SELECT fu_updatecarrera(:idcarrera, :nombre, :activa, :idnivel)"; +print_r($_POST); +$params = [':idcarrera' => $_POST['id'], ':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado'], ':idnivel' => $_POST['nivel']]; +query($sql, $params, true); +$user->print_to_log("Actualiza carrera.", old: $old, new: $params); +header("Location: ../carreras.php?facultad=" . $_POST['facultad']); exit(); \ No newline at end of file diff --git a/action/action_diasfestivos_borra.php b/action/action_diasfestivos_borra.php index faf8ab3..92d1732 100644 --- a/action/action_diasfestivos_borra.php +++ b/action/action_diasfestivos_borra.php @@ -1,15 +1,15 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -#$sql = "SELECT * FROM diasfestivos WHERE diasfestivos_id = :id"; -$sql = "DELETE FROM diasfestivos WHERE diasfestivos_id = :id"; -$params = [':id' => $_POST['id']]; -echo json_encode(query($sql, $params, false)); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +#$sql = "SELECT * FROM diasfestivos WHERE diasfestivos_id = :id"; +$sql = "DELETE FROM diasfestivos WHERE diasfestivos_id = :id"; +$params = [':id' => $_POST['id']]; +echo json_encode(query($sql, $params, false)); diff --git a/action/action_diasfestivos_insert.php b/action/action_diasfestivos_insert.php index 1ccb2fb..369f6eb 100644 --- a/action/action_diasfestivos_insert.php +++ b/action/action_diasfestivos_insert.php @@ -1,48 +1,48 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -print_r($_POST); -if ($_POST['periodo'] == 0) { - $periodo = null; -} else { - $periodo = $_POST['periodo']; -} -if (isset($_POST['rango'])) { - $diaInicio = new DateTime(date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivo'])))); - $diaFin = new DateTime(date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivoFin'])))); - $cantidad = $diaFin->diff($diaInicio); - $date = date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivo']))); - for ($dias = 0; $dias <= $cantidad->days; $dias++) { - $sql = "SELECT fi_diasfestivos(:periodo, :dia)"; - $params = [':periodo' => $periodo, ':dia' => $date]; - query($sql, $params, false); - $date = date("Y-m-d", strtotime($date . "+ 1 days")); - } - header("Location: ../días_festivos.php"); - exit(); -} else { - $sql = "SELECT * FROM fs_diasfestivos(null, :dia)"; - $params = [':dia' => $_POST['diaFestivo']]; - $dia_general = query($sql, $params, false); - $sql = "SELECT * FROM fs_diasfestivos(null, null, :periodo, :dia)"; - $params = [':periodo' => $periodo, ":dia" => $_POST['diaFestivo']]; - $dia = query($sql, $params, false); - if (!$dia && !$dia_general) { //no hay repetidos - $sql = "SELECT fi_diasfestivos(:periodo, :dia)"; - $id = query($sql, $params, false); - header("Location: ../días_festivos.php"); - exit(); - } else { - header("Location: ../días_festivos.php?error=1"); - exit(); - } -} + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +print_r($_POST); +if ($_POST['periodo'] == 0) { + $periodo = null; +} else { + $periodo = $_POST['periodo']; +} +if (isset($_POST['rango'])) { + $diaInicio = new DateTime(date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivo'])))); + $diaFin = new DateTime(date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivoFin'])))); + $cantidad = $diaFin->diff($diaInicio); + $date = date("Y-m-d", strtotime(str_replace("/", "-", $_POST['diaFestivo']))); + for ($dias = 0; $dias <= $cantidad->days; $dias++) { + $sql = "SELECT fi_diasfestivos(:periodo, :dia)"; + $params = [':periodo' => $periodo, ':dia' => $date]; + query($sql, $params, false); + $date = date("Y-m-d", strtotime($date . "+ 1 days")); + } + header("Location: ../días_festivos.php"); + exit(); +} else { + $sql = "SELECT * FROM fs_diasfestivos(null, :dia)"; + $params = [':dia' => $_POST['diaFestivo']]; + $dia_general = query($sql, $params, false); + $sql = "SELECT * FROM fs_diasfestivos(null, null, :periodo, :dia)"; + $params = [':periodo' => $periodo, ":dia" => $_POST['diaFestivo']]; + $dia = query($sql, $params, false); + if (!$dia && !$dia_general) { //no hay repetidos + $sql = "SELECT fi_diasfestivos(:periodo, :dia)"; + $id = query($sql, $params, false); + header("Location: ../días_festivos.php"); + exit(); + } else { + header("Location: ../días_festivos.php?error=1"); + exit(); + } +} diff --git a/action/action_diasfestivos_select.php b/action/action_diasfestivos_select.php index 2356c7a..efa1006 100644 --- a/action/action_diasfestivos_select.php +++ b/action/action_diasfestivos_select.php @@ -1,19 +1,19 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -$params = [':id' => $_POST['id']]; -if ($_POST['periodo'] == 0) { - $sql = "SELECT * FROM fs_diasfestivos(:id, null)"; -} else { - $sql = "SELECT * FROM fs_diasfestivos(null, :id, null, null)"; -} -echo json_encode(query($sql, $params, true)); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +$params = [':id' => $_POST['id']]; +if ($_POST['periodo'] == 0) { + $sql = "SELECT * FROM fs_diasfestivos(:id, null)"; +} else { + $sql = "SELECT * FROM fs_diasfestivos(null, :id, null, null)"; +} +echo json_encode(query($sql, $params, true)); diff --git a/action/action_diasfestivos_update.php b/action/action_diasfestivos_update.php index be0b45b..a68eaa5 100644 --- a/action/action_diasfestivos_update.php +++ b/action/action_diasfestivos_update.php @@ -1,31 +1,31 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -if ($_POST['periodo'] == 0) { - $periodo = null; -} else - $periodo = $_POST['periodo']; -$sql = "SELECT * FROM fs_diasfestivos(null, :dia) WHERE diasfestivos_id != :id"; -$params = [':dia' => $_POST['diaFestivo'], ':id' => $_POST['id']]; -$dia_general = query($sql, $params, false); -$sql = "SELECT * FROM fs_diasfestivos(null, null, :periodo, :dia) WHERE diasfestivos_id != :id"; -$params = [':periodo' => $periodo, ':dia' => $_POST['diaFestivo'], ':id' => $_POST['id']]; -$dia = query($sql, $params, false); -if (!$dia && !$dia_general) { //no hay repetidos - $sql = "SELECT fu_update_diasfestivos(:id, :dia, :periodo)"; - query($sql, $params, false); - header("Location: ../días_festivos.php"); - exit(); -} else { //es repetido - header("Location: ../días_festivos.php?error=1"); - exit(); -} + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +if ($_POST['periodo'] == 0) { + $periodo = null; +} else + $periodo = $_POST['periodo']; +$sql = "SELECT * FROM fs_diasfestivos(null, :dia) WHERE diasfestivos_id != :id"; +$params = [':dia' => $_POST['diaFestivo'], ':id' => $_POST['id']]; +$dia_general = query($sql, $params, false); +$sql = "SELECT * FROM fs_diasfestivos(null, null, :periodo, :dia) WHERE diasfestivos_id != :id"; +$params = [':periodo' => $periodo, ':dia' => $_POST['diaFestivo'], ':id' => $_POST['id']]; +$dia = query($sql, $params, false); +if (!$dia && !$dia_general) { //no hay repetidos + $sql = "SELECT fu_update_diasfestivos(:id, :dia, :periodo)"; + query($sql, $params, false); + header("Location: ../días_festivos.php"); + exit(); +} else { //es repetido + header("Location: ../días_festivos.php?error=1"); + exit(); +} diff --git a/action/action_estado_supervisor.php b/action/action_estado_supervisor.php index f15d457..12ffd1f 100644 --- a/action/action_estado_supervisor.php +++ b/action/action_estado_supervisor.php @@ -1,42 +1,42 @@ - [ - ], -]); -#output rutas: [ ...ruta, salones: [{...salon}] ] -header('Content-Type: application/json charset=utf-8'); -#return html -$ruta = "../"; -require_once "../class/c_login.php"; -// check method -try { - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - // check parameters - $raw = file_get_contents('php://input'); - $post_get = json_decode($raw, true); - - $data = $db->get('estado_supervisor'); - echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } else { - http_response_code(405); - echo json_encode(['error' => 'method not allowed']); - exit; - - } - -} catch (PDOException $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - 'query' => $db->getLastQuery(), - 'post_data' => $post_get, - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; -} catch (Exception $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; + [ + ], +]); +#output rutas: [ ...ruta, salones: [{...salon}] ] +header('Content-Type: application/json charset=utf-8'); +#return html +$ruta = "../"; +require_once "../class/c_login.php"; +// check method +try { + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + // check parameters + $raw = file_get_contents('php://input'); + $post_get = json_decode($raw, true); + + $data = $db->get('estado_supervisor'); + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } else { + http_response_code(405); + echo json_encode(['error' => 'method not allowed']); + exit; + + } + +} catch (PDOException $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + 'query' => $db->getLastQuery(), + 'post_data' => $post_get, + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} catch (Exception $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; } \ No newline at end of file diff --git a/action/action_facultad.php b/action/action_facultad.php index 3b612e8..33fa342 100644 --- a/action/action_facultad.php +++ b/action/action_facultad.php @@ -1,51 +1,51 @@ - [], -]; -header('Content-Type: application/json charset=utf-8'); -$ruta = "../"; -require_once "../class/c_login.php"; - -// check if the session is started -if (!isset($_SESSION['user'])) { - http_response_code(500); - echo json_encode([ - 'error' => 'No se ha iniciado sesión' - ]); - exit; -} - -$user = unserialize($_SESSION['user']); -try { - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - // check parameters - array_walk($information['GET'], function ($value) { - if (!array_key_exists($value, $_GET)) { - http_response_code(400); - echo json_encode(['error' => "$value is required"]); - exit; - } - }); - // step 1: get subrutas - $data = $db->get('facultad'); - - echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } else { - http_response_code(405); - echo json_encode(['error' => 'method not allowed']); - exit; - } -} catch (PDOException $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - 'query' => $db->getLastQuery(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; -} catch (Exception $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; + [], +]; +header('Content-Type: application/json charset=utf-8'); +$ruta = "../"; +require_once "../class/c_login.php"; + +// check if the session is started +if (!isset($_SESSION['user'])) { + http_response_code(500); + echo json_encode([ + 'error' => 'No se ha iniciado sesión' + ]); + exit; +} + +$user = unserialize($_SESSION['user']); +try { + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + // check parameters + array_walk($information['GET'], function ($value) { + if (!array_key_exists($value, $_GET)) { + http_response_code(400); + echo json_encode(['error' => "$value is required"]); + exit; + } + }); + // step 1: get subrutas + $data = $db->get('facultad'); + + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } else { + http_response_code(405); + echo json_encode(['error' => 'method not allowed']); + exit; + } +} catch (PDOException $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + 'query' => $db->getLastQuery(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} catch (Exception $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; } \ No newline at end of file diff --git a/action/action_facultades_insert.php b/action/action_facultades_insert.php index ffc80a6..fbadfb5 100644 --- a/action/action_facultades_insert.php +++ b/action/action_facultades_insert.php @@ -1,23 +1,23 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -$sql = "SELECT fi_facultad(:nombre, :activa)"; -$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado']]; -$fac_id = query($sql, $params, true); -$sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; -$params = [':idfacultad' => $fac_id['fi_facultad'], ':idnivel' => 1, ':antes' => -15, ':despues' => 16, ':retardo' => 31]; -query($sql, $params, false); -$params = [':idfacultad' => $fac_id['fi_facultad'], ':idnivel' => 2, ':antes' => -15, ':despues' => 16, ':retardo' => 31]; -query($sql, $params, false); -print_r($fac_id); -header("Location: ../carreras.php?facultad=" . $fac_id['fi_facultad']); -exit(); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +$sql = "SELECT fi_facultad(:nombre, :activa)"; +$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado']]; +$fac_id = query($sql, $params, true); +$sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; +$params = [':idfacultad' => $fac_id['fi_facultad'], ':idnivel' => 1, ':antes' => -15, ':despues' => 16, ':retardo' => 31]; +query($sql, $params, false); +$params = [':idfacultad' => $fac_id['fi_facultad'], ':idnivel' => 2, ':antes' => -15, ':despues' => 16, ':retardo' => 31]; +query($sql, $params, false); +print_r($fac_id); +header("Location: ../carreras.php?facultad=" . $fac_id['fi_facultad']); +exit(); diff --git a/action/action_facultades_select.php b/action/action_facultades_select.php index b4a7206..82c7516 100644 --- a/action/action_facultades_select.php +++ b/action/action_facultades_select.php @@ -1,15 +1,15 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -$sql = "SELECT * FROM facultad WHERE facultad_id = :idFacultad"; -$params = [':idFacultad' => $_POST['id_facultad']]; -echo json_encode(query($sql, $params, false)); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +$sql = "SELECT * FROM facultad WHERE facultad_id = :idFacultad"; +$params = [':idFacultad' => $_POST['id_facultad']]; +echo json_encode(query($sql, $params, false)); diff --git a/action/action_facultades_update.php b/action/action_facultades_update.php index d84c0c2..936cf92 100644 --- a/action/action_facultades_update.php +++ b/action/action_facultades_update.php @@ -1,17 +1,17 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; -global $pdo; -$sql = "SELECT fu_updatefacultad(:nombre, :activa, :id)"; -$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado'], ':id' => $_POST['id']]; -query($sql, $params, false); -header("Location: ../facultades.php"); -exit(); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; +global $pdo; +$sql = "SELECT fu_updatefacultad(:nombre, :activa, :id)"; +$params = [':nombre' => mb_strtoupper($_POST['nombre']), ':activa' => $_POST['estado'], ':id' => $_POST['id']]; +query($sql, $params, false); +header("Location: ../facultades.php"); +exit(); diff --git a/action/action_fechas_clase.php b/action/action_fechas_clase.php index afefd3e..b9ae5f8 100644 --- a/action/action_fechas_clase.php +++ b/action/action_fechas_clase.php @@ -1,26 +1,26 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; - -// if method is get -header("Content-Type: application/json"); -if ($_SERVER['REQUEST_METHOD'] === 'GET') { - $user->print_to_log("Acceso a reposiciones"); - if (empty($_GET['horario_id'])) - die(json_encode(['error' => 'No se ha enviado el id del horario'])); - // fecha greater than today - $reposiciones = $db->query("SELECT fecha, EXTRACT(DOW FROM fecha) as day, EXTRACT(MONTH FROM fecha) as month, EXTRACT(YEAR FROM fecha) as year, EXTRACT(DAY FROM fecha) as dia_mes FROM fechas_clase(:horario_id) WHERE fecha > CURRENT_DATE", [ - 'horario_id' => $_GET['horario_id'] - ]); - echo json_encode([ - 'status' => 'success', - 'data' => $reposiciones - ]); -} + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; + +// if method is get +header("Content-Type: application/json"); +if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $user->print_to_log("Acceso a reposiciones"); + if (empty($_GET['horario_id'])) + die(json_encode(['error' => 'No se ha enviado el id del horario'])); + // fecha greater than today + $reposiciones = $db->query("SELECT fecha, EXTRACT(DOW FROM fecha) as day, EXTRACT(MONTH FROM fecha) as month, EXTRACT(YEAR FROM fecha) as year, EXTRACT(DAY FROM fecha) as dia_mes FROM fechas_clase(:horario_id) WHERE fecha > CURRENT_DATE", [ + 'horario_id' => $_GET['horario_id'] + ]); + echo json_encode([ + 'status' => 'success', + 'data' => $reposiciones + ]); +} diff --git a/action/action_grupo.php b/action/action_grupo.php index 64b583f..9bf3f89 100644 --- a/action/action_grupo.php +++ b/action/action_grupo.php @@ -1,23 +1,23 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once("../include/bd_pdo.php"); -extract($_POST); -$params = ['per' => $_POST['periodo'], 'fac' => $_POST['facultad'], 'car' => $_POST['carrera']]; - -$user->print_to_log("Acceso a grupos", old: $params); -$grupos = queryAll("SELECT DISTINCT LENGTH(GRUPO), GRUPO FROM fs_horario_basic WHERE PERIODO_ID = COALESCE(:per, PERIODO_ID) AND FACULTAD_ID = COALESCE(:fac, FACULTAD_ID) AND CARRERA_ID = COALESCE(:car, CARRERA_ID) ORDER BY LENGTH(GRUPO), GRUPO", $params); - -$grupos = array_map(fn ($grupo) => $grupo['grupo'], $grupos); - -echo json_encode([ - 'status' => 'success', - 'grupos' => $grupos -]); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once("../include/bd_pdo.php"); +extract($_POST); +$params = ['per' => $_POST['periodo'], 'fac' => $_POST['facultad'], 'car' => $_POST['carrera']]; + +$user->print_to_log("Acceso a grupos", old: $params); +$grupos = queryAll("SELECT DISTINCT LENGTH(GRUPO), GRUPO FROM fs_horario_basic WHERE PERIODO_ID = COALESCE(:per, PERIODO_ID) AND FACULTAD_ID = COALESCE(:fac, FACULTAD_ID) AND CARRERA_ID = COALESCE(:car, CARRERA_ID) ORDER BY LENGTH(GRUPO), GRUPO", $params); + +$grupos = array_map(fn ($grupo) => $grupo['grupo'], $grupos); + +echo json_encode([ + 'status' => 'success', + 'grupos' => $grupos +]); diff --git a/action/action_grupo_horario.php b/action/action_grupo_horario.php index b8a24e1..5ca8f97 100644 --- a/action/action_grupo_horario.php +++ b/action/action_grupo_horario.php @@ -1,28 +1,28 @@ -querySingle( - "WITH bloques AS ( - SELECT id, hora_inicio, hora_fin - FROM public.bloque_horario - WHERE grupo = ? - ORDER BY hora_inicio ASC -) - -SELECT json_agg(json_build_object( - 'id', id, - 'hora_inicio', hora_inicio, - 'hora_fin', hora_fin, - 'selected', current_time between hora_inicio and hora_fin -)) AS bloque_horario -FROM bloques -", - [$grupo] -)['bloque_horario']; - - -echo $grupo_horarios; \ No newline at end of file +querySingle( + "WITH bloques AS ( + SELECT id, hora_inicio, hora_fin + FROM public.bloque_horario + WHERE grupo = ? + ORDER BY hora_inicio ASC +) + +SELECT json_agg(json_build_object( + 'id', id, + 'hora_inicio', hora_inicio, + 'hora_fin', hora_fin, + 'selected', current_time between hora_inicio and hora_fin +)) AS bloque_horario +FROM bloques +", + [$grupo] +)['bloque_horario']; + + +echo $grupo_horarios; diff --git a/action/action_horario.php b/action/action_horario.php index 860498c..8594f4e 100644 --- a/action/action_horario.php +++ b/action/action_horario.php @@ -1,35 +1,35 @@ -get("fs_horario($periodo, $carrera, '$grupo', true)"); - -// get each id from $horarios (might be duplicate) - -try { - $horarios = array_map(function ($horario) use ($dias, $db) { - $horario['profesores'] = array_map( - fn ($profesor) => - $db->where("id", $profesor)->getOne("fs_profesor"), - explode(",", substr($horario['profesores'], 1, -1)) - ); - $horario['dia'] = $dias[$horario['dia']]; - return $horario; - }, $horarios); -} catch (Exception $e) { - die(json_encode([ - "status" => "error", - "message" => $e->getMessage(), - ])); -} -?> - "success", - "horario" => $horarios, +get("fs_horario($periodo, $carrera, '$grupo', true)"); + +// get each id from $horarios (might be duplicate) + +try { + $horarios = array_map(function ($horario) use ($dias, $db) { + $horario['profesores'] = array_map( + fn ($profesor) => + $db->where("id", $profesor)->getOne("fs_profesor"), + explode(",", substr($horario['profesores'], 1, -1)) + ); + $horario['dia'] = $dias[$horario['dia']]; + return $horario; + }, $horarios); +} catch (Exception $e) { + die(json_encode([ + "status" => "error", + "message" => $e->getMessage(), + ])); +} +?> + "success", + "horario" => $horarios, ]) ?> \ No newline at end of file diff --git a/action/action_horario_create.php b/action/action_horario_create.php index 75fece7..ce7ede2 100644 --- a/action/action_horario_create.php +++ b/action/action_horario_create.php @@ -1,41 +1,41 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; - -extract($_POST); - -$params = [ - "hora" => $hora, - "salon" => $salón, - "facultad_id" => $facultad, - "periodo" => $periodo, - "grupo" => $grupo, - "materia_id" => $materia, - "dia" => $día, - "duracion" => $duración, - "profesores" => "{{$profesores}}", -]; - -header("Content-Type: application/json"); -$user->print_to_log("Creación de horario", new: $params); - -try { - $db->insert("fs_horario", $params); -} catch (Exception $e) { - die(json_encode([ - "status" => "error", - "message" => "No se pudo crear el horario", - ])); -} -die(json_encode([ - "status" => "success", - "message" => "Horario creado correctamente", -])); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; + +extract($_POST); + +$params = [ + "hora" => $hora, + "salon" => $salón, + "facultad_id" => $facultad, + "periodo" => $periodo, + "grupo" => $grupo, + "materia_id" => $materia, + "dia" => $día, + "duracion" => $duración, + "profesores" => "{{$profesores}}", +]; + +header("Content-Type: application/json"); +$user->print_to_log("Creación de horario", new: $params); + +try { + $db->insert("fs_horario", $params); +} catch (Exception $e) { + die(json_encode([ + "status" => "error", + "message" => "No se pudo crear el horario", + ])); +} +die(json_encode([ + "status" => "success", + "message" => "Horario creado correctamente", +])); diff --git a/action/action_horario_delete.php b/action/action_horario_delete.php index ca4bfdc..da54205 100644 --- a/action/action_horario_delete.php +++ b/action/action_horario_delete.php @@ -1,38 +1,38 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); - -extract($_POST); -try { - $old = $db - ->where('horario_id', $id) - ->getOne('horario'); - - $user->print_to_log("Eliminación de horario", old: $old); - - $horario = $db - ->where('id', $id) - ->delete('fs_horario'); -} catch (Exception $e) { - // if message contains "Integrity constraint violation" - $message = (strpos($e->getMessage(), 'Foreign') !== false) - ? "No se puede eliminar el registro, tiene datos asociados" - : "Error al eliminar el registro"; - - die(json_encode([ - "status" => "error", - "message" => $message, - "response" => $e->getMessage(), - ])); -} - -die(json_encode([ - "status" => "success", - "message" => "Horario eliminado correctamente", + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); + +extract($_POST); +try { + $old = $db + ->where('horario_id', $id) + ->getOne('horario'); + + $user->print_to_log("Eliminación de horario", old: $old); + + $horario = $db + ->where('id', $id) + ->delete('fs_horario'); +} catch (Exception $e) { + // if message contains "Integrity constraint violation" + $message = (strpos($e->getMessage(), 'Foreign') !== false) + ? "No se puede eliminar el registro, tiene datos asociados" + : "Error al eliminar el registro"; + + die(json_encode([ + "status" => "error", + "message" => $message, + "response" => $e->getMessage(), + ])); +} + +die(json_encode([ + "status" => "success", + "message" => "Horario eliminado correctamente", ])); \ No newline at end of file diff --git a/action/action_horario_excel.php b/action/action_horario_excel.php index 6989458..4cda178 100644 --- a/action/action_horario_excel.php +++ b/action/action_horario_excel.php @@ -1,51 +1,51 @@ - $horario['materia'], - 'carrera' => $carrera, - ]; - $horario['materia'] = query("SELECT FI_MATERIA(:materia, :carrera) id", $params)['id']; - - $params = [ - 'clave' => $horario['clave'], - 'nombre' => $horario['nombre'], - 'correo' => $horario['correo'], - 'grado' => $horario['grado'], - 'facultad' => $facultad, - ]; - - $horario['profesor'] = query("SELECT FI_PROFESOR(:nombre, :clave, :facultad, :correo, :grado) id", $params)['id']; - $horario = array_diff_key($horario, array_flip(['clave', 'nombre', 'correo', 'grado', ''])); - $horario['periodo'] = $periodo; - $horario['facultad'] = $facultad; - - try { - query( - "SELECT FI_HORARIO(:horario::VARCHAR, :profesor::INT, :materia::INT, :facultad::INT, :periodo::INT, :grupo::VARCHAR, :salon::VARCHAR)", - $horario - ); - } catch (Exception $e) { - die(json_encode([ - "status" => "error", - "sql" => $e->getMessage(), - "message" => "Error al cargar el archivo", - ])); - } -} -?> - "success", - "message" => "Horarios guardado con éxito", -]) ?> + $horario['materia'], + 'carrera' => $carrera, + ]; + $horario['materia'] = query("SELECT FI_MATERIA(:materia, :carrera) id", $params)['id']; + + $params = [ + 'clave' => $horario['clave'], + 'nombre' => $horario['nombre'], + 'correo' => $horario['correo'], + 'grado' => $horario['grado'], + 'facultad' => $facultad, + ]; + + $horario['profesor'] = query("SELECT FI_PROFESOR(:nombre, :clave, :facultad, :correo, :grado) id", $params)['id']; + $horario = array_diff_key($horario, array_flip(['clave', 'nombre', 'correo', 'grado', ''])); + $horario['periodo'] = $periodo; + $horario['facultad'] = $facultad; + + try { + query( + "SELECT FI_HORARIO(:horario::VARCHAR, :profesor::INT, :materia::INT, :facultad::INT, :periodo::INT, :grupo::VARCHAR, :salon::VARCHAR)", + $horario + ); + } catch (Exception $e) { + die(json_encode([ + "status" => "error", + "sql" => $e->getMessage(), + "message" => "Error al cargar el archivo", + ])); + } +} +?> + "success", + "message" => "Horarios guardado con éxito", +]) ?> diff --git a/action/action_horario_profesor.php b/action/action_horario_profesor.php index 2f19c48..95f6b3a 100644 --- a/action/action_horario_profesor.php +++ b/action/action_horario_profesor.php @@ -1,38 +1,38 @@ -query("SELECT * FROM fs_horario(_periodo_id => ?, _last => true, _profesor_id => ?) ORDER BY MATERIA", [ - $_POST['periodo_id'], - $_POST['profesor_id'], - ]); - - $horarios = array_map(function ($horario) use ($dias, $db) { - $horario['profesores'] = array_map( - fn ($profesor) => - $db->where("id", $profesor)->getOne("fs_profesor"), - explode(",", substr($horario['profesores'], 1, -1)) - ); - $horario['dia'] = $dias[$horario['dia']]; - return $horario; - }, $horarios); - die(json_encode([ - "status" => "success", - "data" => $horarios, - // "data" => [], - ])); -} catch (Exception $e) { - die(json_encode([ - "status" => "error", - "message" => $e->getMessage(), - "query" => $db->getLastQuery(), - ])); -} +query("SELECT * FROM fs_horario(_periodo_id => ?, _last => true, _profesor_id => ?) ORDER BY MATERIA", [ + $_POST['periodo_id'], + $_POST['profesor_id'], + ]); + + $horarios = array_map(function ($horario) use ($dias, $db) { + $horario['profesores'] = array_map( + fn ($profesor) => + $db->where("id", $profesor)->getOne("fs_profesor"), + explode(",", substr($horario['profesores'], 1, -1)) + ); + $horario['dia'] = $dias[$horario['dia']]; + return $horario; + }, $horarios); + die(json_encode([ + "status" => "success", + "data" => $horarios, + // "data" => [], + ])); +} catch (Exception $e) { + die(json_encode([ + "status" => "error", + "message" => $e->getMessage(), + "query" => $db->getLastQuery(), + ])); +} diff --git a/action/action_horario_update.php b/action/action_horario_update.php index d42db3c..a55554a 100644 --- a/action/action_horario_update.php +++ b/action/action_horario_update.php @@ -1,48 +1,48 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); - -$horario = array_map(fn ($value) => $_POST[$value], array_filter([ - "hora" => "hora", - "dia" => "día", - "salon" => "salón", - "duracion" => "duración", -], fn ($value) => !empty($_POST[$value]))); - -if (!empty($_POST['profesores'])) - $horario["profesores"] = "{ {$_POST['profesores']} }"; - -try { - $id = $_POST['id'] ?? 0; - - $old = $db - ->where("horario_id", $id) - ->getOne("horario"); - - $horario = $db - ->where("id", $id) - ->update("fs_horario", $horario); - - $new = $db - ->orderBy("horario_id", "DESC") - ->getOne("horario"); - - $user->print_to_log("Actualización de horario", old: $old, new: $new); -} catch (Exception $e) { - die(json_encode([ - "status" => "error", - "message" => $e->getMessage(), - 'POST' => $_POST, - ])); -} - -die(json_encode([ - "status" => "success", -])); + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); + +$horario = array_map(fn ($value) => $_POST[$value], array_filter([ + "hora" => "hora", + "dia" => "día", + "salon" => "salón", + "duracion" => "duración", +], fn ($value) => !empty($_POST[$value]))); + +if (!empty($_POST['profesores'])) + $horario["profesores"] = "{ {$_POST['profesores']} }"; + +try { + $id = $_POST['id'] ?? 0; + + $old = $db + ->where("horario_id", $id) + ->getOne("horario"); + + $horario = $db + ->where("id", $id) + ->update("fs_horario", $horario); + + $new = $db + ->orderBy("horario_id", "DESC") + ->getOne("horario"); + + $user->print_to_log("Actualización de horario", old: $old, new: $new); +} catch (Exception $e) { + die(json_encode([ + "status" => "error", + "message" => $e->getMessage(), + 'POST' => $_POST, + ])); +} + +die(json_encode([ + "status" => "success", +])); diff --git a/action/action_justificar.php b/action/action_justificar.php index 89a6a06..2a42a89 100644 --- a/action/action_justificar.php +++ b/action/action_justificar.php @@ -1,33 +1,33 @@ - $clave, - 'hora' => $hora, - 'id' => $id - ]]; -} -foreach ($claves as $horario) - try { - $profesor_id = $horario["clave"]; - query("SELECT fi_registrar_asistencia(:id::INT, FALSE, ARRAY[ NOW(), :fecha::DATE + :hora::TIME ]::TIMESTAMP[], :profesor_id::INT, TRUE)", [ - ":fecha" => $fecha->format('Y-m-d'), - ":hora" => $horario["hora"], - ":id" => $horario["id"], - ":profesor_id" => $profesor_id - ]); - } - catch (Exception $e) { - die( json_encode(["error" => $e->getMessage()]) ); - } - -die(json_encode(["success" => true])); + $clave, + 'hora' => $hora, + 'id' => $id + ]]; +} +foreach ($claves as $horario) + try { + $profesor_id = $horario["clave"]; + query("SELECT fi_registrar_asistencia(:id::INT, FALSE, ARRAY[ NOW(), :fecha::DATE + :hora::TIME ]::TIMESTAMP[], :profesor_id::INT, TRUE)", [ + ":fecha" => $fecha->format('Y-m-d'), + ":hora" => $horario["hora"], + ":id" => $horario["id"], + ":profesor_id" => $profesor_id + ]); + } + catch (Exception $e) { + die( json_encode(["error" => $e->getMessage()]) ); + } + +die(json_encode(["success" => true])); diff --git a/action/action_login.php b/action/action_login.php index c18661d..f0dc374 100644 --- a/action/action_login.php +++ b/action/action_login.php @@ -1,43 +1,42 @@ -admin && ($access = $user->access('asistencia')) == 'n') - die(json_encode(['error' => true])); - -$user->print_to_log('Consultar materias'); -$materias = queryAll( - "SELECT id, nombre FROM FS_MATERIA WHERE carrera = COALESCE(:carrera, carrera) ORDER BY nombre", - [':carrera' => empty($carrera) ? null : $carrera] -); -?> - - 'success', - 'materias' => $materias, +admin && ($access = $user->access('asistencia')) == 'n') + die(json_encode(['error' => true])); + +$user->print_to_log('Consultar materias'); +$materias = queryAll( + "SELECT id, nombre FROM FS_MATERIA WHERE carrera = COALESCE(:carrera, carrera) ORDER BY nombre", + [':carrera' => empty($carrera) ? null : $carrera] +); +?> + + 'success', + 'materias' => $materias, ]); ?> \ No newline at end of file diff --git a/action/action_materias_select.php b/action/action_materias_select.php index be20f63..f0d56a9 100644 --- a/action/action_materias_select.php +++ b/action/action_materias_select.php @@ -1,8 +1,8 @@ - $_POST['idmateria']]; - echo json_encode(query($sql, $params, false)); + $_POST['idmateria']]; + echo json_encode(query($sql, $params, false)); ?> \ No newline at end of file diff --git a/action/action_materias_update.php b/action/action_materias_update.php index a98ca1f..19c4e8e 100644 --- a/action/action_materias_update.php +++ b/action/action_materias_update.php @@ -1,11 +1,11 @@ - mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"]); - $hecho = query($sql, $params, false); - header("Location: ../materias.php"); - exit(); + mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"]); + $hecho = query($sql, $params, false); + header("Location: ../materias.php"); + exit(); ?> \ No newline at end of file diff --git a/action/action_new_horario.php b/action/action_new_horario.php index f2c82e5..27e8b1b 100644 --- a/action/action_new_horario.php +++ b/action/action_new_horario.php @@ -1,17 +1,17 @@ - - - + + $_POST['fecha_inicial'], - ':fecha_fin' => $_POST['fecha_final'], - ':estado' => $_POST['estadoP'], - ':nombre' => mb_strtoupper($_POST['nombreP']), - ':nivel' => $_POST['nivelP'], - ':facultad' => $_POST['facultadP'] - ]; - echo json_encode(query($sql, $params, true)); - header("Location: ../carreras.php?facultad=".$_POST['facultadP']); - exit(); + $_POST['fecha_inicial'], + ':fecha_fin' => $_POST['fecha_final'], + ':estado' => $_POST['estadoP'], + ':nombre' => mb_strtoupper($_POST['nombreP']), + ':nivel' => $_POST['nivelP'], + ':facultad' => $_POST['facultadP'] + ]; + echo json_encode(query($sql, $params, true)); + header("Location: ../carreras.php?facultad=".$_POST['facultadP']); + exit(); ?> \ No newline at end of file diff --git a/action/action_periodos_select.php b/action/action_periodos_select.php index 51e98bb..e6ca0a3 100644 --- a/action/action_periodos_select.php +++ b/action/action_periodos_select.php @@ -1,8 +1,8 @@ - $_POST['idfacultad'], ':idperiodo' => $_POST['idperiodo']]; - echo json_encode(query($sql, $params, true)); + $_POST['idfacultad'], ':idperiodo' => $_POST['idperiodo']]; + echo json_encode(query($sql, $params, true)); ?> \ No newline at end of file diff --git a/action/action_periodos_update.php b/action/action_periodos_update.php index d374ef5..ad055d6 100644 --- a/action/action_periodos_update.php +++ b/action/action_periodos_update.php @@ -1,18 +1,18 @@ - $_POST['idP'], - ':fecha_inicio' => $_POST['fecha_inicial'], - ':fecha_final' => $_POST['fecha_final'], - ':estado' => $_POST['estadoP'], - ':nombre' => mb_strtoupper($_POST['nombreP']), - ':nivel' => $_POST['nivelP'] - ]; - echo json_encode(query($sql, $params, true)); - header("Location: ../carreras.php?facultad=".$_POST['facultadP']); - exit(); + $_POST['idP'], + ':fecha_inicio' => $_POST['fecha_inicial'], + ':fecha_final' => $_POST['fecha_final'], + ':estado' => $_POST['estadoP'], + ':nombre' => mb_strtoupper($_POST['nombreP']), + ':nivel' => $_POST['nivelP'] + ]; + echo json_encode(query($sql, $params, true)); + header("Location: ../carreras.php?facultad=".$_POST['facultadP']); + exit(); ?> \ No newline at end of file diff --git a/action/action_periodousuario_update.php b/action/action_periodousuario_update.php index 45dd256..279b774 100644 --- a/action/action_periodousuario_update.php +++ b/action/action_periodousuario_update.php @@ -1,27 +1,27 @@ - $user->user['id'], ':per' => $_POST['id']); -$user->print_to_log('Actualizando periodo from ' . $user->periodo . ' to ' . $_POST['id']); - -query("SELECT FU_UPDATEPERIODO(:id, :per)", $params); -$user->periodo = $params[':per']; - -# if the user is admin, also update the facultad in user object -if ($user->admin) { - $facultad = query("SELECT FACULTAD_ID id, FACULTAD f FROM FS_PERIODO WHERE ID = :id", [':id' => $user->periodo]); - $user->facultad = array( - 'facultad_id' => $facultad["id"], - 'facultad' => $facultad["f"], - ); -} - -$_SESSION['user'] = serialize($user); -header("Location: {$_POST["target"]}"); + $user->user['id'], ':per' => $_POST['id']); +$user->print_to_log('Actualizando periodo from ' . $user->periodo . ' to ' . $_POST['id']); + +query("SELECT FU_UPDATEPERIODO(:id, :per)", $params); +$user->periodo = $params[':per']; + +# if the user is admin, also update the facultad in user object +if ($user->admin) { + $facultad = query("SELECT FACULTAD_ID id, FACULTAD f FROM FS_PERIODO WHERE ID = :id", [':id' => $user->periodo]); + $user->facultad = array( + 'facultad_id' => $facultad["id"], + 'facultad' => $facultad["f"], + ); +} + +$_SESSION['user'] = serialize($user); +header("Location: {$_POST["target"]}"); diff --git a/action/action_permisos_update.php b/action/action_permisos_update.php index ee06b96..2ef88e5 100644 --- a/action/action_permisos_update.php +++ b/action/action_permisos_update.php @@ -1,40 +1,40 @@ -


"; - #print_r($ver); - #print_r($editar); - query("SELECT fd_permiso()", null, false); - foreach($ver as $lectura){ - $igual=false; - $ver_separado = explode("_", $lectura); - #print_r($ver_separado); - foreach($completo as $comp){ - if($ver_separado[0] == $comp[0] && $ver_separado[1] == $comp[1]){ - #echo " igual"; - $igual=true; - break; - } - } - #echo "
"; - if(!$igual) - $completo[]=$ver_separado; - } - #print_r($completo); - foreach($completo as $actual){ - $sql = "SELECT fi_permiso(:pagina, :rol, :tipo)"; - $params = [':pagina' => $actual['0'], ':rol' => $actual['1'], ':tipo' => $actual['2']]; - query($sql, $params, false); - } - header("Location: ../permisos.php"); - exit(); +


"; + #print_r($ver); + #print_r($editar); + query("SELECT fd_permiso()", null, false); + foreach($ver as $lectura){ + $igual=false; + $ver_separado = explode("_", $lectura); + #print_r($ver_separado); + foreach($completo as $comp){ + if($ver_separado[0] == $comp[0] && $ver_separado[1] == $comp[1]){ + #echo " igual"; + $igual=true; + break; + } + } + #echo "
"; + if(!$igual) + $completo[]=$ver_separado; + } + #print_r($completo); + foreach($completo as $actual){ + $sql = "SELECT fi_permiso(:pagina, :rol, :tipo)"; + $params = [':pagina' => $actual['0'], ':rol' => $actual['1'], ':tipo' => $actual['2']]; + query($sql, $params, false); + } + header("Location: ../permisos.php"); + exit(); ?> \ No newline at end of file diff --git a/action/action_profesor.php b/action/action_profesor.php index 19f54af..e5746d2 100644 --- a/action/action_profesor.php +++ b/action/action_profesor.php @@ -1,14 +1,14 @@ -where("facultad_id", $facultad ?? 0) - ->get("fs_profesor"); - -echo json_encode([ - "status" => "success", - "profesores" => $profesores +where("facultad_id", $facultad ?? 0) + ->get("fs_profesor"); + +echo json_encode([ + "status" => "success", + "profesores" => $profesores ]); \ No newline at end of file diff --git a/action/action_profesor_faltas.php b/action/action_profesor_faltas.php index dbbff61..e43cb3d 100644 --- a/action/action_profesor_faltas.php +++ b/action/action_profesor_faltas.php @@ -1,40 +1,40 @@ - '22:00' ? '22:00' : $hora_fin) + 1800); - -die(json_encode( - array_map(fn ($row) => array_merge( - $db->where('id', $row['profesor_id'])->getOne('fs_profesor'), - $db->where('id', $row['materia_id'])->getOne('fs_materia'), - $row - ), - queryAll( - "SELECT REPORTE.* - FROM fs_asistencia_profesorreporte(null, :periodo, null, :fecha, :fecha) AS REPORTE - JOIN PROFESOR P ON P.PROFESOR_ID = REPORTE.PROFESOR_ID - WHERE HORA_CHECADO IS NULL - AND HORA BETWEEN :inicio AND :fin - AND P.PROFESOR_CLAVE ILIKE COALESCE(:clave, P.PROFESOR_CLAVE) and UNACCENT(P.PROFESOR_NOMBRE) ILIKE UNACCENT(COALESCE(:nombre, P.PROFESOR_NOMBRE)) - AND FECHA = :fecha - ORDER BY HORA, MATERIA", - [ - 'periodo' => $periodo, - 'fecha' => $fecha, - 'inicio' => $hora_inicio, - 'fin' => $hora_fin, - 'clave' => empty($clave) ? null : "%$clave%", - 'nombre' => empty($nombre) ? null : "%$nombre%" - ] -)))); - - + '22:00' ? '22:00' : $hora_fin) + 1800); + +die(json_encode( + array_map(fn ($row) => array_merge( + $db->where('id', $row['profesor_id'])->getOne('fs_profesor'), + $db->where('id', $row['materia_id'])->getOne('fs_materia'), + $row + ), + queryAll( + "SELECT REPORTE.* + FROM fs_asistencia_profesorreporte(null, :periodo, null, :fecha, :fecha) AS REPORTE + JOIN PROFESOR P ON P.PROFESOR_ID = REPORTE.PROFESOR_ID + WHERE HORA_CHECADO IS NULL + AND HORA BETWEEN :inicio AND :fin + AND P.PROFESOR_CLAVE ILIKE COALESCE(:clave, P.PROFESOR_CLAVE) and UNACCENT(P.PROFESOR_NOMBRE) ILIKE UNACCENT(COALESCE(:nombre, P.PROFESOR_NOMBRE)) + AND FECHA = :fecha + ORDER BY HORA, MATERIA", + [ + 'periodo' => $periodo, + 'fecha' => $fecha, + 'inicio' => $hora_inicio, + 'fin' => $hora_fin, + 'clave' => empty($clave) ? null : "%$clave%", + 'nombre' => empty($nombre) ? null : "%$nombre%" + ] +)))); + + #ECHO "$hora_inicio - $hora_fin"; \ No newline at end of file diff --git a/action/action_profesores_borra.php b/action/action_profesores_borra.php index bdbe096..9dd9927 100644 --- a/action/action_profesores_borra.php +++ b/action/action_profesores_borra.php @@ -1,7 +1,7 @@ - $_POST['id_profesor'], ':idfacultad' => $_POST['id_facultad'], ':estado' => $_POST['estado']]; - echo json_encode(query($sql, $params, false)); + $_POST['id_profesor'], ':idfacultad' => $_POST['id_facultad'], ':estado' => $_POST['estado']]; + echo json_encode(query($sql, $params, false)); ?> \ No newline at end of file diff --git a/action/action_profesores_insert.php b/action/action_profesores_insert.php index b67d3f1..9d26501 100644 --- a/action/action_profesores_insert.php +++ b/action/action_profesores_insert.php @@ -1,75 +1,75 @@ - FILTER_FLAG_STRIP_LOW))); - if(isset($_POST["dlfacultad"])) - $facultad = trim(filter_input(INPUT_POST, "dlfacultad", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - else - $facultad = trim(filter_input(INPUT_POST, "mfacultad", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - $clave = trim(filter_input(INPUT_POST, "mclave", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - $grado = trim(filter_input(INPUT_POST, "grado", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - $nombre = trim(filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - $grado = mb_strtoupper($grado); - if(!empty($grado)){ - if(!ctype_space($grado)){ - if($grado[strlen($grado)-1] != '.') - $grado.='.'; - } - else{ - $grado=""; - } - } - $fs_profesores = query(//revisar si existe la clave del profesor - "SELECT * FROM fs_profesor WHERE clave = :clave", - array(":clave" => $_POST["mclave"]), - true - ); - if(!$fs_profesores){//hay que crearlo desde 0 (profesor) y agregarlo a su facultad(facultad_profesor) - $profesor_id = query( - "SELECT public.fi_profesor( - :nombre, - :clave, - :facultad, - null, - :grado - )", - array(":nombre" => mb_strtoupper($nombre), ":clave" => $clave, ":facultad" => $facultad, ":grado" => $grado), - true - ); - header("Location: ../profesores.php"); - exit(); - } - else{//el profesor ya existe - $profac = query( - "SELECT * FROM facultad_profesor WHERE facultad_id = :facultad AND profesor_id = :profesor", - array(":facultad" => $facultad, ":profesor" => $fs_profesores["id"]), - true - ); - if(!$profac){//agregarlo a la facultad (facultad_profesor) - query( - "SELECT fi_facultad_profesor( - :facultad, - :profesor - )", - array(":facultad" => $facultad, ":profesor" => $fs_profesores["id"]), - true - ); - header("Location: ../profesores.php"); - exit(); - } - else{//regresar error (ya existe este profesor en esta facultad) - //print_r($profac); - if(!$profac['fp_activo']){ - query( - "SELECT fu_estado_facultad_profesor(:idprofesor, :idfacultad, :estado)", - array(":idprofesor" => $fs_profesores["id"], ":idfacultad" => $facultad, ":estado" => true), - true - ); - header("Location: ../profesores.php"); - exit(); - } - header("Location: ../profesores.php?error=1"); - #exit(); - } - } + FILTER_FLAG_STRIP_LOW))); + if(isset($_POST["dlfacultad"])) + $facultad = trim(filter_input(INPUT_POST, "dlfacultad", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); + else + $facultad = trim(filter_input(INPUT_POST, "mfacultad", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); + $clave = trim(filter_input(INPUT_POST, "mclave", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); + $grado = trim(filter_input(INPUT_POST, "grado", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); + $nombre = trim(filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); + $grado = mb_strtoupper($grado); + if(!empty($grado)){ + if(!ctype_space($grado)){ + if($grado[strlen($grado)-1] != '.') + $grado.='.'; + } + else{ + $grado=""; + } + } + $fs_profesores = query(//revisar si existe la clave del profesor + "SELECT * FROM fs_profesor WHERE clave = :clave", + array(":clave" => $_POST["mclave"]), + true + ); + if(!$fs_profesores){//hay que crearlo desde 0 (profesor) y agregarlo a su facultad(facultad_profesor) + $profesor_id = query( + "SELECT public.fi_profesor( + :nombre, + :clave, + :facultad, + null, + :grado + )", + array(":nombre" => mb_strtoupper($nombre), ":clave" => $clave, ":facultad" => $facultad, ":grado" => $grado), + true + ); + header("Location: ../profesores.php"); + exit(); + } + else{//el profesor ya existe + $profac = query( + "SELECT * FROM facultad_profesor WHERE facultad_id = :facultad AND profesor_id = :profesor", + array(":facultad" => $facultad, ":profesor" => $fs_profesores["id"]), + true + ); + if(!$profac){//agregarlo a la facultad (facultad_profesor) + query( + "SELECT fi_facultad_profesor( + :facultad, + :profesor + )", + array(":facultad" => $facultad, ":profesor" => $fs_profesores["id"]), + true + ); + header("Location: ../profesores.php"); + exit(); + } + else{//regresar error (ya existe este profesor en esta facultad) + //print_r($profac); + if(!$profac['fp_activo']){ + query( + "SELECT fu_estado_facultad_profesor(:idprofesor, :idfacultad, :estado)", + array(":idprofesor" => $fs_profesores["id"], ":idfacultad" => $facultad, ":estado" => true), + true + ); + header("Location: ../profesores.php"); + exit(); + } + header("Location: ../profesores.php?error=1"); + #exit(); + } + } ?> \ No newline at end of file diff --git a/action/action_profesores_select.php b/action/action_profesores_select.php index 55f449f..6443e89 100644 --- a/action/action_profesores_select.php +++ b/action/action_profesores_select.php @@ -1,10 +1,10 @@ - $_POST['profesor']]; - -echo json_encode(query($sql, $params, false)); + $_POST['profesor']]; + +echo json_encode(query($sql, $params, false)); diff --git a/action/action_profesores_update.php b/action/action_profesores_update.php index 58d9e5c..c55a54f 100644 --- a/action/action_profesores_update.php +++ b/action/action_profesores_update.php @@ -1,36 +1,36 @@ - $_POST["mclave"]), - true - ); - if($profesor){ - if($profesor['profesor_id'] != $_POST['id']){ - echo "clave en uso"; - header("Location: ../profesores.php?error=2"); - exit(); - } - } - $grado = $_POST['grado']; - $grado = mb_strtoupper($grado); - if(!empty($grado)){ - if(!ctype_space($grado)){ - if($grado[strlen($grado)-1] != '.') - $grado.='.'; - } - else{ - $grado=""; - } - } - print_r($_POST); - $sql = "SELECT public.fu_updateprofesor(:id, :clave, :nombre, :grado)"; - $params = array(':id' => $_POST["id"], ':clave' => $_POST["mclave"], ':nombre' => mb_strtoupper($_POST["nombre"]), ':grado' => $grado); - $hecho = query($sql, $params, false); - - header("Location: ../profesores.php", true, 307); - exit(); + $_POST["mclave"]), + true + ); + if($profesor){ + if($profesor['profesor_id'] != $_POST['id']){ + echo "clave en uso"; + header("Location: ../profesores.php?error=2"); + exit(); + } + } + $grado = $_POST['grado']; + $grado = mb_strtoupper($grado); + if(!empty($grado)){ + if(!ctype_space($grado)){ + if($grado[strlen($grado)-1] != '.') + $grado.='.'; + } + else{ + $grado=""; + } + } + print_r($_POST); + $sql = "SELECT public.fu_updateprofesor(:id, :clave, :nombre, :grado)"; + $params = array(':id' => $_POST["id"], ':clave' => $_POST["mclave"], ':nombre' => mb_strtoupper($_POST["nombre"]), ':grado' => $grado); + $hecho = query($sql, $params, false); + + header("Location: ../profesores.php", true, 307); + exit(); ?> \ No newline at end of file diff --git a/action/action_reposiciones.php b/action/action_reposiciones.php index 75a402e..5c672da 100644 --- a/action/action_reposiciones.php +++ b/action/action_reposiciones.php @@ -1,54 +1,54 @@ - 'No se ha iniciado sesión'])); - -$user = unserialize($_SESSION['user']); -$ruta = "../"; -require_once "../include/bd_pdo.php"; - -// if method is get -header("Content-Type: application/json"); -if ($_SERVER['REQUEST_METHOD'] === 'GET') { - $user->print_to_log("Acceso a reposiciones"); - $reposiciones = $db - ->where('periodo_id', $_GET['periodo_id'] ?? null) - ->where('profesor_id', $_GET['profesor_id'] ?? []) - ->get("reposicion"); - echo json_encode([ - 'status' => 'success', - 'reposiciones' => $reposiciones - ]); -} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { - $user->print_to_log("Creación de reposición", new: $params); - try { - $requiredParams = ['horario_id', 'fecha', 'hora', 'duracion_id', 'descripcion', 'profesor_id', 'salon', 'unidad', 'periodo_id', 'fecha_clase']; - - // Filter params based on requiredParams - $params = array_filter($_POST, function ($key) use ($requiredParams) { - return in_array($key, $requiredParams); - }, ARRAY_FILTER_USE_KEY); - - // Check if all required params are present - if (count($params) !== count($requiredParams)) { - throw new Exception('Falta uno o más parámetros requeridos'); - } - - $db->insert("reposicion", $params); - - // Return success response - echo json_encode([ - "status" => "success", - "message" => "Reposición creada correctamente", - ]); - } catch (Exception $e) { - // Return error response - echo json_encode([ - "status" => "error", - "message" => "No se pudo crear la reposición", - "error" => $e->getMessage(), - ]); - } -} + 'No se ha iniciado sesión'])); + +$user = unserialize($_SESSION['user']); +$ruta = "../"; +require_once "../include/bd_pdo.php"; + +// if method is get +header("Content-Type: application/json"); +if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $user->print_to_log("Acceso a reposiciones"); + $reposiciones = $db + ->where('periodo_id', $_GET['periodo_id'] ?? null) + ->where('profesor_id', $_GET['profesor_id'] ?? []) + ->get("reposicion"); + echo json_encode([ + 'status' => 'success', + 'reposiciones' => $reposiciones + ]); +} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { + $user->print_to_log("Creación de reposición", new: $params); + try { + $requiredParams = ['horario_id', 'fecha', 'hora', 'duracion_id', 'descripcion', 'profesor_id', 'salon', 'unidad', 'periodo_id', 'fecha_clase']; + + // Filter params based on requiredParams + $params = array_filter($_POST, function ($key) use ($requiredParams) { + return in_array($key, $requiredParams); + }, ARRAY_FILTER_USE_KEY); + + // Check if all required params are present + if (count($params) !== count($requiredParams)) { + throw new Exception('Falta uno o más parámetros requeridos'); + } + + $db->insert("reposicion", $params); + + // Return success response + echo json_encode([ + "status" => "success", + "message" => "Reposición creada correctamente", + ]); + } catch (Exception $e) { + // Return error response + echo json_encode([ + "status" => "error", + "message" => "No se pudo crear la reposición", + "error" => $e->getMessage(), + ]); + } +} diff --git a/action/action_revisar_excel.php b/action/action_revisar_excel.php index 95facb2..1b66f89 100644 --- a/action/action_revisar_excel.php +++ b/action/action_revisar_excel.php @@ -1,50 +1,50 @@ -setReadDataOnly(true); - -$file = $_FILES['archivo']; - - -$spreadsheet = $reader->load($file['tmp_name'][0]); - -$data = []; - -try { - - foreach_sheet( - $spreadsheet, // object $spreadsheet - function (array $row_data, int $i, string $sheet) { - global $horario, $data; - - if (renglón_vacío($row_data)) return; - validar_registro($row_data, $i); - - $horario["horario"] = horario($row_data, $i, $sheet); - - foreach (array_filter($row_data) as $key => $value) - $horario = array_merge($horario, ($key == 'maestro') ? columna_nombre($value) : [$key => $value]); - - $data[] = $horario; - } - ); - - die(json_encode([ - "status" => "success", - "message" => "Horario revisado con éxito, se leyeron: " . count($data) . " registros", - "data" => $data - ])); -} catch (Exception $e) { - die(json_encode([ - "status" => "error", - "message" => $e->getMessage(), - ])); -} +setReadDataOnly(true); + +$file = $_FILES['archivo']; + + +$spreadsheet = $reader->load($file['tmp_name'][0]); + +$data = []; + +try { + + foreach_sheet( + $spreadsheet, // object $spreadsheet + function (array $row_data, int $i, string $sheet) { + global $horario, $data; + + if (renglón_vacío($row_data)) return; + validar_registro($row_data, $i); + + $horario["horario"] = horario($row_data, $i, $sheet); + + foreach (array_filter($row_data) as $key => $value) + $horario = array_merge($horario, ($key == 'maestro') ? columna_nombre($value) : [$key => $value]); + + $data[] = $horario; + } + ); + + die(json_encode([ + "status" => "success", + "message" => "Horario revisado con éxito, se leyeron: " . count($data) . " registros", + "data" => $data + ])); +} catch (Exception $e) { + die(json_encode([ + "status" => "error", + "message" => $e->getMessage(), + ])); +} diff --git a/action/action_roles_insert.php b/action/action_roles_insert.php index f470515..a9ad636 100644 --- a/action/action_roles_insert.php +++ b/action/action_roles_insert.php @@ -1,11 +1,11 @@ - mb_strtoupper($_POST['mtitulo'])]; - $hecho = query($sql, $params, true); - header("Location: ../roles.php"); - exit(); + mb_strtoupper($_POST['mtitulo'])]; + $hecho = query($sql, $params, true); + header("Location: ../roles.php"); + exit(); ?> \ No newline at end of file diff --git a/action/action_roles_select.php b/action/action_roles_select.php index 19ebc3f..6ac2266 100644 --- a/action/action_roles_select.php +++ b/action/action_roles_select.php @@ -1,11 +1,11 @@ - $_POST['rol']]; - - echo json_encode( query($sql, $params, true)); + $_POST['rol']]; + + echo json_encode( query($sql, $params, true)); ?> \ No newline at end of file diff --git a/action/action_roles_update.php b/action/action_roles_update.php index b02b239..479f048 100644 --- a/action/action_roles_update.php +++ b/action/action_roles_update.php @@ -1,11 +1,11 @@ - mb_strtoupper($_POST['mtitulo']), ':id' => $_POST['id']); - print_r($_POST); - $hecho = query($sql, $params, false); - header("Location: ../roles.php", true, 307); - exit(); + mb_strtoupper($_POST['mtitulo']), ':id' => $_POST['id']); + print_r($_POST); + $hecho = query($sql, $params, false); + header("Location: ../roles.php", true, 307); + exit(); ?> \ No newline at end of file diff --git a/action/action_tiempos_update.php b/action/action_tiempos_update.php index a642b42..2407d95 100644 --- a/action/action_tiempos_update.php +++ b/action/action_tiempos_update.php @@ -1,37 +1,37 @@ - $_POST['facultadT']], true -); - -if($fs_tiempo){ - $sql = "SELECT fu_update_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; - $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 1, ':antes' => -1*$_POST['antesL'], ':despues' => $_POST['despuesL']+1, ':retardo' => $_POST['retardoL']+$_POST['despuesL']+1]; -} -else{ - $sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; - $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 1, ':antes' => -1*$_POST['antesL'], ':despues' => $_POST['despuesL']+1, ':retardo' => $_POST['retardoL']+$_POST['despuesL']+1]; -} -query($sql, $params, false); - - -$fs_tiempo2 = query( - "SELECT * FROM fs_tiempo_checado(:facultad, 2)", [':facultad' => $_POST['facultadT']], true -); - -if($fs_tiempo2){ - $sql = "SELECT fu_update_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; - $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 2, ':antes' => -1*$_POST['antesP'], ':despues' => $_POST['despuesP']+1, ':retardo' => $_POST['retardoP']+$_POST['despuesP']+1]; -} -else{ - $sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; - $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 2, ':antes' => -1*$_POST['antesP'], ':despues' => $_POST['despuesP']+1, ':retardo' => $_POST['retardoP']+$_POST['despuesP']+1]; -} -query($sql, $params, false); - -header("Location: ../carreras.php?facultad=".$_POST['facultadT']); -exit(); + $_POST['facultadT']], true +); + +if($fs_tiempo){ + $sql = "SELECT fu_update_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; + $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 1, ':antes' => -1*$_POST['antesL'], ':despues' => $_POST['despuesL']+1, ':retardo' => $_POST['retardoL']+$_POST['despuesL']+1]; +} +else{ + $sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; + $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 1, ':antes' => -1*$_POST['antesL'], ':despues' => $_POST['despuesL']+1, ':retardo' => $_POST['retardoL']+$_POST['despuesL']+1]; +} +query($sql, $params, false); + + +$fs_tiempo2 = query( + "SELECT * FROM fs_tiempo_checado(:facultad, 2)", [':facultad' => $_POST['facultadT']], true +); + +if($fs_tiempo2){ + $sql = "SELECT fu_update_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; + $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 2, ':antes' => -1*$_POST['antesP'], ':despues' => $_POST['despuesP']+1, ':retardo' => $_POST['retardoP']+$_POST['despuesP']+1]; +} +else{ + $sql = "SELECT fi_tiempo_checado(:idfacultad, :idnivel, :antes, :despues, :retardo)"; + $params = [':idfacultad' => $_POST['facultadT'], ':idnivel' => 2, ':antes' => -1*$_POST['antesP'], ':despues' => $_POST['despuesP']+1, ':retardo' => $_POST['retardoP']+$_POST['despuesP']+1]; +} +query($sql, $params, false); + +header("Location: ../carreras.php?facultad=".$_POST['facultadT']); +exit(); ?> \ No newline at end of file diff --git a/action/action_usuario.php b/action/action_usuario.php index 6d40f4f..fcef3f2 100644 --- a/action/action_usuario.php +++ b/action/action_usuario.php @@ -1,22 +1,22 @@ - $facultades[$i]["id"]) - ); -} - -echo json_encode($facultades); + $facultades[$i]["id"]) + ); +} + +echo json_encode($facultades); diff --git a/action/action_usuarios_insert.php b/action/action_usuarios_insert.php index 85d1c98..4d6c5a4 100644 --- a/action/action_usuarios_insert.php +++ b/action/action_usuarios_insert.php @@ -1,22 +1,22 @@ - $_POST['mclave']], true); - if(!$hecho){ - $sql = "SELECT fi_usuario(:nombre, :correo, :clave, :rol, :facultad)"; - $params = [':nombre' => mb_strtoupper($_POST['mnombre']), ':correo' => $_POST['mcorreo'], ':clave' => $_POST['mclave'], ':rol' => $_POST['mrol'], ':facultad' => $facultad]; - $hecho = query($sql, $params, true); - header("Location: ../usuarios.php", true, 307); - exit(); - } - else{ - header("Location: ../usuarios.php?error=1"); - exit(); - } + $_POST['mclave']], true); + if(!$hecho){ + $sql = "SELECT fi_usuario(:nombre, :correo, :clave, :rol, :facultad)"; + $params = [':nombre' => mb_strtoupper($_POST['mnombre']), ':correo' => $_POST['mcorreo'], ':clave' => $_POST['mclave'], ':rol' => $_POST['mrol'], ':facultad' => $facultad]; + $hecho = query($sql, $params, true); + header("Location: ../usuarios.php", true, 307); + exit(); + } + else{ + header("Location: ../usuarios.php?error=1"); + exit(); + } ?> \ No newline at end of file diff --git a/action/action_usuarios_select.php b/action/action_usuarios_select.php index 9ce0674..aabbd20 100644 --- a/action/action_usuarios_select.php +++ b/action/action_usuarios_select.php @@ -1,8 +1,8 @@ - $_POST['usuario']]; - echo json_encode(query($sql, $params, true)); + $_POST['usuario']]; + echo json_encode(query($sql, $params, true)); ?> \ No newline at end of file diff --git a/action/action_usuarios_update.php b/action/action_usuarios_update.php index 7406baa..7f843a9 100644 --- a/action/action_usuarios_update.php +++ b/action/action_usuarios_update.php @@ -1,15 +1,15 @@ - $_POST['id'], ':nombre' => mb_strtoupper($_POST['mnombre']), ':correo' => $_POST['mcorreo'], ':clave' => $_POST['mclave'], ':rol' => $_POST['mrol'], ':facultad' => $facultad); - #print_r($_POST); - $hecho = query($sql, $params, false); - header("Location: ../usuarios.php", true, 307); - exit(); + $_POST['id'], ':nombre' => mb_strtoupper($_POST['mnombre']), ':correo' => $_POST['mcorreo'], ':clave' => $_POST['mclave'], ':rol' => $_POST['mrol'], ':facultad' => $facultad); + #print_r($_POST); + $hecho = query($sql, $params, false); + header("Location: ../usuarios.php", true, 307); + exit(); ?> \ No newline at end of file diff --git a/action/carrera_find.php b/action/carrera_find.php index 4ae02cc..e18bb10 100644 --- a/action/carrera_find.php +++ b/action/carrera_find.php @@ -1,10 +1,10 @@ - $_POST['fac_id']]; - -echo json_encode(query($sql, $params, false)); + $_POST['fac_id']]; + +echo json_encode(query($sql, $params, false)); ?> \ No newline at end of file diff --git a/action/force_session.php b/action/force_session.php index 5902baa..781fa82 100644 --- a/action/force_session.php +++ b/action/force_session.php @@ -1,37 +1,37 @@ - $usuario]); -// die(json_encode($user)); - -$facultad = [ - "facultad_id" => $user["facultad"], - "facultad" => $user["facultad_nombre"] -]; - -$rol = [ - "rol_id" => $user["rol"], - "rol" => $user["titulo"] -]; - -$admin = false; - -$periodo = $user["periodo"]; - -$user = [ - "id" => $user["id"], - "nombre" => $user["username"] -]; - -$user = new Login($user, $facultad, $rol, $admin, $periodo); -if (isset($_SESSION)) - session_start(); -$_SESSION['user'] = serialize($user); - -header("Location: ../main.php"); + $usuario]); +// die(json_encode($user)); + +$facultad = [ + "facultad_id" => $user["facultad"], + "facultad" => $user["facultad_nombre"] +]; + +$rol = [ + "rol_id" => $user["rol"], + "rol" => $user["titulo"] +]; + +$admin = false; + +$periodo = $user["periodo"]; + +$user = [ + "id" => $user["id"], + "nombre" => $user["username"] +]; + +$user = new Login($user, $facultad, $rol, $admin, $periodo); +if (isset($_SESSION)) + session_start(); +$_SESSION['user'] = serialize($user); + +header("Location: ../main.php"); exit; \ No newline at end of file diff --git a/action/registro_supervisor.php b/action/registro_supervisor.php index 0b8eb8b..b279381 100644 --- a/action/registro_supervisor.php +++ b/action/registro_supervisor.php @@ -1,60 +1,60 @@ - [ - 'profesor_id', - 'horario_id', - 'estado', - 'comentario', - 'supervisor_id', - ], -]); -#output rutas: [ ...ruta, salones: [{...salon}] ] -header('Content-Type: application/json charset=utf-8'); -#return html -$ruta = "../"; -require_once "../class/c_login.php"; -// check method -try { - if ($_SERVER['REQUEST_METHOD'] === 'POST') { - // check parameters - $raw = file_get_contents('php://input'); - $post_data = json_decode($raw, true); - // if it's a list - // step 1: get subrutas - if (empty($post_data)) { - http_response_code(400); - echo json_encode(['error' => 'No hay clases pendientes']); - exit; - } - - $data = $db->query( - 'INSERT INTO registro (profesor_id, horario_id, registro_fecha_supervisor, estado_supervisor_id, registro_fecha_ideal, supervisor_id, comentario) - VALUES' . - implode(',', array_map(fn($x) => "({$x['profesor_id']} , {$x['horario_id']}, NOW()," . (is_null($x['estado']) ? 'null' : $x['estado']) . ", NOW(), {$x['supervisor_id']}," . (empty($x['comentario']) ? 'null' : "'{$x['comentario']}'") . ')', $post_data)) - . ' ON CONFLICT (profesor_id, horario_id, registro_fecha_ideal) DO UPDATE SET estado_supervisor_id = EXCLUDED.estado_supervisor_id, registro_fecha_supervisor = NOW(), comentario = EXCLUDED.comentario - RETURNING *' - ); - echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } else { - http_response_code(405); - echo json_encode(['error' => 'method not allowed']); - exit; - - } - -} catch (PDOException $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - 'query' => $db->getLastQuery(), - 'post_data' => $post_data, - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; -} catch (Exception $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; + [ + 'profesor_id', + 'horario_id', + 'estado', + 'comentario', + 'supervisor_id', + ], +]); +#output rutas: [ ...ruta, salones: [{...salon}] ] +header('Content-Type: application/json charset=utf-8'); +#return html +$ruta = "../"; +require_once "../class/c_login.php"; +// check method +try { + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // check parameters + $raw = file_get_contents('php://input'); + $post_data = json_decode($raw, true); + // if it's a list + // step 1: get subrutas + if (empty($post_data)) { + http_response_code(400); + echo json_encode(['error' => 'No hay clases pendientes']); + exit; + } + + $data = $db->query( + 'INSERT INTO registro (profesor_id, horario_id, registro_fecha_supervisor, estado_supervisor_id, registro_fecha_ideal, supervisor_id, comentario) + VALUES' . + implode(',', array_map(fn($x) => "({$x['profesor_id']} , {$x['horario_id']}, NOW()," . (is_null($x['estado']) ? 'null' : $x['estado']) . ", NOW(), {$x['supervisor_id']}," . (empty($x['comentario']) ? 'null' : "'{$x['comentario']}'") . ')', $post_data)) + . ' ON CONFLICT (profesor_id, horario_id, registro_fecha_ideal) DO UPDATE SET estado_supervisor_id = EXCLUDED.estado_supervisor_id, registro_fecha_supervisor = NOW(), comentario = EXCLUDED.comentario, supervisor_id = EXCLUDED.supervisor_id + RETURNING *' + ); + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } else { + http_response_code(405); + echo json_encode(['error' => 'method not allowed']); + exit; + + } + +} catch (PDOException $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + 'query' => $db->getLastQuery(), + 'post_data' => $post_data, + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} catch (Exception $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; } \ No newline at end of file diff --git a/action/rutas.php b/action/rutas.php index de052f7..debe75f 100644 --- a/action/rutas.php +++ b/action/rutas.php @@ -1,28 +1,28 @@ -where('salon', 'UNIVERSIDAD LA SALLE', 'ILIKE') - ->getOne('salon_view'); - -$rutas = - array_map( - function (&$ruta) use ($db) { - $ruta['subrutas'] = - $db - ->where('id_espacio_padre', $ruta['id_espacio_sgu']) - ->orderBy('salon') - ->get('salon_view'); - return $ruta; - - }, - $db - ->where('id_espacio_padre', $universidad_la_salle['id_espacio_sgu']) - ->orderBy('salon') - ->get('salon_view') - ); - -// echo json_encode($universidad_la_salle, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); EXIT; +where('salon', 'UNIVERSIDAD LA SALLE', 'ILIKE') + ->getOne('salon_view'); + +$rutas = + array_map( + function ($ruta) use ($db) { + $ruta['subrutas'] = + $db + ->where('id_espacio_padre', $ruta['id_espacio_sgu']) + ->orderBy('salon') + ->get('salon_view'); + return $ruta; + + }, + $db + ->where('id_espacio_padre', $universidad_la_salle['id_espacio_sgu']) + ->orderBy('salon') + ->get('salon_view') + ); + +// echo json_encode($universidad_la_salle, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); EXIT; echo json_encode($rutas, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); \ No newline at end of file diff --git a/action/rutas_salón_horario.php b/action/rutas_salón_horario.php index e376af1..96b00fb 100644 --- a/action/rutas_salón_horario.php +++ b/action/rutas_salón_horario.php @@ -1,73 +1,73 @@ - [ - 'id_espacio_sgu', - 'bloque_horario_id', - ], -]; -#output rutas: [ ...ruta, salones: [{...salon}] ] -header('Content-Type: application/json charset=utf-8'); -$ruta = "../"; -require_once "../class/c_login.php"; -// check method -try { - if ($_SERVER['REQUEST_METHOD'] === 'GET') { - // check parameters - array_walk($information['GET'], function ($value) { - if (!array_key_exists($value, $_GET)) { - http_response_code(400); - echo json_encode(['error' => "$value is required"]); - exit; - } - }); - // step 1: get subrutas - $data = $db - ->where('tiene_salones') - ->where("{$_GET['id_espacio_sgu']} = ANY(id_espacio_sgu_array)") - ->get('salon_view'); - - // step 3: get horarios - $data = array_map( - fn($ruta) => array_merge( - [ - 'horarios' => $db - ->join('periodo', 'periodo.periodo_id = horario_view.periodo_id') - ->join('bloque_horario', '(bloque_horario.hora_inicio, bloque_horario.hora_fin) OVERLAPS (horario_view.horario_hora, horario_view.horario_hora + horario_view.duracion)') - ->join('salon_view', 'salon_view.salon_id = horario_view.salon_id') - ->join('horario_profesor', 'horario_profesor.horario_id = horario_view.horario_id') - ->join('profesor', 'profesor.profesor_id = horario_profesor.profesor_id') - ->join('registro', '(registro.profesor_id, registro.horario_id, registro.registro_fecha_ideal) = (profesor.profesor_id, horario_view.horario_id, CURRENT_DATE)', 'LEFT') - ->where('CURRENT_DATE BETWEEN periodo.periodo_fecha_inicio AND periodo.periodo_fecha_fin') - ->where('horario_dia = EXTRACT(DOW FROM CURRENT_DATE)') - ->where('bloque_horario.id', $_GET['bloque_horario_id']) - ->where('id_espacio_padre', $ruta['id_espacio_sgu']) - ->get('horario_view', null, '*, horario_view.horario_id, profesor.profesor_id'), - ], - $ruta - ), - $data - ); - - echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } else { - http_response_code(405); - echo json_encode(['error' => 'method not allowed']); - exit; - - } - -} catch (PDOException $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - 'query' => $db->getLastQuery(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; -} catch (Exception $th) { - http_response_code(500); - echo json_encode([ - 'error' => $th->getMessage(), - ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - exit; + [ + 'id_espacio_sgu', + 'bloque_horario_id', + ], +]; +#output rutas: [ ...ruta, salones: [{...salon}] ] +header('Content-Type: application/json charset=utf-8'); +$ruta = "../"; +require_once "../class/c_login.php"; +// check method +try { + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + // check parameters + array_walk($information['GET'], function ($value) { + if (!array_key_exists($value, $_GET)) { + http_response_code(400); + echo json_encode(['error' => "$value is required"]); + exit; + } + }); + // step 1: get subrutas + $data = $db + ->where('tiene_salones') + ->where("{$_GET['id_espacio_sgu']} = ANY(id_espacio_sgu_array)") + ->get('salon_view'); + + // step 3: get horarios + $data = array_map( + fn($ruta) => array_merge( + [ + 'horarios' => $db + ->join('periodo', 'periodo.periodo_id = horario_view.periodo_id') + ->join('bloque_horario', '(bloque_horario.hora_inicio, bloque_horario.hora_fin) OVERLAPS (horario_view.horario_hora, horario_view.horario_hora + horario_view.duracion)') + ->join('salon_view', 'salon_view.salon_id = horario_view.salon_id') + ->join('horario_profesor', 'horario_profesor.horario_id = horario_view.horario_id') + ->join('profesor', 'profesor.profesor_id = horario_profesor.profesor_id') + ->join('registro', '(registro.profesor_id, registro.horario_id, registro.registro_fecha_ideal) = (profesor.profesor_id, horario_view.horario_id, CURRENT_DATE)', 'LEFT') + ->where('CURRENT_DATE BETWEEN periodo.periodo_fecha_inicio AND periodo.periodo_fecha_fin') + ->where('horario_dia = EXTRACT(DOW FROM CURRENT_DATE)') + ->where('bloque_horario.id', $_GET['bloque_horario_id']) + ->where('id_espacio_padre', $ruta['id_espacio_sgu']) + ->get('horario_view', null, '*, horario_view.horario_id, profesor.profesor_id'), + ], + $ruta + ), + $data + ); + + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + } else { + http_response_code(405); + echo json_encode(['error' => 'method not allowed']); + exit; + + } + +} catch (PDOException $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + 'query' => $db->getLastQuery(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} catch (Exception $th) { + http_response_code(500); + echo json_encode([ + 'error' => $th->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; } \ No newline at end of file diff --git a/action/schemas/registro_supervisor.json b/action/schemas/registro_supervisor.json index 90571c2..de0de0e 100644 --- a/action/schemas/registro_supervisor.json +++ b/action/schemas/registro_supervisor.json @@ -1,24 +1,24 @@ -{ - "type": "array", - "items": { - "type": "object", - "properties": { - "profesor_id": { - "type": "integer" - }, - "horario_id": { - "type": "integer" - }, - "estado": { - "type": ["integer", "null"] - }, - "comentario": { - "type": "string" - }, - "supervisor_id": { - "type": "integer" - } - }, - "required": ["profesor_id", "horario_id", "comentario", "supervisor_id"] - } -} +{ + "type": "array", + "items": { + "type": "object", + "properties": { + "profesor_id": { + "type": "integer" + }, + "horario_id": { + "type": "integer" + }, + "estado": { + "type": ["integer", "null"] + }, + "comentario": { + "type": "string" + }, + "supervisor_id": { + "type": "integer" + } + }, + "required": ["profesor_id", "horario_id", "comentario", "supervisor_id"] + } +} diff --git a/action/usuario_find.php b/action/usuario_find.php index 61cae9c..ed94c98 100644 --- a/action/usuario_find.php +++ b/action/usuario_find.php @@ -1,26 +1,26 @@ - $nombre, ':clave' => $clave, ':facultad' => $facultad]; - -echo json_encode(query($sql, $params, false)); + $nombre, ':clave' => $clave, ':facultad' => $facultad]; + +echo json_encode(query($sql, $params, false)); ?> \ No newline at end of file diff --git a/alta_de_horario.php b/alta_de_horario.php index c72a868..82e9116 100644 --- a/alta_de_horario.php +++ b/alta_de_horario.php @@ -1,286 +1,286 @@ -access(); -if (!$user->admin && in_array($user->acceso, ['r', 'n'])) - die(header('Location: main.php?error=1')); - -$user->print_to_log('Consultar: Alta de horario'); -?> - - - - - Cargar horario desde Excel | <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - -
-
-
- -
-
-
- -
-
-
- where('id', $user->periodo)->getOne('fs_periodo'); - $carreras = $db - ->where('nivel', $periodo['nivel_id']) - ->where('facultad', $user->facultad['facultad_id']) - ->orderBy('carrera') - ->get('fs_carrera'); - ?> -
- - -
-
-
Seleccionar carrera
- -
    - -
  • - -
  • - -
- -
-
- -
- -
- -
- -
-
- -
- - - - -
-
-
- -
-
- - - - - - - - - - - - - - - +access(); +if (!$user->admin && in_array($user->acceso, ['r', 'n'])) + die(header('Location: main.php?error=1')); + +$user->print_to_log('Consultar: Alta de horario'); +?> + + + + + Cargar horario desde Excel | <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+ where('id', $user->periodo)->getOne('fs_periodo'); + $carreras = $db + ->where('nivel', $periodo['nivel_id']) + ->where('facultad', $user->facultad['facultad_id']) + ->orderBy('carrera') + ->get('fs_carrera'); + ?> +
+ + +
+
+
Seleccionar carrera
+ +
    + +
  • + +
  • + +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auditoría.php b/auditoría.php index ea78891..9912ee1 100644 --- a/auditoría.php +++ b/auditoría.php @@ -1,377 +1,422 @@ - - - - - - - Supervisor - - - - - - - -
-
-
-
- -
-
-
Selecciona una facultad
- -
    -
  • - Todas las facultades -
  • -
  • - ( {{facultad.clave_dependencia}} ) {{ facultad.facultad_nombre }} -
  • -
- -
-
-
-
- -
-
- -
-
-
-
- -
-
- -
-
- -
-
-
-
- -
-
- - -
- - -
-
-
- -
-
-
-
Selecciona un estado de asistencia
- -
    -
  • - Todos los registros -
  • -
  • - {{estado.nombre}} -
  • -
- -
-
-
-
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Fecha - SalónProfesorHorarioRegistroSupervisor
No hay clases en este horario
{{ registro.registro_fecha_ideal }} - {{ registro.salon }} -
- {{ registro.profesor_clave }} - {{ registro.profesor_nombre }} -
-
- -
-
{{ registro.horario_hora.slice(0,5) }} - {{ - registro.horario_fin.slice(0,5) }} -
-
- Registro {{ registro.registro_fecha.slice(11,16) }} -
-
-
- -
- -
-
- Sin registro -
-
-
-
-
-
-
- {{ registro.usuario_nombre }} -
-
- Hora - {{ registro.registro_fecha_supervisor.slice(11,19) }} -
-
- - - {{ registro.nombre }} - -
-
- -
-
- Observaciones: - {{registro.comentario.slice(0, - 25)}}{{registro.comentario.length > 10 ? '...' : ''}} -
-
- - -
-
- -
-
- Sin registro -
-
-
-
-
- - - - -
- - - - - - - - + + + + + + + Supervisor + + + + + + + +
+
+ +
+
+ +
+
+
Selecciona una facultad
+ +
    +
  • + Todas las facultades +
  • +
  • + ( {{facultad.clave_dependencia}} ) {{ facultad.facultad_nombre }} +
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ {{ store.bloques_horario.data.find(bloque => bloque.selected).hora_inicio.substr(0,5) + }} - + {{ store.bloques_horario.data.find(bloque => bloque.selected).hora_fin.substr(0,5) }} +
+ +
    +
  • + Mañana +
  • + +
  • + {{ bloque.hora_inicio.substr(0,5) }} - {{ bloque.hora_fin.substr(0,5) }} +
  • +
  • + Tarde +
  • +
  • + {{ bloque.hora_inicio.substr(0,5) }} - {{ bloque.hora_fin.substr(0,5) }} +
  • + +
+ +
+
+
+
+ +
+
+ + +
+ + +
+
+
+ +
+
+
+
Selecciona un estado de asistencia
+ +
    +
  • + Todos los registros +
  • +
  • + {{estado.nombre}} +
  • +
+ +
+
+
+
+
+ +
+
+ + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Fecha + SalónProfesorHorarioRegistroSupervisor
No hay clases en este horario
{{ registro.registro_fecha_ideal }} + {{ registro.salon }} +
+ {{ registro.profesor_clave }} + {{ registro.profesor_nombre }} +
+
+ +
+
{{ registro.horario_hora.slice(0,5) }} - {{ + registro.horario_fin.slice(0,5) }} +
+
+ Registro {{ registro.registro_fecha.slice(11,16) }} +
+
+
+ +
+ +
+
+ Sin registro +
+
+
+
+
+
+
+ {{ registro.usuario_nombre }} +
+
+ Hora + {{ registro.registro_fecha_supervisor.slice(11,19) }} +
+
+ + + {{ registro.nombre }} + +
+
+ +
+
+ Observaciones: + {{registro.comentario.slice(0, + 25)}}{{registro.comentario.length > 10 ? '...' : ''}} +
+
+ + +
+
+ +
+
+ Sin registro +
+
+
+
+
+ + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/avisos.php b/avisos.php index 43e55ac..20f7af2 100644 --- a/avisos.php +++ b/avisos.php @@ -1,265 +1,265 @@ -access(); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Avisos'); -} -$fac = $user->facultad['facultad_id']; -if($user->admin){ - $fac = null; -} -$limit = 20; -if(isset($_POST['filter_fecha']) && $_POST['filter_fecha'] != ""){ - $filter_fecha = $_POST['filter_fecha']; -} -else{ - $filter_fecha = null; -} -if(isset($_GET['pag'])){ - $pag = $_GET['pag'] - 1; -}else{ - $pag = 0; -} -if($user->admin){ - $count = query("SELECT count(1) FROM fs_aviso(null, :fecha, :facultad_id, null, 0, null)", [':fecha' => $filter_fecha, ':facultad_id' => $fac], true); - $fs_avisos = query("SELECT * FROM fs_aviso(null, :fecha, :facultad_id, :limite, :offset, null)", [':fecha' => $filter_fecha, ':facultad_id' => $fac, ':limite' => $limit, ':offset' => $pag * $limit], false); -}else{ - $count = query("SELECT count(1) FROM fs_aviso(null, :fecha, :facultad_id, null, 0, true)", [':fecha' => $filter_fecha, ':facultad_id' => $fac], true); - $fs_avisos = query("SELECT * FROM fs_aviso(null, :fecha, :facultad_id, :limite, :offset, true)", [':fecha' => $filter_fecha, ':facultad_id' => $fac, ':limite' => $limit, ':offset' => $pag * $limit], false); -} -$paginas = ceil($count['count'] / $limit); -?> - - - - - - - Avisos - - - - - - - access(); - ?> -
- acceso == 'w') {?> - - - -
-
-
-
-
- -
- -
-
-

Se muestran los avisos posteriores a la fecha

-
-
-
- - -
-
-
-
-
-
- -
-
- - - - - acceso == 'w') {?> - - - - - acceso == 'w') {?> - - - - - - = $aviso['aviso_fecha_inicial'] && $today <= $aviso['aviso_fecha_final']){ - $color = 'success'; - $title = 'En tiempo'; - $icono = 'reloj'; - }else if($today < $aviso['aviso_fecha_inicial']){ - $color = 'warning'; - $title = 'Antes de tiempo'; - } - if($aviso['aviso_estado'] == true){ - $color2 = 'success'; - $title2 = 'Activo'; - } - $day = explode("-", $aviso['aviso_fecha_inicial']); - $dia_inicial = $day['2'].'/'.$day['1'].'/'.$day[0]; - $day = explode("-", $aviso['aviso_fecha_final']); - $dia_final = $day['2'].'/'.$day['1'].'/'.$day[0]; - ?> - - - acceso == 'w') {?> - - - - - acceso == 'w') {?> - - - - - -
EstadoFacultadFechasMensajeAcciones
admin){ ?> - - - - - -
-
-
- -
- - - acceso == 'w') {?> - - - - - - - - - - - +access(); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Avisos'); +} +$fac = $user->facultad['facultad_id']; +if($user->admin){ + $fac = null; +} +$limit = 20; +if(isset($_POST['filter_fecha']) && $_POST['filter_fecha'] != ""){ + $filter_fecha = $_POST['filter_fecha']; +} +else{ + $filter_fecha = null; +} +if(isset($_GET['pag'])){ + $pag = $_GET['pag'] - 1; +}else{ + $pag = 0; +} +if($user->admin){ + $count = query("SELECT count(1) FROM fs_aviso(null, :fecha, :facultad_id, null, 0, null)", [':fecha' => $filter_fecha, ':facultad_id' => $fac], true); + $fs_avisos = query("SELECT * FROM fs_aviso(null, :fecha, :facultad_id, :limite, :offset, null)", [':fecha' => $filter_fecha, ':facultad_id' => $fac, ':limite' => $limit, ':offset' => $pag * $limit], false); +}else{ + $count = query("SELECT count(1) FROM fs_aviso(null, :fecha, :facultad_id, null, 0, true)", [':fecha' => $filter_fecha, ':facultad_id' => $fac], true); + $fs_avisos = query("SELECT * FROM fs_aviso(null, :fecha, :facultad_id, :limite, :offset, true)", [':fecha' => $filter_fecha, ':facultad_id' => $fac, ':limite' => $limit, ':offset' => $pag * $limit], false); +} +$paginas = ceil($count['count'] / $limit); +?> + + + + + + + Avisos + + + + + + + access(); + ?> +
+ acceso == 'w') {?> + + + +
+
+
+
+
+ +
+ +
+
+

Se muestran los avisos posteriores a la fecha

+
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + acceso == 'w') {?> + + + + + acceso == 'w') {?> + + + + + + = $aviso['aviso_fecha_inicial'] && $today <= $aviso['aviso_fecha_final']){ + $color = 'success'; + $title = 'En tiempo'; + $icono = 'reloj'; + }else if($today < $aviso['aviso_fecha_inicial']){ + $color = 'warning'; + $title = 'Antes de tiempo'; + } + if($aviso['aviso_estado'] == true){ + $color2 = 'success'; + $title2 = 'Activo'; + } + $day = explode("-", $aviso['aviso_fecha_inicial']); + $dia_inicial = $day['2'].'/'.$day['1'].'/'.$day[0]; + $day = explode("-", $aviso['aviso_fecha_final']); + $dia_final = $day['2'].'/'.$day['1'].'/'.$day[0]; + ?> + + + acceso == 'w') {?> + + + + + acceso == 'w') {?> + + + + + +
EstadoFacultadFechasMensajeAcciones
admin){ ?> - + + + + +
+
+
+ +
+ + + acceso == 'w') {?> + + + + + + + + + + + \ No newline at end of file diff --git a/avisos_crear.php b/avisos_crear.php index 1afb195..6381973 100644 --- a/avisos_crear.php +++ b/avisos_crear.php @@ -1,435 +1,435 @@ -access('Avisos'); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Avisos Crear'); -} -$fac = $user->facultad['facultad_id']; -if($user->admin){ - $fac = null; -} -$fs_carreras = query('SELECT * FROM fs_carreras(:fac, null, null)', [':fac' => $fac], false); -$fs_facultades = query('SELECT * FROM facultad WHERE facultad_activa = true', null, false); -?> - - - - - - - Avisos Crear - - - - - - - - - access('Avisos'); - ?> -
-
-
-
-
- admin){ ?> -
- -
-
-
Mostrar todas
- -
    - -
  • - -
- -
-
-
- - - -
- -
- -
No es una fecha valida
-
-
-
- -
- -
No es una fecha valida
-
-
-
- -
- -
No puede estar vacio
-
-
-
- -
-
- - -
-
-
-
- - -
-
-
-
No hay profesores para mandar el aviso
-
-

Carreras

-

Utiliza el botón para asignar las carreras que recibirán el aviso.

-
-
- -
-
-

-

-
-
-
- -
-

Nombre de profesores

-

Utiliza el botón para asignar los profesores que recibirán el aviso.

-
-
- -
-
-

-

-
-
-
-
-
-
- - Cancelar -
-
-
-
-
-
- - - - - - - - - - - - - - - - - +access('Avisos'); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Avisos Crear'); +} +$fac = $user->facultad['facultad_id']; +if($user->admin){ + $fac = null; +} +$fs_carreras = query('SELECT * FROM fs_carreras(:fac, null, null)', [':fac' => $fac], false); +$fs_facultades = query('SELECT * FROM facultad WHERE facultad_activa = true', null, false); +?> + + + + + + + Avisos Crear + + + + + + + + + access('Avisos'); + ?> +
+
+
+
+
+ admin){ ?> +
+ +
+
+
Mostrar todas
+ +
    + +
  • + +
+ +
+
+
+ + + +
+ +
+ +
No es una fecha valida
+
+
+
+ +
+ +
No es una fecha valida
+
+
+
+ +
+ +
No puede estar vacio
+
+
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+
No hay profesores para mandar el aviso
+
+

Carreras

+

Utiliza el botón para asignar las carreras que recibirán el aviso.

+
+
+ +
+
+

+

+
+
+
+ +
+

Nombre de profesores

+

Utiliza el botón para asignar los profesores que recibirán el aviso.

+
+
+ +
+
+

+

+
+
+
+
+
+
+ + Cancelar +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/avisos_editar.php b/avisos_editar.php index be30dda..a2fa414 100644 --- a/avisos_editar.php +++ b/avisos_editar.php @@ -1,437 +1,437 @@ -access('Avisos'); -if (!$user->admin && $user->acceso == 'n') { - header('Location: main.php?error=1'); -} else { - $user->print_to_log('Avisos Editar'); -} -$fac = $user->facultad['facultad_id']; -if ($user->admin) { - $fac = null; -} -$fs_aviso = query('SELECT * FROM fs_aviso(:aviso_id, null, :facultad_id, null, 0, null)', [':aviso_id' => $_GET['id'], ':facultad_id' => $fac], true); -$fs_carreras = query('SELECT * FROM fs_carreras(:fac, null, null)', [':fac' => $fs_aviso['facultad_id']], false); -$fs_usr = query('SELECT * FROM fs_profesor_aviso(:aviso_id)', [':aviso_id' => $_GET['id']], false); -$today = date('Y-m-d'); -$edit = $today < $fs_aviso['aviso_fecha_inicial']; -?> - - - - - - - Avisos Crear - - - - - - - - - access('Avisos'); - ?> -
-
-
-
- -
-
- -
- - "> -
No es una fecha valida
- -
- -
- -
-
-
- -
- "> -
No es una fecha valida
-
-
-
- -
- - - -

- -
-
- -
- -
-
- - -
-
-
-
- - -
-
-
-
No hay profesores para mandar el aviso
-
-

Carreras

-

Utiliza el botón para asignar las carreras que recibirán el aviso.

-
-
- -
-
-

-

-
-
-
- -
-

Nombre de profesores

-

Utiliza el botón para asignar los profesores que recibirán el aviso.

-
-
- -
-
-

-

-
-
-
-
- -

Profesores que recibirán el aviso

-
-
-
-
    - " . $fs_usr[$i]['profesor_nombre'] . ""; - } ?> -
-
-
-
-
-
    - " . $fs_usr[$i]['profesor_nombre'] . ""; - } ?> -
-
-
-
- -
-
- - Cancelar -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - +access('Avisos'); +if (!$user->admin && $user->acceso == 'n') { + header('Location: main.php?error=1'); +} else { + $user->print_to_log('Avisos Editar'); +} +$fac = $user->facultad['facultad_id']; +if ($user->admin) { + $fac = null; +} +$fs_aviso = query('SELECT * FROM fs_aviso(:aviso_id, null, :facultad_id, null, 0, null)', [':aviso_id' => $_GET['id'], ':facultad_id' => $fac], true); +$fs_carreras = query('SELECT * FROM fs_carreras(:fac, null, null)', [':fac' => $fs_aviso['facultad_id']], false); +$fs_usr = query('SELECT * FROM fs_profesor_aviso(:aviso_id)', [':aviso_id' => $_GET['id']], false); +$today = date('Y-m-d'); +$edit = $today < $fs_aviso['aviso_fecha_inicial']; +?> + + + + + + + Avisos Crear + + + + + + + + + access('Avisos'); + ?> +
+
+
+
+ +
+
+ +
+ + "> +
No es una fecha valida
+ +
+ +
+ +
+
+
+ +
+ "> +
No es una fecha valida
+
+
+
+ +
+ + + +

+ +
+
+ +
+ +
+
+ + +
+
+
+
+ + +
+
+
+
No hay profesores para mandar el aviso
+
+

Carreras

+

Utiliza el botón para asignar las carreras que recibirán el aviso.

+
+
+ +
+
+

+

+
+
+
+ +
+

Nombre de profesores

+

Utiliza el botón para asignar los profesores que recibirán el aviso.

+
+
+ +
+
+

+

+
+
+
+
+ +

Profesores que recibirán el aviso

+
+
+
+
    + " . $fs_usr[$i]['profesor_nombre'] . ""; + } ?> +
+
+
+
+
+
    + " . $fs_usr[$i]['profesor_nombre'] . ""; + } ?> +
+
+
+
+ +
+
+ + Cancelar +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/base.php b/base.php index a7ac2aa..5c129fe 100644 --- a/base.php +++ b/base.php @@ -1,58 +1,58 @@ -access('usuarios'); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Base'); -} -$fac = $user->facultad['facultad_id'] ?? -1; -if($user->admin){ - $fac=null; -} -?> - - - - - - - Base - - - - - - -
-
- - - - - - - +access('usuarios'); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Base'); +} +$fac = $user->facultad['facultad_id'] ?? -1; +if($user->admin){ + $fac=null; +} +?> + + + + + + + Base + + + + + + +
+
+ + + + + + + \ No newline at end of file diff --git a/bypass.php b/bypass.php index 0a6db29..de9526a 100644 --- a/bypass.php +++ b/bypass.php @@ -1,139 +1,139 @@ - - - - - - - .: Administrador de checador :. - - - - - - - - - - - -
-
-
-
-

Iniciar sesión

-
-
-
-
-
-

Utiliza tu usuario y contraseña institucionales

-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
- -
-
-
-
Selecciona un usuario
- -
    - -
- -
-
-
-
- -

¡ERROR!

- -
-

- -

-
-
-
- - - - - - - - - - - - + + + + + + + .: Administrador de checador :. + + + + + + + + + + + +
+
+
+
+

Iniciar sesión

+
+
+
+
+
+

Utiliza tu usuario y contraseña institucionales

+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+ +
+
+
+
Selecciona un usuario
+ +
    + +
+ +
+
+
+
+ +

¡ERROR!

+ +
+

+ +

+
+
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/carreras.php b/carreras.php index a5f8e5e..427932d 100644 --- a/carreras.php +++ b/carreras.php @@ -1,813 +1,813 @@ -access('facultades'); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Carreras'); -} -if(!$user->admin && $user->facultad['facultad_id']!=$_GET['facultad']){ - header('Location: carreras.php?facultad='.$user->facultad['facultad_id']); - $mal=true; -} -$mal=false; -?> - - - - - - - Carreras - - - - - - - - $_GET['facultad']), true); - $fs_carreras = query( - "SELECT * FROM fs_carreras(:idfacultad, null, null)", - array(':idfacultad' => $_GET['facultad']), - single:false - ); - } - include "import/html_header.php"; - html_header( - "CARRERAS | " . $facultad['facultad_nombre'], - "Gestión de Checador " - ); - $user->access('facultades'); - - - $fs_niveles = query( - "SELECT * FROM nivel", null, false - ); - - $fs_periodos = query( - "SELECT * FROM fs_periodos(:idfacultad) WHERE estado = 'Activo' ", - array(':idfacultad' => $_GET['facultad']), - false - ); - - $fs_tiempoLic = query( - "SELECT * FROM fs_tiempo_checado(:idfacultad, 1)", - array(':idfacultad' => $_GET['facultad']), - true - ); - $fs_tiempoPos = query( - "SELECT * FROM fs_tiempo_checado(:idfacultad, 2)", - array(':idfacultad' => $_GET['facultad']), - true - ); - ?> -
- -
- -
- -
- -
- - -
-
- acceso == 'w') {?> -
- -
- -
- -
-
- - - - - - - - - acceso == 'w') {?> - - - - - - - - - - - - - acceso == 'w') {?> - - - - - -
EstadoNivelPeriodoInicioFinAcciones
- - - - - - - - - - - -
-
-
-
- -
-
- acceso == 'w') {?> -
- -
- -
- -
-
- - - - - - - acceso == 'w') {?> - - - - - - - - - - - acceso == 'w') {?> - - - - - -
EstadoNivelCarreraAcciones
- - - -
-
-
-
- -
-

Asigna los minutos de tolerancia antes y después del horario de clase

- -
- -

Licenciatura

-
-
- Antes - -
- Debe ser un numero mayor que 0 -
- min -
-
-
Hora de clase
-
-
- Despues - -
- Debe ser un numero mayor que 0 -
- min -
-
- Retardos - -
- Debe ser un numero mayor que 0 -
- min -
-
- ¿Tiene retardos?
-
- - -
-
-
-

-

Posgrado

-
-
- Antes - -
- Debe ser un numero mayor que 0 -
- min -
-
-
Hora de clase
-
-
- Despues - -
- Debe ser un numero mayor que 0 -
- min -
-
- Retardo - -
- Debe ser un numero mayor que 0 -
- min -
-
- ¿Tiene retardos?
-
- - -
-
-
-
-
-
-
- - -
-
-
-
-
- - - - - - - - - - - - - - - +access('facultades'); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Carreras'); +} +if(!$user->admin && $user->facultad['facultad_id']!=$_GET['facultad']){ + header('Location: carreras.php?facultad='.$user->facultad['facultad_id']); + $mal=true; +} +$mal=false; +?> + + + + + + + Carreras + + + + + + + + $_GET['facultad']), true); + $fs_carreras = query( + "SELECT * FROM fs_carreras(:idfacultad, null, null)", + array(':idfacultad' => $_GET['facultad']), + single:false + ); + } + include "import/html_header.php"; + html_header( + "CARRERAS | " . $facultad['facultad_nombre'], + "Gestión de Checador " + ); + $user->access('facultades'); + + + $fs_niveles = query( + "SELECT * FROM nivel", null, false + ); + + $fs_periodos = query( + "SELECT * FROM fs_periodos(:idfacultad) WHERE estado = 'Activo' ", + array(':idfacultad' => $_GET['facultad']), + false + ); + + $fs_tiempoLic = query( + "SELECT * FROM fs_tiempo_checado(:idfacultad, 1)", + array(':idfacultad' => $_GET['facultad']), + true + ); + $fs_tiempoPos = query( + "SELECT * FROM fs_tiempo_checado(:idfacultad, 2)", + array(':idfacultad' => $_GET['facultad']), + true + ); + ?> +
+ +
+ +
+ +
+ +
+ + +
+
+ acceso == 'w') {?> +
+ +
+ +
+ +
+
+ + + + + + + + + acceso == 'w') {?> + + + + + + + + + + + + + acceso == 'w') {?> + + + + + +
EstadoNivelPeriodoInicioFinAcciones
+ + + + + + + + + + + +
+
+
+
+ +
+
+ acceso == 'w') {?> +
+ +
+ +
+ +
+
+ + + + + + + acceso == 'w') {?> + + + + + + + + + + + acceso == 'w') {?> + + + + + +
EstadoNivelCarreraAcciones
+ + + +
+
+
+
+ +
+

Asigna los minutos de tolerancia antes y después del horario de clase

+ +
+ +

Licenciatura

+
+
+ Antes + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+
Hora de clase
+
+
+ Despues + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+ Retardos + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+ ¿Tiene retardos?
+
+ + +
+
+
+

+

Posgrado

+
+
+ Antes + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+
Hora de clase
+
+
+ Despues + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+ Retardo + +
+ Debe ser un numero mayor que 0 +
+ min +
+
+ ¿Tiene retardos?
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/class/c_logasistencia.php b/class/c_logasistencia.php index 009346c..c944c74 100644 --- a/class/c_logasistencia.php +++ b/class/c_logasistencia.php @@ -1,73 +1,73 @@ -month = date("m"); - $this->year = date("Y"); - $this->dir = ($ruta ?? '') . "log/"; - $this->updateFilename(); - } - - function setMes(string $mes) - { - $this->month = $mes; - $this->updateFilename(); - } - function setAno(string $ano) - { - $this->year = $ano; - $this->updateFilename(); - } - - private function updateFilename() - { - $this->file = "asistencias_" . $this->year . "_" . $this->month . ".log"; - } - private function cleanLog($text) - { //remueve || de los textos - return trim(str_ireplace("||", "", $text)); - } - - function appendLog($claveULSA, $nombre, $desc) - { - $filename = $this->dir . $this->file; - if (!file_exists($this->dir)) { - mkdir($this->dir, 0755, true); - } - if (file_exists($this->dir)) { - $data = date('Y-m-d H:i:s') . "||" . $this->cleanLog($claveULSA) . "||" . $this->cleanLog($desc) . "||" . $this->cleanLog($nombre) . "\n"; - /*echo*/ - file_put_contents($filename, $data, FILE_APPEND); - } - } - function getLog($mes = "", $ano = "") - { - if ($mes != "") $this->setMes($mes); - if ($ano != "") $this->setAno($ano); - $filename = $this->dir . $this->file; - if (file_exists($filename)) { - //return array_slice(file ($filename , FILE_SKIP_EMPTY_LINES) , -10); - $lines = file($filename, FILE_SKIP_EMPTY_LINES); - //echo "antes: ".count($lines); - if (count($lines) > MAX_LINES) { - $lines = array_slice($lines, MAX_LINES * (-1)); - } - //echo "despues: ".count($lines); - return $lines; - } else - return array(); - } -} +month = date("m"); + $this->year = date("Y"); + $this->dir = ($ruta ?? '') . "log/"; + $this->updateFilename(); + } + + function setMes(string $mes) + { + $this->month = $mes; + $this->updateFilename(); + } + function setAno(string $ano) + { + $this->year = $ano; + $this->updateFilename(); + } + + private function updateFilename() + { + $this->file = "asistencias_" . $this->year . "_" . $this->month . ".log"; + } + private function cleanLog($text) + { //remueve || de los textos + return trim(str_ireplace("||", "", $text)); + } + + function appendLog($claveULSA, $nombre, $desc) + { + $filename = $this->dir . $this->file; + if (!file_exists($this->dir)) { + mkdir($this->dir, 0755, true); + } + if (file_exists($this->dir)) { + $data = date('Y-m-d H:i:s') . "||" . $this->cleanLog($claveULSA) . "||" . $this->cleanLog($desc) . "||" . $this->cleanLog($nombre) . "\n"; + /*echo*/ + file_put_contents($filename, $data, FILE_APPEND); + } + } + function getLog($mes = "", $ano = "") + { + if ($mes != "") $this->setMes($mes); + if ($ano != "") $this->setAno($ano); + $filename = $this->dir . $this->file; + if (file_exists($filename)) { + //return array_slice(file ($filename , FILE_SKIP_EMPTY_LINES) , -10); + $lines = file($filename, FILE_SKIP_EMPTY_LINES); + //echo "antes: ".count($lines); + if (count($lines) > MAX_LINES) { + $lines = array_slice($lines, MAX_LINES * (-1)); + } + //echo "despues: ".count($lines); + return $lines; + } else + return array(); + } +} diff --git a/class/c_login.php b/class/c_login.php index c977e5e..3afac45 100644 --- a/class/c_login.php +++ b/class/c_login.php @@ -1,130 +1,143 @@ -appendLog($this->user["id"], $this->user["nombre"], $desc); - } - public function access(string $pagina = null): void - { - if ($this->admin) { - $this->acceso = "w"; - return; - } - - # print_r( $access ); - $this->acceso = query( - 'SELECT tipo FROM PERMISO_VIEW WHERE ID = :usr AND PAGINA_RUTA ILIKE :ruta', - array( - ':usr' => $this->user["id"], - ':ruta' => $pagina ?? substr(basename($_SERVER['PHP_SELF']), 0, -4) - ) - )["tipo"] ?? 'n'; - } - public function __toString(): string - { - return "Usuario: {$this->user["nombre"]} ({$this->user["id"]}), Es admin: {$this->admin}, supervisor: {$this->supervisor}, jefe carrera: {$this->jefe_carrera}, profesor: {$this->profesor}"; - } - private static function validaUsuario($user, $pass): bool - { - file_put_contents('php://stderr', $user); - if (in_array($user, ['ad017045']) and $pass == "admin") - return true; - $client = new nusoap_client('http://200.13.89.2/validacion.php?wsdl', 'wsdl'); - $client->getError() and die('Error al crear el cliente: ' . $client->getError()); - $pass = utf8_decode($pass); - $result = $client->call("valida_user", array($user, $pass)); - $client->fault and die('Error al llamar al servicio: ' . $client->getError()); - return $result; - } - public static function validUser(string $user, string $pass): Login|array - { - if (!Login::validaUsuario($user, $pass)) { - return [ - 'error' => true, - 'msg' => 'Error al autenticar usuario' - ]; - } - global $db; - - if ($db->has("FS_VALIDACLAVEULSA('$user')")) { - #die (Login::validaUsuario($user, $pass)); - $fs_validaclaveulsa = $db->querySingle( - 'SELECT * FROM FS_VALIDACLAVEULSA(?)', - [$user] - ); - - $user = array( - 'id' => $fs_validaclaveulsa["id"], - 'nombre' => $fs_validaclaveulsa["nombre"], - ); - $facultad = array( - 'facultad_id' => $fs_validaclaveulsa["facultad_id"], - 'facultad' => $fs_validaclaveulsa["facultad"], - ); - $rol = array( - 'id' => $fs_validaclaveulsa["rol_id"], - 'rol' => $fs_validaclaveulsa["rol"] - ); - $supervisor = $db - ->join('rol', 'rol.rol_id = usuario.rol_id') - ->where('usuario_id', $user["id"]) - ->where('rol.rol_titulo', 'Supervisor') - ->has('usuario'); - $jefe_carrera = $db->where('usuario_id', $user["id"])->has('usuario_carrera'); - - $admin = $fs_validaclaveulsa["is_admin"]; - $periodo = $fs_validaclaveulsa["periodo_id"]; - - return new Login($user, $facultad, $rol, $admin, $periodo, $supervisor, $jefe_carrera, false); - } else if ($db->where('profesor_clave', preg_replace('/^do0*/', '', $user))->has("profesor")) { - $profesor = $db->where('profesor_clave', preg_replace('/^do0*/', '', $user))->getOne("profesor"); - $user = array( - 'id' => $profesor["profesor_clave"], - 'nombre' => $profesor["profesor_nombre"], - ); - $facultad = $rol = array( - 'facultad_id' => null, - 'facultad' => 'Docente', - ); - - $supervisor = false; - $jefe_carrera = false; - $admin = false; - $periodo = null; - // CREATE A COOKIE FOR THE REST OF THE day for example: 23:00 then duration will be 1 hour - setcookie("profesor", $user["id"], strtotime('today midnight') + 86400, "/"); - return new Login($user, $facultad, $rol, $admin, $periodo, $supervisor, $jefe_carrera, true); - } else - return [ - 'error' => true, - 'msg' => 'Usuario no encontrado' - ]; - } - public static function log_out(): void - { - session_start(); - session_destroy(); - } +appendLog($this->user["id"], $this->user["nombre"], $desc); + } + public function access(string $pagina = null): void + { + + global $db; + + if ($this->admin) { + $this->acceso = "w"; + return; + } + + # print_r( $access ); + $this->acceso = $db->query( + 'SELECT tipo FROM PERMISO_VIEW WHERE ID = :usr AND PAGINA_RUTA ILIKE :ruta', + array( + ':usr' => $this->user["id"], + ':ruta' => $pagina ?? substr(basename($_SERVER['PHP_SELF']), 0, -4) + ) + )["tipo"] ?? 'n'; + } + public function __toString(): string + { + return "Usuario: {$this->user["nombre"]} ({$this->user["id"]}), Es admin: {$this->admin}, supervisor: {$this->supervisor}, jefe carrera: {$this->jefe_carrera}, profesor: {$this->profesor}"; + } + private static function validaUsuario($user, $pass): bool + { + file_put_contents('php://stderr', $user); + if ($user == 'ad017045' and $pass == "admin") + return true; + + $client = new nusoap_client('http://200.13.89.2/validacion.php?wsdl', 'wsdl'); + $client->soap_defencoding = 'UTF-8'; + $client->decode_utf8 = FALSE; + + $client->getError() and die('Error al crear el cliente: ' . $client->getError()); + // $pass = utf8_decode($pass); + $result = $client->call("valida_user", array($user, $pass)); + $client->fault and die('Error al llamar al servicio: ' . $client->getError()); + return $result; + } + public static function validUser(string $user, string $pass): Login|array + { + if (Login::validaUsuario($user, $pass) === false) { + return [ + 'error' => true, + 'msg' => 'Error al autenticar usuario' + ]; + } + global $db; + + if ($db->has("FS_VALIDACLAVEULSA('$user')")) { + #die (Login::validaUsuario($user, $pass)); + $fs_validaclaveulsa = $db->querySingle( + 'SELECT * FROM FS_VALIDACLAVEULSA(?)', + [$user] + ); + + $user = array( + 'id' => $fs_validaclaveulsa["id"], + 'nombre' => $fs_validaclaveulsa["nombre"], + 'clave' => $db->where('usuario_id', $fs_validaclaveulsa["id"])->getOne("usuario")["usuario_clave"] + ); + $facultad = array( + 'facultad_id' => $fs_validaclaveulsa["facultad_id"], + 'facultad' => $fs_validaclaveulsa["facultad"], + ); + $rol = array( + 'id' => $fs_validaclaveulsa["rol_id"], + 'rol' => $fs_validaclaveulsa["rol"] + ); + $supervisor = $db + ->join('rol', 'rol.rol_id = usuario.rol_id') + ->where('usuario_id', $user["id"]) + ->where('rol.rol_titulo', 'Supervisor') + ->has('usuario'); + $jefe_carrera = $db->where('usuario_id', $user["id"])->has('usuario_carrera'); + + $admin = $fs_validaclaveulsa["is_admin"]; + $periodo = $fs_validaclaveulsa["periodo_id"]; + + return new Login($user, $facultad, $rol, $admin, $periodo, $supervisor, $jefe_carrera, false); + } else if ($db->where('profesor_clave', preg_replace('/^do0*/', '', $user), 'ilike')->has("profesor")) { + $profesor = $db->where('profesor_clave', preg_replace('/^do0*/', '', $user), 'ilike')->getOne("profesor"); + $user = array( + 'id' => $profesor["profesor_clave"], + 'nombre' => $profesor["profesor_nombre"], + ); + $facultad = array( + 'facultad_id' => null, + 'facultad' => null, + ); + $rol = array( + 'id' => null, + 'rol' => 'Docente' + ); + + // CREATE A COOKIE FOR THE REST OF THE day for example: 23:00 then duration will be 1 hour + setcookie("profesor", $user["id"], strtotime('today midnight') + 86400, "/"); + return new Login($user, $facultad, $rol, admin: false, periodo: null, supervisor: false, jefe_carrera: false, profesor: true); + } else + return [ + 'error' => true, + 'msg' => 'Usuario no encontrado' + ]; + } + public static function log_out(): void + { + session_start(); + session_destroy(); + } } \ No newline at end of file diff --git a/class/c_menu.php b/class/c_menu.php index 6dde8b9..def768e 100644 --- a/class/c_menu.php +++ b/class/c_menu.php @@ -1,15 +1,15 @@ -conn = new Connection(); - } - - public function getMenu() { - $sql = "SELECT * FROM menu"; - $result = $this->conn->getConnection()->query($sql); - $this->menu = $result->fetchAll(); - return $this->menu; - } +conn = new Connection(); + } + + public function getMenu() { + $sql = "SELECT * FROM menu"; + $result = $this->conn->getConnection()->query($sql); + $this->menu = $result->fetchAll(); + return $this->menu; + } } \ No newline at end of file diff --git a/class/connection.php b/class/connection.php index 38ab3e9..6095d28 100644 --- a/class/connection.php +++ b/class/connection.php @@ -1,57 +1,57 @@ -conn = new PDO( - "pgsql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS, - array(PDO::ATTR_PERSISTENT => true) - ); - } - public function getConnection() { - return $this->conn; - } - - public function query() {} -} - -try { - $pdo = new PDO( - "pgsql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS, - array( - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_PERSISTENT => true - ) - ); -} catch (PDOException $e) { - print "Error!: " . $e->getMessage() . "
"; - die(); -} - -function SQL(string $sql, array $params = []) -{ - global $pdo; - $stmt = $pdo->prepare($sql); - foreach ($params as $key => $value) { - // bind Parameter - $stmt->bindParam($key, $value); - } - $stmt->execute($params); - return $stmt->fetchAll(); -} - -function filter_by(array $array, array $fields): array -{ - $result = []; - foreach ($array as $key => $value) { - $result[$key] = []; - foreach ($fields as $field) { - $result[$key][$field] = $value[$field]; - } - } - return $result; +conn = new PDO( + "pgsql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS, + array(PDO::ATTR_PERSISTENT => true) + ); + } + public function getConnection() { + return $this->conn; + } + + public function query() {} +} + +try { + $pdo = new PDO( + "pgsql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS, + array( + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_PERSISTENT => true + ) + ); +} catch (PDOException $e) { + print "Error!: " . $e->getMessage() . "
"; + die(); +} + +function SQL(string $sql, array $params = []) +{ + global $pdo; + $stmt = $pdo->prepare($sql); + foreach ($params as $key => $value) { + // bind Parameter + $stmt->bindParam($key, $value); + } + $stmt->execute($params); + return $stmt->fetchAll(); +} + +function filter_by(array $array, array $fields): array +{ + $result = []; + foreach ($array as $key => $value) { + $result[$key] = []; + foreach ($fields as $field) { + $result[$key][$field] = $value[$field]; + } + } + return $result; } \ No newline at end of file diff --git a/consultar_horario.php b/consultar_horario.php index 1b70d60..46b97d0 100644 --- a/consultar_horario.php +++ b/consultar_horario.php @@ -1,1613 +1,1613 @@ -access(); -if (!$user->admin && in_array($user->acceso, ['n'])) - die(header('Location: main.php?error=1')); - -$user->print_to_log('Consultar horario'); - -$write = $user->admin || in_array($user->acceso, ['w']); -// var_dump($user); -?> - - - - - Consultar horario | - <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - - - - - " ?> -
-
- - - -
-
-
- $user->facultad['facultad_id'], ":per" => $user->periodo], single: false); - // repliaction of the query in the database with database class - $nivel = $user->periodo ? $db->where('id', $user->periodo)->getOne('fs_periodo') : false; - - $carreras = $nivel ? $db - ->orderBy('carrera') - ->where('facultad', $nivel['facultad_id']) - ->where('nivel', $nivel['nivel_id']) - ->get('fs_carrera', 100, 'id, carrera') : []; - - ?> -
- -
-
-
Seleccionar carrera
- -
    - -
  • - -
  • - -
- -
-
-
- - - -
- -
-
-
Seleccionar grupo
- -
    -
- -
-
-
- -
- - - -
-
-
- -
- - - -
- - - - - - - - - - - - - -
HoraLunesMartesMiércolesJuevesViernesSábado
-
- - - - -
- - - - - - - - - - +access(); +if (!$user->admin && in_array($user->acceso, ['n'])) + die(header('Location: main.php?error=1')); + +$user->print_to_log('Consultar horario'); + +$write = $user->admin || in_array($user->acceso, ['w']); +// var_dump($user); +?> + + + + + Consultar horario | + <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + + + + + " ?> +
+
+ + + +
+
+
+ $user->facultad['facultad_id'], ":per" => $user->periodo], single: false); + // repliaction of the query in the database with database class + $nivel = $user->periodo ? $db->where('id', $user->periodo)->getOne('fs_periodo') : false; + + $carreras = $nivel ? $db + ->orderBy('carrera') + ->where('facultad', $nivel['facultad_id']) + ->where('nivel', $nivel['nivel_id']) + ->get('fs_carrera', 100, 'id, carrera') : []; + + ?> +
+ +
+
+
Seleccionar carrera
+ +
    + +
  • + +
  • + +
+ +
+
+
+ + + +
+ +
+
+
Seleccionar grupo
+ +
    +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+ + + + + + + + + + + + + +
HoraLunesMartesMiércolesJuevesViernesSábado
+
+ + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/css/checador.css b/css/checador.css index a1a1519..e54abd2 100644 --- a/css/checador.css +++ b/css/checador.css @@ -1,46 +1,46 @@ - -body { - font-family: 'indivisa-text'; - /*background-image: linear-gradient(rgba(0,29,104, 0.3), rgba(0,29,104, 0.3)), url('../imagenes/fondochecador.png');*/ - background-image: url('../imagenes/fondochecador.jpg'); - background-repeat: no-repeat; - background-attachment: fixed; - background-size: cover; - background-position: center; - height: 100%; - overflow: hidden; -} - -.hora{font-size: 4rem; border-right: 2px solid #d21034; line-height: 1.1; padding-bottom: 8px;} -.fecha{font-size: 1.9rem; line-height: 1.2em; } -.facultad{font-size: 1.5rem; font-weight: bold; color: #aaa;} -.checa-box{width:800px; min-height: 380px; -webkit-box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2); -moz-box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2); box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2);} - -h1, h2, h3 {letter-spacing: 1px; position: relative; color: #001e61;} -.subtitle:before{ content: ''; position: absolute; bottom: -8px; left: 0; width: 80px; display: block; background: #d21034; height: 3px; } - -.text-big{font-size:3.6rem;} -#list-result{font-size:1.15rem;} -#list-result li{margin:0.2em 0; border-bottom: 1px dashed #969696;} - -.text-clave{ outline: none; color: #b7b7b7 !important; background: transparent; border: 1px solid #dbdcdd; border-radius: 5px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; font-size: 12px; font-weight: 300; vertical-align: middle; text-align:center; padding: 10px 20px;} -.text-clave:focus{ color: #001d68 !important; border-color: #001d68;} -.sin-servicio, .text-clave{font-size:1.7rem;} -.aviso{ font-size:120%;} -.mensaje{ font-size: 7vh; } - -@media (max-width: 768px) { - .hora{ font-size: 3.2rem;} - .fecha{font-size: 1.4rem;} - .checa-box{width:100%;} - .text-big{font-size:3rem;} - .sin-servicio, .text-clave{font-size:1.2rem;} -} -@media (max-width: 576px) { - .hora{font-size: 2rem !important;} - .fecha, .titulo{font-size: 1rem;} - #logo{width: 75%;} - .facultad{font-size: 1.2rem} - .text-big{font-size:2.8rem;} - -} + +body { + font-family: 'indivisa-text'; + /*background-image: linear-gradient(rgba(0,29,104, 0.3), rgba(0,29,104, 0.3)), url('../imagenes/fondochecador.png');*/ + background-image: url('../imagenes/fondochecador.jpg'); + background-repeat: no-repeat; + background-attachment: fixed; + background-size: cover; + background-position: center; + height: 100%; + overflow: hidden; +} + +.hora{font-size: 4rem; border-right: 2px solid #d21034; line-height: 1.1; padding-bottom: 8px;} +.fecha{font-size: 1.9rem; line-height: 1.2em; } +.facultad{font-size: 1.5rem; font-weight: bold; color: #aaa;} +.checa-box{width:800px; min-height: 380px; -webkit-box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2); -moz-box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2); box-shadow: 0px 0px 5px 1px rgba(150,150,150,0.2);} + +h1, h2, h3 {letter-spacing: 1px; position: relative; color: #001e61;} +.subtitle:before{ content: ''; position: absolute; bottom: -8px; left: 0; width: 80px; display: block; background: #d21034; height: 3px; } + +.text-big{font-size:3.6rem;} +#list-result{font-size:1.15rem;} +#list-result li{margin:0.2em 0; border-bottom: 1px dashed #969696;} + +.text-clave{ outline: none; color: #b7b7b7 !important; background: transparent; border: 1px solid #dbdcdd; border-radius: 5px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; font-size: 12px; font-weight: 300; vertical-align: middle; text-align:center; padding: 10px 20px;} +.text-clave:focus{ color: #001d68 !important; border-color: #001d68;} +.sin-servicio, .text-clave{font-size:1.7rem;} +.aviso{ font-size:120%;} +.mensaje{ font-size: 7vh; } + +@media (max-width: 768px) { + .hora{ font-size: 3.2rem;} + .fecha{font-size: 1.4rem;} + .checa-box{width:100%;} + .text-big{font-size:3rem;} + .sin-servicio, .text-clave{font-size:1.2rem;} +} +@media (max-width: 576px) { + .hora{font-size: 2rem !important;} + .fecha, .titulo{font-size: 1rem;} + #logo{width: 75%;} + .facultad{font-size: 1.2rem} + .text-big{font-size:2.8rem;} + +} diff --git a/css/custominputfile.min.css b/css/custominputfile.min.css index 68593f7..d460119 100644 --- a/css/custominputfile.min.css +++ b/css/custominputfile.min.css @@ -1,10 +1,10 @@ -/* - jQuery Custom Input File Plugin - version 1.0 - Copyright 2014, Ángel Espro, www.aesolucionesweb.com.ar, - Licence : GNU General Public License - - Site: www.aesolucionesweb.com.ar/plugins/custom-input-file - - You must not remove these lines. Read gpl.txt for further legal information. -*/ +/* + jQuery Custom Input File Plugin - version 1.0 + Copyright 2014, Ángel Espro, www.aesolucionesweb.com.ar, + Licence : GNU General Public License + + Site: www.aesolucionesweb.com.ar/plugins/custom-input-file + + You must not remove these lines. Read gpl.txt for further legal information. +*/ .cif-file-picker{position:relative;width:380px;height:180px;padding:0;border:4px dashed rgba(0,0,0,.2);display:table-cell;vertical-align:middle;text-align:center;opacity:.5;box-sizing:border-box;-moz-box-sizing:border-box}.cif-icon-picker{background:url(cif-icons-20xy.png) 0 0 no-repeat;width:80px;height:60px;display:inline-block}.cif-file-picker h3{margin:0;font-size:20px;text-align:center}.cif-file-picker p{margin:0 0 10px 0;font-size:16px;text-align:center}.cif-file-picker:hover{opacity:1}.cif-file-picker.dragover:not(.inactive){border-color:#46be5e;opacity:1;box-shadow:0 0 50px rgba(0,0,0,.5)}.cif-file-picker.inactive{opacity:.2}.cif-file-picker.inactive.dragover{cursor:pointer}.cif-parent{position:relative;margin-bottom:10px}.foto-file-row .field-wr-int{position:relative}.cif-close{opacity:.5;text-indent:-100000px;width:14px;height:14px;cursor:default;color:#555;background:url(cif-icons-20xy.png) 0px -60px no-repeat}.cif-file-container.cif-type-image .cif-close{top:0px;left:0px;position:absolute}.cif-close:hover{opacity:1}.cif-file-container.cif-container-all-type .cif-file-row{margin:10px 0}.cif-file-container.cif-container-all-type .cif-parent{max-width:380px;box-sizing:border-box;-moz-box-sizing:border-box;padding:10px 10px 10px 30px;border:1px solid #dfdfdf;background:#F4F4F4}.cif-file-container.cif-container-all-type .cif-all-type{font-size:13px;line-height:16px}.cif-file-container.cif-container-all-type .cif-close{top:50%;margin-top:-7px;left:5px;position:absolute}.cif-file-container.cif-container-all-type .cif-file-size{opacity:.8}.cif-file-container.cif-container-image-type .cif-file-row{border-bottom:1px solid #f2f2f2;padding:20px 0}.cif-file-container.cif-container-image-type .cif-parent{padding-top:30px}.cif-file-container.cif-container-image-type .cif-close{top:5px}.cif-img{max-height:300px;max-width:380px}#cif-msg-wr{font-size:13px;position:fixed;z-index:10000;top:100px;right:20px;max-width:50%;padding:15px;background:#fff;border:1px solid #dfdfdf;box-shadow:3px 3px 6px rgba(0,0,0,.5)}#cif-msg-wr .cif-msg-close{opacity:.5;position:absolute;right:0;top:0;width:16px;height:16px;text-indent:-100000px;background:url(cif-icons-20xy.png) 0 -75px no-repeat}#cif-msg-wr .cif-msg-close:hover{opacity:1}.cif-msg-icon{padding:0 10px;font-size:8px}.cif-msg-icon-error{background:url(cif-icons-20xy.png) 0 -120px no-repeat}.cif-msg-icon-ok{background:url(cif-icons-20xy.png) 0 -100px no-repeat}.cf-progressbar-wr{position:fixed;top:0;left:0;background:rgba(0,0,0,.7);width:100%;height:100%;z-index:50000}.cf-progressbar{height:12px;position:absolute;top:50%;margin-top:-6px;left:50%;margin-left:-125px;width:250px;background:#dadada;padding:2px;box-sizing:border-box;border:1px solid #000}.cf-progressbar>span{display:block;height:100%;background:rgb(43,194,83);background-image:url(bg-progress-bar.png);position:relative;transition:width 200ms;overflow:hidden}.jcrop-holder .preview-pane{display:block;position:absolute;z-index:2000;top:00px;left:102%;padding:6px;border:1px rgba(0,0,0,.4) solid;background-color:white;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:1px 1px 5px 2px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 5px 2px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 5px 2px rgba(0, 0, 0, 0.2)}.preview-pane .preview-container{overflow:hidden} \ No newline at end of file diff --git a/css/richtext.css b/css/richtext.css index 9700b35..e36f6b7 100644 --- a/css/richtext.css +++ b/css/richtext.css @@ -1,190 +1,190 @@ -.richText { - position: relative; - border: 1px solid #D6D8D8; - background: #D6D8D8; - width: 100%; - border-radius: 0.25rem; -} - -.richText .richText-toolbar ul { - padding: 0 !important; - margin: 0 !important; - display: flex; - flex-wrap: wrap; - justify-content: left;/*center*/ -} - -.richText .richText-toolbar ul li { - list-style: none; -} - -.richText .richText-toolbar ul li a { - display: block; - padding: 0.25rem 0.5rem; - cursor: pointer; - -webkit-transition: color 0.4s; - -moz-transition: color 0.4s; - transition: color 0.4s; -} - -.richText .richText-toolbar ul li a:hover { - color: #001d68; -} - -.richText .richText-toolbar ul li a .fa, .richText .richText-toolbar ul li a .fas, .richText .richText-toolbar ul li a .far, .richText .richText-toolbar ul li a svg { - pointer-events: none; -} - -.richText .richText-toolbar ul li[data-disable="true"] { - opacity: 0.1; -} - -.richText .richText-toolbar ul li[data-disable="true"] a { - cursor: default; -} - -.richText .richText-toolbar ul li:not([data-disable="true"]).is-selected .richText-dropdown-outer { - display: block; -} - -.richText .richText-toolbar ul:after { - display: block; - content: ""; - clear: both; -} - -.richText .richText-toolbar:last-child { - font-size: 0.75rem; -} - -.richText .richText-toolbar:after { - display: block; - clear: both; - content: ""; -} - -.richText .richText-form select {cursor: pointer;} - -.richText .richText-editor { - padding: 0.5rem; - background-color: #FFFFFF; - height: 15rem; - outline: none; - overflow-y: scroll; - overflow-x: auto; -} - -.richText .richText-toolbar ul li a .richText-dropdown-outer { - display: none; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.3); - cursor: default; -} - -.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown { - position: relative; - z-index:10; - display: block; - margin: 3% auto 0 auto; - background-color: #D6D8D8; - border: 0.1rem solid #777777; - border-radius: 0.25rem; - padding: 0.75rem; - padding-top: 1.5rem; - max-width: 90%; - -webkit-box-shadow: 0 0 5px 0 #777777; - -moz-box-shadow: 0 0 5px 0 #777777; - box-shadow: 0 0 5px 0 #777777; -} - -.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown .richText-dropdown-close { - position: absolute; - top: 0.25rem; - right: 0.5rem; - color: #CE0E2D; - cursor: pointer; -} - -.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown .richText-dropdown-close:hover { - opacity: 0.5 -} - -.richText-form-item{ - position: relative; - display: flex; - flex-wrap: wrap; - align-items: stretch; - width: 100%; -} - -.richText .richText-form label { - display: flex; - align-items: left;/*center*/ - padding: 0.375rem 0.75rem; - margin-bottom: 0; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - font-weight: 600; - text-align: left;/*center*/ - white-space: nowrap; -} - -.richText .richText-form input[type="text"], .richText .richText-form input[type="file"], .richText .richText-form input[type="number"], .richText .richText-form select { - display: block; - height: calc(1.5em + 0.75rem + 2px); - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #777777; - background-color: #FFFFFF; - background-clip: padding-box; - border: 1px solid #D6D8DB; - border-radius: 0.25rem; - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - position: relative; - flex: 1 1 auto; - width: 1%; - margin-bottom: 0; -} - -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown {list-style: none;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li {display: block;float: none;font-family: Calibri,Verdana,Helvetica,sans-serif;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li a {display: block;padding: 10px 15px;border-bottom: #EFEFEF solid 1px;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li a:hover {background-color: #FFFFFF;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline {margin: 10px 6px;float: left;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline a {display: block;padding: 0;margin: 0;border: none;-webkit-border-radius: 50%;-moz-border-radius: 50%;border-radius: 50%;-webkit-box-shadow: 0 0 10px 0 #999;-moz-box-shadow: 0 0 10px 0 #999;box-shadow: 0 0 10px 0 #999;} -.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline a span {display: block;height: 30px;width: 30px;-webkit-border-radius: 50%;-moz-border-radius: 50%;border-radius: 50%;} - - -.richText .richText-undo, .richText .richText-redo { - float: left; - display: block; - padding: 0.5rem; - cursor: pointer; -} - -.richText .richText-undo.is-disabled, .richText .richText-redo.is-disabled { - opacity: 0.4; -} - -.richText .richText-help { - display: none; -} - -/* -.richText .richText-initial {margin-bottom: -4px;padding: 10px;background-color: #282828;border: none;color: #33FF33;font-family: Monospace,Calibri,Verdana,Helvetica,sans-serif;max-width: 100%;min-width: 100%;width: 100%;min-height: 400px;height: 400px;} -.richText .richText-editor ul, .richText .richText-editor ol {margin: 10px 25px;} -.richText .richText-editor:focus {border-left: #3498db solid 2px;} -.richText .richText-editor table {margin: 10px 0;border-spacing: 0;width: 100%;} -.richText .richText-editor table td, .richText .richText-editor table th {padding: 10px;border: #EFEFEF solid 1px;} -.richText .richText-help {float: right;display: block;padding: 10px 15px;cursor: pointer;} -.richText .richText-help-popup a {color: #3498db;text-decoration: underline;} -.richText .richText-help-popup hr {margin: 10px auto 5px auto;border: none;border-top: #EFEFEF solid 1px;} -.richText .richText-list.list-rightclick {position: absolute;background-color: #FAFAFA;border-right: #EFEFEF solid 1px;border-bottom: #EFEFEF solid 1px;} +.richText { + position: relative; + border: 1px solid #D6D8D8; + background: #D6D8D8; + width: 100%; + border-radius: 0.25rem; +} + +.richText .richText-toolbar ul { + padding: 0 !important; + margin: 0 !important; + display: flex; + flex-wrap: wrap; + justify-content: left;/*center*/ +} + +.richText .richText-toolbar ul li { + list-style: none; +} + +.richText .richText-toolbar ul li a { + display: block; + padding: 0.25rem 0.5rem; + cursor: pointer; + -webkit-transition: color 0.4s; + -moz-transition: color 0.4s; + transition: color 0.4s; +} + +.richText .richText-toolbar ul li a:hover { + color: #001d68; +} + +.richText .richText-toolbar ul li a .fa, .richText .richText-toolbar ul li a .fas, .richText .richText-toolbar ul li a .far, .richText .richText-toolbar ul li a svg { + pointer-events: none; +} + +.richText .richText-toolbar ul li[data-disable="true"] { + opacity: 0.1; +} + +.richText .richText-toolbar ul li[data-disable="true"] a { + cursor: default; +} + +.richText .richText-toolbar ul li:not([data-disable="true"]).is-selected .richText-dropdown-outer { + display: block; +} + +.richText .richText-toolbar ul:after { + display: block; + content: ""; + clear: both; +} + +.richText .richText-toolbar:last-child { + font-size: 0.75rem; +} + +.richText .richText-toolbar:after { + display: block; + clear: both; + content: ""; +} + +.richText .richText-form select {cursor: pointer;} + +.richText .richText-editor { + padding: 0.5rem; + background-color: #FFFFFF; + height: 15rem; + outline: none; + overflow-y: scroll; + overflow-x: auto; +} + +.richText .richText-toolbar ul li a .richText-dropdown-outer { + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.3); + cursor: default; +} + +.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown { + position: relative; + z-index:10; + display: block; + margin: 3% auto 0 auto; + background-color: #D6D8D8; + border: 0.1rem solid #777777; + border-radius: 0.25rem; + padding: 0.75rem; + padding-top: 1.5rem; + max-width: 90%; + -webkit-box-shadow: 0 0 5px 0 #777777; + -moz-box-shadow: 0 0 5px 0 #777777; + box-shadow: 0 0 5px 0 #777777; +} + +.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown .richText-dropdown-close { + position: absolute; + top: 0.25rem; + right: 0.5rem; + color: #CE0E2D; + cursor: pointer; +} + +.richText .richText-toolbar ul li a .richText-dropdown-outer .richText-dropdown .richText-dropdown-close:hover { + opacity: 0.5 +} + +.richText-form-item{ + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} + +.richText .richText-form label { + display: flex; + align-items: left;/*center*/ + padding: 0.375rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + font-weight: 600; + text-align: left;/*center*/ + white-space: nowrap; +} + +.richText .richText-form input[type="text"], .richText .richText-form input[type="file"], .richText .richText-form input[type="number"], .richText .richText-form select { + display: block; + height: calc(1.5em + 0.75rem + 2px); + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #777777; + background-color: #FFFFFF; + background-clip: padding-box; + border: 1px solid #D6D8DB; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + position: relative; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; +} + +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown {list-style: none;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li {display: block;float: none;font-family: Calibri,Verdana,Helvetica,sans-serif;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li a {display: block;padding: 10px 15px;border-bottom: #EFEFEF solid 1px;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li a:hover {background-color: #FFFFFF;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline {margin: 10px 6px;float: left;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline a {display: block;padding: 0;margin: 0;border: none;-webkit-border-radius: 50%;-moz-border-radius: 50%;border-radius: 50%;-webkit-box-shadow: 0 0 10px 0 #999;-moz-box-shadow: 0 0 10px 0 #999;box-shadow: 0 0 10px 0 #999;} +.richText .richText-toolbar ul li a .richText-dropdown-outer ul.richText-dropdown li.inline a span {display: block;height: 30px;width: 30px;-webkit-border-radius: 50%;-moz-border-radius: 50%;border-radius: 50%;} + + +.richText .richText-undo, .richText .richText-redo { + float: left; + display: block; + padding: 0.5rem; + cursor: pointer; +} + +.richText .richText-undo.is-disabled, .richText .richText-redo.is-disabled { + opacity: 0.4; +} + +.richText .richText-help { + display: none; +} + +/* +.richText .richText-initial {margin-bottom: -4px;padding: 10px;background-color: #282828;border: none;color: #33FF33;font-family: Monospace,Calibri,Verdana,Helvetica,sans-serif;max-width: 100%;min-width: 100%;width: 100%;min-height: 400px;height: 400px;} +.richText .richText-editor ul, .richText .richText-editor ol {margin: 10px 25px;} +.richText .richText-editor:focus {border-left: #3498db solid 2px;} +.richText .richText-editor table {margin: 10px 0;border-spacing: 0;width: 100%;} +.richText .richText-editor table td, .richText .richText-editor table th {padding: 10px;border: #EFEFEF solid 1px;} +.richText .richText-help {float: right;display: block;padding: 10px 15px;cursor: pointer;} +.richText .richText-help-popup a {color: #3498db;text-decoration: underline;} +.richText .richText-help-popup hr {margin: 10px auto 5px auto;border: none;border-top: #EFEFEF solid 1px;} +.richText .richText-list.list-rightclick {position: absolute;background-color: #FAFAFA;border-right: #EFEFEF solid 1px;border-bottom: #EFEFEF solid 1px;} .richText .richText-list.list-rightclick li {padding: 5px 7px;cursor: pointer;list-style: none;}*/ \ No newline at end of file diff --git a/demo.html b/demo.html index 2d1edc6..1345a80 100644 --- a/demo.html +++ b/demo.html @@ -1,235 +1,235 @@ - -

- ing-fb1 -

-

- ing-fb2 -

-

- ing-tw1 -

-

- ing-tw2 -

-

- ing-in1 -

-

- ing-in2 -

-

- ing-instra1 -

-

- ing-instra2 -

-

- ing-youtube -

-

- ing-telefono -

-

- ing-mail -

-

- ing-link -

-

- ing-ubicacion -

-

- ing-puntos -

-

- ing-usuario -

-

- ing-pass -

-

- ing-menu -

-

- ing-salir -

-

- ing-flecha -

-

- ing-cambiar -

-

- ing-caret -

-

- ing-aceptar -

-

- ing-cancelar -

-

- ing-mas -

-

- ing-menos -

-

- ing-editar -

-

- ing-buscar -

-

- ing-ojo -

-

- ing-borrar -

-

- ing-basura -

-

- ing-camara -

-

- ing-importante -

-

- ing-bullet -

-

- ing-home -

-

- ing-formacion -

-

- ing-empleo -

-

- ing-insignia1 -

-

- ing-insignia2 -

-

- ing-insignia3 -

-

- ing-insignia4 -

-

- ing-eventos -

-

- ing-reporte -

-

- ing-catalogo -

-

- ing-evalua-cartel -

-

- ing-revision-cartel -

-

- ing-reporte-resultados -

-

- ing-mi-cartel -

-

- ing-galeria1 -

-

- ing-galeria2 -

-

- ing-iniciar-sesion -

-

- ing-finalistas -

-

- ing-comite -

-

- ing-administrador -

-

- ing-estrella1 -

-

- ing-estrella2 -

-

- ing-carga-archivo -

-

- ing-carga-multiple -

-

- ing-descarga -

-

- ing-autorizar -

-

- ing-negar -

-

- ing-no-cargado -

-

- ing-alumnos -

-

- ing-cardex -

-

- ing-configuracion -

-

- ing-listado-menus -

-

- ing-mi-cuenta -

-

- ing-ver -

-

- ing-grafica -

-

- ing-clic -

-

- ing-guardar -

-

- ing-regresar -

-

- ing-cuadrado -

-

- ing-imprimir -

-

- ing-importante2 -

-

- ing-copiar -

-

- ing-reloj -

-

- ing-retardo -

-

- ing-justificar + +

+ ing-fb1 +

+

+ ing-fb2 +

+

+ ing-tw1 +

+

+ ing-tw2 +

+

+ ing-in1 +

+

+ ing-in2 +

+

+ ing-instra1 +

+

+ ing-instra2 +

+

+ ing-youtube +

+

+ ing-telefono +

+

+ ing-mail +

+

+ ing-link +

+

+ ing-ubicacion +

+

+ ing-puntos +

+

+ ing-usuario +

+

+ ing-pass +

+

+ ing-menu +

+

+ ing-salir +

+

+ ing-flecha +

+

+ ing-cambiar +

+

+ ing-caret +

+

+ ing-aceptar +

+

+ ing-cancelar +

+

+ ing-mas +

+

+ ing-menos +

+

+ ing-editar +

+

+ ing-buscar +

+

+ ing-ojo +

+

+ ing-borrar +

+

+ ing-basura +

+

+ ing-camara +

+

+ ing-importante +

+

+ ing-bullet +

+

+ ing-home +

+

+ ing-formacion +

+

+ ing-empleo +

+

+ ing-insignia1 +

+

+ ing-insignia2 +

+

+ ing-insignia3 +

+

+ ing-insignia4 +

+

+ ing-eventos +

+

+ ing-reporte +

+

+ ing-catalogo +

+

+ ing-evalua-cartel +

+

+ ing-revision-cartel +

+

+ ing-reporte-resultados +

+

+ ing-mi-cartel +

+

+ ing-galeria1 +

+

+ ing-galeria2 +

+

+ ing-iniciar-sesion +

+

+ ing-finalistas +

+

+ ing-comite +

+

+ ing-administrador +

+

+ ing-estrella1 +

+

+ ing-estrella2 +

+

+ ing-carga-archivo +

+

+ ing-carga-multiple +

+

+ ing-descarga +

+

+ ing-autorizar +

+

+ ing-negar +

+

+ ing-no-cargado +

+

+ ing-alumnos +

+

+ ing-cardex +

+

+ ing-configuracion +

+

+ ing-listado-menus +

+

+ ing-mi-cuenta +

+

+ ing-ver +

+

+ ing-grafica +

+

+ ing-clic +

+

+ ing-guardar +

+

+ ing-regresar +

+

+ ing-cuadrado +

+

+ ing-imprimir +

+

+ ing-importante2 +

+

+ ing-copiar +

+

+ ing-reloj +

+

+ ing-retardo +

+

+ ing-justificar

\ No newline at end of file diff --git a/días_festivos.php b/días_festivos.php index 2f72570..1aae19b 100644 --- a/días_festivos.php +++ b/días_festivos.php @@ -1,343 +1,343 @@ -access(); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Dias_festivos'); -} -if(isset($_GET['facultad'])){ - $fac = $_GET['facultad']; -}else if($user->admin){ - $fac = null; -}else{ - $fac = $user->facultad['facultad_id']; -} -?> - - - - - - - Días Festivos - - - - - - - - access(); - $fs_dias_festivos = query("SELECT * FROM fs_diasfestivos(:facultad, null, null, null) ORDER BY diasfestivos_dia", [':facultad' => $fac], false); - $fs_periodos = query("SELECT * FROM fs_periodos(null, null) WHERE estado = 'Activo'", null, false); - $fs_dias_festivos_generales = query("SELECT * FROM fs_diasfestivos(null, null) ORDER BY diasfestivos_dia", null, false); - ?> -
- admin){ ?> -
- -
- -
- - -
-
- - - - - - - admin){ ?> - - - - - - - - - - - - admin){ ?> - - - - - - - - - - - admin){ ?> - - - - - - -
DíaPeriodoNivelFacultadAcciones
- - -
TodosTodosTodas - - -
-
-
- -
- - - - - - - - - - - - - - - - +access(); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Dias_festivos'); +} +if(isset($_GET['facultad'])){ + $fac = $_GET['facultad']; +}else if($user->admin){ + $fac = null; +}else{ + $fac = $user->facultad['facultad_id']; +} +?> + + + + + + + Días Festivos + + + + + + + + access(); + $fs_dias_festivos = query("SELECT * FROM fs_diasfestivos(:facultad, null, null, null) ORDER BY diasfestivos_dia", [':facultad' => $fac], false); + $fs_periodos = query("SELECT * FROM fs_periodos(null, null) WHERE estado = 'Activo'", null, false); + $fs_dias_festivos_generales = query("SELECT * FROM fs_diasfestivos(null, null) ORDER BY diasfestivos_dia", null, false); + ?> +
+ admin){ ?> +
+ +
+ +
+ + +
+
+ + + + + + + admin){ ?> + + + + + + + + + + + + admin){ ?> + + + + + + + + + + + admin){ ?> + + + + + + +
DíaPeriodoNivelFacultadAcciones
+ + +
TodosTodosTodas + + +
+
+
+ +
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/editar_horario.php b/editar_horario.php index cbca306..f5e9180 100644 --- a/editar_horario.php +++ b/editar_horario.php @@ -1,111 +1,111 @@ -admin) - header('Location: main.php?error=1'); -?> - - - - - - - - Editar Horarios | <?php echo $_SESSION['facultad'] ?? "Administrador"; ?> - - - - - - - - - - -
-
-
-
- -
- - - -
- -
-
- - -
-
- - - - - - - - - - - - - - - - - - - -
HoraLunesMartesMiércolesJuevesViernesSábadoDomingo
7:00 - 8:00 -
-
-
-
-
- - - - - $facultad_id, ":dia" => $dia) - ); - foreach ($horarios as $h) - $horario[$dia][] = $h; - } - return $horario; -} +admin) + header('Location: main.php?error=1'); +?> + + + + + + + + Editar Horarios | <?php echo $_SESSION['facultad'] ?? "Administrador"; ?> + + + + + + + + + + +
+
+
+
+ +
+ + + +
+ +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + +
HoraLunesMartesMiércolesJuevesViernesSábadoDomingo
7:00 - 8:00 +
+
+
+
+
+ + + + + $facultad_id, ":dia" => $dia) + ); + foreach ($horarios as $h) + $horario[$dia][] = $h; + } + return $horario; +} ?> \ No newline at end of file diff --git a/excel_horario.php b/excel_horario.php index 16e4796..8a95869 100644 --- a/excel_horario.php +++ b/excel_horario.php @@ -1,209 +1,209 @@ -access('excel_horario'); - -if (!$user->admin && in_array($user->acceso, ['r', 'n'])) { - // die($access); - header('Location: main.php?error=1'); -} else { - $user->print_to_log('Consultar asistencia'); -} -?> - - - - - Cargar horario desde Excel | <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - -
-
- -
-
-
- $user->facultad['facultad_id'], ":per" => $user->periodo], single: false); - #die(print_r($carreras, true)); - ?> -
- -
-
-
Seleccionar carrera
- -
    - -
  • - -
  • - -
- -
-
-
- -
- -
- -
-
- -
- - -
-
-
- -
-
- - - - - - - - - - - - +access('excel_horario'); + +if (!$user->admin && in_array($user->acceso, ['r', 'n'])) { + // die($access); + header('Location: main.php?error=1'); +} else { + $user->print_to_log('Consultar asistencia'); +} +?> + + + + + Cargar horario desde Excel | <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + +
+
+ +
+
+
+ $user->facultad['facultad_id'], ":per" => $user->periodo], single: false); + #die(print_r($carreras, true)); + ?> +
+ +
+
+
Seleccionar carrera
+ +
    + +
  • + +
  • + +
+ +
+
+
+ +
+ +
+ +
+
+ +
+ + +
+
+
+ +
+
+ + + + + + + + + + + + \ No newline at end of file diff --git a/facultades.php b/facultades.php index 178fbcb..3411c3a 100644 --- a/facultades.php +++ b/facultades.php @@ -1,283 +1,283 @@ -access(); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Facultades'); -} -if($user->admin!=true){ - header('Location: carreras.php?facultad='.$user->facultad['facultad_id']); -} -?> - - - - - - - Facultades - - - - - access(); - if(isset($_POST["estado"])){ - echo "estado=".$_POST["estado"]; - } - - if(isset($_POST["desc"])){ - $desc=$_POST["desc"]; - $filter_desc = trim(filter_input(INPUT_POST, "desc", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $desc=null; - } - if($user->admin==true){ - $fs_facultades = query( - "SELECT * FROM fs_facultades(:nombre)", - array(":nombre" => $desc), - single:false - ); - }else{ - $fs_facultades = query( - "SELECT * FROM fs_facultades(:nombre) where facultad_id = :facultad", - array(":nombre" => $desc, ":facultad" => $user->facultad["facultad_id"]), - single:false - ); - } - ?> -
- admin==true) {?> -
-
- -
-
- - -
-
-
-
-
- -
- > -
-
-
-
-
- - -
-
-
-
-
- - -
-
- - - - - - acceso == 'w') {?> - - - - - - - " id=""> - - - - acceso == 'w') {?> - - - - - -
EstadoFacultadAcciones
- - - - " title="Agregar carreras o periodos"> -
-
-
-
-
- - - - - - - - - - +access(); +if(!$user->admin && $user->acceso == 'n'){ + header('Location: main.php?error=1'); +}else{ + $user->print_to_log('Facultades'); +} +if($user->admin!=true){ + header('Location: carreras.php?facultad='.$user->facultad['facultad_id']); +} +?> + + + + + + + Facultades + + + + + access(); + if(isset($_POST["estado"])){ + echo "estado=".$_POST["estado"]; + } + + if(isset($_POST["desc"])){ + $desc=$_POST["desc"]; + $filter_desc = trim(filter_input(INPUT_POST, "desc", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + }else{ + $desc=null; + } + if($user->admin==true){ + $fs_facultades = query( + "SELECT * FROM fs_facultades(:nombre)", + array(":nombre" => $desc), + single:false + ); + }else{ + $fs_facultades = query( + "SELECT * FROM fs_facultades(:nombre) where facultad_id = :facultad", + array(":nombre" => $desc, ":facultad" => $user->facultad["facultad_id"]), + single:false + ); + } + ?> +
+ admin==true) {?> +
+
+ +
+
+ + +
+
+
+
+
+ +
+ > +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+ + + + + + acceso == 'w') {?> + + + + + + + " id=""> + + + + acceso == 'w') {?> + + + + + +
EstadoFacultadAcciones
+ + + + " title="Agregar carreras o periodos"> +
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/horario_profesor.php b/horario_profesor.php index c671ce9..71d9564 100644 --- a/horario_profesor.php +++ b/horario_profesor.php @@ -1,135 +1,135 @@ -access(); -if (!$user->admin && in_array($user->acceso, ['n'])) - die(header('Location: main.php?error=1')); - -$user->print_to_log('Consultar horario'); - -$write = $user->admin || in_array($user->acceso, ['w']); -// var_dump($user); -?> - - - - - Consultar horario | <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - - - - - - - - - - - - - " ?> -
-
- - -
-
-
- -
- -
- -
- Profesor encontrado -
-
- Profesor no encontrado -
- - where('facultad_id', $user->facultad['facultad_id'])->get("fs_profesor"); - foreach ($profesores as $profesor) { - extract($profesor); - ?> - - - -
    - - -
    -
    - - -
    - - -
    -
    -
    -
    -
    - - - -
    - - - - - - - -
    - - - - - - - - - - - - - -
    HoraLunesMartesMiércolesJuevesViernesSábado
    -
    -
    - - +access(); +if (!$user->admin && in_array($user->acceso, ['n'])) + die(header('Location: main.php?error=1')); + +$user->print_to_log('Consultar horario'); + +$write = $user->admin || in_array($user->acceso, ['w']); +// var_dump($user); +?> + + + + + Consultar horario | <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + + + + + + + + + + + + + " ?> +
    +
    + + +
    +
    +
    + +
    + +
    + +
    + Profesor encontrado +
    +
    + Profesor no encontrado +
    + + where('facultad_id', $user->facultad['facultad_id'])->get("fs_profesor"); + foreach ($profesores as $profesor) { + extract($profesor); + ?> + + + +
      + + +
      +
      + + +
      + + +
      +
      +
      +
      +
      + + + +
      + + + + + + + +
      + + + + + + + + + + + + + +
      HoraLunesMartesMiércolesJuevesViernesSábado
      +
      +
      + + \ No newline at end of file diff --git a/import/html_css_files.php b/import/html_css_files.php index 23d532a..8eb65e2 100644 --- a/import/html_css_files.php +++ b/import/html_css_files.php @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/import/html_footer.php b/import/html_footer.php index 6273a78..3ca5ddf 100644 --- a/import/html_footer.php +++ b/import/html_footer.php @@ -1,105 +1,105 @@ -
      - +
      +
      \ No newline at end of file diff --git a/import/html_forms.php b/import/html_forms.php index 8be644d..c2ccc79 100644 --- a/import/html_forms.php +++ b/import/html_forms.php @@ -1,22 +1,22 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/import/html_forms_asistencia.php b/import/html_forms_asistencia.php index 3689572..06ebe3b 100644 --- a/import/html_forms_asistencia.php +++ b/import/html_forms_asistencia.php @@ -1,139 +1,139 @@ - - - -
      -
      - - where('id', $user->periodo)->getOne('fs_periodo'); - $carreras = $db - ->where('nivel', $periodo['nivel_id']) - ->where('facultad', $user->facultad['facultad_id']) - ->orderBy('carrera') - ->get('fs_carrera'); - - ?> -
      - -
      -
      -
      Seleccionar todas las carreras
      - -
        -
      • Seleccionar todas las carreras
      • - -
      • - -
      • - -
      - -
      -
      -
      - -
      - -
      - -
      -
      -
      - -
      - -
      -
      - -
      - -
      - -
      No es una fecha válida.
      -
      -
      -
      - -
      - -
      No es una fecha válida o el rango es incorrecto.
      -
      -
      -
      -
      - - -
      - -
      - - \ No newline at end of file diff --git a/import/html_forms_justificacion.php b/import/html_forms_justificacion.php index 0a1a785..402556c 100644 --- a/import/html_forms_justificacion.php +++ b/import/html_forms_justificacion.php @@ -1,111 +1,111 @@ - - - -
      -
      -
      - Selecciona la fecha que deseas justificar. -
      -
      - -
      - -
      No es una fecha válida.
      -
      -
      - -
      - -
      - -
      - - - -
      -
      No es una hora válida.
      -
      - -
      - - -
      - -
      - -
      - - - -
      -
      No es una hora válida.
      -
      -
      - -
      - -
      - -
      No es una clave válida.
      -
      -
      - - -
      - -
      - -
      No es un nombre válido.
      -
      -
      - -
      - - - -
      - -
      - -
      - - - + \ No newline at end of file diff --git a/import/html_forms_vista.php b/import/html_forms_vista.php index bff4d50..bd76f1b 100644 --- a/import/html_forms_vista.php +++ b/import/html_forms_vista.php @@ -1,163 +1,163 @@ -
      - $id, ':per' => $user->periodo]); -// materia por carrera -#print_r($carreras); -$materias = queryAll("SELECT DISTINCT * FROM FS_MATERIA WHERE CARRERA = COALESCE(:car, CARRERA) AND ID IN (SELECT distinct materia_id FROM HORARIO WHERE :id IN (SELECT HORARIO_ID FROM HORARIO_PROFESOR WHERE PROFESOR_ID = :id) AND PERIODO_ID = :per) ORDER BY NOMBRE", [":car" => empty($carrera) ? null : $carrera, ':id' => $id, ':per' => $user->periodo]); -#exit(); -$periodo = query("SELECT inicio, fin FROM FS_PERIODO WHERE ID = :per", [':per' => $user->periodo]); -?> - - -
      - - - - -
      -
      - -
      -
      -
      Todas las carreras
      - -
        - -
      • Todas las carreras
      • - -
      • " onclick="carreras()"> - -
      • - -
      - -
      -
      -
      - -
      - -
      -
      -
      Todas las materias
      - -
        -
      • Todas las materias
      • - -
      • "> - -
      • - -
      - -
      -
      -
      - - -
      - -
      - -
      No es una fecha válida.
      -
      -
      -
      - -
      - -
      No es una fecha válida o el rango es incorrecto.
      -
      -
      -
      - - -
      - - -
      -
      - - \ No newline at end of file diff --git a/import/html_header.php b/import/html_header.php index 292f123..84c5d61 100644 --- a/import/html_header.php +++ b/import/html_header.php @@ -1,160 +1,149 @@ - - - -admin) - $paginas = queryAll("SELECT * FROM pagina ORDER BY pagina_ruta"); - else - $paginas = queryAll("SELECT * FROM PERMISO_VIEW WHERE id = :id ORDER BY pagina_ruta", array(":id" => $user->user['id'])); - - ?> - -
      -
      - -
      - -
      - -
      -
      -

      - -

      -
      - -
      -
      -

      - -

      -
      -
      -
      - \ No newline at end of file + + + +admin): + ?> +admin ? queryAll("SELECT * FROM GRUPO ORDER BY grupo_nombre") : $db->query("SELECT * FROM GRUPO WHERE grupo_id IN (SELECT grupo_id FROM PERMISO_VIEW WHERE id = :id) ORDER BY grupo_nombre", array(":id" => $user->user['id'])); + +function html_header($title, $header = null) +{ + global $grupos, $user, $db; + ?> + +
      +
      + +
      + +
      + +
      +
      +

      + +

      +
      + +
      +
      +

      + +

      +
      +
      +
      + \ No newline at end of file diff --git a/import/html_header_index.php b/import/html_header_index.php index 42c72a6..0761f1e 100644 --- a/import/html_header_index.php +++ b/import/html_header_index.php @@ -1,32 +1,31 @@ - - - -
      - -
      -
      -

      -

      -
      - -
      -
      -

      -
      -
      -
      - + + +
      + +
      +
      +

      +

      +
      + +
      +
      +

      +
      +
      +
      + - - - - - -`; - return html; +function barra(profesor, retardos) { + profesor.faltas = profesor.total - profesor.asistencias - profesor.retardos - profesor.justificaciones; + if (profesor.total != 0) + var porcentajes = { + "asistencias": profesor.asistencias / profesor.total * 100, + "retardos": profesor.retardos / profesor.total * 100, + "justificaciones": profesor.justificaciones / profesor.total * 100, + "faltas": 100 * profesor.faltas / profesor.total + } + else + var porcentajes = { + "asistencias": 0, + "retardos": 0, + "justificaciones": 0, + "faltas": 0 + } + var html = ` +
      +
      +
      +
      +
      + + ${retardos ? `
      ` : ``} +
      +
      +
      +
      +
      + + +
      + Asistencias: ${profesor.asistencias} + ${retardos ? `Retardos: ${profesor.retardos}` : `` } + Justificaciones: ${profesor.justificaciones} + Faltas: ${profesor.faltas} +
      +
      +`; + return html; } \ No newline at end of file diff --git a/js/client.js b/js/client.js index 236d201..9087072 100644 --- a/js/client.js +++ b/js/client.js @@ -1,120 +1,120 @@ -// @ts-ignore Import module -import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'; -const webServices = { - getPeriodosV1: async () => { - try { - const response = await fetch('periodos.v1.php'); - return await response.json(); - } - catch (error) { - console.log(error); - return []; - } - }, - getPeriodosV2: async () => { - try { - const response = await fetch('periodos.v2.php'); - return await response.json(); - } - catch (error) { - console.log(error); - return []; - } - } -}; -const store = reactive({ - periodosV1: [], - periodosV2: [], - errors: [], - fechas(idPeriodo) { - const periodo = this.periodosV2.find((periodo) => periodo.IdPeriodo === idPeriodo); - return { - inicio: periodo ? periodo.FechaInicio : '', - fin: periodo ? periodo.FechaFin : '' - }; - }, - periodov1(idPeriodo) { - return this.periodosV1.find((periodo) => periodo.IdPeriodo === idPeriodo); - }, - periodov2(idPeriodo) { - return this.periodosV2.filter((periodo) => periodo.IdPeriodo === idPeriodo); - }, - async addPeriodo(periodo) { - try { - const result = await fetch('backend/periodos.php', { - method: 'POST', - body: JSON.stringify({ - ...periodo, - ...this.fechas(periodo.IdPeriodo) - }), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()); - if (result.success) { - this.periodosV1 = this.periodosV1.map((periodoV1) => { - if (periodoV1.IdPeriodo === periodo.IdPeriodo) { - periodoV1.in_db = true; - } - return periodoV1; - }); - return result; - } - else { - this.errors.push(result.message); - } - } - catch (error) { - this.errors.push(error); - } - }, - async addCarreras(idPeriodo) { - try { - const periodoV1 = this.periodov1(idPeriodo); - const periodoV2 = this.periodov2(idPeriodo); - const data = periodoV2.map(({ ClaveCarrera, NombreCarrera }) => ({ - ClaveCarrera: ClaveCarrera, - NombreCarrera: NombreCarrera, - IdNivel: periodoV1.IdNivel, - })); - const result = await fetch('backend/carreras.php', { - method: 'POST', - body: JSON.stringify(data), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()); - if (result.success) { - await webServices.getPeriodosV1().then((periodosV1) => { - this.periodosV1 = periodosV1; - }); - await webServices.getPeriodosV2().then((periodosV2) => { - this.periodosV2 = periodosV2; - }); - } - } - catch (error) { - this.errors.push(error); - } - } -}); -createApp({ - store, - info(IdPeriodo) { - const periodo = store.periodosV2.find((periodo) => periodo.IdPeriodo === IdPeriodo && - periodo.FechaInicio != '' && periodo.FechaFin != ''); - return periodo; - }, - complete(IdPeriodo) { - const info = this.info(IdPeriodo); - return info !== undefined; - }, - mounted: async () => { - await webServices.getPeriodosV1().then((periodosV1) => { - store.periodosV1 = periodosV1; - }); - await webServices.getPeriodosV2().then((periodosV2) => { - store.periodosV2 = periodosV2; - }); - } -}).mount(); +// @ts-ignore Import module +import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'; +const webServices = { + getPeriodosV1: async () => { + try { + const response = await fetch('periodos.v1.php'); + return await response.json(); + } + catch (error) { + console.log(error); + return []; + } + }, + getPeriodosV2: async () => { + try { + const response = await fetch('periodos.v2.php'); + return await response.json(); + } + catch (error) { + console.log(error); + return []; + } + } +}; +const store = reactive({ + periodosV1: [], + periodosV2: [], + errors: [], + fechas(idPeriodo) { + const periodo = this.periodosV2.find((periodo) => periodo.IdPeriodo === idPeriodo); + return { + inicio: periodo ? periodo.FechaInicio : '', + fin: periodo ? periodo.FechaFin : '' + }; + }, + periodov1(idPeriodo) { + return this.periodosV1.find((periodo) => periodo.IdPeriodo === idPeriodo); + }, + periodov2(idPeriodo) { + return this.periodosV2.filter((periodo) => periodo.IdPeriodo === idPeriodo); + }, + async addPeriodo(periodo) { + try { + const result = await fetch('backend/periodos.php', { + method: 'POST', + body: JSON.stringify({ + ...periodo, + ...this.fechas(periodo.IdPeriodo) + }), + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => response.json()); + if (result.success) { + this.periodosV1 = this.periodosV1.map((periodoV1) => { + if (periodoV1.IdPeriodo === periodo.IdPeriodo) { + periodoV1.in_db = true; + } + return periodoV1; + }); + return result; + } + else { + this.errors.push(result.message); + } + } + catch (error) { + this.errors.push(error); + } + }, + async addCarreras(idPeriodo) { + try { + const periodoV1 = this.periodov1(idPeriodo); + const periodoV2 = this.periodov2(idPeriodo); + const data = periodoV2.map(({ ClaveCarrera, NombreCarrera }) => ({ + ClaveCarrera: ClaveCarrera, + NombreCarrera: NombreCarrera, + IdNivel: periodoV1.IdNivel, + })); + const result = await fetch('backend/carreras.php', { + method: 'POST', + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => response.json()); + if (result.success) { + await webServices.getPeriodosV1().then((periodosV1) => { + this.periodosV1 = periodosV1; + }); + await webServices.getPeriodosV2().then((periodosV2) => { + this.periodosV2 = periodosV2; + }); + } + } + catch (error) { + this.errors.push(error); + } + } +}); +createApp({ + store, + info(IdPeriodo) { + const periodo = store.periodosV2.find((periodo) => periodo.IdPeriodo === IdPeriodo && + periodo.FechaInicio != '' && periodo.FechaFin != ''); + return periodo; + }, + complete(IdPeriodo) { + const info = this.info(IdPeriodo); + return info !== undefined; + }, + mounted: async () => { + await webServices.getPeriodosV1().then((periodosV1) => { + store.periodosV1 = periodosV1; + }); + await webServices.getPeriodosV2().then((periodosV2) => { + store.periodosV2 = periodosV2; + }); + } +}).mount(); diff --git a/js/consulta_horarios.js b/js/consulta_horarios.js index 9ef150d..85e7a2e 100644 --- a/js/consulta_horarios.js +++ b/js/consulta_horarios.js @@ -1,288 +1,288 @@ -// initial state -const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]; -const horas_estándar = /* range from 7 to 22 */ Array.from(Array(22 - 7 + 1).keys()).map(x => x + 7); -// fill the table with empty cells -for (let i = 0; i < horas_estándar.length - 1; i++) { - const hora = horas_estándar[i]; - const tr = document.createElement("tr"); - tr.id = `hora-${hora}-00`; - tr.classList.add(hora > 13 ? "tarde" : "mañana"); - 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); - for (let j = 0; j < días.length; j++) { - const día = días[j]; - const td = document.createElement("td"); - td.id = `hora-${hora}-00-${día}`; - tr.appendChild(td); - } - document.querySelector("tbody#horario")?.appendChild(tr); - // add 7 rows for each hour - const hours = [15, 30, 45]; - for (let j = 1; j < 4; j++) { - const tr = document.createElement("tr"); - tr.id = `hora-${hora}-${hours[j - 1]}`; - tr.classList.add(hora > 13 ? "tarde" : "mañana"); - for (let k = 0; k < días.length; k++) { - const día = días[k]; - const td = document.createElement("td"); - td.id = `hora-${hora}-${hours[j - 1]}-${día}`; - // td.innerText = `hora-${hora}-${hours[j - 1]}-${día}`; - tr.appendChild(td); - } - document.querySelector("tbody#horario")?.appendChild(tr); - } -} -// add an inital height to the table cells -const tds = document.querySelectorAll("tbody#horario td"); -tds.forEach(td => td.style.height = "2rem"); -var table = document.querySelector("table"); -var empty_table = table?.innerHTML || ""; -// hide the table -table.style.display = "none"; -document.getElementById('dlProfesor')?.addEventListener('input', function () { - var input = document.getElementById('dlProfesor'); - var value = input.value; - var option = document.querySelector(`option[value="${value}"]`); - if (option) { - var id = option.getAttribute('data-id'); - const input_profesor = document.getElementById('editor_profesor'); - input_profesor.value = id; - // remove is invalid class - input.classList.remove("is-invalid"); - // add is valid class - input.classList.add("is-valid"); - } - else { - const input_profesor = document.getElementById('editor_profesor'); - input_profesor.value = ""; - // remove is valid class - input.classList.remove("is-valid"); - // add is invalid class - input.classList.add("is-invalid"); - } -}); -/** - * Functions and Methods - **/ -const buscarGrupo = async () => { - // Add loading animation in the button - const btn = document.querySelector("#btn-buscar"); - btn.innerHTML = ' Cargando...'; - btn.disabled = true; - const carrera = document.querySelector("#filter_carrera")?.value; - const grupo = document.querySelector("#filter_grupo")?.value; - console.log(`Carrera: ${carrera}, Grupo: ${grupo}`); - if (carrera == "" || grupo == "") { - triggerMessage("El nombre del grupo y la carrera son requeridos", "Faltan campos"); - // Remove loading animation in the button - btn.innerHTML = ' Buscar'; - btn.disabled = false; - return; - } - const formData = new FormData(); - formData.append("carrera", carrera); - formData.append("grupo", grupo); - formData.append("periodo", document.querySelector("#periodo")?.value); - const thisScript = document.currentScript; - const facultad = thisScript.getAttribute("data-facultad"); - formData.append('facultad', facultad); - try { - const response = await fetch("action/action_horario.php", { - method: "POST", - body: formData - }).then(res => res.json()); - if (response.status == "success") { - let limits = { - min: 22, - max: 7 - }; - let sábado = false; - const horario = response.horario; - // show the table - table.style.display = "table"; - // clear the table - table.innerHTML = empty_table; - // fill the table - for (let i = 0; i < horario.length; i++) { - const dia = horario[i].dia; - if (dia == "sábado") - sábado = true; - const { hora, minutos } = { - hora: parseInt(horario[i].hora.split(":")[0]), - minutos: horario[i].hora.split(":")[1] - }; - // update the limits - if (hora < limits.min) { - limits.min = hora; - } - if (hora > limits.max) { - limits.max = hora; - } - const materia = horario[i].materia; - const profesor = horario[i].profesor; - const salon = horario[i].salon; - const id = horario[i].horario_id; - const prof_id = horario[i].profesor_id; - const cell = document.querySelector(`#hora-${hora}-${minutos}-${dia}`); - cell.innerHTML = - ` -
      - ${hora}:${minutos} - ${materia}
      -
      Salón: ${salon}
      - ${profesor} -
      - `; - const html = `
      `; - const td = cell.closest("td"); - td.innerHTML += html; - td.classList.add("position-relative"); - // this cell spans 4 rows - cell.rowSpan = 6; - cell.classList.add("bloque-clase", "overflow"); - for (let j = 1; j < 6; j++) { - const minute = (parseInt(minutos) + j * 15); - const next_minute = (minute % 60).toString().padStart(2, "0"); - const next_hour = (hora + Math.floor(minute / 60)); - const next_cell = document.querySelector(`#hora-${next_hour}-${next_minute}-${dia}`); - next_cell.remove(); - } - } - // remove the elements that are not in the limits - const horas = document.querySelectorAll("tbody#horario tr"); - for (let i = 0; i < horas.length; i++) { - const hora = horas[i]; - const hora_id = parseInt(hora.id.split("-")[1]); - if (hora_id < limits.min || hora_id > limits.max) { - hora.remove(); - } - } - // if there is no sábado, remove the column - if (!sábado) { - document.querySelectorAll("tbody#horario td").forEach(td => { - if (td.id.split("-")[3] == "sábado") { - td.remove(); - } - }); - // remove the header (the last) - const headers = document.querySelector("#headers"); - headers.lastElementChild?.remove(); - } - // adjust width - const ths = document.querySelectorAll("tr#headers th"); - const width = 95 / (ths.length - 1); - ths.forEach((th, key) => th.style.width = (key == 0) ? "5%" : `${width}%`); - // 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", () => { - element.classList.add("d-none"); - }); - }); - } - else { - triggerMessage(response.message, "Error"); - // Remove loading animation in the button - btn.innerHTML = ' Buscar'; - btn.disabled = false; - } - } - catch (error) { - triggerMessage("Error al cargar el horario", "Error"); - triggerMessage(error, "Error"); - } - // Remove loading animation in the button - btn.innerHTML = ' Buscar'; - btn.disabled = false; -}; -async function guardar(id) { - const btn = document.querySelector("#btn-guardar"); - const clone = btn.cloneNode(true); - btn.innerHTML = ' Guardando...'; - btn.disabled = true; - const data = { - hora: document.querySelector("#editor_hora"), - dia: document.querySelector("#editor_dia"), - salon: document.querySelector("#editor_salón"), - profesor: document.querySelector("#editor_profesor"), - }; - const hora = data.hora.value; // h:mm - const { compareHours } = await import('./date_functions'); - const hora_antes = compareHours(hora, "07:15") < 0; - const hora_después = compareHours(hora, "21:30") > 0; - if (hora_antes || hora_después) { - alert(`La hora ${hora} no es válida`); - triggerMessage("Selecciona una hora", "Error"); - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - data.hora.focus(); - data.hora.classList.add("is-invalid"); - return; - } - const dia = data.dia.value; - const salon = data.salon.value; - const profesor = data.profesor.value; - const formData = new FormData(); - formData.append("id", id); - formData.append("hora", hora); - formData.append("dia", dia); - formData.append("salon", salon); - formData.append("profesor", profesor); - const response = await fetch("action/action_horario_update.php", { - method: "POST", - body: formData - }).then(res => res.json()); - if (response.status == "success") { - triggerMessage(response.message, "Éxito", "success"); - btn.innerHTML = ' Guardado'; - btn.classList.add("btn-success"); - btn.classList.remove("btn-primary"); - // return to the initial state - setTimeout(() => { - buscarGrupo(); - btn.replaceWith(clone); - $("#modal-editar").modal("hide"); - }, 1000); - } - else { - triggerMessage(response.message, "Error"); - btn.replaceWith(clone); - $("#modal-editar").modal("hide"); - } -} -function triggerMessage(message, header, colour = "danger") { - throw new Error('Function not implemented.'); -} +// initial state +const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]; +const horas_estándar = /* range from 7 to 22 */ Array.from(Array(22 - 7 + 1).keys()).map(x => x + 7); +// fill the table with empty cells +for (let i = 0; i < horas_estándar.length - 1; i++) { + const hora = horas_estándar[i]; + const tr = document.createElement("tr"); + tr.id = `hora-${hora}-00`; + tr.classList.add(hora > 13 ? "tarde" : "mañana"); + 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); + for (let j = 0; j < días.length; j++) { + const día = días[j]; + const td = document.createElement("td"); + td.id = `hora-${hora}-00-${día}`; + tr.appendChild(td); + } + document.querySelector("tbody#horario")?.appendChild(tr); + // add 7 rows for each hour + const hours = [15, 30, 45]; + for (let j = 1; j < 4; j++) { + const tr = document.createElement("tr"); + tr.id = `hora-${hora}-${hours[j - 1]}`; + tr.classList.add(hora > 13 ? "tarde" : "mañana"); + for (let k = 0; k < días.length; k++) { + const día = días[k]; + const td = document.createElement("td"); + td.id = `hora-${hora}-${hours[j - 1]}-${día}`; + // td.innerText = `hora-${hora}-${hours[j - 1]}-${día}`; + tr.appendChild(td); + } + document.querySelector("tbody#horario")?.appendChild(tr); + } +} +// add an inital height to the table cells +const tds = document.querySelectorAll("tbody#horario td"); +tds.forEach(td => td.style.height = "2rem"); +var table = document.querySelector("table"); +var empty_table = table?.innerHTML || ""; +// hide the table +table.style.display = "none"; +document.getElementById('dlProfesor')?.addEventListener('input', function () { + var input = document.getElementById('dlProfesor'); + var value = input.value; + var option = document.querySelector(`option[value="${value}"]`); + if (option) { + var id = option.getAttribute('data-id'); + const input_profesor = document.getElementById('editor_profesor'); + input_profesor.value = id; + // remove is invalid class + input.classList.remove("is-invalid"); + // add is valid class + input.classList.add("is-valid"); + } + else { + const input_profesor = document.getElementById('editor_profesor'); + input_profesor.value = ""; + // remove is valid class + input.classList.remove("is-valid"); + // add is invalid class + input.classList.add("is-invalid"); + } +}); +/** + * Functions and Methods + **/ +const buscarGrupo = async () => { + // Add loading animation in the button + const btn = document.querySelector("#btn-buscar"); + btn.innerHTML = ' Cargando...'; + btn.disabled = true; + const carrera = document.querySelector("#filter_carrera")?.value; + const grupo = document.querySelector("#filter_grupo")?.value; + console.log(`Carrera: ${carrera}, Grupo: ${grupo}`); + if (carrera == "" || grupo == "") { + triggerMessage("El nombre del grupo y la carrera son requeridos", "Faltan campos"); + // Remove loading animation in the button + btn.innerHTML = ' Buscar'; + btn.disabled = false; + return; + } + const formData = new FormData(); + formData.append("carrera", carrera); + formData.append("grupo", grupo); + formData.append("periodo", document.querySelector("#periodo")?.value); + const thisScript = document.currentScript; + const facultad = thisScript.getAttribute("data-facultad"); + formData.append('facultad', facultad); + try { + const response = await fetch("action/action_horario.php", { + method: "POST", + body: formData + }).then(res => res.json()); + if (response.status == "success") { + let limits = { + min: 22, + max: 7 + }; + let sábado = false; + const horario = response.horario; + // show the table + table.style.display = "table"; + // clear the table + table.innerHTML = empty_table; + // fill the table + for (let i = 0; i < horario.length; i++) { + const dia = horario[i].dia; + if (dia == "sábado") + sábado = true; + const { hora, minutos } = { + hora: parseInt(horario[i].hora.split(":")[0]), + minutos: horario[i].hora.split(":")[1] + }; + // update the limits + if (hora < limits.min) { + limits.min = hora; + } + if (hora > limits.max) { + limits.max = hora; + } + const materia = horario[i].materia; + const profesor = horario[i].profesor; + const salon = horario[i].salon; + const id = horario[i].horario_id; + const prof_id = horario[i].profesor_id; + const cell = document.querySelector(`#hora-${hora}-${minutos}-${dia}`); + cell.innerHTML = + ` +
      + ${hora}:${minutos} + ${materia}
      +
      Salón: ${salon}
      + ${profesor} +
      + `; + const html = ``; + const td = cell.closest("td"); + td.innerHTML += html; + td.classList.add("position-relative"); + // this cell spans 4 rows + cell.rowSpan = 6; + cell.classList.add("bloque-clase", "overflow"); + for (let j = 1; j < 6; j++) { + const minute = (parseInt(minutos) + j * 15); + const next_minute = (minute % 60).toString().padStart(2, "0"); + const next_hour = (hora + Math.floor(minute / 60)); + const next_cell = document.querySelector(`#hora-${next_hour}-${next_minute}-${dia}`); + next_cell.remove(); + } + } + // remove the elements that are not in the limits + const horas = document.querySelectorAll("tbody#horario tr"); + for (let i = 0; i < horas.length; i++) { + const hora = horas[i]; + const hora_id = parseInt(hora.id.split("-")[1]); + if (hora_id < limits.min || hora_id > limits.max) { + hora.remove(); + } + } + // if there is no sábado, remove the column + if (!sábado) { + document.querySelectorAll("tbody#horario td").forEach(td => { + if (td.id.split("-")[3] == "sábado") { + td.remove(); + } + }); + // remove the header (the last) + const headers = document.querySelector("#headers"); + headers.lastElementChild?.remove(); + } + // adjust width + const ths = document.querySelectorAll("tr#headers th"); + const width = 95 / (ths.length - 1); + ths.forEach((th, key) => th.style.width = (key == 0) ? "5%" : `${width}%`); + // 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", () => { + element.classList.add("d-none"); + }); + }); + } + else { + triggerMessage(response.message, "Error"); + // Remove loading animation in the button + btn.innerHTML = ' Buscar'; + btn.disabled = false; + } + } + catch (error) { + triggerMessage("Error al cargar el horario", "Error"); + triggerMessage(error, "Error"); + } + // Remove loading animation in the button + btn.innerHTML = ' Buscar'; + btn.disabled = false; +}; +async function guardar(id) { + const btn = document.querySelector("#btn-guardar"); + const clone = btn.cloneNode(true); + btn.innerHTML = ' Guardando...'; + btn.disabled = true; + const data = { + hora: document.querySelector("#editor_hora"), + dia: document.querySelector("#editor_dia"), + salon: document.querySelector("#editor_salón"), + profesor: document.querySelector("#editor_profesor"), + }; + const hora = data.hora.value; // h:mm + const { compareHours } = await import('./date_functions'); + const hora_antes = compareHours(hora, "07:15") < 0; + const hora_después = compareHours(hora, "21:30") > 0; + if (hora_antes || hora_después) { + alert(`La hora ${hora} no es válida`); + triggerMessage("Selecciona una hora", "Error"); + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + data.hora.focus(); + data.hora.classList.add("is-invalid"); + return; + } + const dia = data.dia.value; + const salon = data.salon.value; + const profesor = data.profesor.value; + const formData = new FormData(); + formData.append("id", id); + formData.append("hora", hora); + formData.append("dia", dia); + formData.append("salon", salon); + formData.append("profesor", profesor); + const response = await fetch("action/action_horario_update.php", { + method: "POST", + body: formData + }).then(res => res.json()); + if (response.status == "success") { + triggerMessage(response.message, "Éxito", "success"); + btn.innerHTML = ' Guardado'; + btn.classList.add("btn-success"); + btn.classList.remove("btn-primary"); + // return to the initial state + setTimeout(() => { + buscarGrupo(); + btn.replaceWith(clone); + $("#modal-editar").modal("hide"); + }, 1000); + } + else { + triggerMessage(response.message, "Error"); + btn.replaceWith(clone); + $("#modal-editar").modal("hide"); + } +} +function triggerMessage(message, header, colour = "danger") { + throw new Error('Function not implemented.'); +} diff --git a/js/consultar_horarios.js b/js/consultar_horarios.js index 4d300a5..e6715d8 100644 --- a/js/consultar_horarios.js +++ b/js/consultar_horarios.js @@ -1,981 +1,981 @@ -import { - triggerMessage -} from './module/messages.js'; -var gHorarios = []; - -/**@Auxiliary functions */ -function listProfesor({ - id, - grado, - profesor, - clave -}) { - const li = document.createElement('li'); - li.setAttribute('data-id', id); - li.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center'); - li.innerHTML = `${clave} | ${grado} ${profesor}` - - const btn = document.createElement('button'); - btn.setAttribute('type', 'button'); - btn.classList.add('badge', 'badge-danger', 'badge-pill', 'border-0'); - btn.onclick = _ => li.remove(); - - const i = document.createElement('i'); - i.classList.add('ing-cancelar'); - btn.appendChild(i); - li.appendChild(btn); - - document.getElementById("profesores").appendChild(li); -} -// function for comparing two hours in format hh:mm (24 hours) and return the spaceship operator -function compareHours(hora1, hora2) { - // parseInt each hour and minute - const [h1, m1, ] = hora1.split(":").map(x => parseInt(x)); - const [h2, m2, ] = hora2.split(":").map(x => parseInt(x)); - - if (h1 > h2) - return 1; - else if (h1 < h2) - return -1; - else if (m1 > m2) - return 1; - else if (m1 < m2) - return -1; - else - return 0; -} -async function buscarGrupo() { - - // Add loading animation in the button - const btn = document.querySelector("#btn-buscar"); - btn.innerHTML = ' Cargando...'; - btn.disabled = true; - - const carrera = document.querySelector("#filter_carrera").value; - const grupo = document.querySelector("#filter_grupo").value; - - if (carrera == "" || grupo == "") { - triggerMessage("El nombre del grupo y la carrera son requeridos", "Faltan campos"); - - // Remove loading animation in the button - btn.innerHTML = ' Buscar'; - btn.disabled = false; - - return; - } - const formData = new FormData(); - - formData.append("carrera", carrera); - formData.append("grupo", grupo); - formData.append("periodo", document.querySelector("#periodo").value); - formData.append('facultad', 'facultad['facultad_id'] ?>'); - - try { - gHorarios = []; - const { - status, - horario: horarios, - } = await fetch("action/action_horario.php", { - method: "POST", - body: formData - }).then(res => res.json()); - - if (status != "success") { - triggerMessage(response.message, "Error"); - // Remove loading animation in the button - btn.innerHTML = /* HTML */ ` Buscar`; - btn.disabled = false; - } - // show the table - table.style.display = "table"; - document.querySelectorAll('.hidden').forEach(element => element.style.display = "block"); - // clear the table - table.innerHTML = empty_table; - - if (horarios.length == 0) { - // reload window - window.location.reload(); - return; - } - // fill the table - gHorarios = horarios; - - 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 the days are different, there is no conflict - if (dia1 != dia2) { - return false; - } - - const compareInicios = compareHours(hora_inicio1, hora_inicio2); - const compareFinales = compareHours(hora_final1, hora_final2); - const compareInicioFinal = compareHours(hora_inicio1, hora_final2); - const compareFinalInicio = compareHours(hora_final1, hora_inicio2); - - // if the horario is inside the other - if (compareInicios === 0 || compareFinales === 0) - return true - if (compareInicios === 1 && compareInicioFinal === -1) - return true - if (compareFinales === -1 && compareFinalInicio === 1) - return true - - // if the horario is outside the other - if (compareInicios === -1 && compareFinales === 1) - return true - - return false; - } - - // remove the next 5 cells - function removeNextCells(horas, minutos, dia, cells = 5) { - [...Array(cells).keys()].map(i => i + 1).forEach(i => { - const minute = (minutos + i * 15) - const next_minute = (minute % 60).toString().padStart(2, "0"); - const next_hour = (horas + Math.floor(minute / 60)) - - document.getElementById(`hora-${next_hour}:${next_minute}-${dia}`).remove() - }); - } - - function newBlock(horario, edit = false) { - function move(horario, cells) { - const { - hora: hora_inicio, - dia, - } = horario; - - const [horas, minutos] = hora_inicio.split(":").map(x => parseInt(x)); - - const cell = document.getElementById(`hora-${horas}:${minutos.toString().padStart(2, "0")}-${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, dia, cells); - } - const { - id, - materia, - salon, - profesores, - hora: hora_inicio, - dia, - bloques - } = horario; - - const [horas, minutos] = hora_inicio.split(":").map(x => parseInt(x)); - const hora = `${horas}:${minutos.toString().padStart(2, "0")}`; - horario.hora = hora; - - const cell = document.getElementById(`hora-${hora}-${dia}`); - - - cell.dataset.ids = id; - - cell.innerHTML = /*html*/ ` - ${hora} - ${materia}
      -
      Salón: ${salon}
      - - ${profesores.map(({grado, profesor}) => /*html*/ ` ${grado} ${profesor}`).join("
      ")} -
      ` - - if (edit) - cell.innerHTML += /*html*/ - ` - ` - - cell.classList.add("bloque-clase", "position-relative"); - cell.rowSpan = bloques; - // draggable - cell.draggable = ; - - bloques > 0 ? removeNextCells(horas, minutos, dia, bloques - 1) : null; - } - - 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 = /* HTML */ ` - - ${hora} - -
      -
      - - - Empalme de ${ids.length} horarios -
      - Ver horarios … -
      -
      - `; - - // the text must be centered - // cell.style.backgroundColor = "#f6cfd6"; - cell.classList.add("conflict", "bloque-clase"); - // add cursor clickable role = "button" - cell.setAttribute("role", "button"); - - // add the event listener for the cell - cell.addEventListener("click", () => { - $("#modal-choose").modal("show"); - const ids = cell.getAttribute("data-ids").split(",").map(x => parseInt(x)); - const horarios = gHorarios.filter(horario => ids.includes(horario.id)); - const tbody = document.querySelector("#modal-choose tbody"); - tbody.innerHTML = ""; - horarios.sort((a, b) => compareHours(a.hora, b.hora)).forEach(horario => { - const { - materia, - dia, - hora, - hora_final, - profesores, - salon, - id, - } = horario; - - // remove the last 00 of the hour - const [horaFmt, hora_finalFmt] = [hora, hora_final].map(hora => hora.slice(0, -3)) - const buttons = /* HTML */ ` - - - - - - ` - - tbody.innerHTML += /* HTML */ ` - - ${horaFmt}-${hora_finalFmt} - ${materia} - - ${profesores.map(({ grado, profesor }) => `${grado} ${profesor}`).join(", ")} - - ${salon} - ${edit ? buttons : ""} - `; - }); - - document.querySelectorAll(".dismiss-editar").forEach(btn => { - btn.addEventListener("click", () => $("#modal-choose").modal("hide")); - }); - - }); - - // blocks is (firsthour - lasthour) / 15 minutes - // sum the duracion_bloques of each horario - 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 diff = date_f - date_i; - return diff / (1000 * 60 * 15); - } - - const lastHorario = horarios[horarios.length - 1]; - // remove the next cells - // get the max hora_final - 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 blocks = getDuration(first_horario.hora, `${maxHoraFinal.getHours()}:${maxHoraFinal.getMinutes()}`); - cell.rowSpan = blocks - 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, ) - ) - - conflictBlocksPacked.forEach(horarios => - newConflictBlock(horarios, ) - ) - - // 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") - ); - }); - - } catch (error) { - triggerMessage("Error al cargar el horario", "Error"); - triggerMessage(error, "Error"); - } - - // 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 = /* for data-ids */ dragging.getAttribute("data-ids"); - const hora = /* for data-hora */ this.id.split("-")[1]; - const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]; - let día = /* for data-dia */ 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; - } - - - moveHorario(id, día, hora); - } - - element.addEventListener("dragover", dragOver); - element.addEventListener("dragleave", dragLeave); - element.addEventListener("drop", drop); - }); - - - // Remove loading animation in the button - btn.innerHTML = ' Buscar'; - btn.disabled = false; - - // console.table(gHorarios); -} - -async function guardar(id) { - const btn = document.querySelector("#btn-guardar"); - const clone = btn.cloneNode(true); - btn.innerHTML = ' Guardando...'; - btn.disabled = true; - - const data = { - dia: document.querySelector("#editor_dia"), - salon: document.querySelector("#editor_salón"), - //vprofesor: document.querySelector("#editor_profesor"), - duración: document.querySelector("#editor_duración") - }; - - const dia = data.dia.value; - const salon = data.salon.value; - - if (salon == "") { - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - return; - } - - const hora = document.querySelector("#selector_horas").value; - const minutos = document.querySelector("#selector_minutos").value; - const bloques = document.querySelector("#dlduración li.selected").getAttribute("data-bloques"); - - const start = moment(`${hora}:${minutos}`, "HH:mm").add(bloques * 15, "minutes"); - const end = moment("22:00", "HH:mm"); - - if (start.isAfter(end)) { - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - document.querySelector("#dlduración").classList.add("is-invalid"); - return; - } - - const profesoresList = [...document.querySelectorAll("#profesores li")]; - - if (profesoresList.length == 0) { - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - return; - } - - const formData = new FormData(); - // const id = btn.getAttribute("data-id"); - formData.append("id", id); - const horas = document.querySelectorAll("#selector_horas, #selector_minutos") - formData.append("hora", `${horas[0].value}:${horas[1].value}`); - formData.append("día", dia); - formData.append("salón", salon); - const profesores = profesoresList.map(li => li.getAttribute("data-id")); - formData.append("duración", data.duración.value); - formData.append("profesores", profesores.join(",")); - - - const response = await fetch("action/action_horario_update.php", { - method: "POST", - body: formData - }).then(res => res.json()); - - if (response.status == "success") { - triggerMessage("Horario actualizado", "Éxito", "success"); - btn.innerHTML = ' Guardado'; - btn.classList.add("btn-success"); - btn.classList.remove("btn-primary"); - - // return to the initial state - setTimeout(() => { - buscarGrupo(); - btn.replaceWith(clone); - $("#modal-editar").modal("hide"); - }, 100); - } else { - triggerMessage(response.message, "Error"); - btn.replaceWith(clone); - - $("#modal-editar").modal("hide"); - } - -} -async function borrarHorario(id) { - const btn = document.querySelector("#btn-borrar"); - const clone = btn.cloneNode(true); - btn.innerHTML = ' Borrando...'; - btn.disabled = true; - - const formData = new FormData(); - formData.append("id", id); - - const response = await fetch("action/action_horario_delete.php", { - method: "POST", - body: formData - }).then(res => res.json()); - - if (response.status == "success") { - triggerMessage('Horario borrado', "Éxito", "success"); - btn.innerHTML = ' Borrado'; - btn.classList.add("btn-success"); - btn.classList.remove("btn-danger"); - - // return to the initial state - setTimeout(() => { - buscarGrupo(); - btn.replaceWith(clone); - $("#modal-borrar").modal("hide"); - }, 1000); - } else { - triggerMessage(response.message, "Error"); - btn.replaceWith(clone); - - $("#modal-borrar").modal("hide"); - } - -} - -function guardarHorario() { - let goBack = false; - const btn = document.querySelector("#btn-guardar-horario"); - const clone = btn.cloneNode(true); - btn.innerHTML = ' Guardando...'; - btn.disabled = true; - - const data = { - dia: document.querySelector("#new_dia"), - salon: document.querySelector("#new_salón"), - profesor: document.querySelector("#new_profesor"), - duración: document.querySelector("#new_duración"), - materia: document.querySelector("#new_materia") - }; - - const dia = data.dia.value; - const salon = data.salon.value; - const profesor = data.profesor.value; - const materia = data.materia.value; - const duración = data.duración.value; - - if (duración == "") { - invalidDatalist("#new_duración"); - goBack = true; - } - - if (profesor == "") { - data.profesor.classList.add("is-invalid"); - goBack = true; - } - - if (salon == "") { - data.salon.classList.add("is-invalid"); - goBack = true; - } - - if (dia == "") { - invalidDatalist("#new_dia"); - goBack = true; - } - - if (materia == "") { - data.materia.classList.add("is-invalid"); - goBack = true; - } - - const hora = document.querySelector("#new_horas").value; - if (hora == "") { - invalidDatalist("#new_horas"); - goBack = true; - } - const minutos = document.querySelector("#new_minutos").value; - if (minutos == "") { - invalidDatalist("#new_minutos"); - goBack = true; - } - - const bloques = document.querySelector("#dlNewDuración li.selected")?.getAttribute("data-bloques"); - const start = moment(`${hora}:${minutos}`, "HH:mm").add(bloques * 15, "minutes"); - const end = moment("22:00", "HH:mm"); - - if (start.isAfter(end)) { - document.querySelector("#dlNewDuración").classList.add("is-invalid"); - goBack = true; - } - - if (goBack) { - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - return; - } - - const formData = new FormData(); - formData.append("grupo", document.querySelector("#filter_grupo").value); - formData.append("hora", `${hora}:${minutos}`); - formData.append("día", dia); - formData.append("salón", salon); - formData.append("profesor", profesor); - formData.append("duración", data.duración.value); - formData.append("periodo", "periodo ?>"); - formData.append("materia", materia); - formData.append("facultad", "facultad['facultad_id'] ?>"); - - - fetch("action/action_horario_create.php", { - method: "POST", - body: formData - }).then(res => res.json()).then(response => { - if (response.status == "success") { - triggerMessage("Horario guardado", "Éxito", "success"); - btn.innerHTML = /* html */ ` Guardado`; - btn.classList.add("btn-success"); - btn.classList.remove("btn-primary"); - - // return to the initial state - setTimeout(() => { - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - btn.classList.remove("btn-success"); - btn.classList.add("btn-primary"); - - - // this modal - $("#modal-nuevo").modal("hide"); - const modalNuevo = document.querySelector("#modal-nuevo"); - modalNuevo.querySelectorAll("input").forEach(input => { - input.value = ""; - }); - - // reset the datalist - modalNuevo.querySelectorAll(".datalist").forEach(datalist => { - const cloneDatalist = modalNuevoClone.querySelector(`#${datalist.id}`).cloneNode(true); - // log - datalist.replaceWith(cloneDatalist); - }); - // remove all is-valid and is-invalid - modalNuevo.querySelectorAll(".is-valid, .is-invalid").forEach(el => { - el.classList.remove("is-valid", "is-invalid"); - }); - - }, 100); - } else { - triggerMessage(response.message, "Error"); - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - - - $("#modal-nuevo").modal("hide"); - } - }).then(() => { - buscarGrupo(); - }).catch(err => { - triggerMessage(err, "Error"); - btn.innerHTML = clone.innerHTML; - btn.disabled = false; - - $("#modal-nuevo").modal("hide"); - }); - - // buscarGrupo(); -} - -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(() => { - buscarGrupo(); - }).catch(err => { - triggerMessage(err, "Error"); - }); - -} - -// initial state -{ - // fill the table with empty cells - [...Array(16).keys()].map(x => x + 7).forEach(hora => { - // add 7 rows for each hour - [0, 15, 30, 45].map(minute => minute.toString().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 == 0) { - 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); - }); - document.querySelector("tbody#horario").appendChild(tr); - }); - }) - - // add an inital height to the table cells - // query selector All tds and ths inside the tbody#horario - // previous query selector: "tbody#horario td, tbody#horario tr" - document.querySelectorAll("tbody#horario td, tbody#horario tr").forEach(element => element.style.height = "2rem"); - document.getElementById('btn-buscar').addEventListener('click', buscarGrupo); - document.getElementById('dlProfesor').addEventListener('input', function(e) { - var input = document.getElementById('dlProfesor'); - var value = input.value; - var option = document.querySelector(`option[value="${value}"]`); - - if (!option) { - document.getElementById('editor_profesor').value = ""; - // remove is valid class - input.classList.remove("is-valid"); - // add is invalid class - input.classList.add("is-invalid"); - return - } - - var id = option.getAttribute('data-id'); - if (!document.querySelector(`li[data-id="${id}"]`)) - listProfesor({ - id: id, - grado: option.getAttribute('data-grado'), - profesor: option.getAttribute('data-profesor'), - clave: option.getAttribute('data-clave') - }); - e.target.value = ""; - }); -} - -// state -const table = document.querySelector("table"); -const empty_table = table.innerHTML; -document.querySelectorAll('.hidden').forEach(element => element.style.display = "none"); -// hide the table -table.style.display = "none"; -disableDatalist("#filter_grupo"); - -document.getElementById("btn-excel-horario").addEventListener("click", () => { - const formData = new FormData(); - const grupo = document.getElementById("filter_grupo").value; - formData.append("grupo", grupo); - formData.append('sábado', gHorarios.some(horario => horario.dia == "sábado")); - formData.append("horarios", JSON.stringify(gHorarios)); - // min and max hour - formData.append("min", gHorarios.reduce((min, horario) => { - const hora = horario.hora.split(":").map(x => parseInt(x))[0] - return Math.min(hora, min); - }, 24)); - formData.append("max", gHorarios.reduce((max, horario) => { - const { - hora, - bloques - } = horario; - // after hour - const lastHour = moment(hora, "HH:mm").add(bloques * 15, "minutes"); - const lastMoment = moment(`${lastHour.format("HH")}:00`, "HH:mm"); - const intHour = parseInt(lastHour.format("HH")); - - return Math.max(lastMoment.isSame(lastHour) ? intHour - 1 : intHour, max); - }, 0)); - - fetch("export/horario_excel.php", { - method: "POST", - body: formData - }) - .then(response => response.blob()) - .then(blob => { - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.style.display = 'none'; - a.setAttribute('href', url); - a.setAttribute('download', `horario-${grupo}.xlsx`); - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(url); - }) - .catch(() => triggerMessage("error", "Error al exportar el horario")); -}); - -// on click the li element, inside datalist #dlcarera -document.querySelectorAll("#dlcarrera li").forEach(async li => { - li.addEventListener("click", async () => { - // get the data-id from the li element - const carrera = li.getAttribute("data-id"); - const facultad = 'facultad['facultad_id'] ?>'; - const periodo = 'periodo ?>'; - - const formData = new FormData(); - formData.append("carrera", carrera); - formData.append("facultad", facultad); - formData.append("periodo", periodo); - - try { - const { - status, - grupos - } = await fetch("action/action_grupo.php", { - method: "POST", - body: formData - }).then(res => res.json()); - - if (status != "success") { - throw new Error("Error al cargar los grupos"); - } else if (grupos.length == 0) { - throw new Error("No hay grupos para esta carrera"); - } - - const dlgrupo = document.querySelector("#dlgrupo ul"); - const prompt = document.querySelector("#dlgrupo .datalist-input"); - dlgrupo.innerHTML = ""; - - grupos.forEach(grupo => { - const li = document.createElement("li"); - // data-id is the id of the group - li.setAttribute("data-id", grupo); - li.textContent = grupo; - dlgrupo.appendChild(li); - }); - - // write Seleccionar grupo - prompt.textContent = "Seleccionar grupo"; - - disableDatalist("#filter_grupo", false); - - // to #filter_grupo input value - const filter_grupo = document.querySelector("#filter_grupo"); - filter_grupo.value = ""; - } catch (error) { - // remove Error: from the error message - error = error.toString().replace("Error: ", ""); - triggerMessage(error, "Error"); - console.error(error); - } - - const datalist = document.querySelector("#materias"); - const materias = await fetch("action/action_materias.php", { - method: "POST", - body: formData - }).then(res => res.json()); - }); - -}) - -// on modal edit, show the data -$("#modal-editar").on("show.bs.modal", async function(event) { - document.querySelectorAll("#modal-editar .is-invalid, #modal-editar .is-valid")?.forEach(element => element.classList.remove("is-invalid", "is-valid")); - - const button = event.relatedTarget; - const parentId = button.parentElement.parentElement.getAttribute("data-ids"); - - const { - id, - dia, - hora, - materia, - salon, - profesores, - duracion - } = gHorarios?.find(horario => horario.id == parentId); - - // search the data-id of the day and click it - const númeroDía = ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'].reduce((acc, curr, key) => (curr == dia) ? key : acc); - document.querySelector(`#dldia li[data-id="${númeroDía}"]`)?.click(); - document.querySelector(`#dlduración li[data-id="${duracion}"]`)?.click(); - const horas = hora.split(":")[0]; - const minutos = hora.split(":")[1]; - - setDatalist("#selector_horas", horas); - setDatalist("#selector_minutos", minutos); - document.getElementById('editor_salón').value = salon; - - - // get the option with data-id profesor - document.getElementById("profesores").innerHTML = ""; - profesores.forEach(listProfesor); - - const btnGuardar = document.getElementById('btn-guardar'); - btnGuardar.onclick = () => guardar(id); -}) - -$("#modal-borrar").modal({ - show: false, - backdrop: "static", - keyboard: false, -}) - -$("#modal-borrar").on("show.bs.modal", async function(event) { - const button = event.relatedTarget; - const id = button.parentElement.parentElement.getAttribute("data-ids"); - - const btnBorrar = document.getElementById('btn-borrar'); - btnBorrar.onclick = () => borrarHorario(id); +import { + triggerMessage +} from './module/messages.js'; +var gHorarios = []; + +/**@Auxiliary functions */ +function listProfesor({ + id, + grado, + profesor, + clave +}) { + const li = document.createElement('li'); + li.setAttribute('data-id', id); + li.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center'); + li.innerHTML = `${clave} | ${grado} ${profesor}` + + const btn = document.createElement('button'); + btn.setAttribute('type', 'button'); + btn.classList.add('badge', 'badge-danger', 'badge-pill', 'border-0'); + btn.onclick = _ => li.remove(); + + const i = document.createElement('i'); + i.classList.add('ing-cancelar'); + btn.appendChild(i); + li.appendChild(btn); + + document.getElementById("profesores").appendChild(li); +} +// function for comparing two hours in format hh:mm (24 hours) and return the spaceship operator +function compareHours(hora1, hora2) { + // parseInt each hour and minute + const [h1, m1, ] = hora1.split(":").map(x => parseInt(x)); + const [h2, m2, ] = hora2.split(":").map(x => parseInt(x)); + + if (h1 > h2) + return 1; + else if (h1 < h2) + return -1; + else if (m1 > m2) + return 1; + else if (m1 < m2) + return -1; + else + return 0; +} +async function buscarGrupo() { + + // Add loading animation in the button + const btn = document.querySelector("#btn-buscar"); + btn.innerHTML = ' Cargando...'; + btn.disabled = true; + + const carrera = document.querySelector("#filter_carrera").value; + const grupo = document.querySelector("#filter_grupo").value; + + if (carrera == "" || grupo == "") { + triggerMessage("El nombre del grupo y la carrera son requeridos", "Faltan campos"); + + // Remove loading animation in the button + btn.innerHTML = ' Buscar'; + btn.disabled = false; + + return; + } + const formData = new FormData(); + + formData.append("carrera", carrera); + formData.append("grupo", grupo); + formData.append("periodo", document.querySelector("#periodo").value); + formData.append('facultad', 'facultad['facultad_id'] ?>'); + + try { + gHorarios = []; + const { + status, + horario: horarios, + } = await fetch("action/action_horario.php", { + method: "POST", + body: formData + }).then(res => res.json()); + + if (status != "success") { + triggerMessage(response.message, "Error"); + // Remove loading animation in the button + btn.innerHTML = /* HTML */ ` Buscar`; + btn.disabled = false; + } + // show the table + table.style.display = "table"; + document.querySelectorAll('.hidden').forEach(element => element.style.display = "block"); + // clear the table + table.innerHTML = empty_table; + + if (horarios.length == 0) { + // reload window + window.location.reload(); + return; + } + // fill the table + gHorarios = horarios; + + 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 the days are different, there is no conflict + if (dia1 != dia2) { + return false; + } + + const compareInicios = compareHours(hora_inicio1, hora_inicio2); + const compareFinales = compareHours(hora_final1, hora_final2); + const compareInicioFinal = compareHours(hora_inicio1, hora_final2); + const compareFinalInicio = compareHours(hora_final1, hora_inicio2); + + // if the horario is inside the other + if (compareInicios === 0 || compareFinales === 0) + return true + if (compareInicios === 1 && compareInicioFinal === -1) + return true + if (compareFinales === -1 && compareFinalInicio === 1) + return true + + // if the horario is outside the other + if (compareInicios === -1 && compareFinales === 1) + return true + + return false; + } + + // remove the next 5 cells + function removeNextCells(horas, minutos, dia, cells = 5) { + [...Array(cells).keys()].map(i => i + 1).forEach(i => { + const minute = (minutos + i * 15) + const next_minute = (minute % 60).toString().padStart(2, "0"); + const next_hour = (horas + Math.floor(minute / 60)) + + document.getElementById(`hora-${next_hour}:${next_minute}-${dia}`).remove() + }); + } + + function newBlock(horario, edit = false) { + function move(horario, cells) { + const { + hora: hora_inicio, + dia, + } = horario; + + const [horas, minutos] = hora_inicio.split(":").map(x => parseInt(x)); + + const cell = document.getElementById(`hora-${horas}:${minutos.toString().padStart(2, "0")}-${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, dia, cells); + } + const { + id, + materia, + salon, + profesores, + hora: hora_inicio, + dia, + bloques + } = horario; + + const [horas, minutos] = hora_inicio.split(":").map(x => parseInt(x)); + const hora = `${horas}:${minutos.toString().padStart(2, "0")}`; + horario.hora = hora; + + const cell = document.getElementById(`hora-${hora}-${dia}`); + + + cell.dataset.ids = id; + + cell.innerHTML = /*html*/ ` + ${hora} + ${materia}
      +
      Salón: ${salon}
      + + ${profesores.map(({grado, profesor}) => /*html*/ ` ${grado} ${profesor}`).join("
      ")} +
      ` + + if (edit) + cell.innerHTML += /*html*/ + ` + ` + + cell.classList.add("bloque-clase", "position-relative"); + cell.rowSpan = bloques; + // draggable + cell.draggable = ; + + bloques > 0 ? removeNextCells(horas, minutos, dia, bloques - 1) : null; + } + + 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 = /* HTML */ ` + + ${hora} + +
      +
      + + + Empalme de ${ids.length} horarios +
      + Ver horarios … +
      +
      + `; + + // the text must be centered + // cell.style.backgroundColor = "#f6cfd6"; + cell.classList.add("conflict", "bloque-clase"); + // add cursor clickable role = "button" + cell.setAttribute("role", "button"); + + // add the event listener for the cell + cell.addEventListener("click", () => { + $("#modal-choose").modal("show"); + const ids = cell.getAttribute("data-ids").split(",").map(x => parseInt(x)); + const horarios = gHorarios.filter(horario => ids.includes(horario.id)); + const tbody = document.querySelector("#modal-choose tbody"); + tbody.innerHTML = ""; + horarios.sort((a, b) => compareHours(a.hora, b.hora)).forEach(horario => { + const { + materia, + dia, + hora, + hora_final, + profesores, + salon, + id, + } = horario; + + // remove the last 00 of the hour + const [horaFmt, hora_finalFmt] = [hora, hora_final].map(hora => hora.slice(0, -3)) + const buttons = /* HTML */ ` + + + + + + ` + + tbody.innerHTML += /* HTML */ ` + + ${horaFmt}-${hora_finalFmt} + ${materia} + + ${profesores.map(({ grado, profesor }) => `${grado} ${profesor}`).join(", ")} + + ${salon} + ${edit ? buttons : ""} + `; + }); + + document.querySelectorAll(".dismiss-editar").forEach(btn => { + btn.addEventListener("click", () => $("#modal-choose").modal("hide")); + }); + + }); + + // blocks is (firsthour - lasthour) / 15 minutes + // sum the duracion_bloques of each horario + 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 diff = date_f - date_i; + return diff / (1000 * 60 * 15); + } + + const lastHorario = horarios[horarios.length - 1]; + // remove the next cells + // get the max hora_final + 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 blocks = getDuration(first_horario.hora, `${maxHoraFinal.getHours()}:${maxHoraFinal.getMinutes()}`); + cell.rowSpan = blocks + 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, ) + ) + + conflictBlocksPacked.forEach(horarios => + newConflictBlock(horarios, ) + ) + + // 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") + ); + }); + + } catch (error) { + triggerMessage("Error al cargar el horario", "Error"); + triggerMessage(error, "Error"); + } + + // 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 = /* for data-ids */ dragging.getAttribute("data-ids"); + const hora = /* for data-hora */ this.id.split("-")[1]; + const días = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]; + let día = /* for data-dia */ 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; + } + + + moveHorario(id, día, hora); + } + + element.addEventListener("dragover", dragOver); + element.addEventListener("dragleave", dragLeave); + element.addEventListener("drop", drop); + }); + + + // Remove loading animation in the button + btn.innerHTML = ' Buscar'; + btn.disabled = false; + + // console.table(gHorarios); +} + +async function guardar(id) { + const btn = document.querySelector("#btn-guardar"); + const clone = btn.cloneNode(true); + btn.innerHTML = ' Guardando...'; + btn.disabled = true; + + const data = { + dia: document.querySelector("#editor_dia"), + salon: document.querySelector("#editor_salón"), + //vprofesor: document.querySelector("#editor_profesor"), + duración: document.querySelector("#editor_duración") + }; + + const dia = data.dia.value; + const salon = data.salon.value; + + if (salon == "") { + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + return; + } + + const hora = document.querySelector("#selector_horas").value; + const minutos = document.querySelector("#selector_minutos").value; + const bloques = document.querySelector("#dlduración li.selected").getAttribute("data-bloques"); + + const start = moment(`${hora}:${minutos}`, "HH:mm").add(bloques * 15, "minutes"); + const end = moment("22:00", "HH:mm"); + + if (start.isAfter(end)) { + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + document.querySelector("#dlduración").classList.add("is-invalid"); + return; + } + + const profesoresList = [...document.querySelectorAll("#profesores li")]; + + if (profesoresList.length == 0) { + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + return; + } + + const formData = new FormData(); + // const id = btn.getAttribute("data-id"); + formData.append("id", id); + const horas = document.querySelectorAll("#selector_horas, #selector_minutos") + formData.append("hora", `${horas[0].value}:${horas[1].value}`); + formData.append("día", dia); + formData.append("salón", salon); + const profesores = profesoresList.map(li => li.getAttribute("data-id")); + formData.append("duración", data.duración.value); + formData.append("profesores", profesores.join(",")); + + + const response = await fetch("action/action_horario_update.php", { + method: "POST", + body: formData + }).then(res => res.json()); + + if (response.status == "success") { + triggerMessage("Horario actualizado", "Éxito", "success"); + btn.innerHTML = ' Guardado'; + btn.classList.add("btn-success"); + btn.classList.remove("btn-primary"); + + // return to the initial state + setTimeout(() => { + buscarGrupo(); + btn.replaceWith(clone); + $("#modal-editar").modal("hide"); + }, 100); + } else { + triggerMessage(response.message, "Error"); + btn.replaceWith(clone); + + $("#modal-editar").modal("hide"); + } + +} +async function borrarHorario(id) { + const btn = document.querySelector("#btn-borrar"); + const clone = btn.cloneNode(true); + btn.innerHTML = ' Borrando...'; + btn.disabled = true; + + const formData = new FormData(); + formData.append("id", id); + + const response = await fetch("action/action_horario_delete.php", { + method: "POST", + body: formData + }).then(res => res.json()); + + if (response.status == "success") { + triggerMessage('Horario borrado', "Éxito", "success"); + btn.innerHTML = ' Borrado'; + btn.classList.add("btn-success"); + btn.classList.remove("btn-danger"); + + // return to the initial state + setTimeout(() => { + buscarGrupo(); + btn.replaceWith(clone); + $("#modal-borrar").modal("hide"); + }, 1000); + } else { + triggerMessage(response.message, "Error"); + btn.replaceWith(clone); + + $("#modal-borrar").modal("hide"); + } + +} + +function guardarHorario() { + let goBack = false; + const btn = document.querySelector("#btn-guardar-horario"); + const clone = btn.cloneNode(true); + btn.innerHTML = ' Guardando...'; + btn.disabled = true; + + const data = { + dia: document.querySelector("#new_dia"), + salon: document.querySelector("#new_salón"), + profesor: document.querySelector("#new_profesor"), + duración: document.querySelector("#new_duración"), + materia: document.querySelector("#new_materia") + }; + + const dia = data.dia.value; + const salon = data.salon.value; + const profesor = data.profesor.value; + const materia = data.materia.value; + const duración = data.duración.value; + + if (duración == "") { + invalidDatalist("#new_duración"); + goBack = true; + } + + if (profesor == "") { + data.profesor.classList.add("is-invalid"); + goBack = true; + } + + if (salon == "") { + data.salon.classList.add("is-invalid"); + goBack = true; + } + + if (dia == "") { + invalidDatalist("#new_dia"); + goBack = true; + } + + if (materia == "") { + data.materia.classList.add("is-invalid"); + goBack = true; + } + + const hora = document.querySelector("#new_horas").value; + if (hora == "") { + invalidDatalist("#new_horas"); + goBack = true; + } + const minutos = document.querySelector("#new_minutos").value; + if (minutos == "") { + invalidDatalist("#new_minutos"); + goBack = true; + } + + const bloques = document.querySelector("#dlNewDuración li.selected")?.getAttribute("data-bloques"); + const start = moment(`${hora}:${minutos}`, "HH:mm").add(bloques * 15, "minutes"); + const end = moment("22:00", "HH:mm"); + + if (start.isAfter(end)) { + document.querySelector("#dlNewDuración").classList.add("is-invalid"); + goBack = true; + } + + if (goBack) { + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + return; + } + + const formData = new FormData(); + formData.append("grupo", document.querySelector("#filter_grupo").value); + formData.append("hora", `${hora}:${minutos}`); + formData.append("día", dia); + formData.append("salón", salon); + formData.append("profesor", profesor); + formData.append("duración", data.duración.value); + formData.append("periodo", "periodo ?>"); + formData.append("materia", materia); + formData.append("facultad", "facultad['facultad_id'] ?>"); + + + fetch("action/action_horario_create.php", { + method: "POST", + body: formData + }).then(res => res.json()).then(response => { + if (response.status == "success") { + triggerMessage("Horario guardado", "Éxito", "success"); + btn.innerHTML = /* html */ ` Guardado`; + btn.classList.add("btn-success"); + btn.classList.remove("btn-primary"); + + // return to the initial state + setTimeout(() => { + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + btn.classList.remove("btn-success"); + btn.classList.add("btn-primary"); + + + // this modal + $("#modal-nuevo").modal("hide"); + const modalNuevo = document.querySelector("#modal-nuevo"); + modalNuevo.querySelectorAll("input").forEach(input => { + input.value = ""; + }); + + // reset the datalist + modalNuevo.querySelectorAll(".datalist").forEach(datalist => { + const cloneDatalist = modalNuevoClone.querySelector(`#${datalist.id}`).cloneNode(true); + // log + datalist.replaceWith(cloneDatalist); + }); + // remove all is-valid and is-invalid + modalNuevo.querySelectorAll(".is-valid, .is-invalid").forEach(el => { + el.classList.remove("is-valid", "is-invalid"); + }); + + }, 100); + } else { + triggerMessage(response.message, "Error"); + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + + + $("#modal-nuevo").modal("hide"); + } + }).then(() => { + buscarGrupo(); + }).catch(err => { + triggerMessage(err, "Error"); + btn.innerHTML = clone.innerHTML; + btn.disabled = false; + + $("#modal-nuevo").modal("hide"); + }); + + // buscarGrupo(); +} + +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(() => { + buscarGrupo(); + }).catch(err => { + triggerMessage(err, "Error"); + }); + +} + +// initial state +{ + // fill the table with empty cells + [...Array(16).keys()].map(x => x + 7).forEach(hora => { + // add 7 rows for each hour + [0, 15, 30, 45].map(minute => minute.toString().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 == 0) { + 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); + }); + document.querySelector("tbody#horario").appendChild(tr); + }); + }) + + // add an inital height to the table cells + // query selector All tds and ths inside the tbody#horario + // previous query selector: "tbody#horario td, tbody#horario tr" + document.querySelectorAll("tbody#horario td, tbody#horario tr").forEach(element => element.style.height = "2rem"); + document.getElementById('btn-buscar').addEventListener('click', buscarGrupo); + document.getElementById('dlProfesor').addEventListener('input', function(e) { + var input = document.getElementById('dlProfesor'); + var value = input.value; + var option = document.querySelector(`option[value="${value}"]`); + + if (!option) { + document.getElementById('editor_profesor').value = ""; + // remove is valid class + input.classList.remove("is-valid"); + // add is invalid class + input.classList.add("is-invalid"); + return + } + + var id = option.getAttribute('data-id'); + if (!document.querySelector(`li[data-id="${id}"]`)) + listProfesor({ + id: id, + grado: option.getAttribute('data-grado'), + profesor: option.getAttribute('data-profesor'), + clave: option.getAttribute('data-clave') + }); + e.target.value = ""; + }); +} + +// state +const table = document.querySelector("table"); +const empty_table = table.innerHTML; +document.querySelectorAll('.hidden').forEach(element => element.style.display = "none"); +// hide the table +table.style.display = "none"; +disableDatalist("#filter_grupo"); + +document.getElementById("btn-excel-horario").addEventListener("click", () => { + const formData = new FormData(); + const grupo = document.getElementById("filter_grupo").value; + formData.append("grupo", grupo); + formData.append('sábado', gHorarios.some(horario => horario.dia == "sábado")); + formData.append("horarios", JSON.stringify(gHorarios)); + // min and max hour + formData.append("min", gHorarios.reduce((min, horario) => { + const hora = horario.hora.split(":").map(x => parseInt(x))[0] + return Math.min(hora, min); + }, 24)); + formData.append("max", gHorarios.reduce((max, horario) => { + const { + hora, + bloques + } = horario; + // after hour + const lastHour = moment(hora, "HH:mm").add(bloques * 15, "minutes"); + const lastMoment = moment(`${lastHour.format("HH")}:00`, "HH:mm"); + const intHour = parseInt(lastHour.format("HH")); + + return Math.max(lastMoment.isSame(lastHour) ? intHour - 1 : intHour, max); + }, 0)); + + fetch("export/horario_excel.php", { + method: "POST", + body: formData + }) + .then(response => response.blob()) + .then(blob => { + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.style.display = 'none'; + a.setAttribute('href', url); + a.setAttribute('download', `horario-${grupo}.xlsx`); + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + }) + .catch(() => triggerMessage("error", "Error al exportar el horario")); +}); + +// on click the li element, inside datalist #dlcarera +document.querySelectorAll("#dlcarrera li").forEach(async li => { + li.addEventListener("click", async () => { + // get the data-id from the li element + const carrera = li.getAttribute("data-id"); + const facultad = 'facultad['facultad_id'] ?>'; + const periodo = 'periodo ?>'; + + const formData = new FormData(); + formData.append("carrera", carrera); + formData.append("facultad", facultad); + formData.append("periodo", periodo); + + try { + const { + status, + grupos + } = await fetch("action/action_grupo.php", { + method: "POST", + body: formData + }).then(res => res.json()); + + if (status != "success") { + throw new Error("Error al cargar los grupos"); + } else if (grupos.length == 0) { + throw new Error("No hay grupos para esta carrera"); + } + + const dlgrupo = document.querySelector("#dlgrupo ul"); + const prompt = document.querySelector("#dlgrupo .datalist-input"); + dlgrupo.innerHTML = ""; + + grupos.forEach(grupo => { + const li = document.createElement("li"); + // data-id is the id of the group + li.setAttribute("data-id", grupo); + li.textContent = grupo; + dlgrupo.appendChild(li); + }); + + // write Seleccionar grupo + prompt.textContent = "Seleccionar grupo"; + + disableDatalist("#filter_grupo", false); + + // to #filter_grupo input value + const filter_grupo = document.querySelector("#filter_grupo"); + filter_grupo.value = ""; + } catch (error) { + // remove Error: from the error message + error = error.toString().replace("Error: ", ""); + triggerMessage(error, "Error"); + console.error(error); + } + + const datalist = document.querySelector("#materias"); + const materias = await fetch("action/action_materias.php", { + method: "POST", + body: formData + }).then(res => res.json()); + }); + +}) + +// on modal edit, show the data +$("#modal-editar").on("show.bs.modal", async function(event) { + document.querySelectorAll("#modal-editar .is-invalid, #modal-editar .is-valid")?.forEach(element => element.classList.remove("is-invalid", "is-valid")); + + const button = event.relatedTarget; + const parentId = button.parentElement.parentElement.getAttribute("data-ids"); + + const { + id, + dia, + hora, + materia, + salon, + profesores, + duracion + } = gHorarios?.find(horario => horario.id == parentId); + + // search the data-id of the day and click it + const númeroDía = ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'].reduce((acc, curr, key) => (curr == dia) ? key : acc); + document.querySelector(`#dldia li[data-id="${númeroDía}"]`)?.click(); + document.querySelector(`#dlduración li[data-id="${duracion}"]`)?.click(); + const horas = hora.split(":")[0]; + const minutos = hora.split(":")[1]; + + setDatalist("#selector_horas", horas); + setDatalist("#selector_minutos", minutos); + document.getElementById('editor_salón').value = salon; + + + // get the option with data-id profesor + document.getElementById("profesores").innerHTML = ""; + profesores.forEach(listProfesor); + + const btnGuardar = document.getElementById('btn-guardar'); + btnGuardar.onclick = () => guardar(id); +}) + +$("#modal-borrar").modal({ + show: false, + backdrop: "static", + keyboard: false, +}) + +$("#modal-borrar").on("show.bs.modal", async function(event) { + const button = event.relatedTarget; + const id = button.parentElement.parentElement.getAttribute("data-ids"); + + const btnBorrar = document.getElementById('btn-borrar'); + btnBorrar.onclick = () => borrarHorario(id); }) \ No newline at end of file diff --git a/js/custominputfile.min-es.js b/js/custominputfile.min-es.js index 9cf25f8..f974f40 100644 --- a/js/custominputfile.min-es.js +++ b/js/custominputfile.min-es.js @@ -1,75 +1,75 @@ -/* - jQuery Custom Input File Plugin - version 1.0 - Copyright 2014, Ángel Espro, www.aesolucionesweb.com.ar, - Licence : GNU General Public License - - Site: www.aesolucionesweb.com.ar/plugins/custom-input-file - - You must not remove these lines. Read gpl.txt for further legal information. -*/ -(function($){CustomFile=function(elem,options){this.elem=$(elem);this.itemFileList=[];this.defaults={type:'all',allowed:'all',notAllowed:[],addContainerAfter:$(elem),multiple:true,maxFiles:5,maxMB:0,maxKBperFile:2048,fileWrapper:'
      ',filePicker:'

      Soltar archivos aquí

      o clic para seleccionar desde carpeta

      ',image:{crop:false,preview:{display:true,maxWidth:300},cropSize:[320,225],minSize:[0,0],maxSize:[0,0]},messages:{errorType:"Tipo de archivo no permitido",errorMaxMB:"Peso máximo de archivos acumulado excedido",errorFileKB:"Archivo muy pesado",errorMaxFiles:"Cantidad máxima de archivos alcanzada",errorBigImage:"Imagen muy grande",errorSmallImage:"Imagen muy pequeña",errorOnReading:"Aplicación ocupada. Inténtelo más tarde.",errorMultipleDisable:"Suelte un archivo por vez."},popup:{active:true,autoclose:true,delay:10000},callbacks:{onComplete:function(app){},beforeRead:function(file){},onSuccess:function(item,callback){},onError:function(file,msg){},beforeRemove:function(item){},}} -this.settings=$.extend(true,{},this.defaults,options);this.status='stop';this.init();} -CustomFile.prototype={init:function(){var attnm=this.elem.attr("name");if(attnm=='')var attnm="inputfile";this.name=(attnm.indexOf("[]",attnm-2)===-1)?attnm+"[]":attnm;this.form=this.elem.parents('form');this.container=$('
      ');var image=this.settings.image;image.minSize=(typeof(image.minSize)!=='object'||image.minSize.length!==2)?[0,0]:image.minSize;if(image.crop){var minSize=[];for(i=0;iimage.cropSize[i])?image.minSize[i]:image.cropSize[i];minSize.push(value);} -image.minSize=minSize} -this.setFileWrapper();this.appendContainer();this.filePicker=new FilePicker(this);$.customFile.elements.push(this);},onSuccess:function(item,callback){this.itemFileList.push(item);if(this.settings.callbacks.onSuccess(item,callback)===false)return;callback();},onError:function(file,msg){this.settings.callbacks.onError(file,msg);var popupSet=this.settings.popup;if(popupSet.active) -for(k=0;k42)var fileName=fileName.substr(0,40)+"...";msg[k]+=' ('+fileName+'.'+fileExt+')';$.customFile.popup.add(msg[k],popupSet.autoclose,popupSet.delay,'error');}},onComplete:function(){this.status="completed";if(this.settings.multiple){var response=this.checkMaxFiles() -var popupSet=this.settings.popup;if(response&&popupSet.active)$.customFile.popup.add(response,popupSet.autoclose,popupSet.delay,'ok');}else{if(this.itemFileList.length>1)this.itemFileList[0].destroy();} -this.settings.callbacks.onComplete(this);},read:function(fileList,currentItem){var i=currentItem;if(i+1>fileList.length)this.status='completed';if(this.status==='completed'){this.onComplete();return false;} -var beforeRead=this.settings.callbacks.beforeRead(fileList[i]);if(beforeRead===false)return this.read(fileList,i+1);app=this;var response=app.checkMaxFiles(fileList[i]);if(typeof(response)==='string'){this.onError(fileList[i],[response]);return this.read(fileList,i+1);} -var msg=[];var checklist=["checkFileKB","checkFileType","checkTotalMB"] -for(j=0;j0){this.onError(fileList[i],msg);return this.read(fileList,i+1);} -new FileItem(this,fileList,i);},appendContainer:function(){var sett=this.settings;if(sett.fileWrapper.parent().length!=0&&sett.appendAfter!=this.elem){sett.addContainerAfter=sett.fileWrapper;} -sett.addContainerAfter.after(this.container);},setFileWrapper:function(){var app=this;var fwr=this.settings.fileWrapper;if(typeof(fwr)==='string')this.settings.fileWrapper=$(fwr);this.settings.fileWrapper=$('
      ',{class:"cif-file-row"}).append(this.settings.fileWrapper);var fwr=this.settings.fileWrapper;fwr.find(':input').each(function(index){var $this=$(this);var attnm=$this.attr("name");if(!attnm)var attnm=app.name.substr(0,app.name.indexOf("[]",-2))+"-"+index;if(attnm.indexOf("[]",-2)===-1){$this.attr("name",attnm+"[]");}});if(fwr.find('.cif-img').length==0&&this.settings.type=='image'){var parent=fwr.find('.cif-parent');if(parent.length===0){var $img=fwr.find('img');var parent=$('
      ',{class:'cif-parent'});parent.append($img);fwr.append(parent);} -if(parent.find('img').length===0)parent.append('') -parent.find('img').addClass("cif-img");} -if(fwr.find('.cif-parent').length==0){fwr.prepend('
      ');}},checkFileKB:function(file){if(file.size>this.settings.maxKBperFile*1024&&this.settings.maxKBperFile!=0){var msg=this.settings.messages.errorFileKB;} -return msg;},checkFileType:function(file){var ext=file.name.substr(file.name.lastIndexOf('.')+1);var ext=ext.toLowerCase();var imageCropAllowed=["jpeg","jpg","png"] -if((this.settings.type=='image'&&this.settings.image.crop&&imageCropAllowed.indexOf(ext)==-1)||(this.settings.type=='image'&&!file.type.match(/image\//))||(this.settings.allowed!='all'&&this.settings.allowed.indexOf(ext)==-1)||(this.settings.notAllowed.indexOf(ext)!=-1)) -{var msg=this.settings.messages.errorType;} -return msg;},checkMaxFiles:function(file){if(this.settings.maxFiles<=this.itemFileList.length&&this.settings.maxFiles){var msg=this.settings.messages.errorMaxFiles;this.filePicker.btn.addClass('inactive');}else{this.filePicker.btn.removeClass('inactive');} -return msg;},checkTotalMB:function(file){var fileSize=(typeof(file)!=='undefined')?file.size:0;var totalSize=0;for(var obj in this.itemFileList){totalSize+=this.itemFileList[obj].file.size;} -if(fileSize+totalSize>this.settings.maxMB*1024*1024&&this.settings.maxMB!=0){var msg=this.settings.messages.errorMaxMB;} -return msg;},checkImageSize:function(img,file){var stt=this.settings.image -if((stt.minSize[0]&&img.widthstt.maxSize[0])||(stt.maxSize[1]&&img.height>stt.maxSize[1])){var msg=this.settings.messages.errorBigImage;if(stt.maxSize[0])msg+=' Ancho máximo:'+stt.maxSize[0]+'px.';if(stt.maxSize[1])msg+=' Alto máximo: '+stt.maxSize[1]+'px.';} -return msg;},} -FilePicker=function(app){this.btn=$('
      ').append(app.settings.filePicker);this.init(app);} -FilePicker.prototype={init:function(app){var multiple=(app.settings.multiple||app.elem.attr("multiple")=="multiple")?'multiple="multiple"':' ';this.inputHidden=$('');app.elem.after(this.btn);var elem=app.elem.clone();app.elem.detach();app.elem=elem;this.btn.addClass("cif-pkr-"+app.elem.attr("name"));var btn=this.btn;var inputHidden=this.inputHidden;inputHidden.change(function(){var popupSet=app.settings.popup;if(app.status=='reading')return $.customFile.popup.add(app.settings.messages.errorOnReading,popupSet.autoclose,popupSet.delay,'error');$.customFile.popup.close();fileList=$(this)[0].files;app.status='reading';app.read(fileList,0);});btn.on({click:function(){if(!$(this).is('.inactive'))inputHidden.click();return false;},dragover:function(e){e=e||window.event;e.preventDefault();if($(this).is('.inactive'))e.dataTransfer.dropEffect='none';btn.addClass('dragover');return false;},dragleave:function(e){btn.removeClass('dragover');return false;},drop:function(e){e=window.event;e.preventDefault();btn.removeClass('dragover');var popupSet=app.settings.popup;if(app.status=='reading')return $.customFile.popup.add(app.settings.messages.errorOnReading,popupSet.autoclose,popupSet.delay,'error');$.customFile.popup.close();var fileList=e.dataTransfer.files;if(fileList.length>1&&!app.settings.multiple)return $.customFile.popup.add(app.settings.messages.errorMultipleDisable,popupSet.autoclose,popupSet.delay,'error');app.status='reading';app.read(fileList,0);}});},};FileItem=function(app,fileList,currentItem){this.file=fileList[currentItem];this.app=app;this.fileList=fileList;this.currentItem=currentItem;this.init();} -FileItem.prototype={init:function(){this.jcropObj=null;this.node=this.app.settings.fileWrapper.clone();this.img=null;this.btnClose=$('
      close
      ');this.btnClose.click(function(){fileObj.destroy();});this.fr=new FileReader;var fr=this.fr;var app=this.app;var fileObj=this;var fileList=this.fileList;var currentItem=this.currentItem;var callback=function(){app.onSuccess(fileObj,function(){app.read(fileList,currentItem+1);});delete fileObj.fr;delete fileObj.fileList;delete fileObj.currentItem;} -fr.onload=function(){switch(app.settings.type){case"image":fileObj.readImage(callback);break;default:fileObj.readAllTypes(callback);break;}} -fr.readAsDataURL(this.file);},destroy:function(){this.app.settings.callbacks.beforeRemove(this);if(this.node)this.node.remove();var i=this.app.itemFileList.indexOf(this);this.app.itemFileList.splice(i,1);this.app.checkMaxFiles();},serialize:function(){return $.customFile.serialize([{key:this.app.name,value:this.file}]);},readImage:function(callback){var fileObj=this;var fr=this.fr;var app=this.app;var imgNode=fileObj.node.find("img.cif-img");fileObj.img=new Image;fileObj.img.src=fr.result;fileObj.img.onload=function(){msg=app.checkImageSize(fileObj.img,fileObj.file);if(msg){app.onError(fileObj.file,[msg]);return app.read(fileObj.fileList,fileObj.currentItem+1);} -imgNode.attr("src",fr.result);imgNode.parent().prepend(fileObj.btnClose);app.container.append(fileObj.node);if(app.settings.image.crop===true){fileObj.jcropObj=fileObj.initJcrop(app.settings.image,imgNode.parent(),fileObj.img,app.name);} -callback();}},readAllTypes:function(callback){fileObj=this;var parent=fileObj.node.find('.cif-parent');var FileExt=fileObj.file.name.substr(fileObj.file.name.lastIndexOf('.')+1);var FileName=fileObj.file.name.substr(0,fileObj.file.name.lastIndexOf('.'));if(FileName.length>42)var FileName=FileName.substr(0,40)+"...";var fileSize=(fileObj.file.size<102400)?(fileObj.file.size/1024).toFixed(2):Math.round(fileObj.file.size/1024);parent.append($('
      '+FileName+'.'+FileExt+' ('+fileSize+'KB)
      ')).append(fileObj.btnClose);this.app.container.append(fileObj.node) -callback();},initJcrop:function(options,parent,img,appName){var jcrop_api,boundx,boundy;if(options.preview.display){appName=appName.replace("[]","");prevMaxWidth=options.preview.maxWidth;prevSize=(options.cropSize[0]>prevMaxWidth)?[prevMaxWidth,options.cropSize[1]/options.cropSize[0]*prevMaxWidth]:options.cropSize;parent.append('
      ' -+'');parent.css("min-height",prevSize[1]+20+"px");} -var $preview=parent.find('.preview-pane'),$pcnt=$preview.find('.preview-container'),$pimg=$preview.find('.preview-container img'),xsize=$pcnt.width(),ysize=$pcnt.height();api=parent.find('.cif-img').Jcrop({keySupport:false,onChange:updatePreview,onSelect:updatePreview,aspectRatio:options.cropSize[0]/options.cropSize[1],minSize:options.cropSize,trueSize:[img.width,img.height]},function(){var bounds=this.getBounds();boundx=bounds[0];boundy=bounds[1];jcrop_api=this;jcrop_api.animateTo([0,0,options.cropSize[0]]);$preview.appendTo(jcrop_api.ui.holder);});function updatePreview(c){if(parseInt(c.w)>0&&options.preview.display){var rx=xsize / c.w;var ry=ysize / c.h;$pimg.css({width:Math.round(rx*boundx)+'px',height:Math.round(ry*boundy)+'px',marginLeft:'-'+Math.round(rx*c.x)+'px',marginTop:'-'+Math.round(ry*c.y)+'px'});} -updateCoords(c);};function updateCoords(c){parent.find('.jcropx').val(c.x);parent.find('.jcropy').val(c.y);parent.find('.jcropw').val(c.w);parent.find('.jcroph').val(c.h);} -return jcrop_api;}} -$.customFile={elements:[],getElements:function(selector){var elements=[];var selector=selector.split(",");var el=$.customFile.elements;for(k=0;k
      ',appendTo:$('body'),removeAfterComplete:true,node:null},progress:function(e,total,position,percent){this.progressBar.node.find("span").width(percent+'%');},xhr:function(){var ax=this;var xhr=$.ajaxSettings.xhr();xhr.upload.onprogress=function(e){var e=e||window.event;var position=e.position||e.loaded;var total=e.totalSize||e.total;var percent=((e.loaded/e.total)*100)+"";ax.progress(e,total,position,percent);};xhr.upload.onload=function(){ax.progressBar.node.find("span").width('100%');if(ax.progressBar.removeAfterComplete) -ax.progressBar.node.fadeOut(function(){$(this).remove();});};return xhr;},beforeSend:function(){},complete:function(){},success:function(xml){},} -var settings=$.extend(true,{},defaults,options);if(!settings.progressBar.active)settings.progress=function(){};settings.progressBar.node=$(settings.progressBar.markup);var settBefore=settings.beforeSend;if(settings.progressBar.active){settings.beforeSend=function(){settBefore();settings.progressBar.appendTo.append(settings.progressBar.node);};} -$.ajax(settings);},validate:function(elements,options){elements=this.getElements(elements);for(j=0;j
      close
      '),open:function(){var popup=this;this.wrapper.find('.cif-msg-close').click(function(){popup.close()});$('body').append(popup.wrapper);},add:function(msg,autoclose,delay,type){if(!delay)delay=3000;switch(type){case"error":var icon='';break;case"ok":var icon='';break;default:var icon='';} -var popup=this;if($('body').find(popup.wrapper).length<1)popup.open();this.wrapper.append('
      '+icon+msg+'
      ');if(typeof(fftimeout)!=='undefined')clearTimeout(fftimeout);if(autoclose) -fftimeout=setTimeout(function(){popup.close();},delay);},close:function(){this.wrapper.find(".cif-msg").remove();this.wrapper.detach();}}} -$.fn.customFile=function(options){return this.each(function(){var element=$(this);var tagName=element[0].tagName.toLowerCase();if(tagName=='input'){var customFile=new CustomFile(this,options);var prop=customFile.form -if(typeof(customFile.form.data("appCustomFile"))!="undefined"){var formData=customFile.form.data("appCustomFile");formData.push(customFile);}else{var formData=new Array(customFile);} +/* + jQuery Custom Input File Plugin - version 1.0 + Copyright 2014, Ángel Espro, www.aesolucionesweb.com.ar, + Licence : GNU General Public License + + Site: www.aesolucionesweb.com.ar/plugins/custom-input-file + + You must not remove these lines. Read gpl.txt for further legal information. +*/ +(function($){CustomFile=function(elem,options){this.elem=$(elem);this.itemFileList=[];this.defaults={type:'all',allowed:'all',notAllowed:[],addContainerAfter:$(elem),multiple:true,maxFiles:5,maxMB:0,maxKBperFile:2048,fileWrapper:'
      ',filePicker:'

      Soltar archivos aquí

      o clic para seleccionar desde carpeta

      ',image:{crop:false,preview:{display:true,maxWidth:300},cropSize:[320,225],minSize:[0,0],maxSize:[0,0]},messages:{errorType:"Tipo de archivo no permitido",errorMaxMB:"Peso máximo de archivos acumulado excedido",errorFileKB:"Archivo muy pesado",errorMaxFiles:"Cantidad máxima de archivos alcanzada",errorBigImage:"Imagen muy grande",errorSmallImage:"Imagen muy pequeña",errorOnReading:"Aplicación ocupada. Inténtelo más tarde.",errorMultipleDisable:"Suelte un archivo por vez."},popup:{active:true,autoclose:true,delay:10000},callbacks:{onComplete:function(app){},beforeRead:function(file){},onSuccess:function(item,callback){},onError:function(file,msg){},beforeRemove:function(item){},}} +this.settings=$.extend(true,{},this.defaults,options);this.status='stop';this.init();} +CustomFile.prototype={init:function(){var attnm=this.elem.attr("name");if(attnm=='')var attnm="inputfile";this.name=(attnm.indexOf("[]",attnm-2)===-1)?attnm+"[]":attnm;this.form=this.elem.parents('form');this.container=$('
      ');var image=this.settings.image;image.minSize=(typeof(image.minSize)!=='object'||image.minSize.length!==2)?[0,0]:image.minSize;if(image.crop){var minSize=[];for(i=0;iimage.cropSize[i])?image.minSize[i]:image.cropSize[i];minSize.push(value);} +image.minSize=minSize} +this.setFileWrapper();this.appendContainer();this.filePicker=new FilePicker(this);$.customFile.elements.push(this);},onSuccess:function(item,callback){this.itemFileList.push(item);if(this.settings.callbacks.onSuccess(item,callback)===false)return;callback();},onError:function(file,msg){this.settings.callbacks.onError(file,msg);var popupSet=this.settings.popup;if(popupSet.active) +for(k=0;k42)var fileName=fileName.substr(0,40)+"...";msg[k]+=' ('+fileName+'.'+fileExt+')';$.customFile.popup.add(msg[k],popupSet.autoclose,popupSet.delay,'error');}},onComplete:function(){this.status="completed";if(this.settings.multiple){var response=this.checkMaxFiles() +var popupSet=this.settings.popup;if(response&&popupSet.active)$.customFile.popup.add(response,popupSet.autoclose,popupSet.delay,'ok');}else{if(this.itemFileList.length>1)this.itemFileList[0].destroy();} +this.settings.callbacks.onComplete(this);},read:function(fileList,currentItem){var i=currentItem;if(i+1>fileList.length)this.status='completed';if(this.status==='completed'){this.onComplete();return false;} +var beforeRead=this.settings.callbacks.beforeRead(fileList[i]);if(beforeRead===false)return this.read(fileList,i+1);app=this;var response=app.checkMaxFiles(fileList[i]);if(typeof(response)==='string'){this.onError(fileList[i],[response]);return this.read(fileList,i+1);} +var msg=[];var checklist=["checkFileKB","checkFileType","checkTotalMB"] +for(j=0;j0){this.onError(fileList[i],msg);return this.read(fileList,i+1);} +new FileItem(this,fileList,i);},appendContainer:function(){var sett=this.settings;if(sett.fileWrapper.parent().length!=0&&sett.appendAfter!=this.elem){sett.addContainerAfter=sett.fileWrapper;} +sett.addContainerAfter.after(this.container);},setFileWrapper:function(){var app=this;var fwr=this.settings.fileWrapper;if(typeof(fwr)==='string')this.settings.fileWrapper=$(fwr);this.settings.fileWrapper=$('
      ',{class:"cif-file-row"}).append(this.settings.fileWrapper);var fwr=this.settings.fileWrapper;fwr.find(':input').each(function(index){var $this=$(this);var attnm=$this.attr("name");if(!attnm)var attnm=app.name.substr(0,app.name.indexOf("[]",-2))+"-"+index;if(attnm.indexOf("[]",-2)===-1){$this.attr("name",attnm+"[]");}});if(fwr.find('.cif-img').length==0&&this.settings.type=='image'){var parent=fwr.find('.cif-parent');if(parent.length===0){var $img=fwr.find('img');var parent=$('
      ',{class:'cif-parent'});parent.append($img);fwr.append(parent);} +if(parent.find('img').length===0)parent.append('') +parent.find('img').addClass("cif-img");} +if(fwr.find('.cif-parent').length==0){fwr.prepend('
      ');}},checkFileKB:function(file){if(file.size>this.settings.maxKBperFile*1024&&this.settings.maxKBperFile!=0){var msg=this.settings.messages.errorFileKB;} +return msg;},checkFileType:function(file){var ext=file.name.substr(file.name.lastIndexOf('.')+1);var ext=ext.toLowerCase();var imageCropAllowed=["jpeg","jpg","png"] +if((this.settings.type=='image'&&this.settings.image.crop&&imageCropAllowed.indexOf(ext)==-1)||(this.settings.type=='image'&&!file.type.match(/image\//))||(this.settings.allowed!='all'&&this.settings.allowed.indexOf(ext)==-1)||(this.settings.notAllowed.indexOf(ext)!=-1)) +{var msg=this.settings.messages.errorType;} +return msg;},checkMaxFiles:function(file){if(this.settings.maxFiles<=this.itemFileList.length&&this.settings.maxFiles){var msg=this.settings.messages.errorMaxFiles;this.filePicker.btn.addClass('inactive');}else{this.filePicker.btn.removeClass('inactive');} +return msg;},checkTotalMB:function(file){var fileSize=(typeof(file)!=='undefined')?file.size:0;var totalSize=0;for(var obj in this.itemFileList){totalSize+=this.itemFileList[obj].file.size;} +if(fileSize+totalSize>this.settings.maxMB*1024*1024&&this.settings.maxMB!=0){var msg=this.settings.messages.errorMaxMB;} +return msg;},checkImageSize:function(img,file){var stt=this.settings.image +if((stt.minSize[0]&&img.widthstt.maxSize[0])||(stt.maxSize[1]&&img.height>stt.maxSize[1])){var msg=this.settings.messages.errorBigImage;if(stt.maxSize[0])msg+=' Ancho máximo:'+stt.maxSize[0]+'px.';if(stt.maxSize[1])msg+=' Alto máximo: '+stt.maxSize[1]+'px.';} +return msg;},} +FilePicker=function(app){this.btn=$('
      ').append(app.settings.filePicker);this.init(app);} +FilePicker.prototype={init:function(app){var multiple=(app.settings.multiple||app.elem.attr("multiple")=="multiple")?'multiple="multiple"':' ';this.inputHidden=$('');app.elem.after(this.btn);var elem=app.elem.clone();app.elem.detach();app.elem=elem;this.btn.addClass("cif-pkr-"+app.elem.attr("name"));var btn=this.btn;var inputHidden=this.inputHidden;inputHidden.change(function(){var popupSet=app.settings.popup;if(app.status=='reading')return $.customFile.popup.add(app.settings.messages.errorOnReading,popupSet.autoclose,popupSet.delay,'error');$.customFile.popup.close();fileList=$(this)[0].files;app.status='reading';app.read(fileList,0);});btn.on({click:function(){if(!$(this).is('.inactive'))inputHidden.click();return false;},dragover:function(e){e=e||window.event;e.preventDefault();if($(this).is('.inactive'))e.dataTransfer.dropEffect='none';btn.addClass('dragover');return false;},dragleave:function(e){btn.removeClass('dragover');return false;},drop:function(e){e=window.event;e.preventDefault();btn.removeClass('dragover');var popupSet=app.settings.popup;if(app.status=='reading')return $.customFile.popup.add(app.settings.messages.errorOnReading,popupSet.autoclose,popupSet.delay,'error');$.customFile.popup.close();var fileList=e.dataTransfer.files;if(fileList.length>1&&!app.settings.multiple)return $.customFile.popup.add(app.settings.messages.errorMultipleDisable,popupSet.autoclose,popupSet.delay,'error');app.status='reading';app.read(fileList,0);}});},};FileItem=function(app,fileList,currentItem){this.file=fileList[currentItem];this.app=app;this.fileList=fileList;this.currentItem=currentItem;this.init();} +FileItem.prototype={init:function(){this.jcropObj=null;this.node=this.app.settings.fileWrapper.clone();this.img=null;this.btnClose=$('
      close
      ');this.btnClose.click(function(){fileObj.destroy();});this.fr=new FileReader;var fr=this.fr;var app=this.app;var fileObj=this;var fileList=this.fileList;var currentItem=this.currentItem;var callback=function(){app.onSuccess(fileObj,function(){app.read(fileList,currentItem+1);});delete fileObj.fr;delete fileObj.fileList;delete fileObj.currentItem;} +fr.onload=function(){switch(app.settings.type){case"image":fileObj.readImage(callback);break;default:fileObj.readAllTypes(callback);break;}} +fr.readAsDataURL(this.file);},destroy:function(){this.app.settings.callbacks.beforeRemove(this);if(this.node)this.node.remove();var i=this.app.itemFileList.indexOf(this);this.app.itemFileList.splice(i,1);this.app.checkMaxFiles();},serialize:function(){return $.customFile.serialize([{key:this.app.name,value:this.file}]);},readImage:function(callback){var fileObj=this;var fr=this.fr;var app=this.app;var imgNode=fileObj.node.find("img.cif-img");fileObj.img=new Image;fileObj.img.src=fr.result;fileObj.img.onload=function(){msg=app.checkImageSize(fileObj.img,fileObj.file);if(msg){app.onError(fileObj.file,[msg]);return app.read(fileObj.fileList,fileObj.currentItem+1);} +imgNode.attr("src",fr.result);imgNode.parent().prepend(fileObj.btnClose);app.container.append(fileObj.node);if(app.settings.image.crop===true){fileObj.jcropObj=fileObj.initJcrop(app.settings.image,imgNode.parent(),fileObj.img,app.name);} +callback();}},readAllTypes:function(callback){fileObj=this;var parent=fileObj.node.find('.cif-parent');var FileExt=fileObj.file.name.substr(fileObj.file.name.lastIndexOf('.')+1);var FileName=fileObj.file.name.substr(0,fileObj.file.name.lastIndexOf('.'));if(FileName.length>42)var FileName=FileName.substr(0,40)+"...";var fileSize=(fileObj.file.size<102400)?(fileObj.file.size/1024).toFixed(2):Math.round(fileObj.file.size/1024);parent.append($('
      '+FileName+'.'+FileExt+' ('+fileSize+'KB)
      ')).append(fileObj.btnClose);this.app.container.append(fileObj.node) +callback();},initJcrop:function(options,parent,img,appName){var jcrop_api,boundx,boundy;if(options.preview.display){appName=appName.replace("[]","");prevMaxWidth=options.preview.maxWidth;prevSize=(options.cropSize[0]>prevMaxWidth)?[prevMaxWidth,options.cropSize[1]/options.cropSize[0]*prevMaxWidth]:options.cropSize;parent.append('
      ' ++'');parent.css("min-height",prevSize[1]+20+"px");} +var $preview=parent.find('.preview-pane'),$pcnt=$preview.find('.preview-container'),$pimg=$preview.find('.preview-container img'),xsize=$pcnt.width(),ysize=$pcnt.height();api=parent.find('.cif-img').Jcrop({keySupport:false,onChange:updatePreview,onSelect:updatePreview,aspectRatio:options.cropSize[0]/options.cropSize[1],minSize:options.cropSize,trueSize:[img.width,img.height]},function(){var bounds=this.getBounds();boundx=bounds[0];boundy=bounds[1];jcrop_api=this;jcrop_api.animateTo([0,0,options.cropSize[0]]);$preview.appendTo(jcrop_api.ui.holder);});function updatePreview(c){if(parseInt(c.w)>0&&options.preview.display){var rx=xsize / c.w;var ry=ysize / c.h;$pimg.css({width:Math.round(rx*boundx)+'px',height:Math.round(ry*boundy)+'px',marginLeft:'-'+Math.round(rx*c.x)+'px',marginTop:'-'+Math.round(ry*c.y)+'px'});} +updateCoords(c);};function updateCoords(c){parent.find('.jcropx').val(c.x);parent.find('.jcropy').val(c.y);parent.find('.jcropw').val(c.w);parent.find('.jcroph').val(c.h);} +return jcrop_api;}} +$.customFile={elements:[],getElements:function(selector){var elements=[];var selector=selector.split(",");var el=$.customFile.elements;for(k=0;k
      ',appendTo:$('body'),removeAfterComplete:true,node:null},progress:function(e,total,position,percent){this.progressBar.node.find("span").width(percent+'%');},xhr:function(){var ax=this;var xhr=$.ajaxSettings.xhr();xhr.upload.onprogress=function(e){var e=e||window.event;var position=e.position||e.loaded;var total=e.totalSize||e.total;var percent=((e.loaded/e.total)*100)+"";ax.progress(e,total,position,percent);};xhr.upload.onload=function(){ax.progressBar.node.find("span").width('100%');if(ax.progressBar.removeAfterComplete) +ax.progressBar.node.fadeOut(function(){$(this).remove();});};return xhr;},beforeSend:function(){},complete:function(){},success:function(xml){},} +var settings=$.extend(true,{},defaults,options);if(!settings.progressBar.active)settings.progress=function(){};settings.progressBar.node=$(settings.progressBar.markup);var settBefore=settings.beforeSend;if(settings.progressBar.active){settings.beforeSend=function(){settBefore();settings.progressBar.appendTo.append(settings.progressBar.node);};} +$.ajax(settings);},validate:function(elements,options){elements=this.getElements(elements);for(j=0;j
      close
      '),open:function(){var popup=this;this.wrapper.find('.cif-msg-close').click(function(){popup.close()});$('body').append(popup.wrapper);},add:function(msg,autoclose,delay,type){if(!delay)delay=3000;switch(type){case"error":var icon='';break;case"ok":var icon='';break;default:var icon='';} +var popup=this;if($('body').find(popup.wrapper).length<1)popup.open();this.wrapper.append('
      '+icon+msg+'
      ');if(typeof(fftimeout)!=='undefined')clearTimeout(fftimeout);if(autoclose) +fftimeout=setTimeout(function(){popup.close();},delay);},close:function(){this.wrapper.find(".cif-msg").remove();this.wrapper.detach();}}} +$.fn.customFile=function(options){return this.each(function(){var element=$(this);var tagName=element[0].tagName.toLowerCase();if(tagName=='input'){var customFile=new CustomFile(this,options);var prop=customFile.form +if(typeof(customFile.form.data("appCustomFile"))!="undefined"){var formData=customFile.form.data("appCustomFile");formData.push(customFile);}else{var formData=new Array(customFile);} customFile.form.data("appCustomFile",formData);}});};})(jQuery); \ No newline at end of file diff --git a/js/date_functions.js b/js/date_functions.js index 2876dfc..43a4c12 100644 --- a/js/date_functions.js +++ b/js/date_functions.js @@ -1,14 +1,14 @@ -// function that receives two hours in hh:mm format and compares as a spaceship operator -export function compareHours(h1, h2) { - const [h1h, h1m] = h1.split(":").map(Number); - const [h2h, h2m] = h2.split(":").map(Number); - if (h1h > h2h) - return 1; - if (h1h < h2h) - return -1; - if (h1m > h2m) - return 1; - if (h1m < h2m) - return -1; - return 0; -} +// function that receives two hours in hh:mm format and compares as a spaceship operator +export function compareHours(h1, h2) { + const [h1h, h1m] = h1.split(":").map(Number); + const [h2h, h2m] = h2.split(":").map(Number); + if (h1h > h2h) + return 1; + if (h1h < h2h) + return -1; + if (h1m > h2m) + return 1; + if (h1m < h2m) + return -1; + return 0; +} diff --git a/js/fetchlib.js b/js/fetchlib.js index 6066053..db643ef 100644 --- a/js/fetchlib.js +++ b/js/fetchlib.js @@ -1,44 +1,44 @@ -var submit = function (url, data) { - // create a form - var form = document.createElement('form'); - form.method = 'POST'; - form.action = url; - form.style.display = 'none'; - - // add the form data to the form - for (var key in data) { - var input = document.createElement('input'); - input.type = 'hidden'; - input.name = key; - input.value = data[key]; - form.appendChild(input); - } - - // submit the form - document.body.appendChild(form); - form.submit(); -} - -var toFormData = function (obj) { - var formData = new FormData(); - for (var key in obj) { - formData.append(key, obj[key]); - } - return formData; -} -var fetchPHP = async function (url, data = {}) { - return response = await fetch( - url, - { method: 'POST', body: toFormData(data) } - ) - .then(response => { - try { - return response.json() - } - catch (e) { - var message = 'Error en la respuesta del servidor'; - Promise.reject(message) - } - }) - .then(response => response.error ? Promise.reject(response.error) : Promise.resolve(response)) +var submit = function (url, data) { + // create a form + var form = document.createElement('form'); + form.method = 'POST'; + form.action = url; + form.style.display = 'none'; + + // add the form data to the form + for (var key in data) { + var input = document.createElement('input'); + input.type = 'hidden'; + input.name = key; + input.value = data[key]; + form.appendChild(input); + } + + // submit the form + document.body.appendChild(form); + form.submit(); +} + +var toFormData = function (obj) { + var formData = new FormData(); + for (var key in obj) { + formData.append(key, obj[key]); + } + return formData; +} +var fetchPHP = async function (url, data = {}) { + return response = await fetch( + url, + { method: 'POST', body: toFormData(data) } + ) + .then(response => { + try { + return response.json() + } + catch (e) { + var message = 'Error en la respuesta del servidor'; + Promise.reject(message) + } + }) + .then(response => response.error ? Promise.reject(response.error) : Promise.resolve(response)) } \ No newline at end of file diff --git a/js/horario_profesor.js b/js/horario_profesor.js index 1df9802..41c239f 100644 --- a/js/horario_profesor.js +++ b/js/horario_profesor.js @@ -1,414 +1,414 @@ -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 ? - `` - : ''; - cell.innerHTML = - `
      - ${horario.hora} - ${horario.materia}
      -
      Salón: ${horario.salon}
      - - ${horario.profesores.map((profesor) => ` ${profesor.grado ?? ''} ${profesor.profesor}`).join("
      ")} -
      -
      - ${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 = ` - - ${hora} - -
      -
      - - - Empalme de ${ids.length} horarios - -
      - Ver horarios … -
      -
      - `; - // 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 += ` - - ${horario.hora.slice(0, -3)}-${horario.hora_final.slice(0, -3)} - ${horario.materia} - - ${horario.profesores.map(({ grado, profesor }) => `${grado ?? ''} ${profesor}`).join(", ")} - - ${horario.salon} - ${edit ? ` - - - - - - - ` : ""} - `; - }); - 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 = `
      - Loading... -
      `; - 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}"]`); +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 ? + `` + : ''; + cell.innerHTML = + `
      + ${horario.hora} + ${horario.materia}
      +
      Salón: ${horario.salon}
      + + ${horario.profesores.map((profesor) => ` ${profesor.grado ?? ''} ${profesor.profesor}`).join("
      ")} +
      +
      + ${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 = ` + + ${hora} + +
      +
      + + + Empalme de ${ids.length} horarios + +
      + Ver horarios … +
      +
      + `; + // 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 += ` + + ${horario.hora.slice(0, -3)}-${horario.hora_final.slice(0, -3)} + ${horario.materia} + + ${horario.profesores.map(({ grado, profesor }) => `${grado ?? ''} ${profesor}`).join(", ")} + + ${horario.salon} + ${edit ? ` + + + + + + + ` : ""} + `; + }); + 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 = `
      + Loading... +
      `; + 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}"]`); diff --git a/js/jquery-ui.touch-punch.min.js b/js/jquery-ui.touch-punch.min.js index 4fde13c..382316c 100644 --- a/js/jquery-ui.touch-punch.min.js +++ b/js/jquery-ui.touch-punch.min.js @@ -1,11 +1,11 @@ -/*! - * jQuery UI Touch Punch 0.2.3 - * - * Copyright 2011–2014, Dave Furfero - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Depends: - * jquery.ui.widget.js - * jquery.ui.mouse.js - */ +/*! + * jQuery UI Touch Punch 0.2.3 + * + * Copyright 2011–2014, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ !function (a) { function f(a, b) { if (!(a.originalEvent.touches.length > 1)) { a.preventDefault(); var c = a.originalEvent.changedTouches[0], d = document.createEvent("MouseEvents"); d.initMouseEvent(b, !0, !0, window, 1, c.screenX, c.screenY, c.clientX, c.clientY, !1, !1, !1, !1, 0, null), a.target.dispatchEvent(d) } } if (a.support.touch = "ontouchend" in document, a.support.touch) { var e, b = a.ui.mouse.prototype, c = b._mouseInit, d = b._mouseDestroy; b._touchStart = function (a) { var b = this; !e && b._mouseCapture(a.originalEvent.changedTouches[0]) && (e = !0, b._touchMoved = !1, f(a, "mouseover"), f(a, "mousemove"), f(a, "mousedown")) }, b._touchMove = function (a) { e && (this._touchMoved = !0, f(a, "mousemove")) }, b._touchEnd = function (a) { e && (f(a, "mouseup"), f(a, "mouseout"), this._touchMoved || f(a, "click"), e = !1) }, b._mouseInit = function () { var b = this; b.element.bind({ touchstart: a.proxy(b, "_touchStart"), touchmove: a.proxy(b, "_touchMove"), touchend: a.proxy(b, "_touchEnd") }), c.call(b) }, b._mouseDestroy = function () { var b = this; b.element.unbind({ touchstart: a.proxy(b, "_touchStart"), touchmove: a.proxy(b, "_touchMove"), touchend: a.proxy(b, "_touchEnd") }), d.call(b) } } }(jQuery); \ No newline at end of file diff --git a/js/messages.js b/js/messages.js index 956f79a..bc42890 100644 --- a/js/messages.js +++ b/js/messages.js @@ -1,36 +1,36 @@ -function triggerMessage(message, header, color = "danger", selector = "message") { - const container = document.getElementById(selector); - container.innerHTML = ''; - /* Template message_tmp */ - var node = /* html */` - - ` - setTimeout(function () { - container.innerHTML = node; - }, 100); - - - /* setTimeout(function () { - container.innerHTML = ''; - }, 5000); */ -} - -function messageMissingInputs(required) { - var message = 'Faltan los siguientes campos: '; - required.forEach(function (item, index) { - let last = required.length - 1; - if (index == last) - message += item; - else if (index == last - 1) - message += item + ' y '; - else - message += item + ', '; - }); - triggerMessage(message, 'Error', 'danger'); +function triggerMessage(message, header, color = "danger", selector = "message") { + const container = document.getElementById(selector); + container.innerHTML = ''; + /* Template message_tmp */ + var node = /* html */` + + ` + setTimeout(function () { + container.innerHTML = node; + }, 100); + + + /* setTimeout(function () { + container.innerHTML = ''; + }, 5000); */ +} + +function messageMissingInputs(required) { + var message = 'Faltan los siguientes campos: '; + required.forEach(function (item, index) { + let last = required.length - 1; + if (index == last) + message += item; + else if (index == last - 1) + message += item + ' y '; + else + message += item + ', '; + }); + triggerMessage(message, 'Error', 'danger'); } \ No newline at end of file diff --git a/js/messages.php b/js/messages.php index bb2167a..1bb1686 100644 --- a/js/messages.php +++ b/js/messages.php @@ -1,39 +1,39 @@ - \ No newline at end of file diff --git a/js/moment.js b/js/moment.js index fb17705..3db2d51 100644 --- a/js/moment.js +++ b/js/moment.js @@ -1,2 +1,2 @@ -!function(e,a){"object"==typeof exports&&"undefined"!=typeof module?module.exports=a():"function"==typeof define&&define.amd?define(a):e.moment=a()}(this,function(){"use strict";var E;function M(){return E.apply(null,arguments)}function F(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function z(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e,a){return Object.prototype.hasOwnProperty.call(e,a)}function N(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;for(var a in e)if(l(e,a))return;return 1}function d(e){return void 0===e}function J(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function R(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function C(e,a){for(var t=[],s=e.length,n=0;n>>0,s=0;sBe(e)?(r=e+1,a-Be(e)):(r=e,a);return{year:r,dayOfYear:t}}function Xe(e,a,t){var s,n,r=$e(e.year(),a,t),r=Math.floor((e.dayOfYear()-r-1)/7)+1;return r<1?s=r+ea(n=e.year()-1,a,t):r>ea(e.year(),a,t)?(s=r-ea(e.year(),a,t),n=e.year()+1):(n=e.year(),s=r),{week:s,year:n}}function ea(e,a,t){var s=$e(e,a,t),a=$e(e+1,a,t);return(Be(e)-s+a)/7}s("w",["ww",2],"wo","week"),s("W",["WW",2],"Wo","isoWeek"),a("week","w"),a("isoWeek","W"),t("week",5),t("isoWeek",5),p("w",o),p("ww",o,r),p("W",o),p("WW",o,r),je(["w","ww","W","WW"],function(e,a,t,s){a[s.substr(0,1)]=m(e)});function aa(e,a){return e.slice(a,7).concat(e.slice(0,a))}s("d",0,"do","day"),s("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),s("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),s("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),s("e",0,0,"weekday"),s("E",0,0,"isoWeekday"),a("day","d"),a("weekday","e"),a("isoWeekday","E"),t("day",11),t("weekday",11),t("isoWeekday",11),p("d",o),p("e",o),p("E",o),p("dd",function(e,a){return a.weekdaysMinRegex(e)}),p("ddd",function(e,a){return a.weekdaysShortRegex(e)}),p("dddd",function(e,a){return a.weekdaysRegex(e)}),je(["dd","ddd","dddd"],function(e,a,t,s){s=t._locale.weekdaysParse(e,s,t._strict);null!=s?a.d=s:h(t).invalidWeekday=e}),je(["d","e","E"],function(e,a,t,s){a[s]=m(e)});var ta="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),na="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),ra=f,da=f,ia=f;function _a(){function e(e,a){return a.length-e.length}for(var a,t,s,n=[],r=[],d=[],i=[],_=0;_<7;_++)s=U([2e3,1]).day(_),a=k(this.weekdaysMin(s,"")),t=k(this.weekdaysShort(s,"")),s=k(this.weekdays(s,"")),n.push(a),r.push(t),d.push(s),i.push(a),i.push(t),i.push(s);n.sort(e),r.sort(e),d.sort(e),i.sort(e),this._weekdaysRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+n.join("|")+")","i")}function oa(){return this.hours()%12||12}function ma(e,a){s(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}function ua(e,a){return a._meridiemParse}s("H",["HH",2],0,"hour"),s("h",["hh",2],0,oa),s("k",["kk",2],0,function(){return this.hours()||24}),s("hmm",0,0,function(){return""+oa.apply(this)+de(this.minutes(),2)}),s("hmmss",0,0,function(){return""+oa.apply(this)+de(this.minutes(),2)+de(this.seconds(),2)}),s("Hmm",0,0,function(){return""+this.hours()+de(this.minutes(),2)}),s("Hmmss",0,0,function(){return""+this.hours()+de(this.minutes(),2)+de(this.seconds(),2)}),ma("a",!0),ma("A",!1),a("hour","h"),t("hour",13),p("a",ua),p("A",ua),p("H",o),p("h",o),p("k",o),p("HH",o,r),p("hh",o,r),p("kk",o,r),p("hmm",c),p("hmmss",L),p("Hmm",c),p("Hmmss",L),D(["H","HH"],w),D(["k","kk"],function(e,a,t){e=m(e);a[w]=24===e?0:e}),D(["a","A"],function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e}),D(["h","hh"],function(e,a,t){a[w]=m(e),h(t).bigHour=!0}),D("hmm",function(e,a,t){var s=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s)),h(t).bigHour=!0}),D("hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s,2)),a[We]=m(e.substr(n)),h(t).bigHour=!0}),D("Hmm",function(e,a,t){var s=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s))}),D("Hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s,2)),a[We]=m(e.substr(n))});f=Ye("Hours",!0);var la,Ma={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ne,monthsShort:Je,week:{dow:0,doy:6},weekdays:ta,weekdaysMin:na,weekdaysShort:sa,meridiemParse:/[ap]\.?m?\.?/i},b={},ha={};function ca(e){return e&&e.toLowerCase().replace("_","-")}function La(e){for(var a,t,s,n,r=0;r=a&&function(e,a){for(var t=Math.min(e.length,a.length),s=0;s=a-1)break;a--}r++}return la}function Ya(a){var e;if(void 0===b[a]&&"undefined"!=typeof module&&module&&module.exports&&null!=a.match("^[^/\\\\]*$"))try{e=la._abbr,require("./locale/"+a),ya(e)}catch(e){b[a]=null}return b[a]}function ya(e,a){return e&&((a=d(a)?pa(e):fa(e,a))?la=a:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),la._abbr}function fa(e,a){if(null===a)return delete b[e],null;var t,s=Ma;if(a.abbr=e,null!=b[e])ae("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=b[e]._config;else if(null!=a.parentLocale)if(null!=b[a.parentLocale])s=b[a.parentLocale]._config;else{if(null==(t=Ya(a.parentLocale)))return ha[a.parentLocale]||(ha[a.parentLocale]=[]),ha[a.parentLocale].push({name:e,config:a}),null;s=t._config}return b[e]=new ne(se(s,a)),ha[e]&&ha[e].forEach(function(e){fa(e.name,e.config)}),ya(e),b[e]}function pa(e){var a;if(!(e=e&&e._locale&&e._locale._abbr?e._locale._abbr:e))return la;if(!F(e)){if(a=Ya(e))return a;e=[e]}return La(e)}function ka(e){var a=e._a;return a&&-2===h(e).overflow&&(a=a[xe]<0||11ze(a[g],a[xe])?Pe:a[w]<0||24ea(r,_,o)?h(s)._overflowWeeks=!0:null!=m?h(s)._overflowWeekday=!0:(u=Qe(r,d,i,_,o),s._a[g]=u.year,s._dayOfYear=u.dayOfYear)),null!=e._dayOfYear&&(n=Oa(e._a[g],t[g]),(e._dayOfYear>Be(n)||0===e._dayOfYear)&&(h(e)._overflowDayOfYear=!0),m=Ze(n,0,e._dayOfYear),e._a[xe]=m.getUTCMonth(),e._a[Pe]=m.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=l[a]=t[a];for(;a<7;a++)e._a[a]=l[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[w]&&0===e._a[Oe]&&0===e._a[We]&&0===e._a[Ae]&&(e._nextDay=!0,e._a[w]=0),e._d=(e._useUTC?Ze:qe).apply(null,l),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[w]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(h(e).weekdayMismatch=!0)}}function Aa(e){if(e._f===M.ISO_8601)ja(e);else if(e._f===M.RFC_2822)Pa(e);else{e._a=[],h(e).empty=!0;for(var a,t,s,n,r,d=""+e._i,i=d.length,_=0,o=le(e._f,e._locale).match(ie)||[],m=o.length,u=0;ue.valueOf():e.valueOf()"}),n.toJSON=function(){return this.isValid()?this.toISOString():null},n.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},n.unix=function(){return Math.floor(this.valueOf()/1e3)},n.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},n.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},n.eraName=function(){for(var e,a=this.localeData().eras(),t=0,s=a.length;tthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},n.isLocal=function(){return!!this.isValid()&&!this._isUTC},n.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},n.isUtc=Ka,n.isUTC=Ka,n.zoneAbbr=function(){return this._isUTC?"UTC":""},n.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},n.dates=e("dates accessor is deprecated. Use date instead.",Y),n.months=e("months accessor is deprecated. Use month instead",Ge),n.years=e("years accessor is deprecated. Use year instead",Ke),n.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,a){return null!=e?(this.utcOffset(e="string"!=typeof e?-e:e,a),this):-this.utcOffset()}),n.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!d(this._isDSTShifted))return this._isDSTShifted;var e,a={};return Z(a,this),(a=Ea(a))._a?(e=(a._isUTC?U:S)(a._a),this._isDSTShifted=this.isValid()&&0>>0,s=0;sBe(e)?(r=e+1,a-Be(e)):(r=e,a);return{year:r,dayOfYear:t}}function Xe(e,a,t){var s,n,r=$e(e.year(),a,t),r=Math.floor((e.dayOfYear()-r-1)/7)+1;return r<1?s=r+ea(n=e.year()-1,a,t):r>ea(e.year(),a,t)?(s=r-ea(e.year(),a,t),n=e.year()+1):(n=e.year(),s=r),{week:s,year:n}}function ea(e,a,t){var s=$e(e,a,t),a=$e(e+1,a,t);return(Be(e)-s+a)/7}s("w",["ww",2],"wo","week"),s("W",["WW",2],"Wo","isoWeek"),a("week","w"),a("isoWeek","W"),t("week",5),t("isoWeek",5),p("w",o),p("ww",o,r),p("W",o),p("WW",o,r),je(["w","ww","W","WW"],function(e,a,t,s){a[s.substr(0,1)]=m(e)});function aa(e,a){return e.slice(a,7).concat(e.slice(0,a))}s("d",0,"do","day"),s("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),s("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),s("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),s("e",0,0,"weekday"),s("E",0,0,"isoWeekday"),a("day","d"),a("weekday","e"),a("isoWeekday","E"),t("day",11),t("weekday",11),t("isoWeekday",11),p("d",o),p("e",o),p("E",o),p("dd",function(e,a){return a.weekdaysMinRegex(e)}),p("ddd",function(e,a){return a.weekdaysShortRegex(e)}),p("dddd",function(e,a){return a.weekdaysRegex(e)}),je(["dd","ddd","dddd"],function(e,a,t,s){s=t._locale.weekdaysParse(e,s,t._strict);null!=s?a.d=s:h(t).invalidWeekday=e}),je(["d","e","E"],function(e,a,t,s){a[s]=m(e)});var ta="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),na="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),ra=f,da=f,ia=f;function _a(){function e(e,a){return a.length-e.length}for(var a,t,s,n=[],r=[],d=[],i=[],_=0;_<7;_++)s=U([2e3,1]).day(_),a=k(this.weekdaysMin(s,"")),t=k(this.weekdaysShort(s,"")),s=k(this.weekdays(s,"")),n.push(a),r.push(t),d.push(s),i.push(a),i.push(t),i.push(s);n.sort(e),r.sort(e),d.sort(e),i.sort(e),this._weekdaysRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+n.join("|")+")","i")}function oa(){return this.hours()%12||12}function ma(e,a){s(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}function ua(e,a){return a._meridiemParse}s("H",["HH",2],0,"hour"),s("h",["hh",2],0,oa),s("k",["kk",2],0,function(){return this.hours()||24}),s("hmm",0,0,function(){return""+oa.apply(this)+de(this.minutes(),2)}),s("hmmss",0,0,function(){return""+oa.apply(this)+de(this.minutes(),2)+de(this.seconds(),2)}),s("Hmm",0,0,function(){return""+this.hours()+de(this.minutes(),2)}),s("Hmmss",0,0,function(){return""+this.hours()+de(this.minutes(),2)+de(this.seconds(),2)}),ma("a",!0),ma("A",!1),a("hour","h"),t("hour",13),p("a",ua),p("A",ua),p("H",o),p("h",o),p("k",o),p("HH",o,r),p("hh",o,r),p("kk",o,r),p("hmm",c),p("hmmss",L),p("Hmm",c),p("Hmmss",L),D(["H","HH"],w),D(["k","kk"],function(e,a,t){e=m(e);a[w]=24===e?0:e}),D(["a","A"],function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e}),D(["h","hh"],function(e,a,t){a[w]=m(e),h(t).bigHour=!0}),D("hmm",function(e,a,t){var s=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s)),h(t).bigHour=!0}),D("hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s,2)),a[We]=m(e.substr(n)),h(t).bigHour=!0}),D("Hmm",function(e,a,t){var s=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s))}),D("Hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[w]=m(e.substr(0,s)),a[Oe]=m(e.substr(s,2)),a[We]=m(e.substr(n))});f=Ye("Hours",!0);var la,Ma={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ne,monthsShort:Je,week:{dow:0,doy:6},weekdays:ta,weekdaysMin:na,weekdaysShort:sa,meridiemParse:/[ap]\.?m?\.?/i},b={},ha={};function ca(e){return e&&e.toLowerCase().replace("_","-")}function La(e){for(var a,t,s,n,r=0;r=a&&function(e,a){for(var t=Math.min(e.length,a.length),s=0;s=a-1)break;a--}r++}return la}function Ya(a){var e;if(void 0===b[a]&&"undefined"!=typeof module&&module&&module.exports&&null!=a.match("^[^/\\\\]*$"))try{e=la._abbr,require("./locale/"+a),ya(e)}catch(e){b[a]=null}return b[a]}function ya(e,a){return e&&((a=d(a)?pa(e):fa(e,a))?la=a:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),la._abbr}function fa(e,a){if(null===a)return delete b[e],null;var t,s=Ma;if(a.abbr=e,null!=b[e])ae("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=b[e]._config;else if(null!=a.parentLocale)if(null!=b[a.parentLocale])s=b[a.parentLocale]._config;else{if(null==(t=Ya(a.parentLocale)))return ha[a.parentLocale]||(ha[a.parentLocale]=[]),ha[a.parentLocale].push({name:e,config:a}),null;s=t._config}return b[e]=new ne(se(s,a)),ha[e]&&ha[e].forEach(function(e){fa(e.name,e.config)}),ya(e),b[e]}function pa(e){var a;if(!(e=e&&e._locale&&e._locale._abbr?e._locale._abbr:e))return la;if(!F(e)){if(a=Ya(e))return a;e=[e]}return La(e)}function ka(e){var a=e._a;return a&&-2===h(e).overflow&&(a=a[xe]<0||11ze(a[g],a[xe])?Pe:a[w]<0||24ea(r,_,o)?h(s)._overflowWeeks=!0:null!=m?h(s)._overflowWeekday=!0:(u=Qe(r,d,i,_,o),s._a[g]=u.year,s._dayOfYear=u.dayOfYear)),null!=e._dayOfYear&&(n=Oa(e._a[g],t[g]),(e._dayOfYear>Be(n)||0===e._dayOfYear)&&(h(e)._overflowDayOfYear=!0),m=Ze(n,0,e._dayOfYear),e._a[xe]=m.getUTCMonth(),e._a[Pe]=m.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=l[a]=t[a];for(;a<7;a++)e._a[a]=l[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[w]&&0===e._a[Oe]&&0===e._a[We]&&0===e._a[Ae]&&(e._nextDay=!0,e._a[w]=0),e._d=(e._useUTC?Ze:qe).apply(null,l),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[w]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(h(e).weekdayMismatch=!0)}}function Aa(e){if(e._f===M.ISO_8601)ja(e);else if(e._f===M.RFC_2822)Pa(e);else{e._a=[],h(e).empty=!0;for(var a,t,s,n,r,d=""+e._i,i=d.length,_=0,o=le(e._f,e._locale).match(ie)||[],m=o.length,u=0;ue.valueOf():e.valueOf()"}),n.toJSON=function(){return this.isValid()?this.toISOString():null},n.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},n.unix=function(){return Math.floor(this.valueOf()/1e3)},n.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},n.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},n.eraName=function(){for(var e,a=this.localeData().eras(),t=0,s=a.length;tthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},n.isLocal=function(){return!!this.isValid()&&!this._isUTC},n.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},n.isUtc=Ka,n.isUTC=Ka,n.zoneAbbr=function(){return this._isUTC?"UTC":""},n.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},n.dates=e("dates accessor is deprecated. Use date instead.",Y),n.months=e("months accessor is deprecated. Use month instead",Ge),n.years=e("years accessor is deprecated. Use year instead",Ke),n.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,a){return null!=e?(this.utcOffset(e="string"!=typeof e?-e:e,a),this):-this.utcOffset()}),n.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!d(this._isDSTShifted))return this._isDSTShifted;var e,a={};return Z(a,this),(a=Ea(a))._a?(e=(a._isUTC?U:S)(a._a),this._isDSTShifted=this.isValid()&&0 show step 2 -const clave_profesor = document.getElementById('clave_profesor'); -const horario_reponer = document.getElementById('horario_reponer'); -const fechas_clase = document.getElementById('fechas_clase'); -const fecha_reponer = $('#fecha_reponer'); -const hora_reponer = $('#hora_reponer'); -const minutos_reponer = $('#minutos_reponer'); -clave_profesor.addEventListener('change', async () => { - const step2 = document.getElementById('step-2'); - clave_profesor.disabled = true; - // get option which value is the same as clave_profesor.value - const option = document.querySelector(`option[value="${clave_profesor.value}"]`); - // make a form data with #form - const profesor_id = document.getElementById('profesor_id'); - profesor_id.value = option.dataset.id; - const formData = new FormData(form); - const response = await fetch(`./action/action_horario_profesor.php`, { - method: 'POST', - body: formData - }); - const data = await response.json(); - if (data['success'] === false) { - const message = "Hubo un error al obtener los horarios del profesor."; - const title = 'Error'; - const color = 'danger'; - triggerMessage(message, title, color); - return; - } - const horarios = data.data; - const initial = document.createElement('option'); - initial.value = ''; - initial.textContent = 'Seleccione un horario'; - initial.selected = true; - initial.disabled = true; - horario_reponer.innerHTML = ''; - horario_reponer.appendChild(initial); - horarios.forEach((horario) => { - const dias = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo']; - const option = document.createElement('option'); - option.value = `${horario.id}`; - // materia máx 25 caracteres, if materia.length > 25 then slice(0, 20) - const max = 25; - option.textContent = `${horario.materia.slice(0, max) + (horario.materia.length > max ? '...' : '')} - Grupo: ${horario.grupo} - ${horario.hora.slice(0, 5)}-${horario.hora_final.slice(0, 5)} - Salon: ${horario.salon} - ${horario.dia}`; - option.dataset.materia = `${horario.materia}`; - option.dataset.grupo = `${horario.grupo}`; - option.dataset.hora = `${horario.hora.slice(0, 5)}`; // slice(0, 5) => HH:MM - option.dataset.hora_final = `${horario.hora_final.slice(0, 5)}`; - option.dataset.salon = `${horario.salon}`; - option.dataset.dia = `${horario.dia}`; - option.dataset.id = `${horario.id}`; - horario_reponer.appendChild(option); - }); - currentStep = 1; - step2.style.display = 'block'; - prevButton.disabled = false; -}); -// disable clave_profesor -// from second step to first step -prevButton.addEventListener('click', () => { - const inputs = [clave_profesor, horario_reponer, fechas_clase, fecha_reponer, hora_reponer]; - switch (currentStep) { - case 1: - case 2: - case 3: - const step = document.getElementById(`step-${currentStep + 1}`); - step.style.display = 'none'; - inputs[currentStep - 1].disabled = false; - inputs[currentStep - 1].value = ''; - if (--currentStep === 0) { - prevButton.disabled = true; - } - break; - case 4: - const step5 = document.getElementById('step-5'); - step5.style.display = 'none'; - fecha_reponer.prop('disabled', false); - fecha_reponer.val(''); - hora_reponer.parent().removeClass('disabled'); - hora_reponer.siblings('.datalist-input').text('hh'); - hora_reponer.val(''); - minutos_reponer.parent().removeClass('disabled'); - minutos_reponer.siblings('.datalist-input').text('mm'); - minutos_reponer.val(''); - currentStep--; - break; - } - nextButton.disabled = true; -}); -// #horario_reponer on change => show step 3 -horario_reponer.addEventListener('change', async () => { - const selected = horario_reponer.querySelector(`option[value="${horario_reponer.value}"]`); - horario_reponer.title = `Materia: ${selected.dataset.materia} - Grupo: ${selected.dataset.grupo} - Horario: ${selected.dataset.hora}-${selected.dataset.hora_final} - Salon: ${selected.dataset.salon} - Día: ${selected.dataset.dia}`; - const step3 = document.getElementById('step-3'); - horario_reponer.disabled = true; - // make a form data with #form - const response = await fetch(`./action/action_fechas_clase.php?horario_id=${horario_reponer.value}`, { - method: 'GET', - }); - const data = await response.json(); - if (data['success'] === false) { - const message = "Hubo un error al obtener las fechas de clase."; - const title = 'Error'; - const color = 'danger'; - triggerMessage(message, title, color); - return; - } - const meses = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; - const fechas = data.data; - const initial = document.createElement('option'); - initial.value = ''; - initial.textContent = 'Seleccione la fecha de la falta'; - initial.selected = true; - initial.disabled = true; - fechas_clase.innerHTML = ''; - fechas_clase.appendChild(initial); - fechas_clase.title = 'Seleccione la fecha de la falta'; - fechas.forEach((fecha) => { - const option = document.createElement('option'); - option.value = `${fecha}`; - option.textContent = `${fecha.dia_mes} de ${meses[fecha.month - 1]} de ${fecha.year}`; - fechas_clase.appendChild(option); - }); - step3.style.display = 'block'; - currentStep = 2; -}); -// #fechas_clase on change => show step 4 -fechas_clase.addEventListener('change', () => { - const step4 = document.getElementById('step-4'); - step4.style.display = 'block'; - fechas_clase.disabled = true; - currentStep = 3; -}); -// when both #fecha_reponer and #hora_reponer are selected => show step 5 -const lastStep = () => { - // timeout to wait for the value to be set - setTimeout(() => { - if (fecha_reponer.val() !== '' && hora_reponer.val() !== '' && minutos_reponer.val() !== '') { - const step5 = document.getElementById('step-5'); - step5.style.display = 'block'; - // disable both - fecha_reponer.prop('disabled', true); - hora_reponer.parent().addClass('disabled'); - minutos_reponer.parent().addClass('disabled'); - const nextButton = document.getElementById('next-button'); - // remove property disabled - nextButton.removeAttribute('disabled'); - currentStep = 4; - } - }, 100); -}; -fecha_reponer.on('change', lastStep); -// on click on the sibling ul>li of #hora_reponer and #minutos_reponer -hora_reponer.siblings('ul').children('li').on('click', lastStep); -minutos_reponer.siblings('ul').children('li').on('click', lastStep); -// Initialize the form -hideSteps(); -showCurrentStep(); -function hideSteps() { - steps.forEach((step) => { - step.style.display = 'none'; - }); -} -function showCurrentStep() { - steps[currentStep].style.display = 'block'; - prevButton.disabled = currentStep === 0; -} -function handleSubmit(event) { - event.preventDefault(); - // Handle form submission - // You can access the form data using the FormData API or serialize it manually -} -export {}; +// Get references to the HTML elements +const form = document.getElementById('form'); +const steps = Array.from(form.querySelectorAll('.step')); +const nextButton = document.getElementById('next-button'); +const prevButton = document.getElementById('prev-button'); +let currentStep = 0; +// #clave_profesor on change => show step 2 +const clave_profesor = document.getElementById('clave_profesor'); +const horario_reponer = document.getElementById('horario_reponer'); +const fechas_clase = document.getElementById('fechas_clase'); +const fecha_reponer = $('#fecha_reponer'); +const hora_reponer = $('#hora_reponer'); +const minutos_reponer = $('#minutos_reponer'); +clave_profesor.addEventListener('change', async () => { + const step2 = document.getElementById('step-2'); + clave_profesor.disabled = true; + // get option which value is the same as clave_profesor.value + const option = document.querySelector(`option[value="${clave_profesor.value}"]`); + // make a form data with #form + const profesor_id = document.getElementById('profesor_id'); + profesor_id.value = option.dataset.id; + const formData = new FormData(form); + const response = await fetch(`./action/action_horario_profesor.php`, { + method: 'POST', + body: formData + }); + const data = await response.json(); + if (data['success'] === false) { + const message = "Hubo un error al obtener los horarios del profesor."; + const title = 'Error'; + const color = 'danger'; + triggerMessage(message, title, color); + return; + } + const horarios = data.data; + const initial = document.createElement('option'); + initial.value = ''; + initial.textContent = 'Seleccione un horario'; + initial.selected = true; + initial.disabled = true; + horario_reponer.innerHTML = ''; + horario_reponer.appendChild(initial); + horarios.forEach((horario) => { + const dias = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo']; + const option = document.createElement('option'); + option.value = `${horario.id}`; + // materia máx 25 caracteres, if materia.length > 25 then slice(0, 20) + const max = 25; + option.textContent = `${horario.materia.slice(0, max) + (horario.materia.length > max ? '...' : '')} - Grupo: ${horario.grupo} - ${horario.hora.slice(0, 5)}-${horario.hora_final.slice(0, 5)} - Salon: ${horario.salon} - ${horario.dia}`; + option.dataset.materia = `${horario.materia}`; + option.dataset.grupo = `${horario.grupo}`; + option.dataset.hora = `${horario.hora.slice(0, 5)}`; // slice(0, 5) => HH:MM + option.dataset.hora_final = `${horario.hora_final.slice(0, 5)}`; + option.dataset.salon = `${horario.salon}`; + option.dataset.dia = `${horario.dia}`; + option.dataset.id = `${horario.id}`; + horario_reponer.appendChild(option); + }); + currentStep = 1; + step2.style.display = 'block'; + prevButton.disabled = false; +}); +// disable clave_profesor +// from second step to first step +prevButton.addEventListener('click', () => { + const inputs = [clave_profesor, horario_reponer, fechas_clase, fecha_reponer, hora_reponer]; + switch (currentStep) { + case 1: + case 2: + case 3: + const step = document.getElementById(`step-${currentStep + 1}`); + step.style.display = 'none'; + inputs[currentStep - 1].disabled = false; + inputs[currentStep - 1].value = ''; + if (--currentStep === 0) { + prevButton.disabled = true; + } + break; + case 4: + const step5 = document.getElementById('step-5'); + step5.style.display = 'none'; + fecha_reponer.prop('disabled', false); + fecha_reponer.val(''); + hora_reponer.parent().removeClass('disabled'); + hora_reponer.siblings('.datalist-input').text('hh'); + hora_reponer.val(''); + minutos_reponer.parent().removeClass('disabled'); + minutos_reponer.siblings('.datalist-input').text('mm'); + minutos_reponer.val(''); + currentStep--; + break; + } + nextButton.disabled = true; +}); +// #horario_reponer on change => show step 3 +horario_reponer.addEventListener('change', async () => { + const selected = horario_reponer.querySelector(`option[value="${horario_reponer.value}"]`); + horario_reponer.title = `Materia: ${selected.dataset.materia} - Grupo: ${selected.dataset.grupo} - Horario: ${selected.dataset.hora}-${selected.dataset.hora_final} - Salon: ${selected.dataset.salon} - Día: ${selected.dataset.dia}`; + const step3 = document.getElementById('step-3'); + horario_reponer.disabled = true; + // make a form data with #form + const response = await fetch(`./action/action_fechas_clase.php?horario_id=${horario_reponer.value}`, { + method: 'GET', + }); + const data = await response.json(); + if (data['success'] === false) { + const message = "Hubo un error al obtener las fechas de clase."; + const title = 'Error'; + const color = 'danger'; + triggerMessage(message, title, color); + return; + } + const meses = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; + const fechas = data.data; + const initial = document.createElement('option'); + initial.value = ''; + initial.textContent = 'Seleccione la fecha de la falta'; + initial.selected = true; + initial.disabled = true; + fechas_clase.innerHTML = ''; + fechas_clase.appendChild(initial); + fechas_clase.title = 'Seleccione la fecha de la falta'; + fechas.forEach((fecha) => { + const option = document.createElement('option'); + option.value = `${fecha}`; + option.textContent = `${fecha.dia_mes} de ${meses[fecha.month - 1]} de ${fecha.year}`; + fechas_clase.appendChild(option); + }); + step3.style.display = 'block'; + currentStep = 2; +}); +// #fechas_clase on change => show step 4 +fechas_clase.addEventListener('change', () => { + const step4 = document.getElementById('step-4'); + step4.style.display = 'block'; + fechas_clase.disabled = true; + currentStep = 3; +}); +// when both #fecha_reponer and #hora_reponer are selected => show step 5 +const lastStep = () => { + // timeout to wait for the value to be set + setTimeout(() => { + if (fecha_reponer.val() !== '' && hora_reponer.val() !== '' && minutos_reponer.val() !== '') { + const step5 = document.getElementById('step-5'); + step5.style.display = 'block'; + // disable both + fecha_reponer.prop('disabled', true); + hora_reponer.parent().addClass('disabled'); + minutos_reponer.parent().addClass('disabled'); + const nextButton = document.getElementById('next-button'); + // remove property disabled + nextButton.removeAttribute('disabled'); + currentStep = 4; + } + }, 100); +}; +fecha_reponer.on('change', lastStep); +// on click on the sibling ul>li of #hora_reponer and #minutos_reponer +hora_reponer.siblings('ul').children('li').on('click', lastStep); +minutos_reponer.siblings('ul').children('li').on('click', lastStep); +// Initialize the form +hideSteps(); +showCurrentStep(); +function hideSteps() { + steps.forEach((step) => { + step.style.display = 'none'; + }); +} +function showCurrentStep() { + steps[currentStep].style.display = 'block'; + prevButton.disabled = currentStep === 0; +} +function handleSubmit(event) { + event.preventDefault(); + // Handle form submission + // You can access the form data using the FormData API or serialize it manually +} +export {}; diff --git a/js/scrollables.js b/js/scrollables.js index 97801c3..1bf98f5 100644 --- a/js/scrollables.js +++ b/js/scrollables.js @@ -1,31 +1,31 @@ -const scrollButtons = ` - - - -` - -document.body.insertAdjacentHTML('beforeend', scrollButtons); - -const scroll_up = document.querySelector('#scroll-up'); -const scroll_down = document.querySelector('#scroll-down'); - -scroll_up.style.transition = scroll_down.style.transition = 'display 1.5s ease-in-out'; -scroll_up.style.display = scroll_down.style.display = 'none'; - -scroll_up.addEventListener('click', () => - window.scrollTo({ top: 0, behavior: 'smooth' })) - - -scroll_down.addEventListener('click', () => - window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })) - -const check = () => { - scroll_down.style.display = (window.scrollY + window.innerHeight) > document.body.scrollHeight * .8 ? 'none' : 'block' - scroll_up.style.display = (window.scrollY) < document.body.scrollHeight * .2 ? 'none' : 'block' -} - -['scroll', 'resize'].forEach(e => window.addEventListener(e, check)) +const scrollButtons = ` + + + +` + +document.body.insertAdjacentHTML('beforeend', scrollButtons); + +const scroll_up = document.querySelector('#scroll-up'); +const scroll_down = document.querySelector('#scroll-down'); + +scroll_up.style.transition = scroll_down.style.transition = 'display 1.5s ease-in-out'; +scroll_up.style.display = scroll_down.style.display = 'none'; + +scroll_up.addEventListener('click', () => + window.scrollTo({ top: 0, behavior: 'smooth' })) + + +scroll_down.addEventListener('click', () => + window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })) + +const check = () => { + scroll_down.style.display = (window.scrollY + window.innerHeight) > document.body.scrollHeight * .8 ? 'none' : 'block' + scroll_up.style.display = (window.scrollY) < document.body.scrollHeight * .2 ? 'none' : 'block' +} + +['scroll', 'resize'].forEach(e => window.addEventListener(e, check)) diff --git a/js/vista_forms.js b/js/vista_forms.js index e3e9488..70d0f5a 100644 --- a/js/vista_forms.js +++ b/js/vista_forms.js @@ -1,65 +1,65 @@ -$(".date-picker").datepicker($.datepicker.regional["es"]); - $(".date-picker").datepicker({ - dateFormat: "dd/mm/yyyy", - changeMonth: true, - }); - $("#fecha_inicial").datepicker("option", "minDate", fecha_inicial); - $("#fecha_inicial").datepicker("option", "maxDate", limit); - $("#fecha_final").datepicker("option", "minDate", fecha_inicial); - $("#fecha_final").datepicker("option", "maxDate", limit); - - var today = new Date(); - - var fecha_inicial = new Date(format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['inicio'])) ?>); - var fecha_final = new Date(format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['fin'])) ?>); - var limit = new Date(Math.min(today, fecha_final)); - // if today is in the period, set the initial date to today - $("#fecha_inicial").datepicker("setDate", fecha_inicial); - $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final); - - function reset_form() { - $("#fecha_inicial").datepicker("setDate", fecha_inicial); - $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final); - $("#dlcarrera").find("li").removeClass("selected"); - $("#dlcarrera").find("li[data-value='0']").addClass("selected"); - $("#dlmateria").find("li").removeClass("selected"); - $("#dlmateria").find("li[data-value='0']").addClass("selected"); - $("#filter_carrera").val(""); - $("#filter_materia").val(""); - - - console.log(`Todos los campos han sido limpiados.`); - } - - - disableDatalist("#filter_materia", true); - - - - - reset_form(); - - // $("#fecha_inicial").on("change", function() { - // var fecha_inicial = $("#fecha_inicial").datepicker("getDate"); - // var fecha_final = $("#fecha_final").datepicker("getDate"); - // if (fecha_final < fecha_inicial) { - // $("#fecha_final").datepicker("setDate", fecha_inicial); - // } - // $("#fecha_final").datepicker("option", "minDate", fecha_inicial); - // }); - - // $("#fecha_final").on("change", function() { - // var fecha_inicial = $("#fecha_inicial").datepicker("getDate"); - // var fecha_final = $("#fecha_final").datepicker("getDate"); - // if (fecha_final < fecha_inicial) { - // $("#fecha_inicial").datepicker("setDate", fecha_final); - // } - // $("#fecha_inicial").datepicker("option", "maxDate", fecha_final); - // }); - // Datalist carrera then select materia - $(document).on('click', '#dlcarrera li', function() { - // if this is empty - // console.log($(this).attr('data-value')); - if ($(this).attr('data-value') == '0') - disableDatalist("#filter_materia", true); +$(".date-picker").datepicker($.datepicker.regional["es"]); + $(".date-picker").datepicker({ + dateFormat: "dd/mm/yyyy", + changeMonth: true, + }); + $("#fecha_inicial").datepicker("option", "minDate", fecha_inicial); + $("#fecha_inicial").datepicker("option", "maxDate", limit); + $("#fecha_final").datepicker("option", "minDate", fecha_inicial); + $("#fecha_final").datepicker("option", "maxDate", limit); + + var today = new Date(); + + var fecha_inicial = new Date(format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['inicio'])) ?>); + var fecha_final = new Date(format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['fin'])) ?>); + var limit = new Date(Math.min(today, fecha_final)); + // if today is in the period, set the initial date to today + $("#fecha_inicial").datepicker("setDate", fecha_inicial); + $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final); + + function reset_form() { + $("#fecha_inicial").datepicker("setDate", fecha_inicial); + $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final); + $("#dlcarrera").find("li").removeClass("selected"); + $("#dlcarrera").find("li[data-value='0']").addClass("selected"); + $("#dlmateria").find("li").removeClass("selected"); + $("#dlmateria").find("li[data-value='0']").addClass("selected"); + $("#filter_carrera").val(""); + $("#filter_materia").val(""); + + + console.log(`Todos los campos han sido limpiados.`); + } + + + disableDatalist("#filter_materia", true); + + + + + reset_form(); + + // $("#fecha_inicial").on("change", function() { + // var fecha_inicial = $("#fecha_inicial").datepicker("getDate"); + // var fecha_final = $("#fecha_final").datepicker("getDate"); + // if (fecha_final < fecha_inicial) { + // $("#fecha_final").datepicker("setDate", fecha_inicial); + // } + // $("#fecha_final").datepicker("option", "minDate", fecha_inicial); + // }); + + // $("#fecha_final").on("change", function() { + // var fecha_inicial = $("#fecha_inicial").datepicker("getDate"); + // var fecha_final = $("#fecha_final").datepicker("getDate"); + // if (fecha_final < fecha_inicial) { + // $("#fecha_inicial").datepicker("setDate", fecha_final); + // } + // $("#fecha_inicial").datepicker("option", "maxDate", fecha_final); + // }); + // Datalist carrera then select materia + $(document).on('click', '#dlcarrera li', function() { + // if this is empty + // console.log($(this).attr('data-value')); + if ($(this).attr('data-value') == '0') + disableDatalist("#filter_materia", true); }); \ No newline at end of file diff --git a/justificar_asistencias.php b/justificar_asistencias.php index 351cf99..3de1199 100644 --- a/justificar_asistencias.php +++ b/justificar_asistencias.php @@ -1,333 +1,333 @@ -access(); -if (!$user->admin && in_array($user->acceso, ['r', 'n'])) { - // die($access); - header('Location: main.php?error=1'); -} else { - $user->print_to_log('Consultar asistencia'); -} - -?> - - - - - Justificar asistencias | <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - -
      -
      - - - - - - - - - - - - - - - - - - - - -
      - - ClaveProfesorHoraMateriaGrupoSalón
      - -
      -
      - -
      -
      - - -
      - - - - - - +access(); +if (!$user->admin && in_array($user->acceso, ['r', 'n'])) { + // die($access); + header('Location: main.php?error=1'); +} else { + $user->print_to_log('Consultar asistencia'); +} + +?> + + + + + Justificar asistencias | <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + +
      +
      + + + + + + + + + + + + + + + + + + + + +
      + + ClaveProfesorHoraMateriaGrupoSalón
      + +
      +
      + +
      +
      + + +
      + + + + + + \ No newline at end of file diff --git a/main.php b/main.php index c95f475..efc214a 100644 --- a/main.php +++ b/main.php @@ -1,125 +1,112 @@ - - - - - - - - Editar Horarios | - <?= $user->facultad['facultad'] ?? "Administrador"; ?> - - - - - - - -
      -
      -

      - - user['nombre']; ?> - - - facultad['facultad'] ?? "General"; ?> - - - rol['rol']; ?> - -

      -
      -
      - querySingle("SELECT FALSE") or die($db->getLastError()); - if (array_pop($has_token)) { - ?> - - - - - - -
      -
      - - - - - - - + + + + + + + + Editar Horarios | + <?= $user->facultad['facultad'] ?? "Administrador"; ?> + + + + + + + +
      +
      +

      + + user['nombre']; ?> + + + facultad['facultad']; ?> + + + rol['rol']; ?> + +

      +
      +
      + admin + ? $db->query("SELECT * FROM PAGINA WHERE grupo_id = :grupo_id ORDER BY pagina_titulo ASC", array(":grupo_id" => $grupo['grupo_id'])) + : $db->query( + "SELECT * FROM PAGINA WHERE pagina_id IN (SELECT pagina_id FROM PERMISO_VIEW WHERE grupo_id = :grupo_id and id = :id) ORDER BY pagina_titulo", + array(":grupo_id" => $grupo['grupo_id'], ":id" => $user->user['id']) + ); + ?> +

      + + + +

      +
      + +
      + +
      + +
      +
      + + + + + + + \ No newline at end of file diff --git a/materias.php b/materias.php index 14dc211..efaacc3 100644 --- a/materias.php +++ b/materias.php @@ -1,281 +1,281 @@ -access(); -if (!$user->admin && $user->acceso == 'n') { - // die($access); - header('Location: main.php?error=1'); -} else { - $user->print_to_log('Materias'); -} -$facultad = $user->facultad['facultad_id'] ?? -1; -if ($user->admin) { - $facultad = null; -} -?> - - - - - - - Materias - - - - - - access(); - $max_count = 30; - - $sql = "SELECT * FROM fs_materias(:nombre, :carrera, :facultad)"; - if (isset($_POST["desc"])) { - $desc = $_POST["desc"]; - $filter_desc = trim(filter_input(INPUT_POST, "desc", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $desc=null; - } - - if (isset($_POST["carrera"])) { - $pcarrera = $_POST["carrera"]; - $filter_carrera = trim(filter_input(INPUT_POST, "carrera", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $pcarrera=null; - } - - if ($pcarrera == "") { - $sql .= "LIMIT 30"; - } - $fs_materias = query( - $sql, - array(":nombre" => $desc, ":carrera" => $pcarrera, ":facultad" => $facultad), - single: false - ); - $fs_carreras = query( - "SELECT * FROM fs_carreras(:facultad, null, null)", - array(":facultad" => $facultad), - single: false - ); - - //print_r($fs_materias); - - ?> -
      - - -
      -
      -
      -
      -
      - -
      - > -
      -
      -
      - -
      -
      -
      Mostrar todas
      - -
        -
      • Mostrar todas
      • - -
      • - -
      • " class="pl-4 ">
      • - -
      - -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      -
      - - -
      -
      - -

      Se muestran los primeros resultados. Utiliza los filtros para encontrar la materia que buscas.

      - - - - - - - acceso == 'w') { ?> - - - - - - - " id=""> - - - acceso == 'w') { ?> - - - - - -
      NombreCarreraAcciones
      - -
      -
      -
      -
      -
      - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/test.php b/test.php index 24d2557..84bc698 100644 --- a/test.php +++ b/test.php @@ -1,31 +1,31 @@ - - - - - Consultar horario | <?= $user->facultad['facultad'] ?? 'General' ?> - - - - - - - - - - " ?> -
      - -
      - - - - - + + + + + Consultar horario | <?= $user->facultad['facultad'] ?? 'General' ?> + + + + + + + + + + " ?> +
      + +
      + + + + + \ No newline at end of file diff --git a/ts/auditoría.ts b/ts/auditoría.ts index 59bc4f3..aea5137 100644 --- a/ts/auditoría.ts +++ b/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) => - ` - ${store.estados.getEstado(estado).nombre} - ` - ).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') \ No newline at end of file +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) => + ` + ${store.estados.getEstado(estado).nombre} + ` + ).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') diff --git a/ts/client.ts b/ts/client.ts index d07a6f2..a072b0c 100644 --- a/ts/client.ts +++ b/ts/client.ts @@ -1,149 +1,149 @@ -// @ts-ignore Import module -import { createApp, reactive } from 'https://unpkg.com/petite-vue?module' - -export interface PeridoV1 { - IdNivel: number; - IdPeriodo: number; - NombreNivel: string; - NombrePeriodo: string; - in_db: boolean; - linked: boolean; -} - - -export interface PeridoV2 { - ClaveCarrera: string; - FechaFin: string; - FechaInicio: string; - IdPeriodo: number; - NombreCarrera: string; -} - -const webServices = { - getPeriodosV1: async (): Promise => { - try { - const response = await fetch('periodos.v1.php'); - return await response.json(); - } catch (error) { - console.log(error); - return []; - } - }, - getPeriodosV2: async (): Promise => { - try { - const response = await fetch('periodos.v2.php'); - return await response.json(); - } catch (error) { - console.log(error); - return []; - } - } -} - -const store = reactive({ - periodosV1: [] as PeridoV1[], - periodosV2: [] as PeridoV2[], - - errors: [] as string[], - fechas(idPeriodo: number): { inicio: string, fin: string } { - const periodo = this.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo); - return { - inicio: periodo ? periodo.FechaInicio : '', - fin: periodo ? periodo.FechaFin : '' - } - }, - periodov1(idPeriodo: number): PeridoV1 | undefined { - return this.periodosV1.find((periodo: PeridoV1) => periodo.IdPeriodo === idPeriodo); - }, - periodov2(idPeriodo: number): PeridoV2[] { - return this.periodosV2.filter((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo); - }, - async addPeriodo(periodo: PeridoV1 | PeridoV2) { - try { - const result = await fetch('backend/periodos.php', { - method: 'POST', - body: JSON.stringify({ - ...periodo, - ...this.fechas(periodo.IdPeriodo) - }), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()); - if (result.success) { - this.periodosV1 = this.periodosV1.map((periodoV1: PeridoV1) => { - if (periodoV1.IdPeriodo === periodo.IdPeriodo) { - periodoV1.in_db = true; - } - return periodoV1; - }); - return result; - } - else { - this.errors.push(result.message); - } - } catch (error) { - this.errors.push(error); - } - }, - - async addCarreras(idPeriodo: number) { - try { - const periodoV1 = this.periodov1(idPeriodo) as PeridoV1; - const periodoV2 = this.periodov2(idPeriodo) as PeridoV2[]; - - const data = periodoV2.map(({ ClaveCarrera, NombreCarrera }: PeridoV2) => - ({ - ClaveCarrera: ClaveCarrera, - NombreCarrera: NombreCarrera, - IdNivel: periodoV1.IdNivel, - }) - ); - - const result = await fetch('backend/carreras.php', { - method: 'POST', - body: JSON.stringify(data), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => response.json()); - if (result.success) { - await webServices.getPeriodosV1().then((periodosV1) => { - this.periodosV1 = periodosV1; - }); - - await webServices.getPeriodosV2().then((periodosV2) => { - this.periodosV2 = periodosV2; - }); - } - - } catch (error) { - this.errors.push(error); - } - } -}) - - -createApp({ - store, - info(IdPeriodo: number): PeridoV2 { - const periodo = store.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === IdPeriodo && - periodo.FechaInicio != '' && periodo.FechaFin != ''); - return periodo - }, - complete(IdPeriodo: number): boolean { - const info = this.info(IdPeriodo); - return info !== undefined; - }, - mounted: async () => { - - await webServices.getPeriodosV1().then((periodosV1) => { - store.periodosV1 = periodosV1; - }); - - await webServices.getPeriodosV2().then((periodosV2) => { - store.periodosV2 = periodosV2; - }); - - } +// @ts-ignore Import module +import { createApp, reactive } from 'https://unpkg.com/petite-vue?module' + +export interface PeridoV1 { + IdNivel: number; + IdPeriodo: number; + NombreNivel: string; + NombrePeriodo: string; + in_db: boolean; + linked: boolean; +} + + +export interface PeridoV2 { + ClaveCarrera: string; + FechaFin: string; + FechaInicio: string; + IdPeriodo: number; + NombreCarrera: string; +} + +const webServices = { + getPeriodosV1: async (): Promise => { + try { + const response = await fetch('periodos.v1.php'); + return await response.json(); + } catch (error) { + console.log(error); + return []; + } + }, + getPeriodosV2: async (): Promise => { + try { + const response = await fetch('periodos.v2.php'); + return await response.json(); + } catch (error) { + console.log(error); + return []; + } + } +} + +const store = reactive({ + periodosV1: [] as PeridoV1[], + periodosV2: [] as PeridoV2[], + + errors: [] as string[], + fechas(idPeriodo: number): { inicio: string, fin: string } { + const periodo = this.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo); + return { + inicio: periodo ? periodo.FechaInicio : '', + fin: periodo ? periodo.FechaFin : '' + } + }, + periodov1(idPeriodo: number): PeridoV1 | undefined { + return this.periodosV1.find((periodo: PeridoV1) => periodo.IdPeriodo === idPeriodo); + }, + periodov2(idPeriodo: number): PeridoV2[] { + return this.periodosV2.filter((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo); + }, + async addPeriodo(periodo: PeridoV1 | PeridoV2) { + try { + const result = await fetch('backend/periodos.php', { + method: 'POST', + body: JSON.stringify({ + ...periodo, + ...this.fechas(periodo.IdPeriodo) + }), + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => response.json()); + if (result.success) { + this.periodosV1 = this.periodosV1.map((periodoV1: PeridoV1) => { + if (periodoV1.IdPeriodo === periodo.IdPeriodo) { + periodoV1.in_db = true; + } + return periodoV1; + }); + return result; + } + else { + this.errors.push(result.message); + } + } catch (error) { + this.errors.push(error); + } + }, + + async addCarreras(idPeriodo: number) { + try { + const periodoV1 = this.periodov1(idPeriodo) as PeridoV1; + const periodoV2 = this.periodov2(idPeriodo) as PeridoV2[]; + + const data = periodoV2.map(({ ClaveCarrera, NombreCarrera }: PeridoV2) => + ({ + ClaveCarrera: ClaveCarrera, + NombreCarrera: NombreCarrera, + IdNivel: periodoV1.IdNivel, + }) + ); + + const result = await fetch('backend/carreras.php', { + method: 'POST', + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => response.json()); + if (result.success) { + await webServices.getPeriodosV1().then((periodosV1) => { + this.periodosV1 = periodosV1; + }); + + await webServices.getPeriodosV2().then((periodosV2) => { + this.periodosV2 = periodosV2; + }); + } + + } catch (error) { + this.errors.push(error); + } + } +}) + + +createApp({ + store, + info(IdPeriodo: number): PeridoV2 { + const periodo = store.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === IdPeriodo && + periodo.FechaInicio != '' && periodo.FechaFin != ''); + return periodo + }, + complete(IdPeriodo: number): boolean { + const info = this.info(IdPeriodo); + return info !== undefined; + }, + mounted: async () => { + + await webServices.getPeriodosV1().then((periodosV1) => { + store.periodosV1 = periodosV1; + }); + + await webServices.getPeriodosV2().then((periodosV2) => { + store.periodosV2 = periodosV2; + }); + + } }).mount() \ No newline at end of file diff --git a/ts/horario_profesor.ts b/ts/horario_profesor.ts index e7a7f1a..f6298a6 100644 --- a/ts/horario_profesor.ts +++ b/ts/horario_profesor.ts @@ -1,532 +1,532 @@ -declare function triggerMessage(message: string, title: string, color?: string): void; -declare const write: boolean; -declare const moment: any; - -/** - * Funciones auxiliares - */ -type Profesor = { - id: number, - grado: string, - profesor: string, - clave: string, -} - -type Horario = { - id: number, - carrera_id: number, - materia: string, - salon: string, - profesores: Profesor[], - hora: string, - hora_final: string, - dia: string, - duracion: number, - bloques: number, - grupo: string, - materia_id: number, -} - -const compareHours = (hora1: string, hora2: string): number => { - 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 = [] as Horario[]; -const table = document.querySelector("table") as HTMLTableElement; -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: number) => `${minute}`.padStart(2, '0')).forEach((minute: string) => { - const tr = document.createElement("tr") as HTMLTableRowElement; - tr.id = `hora-${hora}:${minute}`; - tr.classList.add(hora > 13 ? "tarde" : "mañana"); - if (minute == "00") { - const th = document.createElement("th") as HTMLTableCellElement; - 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") as HTMLTableCellElement; - td.id = `hora-${hora}:${minute}-${día}`; - tr.appendChild(td); - }); - const tbody = document.querySelector("tbody#horario") as HTMLTableSectionElement; - if (!(tbody instanceof HTMLTableSectionElement)) { - throw new Error("No se ha encontrado el tbody"); - } - - tbody.appendChild(tr); - }); -}); - -const empty_table = table.cloneNode(true) as HTMLTableElement; -document.querySelectorAll('.hidden').forEach((element: HTMLElement) => { - element.style.display = "none"; -}); -// hide the table -table.style.display = "none"; - -function moveHorario(id: string, día: string, hora: string) { - - 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: HTMLElement) => element.style.display = "none"); - return; - } - // show the table - table.style.display = "table"; - document.querySelectorAll('.hidden').forEach((element: HTMLElement) => element.style.display = "block"); - // clear the table - table.innerHTML = empty_table.outerHTML; - - function conflicts(horario1: Horario, horario2: Horario): boolean { - 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: number, minutos: number, dia: string, cells: number = 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: Horario, edit = false) { - function move(horario: Horario, cells: number = 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}`) as HTMLTableCellElement; - if (!cell) return; - - cell.dataset.ids = `${horario.id}`; - - const float_menu = edit ? - `` - : ''; - - cell.innerHTML = - `
      - ${horario.hora} - ${horario.materia}
      -
      Salón: ${horario.salon}
      - - ${horario.profesores.map((profesor: Profesor) => ` ${profesor.grado ?? ''} ${profesor.profesor}`).join("
      ")} -
      -
      - ${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: Horario[], 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 = ` - - ${hora} - -
      -
      - - - Empalme de ${ids.length} horarios - -
      - Ver horarios … -
      -
      - `; - - // 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 += ` - - ${horario.hora.slice(0, -3)}-${horario.hora_final.slice(0, -3)} - ${horario.materia} - - ${horario.profesores.map(({ grado, profesor }) => `${grado ?? ''} ${profesor}`).join(", ")} - - ${horario.salon} - ${edit ? ` - - - - - - - ` : ""} - `; - }); - - document.querySelectorAll(".dismiss-editar").forEach(btn => { - btn.addEventListener("click", () => $("#modal-choose").modal("hide")); - }); - }); - - function getDuration(hora_i: string, hora_f: string): number { - 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: Date, horario: 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") as NodeListOf; - 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}"]`) as HTMLElement; - - // remove all children - while (bloque.firstChild) { - bloque.removeChild(bloque.firstChild); - } - - // prepend a loading child - const loading = `
      - Loading... -
      `; - 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') as HTMLFormElement; - -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') as HTMLInputElement; - const option = form.querySelector(`option[value="${input.value}"]`) as HTMLOptionElement; - - 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') as HTMLInputElement; - 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') as HTMLInputElement; - 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") as NodeListOf; - 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') as HTMLInputElement; -const option = form.querySelector(`option[value="${input.value}"]`) as HTMLOptionElement; - +declare function triggerMessage(message: string, title: string, color?: string): void; +declare const write: boolean; +declare const moment: any; + +/** + * Funciones auxiliares + */ +type Profesor = { + id: number, + grado: string, + profesor: string, + clave: string, +} + +type Horario = { + id: number, + carrera_id: number, + materia: string, + salon: string, + profesores: Profesor[], + hora: string, + hora_final: string, + dia: string, + duracion: number, + bloques: number, + grupo: string, + materia_id: number, +} + +const compareHours = (hora1: string, hora2: string): number => { + 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 = [] as Horario[]; +const table = document.querySelector("table") as HTMLTableElement; +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: number) => `${minute}`.padStart(2, '0')).forEach((minute: string) => { + const tr = document.createElement("tr") as HTMLTableRowElement; + tr.id = `hora-${hora}:${minute}`; + tr.classList.add(hora > 13 ? "tarde" : "mañana"); + if (minute == "00") { + const th = document.createElement("th") as HTMLTableCellElement; + 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") as HTMLTableCellElement; + td.id = `hora-${hora}:${minute}-${día}`; + tr.appendChild(td); + }); + const tbody = document.querySelector("tbody#horario") as HTMLTableSectionElement; + if (!(tbody instanceof HTMLTableSectionElement)) { + throw new Error("No se ha encontrado el tbody"); + } + + tbody.appendChild(tr); + }); +}); + +const empty_table = table.cloneNode(true) as HTMLTableElement; +document.querySelectorAll('.hidden').forEach((element: HTMLElement) => { + element.style.display = "none"; +}); +// hide the table +table.style.display = "none"; + +function moveHorario(id: string, día: string, hora: string) { + + 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: HTMLElement) => element.style.display = "none"); + return; + } + // show the table + table.style.display = "table"; + document.querySelectorAll('.hidden').forEach((element: HTMLElement) => element.style.display = "block"); + // clear the table + table.innerHTML = empty_table.outerHTML; + + function conflicts(horario1: Horario, horario2: Horario): boolean { + 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: number, minutos: number, dia: string, cells: number = 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: Horario, edit = false) { + function move(horario: Horario, cells: number = 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}`) as HTMLTableCellElement; + if (!cell) return; + + cell.dataset.ids = `${horario.id}`; + + const float_menu = edit ? + `` + : ''; + + cell.innerHTML = + `
      + ${horario.hora} + ${horario.materia}
      +
      Salón: ${horario.salon}
      + + ${horario.profesores.map((profesor: Profesor) => ` ${profesor.grado ?? ''} ${profesor.profesor}`).join("
      ")} +
      +
      + ${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: Horario[], 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 = ` + + ${hora} + +
      +
      + + + Empalme de ${ids.length} horarios + +
      + Ver horarios … +
      +
      + `; + + // 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 += ` + + ${horario.hora.slice(0, -3)}-${horario.hora_final.slice(0, -3)} + ${horario.materia} + + ${horario.profesores.map(({ grado, profesor }) => `${grado ?? ''} ${profesor}`).join(", ")} + + ${horario.salon} + ${edit ? ` + + + + + + + ` : ""} + `; + }); + + document.querySelectorAll(".dismiss-editar").forEach(btn => { + btn.addEventListener("click", () => $("#modal-choose").modal("hide")); + }); + }); + + function getDuration(hora_i: string, hora_f: string): number { + 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: Date, horario: 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") as NodeListOf; + 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}"]`) as HTMLElement; + + // remove all children + while (bloque.firstChild) { + bloque.removeChild(bloque.firstChild); + } + + // prepend a loading child + const loading = `
      + Loading... +
      `; + 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') as HTMLFormElement; + +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') as HTMLInputElement; + const option = form.querySelector(`option[value="${input.value}"]`) as HTMLOptionElement; + + 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') as HTMLInputElement; + 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') as HTMLInputElement; + 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") as NodeListOf; + 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') as HTMLInputElement; +const option = form.querySelector(`option[value="${input.value}"]`) as HTMLOptionElement; + diff --git a/ts/reposiciones.ts b/ts/reposiciones.ts index 50fe4d6..5cabca7 100644 --- a/ts/reposiciones.ts +++ b/ts/reposiciones.ts @@ -1,272 +1,272 @@ -import { type } from "os"; - -declare function triggerMessage(message: string, title: string, type?: string): void; -declare const write: boolean; -declare const moment: any; -// from this 'horario_id', 'fecha', 'hora', 'duracion_id', 'descripcion', 'profesor_id', 'salon', 'unidad', 'periodo_id', 'fecha_clase' make a type of ReposicionParams -export interface ReposicionParams { - horario_id: number; - fecha: string; - hora: string; - duracion_id: number; - descripcion: string; - profesor_id: number; - salon: string; - unidad: number; - periodo_id: number; - fecha_clase: string; -} - -type Horario = { - id: number; - carrera_id: number; - materia_id: number; - grupo: string; - profesores: Profesor[]; - dia: string; - hora: string; - hora_final: string; - salon: string; - fecha_inicio: string; - fecha_final: string; - fecha_carga: string; - nivel_id: number; - periodo_id: number; - facultad_id: number; - materia: string; - horas: number; - minutos: number; - duracion: number; - retardo: boolean; - original_id: number; - last: boolean; - bloques: number; -}; - -type Profesor = { - id: number; - clave: string; - grado: string; - profesor: string; - nombre: string; - facultad_id: number; -}; -// Get references to the HTML elements -const form = document.getElementById('form') as HTMLFormElement; -const steps = Array.from(form.querySelectorAll('.step')) as HTMLElement[]; - -const nextButton = document.getElementById('next-button') as HTMLButtonElement; -const prevButton = document.getElementById('prev-button') as HTMLButtonElement; - -let currentStep = 0; - -// #clave_profesor on change => show step 2 -const clave_profesor = document.getElementById('clave_profesor') as HTMLInputElement; -const horario_reponer = document.getElementById('horario_reponer') as HTMLInputElement; -const fechas_clase = document.getElementById('fechas_clase') as HTMLInputElement; - -const fecha_reponer = $('#fecha_reponer') as JQuery; -const hora_reponer = $('#hora_reponer') as JQuery; -const minutos_reponer = $('#minutos_reponer') as JQuery; - -clave_profesor.addEventListener('change', async () => { - const step2 = document.getElementById('step-2') as HTMLElement; - clave_profesor.disabled = true; - // get option which value is the same as clave_profesor.value - const option = document.querySelector(`option[value="${clave_profesor.value}"]`) as HTMLOptionElement; - - // make a form data with #form - const profesor_id = document.getElementById('profesor_id') as HTMLInputElement; - profesor_id.value = option.dataset.id; - - const formData = new FormData(form); - - const response = await fetch(`./action/action_horario_profesor.php`, { - method: 'POST', - body: formData - }); - const data = await response.json(); - if (data['success'] === false) { - const message = "Hubo un error al obtener los horarios del profesor." - const title = 'Error'; - const color = 'danger'; - triggerMessage(message, title, color); - return; - } - const horarios = data.data as Horario[]; - const initial = document.createElement('option'); - initial.value = ''; - initial.textContent = 'Seleccione un horario'; - initial.selected = true; - initial.disabled = true; - horario_reponer.innerHTML = ''; - horario_reponer.appendChild(initial); - - horarios.forEach((horario) => { - const dias = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo']; - const option = document.createElement('option'); - option.value = `${horario.id}`; - // materia máx 25 caracteres, if materia.length > 25 then slice(0, 20) - const max = 25; - option.textContent = `${horario.materia.slice(0, max) + (horario.materia.length > max ? '...' : '')} - Grupo: ${horario.grupo} - ${horario.hora.slice(0, 5)}-${horario.hora_final.slice(0, 5)} - Salon: ${horario.salon} - ${horario.dia}`; - - option.dataset.materia = `${horario.materia}`; - option.dataset.grupo = `${horario.grupo}`; - option.dataset.hora = `${horario.hora.slice(0, 5)}`; // slice(0, 5) => HH:MM - option.dataset.hora_final = `${horario.hora_final.slice(0, 5)}`; - option.dataset.salon = `${horario.salon}`; - option.dataset.dia = `${horario.dia}`; - - option.dataset.id = `${horario.id}`; - horario_reponer.appendChild(option); - }); - currentStep = 1; - step2.style.display = 'block'; - prevButton.disabled = false; -}); -// disable clave_profesor - -// from second step to first step -prevButton.addEventListener('click', () => { - const inputs = [clave_profesor, horario_reponer, fechas_clase, fecha_reponer, hora_reponer] as HTMLInputElement[]; - switch (currentStep) { - case 1: - case 2: - case 3: - const step = document.getElementById(`step-${currentStep + 1}`) as HTMLElement; - step.style.display = 'none'; - inputs[currentStep - 1].disabled = false; - inputs[currentStep - 1].value = ''; - if (--currentStep === 0) { - prevButton.disabled = true; - } - break; - case 4: - const step5 = document.getElementById('step-5') as HTMLElement; - step5.style.display = 'none'; - fecha_reponer.prop('disabled', false); - fecha_reponer.val(''); - - hora_reponer.parent().removeClass('disabled'); - hora_reponer.siblings('.datalist-input').text('hh'); - hora_reponer.val(''); - - minutos_reponer.parent().removeClass('disabled'); - minutos_reponer.siblings('.datalist-input').text('mm'); - minutos_reponer.val(''); - - currentStep--; - break; - } - - nextButton.disabled = true; - -}); - -// #horario_reponer on change => show step 3 -horario_reponer.addEventListener('change', async () => { - const selected = horario_reponer.querySelector(`option[value="${horario_reponer.value}"]`) as HTMLOptionElement; - horario_reponer.title = `Materia: ${selected.dataset.materia} - Grupo: ${selected.dataset.grupo} - Horario: ${selected.dataset.hora}-${selected.dataset.hora_final} - Salon: ${selected.dataset.salon} - Día: ${selected.dataset.dia}`; - const step3 = document.getElementById('step-3') as HTMLElement; - horario_reponer.disabled = true; - // make a form data with #form - const response = await fetch(`./action/action_fechas_clase.php?horario_id=${horario_reponer.value}`, { - method: 'GET', - }); - - const data = await response.json(); - if (data['success'] === false) { - const message = "Hubo un error al obtener las fechas de clase." - const title = 'Error'; - const color = 'danger'; - triggerMessage(message, title, color); - return; - } - type Fecha = { - fecha: string; - dia_mes: number; - day: number; - month: number; - year: number; - } - - const meses = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; - - const fechas = data.data as Fecha[]; - const initial = document.createElement('option'); - initial.value = ''; - initial.textContent = 'Seleccione la fecha de la falta'; - initial.selected = true; - initial.disabled = true; - fechas_clase.innerHTML = ''; - fechas_clase.appendChild(initial); - fechas_clase.title = 'Seleccione la fecha de la falta'; - - fechas.forEach((fecha) => { - const option = document.createElement('option'); - option.value = `${fecha}`; - option.textContent = `${fecha.dia_mes} de ${meses[fecha.month - 1]} de ${fecha.year}`; - fechas_clase.appendChild(option); - }); - - - step3.style.display = 'block'; - currentStep = 2; -}); - -// #fechas_clase on change => show step 4 -fechas_clase.addEventListener('change', () => { - const step4 = document.getElementById('step-4') as HTMLElement; - step4.style.display = 'block'; - fechas_clase.disabled = true; - currentStep = 3; -}); - -// when both #fecha_reponer and #hora_reponer are selected => show step 5 - -const lastStep = () => { - // timeout to wait for the value to be set - setTimeout(() => { - if (fecha_reponer.val() !== '' && hora_reponer.val() !== '' && minutos_reponer.val() !== '') { - const step5 = document.getElementById('step-5') as HTMLElement; - step5.style.display = 'block'; - // disable both - fecha_reponer.prop('disabled', true); - hora_reponer.parent().addClass('disabled'); - minutos_reponer.parent().addClass('disabled'); - - const nextButton = document.getElementById('next-button') as HTMLButtonElement; - // remove property disabled - nextButton.removeAttribute('disabled'); - currentStep = 4; - } - }, 100); -} -fecha_reponer.on('change', lastStep); -// on click on the sibling ul>li of #hora_reponer and #minutos_reponer - -hora_reponer.siblings('ul').children('li').on('click', lastStep); -minutos_reponer.siblings('ul').children('li').on('click', lastStep); - -// Initialize the form -hideSteps(); -showCurrentStep(); - - -function hideSteps() { - steps.forEach((step) => { - step.style.display = 'none'; - }); -} - -function showCurrentStep() { - steps[currentStep].style.display = 'block'; - prevButton.disabled = currentStep === 0; -} - -function handleSubmit(event: Event) { - event.preventDefault(); - - // Handle form submission - // You can access the form data using the FormData API or serialize it manually +import { type } from "os"; + +declare function triggerMessage(message: string, title: string, type?: string): void; +declare const write: boolean; +declare const moment: any; +// from this 'horario_id', 'fecha', 'hora', 'duracion_id', 'descripcion', 'profesor_id', 'salon', 'unidad', 'periodo_id', 'fecha_clase' make a type of ReposicionParams +export interface ReposicionParams { + horario_id: number; + fecha: string; + hora: string; + duracion_id: number; + descripcion: string; + profesor_id: number; + salon: string; + unidad: number; + periodo_id: number; + fecha_clase: string; +} + +type Horario = { + id: number; + carrera_id: number; + materia_id: number; + grupo: string; + profesores: Profesor[]; + dia: string; + hora: string; + hora_final: string; + salon: string; + fecha_inicio: string; + fecha_final: string; + fecha_carga: string; + nivel_id: number; + periodo_id: number; + facultad_id: number; + materia: string; + horas: number; + minutos: number; + duracion: number; + retardo: boolean; + original_id: number; + last: boolean; + bloques: number; +}; + +type Profesor = { + id: number; + clave: string; + grado: string; + profesor: string; + nombre: string; + facultad_id: number; +}; +// Get references to the HTML elements +const form = document.getElementById('form') as HTMLFormElement; +const steps = Array.from(form.querySelectorAll('.step')) as HTMLElement[]; + +const nextButton = document.getElementById('next-button') as HTMLButtonElement; +const prevButton = document.getElementById('prev-button') as HTMLButtonElement; + +let currentStep = 0; + +// #clave_profesor on change => show step 2 +const clave_profesor = document.getElementById('clave_profesor') as HTMLInputElement; +const horario_reponer = document.getElementById('horario_reponer') as HTMLInputElement; +const fechas_clase = document.getElementById('fechas_clase') as HTMLInputElement; + +const fecha_reponer = $('#fecha_reponer') as JQuery; +const hora_reponer = $('#hora_reponer') as JQuery; +const minutos_reponer = $('#minutos_reponer') as JQuery; + +clave_profesor.addEventListener('change', async () => { + const step2 = document.getElementById('step-2') as HTMLElement; + clave_profesor.disabled = true; + // get option which value is the same as clave_profesor.value + const option = document.querySelector(`option[value="${clave_profesor.value}"]`) as HTMLOptionElement; + + // make a form data with #form + const profesor_id = document.getElementById('profesor_id') as HTMLInputElement; + profesor_id.value = option.dataset.id; + + const formData = new FormData(form); + + const response = await fetch(`./action/action_horario_profesor.php`, { + method: 'POST', + body: formData + }); + const data = await response.json(); + if (data['success'] === false) { + const message = "Hubo un error al obtener los horarios del profesor." + const title = 'Error'; + const color = 'danger'; + triggerMessage(message, title, color); + return; + } + const horarios = data.data as Horario[]; + const initial = document.createElement('option'); + initial.value = ''; + initial.textContent = 'Seleccione un horario'; + initial.selected = true; + initial.disabled = true; + horario_reponer.innerHTML = ''; + horario_reponer.appendChild(initial); + + horarios.forEach((horario) => { + const dias = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo']; + const option = document.createElement('option'); + option.value = `${horario.id}`; + // materia máx 25 caracteres, if materia.length > 25 then slice(0, 20) + const max = 25; + option.textContent = `${horario.materia.slice(0, max) + (horario.materia.length > max ? '...' : '')} - Grupo: ${horario.grupo} - ${horario.hora.slice(0, 5)}-${horario.hora_final.slice(0, 5)} - Salon: ${horario.salon} - ${horario.dia}`; + + option.dataset.materia = `${horario.materia}`; + option.dataset.grupo = `${horario.grupo}`; + option.dataset.hora = `${horario.hora.slice(0, 5)}`; // slice(0, 5) => HH:MM + option.dataset.hora_final = `${horario.hora_final.slice(0, 5)}`; + option.dataset.salon = `${horario.salon}`; + option.dataset.dia = `${horario.dia}`; + + option.dataset.id = `${horario.id}`; + horario_reponer.appendChild(option); + }); + currentStep = 1; + step2.style.display = 'block'; + prevButton.disabled = false; +}); +// disable clave_profesor + +// from second step to first step +prevButton.addEventListener('click', () => { + const inputs = [clave_profesor, horario_reponer, fechas_clase, fecha_reponer, hora_reponer] as HTMLInputElement[]; + switch (currentStep) { + case 1: + case 2: + case 3: + const step = document.getElementById(`step-${currentStep + 1}`) as HTMLElement; + step.style.display = 'none'; + inputs[currentStep - 1].disabled = false; + inputs[currentStep - 1].value = ''; + if (--currentStep === 0) { + prevButton.disabled = true; + } + break; + case 4: + const step5 = document.getElementById('step-5') as HTMLElement; + step5.style.display = 'none'; + fecha_reponer.prop('disabled', false); + fecha_reponer.val(''); + + hora_reponer.parent().removeClass('disabled'); + hora_reponer.siblings('.datalist-input').text('hh'); + hora_reponer.val(''); + + minutos_reponer.parent().removeClass('disabled'); + minutos_reponer.siblings('.datalist-input').text('mm'); + minutos_reponer.val(''); + + currentStep--; + break; + } + + nextButton.disabled = true; + +}); + +// #horario_reponer on change => show step 3 +horario_reponer.addEventListener('change', async () => { + const selected = horario_reponer.querySelector(`option[value="${horario_reponer.value}"]`) as HTMLOptionElement; + horario_reponer.title = `Materia: ${selected.dataset.materia} - Grupo: ${selected.dataset.grupo} - Horario: ${selected.dataset.hora}-${selected.dataset.hora_final} - Salon: ${selected.dataset.salon} - Día: ${selected.dataset.dia}`; + const step3 = document.getElementById('step-3') as HTMLElement; + horario_reponer.disabled = true; + // make a form data with #form + const response = await fetch(`./action/action_fechas_clase.php?horario_id=${horario_reponer.value}`, { + method: 'GET', + }); + + const data = await response.json(); + if (data['success'] === false) { + const message = "Hubo un error al obtener las fechas de clase." + const title = 'Error'; + const color = 'danger'; + triggerMessage(message, title, color); + return; + } + type Fecha = { + fecha: string; + dia_mes: number; + day: number; + month: number; + year: number; + } + + const meses = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; + + const fechas = data.data as Fecha[]; + const initial = document.createElement('option'); + initial.value = ''; + initial.textContent = 'Seleccione la fecha de la falta'; + initial.selected = true; + initial.disabled = true; + fechas_clase.innerHTML = ''; + fechas_clase.appendChild(initial); + fechas_clase.title = 'Seleccione la fecha de la falta'; + + fechas.forEach((fecha) => { + const option = document.createElement('option'); + option.value = `${fecha}`; + option.textContent = `${fecha.dia_mes} de ${meses[fecha.month - 1]} de ${fecha.year}`; + fechas_clase.appendChild(option); + }); + + + step3.style.display = 'block'; + currentStep = 2; +}); + +// #fechas_clase on change => show step 4 +fechas_clase.addEventListener('change', () => { + const step4 = document.getElementById('step-4') as HTMLElement; + step4.style.display = 'block'; + fechas_clase.disabled = true; + currentStep = 3; +}); + +// when both #fecha_reponer and #hora_reponer are selected => show step 5 + +const lastStep = () => { + // timeout to wait for the value to be set + setTimeout(() => { + if (fecha_reponer.val() !== '' && hora_reponer.val() !== '' && minutos_reponer.val() !== '') { + const step5 = document.getElementById('step-5') as HTMLElement; + step5.style.display = 'block'; + // disable both + fecha_reponer.prop('disabled', true); + hora_reponer.parent().addClass('disabled'); + minutos_reponer.parent().addClass('disabled'); + + const nextButton = document.getElementById('next-button') as HTMLButtonElement; + // remove property disabled + nextButton.removeAttribute('disabled'); + currentStep = 4; + } + }, 100); +} +fecha_reponer.on('change', lastStep); +// on click on the sibling ul>li of #hora_reponer and #minutos_reponer + +hora_reponer.siblings('ul').children('li').on('click', lastStep); +minutos_reponer.siblings('ul').children('li').on('click', lastStep); + +// Initialize the form +hideSteps(); +showCurrentStep(); + + +function hideSteps() { + steps.forEach((step) => { + step.style.display = 'none'; + }); +} + +function showCurrentStep() { + steps[currentStep].style.display = 'block'; + prevButton.disabled = currentStep === 0; +} + +function handleSubmit(event: Event) { + event.preventDefault(); + + // Handle form submission + // You can access the form data using the FormData API or serialize it manually } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 961a3b3..886cab1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,14 @@ -{ - "compilerOptions": { - "lib": [ - "ESNext", - "dom" - ], - "outDir": "js", - "rootDir": "ts", - "target": "ES2022", - "moduleResolution": "node", - "module": "ESNext" - // ts/auditoría.ts:1:37 - error TS2307: Cannot find module 'https://unpkg.com/petite-vue?module' or its corresponding type declarations. - } +{ + "compilerOptions": { + "lib": [ + "ESNext", + "dom" + ], + "outDir": "js", + "rootDir": "ts", + "target": "ES2022", + "moduleResolution": "node", + "module": "ESNext" + // ts/auditoría.ts:1:37 - error TS2307: Cannot find module 'https://unpkg.com/petite-vue?module' or its corresponding type declarations. + } } \ No newline at end of file diff --git a/usuarios.php b/usuarios.php index c913c14..fd31968 100644 --- a/usuarios.php +++ b/usuarios.php @@ -1,437 +1,464 @@ -access(); -if(!$user->admin && $user->acceso == 'n'){ - header('Location: main.php?error=1'); -}else{ - $user->print_to_log('Usuarios'); -} -$fac = $user->facultad['facultad_id'] ?? -1; -if($user->admin){ - $fac=null; -} -#echo $fac; -?> - - - - - - - Usuarios - - - - - access(); - - if(isset($_POST["desc"])){ - $desc=$_POST["desc"]; - $filter_desc = trim(filter_input(INPUT_POST, "desc", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $desc=NULL; - } - - if(isset($_POST["clave"])){ - $clave=$_POST["clave"]; - $filter_clave = trim(filter_input(INPUT_POST, "clave", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $clave=NULL; - } - - if(isset($_POST["rol"])){ - if($_POST['rol']!="") - { - $rol=$_POST["rol"]; - $filter_rol = trim(filter_input(INPUT_POST, "rol", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - }else{ - $rol=NULL; - } - }else{ - $rol=NULL; - } - - if(isset($_POST["mnombre"])){ - $desc=$_POST["mnombre"]; - $filter_desc = trim(filter_input(INPUT_POST, "mnombre", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - } - if(isset($_POST["mclave"])){ - $clave=$_POST["mclave"]; - $filter_clave = trim(filter_input(INPUT_POST, "mclave", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW))); - } - - $fs_usuarios = query( - "SELECT * FROM fs_usuarios(:facultad, :nombre, :clave, :rol)", - array( - ":facultad" => $fac, - ":nombre" => $desc, - ":clave" => $clave, - ":rol" => $rol - ), - false - ); - $fs_roles = query( - "SELECT * FROM rol ORDER BY rol_titulo", - null, - false - ); - if($user->admin){ - $fs_facultades = query( - "SELECT * FROM facultad WHERE facultad_activa = true ORDER BY facultad_nombre", - null, - false - ); - } - ?> -
      - acceso == 'w') {?> -
      -
      - -
      -
      - - -
      -
      -
      -
      -
      - -
      - > -
      - Debe ser un numero -
      -
      -
      -
      - -
      - > -
      - Debe ser un numero -
      -
      -
      -
      - -
      -
      -
      Mostrar todas
      - -
        -
      • Mostrar todas
      • - -
      • ">
      • - -
      - -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      -
      -
      - -
      -
      - - - - - - - - admin){ ?> - - - acceso == 'w'){?> - - - - - - - - - - - - - admin){ ?> - - - acceso == 'w'){?> - - - - - -
      NombreCorreoClaveRolFacultadAcciones
      - -
      -
      -
      -
      - - - - - - - - - - +access(); +if (!$user->admin && $user->acceso == 'n') { + header('Location: main.php?error=1'); +} else { + $user->print_to_log('Usuarios'); +} +$fac = $user->facultad['facultad_id'] ?? -1; +if ($user->admin) { + $fac = null; +} +#echo $fac; +?> + + + + + + + Usuarios + + + + + access(); + + if (isset($_POST["desc"])) { + $desc = $_POST["desc"]; + $filter_desc = trim(filter_input(INPUT_POST, "desc", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + } else { + $desc = NULL; + } + + if (isset($_POST["clave"])) { + $clave = $_POST["clave"]; + $filter_clave = trim(filter_input(INPUT_POST, "clave", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + } else { + $clave = NULL; + } + + if (isset($_POST["rol"])) { + if ($_POST['rol'] != "") { + $rol = $_POST["rol"]; + $filter_rol = trim(filter_input(INPUT_POST, "rol", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + } else { + $rol = NULL; + } + } else { + $rol = NULL; + } + + if (isset($_POST["mnombre"])) { + $desc = $_POST["mnombre"]; + $filter_desc = trim(filter_input(INPUT_POST, "mnombre", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + } + if (isset($_POST["mclave"])) { + $clave = $_POST["mclave"]; + $filter_clave = trim(filter_input(INPUT_POST, "mclave", FILTER_SANITIZE_STRING, array('flags' => FILTER_FLAG_STRIP_LOW))); + } + + $fs_usuarios = query( + "SELECT * FROM fs_usuarios(:facultad, :nombre, :clave, :rol)", + array( + ":facultad" => $fac, + ":nombre" => $desc, + ":clave" => $clave, + ":rol" => $rol + ), + false + ); + $fs_roles = query( + "SELECT * FROM rol ORDER BY rol_titulo", + null, + false + ); + if ($user->admin) { + $fs_facultades = $db + ->orderBy('facultad_nombre', 'asc') + ->get('facultad'); + } + ?> +
      + acceso == 'w') { ?> +
      +
      + +
      + +
      + + +
      +
      +
      +
      +
      + +
      + > +
      + Debe ser un numero +
      +
      +
      +
      + +
      + + > +
      + Debe ser un numero +
      +
      +
      +
      + Rol +
      +
      +
      Mostrar todas
      + +
        + + +
      • Mostrar todas
      • + +
      • "> +
      • + +
      + +
      +
      +
      + +
      +
      + + +
      +
      + +
      +
      +
      + +
      +
      + + + + + + + + admin) { ?> + + + acceso == 'w') { ?> + + + + + + + + + + + + + + + + + admin) { ?> + + + acceso == 'w') { ?> + + + + + +
      NombreCorreoClaveRolFacultadAcciones
      + + + + + + + + + + + +
      +
      +
      +
      + + + +