archivos de merge desde la rama recuperar-cambios

This commit is contained in:
Hectorgh24 2025-05-26 19:15:25 -06:00
commit a8e2895311
36 changed files with 3743 additions and 655 deletions

1
.gitignore vendored Normal file
View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
-- Crear usuario que utiliza el sistema
CREATE USER lania@localhost IDENTIFIED BY 'l4n1@Cc';
GRANT ALL PRIVILEGES ON lania_cc.* TO lania@localhost;
FLUSH PRIVILEGES;

View File

@ -0,0 +1,183 @@
DROP DATABASE IF EXISTS lania_cc;
CREATE DATABASE lania_cc DEFAULT CHARACTER SET utf8mb4;
USE lania_cc;
-- DDL -------------------------------------------------------------------------------------
CREATE TABLE genero (
id_genero TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(20) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE rango_edad (
id_rango_edad TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(15) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE tipo_identificacion (
id_tipo_id TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(50) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE nivel_estudio (
id_nivel TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(50) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE giro (
id_giro TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(100) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE examen (
id_examen SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre_examen VARCHAR(150) NOT NULL UNIQUE
) ENGINE=InnoDB;
-- IMPORTAR BASE DE DATOS DE INEGI
-- 1. TABLA CANDIDATO (datos básicos)
CREATE TABLE candidato (
id_candidato INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
fecha_entrada DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
fecha_salida DATETIME DEFAULT NULL,
nombres VARCHAR(100) NOT NULL,
primer_apellido VARCHAR(100) NOT NULL,
segundo_apellido VARCHAR(100) DEFAULT NULL,
correo VARCHAR(150) NOT NULL,
telefono VARCHAR(30) NOT NULL,
id_examen SMALLINT UNSIGNED NOT NULL,
id_tipo_id TINYINT UNSIGNED NOT NULL,
id_rango_edad TINYINT UNSIGNED NOT NULL,
id_genero TINYINT UNSIGNED NOT NULL,
FOREIGN KEY (id_examen) REFERENCES examen(id_examen),
FOREIGN KEY (id_tipo_id) REFERENCES tipo_identificacion(id_tipo_id),
FOREIGN KEY (id_rango_edad) REFERENCES rango_edad(id_rango_edad),
FOREIGN KEY (id_genero) REFERENCES genero(id_genero)
) ENGINE=InnoDB;
-- 2. TABLA INFO_CANDIDATOS (datos extendidos)
CREATE TABLE info_candidatos (
id_candidato INT UNSIGNED PRIMARY KEY,
id_pais INT NOT NULL,
id_estado INT DEFAULT NULL,
id_municipio INT DEFAULT NULL,
id_colonia INT DEFAULT NULL,
id_nivel TINYINT UNSIGNED NOT NULL,
id_giro TINYINT UNSIGNED NOT NULL,
nombre_empresa_institucion VARCHAR(150) NOT NULL,
motivo_examen VARCHAR(255) NOT NULL,
calificacion_servicio TINYINT NOT NULL,
consentimiento_pub TINYINT NOT NULL,
FOREIGN KEY (id_candidato) REFERENCES candidato(id_candidato)
ON DELETE CASCADE,
FOREIGN KEY (id_pais) REFERENCES paises(id),
FOREIGN KEY (id_estado) REFERENCES estados(id),
FOREIGN KEY (id_municipio) REFERENCES municipios(id),
FOREIGN KEY (id_colonia) REFERENCES colonias(id),
FOREIGN KEY (id_nivel) REFERENCES nivel_estudio(id_nivel),
FOREIGN KEY (id_giro) REFERENCES giro(id_giro)
) ENGINE=InnoDB;
CREATE TABLE usuario (
id INT AUTO_INCREMENT PRIMARY KEY,
usuario VARCHAR(150) UNIQUE NOT NULL,
contrasena VARCHAR(255) NOT NULL
) ENGINE=InnoDB;
-- DML -------------------------------------------------------------------------------------
-- Inserción catalogo "genero":
INSERT INTO genero (id_genero, descripcion) VALUES
(1, 'Masculino'),
(2, 'Femenino'),
(3, 'Prefiero no decir');
-- Inserción catalogo "rango_edad":
INSERT INTO rango_edad (id_rango_edad, descripcion) VALUES
(1, 'Menos de 18'),
(2, '18-24'),
(3, '24-34'),
(4, '35-44'),
(5, '44-54'),
(6, '55-64'),
(7, '65 o más');
-- Inserción catalogo "tipo_identificacion":
INSERT INTO tipo_identificacion (id_tipo_id, descripcion) VALUES
(1, 'INE'),
(2, 'Pasaporte'),
(3, 'CURP'),
(4, 'RFC'),
(5, 'Cédula Profesional'),
(6, 'Licencia de Conducir'),
(7, 'Otro');
-- Inserción catalogo "nivel_estudio":
INSERT INTO nivel_estudio (id_nivel, descripcion) VALUES
(1, 'Primaria'),
(2, 'Secundaria'),
(3, 'Bachillerato'),
(4, 'Técnico Superior Universitario'),
(5, 'Licenciatura'),
(6, 'Maestría'),
(7, 'Doctorado'),
(8, 'Otro');
-- Inserción catalogo "giro_empresa" considerando los giros de las empresas más comunes:
INSERT INTO giro (id_giro, descripcion) VALUES
(1, 'Tecnologías de la Información'),
(2, 'Gobierno'),
(3, 'Finanzas'),
(4, 'Salud'),
(5, 'Educación'),
(6, 'Telecomunicaciones'),
(7, 'Retail'),
(8, 'Manufactura'),
(9, 'Logística y Transporte'),
(10, 'Construcción'),
(11, 'Turismo y Hospitalidad'),
(12, 'Energía y Recursos Naturales'),
(13, 'Agricultura y Alimentación'),
(14, 'Medios de Comunicación y Entretenimiento'),
(15, 'Otros');
-- Inserción catalogo "examen" se refiere al nombre de la organización a la que pertence el examen:
INSERT INTO examen (id_examen, nombre_examen) VALUES
(1, 'Cisco'),
(2, 'IBM'),
(3, 'Microsoft'),
(4, 'Oracle'),
(5, 'SAP'),
(6, 'CompTIA'),
(7, 'Amazon Web Services'),
(8, 'Google Cloud Platform'),
(9, 'Salesforce'),
(10, 'Red Hat'),
(11, 'VMware'),
(12, 'Palo Alto Networks'),
(13, 'Fortinet'),
(14, 'Juniper Networks'),
(15, 'Otros');
-- Depues de importar la bd de inegi
insert into paises(nombre) values('Otro');
-- Insercion de un candidato de prueba:
INSERT INTO candidato (nombres, primer_apellido, segundo_apellido, correo, telefono, id_examen, id_tipo_id, id_rango_edad, id_genero) VALUES
('Juan', 'Pérez', 'Gómez', 'correo@gmail.com', '1234567890', 1, 1, 2, 1);
INSERT INTO info_candidatos (id_candidato, id_pais, id_estado, id_municipio, id_colonia, id_nivel, id_giro, nombre_empresa_institucion, motivo_examen, calificacion_servicio, consentimiento_pub) VALUES
(1, 1, 1, 1001, 10011, 5, 1, 'Empresa de Prueba', 'Motivo de prueba', 5, 1);

42
config/Database.php Normal file
View File

@ -0,0 +1,42 @@
<?php
// $db = Database::getInstance();
class Database {
private static $instance = null;
private $mysqli;
private $host;
private $dbname;
private $user;
private $password;
private $Database;
public function __construct() {
$host = 'localhost';
$dbname = 'lania_cc';
$user = 'lania';
$password = 'l4n1@Cc';
try {
$this->mysqli = new mysqli($host, $user, $password, $dbname);
// Verificar conexión
if ($this->mysqli->connect_error) {
throw new Exception("Database: Conexión fallida. " . $this->mysqli->connect_error);
}
} catch (Exception $e) {
throw new Exception("Database: Error . " . $e->getMessage());
}
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new Database();
}
return self::$instance->mysqli;
}
}
?>

View File

@ -0,0 +1,104 @@
<?php
require_once __DIR__ . '/../models/CandidatoModel.php';
class CandidatoController {
private static $candidatoModel = null;
public static function inicializar() {
if (self::$candidatoModel === null) {
self::$candidatoModel = new CandidatoModel();
}
}
public static function registrarCandidato() {
$nombres = $_POST['nombres'];
$primer_apellido = $_POST['primer_apellido'];
$segundo_apellido = $_POST['segundo_apellido'];
$correo = $_POST['correo'];
$telefono = $_POST['telefono'];
$id_examen = $_POST['id_examen'];
$id_tipo_id = $_POST['id_tipo_id'];
$id_rango_edad = $_POST['id_rango_edad'];
$id_genero = $_POST['id_genero'];
return self::$candidatoModel->registrarCandidato(
$nombres,
$primer_apellido,
$segundo_apellido,
$correo,
$telefono,
$id_examen,
$id_tipo_id,
$id_rango_edad,
$id_genero
);
}
public static function registrarInfoCandidato() {
$id_candidato = $_POST['id_candidato'];
$exiteInfo = self::existeRegistroInfoCandidato($id_candidato);
if ($exiteInfo) {
return [
"estado" => "error",
"mensaje" => "Ya existe un registro de información para este candidato."
];
}
if(!self::existeIdCandidato($id_candidato)){
return [
"estado" => "error",
"mensaje" => "El ID del candidato no existe."
];
}
$id_pais = $_POST['id_pais'];
$id_estado = $_POST['id_estado'];
$id_municipio = $_POST['id_municipio'];
$id_colonia = $_POST['id_colonia'];
$id_nivel = $_POST['id_nivel'];
$id_giro = $_POST['id_giro'];
$nombre_empresa_institucion = $_POST['nombre_empresa_institucion'];
$motivo_examen = $_POST['motivo_examen'];
$calificacion_servicio = $_POST['calificacion_servicio'];
$consentimiento_pub = $_POST['consentimiento_pub'];
$fecha_salida = $_POST['fecha_salida'];
return self::$candidatoModel->registrarInfoCandidatos(
$id_candidato,
$id_pais,
$id_estado,
$id_municipio,
$id_colonia,
$id_nivel,
$id_giro,
$nombre_empresa_institucion,
$motivo_examen,
$calificacion_servicio,
$consentimiento_pub,
$fecha_salida
);
}
public static function existeRegistroInfoCandidato($id_candidato) {
return self::$candidatoModel->verificarRegistroInfoCandidato($id_candidato);
}
public static function existeIdCandidato($id_candidato){
$resultado = self::$candidatoModel->existeIdCandidato($id_candidato);
if($resultado['estado'] === 'exitoso'){
return true;
} else {
return false;
}
}
}
// Instanciar el modelo al cargar el controlador
CandidatoController::inicializar();
?>

View File

@ -0,0 +1,92 @@
<?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();
}
}
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);
}
?>

View File

@ -0,0 +1,37 @@
<?php
require_once __DIR__ . '/UsuarioController.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Obtener los datos de la solicitud
$usuario = $_POST['numero-personal'];
$contrasena = $_POST['contrasena'];
try {
// Iniciar sesión del usuario
if (UsuarioController::iniciarSesion($usuario, $contrasena)) {
session_start(); // Iniciar la sesión
$_SESSION['autenticado'] = true; // Marcar la sesión como autenticada
echo json_encode([
'estado' => 'exitoso',
'mensaje' => 'Inicio de sesión exitoso'
]);
} else {
echo json_encode([
'estado' => 'error',
'mensaje' => 'Usuario o contraseña incorrectos'
]);
}
} catch (Exception $e) {
echo json_encode([
'estado' => 'error',
'mensaje' => 'Error al iniciar sesión, intentelo más tarde.',
'res' => $e->getMessage()
]);
}
} else {
header('HTTP/1.1 405 Method Not Allowed');
}
?>

View File

@ -0,0 +1,16 @@
<?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

@ -0,0 +1,25 @@
<?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

