Compare commits

...

14 Commits

Author SHA1 Message Date
christian.julian 73e5d3d574 fix: Correción de documentación 2025-06-20 13:39:18 -06:00
christian.julian b8aaa87509 Merge backend into main, conservando archivos de backend 2025-06-20 11:29:29 -06:00
Hectorgh24 b8adbfff3e fix: Se borro todos los archivos, para poder hacer el merge 2025-05-27 14:10:01 -06:00
Hectorgh24 788fa4d4cc Fix: Resolución de conflictos del merge entre temporal-fix y main 2025-05-27 14:05:09 -06:00
Hectorgh24 d528fab969 Archivos de filtro de graficos 2025-05-27 13:45:31 -06:00
Hectorgh24 e77ed0dfd4 solucion de conlictos 3 2025-05-27 13:35:19 -06:00
Hectorgh24 eabf6de16a Revert "fix: Agregar Icon a Siderbar para API"
This reverts commit d85d85dc05.
2025-05-27 10:22:53 -06:00
Hectorgh24 ecded5fe66 solucion de conlictos 2 2025-05-27 10:20:54 -06:00
Hectorgh24 bd62a804f1 solucion de conlictos 2025-05-27 10:03:42 -06:00
Hectorgh24 a8e2895311 archivos de merge desde la rama recuperar-cambios 2025-05-26 19:15:25 -06:00
Hectorgh24 ce6302d6df Funcionalidad de graficos de acuerdo a varios filtros 2025-05-25 23:13:16 -06:00
Hectorgh24 a803956dd6 Funcionalidad de graficos de acuerdo a varios filtros 2025-05-25 23:12:50 -06:00
Hectorgh24 25b076895a Error en la rama backend con el commit db585a7 2025-05-24 21:47:10 -06:00
Hectorgh24 3247d9dfd7 error 2025-05-02 19:26:20 -06:00
41 changed files with 46 additions and 4367 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
.idea/

View File

@ -0,0 +1,46 @@
# Sistema de Registro y Gestión de Candidatos - LANIA
Este proyecto es una plataforma web desarrollada para automatizar el registro de usuarios en el **Centro de Certificación LANIA**, con el objetivo de optimizar la recolección de datos demográficos y de satisfacción de los candidatos, así como proporcionar herramientas de análisis al área de administración.
## ✨ Descripción General
La aplicación se compone de dos partes principales:
- **Web App**: Interfaz gráfica donde candidatos pueden llenar formularios y administradores pueden gestionar usuarios, candidatos y consultar datos analíticos.
- **API REST**: Servicio backend que expone endpoints para la gestión de candidatos, autenticación vía OAuth2 y exportación de datos en múltiples formatos (JSON, CSV, Excel).
## 🎯 Propósito
- Automatizar el proceso de registro y seguimiento de candidatos.
- Recolectar datos clave para la toma de decisiones institucionales.
- Facilitar la gestión de usuarios y candidatos por parte del personal de LANIA.
- Brindar herramientas visuales de análisis mediante un dashboard dinámico.
## 👥 Tipos de Usuario
- **Candidato**: Registra sus datos mediante formularios web.
- **Administrador LANIA**: Visualiza, filtra y exporta datos, administra usuarios y accede al dashboard analítico.
## 🛠 Tecnologías Utilizadas
| Tecnología | Propósito |
|-------------------|------------------------------------------------|
| PHP (MVC) | Lógica del servidor y API REST |
| JavaScript | Interacción dinámica en el cliente |
| MySQL | Almacenamiento de datos |
| Chart.js | Visualización de datos en gráficos |
| OAuth2 | Autenticación y autorización segura |
| HTML/CSS | Maquetación y estilos de la interfaz |
| INEGI BD externa | Validación geográfica de estado/municipio |
## 📂 Funcionalidades Principales
- Dashboard con métricas visuales.
- Formularios dinámicos de registro.
- Control y gestión de candidatos.
- Gestión de usuarios administradores.
- Interfaz para consulta y exportación de datos vía API.
## Documentación de API
En el siguiente enlace se encuentra el archivo .yaml de la documentación de la API que puede ser visualizado con Swagger Editor:
https://uvmx-my.sharepoint.com/:u:/g/personal/zs22016079_estudiantes_uv_mx/EU0hmEyOj29LgbF9R8CStdcBVLkB11Ik2SfwYQg9fWKXtw?e=Kz3nci

View File

@ -1,68 +0,0 @@
<?php
require_once __DIR__ . "/../../config/Database.php";
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['n'])){
$numero_inserts = intval($_GET['n']);
if ($numero_inserts <= 0) {
echo "El número de inserts debe ser un entero positivo.";
exit;
}
// Configuración de rangos para campos aleatorios
$id_examen_min = 1;
$id_examen_max = 15;
$id_tipo_id_min = 1;
$id_tipo_id_max = 5;
$id_rango_edad_min = 1;
$id_rango_edad_max = 7;
$id_genero_min = 1;
$id_genero_max = 3;
$conn = Database::getInstance();
$conn->begin_transaction();
try {
for ($i = 1; $i <= $numero_inserts; $i++) {
$nombres = "Nombre" . $i;
$primer_apellido = "ApellidoP" . $i;
$segundo_apellido = "ApellidoM" . $i;
$correo = "correo" . $i . "@gmail.com";
$fecha_entrada = date('Y-m-d H:i:s');
// fecha_salida es NULL por defecto en la tabla, o se puede especificar como NULL
$telefono = '';
for ($j = 0; $j < 10; $j++) {
$telefono .= rand(0, 9);
}
$id_examen = rand($id_examen_min, $id_examen_max);
$id_tipo_id = rand($id_tipo_id_min, $id_tipo_id_max);
$id_rango_edad = rand($id_rango_edad_min, $id_rango_edad_max);
$id_genero = rand($id_genero_min, $id_genero_max);
$sql = "INSERT INTO candidato (fecha_entrada, nombres, primer_apellido, segundo_apellido, correo, telefono, id_examen, id_tipo_id, id_rango_edad, id_genero)
VALUES ('{$fecha_entrada}', '{$nombres}', '{$primer_apellido}', '{$segundo_apellido}', '{$correo}', '{$telefono}', {$id_examen}, {$id_tipo_id}, {$id_rango_edad}, {$id_genero})";
if (!$conn->query($sql)) {
throw new Exception("Error al insertar el registro {$i}: " . $conn->error);
}
}
$conn->commit();
echo "Se han insertado {$numero_inserts} registros exitosamente.";
} catch (Exception $e) {
$conn->rollback();
echo "Error en la transacción: " . $e->getMessage();
} finally {
$conn->close();
}
} else {
echo "Parámetros incorrectos. Asegúrate de pasar 'n' como parámetro GET con un número entero. Por ejemplo: .../ruta/inserts-prueba.php?n=5";
}
?>

View File

