<?php
// Verificar permisos
if (!current_user_can('manage_options')) {
wp_die(__('No tienes permisos para acceder a esta página.', 'working-english-system'));
}
// Desactivar caché para datos dinámicos
if (!defined('DONOTCACHEPAGE')) {
define('DONOTCACHEPAGE', true);
}
nocache_headers();
// Obtener estudiantes PRIMERO
global $wpdb;
$table_students = $wpdb->prefix . 'wes_students';
// Construir consulta con filtros
$where_conditions = array("deleted_at IS NULL");
$where_values = array();
// Filtro de búsqueda
if (isset($_GET['search']) && !empty($_GET['search'])) {
$search_term = sanitize_text_field($_GET['search']);
$where_conditions[] = "(first_name LIKE %s OR last_name LIKE %s OR email LIKE %s OR student_id LIKE %s)";
$search_like = '%' . $wpdb->esc_like($search_term) . '%';
$where_values = array_merge($where_values, array($search_like, $search_like, $search_like, $search_like));
}
// Filtro de estado
if (isset($_GET['status']) && !empty($_GET['status'])) {
$status = sanitize_text_field($_GET['status']);
$where_conditions[] = "status = %s";
$where_values[] = $status;
}
$where_clause = 'WHERE ' . implode(' AND ', $where_conditions);
if (!empty($where_values)) {
$students = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_students $where_clause ORDER BY created_at DESC",
$where_values
));
} else {
$students = $wpdb->get_results("SELECT * FROM $table_students $where_clause ORDER BY created_at DESC");
}
// Calcular estadísticas DESPUÉS de obtener los datos
$total_students = count($students);
$active_students = array_filter($students, function($s) { return $s->status == 'active'; });
$new_students = array_filter($students, function($s) {
return strtotime($s->created_at) > strtotime('-30 days');
});
// NO cargar header de WordPress para tener control total
// get_header();
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gestión de Estudiantes - Working English International</title>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php
?>
<style>
/* =================================
ESTILOS PROFESIONALES WES - FRONTEND CORREGIDO
================================= */
/* Variables CSS */
:root {
--wes-primary: #B19CD9;
--wes-secondary: #9B59B6;
--wes-success: #9DFF70;
--wes-warning: #FFE066;
--wes-danger: #FF6B6B;
--wes-info: #74B9FF;
--wes-light: #f6f7f7;
--wes-dark: #1d2327;
--wes-border: #c3c4c7;
--wes-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* =================================
ENCABEZADO CORPORATIVO PREMIUM
================================= */
.wes-corporate-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
position: relative;
overflow: hidden;
padding: 0;
margin: 0;
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
}
.wes-corporate-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
radial-gradient(circle at 20% 50%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
radial-gradient(circle at 40% 80%, rgba(120, 198, 121, 0.3) 0%, transparent 50%);
animation: gradientShift 15s ease-in-out infinite;
}
@keyframes gradientShift {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.05); }
}
.corporate-content {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
padding: 25px 40px;
gap: 30px;
backdrop-filter: blur(10px);
background: rgba(255,255,255,0.05);
}
.company-logo {
display: flex;
align-items: center;
gap: 20px;
}
.logo-image {
width: 120px;
height: auto;
filter: drop-shadow(0 4px 20px rgba(0,0,0,0.3));
transition: all 0.3s ease;
}
.logo-image:hover {
transform: scale(1.05);
filter: drop-shadow(0 6px 25px rgba(0,0,0,0.4));
}
.company-info {
text-align: center;
color: white;
}
/* ARREGLADO: Solo una declaración para company-name */
.company-name {
font-size: 36px;
font-weight: 800;
margin: 0;
color: white;
text-shadow: 0 2px 10px rgba(0,0,0,0.3);
letter-spacing: 2px;
}
.company-tagline {
font-size: 16px;
margin: 8px 0 0;
opacity: 0.95;
font-weight: 500;
letter-spacing: 1px;
}
.contact-info {
text-align: right;
color: white;
}
.contact-item {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
margin: 8px 0;
font-size: 14px;
opacity: 0.9;
transition: all 0.3s ease;
}
.contact-item:hover {
opacity: 1;
transform: translateX(-5px);
}
.contact-item i {
width: 20px;
text-align: center;
background: rgba(255,255,255,0.2);
padding: 8px;
border-radius: 50%;
font-size: 12px;
}
.contact-item a {
color: white;
text-decoration: none;
transition: all 0.3s ease;
}
.contact-item a:hover {
color: var(--wes-warning);
text-decoration: none;
}
/* Efectos de partículas flotantes */
.floating-elements {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 1;
}
.floating-elements::before,
.floating-elements::after {
content: '';
position: absolute;
width: 60px;
height: 60px;
background: rgba(255,255,255,0.1);
border-radius: 50%;
animation: float 20s infinite ease-in-out;
}
.floating-elements::before {
top: 20%;
left: 10%;
animation-delay: 0s;
}
.floating-elements::after {
top: 60%;
right: 15%;
animation-delay: 10s;
width: 80px;
height: 80px;
}
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); opacity: 0.5; }
50% { transform: translateY(-20px) rotate(180deg); opacity: 0.8; }
}
/* Responsive del encabezado */
@media (max-width: 1024px) {
.corporate-content {
grid-template-columns: 1fr;
text-align: center;
gap: 20px;
padding: 30px 20px;
}
.company-name {
font-size: 32px;
}
.contact-info {
text-align: center;
}
.contact-item {
justify-content: center;
}
}
@media (max-width: 768px) {
.logo-image {
width: 100px;
}
.company-name {
font-size: 28px;
}
.company-tagline {
font-size: 14px;
}
.corporate-content {
padding: 25px 15px;
}
}
@media (max-width: 480px) {
.logo-image {
width: 80px;
}
.company-name {
font-size: 24px;
}
.contact-item {
font-size: 13px;
}
}
/* =================================
BARRA DE NAVEGACIÓN MODERNA
================================= */
.wes-navbar {
background: linear-gradient(135deg, var(--wes-primary), var(--wes-secondary));
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.nav-brand {
display: flex;
align-items: center;
gap: 12px;
color: white;
font-size: 20px;
font-weight: 700;
padding: 15px 0;
}
.nav-brand i {
font-size: 24px;
color: var(--wes-warning);
}
.nav-menu {
display: flex;
align-items: center;
gap: 5px;
}
.nav-item {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 20px;
color: rgba(255,255,255,0.9);
text-decoration: none;
border-radius: 8px;
font-weight: 500;
font-size: 14px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.nav-item::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s ease;
}
.nav-item:hover::before {
left: 100%;
}
.nav-item:hover {
background: rgba(255,255,255,0.15);
color: white;
text-decoration: none;
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.nav-item.active {
background: rgba(255,255,255,0.25);
color: white;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
}
.nav-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 3px;
background: var(--wes-warning);
border-radius: 2px;
}
.nav-item.disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}
.nav-item i {
font-size: 16px;
width: 20px;
text-align: center;
}
/* Efecto glassmorphism para la navbar */
.wes-navbar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05));
pointer-events: none;
}
/* Responsive de la navbar */
@media (max-width: 768px) {
.wes-navbar {
flex-direction: column;
padding: 15px;
gap: 15px;
}
.nav-menu {
width: 100%;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
}
.nav-item {
padding: 10px 15px;
font-size: 13px;
min-width: 100px;
justify-content: center;
}
.nav-brand {
font-size: 18px;
}
}
@media (max-width: 480px) {
.nav-menu {
grid-template-columns: repeat(2, 1fr);
display: grid;
width: 100%;
gap: 10px;
}
.nav-item {
justify-content: center;
text-align: center;
}
}
/* Actualizar el contenedor principal para que no se superponga */
.wes-frontend-container {
margin-top: 0;
}
/* Ajustar el header para que no choque con la navbar */
.wes-header {
margin-top: 20px;
}
.wes-frontend-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* Header mejorado */
.wes-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding: 20px;
background: linear-gradient(135deg, var(--wes-primary), var(--wes-secondary));
border-radius: 12px;
color: white;
box-shadow: var(--wes-shadow);
}
.wes-header h1 {
margin: 0;
font-size: 28px;
font-weight: 600;
}
.wes-header p {
margin: 5px 0 0;
opacity: 0.9;
font-size: 16px;
}
.btn-new-student {
background: white;
color: var(--wes-primary);
border: none;
padding: 12px 24px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.btn-new-student:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
/* Estadísticas mejoradas */
.wes-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: white;
padding: 25px;
border-radius: 12px;
border: 1px solid var(--wes-border);
text-align: center;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--stat-color, var(--wes-primary));
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: var(--wes-shadow);
}
.stat-card.total { --stat-color: var(--wes-primary); }
.stat-card.active { --stat-color: var(--wes-success); }
.stat-card.new { --stat-color: var(--wes-warning); }
.stat-number {
font-size: 3em;
font-weight: 700;
margin: 0;
color: var(--stat-color, var(--wes-primary));
}
.stat-label {
margin: 10px 0 0;
color: #666;
font-weight: 500;
font-size: 16px;
}
/* Búsqueda mejorada - ARREGLADA */
.wes-search {
background: white;
padding: 25px;
border-radius: 12px;
border: 1px solid var(--wes-border);
margin-bottom: 25px;
box-shadow: var(--wes-shadow);
}
.search-grid {
display: grid;
grid-template-columns: 1fr auto auto auto;
gap: 20px;
align-items: end;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: var(--wes-dark);
}
/* ARREGLADO: Form control SIN cuadros de colores */
.form-control {
width: 100%;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
background: #ffffff;
color: #333333;
box-sizing: border-box;
}
.form-control:focus {
outline: none;
border-color: var(--wes-primary);
box-shadow: 0 0 0 3px rgba(177, 156, 217, 0.1);
background: #ffffff;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background: var(--wes-primary);
color: white;
}
.btn-primary:hover {
background: var(--wes-secondary);
transform: translateY(-1px);
color: white;
text-decoration: none;
box-shadow: 0 4px 12px rgba(177, 156, 217, 0.3);
}
.btn-secondary {
background: #6c757d;
color: white;
}
/* Tabla profesional */
.wes-table-container {
background: white;
border-radius: 12px;
border: 1px solid var(--wes-border);
overflow: hidden;
box-shadow: var(--wes-shadow);
}
.table-header {
padding: 20px 25px;
background: var(--wes-light);
border-bottom: 1px solid var(--wes-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.table-header h2 {
margin: 0;
font-size: 20px;
color: var(--wes-dark);
}
/* Tabla mejorada */
.wes-table {
width: 100%;
border-collapse: collapse;
margin: 0;
}
.wes-table thead {
background: #f8f9fa;
}
.wes-table th {
padding: 16px 20px;
text-align: left;
font-weight: 600;
color: var(--wes-dark);
border-bottom: 2px solid var(--wes-border);
font-size: 14px;
}
.wes-table td {
padding: 16px 20px;
border-bottom: 1px solid #f0f0f0;
vertical-align: middle;
}
.wes-table tbody tr {
transition: all 0.3s ease;
}
.wes-table tbody tr:hover {
background: #f8f9ff;
}
/* Estados mejorados */
.status-badge {
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.status-active {
background: #d4edda;
color: #155724;
}
.status-inactive {
background: #f8d7da;
color: #721c24;
}
.status-graduated {
background: #d1ecf1;
color: #0c5460;
}
.status-suspended {
background: #fff3cd;
color: #856404;
}
.status-retired {
background: #e2e3e5;
color: #383d41;
}
/* Botones de acción mejorados - ARREGLADOS */
.action-buttons {
display: flex;
gap: 8px;
align-items: center;
}
.btn-sm {
padding: 8px 12px;
font-size: 12px;
border-radius: 6px;
min-width: 36px;
height: 36px;
justify-content: center;
line-height: 1.2;
border: none;
cursor: pointer;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
text-decoration: none;
}
/* ARREGLADO: Botón editar específico */
.btn-edit {
background: var(--wes-primary) !important;
color: white !important;
}
.btn-edit:hover {
background: var(--wes-secondary) !important;
transform: translateY(-1px);
color: white !important;
text-decoration: none;
box-shadow: 0 4px 12px rgba(177, 156, 217, 0.3);
}
.btn-warning {
background: var(--wes-warning);
color: #333;
}
.btn-warning:hover {
background: #c69c00;
transform: translateY(-1px);
color: white;
text-decoration: none;
box-shadow: 0 4px 12px rgba(255, 224, 102, 0.4);
}
.btn-danger {
background: var(--wes-danger);
color: white;
}
.btn-danger:hover {
background: #b02a2c;
transform: translateY(-1px);
color: white;
text-decoration: none;
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.4);
}
.btn i {
font-size: 14px;
width: 14px;
text-align: center;
}
/* Remover cualquier estilo conflictivo de dashicons */
.btn .dashicons {
display: none;
}
/* Asegurar que los iconos de Font Awesome se vean */
.btn .fas {
display: inline-block !important;
font-family: "Font Awesome 6 Free" !important;
font-weight: 900 !important;
}
.btn-status {
background: var(--wes-warning);
color: white;
}
.btn-status:hover {
background: #c69c00;
}
/* =================================
SOLUCIÓN SIMPLE - MODAL FUNCIONAL
================================= */
/* Modal overlay - SIN !important excesivos */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
z-index: 999999;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
padding: 20px;
}
.modal-overlay.show {
opacity: 1;
visibility: visible;
}
/* Modal content */
.modal-content {
background: #ffffff;
border-radius: 16px !important;
max-width: 1000px !important;
width: 98% !important;
max-height: 95vh !important;
overflow: hidden;
transform: scale(0.9);
transition: all 0.3s ease;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
display: flex;
flex-direction: column;
position: relative;
z-index: 1000000;
}
.modal-overlay.show .modal-content {
transform: scale(1);
}
/* Header */
.modal-header {
padding: 25px 80px 25px 50px !important;
background: linear-gradient(135deg, var(--wes-primary), var(--wes-secondary));
color: #ffffff;
position: relative;
flex-shrink: 0;
text-align: center;
min-height: 100px;
}
.modal-title {
margin: 0;
font-size: 24px;
font-weight: 600;
color: #ffffff;
}
.modal-subtitle {
margin: 8px 0 0;
opacity: 0.9;
font-size: 16px;
color: #ffffff;
}
/* Botón cerrar */
.btn-close {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255,255,255,0.2);
border: none;
color: #ffffff;
font-size: 24px;
font-weight: bold;
cursor: pointer;
padding: 8px;
border-radius: 8px;
transition: all 0.3s ease;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
line-height: 1;
}
.btn-close:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.1);
}
/* Tabs */
.modal-tabs {
display: flex;
background: #f8f9fa;
border-bottom: 1px solid var(--wes-border);
flex-shrink: 0;
z-index: 1;
}
.tab-btn {
flex: 1;
padding: 16px 20px;
border: none;
background: #f8f9fa;
cursor: pointer;
font-weight: 500;
color: #666666;
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
min-height: 60px;
}
.tab-btn.active {
background: #ffffff;
color: var(--wes-primary);
border-bottom-color: var(--wes-primary);
}
.tab-btn:hover:not(.active) {
background: #e9ecef;
color: var(--wes-dark);
}
/* Modal body */
.modal-body {
padding: 50px;
flex-grow: 1;
overflow-y: auto;
min-height: 0;
max-height: 60vh;
background: #ffffff;
z-index: 1;
}
.tab-content {
display: none;
background: #ffffff;
}
.tab-content.active {
display: block;
background: #ffffff;
}
.tab-title {
margin: 0 0 25px;
font-size: 20px;
color: var(--wes-primary);
display: flex;
align-items: center;
gap: 10px;
}
/* CRÍTICO: Form grid para 2 columnas */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.form-group-full {
grid-column: 1 / -1;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: var(--wes-dark);
}
/* Formularios - Específicos pero sin romper */
#student-modal .form-control {
width: 100%;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
background: #ffffff;
color: #333333;
box-sizing: border-box;
}
#student-modal .form-control:focus {
outline: none;
border-color: var(--wes-primary);
box-shadow: 0 0 0 3px rgba(177, 156, 217, 0.1);
background: #ffffff;
}
#student-modal select.form-control {
background: #ffffff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e") no-repeat right 0.75rem center/1.25rem 1.25rem;
padding-right: 2.5rem;
}
#student-modal textarea.form-control {
background: #ffffff;
resize: vertical;
min-height: 80px;
}
.help-text {
font-size: 12px;
color: #666666;
margin-top: 5px;
}
.info-box {
background: #e7f3ff;
border: 1px solid #b8daff;
border-radius: 8px;
padding: 15px;
margin-top: 20px;
}
.info-box p {
margin: 0;
color: #004085;
font-size: 14px;
}
/* Footer */
.modal-footer {
padding: 20px 50px !important;
background: #f8f9fa;
border-top: 1px solid var(--wes-border);
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
min-height: 70px;
flex-wrap: nowrap;
z-index: 1;
}
.btn-nav {
display: flex;
align-items: center;
gap: 8px;
}
.modal-footer > div {
display: flex;
gap: 10px;
align-items: center;
}
/* Responsive simple */
@media (max-width: 768px) {
.modal-content {
width: 98%;
margin: 10px;
max-height: 95vh;
}
.modal-header {
padding: 20px 50px 20px 20px;
min-height: 80px;
}
.modal-title {
font-size: 20px;
}
.modal-subtitle {
font-size: 14px;
}
.btn-close {
width: 35px;
height: 35px;
font-size: 20px;
top: 15px;
right: 15px;
}
.tab-btn {
font-size: 12px;
padding: 12px 8px;
min-height: 50px;
}
.tab-btn i {
display: none;
}
.modal-body {
padding: 20px 15px;
}
.form-grid {
grid-template-columns: 1fr;
}
.modal-footer {
padding: 15px;
flex-direction: column;
gap: 10px;
min-height: auto;
}
.modal-footer > div {
width: 100%;
justify-content: center;
}
.wes-header {
flex-direction: column;
gap: 15px;
text-align: center;
}
.search-grid {
grid-template-columns: 1fr;
gap: 15px;
}
.action-buttons {
flex-direction: column;
}
}
/* Dropdown para estados */
.status-dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: white;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
border-radius: 8px;
border: 1px solid var(--wes-border);
overflow: hidden;
bottom: 100%;
right: 0;
}
.dropdown-content.show {
display: block;
}
.dropdown-item {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
cursor: pointer;
transition: all 0.3s ease;
}
.dropdown-item:hover {
background-color: #f1f1f1;
}
/* Loading spinner */
.spinner {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid #f3f3f3;
border-top: 2px solid var(--wes-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Estados vacío mejorado */
.empty-state {
padding: 60px 20px;
text-align: center;
color: #646970;
}
.empty-icon {
font-size: 4em;
color: #dcdcde;
margin-bottom: 20px;
}
.empty-title {
font-size: 24px;
margin-bottom: 10px;
color: var(--wes-dark);
}
.empty-description {
font-size: 16px;
margin-bottom: 25px;
}
/* Fix para botones del modal en frontend */
.modal-footer .btn {
min-width: 120px;
height: auto;
line-height: 1.5;
white-space: nowrap;
}
.modal-footer > div {
flex-shrink: 0;
}
.modal-body {
max-height: 50vh !important;
}
/* AGREGAR AQUÍ - Escalar contenido del modal - más compacto */
#student-modal .modal-body {
padding: 30px !important; /* Reducir padding */
font-size: 14px; /* Reducir tamaño de fuente base */
}
#student-modal .form-control {
padding: 10px 14px !important; /* Reducir padding de inputs */
font-size: 13px !important; /* Reducir tamaño de fuente */
}
#student-modal .form-group label {
font-size: 13px !important; /* Reducir tamaño de labels */
margin-bottom: 6px !important; /* Reducir espacio */
}
#student-modal .form-group {
margin-bottom: 15px !important; /* Reducir espacio entre campos */
}
#student-modal .tab-title {
font-size: 18px !important; /* Reducir título de tabs */
margin-bottom: 20px !important;
}
#student-modal .form-grid {
gap: 15px !important; /* Reducir espacio en grid */
}
/* Arreglar espaciado del footer del modal */
#student-modal .modal-footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: 40px !important; /* Separación entre grupos de botones */
}
#student-modal .modal-footer > div {
display: flex;
gap: 15px !important; /* Separación dentro de cada grupo */
align-items: center;
}
/* Asegurar que el primer div (botón Anterior) tenga margen */
#student-modal .modal-footer > div:first-child {
margin-right: auto; /* Empuja hacia la izquierda */
}
/* Asegurar que el segundo div (botones de acción) mantenga su espacio */
#student-modal .modal-footer > div:last-child {
margin-left: auto; /* Empuja hacia la derecha */
}
.btn-sm .dashicons {
font-size: 16px !important;
width: 16px !important;
height: 16px !important;
color: white !important;
}
.btn-status {
background: var(--wes-warning) !important;
border-color: var(--wes-warning) !important;
color: #333 !important;
}
.btn-status:hover {
background: #c69c00 !important;
border-color: #c69c00 !important;
color: white !important;
}
.btn-delete {
background: var(--wes-danger) !important;
border-color: var(--wes-danger) !important;
}
.btn-delete:hover {
background: #b02a2c !important;
border-color: #b02a2c !important;
}
/* ===========================================
ARREGLO DEFINITIVO PARA AMBOS PROBLEMAS
=========================================== */
/* 1. ARREGLAR BOTÓN EDITAR - FORZAR COLOR MORADO */
.btn-edit,
button.btn-edit,
.action-buttons .btn-edit,
.wes-table .btn-edit,
.btn.btn-primary.btn-sm[title="Editar"],
button.btn.btn-primary.btn-sm,
.action-buttons button.btn-primary {
background: #B19CD9 !important;
background-color: #B19CD9 !important;
border-color: #B19CD9 !important;
color: white !important;
}
.btn-edit:hover,
button.btn-edit:hover,
.action-buttons .btn-edit:hover,
.wes-table .btn-edit:hover,
.btn.btn-primary.btn-sm[title="Editar"]:hover,
button.btn.btn-primary.btn-sm:hover,
.action-buttons button.btn-primary:hover {
background: #9B59B6 !important;
background-color: #9B59B6 !important;
border-color: #9B59B6 !important;
color: white !important;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(177, 156, 217, 0.3);
}
/* Asegurar que NO se aplique el azul de Bootstrap */
.btn-primary:not(.btn-new-student):not(.btn-nav):not(#save-btn):not(#next-tab) {
background: #B19CD9 !important;
border-color: #B19CD9 !important;
}
.btn-primary:not(.btn-new-student):not(.btn-nav):not(#save-btn):not(#next-tab):hover {
background: #9B59B6 !important;
border-color: #9B59B6 !important;
}
/* 2. ARREGLAR HEADER DE TABLA - ELIMINAR CUADROS DE COLORES */
.wes-table th,
.wes-table thead th,
.wes-table-container .wes-table th,
.wes-table-container table th,
table.wes-table th,
table.wes-table thead th,
.wes-table-container th {
background: #f8f9fa !important;
background-color: #f8f9fa !important;
background-image: none !important;
color: #1d2327 !important;
border: none !important;
border-bottom: 2px solid #c3c4c7 !important;
padding: 16px 20px !important;
text-align: left !important;
font-weight: 600 !important;
font-size: 14px !important;
vertical-align: middle !important;
position: relative !important;
}
/* Forzar cada columna específicamente para eliminar colores */
.wes-table th:nth-child(1),
.wes-table th:nth-child(2),
.wes-table th:nth-child(3),
.wes-table th:nth-child(4),
.wes-table th:nth-child(5),
.wes-table th:nth-child(6),
.wes-table th:nth-child(7),
.wes-table th:nth-child(8) {
background: #f8f9fa !important;
background-color: #f8f9fa !important;
background-image: none !important;
border-image: none !important;
box-shadow: none !important;
}
/* Eliminar pseudo-elementos que puedan estar causando colores */
.wes-table th::before,
.wes-table th::after,
.wes-table thead th::before,
.wes-table thead th::after,
.wes-table-container th::before,
.wes-table-container th::after {
display: none !important;
content: none !important;
background: none !important;
background-color: transparent !important;
border: none !important;
width: 0 !important;
height: 0 !important;
}
/* Reset completo para el thead */
.wes-table thead,
.wes-table-container thead {
background: #f8f9fa !important;
background-color: #f8f9fa !important;
background-image: none !important;
border: none !important;
}
/* Eliminar cualquier estilo conflictivo de WordPress/plugins */
.wes-table-container table,
.wes-table-container table *,
.wes-table,
.wes-table * {
box-shadow: none !important;
border-image: none !important;
outline: none !important;
text-decoration: none !important;
}
/* Reset específico para th con all: unset y redefinir */
.wes-table th {
all: unset !important;
display: table-cell !important;
padding: 16px 20px !important;
text-align: left !important;
font-weight: 600 !important;
color: #1d2327 !important;
border-bottom: 2px solid #c3c4c7 !important;
font-size: 14px !important;
background: #f8f9fa !important;
background-color: #f8f9fa !important;
vertical-align: middle !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
}
/* Eliminar cualquier gradiente o imagen de fondo que pueda estar aplicando WordPress */
.wes-table-container * {
background-attachment: initial !important;
background-blend-mode: initial !important;
background-clip: initial !important;
background-origin: initial !important;
background-position: initial !important;
background-repeat: initial !important;
background-size: initial !important;
}
/* Override adicional para asegurar que no hay colores extraños */
.wes-table thead tr th {
background: #f8f9fa !important;
}
/* Forzar que los elementos td también sean consistentes */
.wes-table td {
background: white !important;
background-color: white !important;
background-image: none !important;
border-bottom: 1px solid #f0f0f0 !important;
}
.wes-table tbody tr:hover td {
background: #f8f9ff !important;
background-color: #f8f9ff !important;
}
/* Override final para asegurar que no hay interferencias */
.wes-table,
.wes-table * {
border-collapse: collapse !important;
border-spacing: 0 !important;
}
</style>
<!-- Encabezado Corporativo Premium -->
<div class="wes-corporate-header">
<div class="floating-elements"></div>
<div class="corporate-content">
<div class="company-logo">
<img src="http://workingenglishadmin.com/wp-content/uploads/2025/07/letras-1_Mesa-de-trabajo-1.png" alt="Working English International" class="logo-image">
</div>
<div class="company-info">
<h1 class="company-name">Working English International</h1>
<p class="company-tagline">Learn With Us</p>
</div>
<div class="contact-info">
<div class="contact-item">
<i class="fas fa-map-marker-alt"></i>
<span>Casper, Wyoming, USA</span>
</div>
<div class="contact-item">
<i class="fas fa-globe"></i>
<a href="https://www.workingenglishonline.com" target="_blank">www.workingenglishonline.com</a>
</div>
<div class="contact-item">
<i class="fas fa-graduation-cap"></i>
<span>Academic Management System</span>
</div>
</div>
</div>
</div>
<div class="wes-frontend-container">
<!-- Barra de navegación centralizada -->
<div class="wes-navbar">
<div class="nav-brand">
<i class="fas fa-graduation-cap"></i>
<span>WE System</span>
</div>
<nav class="nav-menu">
<a href="/dashboard" class="nav-item">
<i class="fas fa-tachometer-alt"></i>
Dashboard
</a>
<a href="/estudiantes" class="nav-item active">
<i class="fas fa-users"></i>
Estudiantes
</a>
<a href="#" class="nav-item disabled">
<i class="fas fa-chalkboard-teacher"></i>
Maestros
</a>
<a href="#" class="nav-item disabled">
<i class="fas fa-layer-group"></i>
Grupos
</a>
</nav>
</div>
<!-- Header mejorado -->
<div class="wes-header">
<div>
<h1><i class="fas fa-users"></i> Gestión de Estudiantes</h1>
<p>Administra toda la información de tus estudiantes de forma profesional</p>
</div>
<button class="btn-new-student" onclick="openStudentModal()">
<i class="fas fa-plus"></i>
Nuevo Estudiante
</button>
</div>
<!-- Estadísticas mejoradas -->
<div class="wes-stats">
<div class="stat-card total">
<h2 class="stat-number"><?php echo $total_students; ?></h2>
<p class="stat-label">Total Estudiantes</p>
</div>
<div class="stat-card active">
<h2 class="stat-number"><?php echo count($active_students); ?></h2>
<p class="stat-label">Activos</p>
</div>
<div class="stat-card new">
<h2 class="stat-number"><?php echo count($new_students); ?></h2>
<p class="stat-label">Nuevos (30 días)</p>
</div>
</div>
<!-- Búsqueda mejorada -->
<div class="wes-search">
<div class="search-grid">
<div class="form-group">
<label>Buscar estudiante</label>
<input type="text" class="form-control" id="search-input" placeholder="Nombre, email, teléfono o ID...">
</div>
<div class="form-group">
<label>Estado</label>
<select class="form-control" id="status-filter">
<option value="">Todos</option>
<option value="active">Activos</option>
<option value="inactive">Inactivos</option>
<option value="graduated">Graduados</option>
<option value="suspended">Suspendidos</option>
<option value="retired">Retirados</option>
</select>
</div>
<div>
<button class="btn btn-primary" onclick="searchStudents()">
<i class="fas fa-search"></i> Buscar
</button>
</div>
<div>
<button class="btn btn-secondary" onclick="clearSearch()">
<i class="fas fa-times"></i> Limpiar
</button>
</div>
</div>
</div>
<!-- Tabla mejorada -->
<div class="wes-table-container">
<div class="table-header">
<h2>Lista de Estudiantes</h2>
</div>
<?php if (empty($students)): ?>
<!-- Estado vacío -->
<div class="empty-state">
<div class="empty-icon">
<i class="fas fa-users"></i>
</div>
<h3 class="empty-title">No hay estudiantes registrados</h3>
<p class="empty-description">Comienza agregando tu primer estudiante al sistema</p>
<button class="btn btn-primary" onclick="openStudentModal()">
<i class="fas fa-plus"></i>
Agregar Primer Estudiante
</button>
</div>
<?php else: ?>
<!-- Tabla de estudiantes -->
<table class="wes-table">
<thead>
<tr>
<th>ID</th>
<th>Nombre Completo</th>
<th>Email</th>
<th>Teléfono</th>
<th>País</th>
<th>Estado</th>
<th>Fecha Registro</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach ($students as $student): ?>
<tr>
<td><strong><?php echo esc_html($student->student_id); ?></strong></td>
<td>
<div style="font-weight: 600;"><?php echo esc_html($student->first_name . ' ' . $student->last_name); ?></div>
</td>
<td><?php echo $student->email ? esc_html($student->email) : '<span style="color: #999;">Sin email</span>'; ?></td>
<td><?php echo esc_html($student->phone ?: '-'); ?></td>
<td><?php echo esc_html($student->country_of_origin ?: '-'); ?></td>
<td>
<span class="status-badge status-<?php echo $student->status; ?>">
<?php echo ucfirst($student->status); ?>
</span>
</td>
<td><?php echo date('d/m/Y', strtotime($student->created_at)); ?></td>
<td>
<div class="action-buttons">
<button class="btn btn-primary btn-sm btn-edit" onclick="editStudent(<?php echo $student->id; ?>)" title="Editar">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-warning btn-sm" onclick="showStatusDropdown(event, <?php echo $student->id; ?>)" title="Cambiar Estado">
<i class="fas fa-exchange-alt"></i>
</button>
<button class="btn btn-danger btn-sm" onclick="deleteStudent(<?php echo $student->id; ?>)" title="Eliminar">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
<!-- Modal completo para agregar/editar estudiante -->
<div class="modal-overlay" id="student-modal">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="modal-title">Nuevo Estudiante</h2>
<p class="modal-subtitle" id="modal-subtitle">Completa la información del estudiante</p>
<button class="btn-close" onclick="closeStudentModal()">
<i class="fas fa-xmark"></i>
</button>
</div>
<div class="modal-tabs">
<button class="tab-btn active" data-tab="personal">
<i class="fas fa-user"></i>
Datos Personales
</button>
<button class="tab-btn" data-tab="contact">
<i class="fas fa-phone"></i>
Contacto
</button>
<button class="tab-btn" data-tab="emergency">
<i class="fas fa-exclamation-triangle"></i>
Emergencia
</button>
<button class="tab-btn" data-tab="additional">
<i class="fas fa-info-circle"></i>
Adicional
</button>
</div>
<form id="student-form">
<div class="modal-body">
<!-- Tab 1: Datos Personales -->
<div class="tab-content active" id="personal-tab">
<h3 class="tab-title">
<i class="fas fa-user"></i>
Información Personal
</h3>
<div class="form-grid">
<div class="form-group">
<label>Nombre *</label>
<input type="text" name="first_name" id="first_name" class="form-control">
</div>
<div class="form-group">
<label>Apellido *</label>
<input type="text" name="last_name" id="last_name" class="form-control">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>Fecha de Nacimiento</label>
<input type="date" name="date_of_birth" id="date_of_birth" class="form-control">
</div>
<div class="form-group">
<label>Género</label>
<select name="gender" id="gender" class="form-control">
<option value="">Seleccionar...</option>
<option value="male">Masculino</option>
<option value="female">Femenino</option>
<option value="other">Otro</option>
<option value="prefer_not_to_say">Prefiero no decir</option>
</select>
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>País de Origen</label>
<select name="country_of_origin" id="country_of_origin" class="form-control">
<option value="">Seleccionar país...</option>
<option value="Guatemala">Guatemala</option>
<option value="México">México</option>
<option value="Estados Unidos">Estados Unidos</option>
<option value="Honduras">Honduras</option>
<option value="El Salvador">El Salvador</option>
<option value="Nicaragua">Nicaragua</option>
<option value="Costa Rica">Costa Rica</option>
<option value="Panamá">Panamá</option>
<option value="Colombia">Colombia</option>
<option value="España">España</option>
<option value="Otro">Otro</option>
</select>
</div>
<div class="form-group">
<label>Nacionalidad</label>
<input type="text" name="nationality" id="nationality" class="form-control" placeholder="Ej: Guatemalteca">
</div>
</div>
<div class="form-group form-group-full">
<label>Documento de Identidad</label>
<input type="text" name="identity_document" id="identity_document" class="form-control" placeholder="DPI, Pasaporte, Cédula, etc.">
</div>
</div>
<!-- Tab 2: Información de Contacto -->
<div class="tab-content" id="contact-tab">
<h3 class="tab-title">
<i class="fas fa-phone"></i>
Información de Contacto
</h3>
<div class="form-group">
<label>Email Personal</label>
<input type="email" name="email" id="email" class="form-control" placeholder="estudiante@email.com">
<div class="help-text">Email principal de comunicación (opcional)</div>
</div>
<div class="form-group">
<label>Teléfono Personal</label>
<input type="tel" name="phone" id="phone" class="form-control" placeholder="Ej: +502 1234-5678">
</div>
<div class="form-grid">
<div class="form-group">
<label>Ciudad</label>
<input type="text" name="city" id="city" class="form-control" placeholder="Ciudad donde reside">
</div>
</div>
<div class="form-group">
<label>Dirección Completa</label>
<textarea name="address" id="address" rows="3" class="form-control" placeholder="Dirección completa del estudiante"></textarea>
</div>
</div>
<!-- Tab 3: Contacto de Emergencia -->
<div class="tab-content" id="emergency-tab">
<h3 class="tab-title">
<i class="fas fa-exclamation-triangle"></i>
Contacto de Emergencia
</h3>
<div class="form-group">
<label>Nombre del Responsable/Tutor</label>
<input type="text" name="emergency_contact" id="emergency_contact" class="form-control" placeholder="Nombre completo del contacto de emergencia">
</div>
<div class="form-grid">
<div class="form-group">
<label>Email del Responsable</label>
<input type="email" name="emergency_email" id="emergency_email" class="form-control" placeholder="responsable@email.com">
</div>
<div class="form-group">
<label>Teléfono de Emergencia</label>
<input type="tel" name="emergency_phone" id="emergency_phone" class="form-control" placeholder="Ej: +502 1234-5678">
</div>
</div>
<div class="form-group">
<label>Relación</label>
<select name="emergency_relationship" id="emergency_relationship" class="form-control">
<option value="">Seleccionar relación...</option>
<option value="parent">Padre/Madre</option>
<option value="guardian">Tutor/Guardián</option>
<option value="spouse">Cónyuge</option>
<option value="sibling">Hermano/a</option>
<option value="friend">Amigo/a</option>
<option value="other">Otro</option>
</select>
</div>
<div class="info-box">
<p>
<i class="fas fa-info-circle"></i>
<strong>Información importante:</strong> Esta información se usará únicamente en caso de emergencia y es completamente opcional.
</p>
</div>
</div>
<!-- Tab 4: Información Adicional -->
<div class="tab-content" id="additional-tab">
<h3 class="tab-title">
<i class="fas fa-info-circle"></i>
Información Adicional
</h3>
<div class="form-group">
<label>¿Cómo se enteró de la academia?</label>
<select name="how_did_you_hear" id="how_did_you_hear" class="form-control">
<option value="">Seleccionar opción...</option>
<option value="facebook">Facebook</option>
<option value="instagram">Instagram</option>
<option value="google">Google/Internet</option>
<option value="friend_family">Amigo/Familiar</option>
<option value="student">Estudiante actual</option>
<option value="flyer">Volante/Publicidad</option>
<option value="radio">Radio</option>
<option value="newspaper">Periódico</option>
<option value="street_sign">Rótulo en la calle</option>
<option value="other">Otro</option>
</select>
</div>
<div class="form-group">
<label>¿Quién lo refirió?</label>
<input type="text" name="referred_by" id="referred_by" class="form-control" placeholder="Nombre de la persona que lo refirió (opcional)">
</div>
<div class="form-group">
<label>Observaciones Especiales</label>
<textarea name="special_notes" id="special_notes" rows="4" class="form-control" placeholder="Cualquier información adicional relevante..."></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-secondary btn-nav" id="prev-tab" style="display: none;" onclick="previousTab()">
<i class="fas fa-chevron-left"></i> Anterior
</button>
</div>
<div>
<button type="button" class="btn btn-secondary" onclick="closeStudentModal()">Cancelar</button>
<button type="button" class="btn btn-primary btn-nav" id="next-tab" onclick="nextTab()">
Siguiente <i class="fas fa-chevron-right"></i>
</button>
<button type="submit" class="btn btn-primary" id="save-btn" style="display: none;">
<i class="fas fa-save"></i> Guardar Estudiante
</button>
</div>
</div>
<input type="hidden" name="student_id" id="student_id" value="0">
</form>
</div>
</div>
<!-- Dropdown para cambio de estado -->
<div class="status-dropdown" id="status-dropdown" style="display: none;">
<div class="dropdown-content" id="status-dropdown-content">
<a class="dropdown-item" onclick="changeStudentStatus('active')">
<i class="fas fa-check-circle" style="color: var(--wes-success);"></i> Activo
</a>
<a class="dropdown-item" onclick="changeStudentStatus('inactive')">
<i class="fas fa-times-circle" style="color: var(--wes-danger);"></i> Inactivo
</a>
<a class="dropdown-item" onclick="changeStudentStatus('graduated')">
<i class="fas fa-graduation-cap" style="color: var(--wes-info);"></i> Graduado
</a>
<a class="dropdown-item" onclick="changeStudentStatus('suspended')">
<i class="fas fa-pause-circle" style="color: var(--wes-warning);"></i> Suspendido
</a>
<a class="dropdown-item" onclick="changeStudentStatus('retired')">
<i class="fas fa-sign-out-alt" style="color: #6c757d;"></i> Retirado
</a>
</div>
</div>
<!-- Cargar jQuery, Bootstrap y Font Awesome -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
jQuery(document).ready(function($) {
// Variables globales
let currentTab = 0;
let currentStudentId = null;
const tabs = ['personal', 'contact', 'emergency', 'additional'];
// Event listeners
initializeEventListeners();
function initializeEventListeners() {
// Tabs
$('.tab-btn').click(function() {
const targetTab = $(this).data('tab');
const tabIndex = tabs.indexOf(targetTab);
showTab(tabIndex);
});
// Form submission
$('#student-form').submit(function(e) {
e.preventDefault();
e.stopPropagation();
saveStudent();
return false;
});
// Search functionality
$('#search-input').keyup(function(e) {
if (e.key === 'Enter') {
searchStudents();
}
});
// Close modal on outside click
$('#student-modal').click(function(e) {
if (e.target === this) {
closeStudentModal();
}
});
}
// Modal management
window.openStudentModal = function(studentId = null, mode = 'create') {
currentStudentId = studentId;
const modal = $('#student-modal');
const title = $('#modal-title');
const subtitle = $('#modal-subtitle');
resetForm();
if (mode === 'edit' && studentId) {
title.text('Editar Estudiante');
subtitle.text('Actualiza la información del estudiante');
modal.addClass('show');
showTab(0);
setTimeout(() => {
loadStudentData(studentId);
}, 500);
} else {
title.text('Nuevo Estudiante');
subtitle.text('Completa la información del estudiante');
modal.addClass('show');
showTab(0);
}
};
window.closeStudentModal = function() {
const modal = $('#student-modal');
modal.removeClass('show');
setTimeout(() => {
resetForm();
}, 300);
};
function loadStudentData(studentId) {
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_student',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
student_id: studentId
})
.done(function(response) {
if (response.success) {
const student = response.data;
Object.keys(student).forEach(key => {
const field = document.getElementById(key);
if (field && student[key] !== null && student[key] !== undefined) {
field.value = student[key];
}
});
$('#student_id').val(studentId);
showNotification('Datos cargados correctamente', 'success');
} else {
showNotification('Error al cargar los datos: ' + response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión al cargar los datos', 'error');
});
}
function resetForm() {
$('#student-form')[0].reset();
$('#student_id').val('0');
currentStudentId = null;
currentTab = 0;
}
// Tab navigation
function showTab(tabIndex) {
currentTab = tabIndex;
$('.tab-content').removeClass('active');
$('.tab-btn').removeClass('active');
$(`#${tabs[tabIndex]}-tab`).addClass('active');
$(`.tab-btn[data-tab="${tabs[tabIndex]}"]`).addClass('active');
$('#prev-tab').toggle(tabIndex > 0);
$('#next-tab').toggle(tabIndex < tabs.length - 1);
$('#save-btn').toggle(tabIndex === tabs.length - 1);
}
window.nextTab = function() {
if (validateCurrentTab() && currentTab < tabs.length - 1) {
showTab(currentTab + 1);
}
};
window.previousTab = function() {
if (currentTab > 0) {
showTab(currentTab - 1);
}
};
function validateCurrentTab() {
const currentTabName = tabs[currentTab];
if (currentTabName === 'personal') {
const firstName = $('#first_name').val().trim();
const lastName = $('#last_name').val().trim();
if (!firstName) {
showNotification('El nombre es requerido', 'error');
$('#first_name').focus();
return false;
}
if (!lastName) {
showNotification('El apellido es requerido', 'error');
$('#last_name').focus();
return false;
}
}
if (currentTabName === 'contact') {
const email = $('#email').val().trim();
if (email && !isValidEmail(email)) {
showNotification('El formato del email no es válido', 'error');
$('#email').focus();
return false;
}
}
return true;
}
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// Student operations
window.editStudent = function(studentId) {
openStudentModal(studentId, 'edit');
};
window.deleteStudent = function(studentId) {
if (!confirm('¿Estás seguro de eliminar este estudiante?\n\nEsta acción no se puede deshacer.')) {
return;
}
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_delete_student',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
student_id: studentId
})
.done(function(response) {
if (response.success) {
showNotification('Estudiante eliminado correctamente', 'success');
setTimeout(() => {
location.reload();
}, 1000);
} else {
showNotification('Error al eliminar: ' + response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión al eliminar', 'error');
});
};
window.showStatusDropdown = function(event, studentId) {
event.stopPropagation();
currentStudentId = studentId;
const dropdown = $('#status-dropdown');
const dropdownContent = $('#status-dropdown-content');
const rect = event.target.getBoundingClientRect();
dropdown.css({
position: 'fixed',
top: rect.bottom + 5 + 'px',
left: rect.left + 'px',
display: 'block'
});
dropdownContent.addClass('show');
setTimeout(() => {
$(document).on('click', closeStatusDropdown);
}, 100);
};
function closeStatusDropdown() {
const dropdown = $('#status-dropdown');
const dropdownContent = $('#status-dropdown-content');
dropdownContent.removeClass('show');
dropdown.hide();
$(document).off('click', closeStatusDropdown);
}
window.changeStudentStatus = function(newStatus) {
if (!currentStudentId) return;
const statusLabels = {
'active': 'Activo',
'inactive': 'Inactivo',
'graduated': 'Graduado',
'suspended': 'Suspendido',
'retired': 'Retirado'
};
if (!confirm(`¿Cambiar estado del estudiante a "${statusLabels[newStatus]}"?`)) {
closeStatusDropdown();
return;
}
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_update_student_status',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
student_id: currentStudentId,
status: newStatus
})
.done(function(response) {
if (response.success) {
showNotification(`Estado cambiado a "${statusLabels[newStatus]}"`, 'success');
setTimeout(() => location.reload(true), 1000);
} else {
showNotification('Error: ' + response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión', 'error');
});
closeStatusDropdown();
};
function saveStudent() {
if (!validateCurrentTab()) {
return;
}
const saveBtn = $('#save-btn');
const originalText = saveBtn.html();
saveBtn.html('<div class="spinner"></div> Guardando...').prop('disabled', true);
const formData = {
action: 'wes_save_student',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
student_id: $('#student_id').val(),
first_name: $('#first_name').val().trim(),
last_name: $('#last_name').val().trim(),
date_of_birth: $('#date_of_birth').val(),
gender: $('#gender').val(),
country_of_origin: $('#country_of_origin').val(),
nationality: $('#nationality').val(),
identity_document: $('#identity_document').val(),
email: $('#email').val().trim(),
phone: $('#phone').val(),
city: $('#city').val(),
address: $('#address').val(),
emergency_contact: $('#emergency_contact').val(),
emergency_email: $('#emergency_email').val(),
emergency_phone: $('#emergency_phone').val(),
emergency_relationship: $('#emergency_relationship').val(),
how_did_you_hear: $('#how_did_you_hear').val(),
referred_by: $('#referred_by').val(),
special_notes: $('#special_notes').val(),
current_level: 'beginner',
status: 'active',
notes: $('#special_notes').val()
};
$.post('<?php echo admin_url('admin-ajax.php'); ?>', formData)
.done(function(response) {
if (response.success) {
const isEdit = parseInt($('#student_id').val()) > 0;
const message = isEdit ? 'Estudiante actualizado correctamente' : 'Estudiante registrado correctamente';
showNotification(message, 'success');
closeStudentModal();
// Recargar datos y página
setTimeout(() => {
location.reload(true); // Forzar recarga desde servidor
}, 500);
} else {
showNotification('Error: ' + response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión. Intenta de nuevo.', 'error');
})
.always(function() {
saveBtn.html(originalText).prop('disabled', false);
});
}
// Search functions
window.searchStudents = function() {
const searchTerm = $('#search-input').val();
const statusFilter = $('#status-filter').val();
const params = new URLSearchParams();
if (searchTerm) params.append('search', searchTerm);
if (statusFilter) params.append('status', statusFilter);
if (params.toString()) {
window.location.href = window.location.pathname + '?' + params.toString() + '&t=' + new Date().getTime();
}
};
window.clearSearch = function() {
$('#search-input').val('');
$('#status-filter').val('');
window.location.href = window.location.pathname;
};
function showNotification(message, type) {
const notification = $(`
<div class="wes-notification wes-notification-${type}" style="
position: fixed;
top: 20px;
right: 20px;
background: ${type === 'success' ? '#d4edda' : '#f8d7da'};
color: ${type === 'success' ? '#155724' : '#721c24'};
padding: 15px 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000000;
max-width: 400px;
border: 1px solid ${type === 'success' ? '#c3e6cb' : '#f5c6cb'};
">
<strong>${message}</strong>
</div>
`);
$('body').append(notification);
setTimeout(function() {
notification.fadeOut(function() {
$(this).remove();
});
}, 5000);
}
// Inicializar
showTab(0);
// Cargar datos iniciales del frontend
loadStudentsData();
function loadStudentsData() {
// Cargar estadísticas
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_students_stats',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
$('.stat-card.total .stat-number').text(response.data.total_students);
$('.stat-card.active .stat-number').text(response.data.active_students);
$('.stat-card.new .stat-number').text(response.data.new_students_30_days);
}
});
// NO recargar página - solo actualizar estadísticas
}
});
</script>
<?php wp_footer(); ?>
</body>
</html>