@ -0,0 +1,57 @@
<?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){
$usuarios = self::obtenerUsuarios();
foreach ($usuarios as $u) {
if ($u['usuario'] === $usuario) {
return true; // El usuario ya existe
}
}
return false; // El usuario no existe
}
public static function registrarUsuario($usuario, $contrasena){
if (self::existeUsuario($usuario)) {
echo "El usuario ya existe.";
return;
}
self::$usuarioModel->registrarUsuario($usuario, $contrasena);
echo "Usuario: ${usuario} registrado exitosamente.";
}
public static function eliminarUsuario($usuario){
if (!self::existeUsuario($usuario)) {
echo "El usuario no existe.";
return;
}
self::$usuarioModel->eliminarUsuario($usuario);
echo "Usuario: ${usuario} eliminado exitosamente.";
}
}
# Instanciar el modelo al cargar el controlador
UsuarioController::inicializar();
?>

View File

@ -0,0 +1,53 @@
<?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."]);
}
?>

526
controllers/graficos.php Normal file
View File

@ -0,0 +1,526 @@
<?php
require_once '../config/Database.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
$tipoConsulta = $input['tipoConsulta'] ?? '';
$filtros = [
'id_rango_edad' => $input['id_rango_edad'] ?? null,
'id_genero' => $input['id_genero'] ?? null,
'id_examen' => $input['id_examen'] ?? null,
'fechaInicio' => $input['fechaInicio'] ?? null,
'fechaFin' => $input['fechaFin'] ?? null,
];
$graficos = new Graficos();
switch ($tipoConsulta) {
case 'Femenino':
$cantidad = $graficos->obtenerGeneroFemenino($filtros);
break;
case 'Masculino':
$cantidad = $graficos->obtenerGeneroMasculino($filtros);
break;
case 'Prefiero no decirlo':
$cantidad = $graficos->obtenerGeneroNoDefinido($filtros);
break;
case 'Menor de 18 años':
$cantidad = $graficos->obtenerEdadMenor18($filtros);
break;
case '18 a 24 años':
$cantidad = $graficos->obtenerEdad1824($filtros);
break;
case '25 a 34 años':
$cantidad = $graficos->obtenerEdad2434($filtros);
break;
case '35 a 44 años':
$cantidad = $graficos->obtenerEdad3544($filtros);
break;
case '45 a 54 años':
$cantidad = $graficos->obtenerEdad4554($filtros);
break;
case '55 a 64 años':
$cantidad = $graficos->obtenerEdad5564($filtros);
break;
case '65 años o más':
$cantidad = $graficos->obtenerEdad65oMas($filtros);
break;
case 'Estados':
$cantidad = $graficos->obtenerEstados($filtros);
echo json_encode($cantidad);
exit;
case 'Examenes':
$cantidad = $graficos->obtenerExamenes($filtros);
echo json_encode($cantidad);
exit;
case 'Fechas':
$fechaInicio = $input['fechaInicio'] ?? '';
$fechaFin = $input['fechaFin'] ?? '';
$cantidad = $graficos->obtenerFecha($fechaInicio, $fechaFin);
echo json_encode($cantidad);
exit;
default:
$cantidad = 0;
}
echo json_encode(['cantidad' => $cantidad]);
}
class Graficos{
private $Database;
protected $db;
public function __construct() {
$this->Database = new Database();
$this->db = $this->Database->getInstance();
}
public function obtenerGeneroFemenino($filtros = []) {
$sql = "SELECT COUNT(*) AS Femenino FROM candidato WHERE id_genero = 2";
$params = [];
$types = "";
if (!empty($filtros['id_rango_edad']) && $filtros['id_rango_edad'] !== "NULL") {
$sql .= " AND id_rango_edad = ?";
$params[] = $filtros['id_rango_edad'];
$types .= "i";
}
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['Femenino'];
}
$query->close();
return $output;
}
public function obtenerGeneroMasculino($filtros = []) {
$sql = "SELECT COUNT(*) AS Masculino FROM candidato WHERE id_genero = 1";
$params = [];
$types = "";
if (!empty($filtros['id_rango_edad']) && $filtros['id_rango_edad'] !== "NULL") {
$sql .= " AND id_rango_edad = ?";
$params[] = $filtros['id_rango_edad'];
$types .= "i";
}
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['Masculino'];
}
$query->close();
return $output;
}
public function obtenerGeneroNoDefinido($filtros = []) {
$sql = "SELECT COUNT(*) AS NoDefinido FROM candidato WHERE id_genero = 3";
$params = [];
$types = "";
if (!empty($filtros['id_rango_edad']) && $filtros['id_rango_edad'] !== "NULL") {
$sql .= " AND id_rango_edad = ?";
$params[] = $filtros['id_rango_edad'];
$types .= "i";
}
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['NoDefinido'];
}
$query->close();
return $output;
}
public function obtenerEdadMenor18($filtros = []) {
$sql = "SELECT COUNT(*) AS menorEdad FROM candidato WHERE id_rango_edad = 1";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['menorEdad'];
}
$query->close();
return $output;
}
public function obtenerEdad1824($filtros = []) {
$sql = "SELECT COUNT(*) AS edad1824 FROM candidato WHERE id_rango_edad = 2";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad1824'];
}
$query->close();
return $output;
}
public function obtenerEdad2434($filtros = []) {
$sql = "SELECT COUNT(*) AS edad2434 FROM candidato WHERE id_rango_edad = 3";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad2434'];
}
$query->close();
return $output;
}
public function obtenerEdad3544($filtros = []) {
$sql = "SELECT COUNT(*) AS edad3544 FROM candidato WHERE id_rango_edad = 4";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad3544'];
}
$query->close();
return $output;
}
public function obtenerEdad4554($filtros = []) {
$sql = "SELECT COUNT(*) AS edad4554 FROM candidato WHERE id_rango_edad = 5";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad4554'];
}
$query->close();
return $output;
}
public function obtenerEdad5564($filtros = []) {
$sql = "SELECT COUNT(*) AS edad5564 FROM candidato WHERE id_rango_edad = 6";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad5564'];
}
$query->close();
return $output;
}
public function obtenerEdad65oMas($filtros = []) {
$sql = "SELECT COUNT(*) AS edad65oMas FROM candidato WHERE id_rango_edad = 7";
$params = [];
$types = "";
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(fecha_entrada) >= ? AND DATE(fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$output = "0";
if ($resultado->num_rows > 0) {
$data = $resultado->fetch_assoc();
$output = $data['edad65oMas'];
}
$query->close();
return $output;
}
public function obtenerEstados($filtros = []) {
$sql = "SELECT estados.nombre AS estado, COUNT(*) AS cantidad
FROM candidato
INNER JOIN info_candidatos ON candidato.id_candidato = info_candidatos.id_candidato
INNER JOIN estados ON info_candidatos.id_estado = estados.id
WHERE 1=1";
$params = [];
$types = "";
if (!empty($filtros['id_rango_edad']) && $filtros['id_rango_edad'] !== "NULL") {
$sql .= " AND candidato.id_rango_edad = ?";
$params[] = $filtros['id_rango_edad'];
$types .= "i";
}
if (!empty($filtros['id_genero']) && $filtros['id_genero'] !== "NULL") {
$sql .= " AND candidato.id_genero = ?";
$params[] = $filtros['id_genero'];
$types .= "i";
}
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND candidato.id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(candidato.fecha_entrada) >= ? AND DATE(candidato.fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$sql .= " GROUP BY estados.nombre ORDER BY estados.nombre";
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$estados = [];
while ($data = $resultado->fetch_assoc()) {
$estados[] = $data;
}
$query->close();
return $estados;
}
public function obtenerExamenes($filtros = []) {
$sql = "SELECT examen.nombre_examen AS examen, COUNT(*) AS cantidad
FROM candidato
LEFT JOIN examen ON candidato.id_examen = examen.id_examen
WHERE 1=1";
$params = [];
$types = "";
if (!empty($filtros['id_rango_edad']) && $filtros['id_rango_edad'] !== "NULL") {
$sql .= " AND candidato.id_rango_edad = ?";
$params[] = $filtros['id_rango_edad'];
$types .= "i";
}
if (!empty($filtros['id_genero']) && $filtros['id_genero'] !== "NULL") {
$sql .= " AND candidato.id_genero = ?";
$params[] = $filtros['id_genero'];
$types .= "i";
}
if (!empty($filtros['id_examen']) && $filtros['id_examen'] !== "NULL") {
$sql .= " AND candidato.id_examen = ?";
$params[] = $filtros['id_examen'];
$types .= "i";
}
if (!empty($filtros['fechaInicio']) && !empty($filtros['fechaFin'])) {
$sql .= " AND DATE(candidato.fecha_entrada) >= ? AND DATE(candidato.fecha_salida) <= ?";
$params[] = $filtros['fechaInicio'];
$params[] = $filtros['fechaFin'];
$types .= "ss";
}
$sql .= " GROUP BY examen.nombre_examen ORDER BY examen.nombre_examen";
$query = $this->db->prepare($sql);
if ($params) {
$query->bind_param($types, ...$params);
}
$query->execute();
$resultado = $query->get_result();
$examenes = [];
while ($data = $resultado->fetch_assoc()) {
$examenes[] = $data;
}
$query->close();
return $examenes;
}
public function obtenerFecha($fechaInicio, $fechaFin) {
$sql = "SELECT COUNT(*) AS cantidad
FROM candidato
WHERE DATE(fecha_entrada) >= ? AND DATE(fecha_entrada) <= ?";
$query = $this->db->prepare($sql);
$query->bind_param("ss", $fechaInicio, $fechaFin);
$query->execute();
$resultado = $query->get_result();
$data = $resultado->fetch_assoc();
$query->close();
// Devuelve un array con un solo objeto para mantener compatibilidad con el frontend
return [ [ 'cantidad' => $data['cantidad'], 'fechaInicio' => $fechaInicio, 'fechaFin' => $fechaFin ] ];
}
}
?>

View File

@ -579,3 +579,5 @@ main .btn-send:hover {
display: none; display: none;
} }
} }

View File

@ -1,198 +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 básicos</h1>
<ul class="breadcrumbs">
<li><a href="#">Formularios</a></li>
<li class="divider">/</li>
<li><a href="#" class="active">Datos básicos</a></li>
</ul>
<h3 class="title2">¡Bienvenido (a)!</h3>
<p>Nos gustaría conocerte mejor</p>
<br>
<form id="formulario-datos-basicos" action="" method="POST">
<input type="hidden" id="id_candidato" name="id_candidato">
<input type="hidden" id="fecha_entrada" name="fecha_entrada" value="">
<input type="hidden" id="fecha_salida" name="fecha_salida" value="">
<div>
<label for ="nombres">Nombres:</label>
<input type="text" id="nombres" name="nombres" required>
</div>
<div>
<label for="primer_apellido">Primer apellido:</label>
<input type="text" id="primer_apellido" name="primer_apellido" required>
</div>
<div>
<label for="segundo_apellido">Segundo apellido:</label>
<input type="text" id="segundo_apellido" name="segundo_apellido" required>
</div>
<div>
<label for="correo">Correo electrónico:</label>
<input type="text" id="correo" name="correo" required>
</div>
<div>
<label for="telefono">Teléfono:</label>
<input type="number" id="telefono" name="telefono" required>
</div>
<div>
<label for="id_examen">Examen:</label>
<select name="id_examen" id="id_examen" required>
<option value="">Selecciona un examen</option>
<option value="1">Cisco</option>
<option value="2">IBM</option>
<option value="3">Microsoft</option>
<option value="4">Oracle</option>
<option value="5">SAP</option>
<option value="6">CompTIA</option>
<option value="7">Amazon Web Services</option>
<option value="8">Google Cloud Platform</option>
<option value="9">Salesforce</option>
<option value="10">Red Hat</option>
<option value="11">VMWare</option>
<option value="12">Palo Alto Networks</option>
<option value="13">Fornitet</option>
<option value="14">Juniper Networks</option>
<option value="15">Otros</option>
</select><br>
</div>
<div>
<label for="id_tipo_id">Tipo de Identificación:</label>
<select name="id_tipo_id" id="id_tipo_id" required>
<option value="">Selecciona el tipo de identificación</option>
<option value="1">INE</option>
<option value="2">Pasaporte</option>
<option value="3">CURP</option>
<option value="4">RFC</option>
<option value="5">Cédila Profesional</option>
<option value="6">Licencia de conducir</option>
<option value="7">Otro</option>
</select><br>
</div>
<div>
<label for="id_rango_edad">Rango de edad:</label>
<select name="id_rango_edad" id="id_rango_edad" required>
<option value="">Selecciona un rango de edad</option>
<option value="1">Menos de 18</option>
<option value="2">18-24</option>
<option value="3">24-34</option>
<option value="4">35-44</option>
<option value="5">45-54</option>
<option value="6">55-64</option>
<option value="7">65 o más</option>
</select><br>
</div>
<div>
<label for="id_genero">Género:</label>
<select name="id_genero" id="id_genero" required>
<option value="">Selecciona un género</option>
<option value="1">Masculino</option>
<option value="2">Femenino</option>
<option value="3">Prefiero no decir</option>
</select><br>
</div>
<br>
<button type="submit">Enviar</button>
<div id="mensaje-error" class="mensaje-error"><p>hola</p></div>
</form>
</main>
<!-- MAIN -->
</section>
<!-- NAVBAR -->
<script src="js/form.js"></script>
<script src="js/form_datos_basicos.js"""
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