@ -1,102 +0,0 @@
<?php
require_once __DIR__ . '/../models/CatalogosModel.php';
class CatalogosController {
private static $catalogosModel = null;
public static function inicializar() {
if (self::$catalogosModel === null) {
self::$catalogosModel = new Catalogos();
}
}
public static function obtenerInfiCodigoPostal($codigo_postal){
return self::$catalogosModel->obtenerInfiCodigoPostal($codigo_postal);
}
public static function obtenerGiros(){
return self::$catalogosModel->obtenerGiros();
}
public static function obtenerNombresExamenes(){
return self::$catalogosModel->obtenerNombresExamenes();
}
public static function obtenerTiposIdentificacion(){
return self::$catalogosModel->obtenerTiposIdentificacion();
}
public static function obtenerRangosEdad(){
return self::$catalogosModel->obtenerRangosEdad();
}
public static function obtenerNivelesEstudio(){
return self::$catalogosModel->obtenerNivelesEstudio();
}
public static function obtenerNombresEmpresasInstituciones(){
return self::$catalogosModel->obtenerNombresEmpresasInstituciones();
}
public static function obtenerMotivosExamen(){
return self::$catalogosModel->obtenerMotivosExamen();
}
}
CatalogosController::inicializar();
// Petición GET para información del código postal
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['codigo_postal'])) {
header('Content-Type: application/json');
$codigo_postal = $_GET['codigo_postal'];
$result = CatalogosController::obtenerInfiCodigoPostal($codigo_postal);
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'giros') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerGiros();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'examenes') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerNombresExamenes();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'identificacion') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerTiposIdentificacion();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'rangosedad') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerRangosEdad();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'nivelesestudio') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerNivelesEstudio();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'empresasinstituciones') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerNombresEmpresasInstituciones();
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'motivos') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerMotivosExamen();
echo json_encode($result);
}
?>

View File

@ -1,38 +0,0 @@
<?php
require_once __DIR__ . '/../models/CandidatoModel.php';
class ControlCandidatos {
private $candidatoModel;
public function __construct() {
$this->candidatoModel = new CandidatoModel();
}
public function obtenerCandidatosSinFechaSalida(){
$resultado = $this->candidatoModel->obtenerCandidatosSinFechaSalida();
if( isset($resultado['estado'])){
return $resultado;
} else {
// iterar sobre $resultado y concatenar nombre completo, la fecha dejarla como esta
$candidatos = [];
foreach ($resultado as $candidato) {
$nombreCompleto = "{$candidato['nombres']} {$candidato['primer_apellido']} {$candidato['segundo_apellido']}";
$candidatos[] = [
'id_candidato' => $candidato['id_candidato'],
'nombre_completo' => $nombreCompleto,
'fecha_entrada' => $candidato['fecha_entrada']
];
}
return $candidatos;
}
}
public function eliminarCandidato($id_candidato){
return $this->candidatoModel->eliminarCandidato($id_candidato);
}
}
?>

View File

@ -1,32 +0,0 @@
<?php
header('Content-Type: application/json');
require_once __DIR__ . '/UsuarioController.php';
// Inicializar el modelo de usuario
UsuarioController::inicializar();
if ( $_SERVER['REQUEST_METHOD'] === 'POST') {
$usuario = isset($_POST['numero-personal']) ? $_POST['numero-personal'] : '';
$contrasena = isset($_POST['contrasena']) ? $_POST['contrasena'] : '';
// Iniciar sesión y obtener respuesta
$respuesta = UsuarioController::iniciarSesion($usuario, $contrasena);
if ($respuesta['estado'] === 'exitoso') {
// Iniciar sesión
session_start();
$_SESSION['usuario'] = $usuario;
}
echo json_encode($respuesta);
} else {
// Metodo no permitido
echo json_encode([
'estado' => 'error',
'mensaje' => 'Método no permitido'
]);
}
?>

View File

@ -1,16 +0,0 @@
<?php
require_once __DIR__ . '/CandidatoController.php';
// Manejar la solicitud POST para registrar un candidato
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$insertId = CandidatoController::registrarCandidato();
if($insertId > 0){
echo json_encode(['registroExitoso' => true, 'message' => 'Se ha registrado el candidato correctamente.']);
} else {
echo json_encode(['registroExitoso' => false, 'message' => 'Error al registrar el candidato.']);
}
}
?>

View File

@ -1,25 +0,0 @@
<?php
require_once __DIR__ . '/CandidatoController.php';
// Manejar la solicitud POST para registrar información un candidato
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$respuesta = CandidatoController::registrarInfoCandidato();
if(isset($respuesta["estado"]) && $respuesta["estado"] === "exitoso") {
echo json_encode([
"estado" => "exitoso",
"mensaje" => "Se ha registrado la información correctamente.",
"res" => "id_candidato: " . $respuesta["mensaje"]
]);
} else if( isset($respuesta["estado"]) ){
echo json_encode([
"estado" => "error",
"mensaje" => "Error al registrar la información.",
"res" => $respuesta["mensaje"]
]);
}
}
?>

View File

@ -1,56 +0,0 @@
<?php
require_once __DIR__ . '/../models/UsuarioModel.php';
class UsuarioController{
private static $usuarioModel = null;
public static function inicializar() {
if (self::$usuarioModel === null) {
self::$usuarioModel = new UsuarioModel();
}
}
public static function obtenerUsuarios(){
return self::$usuarioModel->obtenerUsuarios();
}
public static function iniciarSesion($usuario, $contrasena){
return self::$usuarioModel->iniciarSesion($usuario, $contrasena);
}
public static function existeUsuario($usuario){
$usuario = self::$usuarioModel->buscarUsuario($usuario);
if ( isset($usuario['usuario']) ) {
return true;
} else {
return false;
}
}
public static function crearUsuario($usuario, $contrasena){
if ( self::existeUsuario($usuario) ) {
return [
'estado' => 'error',
'mensaje' => 'El usuario ya existe.'
];
} else {
return self::$usuarioModel->crearUsuario($usuario, $contrasena);
}
}
public static function eliminarUsuario($id_usuario){
return self::$usuarioModel->eliminarUsuario($id_usuario);
}
public static function actualizarUsuario($id, $usuario, $contrasena){
return self::$usuarioModel->actualizarUsuario($id, $usuario, $contrasena);
}
}
# Instanciar el modelo al cargar el controlador
UsuarioController::inicializar();
?>

View File

@ -1,20 +0,0 @@
<?php
require_once __DIR__ . '/UsuarioController.php';
header('Content-type: application/json');
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = $_POST['id'];
$usuario = $_POST['usuario'];
$contrasena = $_POST['contrasena'];
$resultado = UsuarioController::actualizarUsuario($id, $usuario, $contrasena);
echo json_encode($resultado);
} else {
http_response_code(400);
echo json_encode([
'estado' => 'error',
'mensaje' => 'Método no permitido.'
]);
}
?>

View File

