solucion de conlictos

This commit is contained in:
Hectorgh24 2025-05-27 10:03:42 -06:00
commit bd62a804f1
46 changed files with 4300 additions and 602 deletions

File diff suppressed because one or more lines are too long

View File

@ -44,7 +44,7 @@ CREATE TABLE `candidato` (
CONSTRAINT `candidato_ibfk_2` FOREIGN KEY (`id_tipo_id`) REFERENCES `tipo_identificacion` (`id_tipo_id`),
CONSTRAINT `candidato_ibfk_3` FOREIGN KEY (`id_rango_edad`) REFERENCES `rango_edad` (`id_rango_edad`),
CONSTRAINT `candidato_ibfk_4` FOREIGN KEY (`id_genero`) REFERENCES `genero` (`id_genero`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -53,6 +53,7 @@ CREATE TABLE `candidato` (
LOCK TABLES `candidato` WRITE;
/*!40000 ALTER TABLE `candidato` DISABLE KEYS */;
INSERT INTO `candidato` VALUES (3,'2025-05-18 02:03:30','2025-05-17 20:11:43','Nombre1','ApellidoP1','ApellidoM1','correo1@gmail.com','7248914109',2,4,5,3),(4,'2025-05-18 02:03:30','2025-05-17 20:12:32','Nombre2','ApellidoP2','ApellidoM2','correo2@gmail.com','4479063420',7,4,5,3),(5,'2025-05-18 02:03:30',NULL,'Nombre3','ApellidoP3','ApellidoM3','correo3@gmail.com','6064719620',13,5,4,3),(6,'2025-05-18 02:03:30',NULL,'Nombre4','ApellidoP4','ApellidoM4','correo4@gmail.com','6659734795',14,2,2,2),(7,'2025-05-18 02:03:30',NULL,'Nombre5','ApellidoP5','ApellidoM5','correo5@gmail.com','4512563940',5,1,4,2);
/*!40000 ALTER TABLE `candidato` ENABLE KEYS */;
UNLOCK TABLES;
@ -196,7 +197,7 @@ CREATE TABLE `giro` (
LOCK TABLES `giro` WRITE;
/*!40000 ALTER TABLE `giro` DISABLE KEYS */;
INSERT INTO `giro` VALUES (13,'Agricultura y Alimentación'),(10,'Construcción'),(5,'Educación'),(12,'Energía y Recursos Naturales'),(3,'Finanzas'),(2,'Gobierno'),(9,'Logística y Transporte'),(8,'Manufactura'),(14,'Medios de Comunicación y Entretenimiento'),(15,'Otros'),(7,'Retail'),(4,'Salud'),(1,'Tecnologías de la Información'),(6,'Telecomunicaciones'),(11,'Turismo y Hospitalidad');
INSERT INTO `giro` VALUES (13,'Agricultura y alimentación'),(10,'Construcción'),(5,'Educación'),(12,'Energía y recursos Naturales'),(3,'Finanzas'),(2,'Gobierno'),(9,'Logística y transporte'),(8,'Manufactura'),(14,'Medios de comunicación y entretenimiento'),(15,'Otros'),(7,'Retail'),(4,'Salud'),(1,'Tecnologías de la información'),(6,'Telecomunicaciones'),(11,'Turismo y hospitalidad');
/*!40000 ALTER TABLE `giro` ENABLE KEYS */;
UNLOCK TABLES;
@ -216,7 +217,7 @@ CREATE TABLE `info_candidatos` (
`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,
`id_motivo_examen` int NOT NULL,
`calificacion_servicio` tinyint NOT NULL,
`consentimiento_pub` tinyint NOT NULL,
PRIMARY KEY (`id_candidato`),
@ -226,13 +227,15 @@ CREATE TABLE `info_candidatos` (
KEY `id_colonia` (`id_colonia`),
KEY `id_nivel` (`id_nivel`),
KEY `id_giro` (`id_giro`),
KEY `id_motivo_examen` (`id_motivo_examen`),
CONSTRAINT `info_candidatos_ibfk_1` FOREIGN KEY (`id_candidato`) REFERENCES `candidato` (`id_candidato`) ON DELETE CASCADE,
CONSTRAINT `info_candidatos_ibfk_2` FOREIGN KEY (`id_pais`) REFERENCES `paises` (`id`),
CONSTRAINT `info_candidatos_ibfk_3` FOREIGN KEY (`id_estado`) REFERENCES `estados` (`id`),
CONSTRAINT `info_candidatos_ibfk_4` FOREIGN KEY (`id_municipio`) REFERENCES `municipios` (`id`),
CONSTRAINT `info_candidatos_ibfk_5` FOREIGN KEY (`id_colonia`) REFERENCES `colonias` (`id`),
CONSTRAINT `info_candidatos_ibfk_6` FOREIGN KEY (`id_nivel`) REFERENCES `nivel_estudio` (`id_nivel`),
CONSTRAINT `info_candidatos_ibfk_7` FOREIGN KEY (`id_giro`) REFERENCES `giro` (`id_giro`)
CONSTRAINT `info_candidatos_ibfk_7` FOREIGN KEY (`id_giro`) REFERENCES `giro` (`id_giro`),
CONSTRAINT `info_candidatos_ibfk_8` FOREIGN KEY (`id_motivo_examen`) REFERENCES `motivo_examen` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
@ -242,9 +245,35 @@ CREATE TABLE `info_candidatos` (
LOCK TABLES `info_candidatos` WRITE;
/*!40000 ALTER TABLE `info_candidatos` DISABLE KEYS */;
INSERT INTO `info_candidatos` VALUES (3,2,NULL,NULL,NULL,5,5,'Universidad Veracruzana',5,4,1),(4,1,30,30093,30093534,5,1,'Univesidad de Xalapa',8,4,0);
/*!40000 ALTER TABLE `info_candidatos` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `motivo_examen`
--
DROP TABLE IF EXISTS `motivo_examen`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `motivo_examen` (
`id` int NOT NULL AUTO_INCREMENT,
`descripcion` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `descripcion` (`descripcion`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `motivo_examen`
--
LOCK TABLES `motivo_examen` WRITE;
/*!40000 ALTER TABLE `motivo_examen` DISABLE KEYS */;
INSERT INTO `motivo_examen` VALUES (5,'Cambio de carrera o sector laboral'),(4,'Crecimiento personal'),(3,'Incremento salarial'),(7,'Mantenerse actualizado'),(1,'Mejora u oportunidad laboral'),(6,'Requisito académico'),(2,'Requisito de la empresa o puesto'),(8,'Requisito para obtener otra certificación de nivel superior');
/*!40000 ALTER TABLE `motivo_examen` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `municipios`
--
@ -297,6 +326,110 @@ INSERT INTO `nivel_estudio` VALUES (3,'Bachillerato'),(7,'Doctorado'),(5,'Licenc
/*!40000 ALTER TABLE `nivel_estudio` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `oauth_access_tokens`
--
DROP TABLE IF EXISTS `oauth_access_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `oauth_access_tokens` (
`access_token` varchar(255) NOT NULL,
`client_id` varchar(80) NOT NULL,
`user_id` varchar(80) DEFAULT NULL,
`expires` timestamp NOT NULL,
`scope` varchar(4000) DEFAULT NULL,
PRIMARY KEY (`access_token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `oauth_access_tokens`
--
LOCK TABLES `oauth_access_tokens` WRITE;
/*!40000 ALTER TABLE `oauth_access_tokens` DISABLE KEYS */;
/*!40000 ALTER TABLE `oauth_access_tokens` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `oauth_clients`
--
DROP TABLE IF EXISTS `oauth_clients`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `oauth_clients` (
`client_id` varchar(80) NOT NULL,
`client_secret` varchar(80) NOT NULL,
`redirect_uri` varchar(2000) DEFAULT NULL,
`grant_types` varchar(80) DEFAULT NULL,
`scope` varchar(4000) DEFAULT NULL,
`user_id` varchar(80) DEFAULT NULL,
PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `oauth_clients`
--
LOCK TABLES `oauth_clients` WRITE;
/*!40000 ALTER TABLE `oauth_clients` DISABLE KEYS */;
INSERT INTO `oauth_clients` VALUES ('testclient','testpass',NULL,'client_credentials','basic',NULL);
/*!40000 ALTER TABLE `oauth_clients` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `oauth_refresh_tokens`
--
DROP TABLE IF EXISTS `oauth_refresh_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `oauth_refresh_tokens` (
`refresh_token` varchar(40) NOT NULL,
`client_id` varchar(80) NOT NULL,
`user_id` varchar(80) DEFAULT NULL,
`expires` timestamp NOT NULL,
`scope` varchar(4000) DEFAULT NULL,
PRIMARY KEY (`refresh_token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `oauth_refresh_tokens`
--
LOCK TABLES `oauth_refresh_tokens` WRITE;
/*!40000 ALTER TABLE `oauth_refresh_tokens` DISABLE KEYS */;
/*!40000 ALTER TABLE `oauth_refresh_tokens` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `oauth_scopes`
--
DROP TABLE IF EXISTS `oauth_scopes`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `oauth_scopes` (
`scope` varchar(80) NOT NULL,
`is_default` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`scope`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `oauth_scopes`
--
LOCK TABLES `oauth_scopes` WRITE;
/*!40000 ALTER TABLE `oauth_scopes` DISABLE KEYS */;
INSERT INTO `oauth_scopes` VALUES ('basic',1);
/*!40000 ALTER TABLE `oauth_scopes` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `paises`
--
@ -358,7 +491,7 @@ CREATE TABLE `tipo_identificacion` (
`descripcion` varchar(50) NOT NULL,
PRIMARY KEY (`id_tipo_id`),
UNIQUE KEY `descripcion` (`descripcion`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -367,7 +500,7 @@ CREATE TABLE `tipo_identificacion` (
LOCK TABLES `tipo_identificacion` WRITE;
/*!40000 ALTER TABLE `tipo_identificacion` DISABLE KEYS */;
INSERT INTO `tipo_identificacion` VALUES (5,'Cédula Profesional'),(3,'CURP'),(1,'INE'),(6,'Licencia de Conducir'),(7,'Otro'),(2,'Pasaporte'),(4,'RFC');
INSERT INTO `tipo_identificacion` VALUES (5,'Cartilla militar'),(1,'Credencial de estudiante'),(2,'INE'),(4,'Licencia de conducir'),(3,'Pasaporte');
/*!40000 ALTER TABLE `tipo_identificacion` ENABLE KEYS */;
UNLOCK TABLES;
@ -384,7 +517,7 @@ CREATE TABLE `usuario` (
`contrasena` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `usuario` (`usuario`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -393,6 +526,7 @@ CREATE TABLE `usuario` (
LOCK TABLES `usuario` WRITE;
/*!40000 ALTER TABLE `usuario` DISABLE KEYS */;
INSERT INTO `usuario` VALUES (1,'root','$2y$10$NMfiaNc1VVvEO0PUKV2T2OM8ORI48Kt/dWNRmGrSsZeNm/04yaRaG'),(2,'admin','$2y$10$2kp7nZ.l5dQxuss4YvFZ1.Mzj5XUdf2ephfWoJZ4n8XwfOODD..6i');
/*!40000 ALTER TABLE `usuario` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@ -405,4 +539,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-04-26 13:29:23
-- Dump completed on 2025-05-17 20:36:49

View File

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

View File

@ -37,6 +37,11 @@ CREATE TABLE examen (
-- IMPORTAR BASE DE DATOS DE INEGI
-- Catalogo de motivos
CREATE TABLE motivo_examen (
id INT AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(255) NOT NULL UNIQUE
);
-- 1. TABLA CANDIDATO (datos básicos)
CREATE TABLE candidato (
@ -75,7 +80,7 @@ CREATE TABLE info_candidatos (
id_giro TINYINT UNSIGNED NOT NULL,
nombre_empresa_institucion VARCHAR(150) NOT NULL,
motivo_examen VARCHAR(255) NOT NULL,
id_motivo_examen INT NOT NULL,
calificacion_servicio TINYINT NOT NULL,
consentimiento_pub TINYINT NOT NULL,
@ -87,7 +92,8 @@ CREATE TABLE info_candidatos (
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)
FOREIGN KEY (id_giro) REFERENCES giro(id_giro),
FOREIGN KEY (id_motivo_examen) REFERENCES motivo_examen(id)
) ENGINE=InnoDB;
CREATE TABLE usuario (
@ -97,6 +103,43 @@ CREATE TABLE usuario (
) ENGINE=InnoDB;
-- OAuth 2.0
CREATE TABLE oauth_clients (
client_id VARCHAR(80) NOT NULL,
client_secret VARCHAR(80) NOT NULL,
redirect_uri VARCHAR(2000) DEFAULT NULL,
grant_types VARCHAR(80) DEFAULT NULL,
scope VARCHAR(4000) DEFAULT NULL,
user_id VARCHAR(80) DEFAULT NULL,
PRIMARY KEY (client_id)
);
CREATE TABLE oauth_access_tokens (
access_token VARCHAR(255) NOT NULL,
client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(80) DEFAULT NULL,
expires TIMESTAMP NOT NULL,
scope VARCHAR(4000) DEFAULT NULL,
PRIMARY KEY (access_token)
);
CREATE TABLE oauth_refresh_tokens (
refresh_token VARCHAR(40) NOT NULL,
client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(80) DEFAULT NULL,
expires TIMESTAMP NOT NULL,
scope VARCHAR(4000) DEFAULT NULL,
PRIMARY KEY (refresh_token)
);
CREATE TABLE oauth_scopes (
scope VARCHAR(80) NOT NULL,
is_default BOOLEAN,
PRIMARY KEY (scope)
);
-- DML -------------------------------------------------------------------------------------
-- Inserción catalogo "genero":
@ -117,13 +160,11 @@ INSERT INTO rango_edad (id_rango_edad, descripcion) VALUES
-- 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');
(1, 'Credencial de estudiante'),
(2, 'INE'),
(3, 'Pasaporte'),
(4, 'Licencia de conducir'),
(5, 'Cartilla militar');
-- Inserción catalogo "nivel_estudio":
INSERT INTO nivel_estudio (id_nivel, descripcion) VALUES
@ -138,7 +179,7 @@ INSERT INTO nivel_estudio (id_nivel, descripcion) VALUES
-- 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'),
(1, 'Tecnologías de la información'),
(2, 'Gobierno'),
(3, 'Finanzas'),
(4, 'Salud'),
@ -146,12 +187,12 @@ INSERT INTO giro (id_giro, descripcion) VALUES
(6, 'Telecomunicaciones'),
(7, 'Retail'),
(8, 'Manufactura'),
(9, 'Logística y Transporte'),
(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'),
(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:
@ -175,9 +216,18 @@ INSERT INTO examen (id_examen, nombre_examen) VALUES
-- 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);
-- Inserts para poblar la tabla motivos_examen_certificacion
INSERT INTO motivo_examen (descripcion) VALUES
('Mejora u oportunidad laboral'),
('Requisito de la empresa o puesto'),
('Incremento salarial'),
('Crecimiento personal'),
('Cambio de carrera o sector laboral'),
('Requisito académico'),
('Mantenerse actualizado'),
('Requisito para obtener otra certificación de nivel superior');
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);
INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id)
VALUES ('testclient', 'testpass', NULL, 'client_credentials', 'basic', NULL);
INSERT INTO oauth_scopes (scope, is_default) VALUES ('basic', true);

View File

@ -96,6 +96,7 @@ class CandidatoController {
return false;
}
}
}
// Instanciar el modelo al cargar el controlador

View File

@ -39,6 +39,10 @@ class CatalogosController {
return self::$catalogosModel->obtenerNombresEmpresasInstituciones();
}
public static function obtenerMotivosExamen(){
return self::$catalogosModel->obtenerMotivosExamen();
}
}
CatalogosController::inicializar();
@ -88,5 +92,11 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obt
echo json_encode($result);
}
if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['obtener']) && $_GET['obtener'] === 'motivos') {
header('Content-Type: application/json');
$result = CatalogosController::obtenerMotivosExamen();
echo json_encode($result);
}
?>

View File

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

View File

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

View File

@ -21,32 +21,31 @@ class UsuarioController{
}
public static function existeUsuario($usuario){
$usuarios = self::obtenerUsuarios();
foreach ($usuarios as $u) {
if ($u['usuario'] === $usuario) {
return true; // El usuario ya existe
$usuario = self::$usuarioModel->buscarUsuario($usuario);
if ( isset($usuario['usuario']) ) {
return true;
} else {
return false;
}
}
return false; // El usuario no existe
}
public static function registrarUsuario($usuario, $contrasena){
public static function crearUsuario($usuario, $contrasena){
if ( self::existeUsuario($usuario) ) {
echo "El usuario ya existe.";
return;
return [
'estado' => 'error',
'mensaje' => 'El usuario ya existe.'
];
} else {
return self::$usuarioModel->crearUsuario($usuario, $contrasena);
}
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;
public static function eliminarUsuario($id_usuario){
return self::$usuarioModel->eliminarUsuario($id_usuario);
}
self::$usuarioModel->eliminarUsuario($usuario);
echo "Usuario: ${usuario} eliminado exitosamente.";
public static function actualizarUsuario($id, $usuario, $contrasena){
return self::$usuarioModel->actualizarUsuario($id, $usuario, $contrasena);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

38
css/consultar-api.css Normal file
View File

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

2106
font/bootstrap-icons.css vendored Normal file

File diff suppressed because it is too large Load Diff

5
font/bootstrap-icons.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

69
js/actualizar-usuario.js Normal file
View File

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

362
js/consultar-api.js Normal file
View File

@ -0,0 +1,362 @@
// ==========================================
// CONFIGURACIÓN Y CONSTANTES
// ==========================================
const CONFIG = {
API_BASE_URL: 'http://localhost:5000/api',
FILE_PREFIX: 'candidatos'
};
// ==========================================
// ESTADO DE LA APLICACIÓN
// ==========================================
class AppState {
constructor() {
this.accessToken = '';
this.candidatesData = [];
}
setAccessToken(token) {
this.accessToken = token;
}
getAccessToken() {
return this.accessToken;
}
setCandidatesData(data) {
this.candidatesData = data;
}
getCandidatesData() {
return this.candidatesData;
}
hasToken() {
return !!this.accessToken;
}
hasData() {
return this.candidatesData.length > 0;
}
}
// ==========================================
// SERVICIOS API
// ==========================================
class ApiService {
static async getAccessToken(clientId, clientSecret) {
const formData = new URLSearchParams();
formData.append('grant_type', 'client_credentials');
formData.append('client_id', clientId);
formData.append('client_secret', clientSecret);
const response = await fetch(`${CONFIG.API_BASE_URL}/oauth/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Error en la autenticación');
}
return await response.json();
}
static async getCandidates(accessToken) {
if (!accessToken) {
throw new Error('No hay token de acceso disponible');
}
const response = await fetch(`${CONFIG.API_BASE_URL}/candidatos/obtenerCandidatos`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Error al obtener candidatos');
}
return await response.json();
}
}
// ==========================================
// UTILIDADES
// ==========================================
class Utils {
static getCurrentDateTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
return `${year}${month}${day}_${hours}${minutes}`;
}
static flattenObject(obj, prefix = '') {
const flattened = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const newKey = prefix ? `${prefix}_${key}` : key;
if (obj[key] !== null && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
Object.assign(flattened, Utils.flattenObject(obj[key], newKey));
} else {
flattened[newKey] = obj[key];
}
}
}
return flattened;
}
static convertToCSV(data) {
if (!data.length) return '';
const flatData = data.map(candidato => Utils.flattenObject(candidato));
const headers = Object.keys(flatData[0]);
const csvHeaders = headers.join(',');
const csvRows = flatData.map(row =>
headers.map(header => {
const value = row[header];
if (typeof value === 'string' && (value.includes(',') || value.includes('\n') || value.includes('"'))) {
return `"${value.replace(/"/g, '""')}"`;
}
return value || '';
}).join(',')
);
return [csvHeaders, ...csvRows].join('\n');
}
static downloadFile(content, filename, mimeType) {
const blob = new Blob([content], { type: mimeType });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
URL.revokeObjectURL(link.href);
}
}
// ==========================================
// CONTROLADOR DE DESCARGA
// ==========================================
class DownloadController {
constructor(appState) {
this.appState = appState;
}
downloadJSON() {
if (!this.appState.hasData()) {
alert('No hay datos para descargar');
return;
}
const dataStr = JSON.stringify(this.appState.getCandidatesData(), null, 2);
const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.json`;
Utils.downloadFile(dataStr, filename, 'application/json');
}
downloadCSV() {
if (!this.appState.hasData()) {
alert('No hay datos para descargar');
return;
}
const csvData = Utils.convertToCSV(this.appState.getCandidatesData());
const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.csv`;
Utils.downloadFile(csvData, filename, 'text/csv;charset=utf-8;');
}
downloadExcel() {
if (!this.appState.hasData()) {
alert('No hay datos para descargar');
return;
}
const flatData = this.appState.getCandidatesData().map(candidato => Utils.flattenObject(candidato));
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.json_to_sheet(flatData);
const cols = Object.keys(flatData[0]).map(() => ({ wch: 15 }));
ws['!cols'] = cols;
XLSX.utils.book_append_sheet(wb, ws, 'Candidatos');
const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.xlsx`;
XLSX.writeFile(wb, filename);
}
}
// ==========================================
// CONTROLADOR DE UI
// ==========================================
class UIController {
constructor() {
this.elements = {
tokenType: document.getElementById('token-type'),
expiresIn: document.getElementById('expires-in'),
tokenSection: document.getElementById('token-section'),
noTokenMessage: document.getElementById('no-token-message'),
downloadSection: document.getElementById('download-section'),
recordsCount: document.getElementById('records-count'),
candidatesSection: document.getElementById('candidates-section'),
candidatesTableBody: document.getElementById('candidates-table-body'),
apiResponseSection: document.getElementById('api-response-section'),
apiResponse: document.getElementById('api-response'),
errorSection: document.getElementById('error-section'),
errorMessage: document.getElementById('error-message'),
noResultsMessage: document.getElementById('no-results-message')
};
}
displayTokenInfo(tokenData) {
this.elements.tokenType.textContent = tokenData.token_type;
this.elements.expiresIn.textContent = tokenData.expires_in;
this.elements.tokenSection.classList.remove('hidden');
this.elements.noTokenMessage.classList.add('hidden');
console.log('Token obtenido y almacenado de forma segura');
}
displayCandidates(candidates) {
this.elements.apiResponse.textContent = JSON.stringify(candidates, null, 2);
this.elements.apiResponseSection.classList.remove('hidden');
this.elements.downloadSection.classList.remove('hidden');
this.elements.recordsCount.textContent = candidates.length;
this._fillCandidatesTable(candidates);
this.elements.candidatesSection.classList.remove('hidden');
this.elements.noResultsMessage.classList.add('hidden');
}
_fillCandidatesTable(candidates) {
this.elements.candidatesTableBody.innerHTML = '';
candidates.forEach(candidato => {
const dem = candidato.demograficos || {};
const ubi = dem.ubicacion || {};
const form = candidato.formacion || {};
const exam = candidato.examen || {};
const exp = candidato.experiencia_servicio || {};
const fechas = candidato.fechas || {};
const row = document.createElement('tr');
row.innerHTML = `
<td>${candidato.id_candidato ?? ''}</td>
<td>${candidato.nombre_completo ?? ''}</td>
<td>${candidato.contacto?.correo ?? ''}</td>
<td>${candidato.contacto?.telefono ?? ''}</td>
<td>${dem.genero ?? ''}</td>
<td>${dem.rango_edad ?? ''}</td>
<td>${dem.tipo_identificacion ?? ''}</td>
<td>${ubi.pais ?? ''}</td>
<td>${ubi.estado ?? ''}</td>
<td>${ubi.municipio ?? ''}</td>
<td>${ubi.colonia ?? ''}</td>
<td>${form.nivel_estudio ?? ''}</td>
<td>${form.giro ?? ''}</td>
<td>${form.nombre_empresa_institucion ?? ''}</td>
<td>${exam.id_examen ?? ''}</td>
<td>${exam.nombre_examen ?? ''}</td>
<td>${exam.motivo ?? ''}</td>
<td>${exp.calificacion_servicio ?? ''}</td>
<td>${exp.consentimiento_publicidad !== undefined ? (exp.consentimiento_publicidad ? 'Sí' : 'No') : ''}</td>
<td>${fechas.entrada ?? ''}</td>
<td>${fechas.salida ?? ''}</td>
`;
this.elements.candidatesTableBody.appendChild(row);
});
}
showError(message) {
this.elements.errorMessage.textContent = message;
this.elements.errorSection.classList.remove('hidden');
this.elements.noResultsMessage.classList.add('hidden');
}
hideAllMessages() {
this.elements.errorSection.classList.add('hidden');
this.elements.apiResponseSection.classList.add('hidden');
this.elements.downloadSection.classList.add('hidden');
}
}
// ==========================================
// CONTROLADOR PRINCIPAL DE LA APLICACIÓN
// ==========================================
class AppController {
constructor() {
this.appState = new AppState();
this.uiController = new UIController();
this.downloadController = new DownloadController(this.appState);
this._initializeEventListeners();
}
_initializeEventListeners() {
// OAuth form
document.getElementById('oauth-form').addEventListener('submit', (e) => this._handleOAuthSubmit(e));
// Get candidates button
document.getElementById('get-candidates').addEventListener('click', () => this._handleGetCandidates());
// Download buttons
document.getElementById('download-json').addEventListener('click', () => this.downloadController.downloadJSON());
document.getElementById('download-csv').addEventListener('click', () => this.downloadController.downloadCSV());
document.getElementById('download-excel').addEventListener('click', () => this.downloadController.downloadExcel());
}
async _handleOAuthSubmit(e) {
e.preventDefault();
const clientId = document.getElementById('clientId').value;
const clientSecret = document.getElementById('clientSecret').value;
this.uiController.hideAllMessages();
try {
const response = await ApiService.getAccessToken(clientId, clientSecret);
this.appState.setAccessToken(response.access_token);
this.uiController.displayTokenInfo(response);
} catch (error) {
this.uiController.showError(`Error al obtener token, las credenciales son incorrectas: ${error.message}`);
}
}
async _handleGetCandidates() {
this.uiController.hideAllMessages();
try {
const candidates = await ApiService.getCandidates(this.appState.getAccessToken());
this.appState.setCandidatesData(candidates);
this.uiController.displayCandidates(candidates);
} catch (error) {
this.uiController.showError(`Error al obtener candidatos: ${error.message}`);
}
}
}
// ==========================================
// INICIALIZACIÓN DE LA APLICACIÓN
// ==========================================
document.addEventListener('DOMContentLoaded', function() {
new AppController();
});

35
js/control-candidato.js Normal file
View File

@ -0,0 +1,35 @@
document.addEventListener("DOMContentLoaded" , function() {
const tabla = document.querySelector('table');
tabla.addEventListener("click", function(evento) {
const botonEliminar = evento.target.closest(".boton-eliminar");
if (botonEliminar) {
// Obtener id del candidato a eliminar usando dataset
const idCandidatoEliminar = botonEliminar.dataset.idCandidato;
// Mostrar un mensaje de confirmación antes de eliminar
if (!confirm("¿Desea eliminar al candidato " + idCandidatoEliminar + "?")) {
return;
}
const data = new FormData();
data.append("id_candidato", idCandidatoEliminar);
fetch('../controllers/eliminarCandidato.php', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(data => {
alert(data.mensaje);
location.reload();
})
.catch((error) => {
console.error('Error:', error);
});
}
});
});

34
js/control-usuario.js Normal file
View File

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

69
js/crear-usuario.js Normal file
View File

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

View File

@ -9,12 +9,14 @@ document.addEventListener("DOMContentLoaded", function () {
const coloniaSelect = document.getElementById("id_colonia");
const giroSelect = document.getElementById("id_giro");
const nivelEstudioSelect = document.getElementById("id_nivel");
const motivoExamenSelect = document.getElementById("motivo_examen");
const selectCalificacionServicio = document.getElementById("calificacion_servicio");
const dataListEmpresasInstituciones = document.getElementById("sugerencias_ei");
llenarSelectGiro();
llenarSelectNivelesEstudio();
llenarDataListEmpresasInstituciones();
llenarSelectMotivoExamen();
// FUNCIONES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function llenarSelectGiro() {
@ -72,6 +74,39 @@ document.addEventListener("DOMContentLoaded", function () {
console.error("llenarSelectNivelesEstudio(): Error en la solicitud. ", error);
});
}
//##################################################################################################################
function llenarSelectMotivoExamen() {
// URL para la solicitud
let url = "../controllers/CatalogosController.php?obtener=motivos";
// 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("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 motivos al elemento select
data.forEach(row => {
motivoExamenSelect.innerHTML += "<option value='" + row.id + "'>" + row.descripcion + "</option>";
});
} else {
console.log("llenarSelectMotivoExamen(): No se encontraron datos.");
}
})
.catch(error => {
console.error("llenarSelectMotivoExamen(): ", error);
});
}
// #################################################################################################################
function llenarDataListEmpresasInstituciones(){
let url = "../controllers/CatalogosController.php?obtener=empresasinstituciones";
@ -260,7 +295,7 @@ document.addEventListener("DOMContentLoaded", function () {
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 motivoExamen = document.getElementById('motivo_examen').value;
const calificacionServicio = document.getElementById('calificacion_servicio').value;
const consentimientoPub = document.getElementById('consentimiento_pub').checked;
@ -324,9 +359,9 @@ document.addEventListener("DOMContentLoaded", function () {
//alert("FORMULARIO ENVIADO");
//TEST: Pintar en consola datos del formData
// for (let [key, value] of formData.entries()) {
// console.log(key + ": ", value);
// }
for (let [key, value] of formData.entries()) {
console.log(key + ": ", value);
}
try {
const respuesta = await fetch('../controllers/RegistrarInfoCandidato.php', {
@ -339,7 +374,7 @@ document.addEventListener("DOMContentLoaded", function () {
if (resultado.estado === "exitoso") {
console.log(resultado.res);
alert('Se guardó la información correctamente');
//window.location.href = 'inicio.html';
window.location.href = 'pantalla-salida-form.html';
} else if(resultado.estado === "error") {
console.error("RegistrarInfoCandidato.php: " + resultado.res);
alert("Ocurrió un error, intentelo más tarde.");

View File

@ -1,6 +1,6 @@
async function recuperarCantidadGenero(tipoConsulta, filtros = {}) {
try {
const response = await fetch("../controllers/graficos.php", {
const response = await fetch("/controllers/graficosController.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tipoConsulta, ...filtros }),
@ -15,7 +15,7 @@ async function recuperarCantidadGenero(tipoConsulta, filtros = {}) {
async function recuperarCantidadEdad(tipoConsulta, filtros = {}) {
try {
const response = await fetch("../controllers/graficos.php", {
const response = await fetch("/controllers/graficosController.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tipoConsulta, ...filtros }),
@ -30,7 +30,7 @@ async function recuperarCantidadEdad(tipoConsulta, filtros = {}) {
async function recuperarCantidadEstado(tipoConsulta, filtros = {}) {
try {
const response = await fetch("../controllers/graficos.php", {
const response = await fetch("/controllers/graficosController.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tipoConsulta, ...filtros }),
@ -46,7 +46,7 @@ async function recuperarCantidadEstado(tipoConsulta, filtros = {}) {
async function recuperarCantidadExamen(tipoConsulta, filtros = {}) {
try {
const response = await fetch("../controllers/graficos.php", {
const response = await fetch("/controllers/graficosController.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tipoConsulta, ...filtros }),

View File

@ -18,17 +18,24 @@ formulario.addEventListener("submit", async (event) => {
body: data,
});
// const respuesta = await respuestaPeticion.json();
const respuesta = await respuestaPeticion.json();
if (respuesta.estado === 'exitoso') {
window.location.href = 'views/inicio.html';
} else if(respuesta.estado === 'error') {
notificacion.textContent = respuesta.mensaje;
if(respuesta.res){ // Si existe respuesta.res hubo un error y se imprime en consola
console.error(respuesta.res)
}
notificacion.style.display = "block";
} else {
notificacion.textContent = "Lo sentimos, el servicio no está disponible por el momento";
console.error("No se recibió la respuesta esperada del servidor");
}
} catch (error) {
notificacion.textContent = "Lo sentimos, el servicio no está disponible por el momento";
console.error(error)

160
js/sidebar-navbar.js Normal file
View File

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

View File

@ -1,7 +1,7 @@
async function recuperarCantidadGenero(tipoConsulta) {
try {
const response = await fetch("../controllers/graficos.php", {
const response = await fetch("../controllers/graficosController.php", {
method: "POST",
headers: {
"Content-Type": "application/json",

View File

@ -21,7 +21,7 @@ class CandidatoModel {
* @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 $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
@ -56,7 +56,7 @@ class CandidatoModel {
$sql = "INSERT INTO info_candidatos (
id_candidato, id_pais, id_estado, id_municipio, id_colonia,
id_nivel, id_giro, nombre_empresa_institucion, motivo_examen,
id_nivel, id_giro, nombre_empresa_institucion, id_motivo_examen,
calificacion_servicio, consentimiento_pub
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
@ -69,7 +69,7 @@ class CandidatoModel {
}
$stmt->bind_param(
"iiiiiiissii",
"iiiiiiisiii",
$id_candidato,
$id_pais,
$id_estado,
@ -311,6 +311,54 @@ class CandidatoModel {
return $info;
}
/**
* Obtiene información de los candidatos que no han llenado el segundo formulario
* @return array
*/
public function obtenerCandidatosSinFechaSalida(){
$sql = "SELECT id_candidato, nombres, primer_apellido, segundo_apellido, fecha_entrada FROM lania_cc.candidato WHERE fecha_salida IS NULL ORDER BY fecha_entrada";
try {
$result = $this->conn->query($sql);
} catch (Exception $e) {
return [
"estado" => "error",
"mensaje" => $e->getMessage()
];
}
// Si no hay registros pendientes
if($result->num_rows == 0){
return [
"estado" => "exitoso",
"mensaje" => "No hay registros pendientes"
];
} else {
return $result->fetch_all(MYSQLI_ASSOC);
}
}
public function eliminarCandidato($id_candidato){
$sql = "DELETE 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 eliminar el candidato: " . $stmt->error
];
}
$stmt->close();
return [
"estado" => "exitoso",
"mensaje" => "Candidato eliminado correctamente."
];
}
}
?>

View File

@ -99,7 +99,7 @@ class Catalogos{
* @return array
*/
public function obtenerRangosEdad(){
$sql = "SELECT id_rango_edad, descripcion FROM rango_edad";
$sql = "SELECT id_rango_edad, descripcion FROM rango_edad ORDER BY id_rango_edad";
$result = $this->conn->query($sql);
$rangos = [];
@ -115,7 +115,7 @@ class Catalogos{
* @return array
*/
public function obtenerNivelesEstudio(){
$sql = "SELECT id_nivel, descripcion FROM nivel_estudio";
$sql = "SELECT id_nivel, descripcion FROM nivel_estudio ORDER BY id_nivel";
$result = $this->conn->query($sql);
$niveles = [];
@ -127,7 +127,7 @@ class Catalogos{
}
public function obtenerNombresEmpresasInstituciones(){
$sql = "SELECT DISTINCT nombre_empresa_institucion FROM info_candidatos";
$sql = "SELECT DISTINCT nombre_empresa_institucion FROM info_candidatos ORDER BY nombre_empresa_institucion";
$result = $this->conn->query($sql);
$empresas = [];
@ -138,6 +138,18 @@ class Catalogos{
return $empresas;
}
public function obtenerMotivosExamen(){
$sql = "SELECT id, descripcion FROM motivo_examen ORDER BY descripcion";
$result = $this->conn->query($sql);
$motivos = [];
while($row = $result->fetch_assoc()){
$motivos[] = $row;
}
return $motivos;
}
}
?>

View File

@ -11,80 +11,160 @@ class UsuarioModel {
/**
* Registrar un nuevo usuario
* @param string $usuario Nombre de usuario
* @param string $contrasena Contraseña del usuario
* @return array
*/
public function registrarUsuario($usuario, $contrasena){
public function crearUsuario($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);
return [
'estado' => 'error',
'mensaje' => 'Error al registrar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario ' . $usuario . ' registrado exitosamente.'
];
}
public function actualizarUsuario($id, $usuario, $contrasena){
// Hashear contraseña
$contrasena_hash = password_hash($contrasena, PASSWORD_DEFAULT);
$stmt = $this->conn->prepare("UPDATE usuario SET usuario = ?, contrasena = ? WHERE id = ?");
$stmt->bind_param("ssi", $usuario, $contrasena_hash, $id);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al actualizar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario ' . $usuario .' actualizado exitosamente.'
];
}
/**
* Iniciar sesión de un usuario
* @param string $usuario Nombre de usuario
* @param string $contrasena Contraseña del usuario
* @return bool true si el inicio de sesión es exitoso, false en caso contrario
* @return array
*/
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);
return [
'estado' => 'error',
'mensaje' => 'Error al iniciar sesión, intentelo más tarde.',
'res' => $stmt->error
];
}
// Obtener el resultado
$stmt->store_result();
if ($stmt->num_rows == 0) {
return false; // Usuario no encontrado
return [
'estado' => 'error',
'mensaje' => 'Usuario o contraseña incorrectos.'
];
}
// 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
return [
'estado' => 'exitoso',
'mensaje' => 'Inicio de sesión exitoso.'
];
} else {
return false; // Contraseña incorrecta
return [
'estado' => 'error',
'mensaje' => 'Usuario o contraseña incorrectos.'
];
}
}
public function obtenerUsuarios() {
// Preparar la consulta mysql usando msqli
$stmt = $this->conn->prepare("SELECT usuario FROM usuario");
$stmt = $this->conn->prepare("SELECT id, usuario FROM usuario");
if (!$stmt->execute()) {
throw new Exception("Error al obtener nombres de usuarios: " . $stmt->error);
return [
'estado' => 'error',
'mensaje' => 'Error al obtener usuarios: ' . $stmt->error
];
}
// Obtener el resultado
$result = $stmt->get_result();
$usuarios = [];
while ($row = $result->fetch_assoc()) {
$usuarios[] = $row;
// Si no hay resultados, retornar un array con estado y mensaje
if ($result->num_rows == 0) {
return [
'estado' => 'error',
'mensaje' => 'No hay usuarios registrados.'
];
}
return $usuarios;
return $result->fetch_all(MYSQLI_ASSOC);
}
public function buscarUsuario($usuario) {
$stmt = $this->conn->prepare("SELECT id, usuario FROM usuario WHERE usuario = ?");
$stmt->bind_param("s", $usuario);
if (!$stmt->execute()) {
return [
'estado' => 'error',
'mensaje' => 'Error al verificar usuario: ' . $stmt->error
];
}
$stmt->store_result();
// Si no hay resultados, retornar un array con estado y mensaje
if ($stmt->num_rows == 0) {
return [
'estado' => 'exitoso',
'mensaje' => 'No existe el usuario.'
];
} else {
$stmt->bind_result($id, $usuario);
$stmt->fetch();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario existe.',
'id' => $id,
'usuario' => $usuario
];
}
}
public function eliminarUsuario($id){
// 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);
return [
'estado' => 'error',
'mensaje' => 'Error al eliminar usuario: ' . $stmt->error
];
}
$stmt->close();
return [
'estado' => 'exitoso',
'mensaje' => 'Usuario eliminado exitosamente.'
];
}
}

View File

@ -1,7 +1,7 @@
<?php
session_start();
if (!isset($_SESSION['autenticado']) || $_SESSION['autenticado'] !== true) {
if (!isset($_SESSION['usuario'])) {
header('Location: index.html');
exit();
}

65
views/Main limpio.html Normal file
View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

166
views/consultar-api.html Normal file
View File

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css'>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="../css/inicio.css">
<link rel="stylesheet" href="../font/bootstrap-icons.css">
<link rel="stylesheet" href="../css/consultar-api.css">
<title>API Candidatos</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-usuarios.php"><i class='bx bxs-dashboard icon' ></i>Control usuario</a></li>
<li><a href="consultar-api.html" class="active"><i class='bx bxs-data icon' ></i>API</a></li>
<li><a href="../controllers/cerrarSesion.php"><i class="bi bi-box-arrow-left icon"></i>Cerrar sesión</a></li>
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<!-- ========== MAIN ========== -->
<main>
<h1 class="title" style="margin: 2% 1%">API Candidatos</h1>
<div class="row">
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-header">
<h5>Credenciales del Cliente</h5>
</div>
<div class="card-body">
<form id="oauth-form">
<div class="mb-3">
<label for="clientId" class="form-label">Client ID</label>
<input type="text" class="form-control" id="clientId" required />
</div>
<div class="mb-3">
<label for="clientSecret" class="form-label">Client Secret</label>
<input type="password" class="form-control" id="clientSecret" required />
</div>
<button type="submit" class="btn btn-primary">Obtener Token</button>
</form>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card" id="token-card">
<div class="card-header">
<h5>Estado de Autenticación</h5>
</div>
<div class="card-body">
<div id="token-section" class="hidden">
<div class="success-message">
<p><strong>✓ Autenticación exitosa</strong></p>
<p><strong>Token tipo:</strong> <span id="token-type">-</span></p>
<p><strong>Token válido por:</strong> <span id="expires-in">-</span> segundos</p>
<p><small class="text-muted">El token de acceso se ha guardado de forma segura</small></p>
</div>
<button id="get-candidates" class="btn btn-success">Obtener Candidatos</button>
</div>
<div id="no-token-message">
<p class="text-muted">Ingrese sus credenciales y haga clic en "Obtener Token" para comenzar.</p>
</div>
</div>
</div>
</div>
<div class="col-12">
<div class="card" id="result-card">
<div class="card-header">
<h5>Resultados</h5>
</div>
<div class="card-body">
<div id="download-section" class="download-section hidden">
<h6 class="mb-3">📥 Descargar Datos</h6>
<div class="download-buttons">
<button id="download-json" class="btn btn-outline-primary download-btn">
📄 JSON
</button>
<button id="download-csv" class="btn btn-outline-success download-btn">
📊 CSV
</button>
<button id="download-excel" class="btn btn-outline-info download-btn">
📈 Excel
</button>
</div>
<small class="text-muted d-block mt-2">
Total de registros: <span id="records-count">0</span>
</small>
</div>
<div id="candidates-section" class="hidden">
<h4 class="mb-3">Lista de Candidatos</h4>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Nombre</th>
<th>Correo</th>
<th>Teléfono</th>
<th>Género</th>
<th>Rango Edad</th>
<th>Tipo Identificación</th>
<th>País</th>
<th>Estado</th>
<th>Municipio</th>
<th>Colonia</th>
<th>Nivel Estudio</th>
<th>Giro</th>
<th>Empresa/Institución</th>
<th>ID Examen</th>
<th>Nombre Examen</th>
<th>Motivo</th>
<th>Calificación</th>
<th>Consentimiento Publicidad</th>
<th>Fecha Entrada</th>
<th>Fecha Salida</th>
</tr>
</thead>
<tbody id="candidates-table-body"></tbody>
</table>
</div>
</div>
<div id="api-response-section" class="hidden">
<h4 class="mb-3">Respuesta JSON</h4>
<pre id="api-response">Esperando respuesta...</pre>
</div>
<div id="error-section" class="hidden">
<div class="alert alert-danger" id="error-message"></div>
</div>
<div id="no-results-message">
<p class="text-muted">Obtenga un token y haga una solicitud para ver los resultados aquí.</p>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- .......... MAIN .......... -->
</section>
<!-- <script src="assets/bootstrap/js/bootstrap.min.js"></script> -->
<script src="../js/consultar-api.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="../js/control-candidato.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script> -->
<!-- <script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script> -->
</body>
</html>

View File

@ -0,0 +1,108 @@
<?php
//session_start();
//
//if (!isset($_SESSION['usuario'])) {
// header('Location: ../index.html');
// session_destroy();
// exit();
//}
require_once __DIR__ . "/../controllers/ControlCandidatos.php";
$candidatoControl = new ControlCandidatos();
$resultado = $candidatoControl->obtenerCandidatosSinFechaSalida();
if(isset($resultado['estado'])){
$hayCandidatos = false;
if($resultado['estado'] == 'error'){
// Enviar un console.error con $resultado['mensaje']
echo "<script>console.error('Error: " . $resultado['mensaje'] . "');</script>";
} else {
echo "<script>console.log(" . $resultado['mensaje'] . ");</script>";
}
} else {
$hayCandidatos = true;
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css'>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="../css/inicio.css">
<link rel="stylesheet" href="../font/bootstrap-icons.css">
<title>Control de candidatos</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php" class="active"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-usuarios.php"><i class='bx bxs-dashboard icon' ></i>Control usuario</a></li>
<li><a href="consultar-api.html"><i class='bx bxs-data icon' ></i>API</a></li>
<li><a href="../controllers/cerrarSesion.php"><i class="bi bi-box-arrow-left icon"></i>Cerrar sesión</a></li>
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<!-- ========== MAIN ========== -->
<main>
<h1 class="title" style="margin: 2% 1%">Control</h1>
<!-- ------------------------------ div qué contiene la tabla ------------------------------------------ -->
<div style="margin: 1%">
<div class="table-responsive rounded-4" style="height: 100%;width: 100%;">
<table class="table table-hover table-bordered border-dark-subtle shadow-sm">
<thead>
<tr class="table-dark">
<th>Nombre</th>
<th>Entrada</th>
<th>Acciones</th>
</tr>
</thead>
<tbody class="table-group-divider">
<?php if ($hayCandidatos): ?>
<?php foreach ($resultado as $candidato): ?>
<tr>
<td><?php echo $candidato['nombre_completo'] ?></td>
<td><?php echo $candidato['fecha_entrada'] ?></td>
<td>
<a class="btn border rounded-3 shadow" role="button" style="background-color: #35245b;color: white;" href="formulario-datos-candidato.php?id_candidato=<?php echo $candidato['id_candidato']?>" target="_blank"><i class="bi bi-file-earmark-text"></i> Abrir formulario</a>
<button class="boton-eliminar btn border rounded-3 shadow" role="button" style="background-color: #35245b;color: white;" data-id-candidato="<?php echo $candidato['id_candidato'] ?>"><i class="bi bi-trash"></i> Eliminar</button>
</td>
<tr>
<?php endforeach; ?>
<?php endif; ?>
</tr>
</tbody>
</table>
</div>
</div>
<!-- ------------------------------ /div qué contiene la tabla ----------------------------------------- -->
</main>
<!-- .......... MAIN .......... -->
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="../js/control-candidato.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

103
views/control-usuarios.php Normal file
View File

@ -0,0 +1,103 @@
<?php
//session_start();
//
//if (!isset($_SESSION['usuario'])) {
// header('Location: ../index.html');
// session_destroy();
// exit();
//}
require_once __DIR__ . "/../controllers/UsuarioController.php";
$resultado = UsuarioController::obtenerUsuarios();
$hayUsuarios = true;
// Si hubo algún error se retorno un array con el estado y mensaje, comprobar si existe
if (isset($resultado['estado'])){
$hayUsuarios = false;
echo "<script>console.log('".$resultado['mensaje']."');</script>";
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css'>
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="../css/inicio.css">
<link rel="stylesheet" href="../font/bootstrap-icons.css">
<title>Control de usuarios</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-usuarios.php" class="active"><i class='bx bxs-dashboard icon' ></i>Control usuario</a></li>
<li><a href="consultar-api.html"><i class='bx bxs-data icon' ></i>API</a></li>
<li><a href="../controllers/cerrarSesion.php"><i class="bi bi-box-arrow-left icon"></i>Cerrar sesión</a></li>
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<!-- ========== MAIN ========== -->
<main>
<h1 class="title" style="margin: 2% 1%">Control de usuarios</h1>
<a class="btn border rounded-3 shadow" style="background-color: #35245b;color: white;margin: 1%" href="crearUsuario.php"><i class="bi bi-person-plus"></i> Crear usuario</a>
<!-- ------------------------------ div qué contiene la tabla ------------------------------------------ -->
<div style="margin: 1%">
<div class="table-responsive rounded-4" style="height: 100%;width: 100%;">
<table class="table table-hover table-bordered border-dark-subtle shadow-sm">
<thead>
<tr class="table-dark">
<th>Nombre</th>
<th>Acciones</th>
</tr>
</thead>
<tbody class="table-group-divider">
<?php if ($hayUsuarios): ?>
<?php foreach ($resultado as $usuario): ?>
<tr>
<td><?php echo $usuario['usuario'] ?></td>
<td>
<a class="btn border rounded-3 shadow" role="button" style="background-color: #35245b;color: white;" href="modificar-usuario.php?id=<?php echo $usuario['id'] ?>&usuario=<?php echo urlencode($usuario['usuario']) ?>"><i class="bi bi-pencil-square"></i> Modificar</a>
<button class="boton-eliminar btn border rounded-3 shadow" role="button" style="background-color: #35245b;color: white;" data-id-usuario="<?php echo $usuario['id'] ?>" data-nombre-usuario="<?php echo $usuario['usuario'] ?>"><i class="bi bi-trash"></i> Eliminar</button>
</td>
<tr>
<?php endforeach; ?>
<?php endif; ?>
</tr>
</tbody>
</table>
</div>
</div>
<!-- ------------------------------ /div qué contiene la tabla ----------------------------------------- -->
</main>
<!-- .......... MAIN .......... -->
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="../js/control-usuario.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

81
views/crearUsuario.php Normal file
View File

@ -0,0 +1,81 @@
<?php
//session_start();
//
//if (!isset($_SESSION['usuario'])) {
// header('Location: ../index.html');
// session_destroy();
// exit();
//}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="../font/bootstrap-icons.css">
<link rel="stylesheet" href="../css/inicio.css">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css'>
<title>Crear usuario</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-usuarios.php" class="active"><i class='bx bxs-dashboard icon' ></i>Control usuario</a></li>
<li><a href="../controllers/cerrarSesion.php"><i class="bi bi-box-arrow-left icon"></i>Cerrar sesión</a></li>
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<main>
<h1 class="title" style="margin: 2% 1%">Crear usuario</h1>
<!-- div de formulario ------------------------------------------------------------------------------------- -->
<div class="bg-light-subtle border border-dark-subtle shadow-sm rounded-3" style="margin: 1%">
<div style="margin:5%;">
<form id="form">
<label class="form-label" for="usuario" style="margin: 8px 0px 8px 0px;"><i class="bi bi-person"></i> Nombre de usuario</label>
<input class="border rounded border-dark-subtle form-control" type="text" id="usuario" required="" minlength="1" maxlength="150" pattern="^[a-zA-Z0-9]+$" />
<label class="form-label" for="contrasena" style="margin: 8px 0px 8px 0px;"><i class="bi bi-key"></i> Contraseña</label>
<div class="input-group">
<input class="form-control" type="password" id="contrasena" required="" minlength="1"/>
<button class="btn btn-light" id="togglePassword" type="button" style="border: var(--bs-border-width) solid var(--bs-border-color);"><i class="bi bi-eye"></i></button>
</div>
<label class="form-label" for="contrasena" style="margin: 8px 0px 8px 0px;"><i class="bi bi-key"></i> Vuelva a escribir la contraseña</label>
<input class="form-control" type="password" id="contrasena_verificacion" required="" minlength="1"/>
<input class="btn text-light w-100" type="submit" id="submit" style="margin: 8px 0px 8px 0px;background-color: #35245b"/ value="Crear usuario">
</form>
</div>
</div>
<!-- /div de formulario ------------------------------------------------------------------------------------ -->
</main>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="../js/crear-usuario.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>

View File

@ -9,53 +9,53 @@
</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 style="background-color: #211b52;"><img src="assets/img/logo-lania-w.png" style="height: 5rem;margin: 0px 10px;"></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">
<form style="margin: 0px 10%;" 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="">
<input class="border rounded border-dark-subtle 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="">
<input class="border rounded border-dark-subtle 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">
<input class="border rounded border-dark-subtle 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">
<input class="border rounded border-dark-subtle 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="">
<input class="border rounded border-dark-subtle 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="">
<select class="border rounded border-dark-subtle form-select" id="id_examen" 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="">
<select class="border rounded border-dark-subtle 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>
<label class="form-label" for="id_rango_edad" style="margin: 10px 0px 5px;">Rango de edad</label>
<select class="border rounded border-dark-subtle form-select" id="id_rango_edad" 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 border-dark-subtle form-select" id="id_tipo_id" required="">
<option value="NULL">Seleccione una opción</option>
</select>
<input class="btn border rounded-3 border-3 border-primary-subtle w-100" type="submit" value="Enviar" style="margin: 15px 0px;background-color: #35245b;color: white;" name="btnEnviar"> </form>
<!-- ==================== Fin del formulario ==================== -->
<div id="mensaje-error"></div>
</div>

View File

@ -1,13 +1,11 @@
<?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'];
} else {
// Si no se pasa el id_candidato
//header("Location: inicio.html");
//exit();
} else { // TEST //
$id_candidato = 0;
} // TEST \\
header("Location: control-candidatos.php");
exit();
}
?>
<!DOCTYPE html>
@ -16,72 +14,70 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id_candidato'])){
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>formsLania</title>
<title>Formulario</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 style="background-color: #211b52;"><img src="assets/img/logo-lania-w.png" style="height: 5rem;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; ?>">
<form style="margin: 0px 10%;" id="formulario-datos-extendido" method="post" action="#">
<input class="border rounded-3 border-dark-subtle form-control" type="number" id="id_candidato" value="<?php echo $id_candidato; ?>" hidden="">
<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="">
<select class="border rounded-3 border-dark-subtle 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="">
<input class="border rounded-3 border-dark-subtle 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>
<button class="btn bg-primary-subtle border rounded-3 border-dark-subtle btn-primary w-100" type="button" id="buscarBtn" style="margin: 15px 0px;color: rgb(0,0,0);" 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<input class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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="">
<select class="border rounded-3 border-dark-subtle 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>
@ -89,13 +85,13 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id_candidato'])){
<option value="4">&#128578 Satisfecho</option>
<option value="5">&#128528 Muy satisfecho</option>
</select>
<br>
<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">
<input class="btn border rounded-3 border border-primary-subtle btn-primary w-100" type="submit" style="margin: 15px 0px;" value="Enviar" name="btnEnviar">
</form>
<!-- ==================== Fin del formulario ==================== -->
</div>

View File

@ -266,5 +266,6 @@
<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>
</html>

View File

@ -0,0 +1,92 @@
<?php
//session_start();
//
//if (!isset($_SESSION['usuario'])) {
// header('Location: ../index.html');
// session_destroy();
// exit();
//}
require_once __DIR__ . "/../controllers/UsuarioController.php";
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id']) && isset($_GET['usuario'])) {
$id = $_GET['id'];
$usuario = $_GET['usuario'];
} else {
header('Location: ../views/control-usuarios.php');
exit();
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="../font/bootstrap-icons.css">
<link rel="stylesheet" href="../css/inicio.css">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/boxicons@latest/css/boxicons.min.css'>
<title>Modificar usuario</title>
</head>
<body>
<!-- SIDEBAR -->
<section id="sidebar">
<a href="inicio.html" class="brand"><i class='bx bx-code-alt icon' ></i> LANIA</a>
<ul class="side-menu">
<li><a href="inicio.html"><i class='bx bxs-dashboard icon' ></i>Dashboard</a></li>
<li><a href="formulario-candidato.html" target="_blank"><i class='bx bxs-dashboard icon' ></i>Formulario de registro</a></li>
<li><a href="control-candidatos.php"><i class='bx bxs-dashboard icon' ></i>Control candidatos</a></li>
<li><a href="control-usuarios.php" class="active"><i class='bx bxs-dashboard icon' ></i>Control usuario</a></li>
<li><a href="../controllers/cerrarSesion.php"><i class="bi bi-box-arrow-left icon"></i>Cerrar sesión</a></li>
</ul>
</section>
<!-- .SIDEBAR -->
<section id="content">
<main>
<h1 class="title" style="margin: 2% 1%">Modificar usuario</h1>
<!-- div de formulario ------------------------------------------------------------------------------------- -->
<div class="bg-light-subtle border border-dark-subtle shadow-sm rounded-3" style="margin: 1%">
<div style="margin:5%;">
<form id="form">
<input type="hidden" id="id" value="<?php echo $id ?>"/>
<label class="form-label" for="usuario" style="margin: 8px 0px 8px 0px;"><i class="bi bi-person"></i> Nombre de usuario</label>
<input class="border rounded border-dark-subtle form-control" type="text" id="usuario" required="" minlength="1" maxlength="150" pattern="^[a-zA-Z0-9]+$" value="<?php echo $usuario ?>"/>
<label class="form-label" for="contrasena" style="margin: 8px 0px 8px 0px;"><i class="bi bi-key"></i> Contraseña</label>
<div class="input-group">
<input class="form-control" type="password" id="contrasena" required="" minlength="1"/>
<button class="btn btn-light" id="togglePassword" type="button" style="border: var(--bs-border-width) solid var(--bs-border-color);"><i class="bi bi-eye"></i></button>
</div>
<label class="form-label" for="contrasena" style="margin: 8px 0px 8px 0px;"><i class="bi bi-key"></i> Vuelva a escribir la contraseña</label>
<input class="form-control" type="password" id="contrasena_verificacion" required="" minlength="1"/>
<input class="btn text-light w-100" type="submit" id="submit" style="margin: 8px 0px 8px 0px;background-color: #35245b"/ value="Modificar usuario">
</form>
</div>
</div>
<!-- /div de formulario ------------------------------------------------------------------------------------ -->
</main>
</section>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../js/sidebar-navbar.js"></script>
<script src="../js/actualizar-usuario.js"></script>
<script src="https://website-widgets.pages.dev/dist/sienna.min.js" defer></script>
</body>
</html>