View File

@ -1,119 +0,0 @@
const formulario = document.getElementById("formulario-datos-basicos");
const notificacion = document.getElementById("mensaje-error");
// Función para validar el nombre
function validarNombre(nombre) {
const nombreRegex = /^[a-zA-ZÀ-ÿ\s]+$/; // Permite letras y espacios
return nombreRegex.test(nombre);
}
//funcion para validar apellido
function validarApellido(apellido) {
const apellidoRegex = /^[a-zA-ZÀ-ÿ]+$/; // Permite solo letras, sin espacios
return apellidoRegex.test(apellido);
}
// Función para validar número telefónico (10 dígitos)
function validarTelefono(telefono) {
const telefonoRegex = /^\d{10}$/;
return telefonoRegex.test(telefono);
}
// Función para validar correo electrónico
function validarCorreo(correo) {
const correoRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return correoRegex.test(correo);
}
formulario.addEventListener("submit", async(event) => {
event.preventDefault();
// Limpiar mensaje de error previo
notificacion.textContent = "";
notificacion.style.display = "none";
// Obtener valores de los campos
const idCandidato = document.getElementById('id_candidato').value;
const fechaEntrada = document.getElementById('fecha_entrada').value;
const fechaSalida = document.getElementById('fecha_salida').value;
const nombres = document.getElementById('nombres').value.trim();
const primerApellido = document.getElementById('primer_apellido').value.trim();
const segundoApellido = document.getElementById('segundo_apellido').value.trim();
const correo = document.getElementById('correo').value.trim();
const telefono = document.getElementById('telefono').value.trim();
const idExamen = document.getElementById('id_examen').value;
const idTipoId = document.getElementById('id_tipo_id').value;
const idRangoEdad = document.getElementById('id_rango_edad').value;
const idGenero = document.getElementById('id_genero').value;
// Validaciones
let errores = [];
// Validar correo electrónico
if (!validarCorreo(correo)) {
errores.push("El correo electrónico no es válido. ");
}
// validar nombre
if (!validarNombre(nombres)) {
errores.push("El nombre no tiene un formato válido. ");
}
// validar apellido
if (!validarApellido(primerApellido)) {
errores.push("El primer apellido no tiene un formato válido. ");
}
if (!validarApellido(segundoApellido)) {
errores.push("El segundo apellido no tiene un formato válido. ");
}
// Validar número telefónico
if (!validarTelefono(telefono)) {
errores.push("El número telefónico debe ser un número de 10 dígitos. ");
}
// Si hay errores, mostrarlos y detener el envío
if (errores.length > 0) {
notificacion.textContent = errores.join("\n");
notificacion.style.display = "block";
return;
}
// Preparar datos para envío
const formData = new FormData();
formData.append("id_candidato", idCandidato);
formData.append("fecha_entrada", fechaEntrada);
formData.append("fecha_salida", fechaSalida);
formData.append("nombres", nombres);
formData.append("primer_apellido", primerApellido);
formData.append("segundo_apellido", segundoApellido);
formData.append("correo", correo);
formData.append("telefono", telefono);
formData.append("id_examen", idExamen);
formData.append("id_tipo_id", idTipoId);
formData.append("id_rango_edad", idRangoEdad);
formData.append("id_genero", idGenero);
try {
const respuesta = await fetch('ruta', {
method: "POST",
body: formData,
});
const resultado = await respuesta.json();
if (resultado.datosIngresados) {
alert('Se guardó la información correctamente');
window.location.href = 'inicio.html';
} else {
notificacion.textContent = resultado.mensaje;
notificacion.style.display = "block";
}
} catch (error) {
notificacion.textContent = "Lo sentimos, ocurrió un error: " + error.message;
notificacion.style.display = "block";
}
});

View File

@ -1,61 +0,0 @@
const formulario = document.getElementById("formulario-datos-extendido");
const notificacion = document.getElementById("mensaje-error");
formulario.addEventListener("submit", async(event) => {
event.preventDefault();
// Limpiar mensaje de error previo
notificacion.textContent = "";
notificacion.style.display = "none";
// Obtener valores de los campos
const idCandidato = document.getElementById('id_candidato').value;
const idPais = document.getElementById('id_pais').value;
const codigoPostal = document.getElementById('codigo_postal').value; // campo numérico, no necesita trim
const idEstado = document.getElementById('id_estado').value;
const idMunicipio = document.getElementById('id_municipio').value;
const idColonia = document.getElementById('id_colonia').value;
const idNivel = document.getElementById('id_nivel').value;
const idGiro = document.getElementById('id_giro').value;
const nombreEmpresa = document.getElementById('nombre_empresa').value.trim();
const motivoExamen = document.getElementById('motivo_examen').value.trim();
const calificacionServicio = document.getElementById('calificacion_servicio').value;
const consentimientoPub = document.getElementById('consentimiento_pub').checked;
// Preparar datos para envío
const formData = new FormData();
formData.append("id_candidato", idCandidato);
formData.append("id_pais", idPais);
formData.append("codigo_postal", codigoPostal);
formData.append("id_estado", idEstado);
formData.append("id_municipio", idMunicipio);
formData.append("id_colonia", idColonia);
formData.append("id_nivel", idNivel);
formData.append("id_giro", idGiro);
formData.append("nombre_empresa", nombreEmpresa);
formData.append("motivo_examen", motivoExamen);
formData.append("calificacion_servicio", calificacionServicio);
formData.append("consentimiento_pub", consentimientoPub ? 1 : 0);
try {
const respuesta = await fetch('ruta', {
method: "POST",
body: formData,
});
const resultado = await respuesta.json();
if (resultado.datosIngresados) {
alert('Se guardó la información correctamente');
window.location.href = 'inicio.html';
} else {
notificacion.textContent = resultado.mensaje;
notificacion.style.display = "block";
}
} catch (error) {
notificacion.textContent = "Lo sentimos, ocurrió un error: " + error.message;
notificacion.style.display = "block";
}
});

226
js/formulario-candidato.js Normal file
View File