@ -1,53 +0,0 @@
<?php
// filepath: c:\xampp\htdocs\Proyecto_Lania\LANIA_Proyecto\php\buscarCodigo.php
include 'conexionBd.php'; // Asegúrate de que el archivo esté en la ruta correcta
header('Content-Type: application/json'); // Aseguramos que la respuesta sea JSON
// Crear instancia de la conexión
$conexion = new Conexion();
$conexionBD = $conexion->conectar(); // Establecer conexión
// Verificar que se ha enviado el parámetro 'codigo_postal'
if (isset($_GET['codigo_postal'])) {
$codigo_postal = $_GET['codigo_postal'];
// Consulta SQL para obtener estado, ciudad y colonia en base al código postal
$sql = "SELECT e.nombre AS estado, m.nombre AS municipio, c.nombre AS colonia
FROM colonias c
JOIN municipios m ON c.municipio = m.id
JOIN estados e ON m.estado = e.id
WHERE c.codigo_postal = ?";
// Verificar que la conexión a la base de datos esté activa
if ($conexionBD) {
// Preparar la sentencia SQL
$stmt = $conexionBD->prepare($sql);
$stmt->bind_param("i", $codigo_postal); // El parámetro es un entero (i)
$stmt->execute();
// Obtener los resultados
$result = $stmt->get_result();
// Verificar si hay resultados
if ($result->num_rows > 0) {
$data = [];
while ($row = $result->fetch_assoc()) {
$data[] = $row; // Agregar cada resultado a un array
}
echo json_encode($data); // Devolver los resultados en formato JSON
} else {
echo json_encode([]); // Si no hay resultados, devolver un array vacío
}
$stmt->close();
} else {
echo json_encode(["error" => "Conexión a la base de datos fallida."]);
}
$conexionBD->close();
} else {
// Si no se recibe un código postal, respondemos con un error
echo json_encode(["error" => "Código postal no proporcionado."]);
}
?>

View File

@ -1,4 +0,0 @@
<?php
session_start();
session_destroy();
header('Location: ../index.html');

View File

@ -1,19 +0,0 @@
<?php
require_once __DIR__ . '/UsuarioController.php';
header('Content-type: application/json');
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$usuario = $_POST['usuario'];
$contrasena = $_POST['contrasena'];
$resultado = UsuarioController::crearUsuario($usuario, $contrasena);
echo json_encode($resultado);
} else {
http_response_code(400);
echo json_encode([
'estado' => 'error',
'mensaje' => 'Método no permitido.'
]);
}
?>

View File

@ -1,18 +0,0 @@
<?php
header('Content-Type: application/json', 'charset=UTF-8');
require_once __DIR__ . '/ControlCandidatos.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['id_candidato'])) {
$candidatoController = new ControlCandidatos();
$id_candidato = $_POST['id_candidato'];
$resultado = $candidatoController->eliminarCandidato($id_candidato);
echo json_encode($resultado);
} else {
http_response_code(400);
echo json_encode([
'estado' => 'error',
'mensaje' => 'Método no permitido.'
]);
}
?>

View File

@ -1,18 +0,0 @@
<?php
header('Content-Type: application/json', 'charset=UTF-8');
require_once __DIR__ . '/UsuarioController.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['id_usuario'])) {
$id_usuario = $_POST['id_usuario'];
$resultado = UsuarioController::eliminarUsuario($id_usuario);
echo json_encode($resultado);
} else {
http_response_code(400);
echo json_encode([
'estado' => 'error',
'mensaje' => 'Método no permitido.'
]);
}
?>

View File

@ -1,59 +0,0 @@
<?php
require_once '../config/Database.php';
require_once '../models/GraficoModel.php';
header('Content-Type: application/json'); // Aseguramos que siempre se devuelva JSON
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
$tipoConsulta = $input['tipoConsulta'] ?? '';
switch ($tipoConsulta) {
case 'Femenino':
$cantidad = GraficoModel::obtenerGeneroFemenino();
break;
case 'Masculino':
$cantidad = GraficoModel::obtenerGeneroMasculino();
break;
case 'Prefiero no decirlo':
$cantidad = GraficoModel::obtenerGeneroNoDefinido();
break;
case 'Menor de 18 años':
$cantidad = GraficoModel::obtenerEdadMenor18();
break;
case '18 a 24 años':
$cantidad = GraficoModel::obtenerEdad1824();
break;
case '25 a 34 años':
$cantidad = GraficoModel::obtenerEdad2434();
break;
case '35 a 44 años':
$cantidad = GraficoModel::obtenerEdad3544();
break;
case '45 a 54 años':
$cantidad = GraficoModel::obtenerEdad4554();
break;
case '55 a 64 años':
$cantidad = GraficoModel::obtenerEdad5564();
break;
case '65 años o más':
$cantidad = GraficoModel::obtenerEdad65oMas();
break;
case 'Estados':
$cantidad = GraficoModel::obtenerEstados();
echo json_encode($cantidad); // Devolver directamente el array de estados
exit; // Terminar la ejecucion aqui
case 'Examenes':
$cantidad = GraficoModel::obtenerExamenes();
echo json_encode($cantidad); // Devolver directamente el array de examenes
exit; // Terminar la ejecucion aqui
default:
$cantidad = 0;
}
echo json_encode(['cantidad' => $cantidad]);
}
?>

View File

@ -1 +0,0 @@
<?php

View File

@ -1,38 +0,0 @@
.token-info {
word-break: break-all;
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
pre {
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
}
.hidden {
display: none;
}
.success-message {
background-color: #d4edda;
border-color: #c3e6cb;
color: #155724;
padding: 10px;
border-radius: 5px;
margin-bottom: 15px;
}
.download-section {
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
border: 1px solid #dee2e6;
}
.download-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.download-btn {
min-width: 120px;
}

View File

@ -1,132 +0,0 @@
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
}
body {
background-color: #f1f0f6;
display: grid;
place-items: center;
min-height: 100vh;
}
.login-container {
background-color: #ffffff;
border: 2px solid #e8e8e8;
border-radius: 8px;
padding: 2rem;
width: 100%;
max-width: 500px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
@media screen and (max-width: 768px) {
.login-container {
width: 80%;
}
}
.login-encabezado {
text-align: center;
margin-bottom: 1.5rem;
}
.login-logo {
max-width: 150px;
height: auto;
margin-bottom: 1rem;
}
.login-titulo {
font-size: 1.5rem;
color: #333;
display: flex;
align-items: center;
justify-content: center;
}
.login-subtitulo {
color: #666;
margin-top: 0.5rem;
}
.login-formulario {
color: #666;
margin-top: 0.5rem;
}
.form-grupo {
margin-bottom: 1rem;
}
.form-label {
display: flex;
align-items: center;
margin-bottom: 0.5rem;
font-weight: bold;
}
.form-input {
width: 100%;
padding: 0.75rem;
border: 1px solid #e8e8e8;
border-radius: 4px;
background-color: #f6f6f6;
transition: all 0.3s ease;
}
.form-input:focus {
outline: none;
border-color: #35245b;
box-shadow: 0 0 0 2px rgba(2, 27, 48, 0.2);
}
.login-boton {
background-color: #35245b;
color: white;
border: none;
border-radius: 4px;
padding: 0.75rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 1rem;
width: 100%;
}
.login-boton:hover {
background-color: #432d74;
box-shadow: 0 4px 8px #53388f;
}
.login-boton:active {
transform: scale(0.98);
}
.material-icons {
font-size: 1.25rem;
}
.mensaje-error {
display: none;
background-color: #f8d7da;
color: #dc3545;
border: 1px solid #dc3545;
border-radius: 4px;
padding: 0.75rem;
margin-top: 1rem;
text-align: center;
animation: fadeIn 0.3s ease-in-out;
}

2106
font/bootstrap-icons.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -1,260 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>
<link rel="stylesheet" href="css/form.css">
<title>AdminSite</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<!-- <a href="#" class="brand">
<img src="img/lania_logo.png" alt="Logo" style="height: 40px;">
</a> -->
<ul class="side-menu">
<li><a href="#" class="active"><i class='bx bxs-dashboard icon' ></i> Dashboard</a></li>
<li class="divider" data-text="main">Main</li>
<li>
<a href="#"><i class='bx bxs-inbox icon' ></i> Elements <i class='bx bx-chevron-right icon-right' ></i></a>
<ul class="side-dropdown">
<li><a href="#">Alert</a></li>
<li><a href="#">Badges</a></li>
<li><a href="#">Breadcrumbs</a></li>
<li><a href="#">Button</a></li>
</ul>
</li>
<li><a href="#"><i class='bx bxs-chart icon' ></i> Charts</a></li>
<li><a href="#"><i class='bx bxs-widget icon' ></i> Widgets</a></li>
<li class="divider" data-text="table and forms">Table and forms</li>
<li><a href="#"><i class='bx bx-table icon' ></i> Tables</a></li>
<li>
<a href="#"><i class='bx bxs-notepad icon' ></i> Formularios <i class='bx bx-chevron-right icon-right' ></i></a>
<ul class="side-dropdown">
<li><a href="form_datos_basicos.html">Datos Básicos</a></li>
<li><a href="form_datos_extendidos.html">Datos Extendidos</a></li>
</ul>
</li>
</ul>
<!-- <div class="ads">
<div class="wrapper">
<a href="#" class="btn-upgrade">Upgrade</a>
<p>Become a <span>PRO</span> member and enjoy <span>All Features</span></p>
</div>
</div> -->
</section>
<!-- SIDEBAR -->
<!-- NAVBAR -->
<section id="content">
<!-- NAVBAR -->
<nav>
<i class='bx bx-menu toggle-sidebar' ></i>
<form action="#">
<div class="form-group">
<input type="text" placeholder="Buscar...">
<i class='bx bx-search icon' ></i>
</div>
</form>
<a href="#" class="nav-link">
<i class='bx bxs-bell icon' ></i>
<span class="badge">5</span>
</a>
<a href="#" class="nav-link">
<i class='bx bxs-message-square-dots icon' ></i>
<span class="badge">8</span>
</a>
<span class="divider"></span>
<div class="profile">
<img src="https://images.unsplash.com/photo-1517841905240-472988babdf9?ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8cGVvcGxlfGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" alt="">
<ul class="profile-link">
<li><a href="#"><i class='bx bxs-user-circle icon' ></i> Profile</a></li>
<li><a href="#"><i class='bx bxs-cog' ></i> Settings</a></li>
<li><a href="#"><i class='bx bxs-log-out-circle' ></i> Logout</a></li>
</ul>
</div>
</nav>
<!-- NAVBAR -->
<!-- MAIN -->
<main>
<h1 class="title">Datos Extendidos</h1>
<ul class="breadcrumbs">
<li><a href="#">Formularios</a></li>
<li class="divider">/</li>
<li><a href="#" class="active">Datos Extendidos</a></li>
</ul>
<div class="form-container">
<form id="formulario-datos-extendido" method="post" action="#">
<div class="form-section">
<br>
<h3>Ubicación</h3>
<br>
<div class="form-row">
<input type="hidden" id="id_candidato" name="id_candidato">
<div class="form-col">
<div class="form-group">
<label for="id_pais" class="required">País</label>
<select id="id_pais" name="id_pais" required>
<option value="">Seleccione...</option>
<!-- Aquí irían los países desde la base de datos -->
<option value="1">México</option>
<option value="2">Otro</option>
</select>
</div>
</div>
<div class="form-col">
<div class="form-group">
<label for="codigo_postal" class="required">Código Postal</label>
<input type="number" min="0" step="1" id="codigo_postal" name="codigo_postal" maxlength="10" required>
<button type="button" id="buscarBtn"><span class="material-icons">search</span>Buscar</button>
</div>
</div>
<div class="form-col">
<div class="form-group">
<label for="id_estado">Estado</label>
<select id="id_estado" name="id_estado">
<option value="">Seleccione...</option>
<!-- Aquí irían los estados desde la base de datos -->
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="form-col">
<div class="form-group">
<label for="id_municipio">Municipio</label>
<select id="id_municipio" name="id_municipio">
<option value="">Seleccione...</option>
<!-- Aquí irían los municipios desde la base de datos -->
</select>
</div>
</div>
<div class="form-col">
<div class="form-group">
<label for="id_colonia">Colonia</label>
<select id="id_colonia" name="id_colonia">
<option value="">Seleccione...</option>
<!-- Aquí irían las colonias desde la base de datos -->
</select>
</div>
</div>
</div>
</div>
<!-- Sección 3: Información Académica y Laboral -->
<div class="form-section">
<br>
<h3>Información Académica/Laboral</h3>
<br>
<div class="form-row">
<div class="form-col">
<div class="form-group">
<label for="id_nivel" class="required">Nivel de Estudios</label>
<select id="id_nivel" name="id_nivel" required>
<option value="">Seleccione...</option>
<option value="1">Primaria</option>
<option value="2">Secundaria</option>
<option value="3">Bachillerato</option>
<option value="4">Técnico Superior Universitario</option>
<option value="5">Licenciatura</option>
<option value="6">Maestría</option>
<option value="7">Doctorado</option>
<option value="8">Otro</option>
</select>
</div>
</div>
<div class="form-col">
<div class="form-group">
<label for="id_giro" class="required">Giro</label>
<select id="id_giro" name="id_giro" required>
<option value="">Seleccione...</option>
<option value="1">Tecnologías de la Información</option>
<option value="2">Gobierno</option>
<option value="3">Finanzas</option>
<option value="4">Salud</option>
<option value="5">Educación</option>
<option value="6">Telecomunicaciones</option>
<option value="7">Retail</option>
<option value="8">Manufactura</option>
<option value="9">Logística y Transporte</option>
<option value="10">Construcción</option>
<option value="11">Turismo y Hospitalidad</option>
<option value="12">Energía y Recursos Naturales</option>
<option value="13">Agricultura y Alimentación</option>
<option value="14">Medios de Comunicación y Entretenimiento</option>
<option value="15">Otros</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label for="nombre_empresa">Nombre de la Empresa/Institución</label>
<input type="text" id="nombre_empresa" name="nombre_empresa"
maxlength="100">
</div>
<div class="form-group">
<label for="motivo_examen">Motivo del Examen</label>
<textarea id="motivo_examen" name="motivo_examen" rows="3"></textarea>
</div>
</div>
<!-- Sección 4: Evaluación y Consentimiento -->
<div class="form-section">
<br>
<h3>Evaluación y Consentimiento</h3>
<br>
<div class="form-group">
<p>Calificación del Servicio</p>
<br>
<label for="calificacion_servicio">¿Qué tan satisfecho estás con nuestra institución en general, considerando la calidad de las instalaciones, la atención del personal y el proceso de certificación?</label>
<br>
<select id="calificacion_servicio" name="calificacion_servicio" class="select-emoji">
<option value="">Seleccione una calificación...</option>
<option value="1">😡 Muy insatisfecho</option>
<option value="2">😕 Insatisfecho</option>
<option value="3">😐 Neutral</option>
<option value="4">🙂 Satisfecho</option>
<option value="5">😄 Muy satisfecho</option>
</select>
</div>
<br>
<div class="form-group">
<input type="checkbox" id="consentimiento_pub" name="consentimiento_pub" value="1" checked>
<label for="consentimiento_pub" style="display: inline;">Doy mi consentimiento para la publicación de mis datos</label>
</div>
</div>
<br>
<button type="submit" class="btn-submit">Enviar</button>
<div id="mensaje-error" class="mensaje-error"></div>
</form>
</div>
</main>
<!-- MAIN -->
</section>
<!-- NAVBAR -->
<script src="js/form.js"></script>
<script src="js/form_datos_extendidos.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
<script src="js/buscarCodigo.js"></script>
</body>
</html>

View File

@ -1,69 +0,0 @@
document.addEventListener('DOMContentLoaded', function(){
form = document.getElementById('form');
const contrasena = document.getElementById('contrasena');
const contrasenaVerificacion = document.getElementById('contrasena_verificacion');
const btnSubmit = document.getElementById('submit');
const togglePassword = document.getElementById('togglePassword');
togglePassword.addEventListener('click', function(e) {
const type = contrasena.getAttribute('type') === 'password' ? 'text' : 'password';
contrasena.setAttribute('type', type);
const icon = togglePassword.querySelector('i');
if (type === 'text') {
icon.classList.remove('bi-eye');
icon.classList.add('bi-eye-slash');
} else {
icon.classList.remove('bi-eye-slash');
icon.classList.add('bi-eye');
}
}
);
btnSubmit.addEventListener('click', function(event){
if (!form.checkValidity()) {
form.reportValidity();
return;
}
event.preventDefault();
const c1 = contrasena.value;
const c2 = contrasenaVerificacion.value;
if (c1 === c2) {
const usuario = document.getElementById('usuario').value;
const regex = /^[a-zA-Z0-9]+$/;
if (!regex.test(usuario)) {
alert("Nombre de usuario no valido.");
return;
}
const id = document.getElementById('id').value;
const data = new FormData();
data.append("id", id);
data.append("usuario", usuario);
data.append("contrasena", c1);
fetch('../controllers/actualizarUsuario.php', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(data => {
if (data.estado === "exitoso") {
alert(data.mensaje);
} else if (data.estado === "error") {
alert("Error, intentelo más tarde.");
console.log(data.mensaje);
} else {
alert("Error inesperado, intentelo más tarde.");
console.log(data);
}
window.location.href = "control-usuarios.php";
})
} else {
alert("Las contraseñas no coinciden");
}
})
})

View File

@ -1,77 +0,0 @@
document.addEventListener("DOMContentLoaded", function() {
var buscarBtn = document.getElementById("buscarBtn");
//Añadir un evento al boton de buscar
buscarBtn.addEventListener("click", function() {
var codigoPostal = document.getElementById("codigo_postal").value;
console.log(codigoPostal);
//verificar si el codigo postal esta vacio
if (codigoPostal) {
//crear la url para la peticion
var url = "./php/buscarCodigo.php?codigo_postal=" + encodeURIComponent(codigoPostal);
//Realiza una solicitud HTTP GET a la URL especificada
fetch(url)
.then(response => {
//console.log("Estado de la respuesta:", response.status);
//console.log("Contenido de la respuesta:", response);
// Verifica si la respuesta del servidor es exitosa
if (!response.ok) {
throw new Error("Error en la respuesta del servidor");
}
//Convierte la respuesta a formato JSON
return response.json();
})
.then(data => {
var estadoSelect = document.getElementById("id_estado");
var municipioSelect = document.getElementById("id_municipio");
var coloniaSelect = document.getElementById("id_colonia");
// Inicializa los elementos select con una opción por defecto
estadoSelect.innerHTML = "<option value=''>Seleccionar Estado</option>";
municipioSelect.innerHTML = "<option value=''>Seleccionar Municipios</option>";
coloniaSelect.innerHTML = "<option value=''>Seleccionar Colonia</option>";
// Verifica si se recibieron datos
if (data.length > 0) {
//Crea conjuntos para almacenar estados, ciudades y colonias únicos
let estados = new Set();
let municipios = new Set();
let colonias = [];
// Itera sobre cada fila de datos recibidos
data.forEach(row => {
estados.add(row.estado);
municipios.add(row.municipio);
colonias.push(row.colonia);
});
//Añade las opciones de estados al elemento select
estados.forEach(estado => {
estadoSelect.innerHTML += "<option value='" + estado + "'>" + estado + "</option>";
});
//Añade las opciones de ciudades al elemento select
municipios.forEach(municipio => {
municipioSelect.innerHTML += "<option value='" + municipio + "'>" + municipio + "</option>";
});
//Añade las opciones de colonias al elemento select
colonias.forEach(colonia => {
coloniaSelect.innerHTML += "<option value='" + colonia + "'>" + colonia + "</option>";
});
} else {
alert("No se encontraron datos para el código postal ingresado.");
}
})
.catch(error => {
console.error("Error en la solicitud:", error);
});
} else {
alert("Por favor, ingrese un código postal.");
}
});
});

View File

@ -1,34 +0,0 @@
document.addEventListener("DOMContentLoaded" , function() {
const tabla = document.querySelector('table');
tabla.addEventListener("click", function(evento) {
const botonEliminar = evento.target.closest(".boton-eliminar");
if (botonEliminar) {
const idUsuarioEliminar = botonEliminar.dataset.idUsuario;
const nombreUsuarioEliminar = botonEliminar.dataset.nombreUsuario;
// Mostrar un mensaje de confirmación antes de eliminar
if (!confirm("¿Desea eliminar al usuario " + nombreUsuarioEliminar + "?")) {
return;
}
const data = new FormData();
data.append("id_usuario", idUsuarioEliminar);
fetch('../controllers/eliminarUsuario.php', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(data => {
alert(data.mensaje);
location.reload();
})
.catch((error) => {
console.error('Error:', error);
});
}
});
});

View File

@ -1,69 +0,0 @@
document.addEventListener('DOMContentLoaded', function(){
const form = document.getElementById('form');
const contrasena = document.getElementById('contrasena');
const contrasenaVerificacion = document.getElementById('contrasena_verificacion');
const btnSubmit = document.getElementById('submit');
const togglePassword = document.getElementById('togglePassword');
const password = document.getElementById('contrasena');
togglePassword.addEventListener('click', function(e) {
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
password.setAttribute('type', type);
const icon = togglePassword.querySelector('i');
if (type === 'text') {
icon.classList.remove('bi-eye');
icon.classList.add('bi-eye-slash');
} else {
icon.classList.remove('bi-eye-slash');
icon.classList.add('bi-eye');
}
}
);
btnSubmit.addEventListener('click', function(event){
// Forzar vaidación nativa de HTML5
if (!form.checkValidity()) {
form.reportValidity();
return;
}
event.preventDefault();
const c1 = contrasena.value;
const c2 = contrasenaVerificacion.value;
if (c1 === c2) {
const usuario = document.getElementById('usuario').value;
const regex = /^[a-zA-Z0-9]+$/;
if (!regex.test(usuario)) {
alert("Nombre de usuario no valido.");
return;
}
const data = new FormData();
data.append("usuario", usuario);
data.append("contrasena", c1);
fetch('../controllers/crearUsuario.php', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(data => {
if (data.estado === "exitoso") {
alert(data.mensaje);
window.location.href = "control-usuarios.php";
} else if (data.estado === "error") {
alert("Error, intentelo más tarde.");
console.log(data.mensaje);
} else {
alert("Error inesperado, intentelo más tarde.");
console.log(data);
}
})
} else {
alert("Las contraseñas no coinciden");
}
})
})

View File

@ -1,148 +0,0 @@
// SIDEBAR DROPDOWN
const allDropdown = document.querySelectorAll('#sidebar .side-dropdown');
const sidebar = document.getElementById('sidebar');
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.addEventListener('click', function (e) {
e.preventDefault();
if(!this.classList.contains('active')) {
allDropdown.forEach(i=> {
const aLink = i.parentElement.querySelector('a:first-child');
aLink.classList.remove('active');
i.classList.remove('show');
})
}
this.classList.toggle('active');
item.classList.toggle('show');
})
})
// SIDEBAR COLLAPSE
const toggleSidebar = document.querySelector('nav .toggle-sidebar');
const allSideDivider = document.querySelectorAll('#sidebar .divider');
if(sidebar.classList.contains('hide')) {
allSideDivider.forEach(item=> {
item.textContent = '-'
})
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
} else {
allSideDivider.forEach(item=> {
item.textContent = item.dataset.text;
})
}
toggleSidebar.addEventListener('click', function () {
sidebar.classList.toggle('hide');
if(sidebar.classList.contains('hide')) {
allSideDivider.forEach(item=> {
item.textContent = '-'
})
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
} else {
allSideDivider.forEach(item=> {
item.textContent = item.dataset.text;
})
}
})
sidebar.addEventListener('mouseleave', function () {
if(this.classList.contains('hide')) {
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
allSideDivider.forEach(item=> {
item.textContent = '-'
})
}
})
sidebar.addEventListener('mouseenter', function () {
if(this.classList.contains('hide')) {
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
allSideDivider.forEach(item=> {
item.textContent = item.dataset.text;
})
}
})
// PROFILE DROPDOWN
const profile = document.querySelector('nav .profile');
const imgProfile = profile.querySelector('img');
const dropdownProfile = profile.querySelector('.profile-link');
imgProfile.addEventListener('click', function () {
dropdownProfile.classList.toggle('show');
})
// MENU
const allMenu = document.querySelectorAll('main .content-data .head .menu');
allMenu.forEach(item=> {
const icon = item.querySelector('.icon');
const menuLink = item.querySelector('.menu-link');
icon.addEventListener('click', function () {
menuLink.classList.toggle('show');
})
})
window.addEventListener('click', function (e) {
if(e.target !== imgProfile) {
if(e.target !== dropdownProfile) {
if(dropdownProfile.classList.contains('show')) {
dropdownProfile.classList.remove('show');
}
}
}
allMenu.forEach(item=> {
const icon = item.querySelector('.icon');
const menuLink = item.querySelector('.menu-link');
if(e.target !== icon) {
if(e.target !== menuLink) {
if (menuLink.classList.contains('show')) {
menuLink.classList.remove('show')
}
}
}
})
})

View File

@ -1,43 +0,0 @@
const formulario = document.getElementById("login-formulario");
const notificacion = document.getElementById("mensaje-error");
formulario.addEventListener("submit", async (event) => {
event.preventDefault();
const numeroPersonal = document.getElementById("numero-personal").value;
const contrasena = document.getElementById("contrasena").value;
const data = new FormData();
data.append("numero-personal", numeroPersonal);
data.append("contrasena", contrasena);
try {
const respuestaPeticion = await fetch("controllers/LoginController.php", {
method: "POST",
body: data,
});
// const respuesta = await respuestaPeticion.json();
const respuesta = await respuestaPeticion.json();
if (respuesta.estado === 'exitoso') {
window.location.href = 'views/inicio.html';
} else if(respuesta.estado === 'error') {
notificacion.textContent = respuesta.mensaje;
if(respuesta.res){ // Si existe respuesta.res hubo un error y se imprime en consola
console.error(respuesta.res)
}
notificacion.style.display = "block";
} else {
notificacion.textContent = "Lo sentimos, el servicio no está disponible por el momento";
console.error("No se recibió la respuesta esperada del servidor");
}
} catch (error) {
notificacion.textContent = "Lo sentimos, el servicio no está disponible por el momento";
console.error(error)
}
});

View File

@ -1,160 +0,0 @@
// SIDEBAR DROPDOWN
const allDropdown = document.querySelectorAll('#sidebar .side-dropdown');
const sidebar = document.getElementById('sidebar');
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.addEventListener('click', function (e) {
e.preventDefault();
if(!this.classList.contains('active')) {
allDropdown.forEach(i=> {
const aLink = i.parentElement.querySelector('a:first-child');
aLink.classList.remove('active');
i.classList.remove('show');
})
}
this.classList.toggle('active');
item.classList.toggle('show');
})
})
// SIDEBAR COLLAPSE
// const toggleSidebar = document.querySelector('nav .toggle-sidebar');
const allSideDivider = document.querySelectorAll('#sidebar .divider');
if(sidebar.classList.contains('hide')) {
allSideDivider.forEach(item=> {
item.textContent = '-'
})
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
} else {
allSideDivider.forEach(item=> {
item.textContent = item.dataset.text;
})
}
// toggleSidebar.addEventListener('click', function () {
// sidebar.classList.toggle('hide');
//
// if(sidebar.classList.contains('hide')) {
// allSideDivider.forEach(item=> {
// item.textContent = '-'
// })
//
// allDropdown.forEach(item=> {
// const a = item.parentElement.querySelector('a:first-child');
// a.classList.remove('active');
// item.classList.remove('show');
// })
// } else {
// allSideDivider.forEach(item=> {
// item.textContent = item.dataset.text;
// })
// }
// })
sidebar.addEventListener('mouseleave', function () {
if(this.classList.contains('hide')) {
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
allSideDivider.forEach(item=> {
item.textContent = '-'
})
}
})
sidebar.addEventListener('mouseenter', function () {
if(this.classList.contains('hide')) {
allDropdown.forEach(item=> {
const a = item.parentElement.querySelector('a:first-child');
a.classList.remove('active');
item.classList.remove('show');
})
allSideDivider.forEach(item=> {
item.textContent = item.dataset.text;
})
}
})
// PROFILE DROPDOWN
// const profile = document.querySelector('nav .profile');
// const imgProfile = profile.querySelector('img');
// const dropdownProfile = profile.querySelector('.profile-link');
//
// imgProfile.addEventListener('click', function () {
// dropdownProfile.classList.toggle('show');
// })
// MENU
const allMenu = document.querySelectorAll('main .content-data .head .menu');
allMenu.forEach(item=> {
const icon = item.querySelector('.icon');
const menuLink = item.querySelector('.menu-link');
icon.addEventListener('click', function () {
menuLink.classList.toggle('show');
})
})
// window.addEventListener('click', function (e) {
// if(e.target !== imgProfile) {
// if(e.target !== dropdownProfile) {
// if(dropdownProfile.classList.contains('show')) {
// dropdownProfile.classList.remove('show');
// }
// }
// }
//
// allMenu.forEach(item=> {
// const icon = item.querySelector('.icon');
// const menuLink = item.querySelector('.menu-link');
//
// if(e.target !== icon) {
// if(e.target !== menuLink) {
// if (menuLink.classList.contains('show')) {
// menuLink.classList.remove('show')
// }
// }
// }
// })
// })
// // PROGRESSBAR
// const allProgress = document.querySelectorAll('main .card .progress');
//
// allProgress.forEach(item=> {
// item.style.setProperty('--value', item.dataset.value)
// })