@ -0,0 +1,226 @@
const formulario = document.getElementById("formulario-datos-basicos");
const notificacion = document.getElementById("mensaje-error");
obtenerNombresExamenes();
obtenerTiposIdentificacion();
obtenerRangosEdad();
function obtenerNombresExamenes(){
let url = "../controllers/CatalogosController.php?obtener=examenes";
fetch(url)
.then(response => response.json())
.then(data => {
const selectExamen = document.getElementById('id_examen');
let examen = new Map();
// Iterar sobre cada fila y mapear por por id_examen, nombre_examen
data.forEach(row =>{
examen.set(row['id_examen'], row['nombre_examen']);
})
// LLenar opciones del select de examen
for (let [id_examen, nombre_examen] of examen) {
selectExamen.innerHTML += "<option value='" + id_examen + "'>" + nombre_examen + "</option>";
}
})
.catch(error => console.error('Error al obtener los exámenes:', error));
}
function obtenerTiposIdentificacion(){
let url = "../controllers/CatalogosController.php?obtener=identificacion";
fetch(url)
.then(response => response.json())
.then(data => {
const selectTipoId = document.getElementById('id_tipo_id');
let tipoId = new Map();
// Iterar sobre cada fila y mapear por por id_tipo_id, descripcion
data.forEach(row =>{
tipoId.set(row['id_tipo_id'], row['descripcion']);
})
// LLenar opciones del select de examen
for (let [id_tipo_id, descripcion] of tipoId) {
selectTipoId.innerHTML += "<option value='" + id_tipo_id + "'>" + descripcion + "</option>";
}
})
.catch(error => console.error('Error al obtener los tipos de identificación:', error));
}
function obtenerRangosEdad(){
let url = "../controllers/CatalogosController.php?obtener=rangosedad";
fetch(url)
.then(response => response.json())
.then(data => {
const selectRangoEdad = document.getElementById('id_rango_edad');
let tipoId = new Map();
// Iterar sobre cada fila y mapear por por id_tipo_id, descripcion
data.forEach(row =>{
tipoId.set(row['id_rango_edad'], row['descripcion']);
})
// LLenar opciones del select de examen
for (let [id_rango_edad, descripcion] of tipoId) {
selectRangoEdad.innerHTML += "<option value='" + id_rango_edad + "'>" + descripcion + "</option>";
}
})
.catch(error => console.error('Error al obtener rangos de edad:', error));
}
// Validaciones - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function selectExamenValido(){
const selectExamen = document.getElementById('id_examen');
const idExamen = selectExamen.value;
return idExamen !== "NULL";
}
function selectTipoIdentificacionValido(){
const selectTipoId = document.getElementById('id_tipo_id');
const idTipoId = selectTipoId.value;
return idTipoId !== "NULL";
}
function selectRangoEdadValido(){
const selectRangoEdad = document.getElementById('id_rango_edad');
const idRangoEdad = selectRangoEdad.value;
return idRangoEdad !== "NULL";
}
function selectGeneroValido(){
const selectGenero = document.getElementById('id_genero');
const idGenero = selectGenero.value;
return idGenero !== "NULL";
}
// Función para validar el nombre
function validarNombre(nombre) {
const nombreRegex = /^[a-zA-ZÀ-ÿ\s]+$/; // Permite letras y espacios
return nombreRegex.test(nombre);
}
//funcion para validar apellido
function validarApellido(apellido) {
const apellidoRegex = /^[a-zA-ZÀ-ÿ]+$/; // Permite solo letras, sin espacios
return apellidoRegex.test(apellido);
}
// Función para validar número telefónico (10 dígitos)
function validarTelefono(telefono) {
const telefonoRegex = /^\d{10}$/;
return telefonoRegex.test(telefono);
}
// Función para validar correo electrónico
function validarCorreo(correo) {
const correoRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return correoRegex.test(correo);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Validaciones
formulario.addEventListener("submit", async(event) => {
event.preventDefault();
// Limpiar mensaje de error previo
notificacion.textContent = "";
notificacion.style.display = "none";
// Obtener valores de los campos
const nombres = document.getElementById('nombres').value.trim();
const primerApellido = document.getElementById('primer_apellido').value.trim();
const segundoApellido = document.getElementById('segundo_apellido').value.trim();
const correo = document.getElementById('correo').value.trim();
const telefono = document.getElementById('telefono').value.trim();
const idExamen = document.getElementById('id_examen').value;
const idTipoId = document.getElementById('id_tipo_id').value;
const idRangoEdad = document.getElementById('id_rango_edad').value;
const idGenero = document.getElementById('id_genero').value;
// Validaciones
let errores = [];
// Validar correo electrónico
if (!validarCorreo(correo)) {
errores.push("⦁ El correo electrónico no es válido. ");
}
// validar nombre
if (!validarNombre(nombres)) {
errores.push("⦁ El nombre no tiene un formato válido. ");
}
// validar apellido
if (!validarApellido(primerApellido)) {
errores.push("⦁ El primer apellido no tiene un formato válido. ");
}
if (!validarApellido(segundoApellido)) {
errores.push("⦁ El segundo apellido no tiene un formato válido. ");
}
// Validar número telefónico
if (!validarTelefono(telefono)) {
errores.push("⦁ El número telefónico debe ser un número de 10 dígitos. ");
}
if(!selectExamenValido()){
errores.push("⦁ Seleccione un examen. ");
}
if(!selectTipoIdentificacionValido()){
errores.push("⦁ Seleccione un tipo de identificación. ");
}
if(!selectRangoEdadValido()){
errores.push("⦁ Seleccione un rango de edad. ");
}
if(!selectGeneroValido()){
errores.push("⦁ Seleccione un género. ");
}
// Si hay errores, mostrarlos y detener el envío
if (errores.length > 0) {
alert("Datos del formulario incompletos\n" + errores.join("\n"));
//notificacion.textContent = errores.join("\n");
//notificacion.style.display = "block";
return;
}
// Preparar datos para envío
const formData = new FormData();
formData.append("nombres", nombres);
formData.append("primer_apellido", primerApellido);
formData.append("segundo_apellido", segundoApellido);
formData.append("correo", correo);
formData.append("telefono", telefono);
formData.append("id_examen", idExamen);
formData.append("id_tipo_id", idTipoId);
formData.append("id_rango_edad", idRangoEdad);
formData.append("id_genero", idGenero);
// Enviar petición POST para registrar candidato
try {
const respuesta = await fetch('../controllers/RegistrarCandidatoController.php', {
method: "POST",
body: formData,
});
// Obtener respuesta de petición de registro
const resultado = await respuesta.json();
// Verificar si el registro fue exitoso
if (resultado.registroExitoso) {
alert('Se guardó la información correctamente');
window.location.href = 'pantalla-salida-form.html';
} else {
notificacion.textContent = resultado.message;
notificacion.style.display = "block";
}
} catch (error) {
notificacion.textContent = "Lo sentimos, ocurrió un error: " + error.message;
notificacion.style.display = "block";
}
});

View File

@ -0,0 +1,354 @@
document.addEventListener("DOMContentLoaded", function () {
const formulario = document.getElementById("formulario-datos-extendido");
const buscarBtn = document.getElementById("buscarBtn");
const paisSelect = document.getElementById("id_pais");
const inputCodigoPostal = document.getElementById("codigo_postal");
const inputButtonBuscarCodigoPostal = document.getElementById("buscarBtn");
const estadoSelect = document.getElementById("id_estado");
const municipioSelect = document.getElementById("id_municipio");
const coloniaSelect = document.getElementById("id_colonia");
const giroSelect = document.getElementById("id_giro");
const nivelEstudioSelect = document.getElementById("id_nivel");
const selectCalificacionServicio = document.getElementById("calificacion_servicio");
const dataListEmpresasInstituciones = document.getElementById("sugerencias_ei");
llenarSelectGiro();
llenarSelectNivelesEstudio();
llenarDataListEmpresasInstituciones();
// FUNCIONES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function llenarSelectGiro() {
// URL para la solicitud
let url = "../controllers/CatalogosController.php?obtener=giros";
// Realiza una solicitud HTTP GET a la URL especificada
fetch(url)
.then(response => {
// Verifica si la respuesta del servidor es exitosa
if (!response.ok) {
throw new Error("llenarSelectGiro(): Error en la respuesta del servidor.");
}
// Convertir la respuesta a JSON
return response.json();
})
.then(data => {
// Verifica si se recibieron datos
if (data.length > 0) {
// Añade las opciones de giros al elemento select
data.forEach(row => {
giroSelect.innerHTML += "<option value='" + row.id_giro + "'>" + row.descripcion + "</option>";
});
} else {
alert("llenarSelectGiro(): No se encontraron datos para los giros.");
}
})
.catch(error => {
console.error("llenarSelectGiro(): Error en la solicitud. ", error);
});
}
function llenarSelectNivelesEstudio(){
let url = "../controllers/CatalogosController.php?obtener=nivelesestudio";
// Petición fetch y llenado de select
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error("llenarSelectNivelesEstudio(): Error en la respuesta del servidor.");
}
return response.json();
})
.then(data => {
if (data.length > 0) {
data.forEach(row => {
nivelEstudioSelect.innerHTML += "<option value='" + row.id_nivel + "'>" + row.descripcion + "</option>";
});
} else {
alert("llenarSelectNivelesEstudio(): No se encontraron datos para los giros.");
}
})
.catch(error => {
console.error("llenarSelectNivelesEstudio(): Error en la solicitud. ", error);
});
}
function llenarDataListEmpresasInstituciones(){
let url = "../controllers/CatalogosController.php?obtener=empresasinstituciones";
fetch(url)
.then(response => response.json())
.then(data => {
if (data.length > 0) {
data.forEach(row => {
dataListEmpresasInstituciones.innerHTML += "<option value='" + row.nombre_empresa_institucion + "'>" + row.nombre_empresa_institucion + "</option>";
});
} else {
console.log("llenarDataListEmpresasInstituciones(): No se encontraron datos para las empresas o instituciones.");
}
})
.catch(error => {
console.error("llenarDataListEmpresasInstituciones(): Error en la solicitud. ", error);
});
}
// Función para obtener fecha en formato: 2025-04-27 09:05:18
function obtenerFechaActual() {
const ahora = new Date();
const anio = ahora.getFullYear();
const mes = String(ahora.getMonth() + 1).padStart(2, '0'); // Mes comienza en 0
const dia = String(ahora.getDate()).padStart(2, '0');
const horas = String(ahora.getHours()).padStart(2, '0');
const minutos = String(ahora.getMinutes()).padStart(2, '0');
const segundos = String(ahora.getSeconds()).padStart(2, '0');
return `${anio}-${mes}-${dia} ${horas}:${minutos}:${segundos}`;
}
function selectPaisValido(){
return paisSelect.value !== "NULL";
}
function selectNivelEstudioValido(){
return nivelEstudioSelect.value !== "NULL";
}
function selectGiroValido(){
return giroSelect.value !== "NULL";
}
function selectCalificacionServicioValido(){
return selectCalificacionServicio.value !== "NULL";
}
function selectEstadoValido(){
if(paisSelect.value === "1"){
return estadoSelect.value !== "NULL";
}
return true;
}
function selectMunicipioValido(){
if(paisSelect.value === "1"){
return municipioSelect.value !== "NULL";
}
return true;
}
function selectColoniaValido(){
if(paisSelect.value === "1"){
return coloniaSelect.value !== "NULL";
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FUNCIONES
// EVENTOS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Añadir un evento de cambio al select de país
paisSelect.addEventListener("change", function() {
// Si el país es México, habilitar el campo de código postal
if (paisSelect.value === "1") {
inputCodigoPostal.removeAttribute("disabled");
inputButtonBuscarCodigoPostal.removeAttribute("disabled");
} else {
inputCodigoPostal.value = "";
inputCodigoPostal.setAttribute("disabled", "");
inputButtonBuscarCodigoPostal.setAttribute("disabled", "");
estadoSelect.removeAttribute("required");
municipioSelect.removeAttribute("required");
coloniaSelect.removeAttribute("required");
estadoSelect.setAttribute("disabled", "");
municipioSelect.setAttribute("disabled", "");
coloniaSelect.setAttribute("disabled", "");
estadoSelect.innerHTML = "<option value='NULL'>Seleccione su estado</option>";
municipioSelect.innerHTML = "<option value='NULL'>Seleccione su municipio</option>";
coloniaSelect.innerHTML = "<option value='NULL'>Seleccione su colonia</option>";
}
});
//Añadir un evento al boton de buscar
buscarBtn.addEventListener("click", function () {
let inputCodigoPostal = document.getElementById("codigo_postal").value;
//verificar si el codigo postal esta vacio
if (inputCodigoPostal) {
// Limpia los selects antes de llenarlos
estadoSelect.innerHTML = "<option value='NULL'>Seleccione su estado</option>";
municipioSelect.innerHTML = "<option value='NULL'>Seleccione su municipio</option>";
coloniaSelect.innerHTML = "<option value='NULL'>Seleccione su colonia</option>";
// Construye la URL para la solicitud
let url = "../controllers/CatalogosController.php?codigo_postal=" + encodeURIComponent(inputCodigoPostal);
// 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.json());
// Verifica si la respuesta del servidor es exitosa
if (!response.ok) {
throw new Error("Error en la respuesta del servidor");
}
// Convertir la respuesta a JSON
return response.json();
})
.then(data => {
// Verifica si se recibieron datos
if (data.length > 0) {
// Quitar disable a los selects
estadoSelect.removeAttribute("disabled");
estadoSelect.setAttribute("required", "required");
municipioSelect.removeAttribute("disabled");
municipioSelect.setAttribute("required", "required");
coloniaSelect.removeAttribute("disabled");
coloniaSelect.setAttribute("required", "required");
//Crea conjuntos para almacenar estados, ciudades y colonias
let estados = new Map();
let municipios = new Map();
let colonias = new Map();
// Itera sobre cada fila de datos recibidos
data.forEach(row => {
//console.log(row);
estados.set(row['id_estado'], row['estado']);
municipios.set(row['id_municipio'], row['municipio']);
colonias.set(row['id_colonia'], row['colonia']);
});
// Añade las opciones de estados al elemento select
for (let [id_estado, estado] of estados) {
estadoSelect.innerHTML += "<option value='" + id_estado + "'>" + estado + "</option>";
}
// Añade las opciones de ciudades al elemento select
for (let [id_municipio, municipio] of municipios) {
municipioSelect.innerHTML += "<option value='" + id_municipio + "'>" + municipio + "</option>";
}
// Añade las opciones de colonias al elemento select
for (let [id_colonia, colonia] of colonias) {
coloniaSelect.innerHTML += "<option value='" + id_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.");
}
});
formulario.addEventListener("submit", async(event) => {
event.preventDefault();
// Obtener valores de los campos
const idCandidato = document.getElementById('id_candidato').value;
const idPais = document.getElementById('id_pais').value;
const codigoPostal = document.getElementById('codigo_postal').value;
const idEstado = document.getElementById('id_estado').value;
const idMunicipio = document.getElementById('id_municipio').value;
const idColonia = document.getElementById('id_colonia').value;
const idNivel = document.getElementById('id_nivel').value;
const idGiro = document.getElementById('id_giro').value;
const nombreEmpresa = document.getElementById('nombre_empresa').value.trim();
const motivoExamen = document.getElementById('motivo_examen').value.trim();
const calificacionServicio = document.getElementById('calificacion_servicio').value;
const consentimientoPub = document.getElementById('consentimiento_pub').checked;
const fechaSalida = obtenerFechaActual();
let validaciones = [];
if(!selectPaisValido()){
validaciones.push("⦁ Seleccione un país. ");
}
if(!selectNivelEstudioValido()){
validaciones.push("⦁ Seleccione un nivel de estudio.");
}
if(!selectGiroValido()){
validaciones.push("⦁ Seleccione un giro. ");
}
if(!selectCalificacionServicioValido()){
validaciones.push("⦁ Seleccione una calificación de servicio. ");
}
if(!selectEstadoValido()){
validaciones.push("⦁ Seleccione un estado. ");
}
if(!selectMunicipioValido()){
validaciones.push("⦁ Seleccione un municipio. ");
}
if(!selectColoniaValido()){
validaciones.push("⦁ Seleccione una colonia. ");
}
if(validaciones.length > 0){
alert("Campos del formulario sin llenar\n" + validaciones.join("\n"));
return;
}
// Preparar datos para envío
const formData = new FormData();
formData.append("id_candidato", idCandidato);
formData.append("id_pais", idPais);
formData.append("codigo_postal", codigoPostal);
formData.append("id_estado", idEstado);
formData.append("id_municipio", idMunicipio);
formData.append("id_colonia", idColonia);
formData.append("id_nivel", idNivel);
formData.append("id_giro", idGiro);
formData.append("nombre_empresa_institucion", nombreEmpresa);
formData.append("motivo_examen", motivoExamen);
formData.append("calificacion_servicio", calificacionServicio);
if (consentimientoPub) {
formData.append("consentimiento_pub", 1);
} else {
formData.append("consentimiento_pub", 0);
}
formData.append("fecha_salida", fechaSalida);
// TEST
//alert("FORMULARIO ENVIADO");
// TEST: Pintar en consola datos del formData
// for (let [key, value] of formData.entries()) {
// console.log(key + ": ", value);
// }
try {
const respuesta = await fetch('../controllers/RegistrarInfoCandidato.php', {
method: "POST",
body: formData,
});
const resultado = await respuesta.json();
if (resultado.estado === "exitoso") {
console.log(resultado.res);
alert('Se guardó la información correctamente');
//window.location.href = 'inicio.html';
} else if(resultado.estado === "error") {
console.error("RegistrarInfoCandidato.php: " + resultado.res);
alert("Ocurrió un error, intentelo más tarde.");
}
} catch (error) {
alert("Ocurrió un error, intentelo más tarde.");
console.error("Error en try-catch de fetch a RegistrarInfoCandidato: " + error.message);
}
});
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EVENTOS
});

View File

@ -1,78 +1,58 @@
async function recuperarCantidadGenero(tipoConsulta) { async function recuperarCantidadGenero(tipoConsulta, filtros = {}) {
try { try {
const response = await fetch("./php/graficos.php", { const response = await fetch("../controllers/graficos.php", {
method: "POST", method: "POST",
headers: { headers: { "Content-Type": "application/json" },
"Content-Type": "application/json", body: JSON.stringify({ tipoConsulta, ...filtros }),
},
body: JSON.stringify({ tipoConsulta }),
}); });
const data = await response.json(); const data = await response.json();
return data.cantidad || 0; return data.cantidad || 0;
} catch (error) { } catch (error) {
console.error("Error al recuperar datos:", error); console.error("Error al recuperar datos:", error);
return 0; return 0;
} }
} }
async function recuperarCantidadEdad(tipoConsulta) { async function recuperarCantidadEdad(tipoConsulta, filtros = {}) {
try { try {
const response = await fetch("./php/graficos.php", { const response = await fetch("../controllers/graficos.php", {
method: "POST", method: "POST",
headers: { headers: { "Content-Type": "application/json" },
"Content-Type": "application/json", body: JSON.stringify({ tipoConsulta, ...filtros }),
},
body: JSON.stringify({ tipoConsulta }),
}); });
const data = await response.json(); const data = await response.json();
return data.cantidad || 0; return data.cantidad || 0;
} catch (error) { } catch (error) {
console.error("Error al recuperar datos:", error); console.error("Error al recuperar datos:", error);
return 0; return 0;
} }
} }
async function recuperarCantidadEstado(tipoConsulta) { async function recuperarCantidadEstado(tipoConsulta, filtros = {}) {
try { try {
const response = await fetch("./php/graficos.php", { const response = await fetch("../controllers/graficos.php", {
method: "POST", method: "POST",
headers: { headers: { "Content-Type": "application/json" },
"Content-Type": "application/json", body: JSON.stringify({ tipoConsulta, ...filtros }),
},
body: JSON.stringify({ tipoConsulta }),
}); });
const data = await response.json(); const data = await response.json();
if (!Array.isArray(data)) throw new Error("La respuesta del backend no es un array.");
if (!Array.isArray(data)) { return data;
throw new Error("La respuesta del backend no es un array.");
}
return data;
} catch (error) { } catch (error) {
console.error("Error al recuperar datos de estados:", error); console.error("Error al recuperar datos de estados:", error);
return []; return [];
} }
} }
async function recuperarCantidadExamen(tipoConsulta) { async function recuperarCantidadExamen(tipoConsulta, filtros = {}) {
try { try {
const response = await fetch("./php/graficos.php", { const response = await fetch("../controllers/graficos.php", {
method: "POST", method: "POST",
headers: { headers: { "Content-Type": "application/json" },
"Content-Type": "application/json", body: JSON.stringify({ tipoConsulta, ...filtros }),
},
body: JSON.stringify({ tipoConsulta }),
}); });
const data = await response.json(); const data = await response.json();
if (!Array.isArray(data)) throw new Error("La respuesta del backend no es un array");
if (!Array.isArray(data)) {
throw new Error("La respuesta del backend no es un array");
}
return data; return data;
} catch (error) { } catch (error) {
console.error("Error al recuperar datos de examenes:", error); console.error("Error al recuperar datos de examenes:", error);
@ -80,64 +60,99 @@ async function recuperarCantidadExamen(tipoConsulta) {
} }
} }
async function recuperarCantidadFecha(tipoConsulta, filtros = {}) {
async function obtenerDatosEdades() { try {
const edad1 = await recuperarCantidadEdad("Menor de 18 años"); const response = await fetch("../controllers/graficos.php", {
const edad2 = await recuperarCantidadEdad("18 a 24 años"); method: "POST",
const edad3 = await recuperarCantidadEdad("25 a 34 años"); headers: { "Content-Type": "application/json" },
const edad4 = await recuperarCantidadEdad("35 a 44 años"); body: JSON.stringify({ tipoConsulta, ...filtros }),
const edad5 = await recuperarCantidadEdad("45 a 54 años"); });
const edad6 = await recuperarCantidadEdad("55 a 64 años"); const data = await response.json();
const edad7 = await recuperarCantidadEdad("65 años o más"); if (!Array.isArray(data)) throw new Error("La respuesta del backend no es un array.");
return data;
return [edad1, edad2, edad3, edad4, edad5, edad6]; } catch (error) {
console.error("Error al recuperar datos de fechas:", error);
return [];
}
} }
async function obtenerDatosEdades(filtros = {}) {
const edad1 = await recuperarCantidadEdad("Menor de 18 años", filtros);
const edad2 = await recuperarCantidadEdad("18 a 24 años", filtros);
const edad3 = await recuperarCantidadEdad("25 a 34 años", filtros);
const edad4 = await recuperarCantidadEdad("35 a 44 años", filtros);
const edad5 = await recuperarCantidadEdad("45 a 54 años", filtros);
const edad6 = await recuperarCantidadEdad("55 a 64 años", filtros);
const edad7 = await recuperarCantidadEdad("65 años o más", filtros);
return [edad1, edad2, edad3, edad4, edad5, edad6, edad7];
}
async function obtenerDatosGeneros() { async function obtenerDatosGeneros(filtros = {}) {
const femenino = await recuperarCantidadGenero("Femenino"); const femenino = await recuperarCantidadGenero("Femenino", filtros);
const masculino = await recuperarCantidadGenero("Masculino"); const masculino = await recuperarCantidadGenero("Masculino", filtros);
const noDefinido = await recuperarCantidadGenero("Prefiero no decirlo"); const noDefinido = await recuperarCantidadGenero("Prefiero no decirlo", filtros);
return [femenino, masculino, noDefinido]; return [femenino, masculino, noDefinido];
} }
async function obtenerDatosEstados() { async function obtenerDatosEstados(filtros = {}) {
try { try {
const estados = await recuperarCantidadEstado("Estados"); const estados = await recuperarCantidadEstado("Estados", filtros);
if (!Array.isArray(estados)) { if (!Array.isArray(estados)) {
console.error("Error: 'estados' no es un array. Verifica la respuesta del backend"); console.error("Error: 'estados' no es un array. Verifica la respuesta del backend");
return []; return [];
} }
const estadosValidos = estados.filter(estado => estado.estado && estado.cantidad !== undefined); const estadosValidos = estados.filter(estado => estado.estado && estado.cantidad !== undefined);
return estadosValidos;
return estadosValidos;
} catch (error) { } catch (error) {
console.error("Error al obtener datos de estados:", error); console.error("Error al obtener datos de estados:", error);
return []; return [];
} }
} }
async function obtenerDatosExamenes() { async function obtenerDatosExamenes(filtros = {}) {
try { try {
const examenes = await recuperarCantidadExamen("Examenes"); const examenes = await recuperarCantidadExamen("Examenes", filtros);
if (!Array.isArray(examenes)) { if (!Array.isArray(examenes)) {
console.error("Error: 'examenes' no es un array. Verifica la respuesta del backend"); console.error("Error: 'examenes' no es un array. Verifica la respuesta del backend");
return []; return [];
} }
const examenesValidos = examenes.filter(examen => examen.examen && examen.cantidad !== undefined); const examenesValidos = examenes.filter(examen => examen.examen && examen.cantidad !== undefined);
return examenesValidos;
return examenesValidos;
} catch (error) { } catch (error) {
console.error("Error al obtener datos de examenes:", error); console.error("Error al obtener datos de examenes:", error);
return []; return [];
} }
} }
async function obtenerDatosFechas(filtros = {}) {
try {
const fechas = await recuperarCantidadFecha("Fechas", filtros);
if (!Array.isArray(fechas) || !fechas.length) {
return [];
}
// Solo un objeto con la cantidad total
return fechas;
} catch (error) {
console.error("Error al obtener datos de fechas:", error);
return [];
}
}
function getFiltrosSeleccionados() {
return {
id_rango_edad: document.getElementById('id_rango_edad')?.value || "NULL",
id_genero: document.getElementById('id_genero')?.value || "NULL",
id_examen: document.getElementById('id_examen')?.value || "NULL",
fechaInicio: document.getElementById('date1')?.value || "",
fechaFin: document.getElementById('date2')?.value || ""
};
}
export { obtenerDatosGeneros, obtenerDatosEdades, obtenerDatosEstados, obtenerDatosExamenes }; export {
obtenerDatosGeneros,
obtenerDatosEdades,
obtenerDatosEstados,
obtenerDatosExamenes,
obtenerDatosFechas,
getFiltrosSeleccionados
};

View File

@ -163,10 +163,67 @@ allProgress.forEach(item=> {
import { obtenerDatosGeneros, obtenerDatosEdades, obtenerDatosEstados,obtenerDatosExamenes } from './funcionesGraficos.js'; import {
obtenerDatosGeneros,
obtenerDatosEdades,
obtenerDatosEstados,
obtenerDatosExamenes,
obtenerDatosFechas,
getFiltrosSeleccionados
} from './funcionesGraficos.js';
async function inicializarGrafico() { // Variables globales para los graficos
const [femenino, masculino, noDefinido] = await obtenerDatosGeneros(); let chartGenero = null;
let chartEdad = null;
let chartEstado = null;
let chartExamen = null;
let chartFecha = null;
// Controla si el filtro de fecha está activo
let filtroFechaActivo = false;
async function inicializarGraficoFecha(filtros) {
// Solo dibujar si ambas fechas están presentes y el filtro está activo
if (!filtroFechaActivo || !filtros.fechaInicio || !filtros.fechaFin) {
if (chartFecha) {
chartFecha.destroy();
chartFecha = null;
}
return;
}
const fechas = await obtenerDatosFechas(filtros);
if (!fechas.length) {
if (chartFecha) {
chartFecha.destroy();
chartFecha = null;
}
return;
}
// Solo un valor total
const cantidad = fechas[0].cantidad;
const label = `Del ${fechas[0].fechaInicio} al ${fechas[0].fechaFin}`;
const options = {
series: [{
name: 'Candidatos',
data: [cantidad]
}],
chart: { height: 350, type: 'bar' },
xaxis: { categories: [label] },
dataLabels: { enabled: true },
tooltip: { y: { formatter: val => val + " candidatos" } }
};
if (chartFecha) chartFecha.destroy();
chartFecha = new ApexCharts(document.querySelector("#chart5"), options);
chartFecha.render();
}
async function inicializarGrafico(filtros) {
const [femenino, masculino, noDefinido] = await obtenerDatosGeneros(filtros);
const options = { const options = {
series: [ series: [
@ -174,183 +231,132 @@ async function inicializarGrafico() {
{ name: 'Masculino', data: [masculino] }, { name: 'Masculino', data: [masculino] },
{ name: 'Prefiero no decirlo', data: [noDefinido] }, { name: 'Prefiero no decirlo', data: [noDefinido] },
], ],
chart: { chart: { height: 350, type: 'bar' },
height: 350, plotOptions: { bar: { horizontal: false, columnWidth: '55%', borderRadius: 5 } },
type: 'bar', dataLabels: { enabled: false },
}, xaxis: { categories: ['Géneros'] },
plotOptions: { tooltip: { y: { formatter: val => val + " personas" } }
bar: {
horizontal: false,
columnWidth: '55%',
borderRadius: 5,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: ['Géneros'],
},
tooltip: {
y: {
formatter: function (val) {
return val + " personas";
},
},
},
}; };
const chart = new ApexCharts(document.querySelector("#chart"), options); if (chartGenero) chartGenero.destroy();
chart.render(); chartGenero = new ApexCharts(document.querySelector("#chart"), options);
chartGenero.render();
} }
inicializarGrafico(); async function inicializarGrafico2(filtros) {
const [edad1, edad2, edad3, edad4, edad5, edad6, edad7] = await obtenerDatosEdades(filtros);
async function inicializarGrafico2() {
const [edad1,edad2,edad3,edad4,edad5,edad6,edad7] = await obtenerDatosEdades();
const options2 = { const options2 = {
series: [ series: [
{ name: 'Menor de 18 años', data: [edad1] }, { name: 'Menor de 18 años', data: [edad1] },
{ name: '18 a 24 años', data: [edad2] }, { name: '18 a 24 años', data: [edad2] },
{ name: '25 a 34 años', data: [edad3] }, { name: '25 a 34 años', data: [edad3] },
{ name: '35 a 44 años', data: [edad4] }, { name: '35 a 44 años', data: [edad4] },
{ name: '45 a 54 años', data: [edad5] }, { name: '45 a 54 años', data: [edad5] },
{ name: '55 a 64 años', data: [edad6] }, { name: '55 a 64 años', data: [edad6] },
{ name: '65 años o más', data: [edad7] }, { name: '65 años o más', data: [edad7] },
], ],
chart: { chart: { height: 350, type: 'bar' },
height: 350, plotOptions: { bar: { horizontal: false, columnWidth: '55%', borderRadius: 5 } },
type: 'bar', dataLabels: { enabled: false },
}, xaxis: { categories: ['Edades'] },
plotOptions: { tooltip: { y: { formatter: val => val + " Años" } }
bar: {
horizontal: false,
columnWidth: '55%',
borderRadius: 5,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: ['Edades'],
},
tooltip: {
y: {
formatter: function (val) {
return val + " Años";
},
},
},
}; };
const chart2 = new ApexCharts(document.querySelector("#chart2"), options2); if (chartEdad) chartEdad.destroy();
chart2.render(); chartEdad = new ApexCharts(document.querySelector("#chart2"), options2);
chartEdad.render();
} }
inicializarGrafico2(); async function inicializarGrafico3(filtros) {
const estados = await obtenerDatosEstados(filtros);
const seriesData = estados.map(estado => ({
name: estado.estado,
data: [estado.cantidad]
}));
async function inicializarGrafico3() { const options3 = {
try { series: seriesData,
const estados = await obtenerDatosEstados(); chart: { height: 350, type: 'bar' },
plotOptions: { bar: { horizontal: false, columnWidth: '55%', borderRadius: 5 } },
dataLabels: { enabled: false },
xaxis: { categories: estados.map(estado => estado.estado) },
tooltip: { y: { formatter: val => val + " personas" } }
};
if (!Array.isArray(estados)) { if (chartEstado) chartEstado.destroy();
console.error("Error: 'estados' no es un array. Verifica la funcion obtenerDatosEstados"); chartEstado = new ApexCharts(document.querySelector("#chart3"), options3);
return; chartEstado.render();
} }
const seriesData = estados.map(estado => ({ async function inicializarGrafico4(filtros) {
name: estado.estado, const examenes = await obtenerDatosExamenes(filtros);
data: [estado.cantidad]
}));
const options3 = { const seriesData = examenes.map(examen => ({
series: seriesData, name: examen.examen,
chart: { data: [examen.cantidad]
height: 350, }));
type: 'bar',
},
plotOptions: {
bar: {
horizontal: false,
columnWidth: '55%',
borderRadius: 5,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: estados.map(estado => estado.estado), // categorias en el eje X
},
tooltip: {
y: {
formatter: function (val) {
return val + " personas";
},
},
},
};
const chart3 = new ApexCharts(document.querySelector("#chart3"), options3); const options4 = {
chart3.render(); series: seriesData,
} catch (error) { chart: { height: 350, type: 'bar' },
console.error("Error al inicializar el gráfico 3:", error); plotOptions: { bar: { horizontal: false, columnWidth: '55%', borderRadius: 5 } },
dataLabels: { enabled: false },
xaxis: { categories: examenes.map(examen => examen.examen) },
tooltip: { y: { formatter: val => val + " examenes" } }
};
if (chartExamen) chartExamen.destroy();
chartExamen = new ApexCharts(document.querySelector("#chart4"), options4);
chartExamen.render();
}
async function actualizarTodosLosGraficos() {
// Si el filtro de fecha está activo, se pasan las fechas, si no, se limpian
let filtros = getFiltrosSeleccionados();
if (!filtroFechaActivo) {
filtros.fechaInicio = "";
filtros.fechaFin = "";
} }
await inicializarGrafico(filtros);
await inicializarGrafico2(filtros);
await inicializarGrafico3(filtros);
await inicializarGrafico4(filtros);
await inicializarGraficoFecha(filtros);
} }
inicializarGrafico3(); // Espera a que el DOM esté listo antes de agregar eventos
document.addEventListener('DOMContentLoaded', () => {
// Solo combos, NO fechas
['id_rango_edad', 'id_genero', 'id_examen'].forEach(id => {
const el = document.getElementById(id);
if (el) el.addEventListener('change', actualizarTodosLosGraficos);
});
async function inicializarGrafico4() { // Botón buscar para fechas
try { const btnBuscar = document.getElementById('buscar');
const examenes = await obtenerDatosExamenes(); if (btnBuscar) {
btnBuscar.addEventListener('click', () => {
if (!Array.isArray(examenes)) { const date1 = document.getElementById('date1').value;
console.error("Error: 'examenes' no es un array. Verifica la función obtenerDatosExamenes"); const date2 = document.getElementById('date2').value;
return; // Solo activa el filtro si ambas fechas están presentes
} filtroFechaActivo = !!(date1 && date2);
actualizarTodosLosGraficos();
const seriesData = examenes.map(examen => ({ });
name: examen.examen,
data: [examen.cantidad]
}));
const options4 = {
series: seriesData,
chart: {
height: 350,
type: 'bar',
},
plotOptions: {
bar: {
horizontal: false,
columnWidth: '55%',
borderRadius: 5,
},
},
dataLabels: {
enabled: false,
},
xaxis: {
categories: examenes.map(examen => examen.examen), // categorías en el eje X
},
tooltip: {
y: {
formatter: function (val) {
return val + " examenes";
},
},
},
};
const chart4 = new ApexCharts(document.querySelector("#chart4"), options4);
chart4.render();
} catch (error) {
console.error("Error al inicializar el grafico 4:", error);
} }
}
// Botón limpiar para quitar filtro de fecha
const btnLimpiar = document.getElementById('limpiar');
if (btnLimpiar) {
btnLimpiar.addEventListener('click', () => {
document.getElementById('date1').value = '';
document.getElementById('date2').value = '';
filtroFechaActivo = false;
actualizarTodosLosGraficos();
});
}
inicializarGrafico4(); filtroFechaActivo = false;
actualizarTodosLosGraficos();
});ñ

View File

@ -13,21 +13,24 @@ formulario.addEventListener("submit", async (event) => {
data.append("contrasena", contrasena); data.append("contrasena", contrasena);
try { try {
const respuestaPeticion = await fetch('controladores/login.php', { const respuestaPeticion = await fetch("controllers/LoginController.php", {
method: "POST", method: "POST",
body: data, body: data,
}); });
const verificarCredenciales = await respuestaPeticion.json(); const respuesta = await respuestaPeticion.json();
if (verificarCredenciales.loginExitoso) { if (respuesta.estado === 'exitoso') {
window.location.href = 'inicio.html'; window.location.href = 'views/inicio.html';
} else { } else if(respuesta.estado === 'error') {
notificacion.textContent = "Usuario y/o contraseña incorrectos"; 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"; notificacion.style.display = "block";
} }
} catch (error) { } catch (error) {
notificacion.textContent = notificacion.textContent = "Lo sentimos, el servicio no está disponible por el momento";
"Lo sentimos, el servicio no está disponible por el momento"; console.error(error)
} }
}); });

59
js/tarjetasPromedio.js Normal file
View File

@ -0,0 +1,59 @@
async function recuperarCantidadGenero(tipoConsulta) {
try {
const response = await fetch("../controllers/graficos.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ tipoConsulta }),
});
const data = await response.json();
return data.cantidad || 0;
} catch (error) {
console.error("Error al recuperar datos:", error);
return 0;
}
}
async function obtenerPromedioPorGenero() {
// Obtener conteos de cada género
const femenino = await recuperarCantidadGenero("Femenino");
const masculino = await recuperarCantidadGenero("Masculino");
const noDefinido = await recuperarCantidadGenero("Prefiero no decirlo");
// Suma total de personas
const total = femenino + masculino + noDefinido;
// Evitar división por cero
if (total === 0) {
actualizarTarjetas(0, 0, 0);
return;
}
// Calcular el promedio (cantidad / total de registros)
// Aquí promedio es la proporción simple de cada género dentro del total
const promedioFemenino = femenino / total;
const promedioMasculino = masculino / total;
const promedioNoDefinido = noDefinido / total;
// Actualizar las tarjetas con los valores calculados
actualizarTarjetas(promedioFemenino, promedioMasculino, promedioNoDefinido);
}
// Función para actualizar las tarjetas en el DOM
function actualizarTarjetas(promF, promM, promND) {
// Multiplicamos por 100 para mostrar el promedio como número decimal simple.
// Aquí simplemente mostramos el promedio como número decimal con 2 decimales
document.querySelector("#card-femenino h2").textContent = promF.toFixed(2)+ "%";;
document.querySelector("#card-masculino h2").textContent = promM.toFixed(2) + "%";;
document.querySelector("#card-nodefinido h2").textContent = promND.toFixed(2) + "%";;
}
// Ejecutar cuando el DOM esté listo
document.addEventListener("DOMContentLoaded", obtenerPromedioPorGenero);

316
models/CandidatoModel.php Normal file
View File

@ -0,0 +1,316 @@
<?php
require_once __DIR__ . '/../config/Database.php';
class CandidatoModel {
private $conn;
public function __construct() {
$this->conn = Database::getInstance();
}
/**
* Registra la información de un candidato y su fecha de salida
*
* @param int $id_candidato ID del candidato
* @param int $id_pais ID del país
* @param int|null $id_estado ID del estado
* @param int|null $id_municipio ID del municipio
* @param int|null $id_colonia ID de la colonia
* @param int $id_nivel ID del nivel
* @param int $id_giro ID del giro
* @param string $nombre_empresa_institucion Nombre de la empresa o institución
* @param string $motivo_examen Motivo del examen
* @param int $calificacion_servicio Calificación del servicio
* @param int $consentimiento_pub Consentimiento de publicación
* @param string $fecha_salida Fecha de salida
* @return array Retorna un array asociativo con las claves "estado" y "mensaje"
*/
public function registrarInfoCandidatos(
$id_candidato,
$id_pais,
$id_estado,
$id_municipio,
$id_colonia,
$id_nivel,
$id_giro,
$nombre_empresa_institucion,
$motivo_examen,
$calificacion_servicio,
$consentimiento_pub,
$fecha_salida
) {
try {
$id_pais = (int)$id_pais;
// Si el país no es México (ID 1), se asignan valores nulos a los campos de ubicación
if ($id_pais !== 1) {
$id_estado = null;
$id_municipio = null;
$id_colonia = null;
} else {
$id_estado = (int)$id_estado;
$id_municipio = (int)$id_municipio;
$id_colonia = (int)$id_colonia;
}
$sql = "INSERT INTO info_candidatos (
id_candidato, id_pais, id_estado, id_municipio, id_colonia,
id_nivel, id_giro, nombre_empresa_institucion, motivo_examen,
calificacion_servicio, consentimiento_pub
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
return [
"estado" => "error",
"mensaje" => "Error en la preparación de la consulta: " . $this->conn->error
];
}
$stmt->bind_param(
"iiiiiiissii",
$id_candidato,
$id_pais,
$id_estado,
$id_municipio,
$id_colonia,
$id_nivel,
$id_giro,
$nombre_empresa_institucion,
$motivo_examen,
$calificacion_servicio,
$consentimiento_pub
);
if (!$stmt->execute()) {
return [
"estado" => "error",
"mensaje" => "Error al insertar datos del candidato: " . $stmt->error
];
}
$stmt->close();
// Registrar fecha de salida
$resultadoFecha = $this->registrarFechaSalida($id_candidato, $fecha_salida);
if (isset($resultadoFecha["estado"]) && $resultadoFecha["estado"] === "error") {
return $resultadoFecha; // Propagar el error desde registrarFechaSalida
}
// Retornar éxito
return [
"estado" => "exitoso",
"mensaje" => $id_candidato
];
} catch (Exception $e) {
return [
"estado" => "error",
"mensaje" => "Error en el registro: " . $e->getMessage()
];
}
}
/**
* Registra la fecha de salida de un candidato
*
* @param int $id_candidato ID del candidato
* @param string $fecha_salida Fecha de salida
* @return array Retorna un array asociativo con las claves "estado" y "mensaje"
*/
private function registrarFechaSalida($id_candidato, $fecha_salida) {
try {
// Si no hay fecha de salida, retornar éxito sin hacer nada
if (empty($fecha_salida)) {
return [
"estado" => "exitoso",
"mensaje" => "No se registró fecha de salida"
];
}
// Consulta update
$sql = "UPDATE candidato SET fecha_salida = ? WHERE id_candidato = ?";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
return [
"estado" => "error",
"mensaje" => "Error en la preparación de la consulta de fecha: " . $this->conn->error
];
}
$stmt->bind_param("si",$fecha_salida,$id_candidato);
if (!$stmt->execute()) {
return [
"estado" => "error",
"mensaje" => "Error al registrar fecha de salida: " . $stmt->error
];
}
$stmt->close();
return [
"estado" => "exitoso",
"mensaje" => "Fecha de salida registrada correctamente"
];
} catch (Exception $e) {
return [
"estado" => "error",
"mensaje" => "Error al registrar fecha de salida: " . $e->getMessage()
];
}
}
/**
* Insertar un nuevo candidato en la base de datos.
* @param string $nombres Nombres del candidato.
* @param string $primer_apellido Primer apellido del candidato.
* @param string $segundo_apellido Segundo apellido del candidato.
* @param string $correo Correo electrónico del candidato.
* @param string $telefono Teléfono del candidato.
* @param int $id_examen ID del examen asociado al candidato.
* @param int $id_tipo_id ID del tipo de identificación del candidato.
* @param int $id_rango_edad ID del rango de edad del candidato.
* @param int $id_genero ID del género del candidato.
*/
public function registrarCandidato(
$nombres,
$primer_apellido,
$segundo_apellido,
$correo,
$telefono,
$id_examen,
$id_tipo_id,
$id_rango_edad,
$id_genero
) {
$sql = "INSERT INTO candidato (nombres, primer_apellido, segundo_apellido, correo, telefono, id_examen, id_tipo_id, id_rango_edad, id_genero) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
throw new Exception("Error en la preparación de la consulta: " . $this->conn->error);
}
$stmt->bind_param(
"sssssiiii",
$nombres,
$primer_apellido,
$segundo_apellido,
$correo,
$telefono,
$id_examen,
$id_tipo_id,
$id_rango_edad,
$id_genero
);
if (!$stmt->execute()) {
throw new Exception("Error al insertar candidato: " . $stmt->error);
}
$insertId = $stmt->insert_id;
$stmt->close();
return $insertId;
}
/**
* Verificar si ya existe un registro de información del candidato en la base de datos.
* @param int $id_candidato ID del candidato.
* @return bool true si existe un registro, false en caso contrario.
*/
public function verificarRegistroInfoCandidato($id_candidato) {
$sql = "SELECT COUNT(*) as count FROM info_candidatos WHERE id_candidato = ?";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
throw new Exception("Error en la preparación de la consulta: " . $this->conn->error);
}
$stmt->bind_param("i", $id_candidato);
if (!$stmt->execute()) {
throw new Exception("Error al ejecutar la consulta: " . $stmt->error);
}
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$stmt->close();
return $row['count'] > 0;
}
public function existeIdCandidato($id_candidato) {
try {
$sql = "SELECT COUNT(*) as count FROM candidato WHERE id_candidato = ?";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
return [
"estado" => "error",
"mensaje" => "Error en la preparación de la consulta: " . $this->conn->error
];
}
$stmt->bind_param("i", $id_candidato);
if (!$stmt->execute()) {
return [
"estado" => "error",
"mensaje" => "Error al ejecutar la consulta: " . $stmt->error
];
}
$result = $stmt->get_result();
$stmt->close();
$row = $result->fetch_assoc();
if($row['count'] > 0){
return [
"estado" => "exitoso",
"mensaje" => "ID de candidato existe"
];
} else {
return [
"estado" => "error",
"mensaje" => "ID de candidato no existe"
];
}
} catch (Exception $e) {
return [
"estado" => "error",
"mensaje" => "Error al verificar ID de candidato: " . $e->getMessage()
];
}
}
public function obtenerCandidatoPorId($id_candidato) {
$sql = "SELECT * FROM candidato WHERE id_candidato = ?";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
throw new Exception("Error en la preparación de la consulta: " . $this->conn->error);
}
$stmt->bind_param("i", $id_candidato);
if (!$stmt->execute()) {
throw new Exception("Error al ejecutar la consulta: " . $stmt->error);
}
$result = $stmt->get_result();
$candidato = $result->fetch_assoc();
$stmt->close();
return $candidato;
}
public function obtenerInfoCandidatoPorId($id_candidato) {
$sql = "SELECT * FROM info_candidatos WHERE id_candidato = ?";
$stmt = $this->conn->prepare($sql);
if ($stmt === false) {
throw new Exception("Error en la preparación de la consulta: " . $this->conn->error);
}
$stmt->bind_param("i", $id_candidato);
if (!$stmt->execute()) {
throw new Exception("Error al ejecutar la consulta: " . $stmt->error);
}
$result = $stmt->get_result();
$info = $result->fetch_assoc();
$stmt->close();
return $info;
}
}
?>