View File

@ -1,155 +0,0 @@
<?php
require_once __DIR__ . '/../config/Database.php';
class Catalogos{
private $conn;
public function __construct() {
$this->conn = Database::getInstance();
}
/**
* Obtiene el estado, municipio y colonia en base al código postal proporcionado.
* @param int $codigo_postal El código postal a buscar.
* @return array Un array con los datos de estado, municipio y colonia.
*/
public function obtenerInfiCodigoPostal($codigo_postal){
// Consulta SQL para obtener estado, ciudad y colonia en base al código postal
$sql = "SELECT e.id AS id_estado, e.nombre AS estado, m.id AS id_municipio, m.nombre AS municipio, c.id AS id_colonia, c.nombre AS colonia
FROM colonias c
JOIN municipios m ON c.municipio = m.id
JOIN estados e ON m.estado = e.id
WHERE c.codigo_postal = ?";
// Preparar la sentencia SQL
$stmt = $this->conn->prepare($sql);
$stmt->bind_param("i", $codigo_postal);
$stmt->execute();
// Obtener los resultados
$result = $stmt->get_result();
$stmt->close();
$data = [];
// Verificar si hay resultados
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$data[] = $row; // Agregar cada resultado a un array
}
return $data;
} else {
return $data;
}
}
/**
* Obtiene los giros.
* @return array
*/
public function obtenerGiros(){
$sql = "SELECT id_giro, descripcion FROM giro ORDER BY descripcion";
$result = $this->conn->query($sql);
$giros = [];
while($row = $result->fetch_assoc()){
$giros[] = $row;
}
return $giros;
}
/**
* Obtiene los nombres de los examenes disponibles.
* @return array Lista del nombre de la institución a la que pertenece el examen.
*/
public function obtenerNombresExamenes(){
$sql = "SELECT id_examen, nombre_examen FROM examen ORDER BY nombre_examen";
$result = $this->conn->query($sql);
$examenes = [];
while($row = $result->fetch_assoc()){
$examenes[] = $row;
}
return $examenes;
}
/**
* Obtener los tipos de identificación.
* @return array
*/
public function obtenerTiposIdentificacion(){
$sql = "SELECT id_tipo_id, descripcion FROM tipo_identificacion ORDER BY descripcion";
$result = $this->conn->query($sql);
$tipos = [];
while($row = $result->fetch_assoc()){
$tipos[] = $row;
}
return $tipos;
}
/**
* Obtiene los rangos de edad.
* @return array
*/
public function obtenerRangosEdad(){
$sql = "SELECT id_rango_edad, descripcion FROM rango_edad ORDER BY id_rango_edad";
$result = $this->conn->query($sql);
$rangos = [];
while($row = $result->fetch_assoc()){
$rangos[] = $row;
}
return $rangos;
}
/**
* Obtiene los niveles de estudio.
* @return array
*/
public function obtenerNivelesEstudio(){
$sql = "SELECT id_nivel, descripcion FROM nivel_estudio ORDER BY id_nivel";
$result = $this->conn->query($sql);
$niveles = [];
while($row = $result->fetch_assoc()){
$niveles[] = $row;
}
return $niveles;
}
public function obtenerNombresEmpresasInstituciones(){
$sql = "SELECT DISTINCT nombre_empresa_institucion FROM info_candidatos ORDER BY nombre_empresa_institucion";
$result = $this->conn->query($sql);
$empresas = [];
while($row = $result->fetch_assoc()){
$empresas[] = $row;
}
return $empresas;
}
public function obtenerMotivosExamen(){
$sql = "SELECT id, descripcion FROM motivo_examen ORDER BY descripcion";
$result = $this->conn->query($sql);
$motivos = [];
while($row = $result->fetch_assoc()){
$motivos[] = $row;
}
return $motivos;
}
}
?>

View File

@ -1,266 +0,0 @@
<?php
require_once '../config/Database.php';
class GraficoModel{
private $db;
public function __construct() {
$db = DataBase::getInstance();
}
public static function obtenerGeneroFemenino() {
$query = self::$db->prepare("SELECT COUNT(*) AS Femenino FROM candidato WHERE id_genero = 2 ");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['Femenino'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerGeneroMasculino() {
$query = self::$db->prepare("SELECT COUNT(*) AS Maculino FROM candidato WHERE id_genero = 1 ");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['Maculino'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerGeneroNoDefinido() {
$query = self::$db->prepare("SELECT COUNT(*) AS NoDefinido FROM candidato WHERE id_genero = 3 ");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['NoDefinido'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdadMenor18() {
$query = self::$db->prepare("SELECT COUNT(*) AS menorEdad FROM candidato WHERE id_rango_edad = 1");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['menorEdad'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad1824() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad1824 FROM candidato WHERE id_rango_edad = 2");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad1824'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad2434() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad2434 FROM candidato WHERE id_rango_edad = 3");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad2434'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad3544() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad3544 FROM candidato WHERE id_rango_edad = 4");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad3544'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad4554() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad4554 FROM candidato WHERE id_rango_edad = 5");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad4554'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad5564() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad5564 FROM candidato WHERE id_rango_edad = 6");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad5564'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEdad65oMas() {
$query = self::$db->prepare("SELECT COUNT(*) AS edad65oMas FROM candidato WHERE id_rango_edad = 7");
$query->execute();
$resultado = $query->get_result();
$output = "0";
if($resultado->num_rows > 0) {
while ($data = $resultado->fetch_assoc()) {
$output= $data['edad65oMas'];
}
}
$query->close();
self::$db->close();
return $output;
}
public static function obtenerEstados() {
try {
$query = self::$db->prepare("SELECT estados.nombre AS estado, COUNT(*) AS cantidad
FROM estados
INNER JOIN info_candidatos ON info_candidatos.id_estado = estados.id
GROUP BY estados.nombre
ORDER BY estados.nombre
");
$query->execute();
$resultado = $query->get_result();
$estados = [];
while ($data = $resultado->fetch_assoc()) {
$estados[] = $data;
}
$query->close();
error_log(json_encode($estados));
return $estados;
} catch (Exception $e) {
error_log("Error al obtener los estados: " . $e->getMessage());
return [];
}
}
public static function obtenerExamenes() {
try {
$query = self::$db->prepare("SELECT nombre_examen AS examen , COUNT(*) AS cantidad
FROM examen
INNER JOIN candidato ON candidato.id_examen = examen.id_examen
GROUP BY nombre_examen
ORDER BY nombre_examen;
");
$query->execute();
$resultado = $query->get_result();
$examenes = [];
while ($data = $resultado->fetch_assoc()) {
$examenes[] = $data;
}
$query->close();
error_log(json_encode($examenes));
return $examenes;
} catch (Exception $e) {
error_log("Error al obtener los examenes: " . $e->getMessage());
return [];
}
}
public static function obtenerFecha($fechaInicio, $fechaFin) {
try {
$query = self::$db->prepare("SELECT COUNT(*) AS total
FROM candidato
WHERE DATE(fecha_entrada) = ?
AND DATE(fecha_salida) = ?;
");
$query->bind_param("ss", $fechaInicio, $fechaFin);
$query->execute();
$resultado = $query->get_result();
$fechas = [];
while ($data = $resultado->fetch_assoc()) {
$fechas[] = $data;
}
error_log("Resultados de la consulta: " . json_encode($fechas)); // <-- Agrega este log
$query->close();
return $fechas;
} catch (Exception $e) {
error_log("Error al obtener las fechas: " . $e->getMessage());
return [];
}
}
}
?>

View File

@ -1,172 +0,0 @@
<?php
require_once __DIR__ . '/../config/Database.php';
class UsuarioModel {
private $conn;
public function __construct() {
$this->conn = Database::getInstance();
}
/**
* Registrar un nuevo usuario
* @param string $usuario Nombre de usuario
* @param string $contrasena Contraseña del usuario
* @return array
*/
public function crearUsuario($usuario, $contrasena){
// Hashear contraseña
$contrasena_hash = password_hash($contrasena, PASSWORD_DEFAULT);
$stmt = $this->conn->prepare("INSERT INTO usuario (usuario, contrasena) VALUES (?, ?)");
$stmt->bind_param("ss", $usuario, $contrasena_hash);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al registrar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario ' . $usuario . ' registrado exitosamente.'
];
}
public function actualizarUsuario($id, $usuario, $contrasena){
// Hashear contraseña
$contrasena_hash = password_hash($contrasena, PASSWORD_DEFAULT);
$stmt = $this->conn->prepare("UPDATE usuario SET usuario = ?, contrasena = ? WHERE id = ?");
$stmt->bind_param("ssi", $usuario, $contrasena_hash, $id);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al actualizar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario ' . $usuario .' actualizado exitosamente.'
];
}
/**
* Iniciar sesión de un usuario
* @param string $usuario Nombre de usuario
* @param string $contrasena Contraseña del usuario
* @return array
*/
public function iniciarSesion($usuario, $contrasena) {
$stmt = $this->conn->prepare("SELECT contrasena FROM usuario WHERE usuario = ?");
$stmt->bind_param("s", $usuario);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al iniciar sesión, intentelo más tarde.',
'res' => $stmt->error
];
}
$stmt->store_result();
if ($stmt->num_rows == 0) {
return [
'estado' => 'error',
'mensaje' => 'Usuario o contraseña incorrectos.'
];
}
$stmt->bind_result($contrasena_hash);
$stmt->fetch();
if (password_verify($contrasena, $contrasena_hash)){
return [
'estado' => 'exitoso',
'mensaje' => 'Inicio de sesión exitoso.'
];
} else {
return [
'estado' => 'error',
'mensaje' => 'Usuario o contraseña incorrectos.'
];
}
}
public function obtenerUsuarios() {
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("SELECT id, usuario FROM usuario");
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al obtener usuarios: ' . $stmt->error
];
}
// Obtener el resultado
$result = $stmt->get_result();
// Si no hay resultados, retornar un array con estado y mensaje
if ($result->num_rows == 0) {
return [
'estado' => 'error',
'mensaje' => 'No hay usuarios registrados.'
];
}
return $result->fetch_all(MYSQLI_ASSOC);
}
public function buscarUsuario($usuario) {
$stmt = $this->conn->prepare("SELECT id, usuario FROM usuario WHERE usuario = ?");
$stmt->bind_param("s", $usuario);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al verificar usuario: ' . $stmt->error
];
}
$stmt->store_result();
// Si no hay resultados, retornar un array con estado y mensaje
if ($stmt->num_rows == 0) {
return [
'estado' => 'exitoso',
'mensaje' => 'No existe el usuario.'
];
} else {
$stmt->bind_result($id, $usuario);
$stmt->fetch();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario existe.',
'id' => $id,
'usuario' => $usuario
];
}
}
public function eliminarUsuario($id){
$stmt = $this->conn->prepare("DELETE FROM usuario WHERE id = ?");
$stmt->bind_param("i", $id);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al eliminar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario eliminado exitosamente.'
];
}
}
?>