143
models/CatalogosModel.php Normal file
View File

@ -0,0 +1,143 @@
<?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";
$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";
$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";
$result = $this->conn->query($sql);
$empresas = [];
while($row = $result->fetch_assoc()){
$empresas[] = $row;
}
return $empresas;
}
}
?>

92
models/UsuarioModel.php Normal file
View File

@ -0,0 +1,92 @@
<?php
require_once __DIR__ . '/../config/Database.php';
class UsuarioModel {
private $conn;
public function __construct() {
$this->conn = Database::getInstance();
}
/**
* Registrar un nuevo usuario
*/
public function registrarUsuario($usuario, $contrasena){
// Hashear contraseña
$contrasena_hash = password_hash($contrasena, PASSWORD_DEFAULT);
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("INSERT INTO usuario (usuario, contrasena) VALUES (?, ?)");
$stmt->bind_param("ss", $usuario, $contrasena_hash);
if (!$stmt->execute()) {
throw new Exception("Error al registrar usuario: " . $stmt->error);
}
$stmt->close();
}
/**
* Iniciar sesión de un usuario
* @param string $usuario Nombre de usuario
* @param string $contrasena Contraseña del usuario
* @return bool true si el inicio de sesión es exitoso, false en caso contrario
*/
public function iniciarSesion($usuario, $contrasena) {
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("SELECT contrasena FROM usuario WHERE usuario = ?");
$stmt->bind_param("s", $usuario);
if (!$stmt->execute()) {
throw new Exception("Error al iniciar sesión: " . $stmt->error);
}
// Obtener el resultado
$stmt->store_result();
if ($stmt->num_rows == 0) {
return false; // Usuario no encontrado
}
// Obtener el hash de la contraseña
$stmt->bind_result($contrasena_hash);
$stmt->fetch();
// Verificar la contraseña
if (password_verify($contrasena, $contrasena_hash)) {
return true; // Inicio de sesión exitoso
} else {
return false; // Contraseña incorrecta
}
}
public function obtenerUsuarios() {
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("SELECT usuario FROM usuario");
if (!$stmt->execute()) {
throw new Exception("Error al obtener nombres de usuarios: " . $stmt->error);
}
// Obtener el resultado
$result = $stmt->get_result();
$usuarios = [];
while ($row = $result->fetch_assoc()) {
$usuarios[] = $row;
}
return $usuarios;
}
public function eliminarUsuario($id){
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("DELETE FROM usuario WHERE id = ?");
$stmt->bind_param("i", $id);
if (!$stmt->execute()) {
throw new Exception("Error al eliminar usuario: " . $stmt->error);
}
$stmt->close();
}
}
?>

20
pruebaSesion.php Normal file
View File

@ -0,0 +1,20 @@
<?php
session_start();
if (!isset($_SESSION['autenticado']) || $_SESSION['autenticado'] !== true) {
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>

7
test.php Normal file
View File

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

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.

After

Width:  |  Height:  |  Size: 257 KiB

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="es-mx">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Formulario de registro</title>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="text-bg-light" style="height: 70px;"><img src="assets/img/logo-lania.png" style="height: 65px;margin: 0px 10px;" draggable="false" alt="Laboratorio Nacional de Informática Avanzada"></div>
<div class="card">
<div class="card-body" style="margin: 0px 30px;">
<!-- ==================== Formulario ==================== -->
<form style="margin: 0px 50px;" id="formulario-datos-basicos" action="" method="POST">
<h3>Registro</h3>
<label class="form-label" for="nombres" style="margin: 10px 0px 5px;">Nombre</label>
<input class="border rounded-pill shadow-sm form-control" type="text" id="nombres" placeholder="Nombre/s" required="">
<label class="form-label" for="primer_apellido" style="margin: 10px 0px 5px;">Primer apellido</label>
<input class="border rounded-pill shadow-sm form-control" type="text" id="primer_apellido" placeholder="Primer apellido" required="">
<label class="form-label" for="segundo_apellido" style="margin: 10px 0px 5px;">Segundo apellido</label>
<input class="border rounded-pill shadow-sm form-control" type="text" id="segundo_apellido" placeholder="Segundo apellido">
<label class="form-label" for="correo" style="margin: 10px 0px 5px;">Correo electrónico</label>
<input class="border rounded-pill shadow-sm form-control" type="email" id="correo" required="" placeholder="usuario@ejemplo.com">
<label class="form-label" for="telefono" style="margin: 10px 0px 5px;">Teléfono</label>
<input class="border rounded-pill shadow-sm form-control" type="tel" id="telefono" placeholder="10 digitos de su número de teléfono" minlength="9" maxlength="10" required="">
<label class="form-label" for="id_examen" style="margin: 10px 0px 5px;">Examen</label>
<select class="border rounded-pill shadow-sm form-select" id="id_examen" required="">
<option value="NULL">Seleccione una opción</option>
</select>
<label class="form-label" for="id_tipo_id" style="margin: 10px 0px 5px;">Tipo de identificación</label>
<select class="border rounded-pill shadow-sm form-select" id="id_tipo_id" required="">
<option value="NULL">Seleccione una opción</option>
</select>
<label class="form-label" for="id_rango_edad" style="margin: 10px 0px 5px;">Rango de edad</label>
<select class="border rounded-pill shadow-sm form-select" id="id_rango_edad" required="">
<option value="NULL">Seleccione una opción</option>
</select>
<label class="form-label" for="id_genero" style="margin: 10px 0px 5px;">Género</label>
<select class="border rounded-pill shadow-sm form-select" id="id_genero" required="">
<option value="NULL">Seleccione una opción</option>
<option value="1">Masculino</option>
<option value="2">Femenino</option>
<option value="3">Prefiero no decir</option>
</select>
<input class="btn border rounded-pill border-3 border-primary-subtle shadow btn-lg btn-primary" type="submit" value="Enviar" style="margin: 15px 0px;" name="btnEnviar">
</form>
<!-- ==================== Fin del formulario ==================== -->
<div id="mensaje-error"></div>
</div>
</div>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/formulario-candidato.js"></script>
</body>
</html>

View File

@ -0,0 +1,107 @@
<?php
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id_candidato'])){
// Verifica si se ha pasado el id_candidato como parámetro GET
$id_candidato = $_GET['id_candidato'];
// Si no se pasa el id_candidato
//header("Location: inicio.html");
//exit();
} else { // TEST //
$id_candidato = 0;
} // TEST \\
?>
<!DOCTYPE html>
<html data-bs-theme="light" lang="es-mx">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>formsLania</title>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="text-bg-light" style="height: 70px;"><img src="assets/img/logo-lania.png" style="height: 65px;margin: 0px 10px;"></div>
<div class="card">
<div class="card-body" style="margin: 0px 30px;">
<!-- ==================== Formulario ==================== -->
<form style="margin: 0px 50px;" id="formulario-datos-extendido" method="post" action="#">
<input class="border rounded-pill shadow-sm form-control" type="number" id="id_candidato" value="<?php echo $id_candidato; ?>">
<h4>Información geográfica</h4>
<label class="form-label" for="id_pais" style="margin: 10px 0px 5px;">País</label>
<select class="border rounded-pill shadow-sm form-select" id="id_pais" value="NULL" required="">
<option value="NULL">Seleccione un país</option>
<option value="1">México</option>
<option value="2">Otro</option>
</select>
<label class="form-label" for="codigo_postal" style="margin: 10px 0px 5px;">Código postal</label>
<input class="border rounded-pill shadow-sm form-control" type="number" id="codigo_postal" placeholder="Introduzca su código postal" style="margin: 0px 0px;" maxlength="5" disabled="">
<button class="btn btn-sm bg-white border rounded-pill border-3 border-dark-subtle shadow-sm" type="button" id="buscarBtn" style="margin: 5px 0px;" disabled="">Buscar</button>
<label class="form-label" for="id_estado" style="margin: 10px 0px 5px;display: grid;">Estado</label>
<select class="border rounded-pill shadow-sm form-select" id="id_estado" disabled="">
<option value="NULL">Seleccione su estado</option>
</select>
<label class="form-label" for="id_municipio" style="margin: 10px 0px 5px;">Municipio</label>
<select class="border rounded-pill shadow-sm form-select" id="id_municipio" disabled="">
<option value="NULL">Seleccione su municipio</option>
</select>
<label class="form-label" for="id_colonia" style="margin: 10px 0px 5px;">Colonia</label>
<select class="border rounded-pill shadow-sm form-select" id="id_colonia" disabled="">
<option value="NULL">Seleccione su colonia</option>
</select>
<h4 style="margin: 20px 0px 0px;">Información académica/laboral</h4>
<label class="form-label" for="id_nivel" style="margin: 10px 0px 5px;">Nivel de estudios</label>
<select class="border rounded-pill shadow-sm form-select" id="id_nivel" required="">
<option value="NULL">Seleccione su nivel de estudios</option>
</select>
<label class="form-label" for="nombre_empresa" style="margin: 10px 0px 5px;">Nombre de su empresa o institución</label>
<input class="border rounded-pill form-control" type="text" id="nombre_empresa" list="sugerencias_ei" placeholder="Introduzca el nombre de su empresa o institución" required="">
<datalist id="sugerencias_ei"></datalist>
<label class="form-label" for="id_giro" style="margin: 10px 0px 5px;">Giro de su empresa o institución</label>
<select class="border rounded-pill shadow-sm form-select" id="id_giro" required="">
<option value="NULL">Seleccione una opción</option>
</select>
<label class="form-label" for="motivo_examen" style="margin: 10px 0px 5px;">Motivo de examen</label>
<select class="border rounded-pill shadow-sm form-select" id="motivo_examen" required="">
<option value="NULL">Seleccione una opción</option>
<option value="Lorem Ipsum">Lorem Ipsum</option>
<option value="Adcnjcafgrf">Adcnjcafgrf</option>
</select>
<h4 style="margin: 20px 0px 0px;">Calificación del servicio</h4>
<label class="form-label" for="calificacion_servicio" style="margin: 10px 0px 5px;">¿Qué tan satisfecho está con nuestra institución, considerando la calidad de las instalaciones, la atención del personal y el proceso de aplicación del examen?</label>
<select class="border rounded-pill shadow-sm form-select" id="calificacion_servicio" required="">
<option value="NULL">Seleccione una opción</option>
<option value="1">&#128577 Muy insatisfecho</option>
<option value="2">&#128533 Insatisfecho</option>
<option value="3">&#128528 Neutral</option>
<option value="4">&#128578 Satisfecho</option>
<option value="5">&#128528 Muy satisfecho</option>
</select>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="consentimiento_pub" value="1" checked>
<label class="form-check-label" for="consentimiento_pub">Consiento que mis datos personales sean tratados de conformidad con los términos y condiciones informados en el presente <a href="#">aviso de privacidad</a>.</label>
</div>
<input class="btn border rounded-pill border-3 border-primary-subtle shadow btn-lg btn-primary" type="submit" style="margin: 15px 0px;" value="Enviar" name="btnEnviar">
</form>
<!-- ==================== Fin del formulario ==================== -->
</div>
</div>
<script src="../js/formulario-datos-candidato.js"></script>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

View File

@ -4,7 +4,8 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <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 href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>
<link rel="stylesheet" href="css/inicio.css"> <link rel="stylesheet" href="../css/inicio.css">
<title>AdminSite</title> <title>AdminSite</title>
</head> </head>
<body> <body>
@ -27,13 +28,13 @@
</li> </li>
<li><a href="#"><i class='bx bxs-chart icon' ></i> Charts</a></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><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 class="divider" data-text="tablas y formularios">Tablas y formularios</li>
<li><a href="#"><i class='bx bx-table icon' ></i> Tables</a></li> <li><a href="#"><i class='bx bx-table icon' ></i> Tablas</a></li>
<li> <li>
<a href="#"><i class='bx bxs-notepad icon' ></i> Formularios <i class='bx bx-chevron-right icon-right' ></i></a> <a href="#"><i class='bx bxs-notepad icon' ></i> Formularios <i class='bx bx-chevron-right icon-right' ></i></a>
<ul class="side-dropdown"> <ul class="side-dropdown">
<li><a href="form_datos_basicos.html">Datos Básicos</a></li> <li><a href="formulario-candidato.html">Registro de candidato</a></li>
<li><a href="form_datos_extendidos.html">Datos Extendidos</a></li> <li><a href="formulario-datos-candidato.php">Datos de candidato</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -85,52 +86,109 @@
<li class="divider">/</li> <li class="divider">/</li>
<li><a href="#" class="active">Dashboard</a></li> <li><a href="#" class="active">Dashboard</a></li>
</ul> </ul>
<div class="info-data">
<!--Añadido nuevo -->
<div class="select-data">
<div class="card"> <div class="card">
<div class="head"> <div class="head">
<div> <i class='bx bx-trending-up icon'></i>
<h2>1500</h2> </div>
<p>Traffic</p>
</div>
<i class='bx bx-trending-up icon' ></i> <div style="display: flex; gap: 20px; margin: 10px 0;">
<!-- Campo: Edad -->
<div style="flex: 1;">
<label class="form-label" for="id_rango_edad">Edad</label>
<select class="border rounded-pill shadow-sm form-select" id="id_rango_edad" required>
<option value="NULL">Seleccione una opción</option>
</select>
</div>
<!-- Campo: Género -->
<div style="flex: 1;">
<label class="form-label" for="id_genero" style="margin: 10px 0px 5px;">Género</label>
<select class="border rounded-pill shadow-sm form-select" id="id_genero" required="">
<option value="NULL">Seleccione una opción</option>
<option value="1">Masculino</option>
<option value="2">Femenino</option>
<option value="3">Prefiero no decir</option>
</select>
</div>
<div style="flex: 1;">
<label class="form-label" for="id_examen" style="margin: 10px 0px 5px;">Examen</label>
<select class="border rounded-pill shadow-sm form-select" id="id_examen" required="">
<option value="NULL">Seleccione una opción</option>
</select>
</div> </div>
<span class="progress" data-value="40%"></span>
<span class="label">40%</span>
</div> </div>
<div class="card">
<h2>Fecha</h2>
<h3>Ingresa una fecha de inicio:</h3>
<br>
<input type="date" id="date1" name="date1">
<h3>Ingresa una fecha de final:</h3>
<input type="date" id="date2" name="date2">
<br>
<button type="button" id="buscar">Buscar</button>
<button type="button" id="limpiar">Limpiar</button>
<br>
<div class="content-data">
<div class="head"> <div class="head">
<div> <h3>Resultado de registros en el rango de fecha ingresado</h3>
<h2>234</h2> <div class="menu">
<p>Sales</p>
</div> </div>
<i class='bx bx-trending-down icon down' ></i>
</div> </div>
<span class="progress" data-value="60%"></span> <div class="chart">
<span class="label">60%</span> <div id="chart5"></div>
</div>
<div class="card">
<div class="head">
<div>
<h2>465</h2>
<p>Pageviews</p>
</div>
<i class='bx bx-trending-up icon' ></i>
</div> </div>
<span class="progress" data-value="30%"></span>
<span class="label">30%</span>
</div>
<div class="card">
<div class="head">
<div>
<h2>235</h2>
<p>Visitors</p>
</div>
<i class='bx bx-trending-up icon' ></i>
</div>
<span class="progress" data-value="80%"></span>
<span class="label">80%</span>
</div> </div>
</div> </div>
<div>
<br>
<h3>Promedio de géneros:</h3>
<div class="info-data">
<div class="card" id="card-femenino">
<div class="head">
<div style="display: flex; align-items: center; gap: 8px;">
<i class='bx bx-female' style="font-size: 24px; color: #e91e63;"></i>
<div>
<h2>0</h2>
<p>Femenino</p>
</div>
</div>
</div>
</div>
<div class="card" id="card-masculino">
<div class="head">
<div style="display: flex; align-items: center; gap: 8px;">
<i class='bx bx-male' style="font-size: 24px; color: #2196f3;"></i>
<div>
<h2>0</h2>
<p>Masculino</p>
</div>
</div>
</div>
</div>
<div class="card" id="card-nodefinido">
<div class="head">
<div style="display: flex; align-items: center; gap: 8px;">
<i class='bx bx-male' style="font-size: 24px; color: black;"></i>
<div>
<h2>0</h2>
<p>Prefiero no decirlo</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="data"> <div class="data">
<div class="content-data"> <div class="content-data">
<div class="head"> <div class="head">
@ -197,13 +255,16 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</main> </main>
<!-- MAIN --> <!-- MAIN -->
</section> </section>
<!-- NAVBAR --> <!-- NAVBAR -->
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script type="module" src="js/inicio.js"></script> <script type="module" src="../js/inicio.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script> <script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
<script src="../js/formulario-candidato.js"></script>
<script src="../js/tarjetasPromedio.js"></script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="es-mx">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>formsLania</title>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="text-bg-light" style="height: 70px;"><img src="assets/img/logo-lania.png" style="height: 65px;margin: 0px 10px;"></div>
<div class="card">
<div class="card-body" style="margin: 0px 30px;">
<h1 class="text-center">¡Gracias por registrarse!</h1>
</div>
</div>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>