View File

@ -1,20 +0,0 @@
<?php
session_start();
if (!isset($_SESSION['usuario'])) {
header('Location: index.html');
exit();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pagina protegida</title>
</head>
<body>
<h1>Test</h1>
</body>
</html>

View File

@ -1,7 +0,0 @@
<?php
//require_once __DIR__ . "/controllers/usuarioController.php";
// UsuarioController::registrarUsuario("root", "root");
?>

View File

@ -1,65 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>
<link rel="stylesheet" href="../css/inicio.css">
<title>Gestión de usuarios</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-candidatos.php" class="active"><i class='bx bxs-dashboard icon' ></i>Gestión usuarios</a></li>
<!--
<li class="divider" data-text="main">Main</li>
<li>
<a href="#"><i class='bx bxs-inbox icon' ></i> Elements <i class='bx bx-chevron-right icon-right' ></i></a>
<ul class="side-dropdown">
<li><a href="#">Alert</a></li>
<li><a href="#">Badges</a></li>
<li><a href="#">Breadcrumbs</a></li>
<li><a href="#">Button</a></li>
</ul>
</li>
<li><a href="#"><i class='bx bxs-chart icon' ></i> Charts</a></li>
<li><a href="#"><i class='bx bxs-widget icon' ></i> Widgets</a></li>
<li class="divider" data-text="tablas y formularios">Tablas y formularios</li>
<li><a href="#"><i class='bx bx-table icon' ></i> Tablas</a></li>
<li>
<a href="#"><i class='bx bxs-notepad icon' ></i> Formularios <i class='bx bx-chevron-right icon-right' ></i></a>
<ul class="side-dropdown">
<li><a href="formulario-candidato.html">Registro de candidato</a></li>
<li><a href="formulario-datos-candidato.php">Datos de candidato</a></li>
</ul>
</li>
-->
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<!-- ========== MAIN ========== -->
<main>
<h1 class="title" style="margin: 2% 1%">Control</h1>
</main>
<!-- .......... MAIN .......... -->
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB