<?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();
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1″>
<title>Configuración – Working English International</title>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<!-- CSS PROFESIONAL -->
<style>
/* 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 igual al de estudiantes */
.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;
}
.company-info {
text-align: center;
color: white;
}
.company-name {
font-size: 36px;
font-weight: 800;
margin: 0;
color: white;
text-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
.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;
}
.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;
}
/* Navbar de navegación */
.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: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 i {
font-size: 16px;
width: 20px;
text-align: center;
}
/* Contenedor principal */
.wes-config-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* Header del módulo */
.wes-config-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding: 25px;
background: linear-gradient(135deg, var(--wes-primary), var(--wes-secondary));
border-radius: 12px;
color: white;
box-shadow: var(--wes-shadow);
}
.wes-config-header h1 {
margin: 0;
font-size: 28px;
font-weight: 600;
display: flex;
align-items: center;
gap: 15px;
}
.wes-config-header p {
margin: 8px 0 0;
opacity: 0.9;
font-size: 16px;
}
/* Tabs de configuración */
.config-tabs {
display: flex;
background: white;
border-radius: 12px;
box-shadow: var(--wes-shadow);
margin-bottom: 20px;
overflow: hidden;
}
.config-tab {
flex: 1;
padding: 20px;
text-align: center;
background: #f8f9fa;
border: none;
cursor: pointer;
transition: all 0.3s ease;
color: #666;
font-weight: 500;
border-bottom: 3px solid transparent;
}
.config-tab:hover {
background: #e9ecef;
color: var(--wes-primary);
}
.config-tab.active {
background: white;
color: var(--wes-primary);
border-bottom-color: var(--wes-primary);
}
.config-tab i {
display: block;
font-size: 2rem;
margin-bottom: 10px;
}
/* Contenido de las tabs */
.tab-content {
display: none;
background: white;
border-radius: 12px;
box-shadow: var(--wes-shadow);
overflow: hidden;
}
.tab-content.active {
display: block;
}
.tab-header {
padding: 20px 25px;
background: var(--wes-light);
border-bottom: 1px solid var(--wes-border);
display: flex;
justify-content: space-between;
align-items: center;
}
.tab-title {
margin: 0;
font-size: 20px;
color: var(--wes-dark);
display: flex;
align-items: center;
gap: 10px;
}
.tab-body {
padding: 25px;
}
/* Botones de acción – MÁS PEQUEÑOS */
.btn {
padding: 8px 16px;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
line-height: 1.2;
}
.btn-primary {
background: var(--wes-primary);
color: white;
}
.btn-primary:hover {
background: var(--wes-secondary);
transform: translateY(-1px);
color: white;
text-decoration: none;
}
.btn-success {
background: var(--wes-success);
color: #333;
}
.btn-warning {
background: var(--wes-warning);
color: #333;
}
.btn-danger {
background: var(--wes-danger);
color: white;
}
.btn-sm {
padding: 8px 16px;
font-size: 12px;
}
/* Tabla de datos */
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.data-table th {
background: #f8f9fa;
padding: 12px;
text-align: left;
font-weight: 600;
color: var(--wes-dark);
border-bottom: 2px solid var(--wes-border);
}
.data-table td {
padding: 12px;
border-bottom: 1px solid #f0f0f0;
vertical-align: middle;
}
.data-table tbody tr:hover {
background: #f8f9ff;
}
/* Estado de carga */
.loading-state {
text-align: center;
padding: 3rem;
color: #666;
}
.spinner {
width: 40px;
height: 40px;
border: 3px solid #f3f3f3;
border-top: 3px solid var(--wes-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Modal para formularios – AJUSTADO PARA MEJOR VISUALIZACIÓN */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
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 {
background: white;
border-radius: 12px;
max-width: 1000px;
width: 95%;
max-height: 95vh;
overflow: hidden;
transform: scale(0.9);
transition: all 0.3s ease;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
}
.modal-overlay.show .modal-content {
transform: scale(1);
}
/* Modal header – MÁS COMPACTO */
.modal-header {
padding: 15px 20px;
background: linear-gradient(135deg, var(--wes-primary), var(--wes-secondary));
color: white;
position: relative;
flex-shrink: 0;
}
.modal-title {
margin: 0;
font-size: 18px;
font-weight: 600;
}
.btn-close {
position: absolute;
top: 10px;
right: 15px;
background: rgba(255,255,255,0.2);
border: none;
color: white;
font-size: 20px;
cursor: pointer;
padding: 5px 10px;
border-radius: 6px;
transition: all 0.3s ease;
line-height: 1;
}
.btn-close:hover {
background: rgba(255,255,255,0.3);
}
/* Modal body – MÁS COMPACTO */
.modal-body {
padding: 12px 16px;
flex-grow: 1;
overflow-y: auto;
max-height: 65vh;
font-size: 12px;
}
.modal-footer {
padding: 12px 20px;
background: #f8f9fa;
border-top: 1px solid var(--wes-border);
display: flex;
justify-content: flex-end;
gap: 8px;
flex-shrink: 0;
}
/* Formularios – MÁS COMPACTOS Y PEQUEÑOS */
.form-group {
margin-bottom: 8px;
}
.form-label {
display: block;
margin-bottom: 3px;
font-weight: 600;
color: var(--wes-dark);
font-size: 11px;
}
.form-label.required::after {
content: ' *';
color: var(--wes-danger);
}
.form-control {
width: 85%;
padding: 6px 8px;
border: 2px solid #e0e0e0;
border-radius: 4px;
font-size: 12px;
transition: all 0.3s ease;
height: 32px;
}
.form-control:focus {
outline: none;
border-color: var(--wes-primary);
box-shadow: 0 0 0 2px rgba(177, 156, 217, 0.1);
}
.form-control[type="textarea"],
textarea.form-control {
height: auto;
min-height: 50px;
resize: vertical;
padding: 6px 8px;
width: 85%;
}
select.form-control {
height: 32px;
padding: 5px 8px;
width: 85%;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.form-help {
font-size: 9px;
color: #666;
margin-top: 1px;
line-height: 1.2;
}
.form-control::placeholder {
font-size: 11px;
color: #999;
}
/* Responsive – MEJOR PARA MODALES */
@media (max-width: 768px) {
.wes-config-container {
padding: 10px;
}
.config-tabs {
flex-direction: column;
}
.config-tab {
text-align: left;
padding: 15px 20px;
}
.config-tab i {
display: inline-block;
margin-right: 10px;
margin-bottom: 0;
font-size: 1.2rem;
}
.form-grid {
grid-template-columns: 1fr;
gap: 8px;
}
.modal-content {
width: 98%;
margin: 5px;
max-height: 98vh;
}
.modal-body {
padding: 10px 12px;
max-height: 70vh;
}
.modal-header {
padding: 12px 15px;
}
.modal-footer {
padding: 12px 15px;
}
.form-control {
height: 30px;
padding: 5px 7px;
font-size: 11px;
}
.form-label {
font-size: 10px;
}
}
</style>
<!-- Cargar Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Encabezado Corporativo Premium -->
<div class="wes-corporate-header">
<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>
<!-- Barra de navegación -->
<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">
<i class="fas fa-users"></i>
Estudiantes
</a>
<a href="/configuracion" class="nav-item active">
<i class="fas fa-cogs"></i>
Configuración
</a>
</nav>
</div>
<div class="wes-config-container">
<!-- Header -->
<div class="wes-config-header">
<div>
<h1>
<i class="fas fa-cogs"></i>
Configuración del Sistema
</h1>
<p>Gestiona sedes, idiomas, programas y niveles de forma fácil</p>
</div>
</div>
<!-- Tabs de configuración -->
<div class="config-tabs">
<button class="config-tab active" data-tab="branches">
<i class="fas fa-building"></i>
Sedes
</button>
<button class="config-tab" data-tab="languages">
<i class="fas fa-language"></i>
Idiomas
</button>
<button class="config-tab" data-tab="programs">
<i class="fas fa-graduation-cap"></i>
Programas
</button>
<button class="config-tab" data-tab="levels">
<i class="fas fa-layer-group"></i>
Niveles
</button>
</div>
<!-- Tab 1: Sedes -->
<div class="tab-content active" id="branches-tab">
<div class="tab-header">
<h2 class="tab-title">
<i class="fas fa-building"></i>
Gestión de Sedes
</h2>
<button class="btn btn-primary" onclick="openBranchModal()">
<i class="fas fa-plus"></i>
Nueva Sede
</button>
</div>
<div class="tab-body">
<div class="loading-state" id="branches-loading">
<div class="spinner"></div>
<p>Cargando sedes…</p>
</div>
<div id="branches-content" style="display: none;">
<table class="data-table" id="branches-table">
<thead>
<tr>
<th>Código</th>
<th>Nombre</th>
<th>Ciudad</th>
<th>País</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody id="branches-tbody">
</tbody>
</table>
</div>
</div>
</div>
<!-- Tab 2: Idiomas -->
<div class="tab-content" id="languages-tab">
<div class="tab-header">
<h2 class="tab-title">
<i class="fas fa-language"></i>
Gestión de Idiomas
</h2>
<button class="btn btn-primary" onclick="openLanguageModal()">
<i class="fas fa-plus"></i>
Nuevo Idioma
</button>
</div>
<div class="tab-body">
<div class="loading-state" id="languages-loading">
<div class="spinner"></div>
<p>Cargando idiomas…</p>
</div>
<div id="languages-content" style="display: none;">
<table class="data-table" id="languages-table">
<thead>
<tr>
<th>Código</th>
<th>Nombre</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody id="languages-tbody">
</tbody>
</table>
</div>
</div>
</div>
<!-- Tab 3: Programas -->
<div class="tab-content" id="programs-tab">
<div class="tab-header">
<h2 class="tab-title">
<i class="fas fa-graduation-cap"></i>
Gestión de Programas
</h2>
<button class="btn btn-primary" onclick="openProgramModal()">
<i class="fas fa-plus"></i>
Nuevo Programa
</button>
</div>
<div class="tab-body">
<div class="loading-state" id="programs-loading">
<div class="spinner"></div>
<p>Cargando programas…</p>
</div>
<div id="programs-content" style="display: none;">
<table class="data-table" id="programs-table">
<thead>
<tr>
<th>Idioma</th>
<th>Código</th>
<th>Nombre</th>
<th>Descripción</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody id="programs-tbody">
</tbody>
</table>
</div>
</div>
</div>
<!-- Tab 4: Niveles -->
<div class="tab-content" id="levels-tab">
<div class="tab-header">
<h2 class="tab-title">
<i class="fas fa-layer-group"></i>
Gestión de Niveles
</h2>
<button class="btn btn-primary" onclick="openLevelModal()">
<i class="fas fa-plus"></i>
Nuevo Nivel
</button>
</div>
<div class="tab-body">
<div class="loading-state" id="levels-loading">
<div class="spinner"></div>
<p>Cargando niveles…</p>
</div>
<div id="levels-content" style="display: none;">
<table class="data-table" id="levels-table">
<thead>
<tr>
<th>Idioma</th>
<th>Programa</th>
<th>Orden</th>
<th>Código</th>
<th>Nombre</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody id="levels-tbody">
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Modales para formularios -->
<!-- Modal de Sede -->
<div class="modal-overlay" id="branch-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="branch-modal-title">Nueva Sede</h3>
<button class="btn-close" onclick="closeBranchModal()">×</button>
</div>
<form id="branch-form">
<div class="modal-body">
<div class="form-grid">
<div class="form-group">
<label class="form-label required">Nombre</label>
<input type="text" name="name" id="branch-name" class="form-control" required>
</div>
<div class="form-group">
<label class="form-label required">Código</label>
<input type="text" name="code" id="branch-code" class="form-control" required>
<div class="form-help">Código único, ej: MAIN, NORTH</div>
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Ciudad</label>
<input type="text" name="city" id="branch-city" class="form-control">
</div>
<div class="form-group">
<label class="form-label">País</label>
<!-- REEMPLAZA ESTA SECCIÓN EN TU ARCHIVO -->
<!-- Busca esta línea: <select name="country" id="branch-country" class="form-control"> -->
<!-- Y reemplázala con todo esto: -->
<select name="country" id="branch-country" class="form-control">
<option value="">Seleccionar país…</option>
<option value="Afghanistan">Afghanistan</option>
<option value="Albania">Albania</option>
<option value="Algeria">Algeria</option>
<option value="Argentina">Argentina</option>
<option value="Armenia">Armenia</option>
<option value="Australia">Australia</option>
<option value="Austria">Austria</option>
<option value="Azerbaijan">Azerbaijan</option>
<option value="Bahrain">Bahrain</option>
<option value="Bangladesh">Bangladesh</option>
<option value="Belarus">Belarus</option>
<option value="Belgium">Belgium</option>
<option value="Bolivia">Bolivia</option>
<option value="Bosnia and Herzegovina">Bosnia and Herzegovina</option>
<option value="Brazil">Brazil</option>
<option value="Bulgaria">Bulgaria</option>
<option value="Cambodia">Cambodia</option>
<option value="Cameroon">Cameroon</option>
<option value="Canada">Canada</option>
<option value="Chile">Chile</option>
<option value="China">China</option>
<option value="Colombia">Colombia</option>
<option value="Costa Rica">Costa Rica</option>
<option value="Croatia">Croatia</option>
<option value="Cuba">Cuba</option>
<option value="Cyprus">Cyprus</option>
<option value="Czech Republic">Czech Republic</option>
<option value="Denmark">Denmark</option>
<option value="Dominican Republic">Dominican Republic</option>
<option value="Ecuador">Ecuador</option>
<option value="Egypt">Egypt</option>
<option value="El Salvador">El Salvador</option>
<option value="Estonia">Estonia</option>
<option value="Ethiopia">Ethiopia</option>
<option value="Finland">Finland</option>
<option value="France">France</option>
<option value="Georgia">Georgia</option>
<option value="Germany">Germany</option>
<option value="Ghana">Ghana</option>
<option value="Greece">Greece</option>
<option value="Guatemala">Guatemala</option>
<option value="Honduras">Honduras</option>
<option value="Hungary">Hungary</option>
<option value="Iceland">Iceland</option>
<option value="India">India</option>
<option value="Indonesia">Indonesia</option>
<option value="Iran">Iran</option>
<option value="Iraq">Iraq</option>
<option value="Ireland">Ireland</option>
<option value="Israel">Israel</option>
<option value="Italy">Italy</option>
<option value="Japan">Japan</option>
<option value="Jordan">Jordan</option>
<option value="Kazakhstan">Kazakhstan</option>
<option value="Kenya">Kenya</option>
<option value="Kuwait">Kuwait</option>
<option value="Latvia">Latvia</option>
<option value="Lebanon">Lebanon</option>
<option value="Libya">Libya</option>
<option value="Lithuania">Lithuania</option>
<option value="Luxembourg">Luxembourg</option>
<option value="Malaysia">Malaysia</option>
<option value="Malta">Malta</option>
<option value="Mexico">Mexico</option>
<option value="Morocco">Morocco</option>
<option value="Netherlands">Netherlands</option>
<option value="New Zealand">New Zealand</option>
<option value="Nicaragua">Nicaragua</option>
<option value="Nigeria">Nigeria</option>
<option value="Norway">Norway</option>
<option value="Pakistan">Pakistan</option>
<option value="Panama">Panama</option>
<option value="Paraguay">Paraguay</option>
<option value="Peru">Peru</option>
<option value="Philippines">Philippines</option>
<option value="Poland">Poland</option>
<option value="Portugal">Portugal</option>
<option value="Qatar">Qatar</option>
<option value="Romania">Romania</option>
<option value="Russia">Russia</option>
<option value="Saudi Arabia">Saudi Arabia</option>
<option value="Serbia">Serbia</option>
<option value="Singapore">Singapore</option>
<option value="Slovakia">Slovakia</option>
<option value="Slovenia">Slovenia</option>
<option value="South Africa">South Africa</option>
<option value="South Korea">South Korea</option>
<option value="Spain">Spain</option>
<option value="Sri Lanka">Sri Lanka</option>
<option value="Sweden">Sweden</option>
<option value="Switzerland">Switzerland</option>
<option value="Syria">Syria</option>
<option value="Taiwan">Taiwan</option>
<option value="Thailand">Thailand</option>
<option value="Tunisia">Tunisia</option>
<option value="Turkey">Turkey</option>
<option value="Ukraine">Ukraine</option>
<option value="United Arab Emirates">United Arab Emirates</option>
<option value="United Kingdom">United Kingdom</option>
<option value="United States">United States</option>
<option value="Uruguay">Uruguay</option>
<option value="Venezuela">Venezuela</option>
<option value="Vietnam">Vietnam</option>
<option value="Yemen">Yemen</option>
</select>
</div>
</div>
<div class="form-group">
<label class="form-label">Dirección</label>
<textarea name="address" id="branch-address" class="form-control" rows="3"></textarea>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label">Gerente</label>
<input type="text" name="manager_name" id="branch-manager" class="form-control">
</div>
<div class="form-group">
<label class="form-label">Teléfono</label>
<input type="text" name="phone" id="branch-phone" class="form-control">
</div>
</div>
<div class="form-group">
<label class="form-label">Email</label>
<input type="email" name="email" id="branch-email" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeBranchModal()">Cancelar</button>
<button type="submit" class="btn btn-primary" id="save-branch-btn">
<i class="fas fa-save"></i> Guardar Sede
</button>
</div>
<input type="hidden" name="branch_id" id="branch-id" value="0">
</form>
</div>
</div>
<!-- Modal de Idioma -->
<div class="modal-overlay" id="language-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="language-modal-title">Nuevo Idioma</h3>
<button class="btn-close" onclick="closeLanguageModal()">×</button>
</div>
<form id="language-form">
<div class="modal-body">
<div class="form-grid">
<div class="form-group">
<label class="form-label required">Nombre</label>
<input type="text" name="name" id="language-name" class="form-control" required>
<div class="form-help">Ej: English, Spanish, French</div>
</div>
<div class="form-group">
<label class="form-label required">Código</label>
<input type="text" name="code" id="language-code" class="form-control" required maxlength="3">
<div class="form-help">Código de 2-3 letras, ej: EN, ES, FR</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeLanguageModal()">Cancelar</button>
<button type="submit" class="btn btn-primary" id="save-language-btn">
<i class="fas fa-save"></i> Guardar Idioma
</button>
</div>
<input type="hidden" name="language_id" id="language-id" value="0">
</form>
</div>
</div>
<!-- Modal de Programa -->
<div class="modal-overlay" id="program-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="program-modal-title">Nuevo Programa</h3>
<button class="btn-close" onclick="closeProgramModal()">×</button>
</div>
<form id="program-form">
<div class="modal-body">
<div class="form-group">
<label class="form-label required">Idioma</label>
<select name="language_id" id="program-language" class="form-control" required>
<option value="">Seleccionar idioma…</option>
</select>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label required">Nombre</label>
<input type="text" name="name" id="program-name" class="form-control" required>
<div class="form-help">Ej: Kids Program, Professional</div>
</div>
<div class="form-group">
<label class="form-label required">Código</label>
<input type="text" name="code" id="program-code" class="form-control" required>
<div class="form-help">Ej: KIDS, PROF, BIZ</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Descripción</label>
<textarea name="description" id="program-description" class="form-control" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeProgramModal()">Cancelar</button>
<button type="submit" class="btn btn-primary" id="save-program-btn">
<i class="fas fa-save"></i> Guardar Programa
</button>
</div>
<input type="hidden" name="program_id" id="program-id" value="0">
</form>
</div>
</div>
<!-- Modal de Nivel -->
<div class="modal-overlay" id="level-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="level-modal-title">Nuevo Nivel</h3>
<button class="btn-close" onclick="closeLevelModal()">×</button>
</div>
<form id="level-form">
<div class="modal-body">
<div class="form-group">
<label class="form-label required">Programa</label>
<select name="program_id" id="level-program" class="form-control" required>
<option value="">Seleccionar programa…</option>
</select>
</div>
<div class="form-grid">
<div class="form-group">
<label class="form-label required">Nombre</label>
<input type="text" name="name" id="level-name" class="form-control" required>
<div class="form-help">Ej: Beginner, A1, Intermediate</div>
</div>
<div class="form-group">
<label class="form-label required">Código</label>
<input type="text" name="code" id="level-code" class="form-control" required>
<div class="form-help">Ej: BEG, A1, INT</div>
</div>
</div>
<div class="form-group">
<label class="form-label required">Orden</label>
<input type="number" name="order_number" id="level-order" class="form-control" required min="1">
<div class="form-help">Número que define el orden del nivel</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeLevelModal()">Cancelar</button>
<button type="submit" class="btn btn-primary" id="save-level-btn">
<i class="fas fa-save"></i> Guardar Nivel
</button>
</div>
<input type="hidden" name="level_id" id="level-id" value="0">
</form>
</div>
</div>
<!-- Modal de Idiomas por Sede -->
<div class="modal-overlay" id="branch-languages-modal">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="branch-languages-modal-title">Gestión de Idiomas</h3>
<button class="btn-close" onclick="closeBranchLanguagesModal()">×</button>
</div>
<div class="modal-body">
<div class="loading-state" id="branch-languages-loading">
<div class="spinner"></div>
<p>Cargando idiomas...</p>
</div>
<div id="branch-languages-content" style="display: none;">
<p style="color: #666; margin-bottom: 15px; font-size: 13px;">
<i class="fas fa-info-circle"></i>
Haz clic en los botones para asignar o desasignar idiomas a esta sede.
</p>
<div id="branch-languages-list">
<!-- Aquí se cargarán los idiomas -->
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeBranchLanguagesModal()">Cerrar</button>
</div>
</div>
</div>
<!-- JavaScript principal -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
jQuery(document).ready(function($) {
// Variables globales
let currentTab = 'branches';
let languages = [];
let programs = [];
// Inicializar
initializeTabs();
loadBranches();
// ===================================
// CARGAR PAÍSES
// ===================================
// ===================================
// MANEJO DE TABS
// ===================================
function initializeTabs() {
$('.config-tab').click(function() {
const tab = $(this).data('tab');
switchTab(tab);
});
}
function switchTab(tab) {
currentTab = tab;
// Actualizar tabs
$('.config-tab').removeClass('active');
$(`.config-tab[data-tab="${tab}"]`).addClass('active');
// Actualizar contenido
$('.tab-content').removeClass('active');
$(`#${tab}-tab`).addClass('active');
// Cargar datos según el tab
switch(tab) {
case 'branches':
loadBranches();
break;
case 'languages':
loadLanguages();
break;
case 'programs':
loadPrograms();
break;
case 'levels':
loadLevels();
break;
}
}
// ===================================
// SEDES
// ===================================
function loadBranches() {
$('#branches-loading').show();
$('#branches-content').hide();
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_branches',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
renderBranches(response.data);
$('#branches-content').show();
} else {
showNotification('Error al cargar sedes', 'error');
}
})
.always(function() {
$('#branches-loading').hide();
});
}
function renderBranches(branches) {
const tbody = $('#branches-tbody');
tbody.empty();
branches.forEach(branch => {
const statusClass = branch.status === 'active' ? 'success' : 'warning';
const statusText = branch.status === 'active' ? 'Activo' : 'Inactivo';
tbody.append(`
<tr>
<td><strong>${branch.code}</strong></td>
<td>${branch.name}</td>
<td>${branch.city || '-'}</td>
<td>${branch.country || '-'}</td>
<td><span class="btn btn-${statusClass} btn-sm">${statusText}</span></td>
<td>
<button class="btn btn-primary btn-sm" onclick="editBranch(${branch.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-sm" onclick="deleteBranch(${branch.id})">
<i class="fas fa-trash"></i>
</button>
<button class="btn btn-warning btn-sm" onclick="manageBranchLanguages(${branch.id}, '${branch.name}')">
<i class="fas fa-language"></i>
</button>
</td>
</tr>
`);
});
}
window.openBranchModal = function(branchId = 0) {
$('#branch-id').val(branchId);
// Asegurar que los países estén cargados
if (branchId > 0) {
$('#branch-modal-title').text('Editar Sede');
// Cargar datos de la sede
loadBranchData(branchId);
} else {
$('#branch-modal-title').text('Nueva Sede');
$('#branch-form')[0].reset();
$('#branch-id').val('0');
}
$('#branch-modal').addClass('show');
};
window.closeBranchModal = function() {
$('#branch-modal').removeClass('show');
};
window.editBranch = function(branchId) {
openBranchModal(branchId);
};
window.deleteBranch = function(branchId) {
if (!confirm('¿Estás seguro de eliminar esta sede?')) return;
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_delete_branch',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
branch_id: branchId
})
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
loadBranches();
} else {
showNotification(response.data, 'error');
}
});
};
function loadBranchData(branchId) {
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_branches',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
const branch = response.data.find(b => b.id == branchId);
if (branch) {
$('#branch-name').val(branch.name || '');
$('#branch-code').val(branch.code || '');
$('#branch-address').val(branch.address || '');
$('#branch-city').val(branch.city || '');
$('#branch-country').val(branch.country || '');
$('#branch-manager').val(branch.manager_name || '');
$('#branch-phone').val(branch.phone || '');
$('#branch-email').val(branch.email || '');
}
}
});
}
$('#branch-form').submit(function(e) {
e.preventDefault();
const formData = {
action: 'wes_save_branch',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
branch_id: $('#branch-id').val(),
name: $('#branch-name').val(),
code: $('#branch-code').val(),
address: $('#branch-address').val(),
city: $('#branch-city').val(),
country: $('#branch-country').val(),
manager_name: $('#branch-manager').val(),
phone: $('#branch-phone').val(),
email: $('#branch-email').val(),
status: 'active'
};
const $btn = $('#save-branch-btn');
const originalText = $btn.html();
$btn.html('<i class="fas fa-spinner fa-spin"></i> Guardando…').prop('disabled', true);
$.post('<?php echo admin_url('admin-ajax.php'); ?>', formData)
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
closeBranchModal();
loadBranches();
} else {
// Manejar errores mejorados
showNotification(response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión. Intente nuevamente.', 'error');
})
.always(function() {
$btn.html(originalText).prop('disabled', false);
});
});
// ===================================
// IDIOMAS
// ===================================
function loadLanguages() {
$('#languages-loading').show();
$('#languages-content').hide();
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_languages',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
languages = response.data;
renderLanguages(response.data);
$('#languages-content').show();
updateProgramLanguageOptions();
} else {
showNotification('Error al cargar idiomas', 'error');
}
})
.always(function() {
$('#languages-loading').hide();
});
}
function renderLanguages(languages) {
const tbody = $('#languages-tbody');
tbody.empty();
languages.forEach(language => {
const statusClass = language.status === 'active' ? 'success' : 'warning';
const statusText = language.status === 'active' ? 'Activo' : 'Inactivo';
tbody.append(`
<tr>
<td><strong>${language.code}</strong></td>
<td>${language.name}</td>
<td><span class="btn btn-${statusClass} btn-sm">${statusText}</span></td>
<td>
<button class="btn btn-primary btn-sm" onclick="editLanguage(${language.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-sm" onclick="deleteLanguage(${language.id})">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
`);
});
}
function updateProgramLanguageOptions() {
const select = $('#program-language');
select.find('option:not(:first)').remove();
languages.forEach(language => {
if (language.status === 'active') {
select.append(`<option value="${language.id}">${language.name}</option>`);
}
});
}
window.openLanguageModal = function(languageId = 0) {
$('#language-id').val(languageId);
if (languageId > 0) {
$('#language-modal-title').text('Editar Idioma');
loadLanguageData(languageId);
} else {
$('#language-modal-title').text('Nuevo Idioma');
$('#language-form')[0].reset();
$('#language-id').val('0');
}
$('#language-modal').addClass('show');
};
window.closeLanguageModal = function() {
$('#language-modal').removeClass('show');
};
window.editLanguage = function(languageId) {
openLanguageModal(languageId);
};
window.deleteLanguage = function(languageId) {
if (!confirm('¿Estás seguro de eliminar este idioma?')) return;
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_delete_language',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
language_id: languageId
})
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
loadLanguages();
} else {
showNotification(response.data, 'error');
}
});
};
function loadLanguageData(languageId) {
const language = languages.find(l => l.id == languageId);
if (language) {
$('#language-name').val(language.name || '');
$('#language-code').val(language.code || '');
}
}
$('#language-form').submit(function(e) {
e.preventDefault();
const formData = {
action: 'wes_save_language',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
language_id: $('#language-id').val(),
name: $('#language-name').val(),
code: $('#language-code').val().toUpperCase(),
status: 'active'
};
const $btn = $('#save-language-btn');
const originalText = $btn.html();
$btn.html('<i class="fas fa-spinner fa-spin"></i> Guardando…').prop('disabled', true);
$.post('<?php echo admin_url('admin-ajax.php'); ?>', formData)
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
closeLanguageModal();
loadLanguages();
} else {
showNotification(response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión. Intente nuevamente.', 'error');
})
.always(function() {
$btn.html(originalText).prop('disabled', false);
});
});
// ===================================
// PROGRAMAS
// ===================================
function loadPrograms() {
$('#programs-loading').show();
$('#programs-content').hide();
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_programs',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
programs = response.data;
renderPrograms(response.data);
$('#programs-content').show();
updateLevelProgramOptions();
} else {
showNotification('Error al cargar programas', 'error');
}
})
.always(function() {
$('#programs-loading').hide();
});
}
function renderPrograms(programs) {
const tbody = $('#programs-tbody');
tbody.empty();
programs.forEach(program => {
const statusClass = program.status === 'active' ? 'success' : 'warning';
const statusText = program.status === 'active' ? 'Activo' : 'Inactivo';
tbody.append(`
<tr>
<td>${program.language_name}</td>
<td><strong>${program.code}</strong></td>
<td>${program.name}</td>
<td>${program.description || '-'}</td>
<td><span class="btn btn-${statusClass} btn-sm">${statusText}</span></td>
<td>
<button class="btn btn-primary btn-sm" onclick="editProgram(${program.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-sm" onclick="deleteProgram(${program.id})">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
`);
});
}
function updateLevelProgramOptions() {
const select = $('#level-program');
select.find('option:not(:first)').remove();
programs.forEach(program => {
if (program.status === 'active') {
select.append(`<option value="${program.id}">${program.language_name} – ${program.name}</option>`);
}
});
}
window.openProgramModal = function(programId = 0) {
$('#program-id').val(programId);
if (programId > 0) {
$('#program-modal-title').text('Editar Programa');
loadProgramData(programId);
} else {
$('#program-modal-title').text('Nuevo Programa');
$('#program-form')[0].reset();
$('#program-id').val('0');
}
$('#program-modal').addClass('show');
};
window.closeProgramModal = function() {
$('#program-modal').removeClass('show');
};
window.editProgram = function(programId) {
openProgramModal(programId);
};
window.deleteProgram = function(programId) {
if (!confirm('¿Estás seguro de eliminar este programa?')) return;
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_delete_program',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
program_id: programId
})
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
loadPrograms();
} else {
showNotification(response.data, 'error');
}
});
};
function loadProgramData(programId) {
const program = programs.find(p => p.id == programId);
if (program) {
$('#program-language').val(program.language_id || '');
$('#program-name').val(program.name || '');
$('#program-code').val(program.code || '');
$('#program-description').val(program.description || '');
}
}
$('#program-form').submit(function(e) {
e.preventDefault();
const formData = {
action: 'wes_save_program',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
program_id: $('#program-id').val(),
language_id: $('#program-language').val(),
name: $('#program-name').val(),
code: $('#program-code').val().toUpperCase(),
description: $('#program-description').val(),
status: 'active'
};
const $btn = $('#save-program-btn');
const originalText = $btn.html();
$btn.html('<i class="fas fa-spinner fa-spin"></i> Guardando…').prop('disabled', true);
$.post('<?php echo admin_url('admin-ajax.php'); ?>', formData)
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
closeProgramModal();
loadPrograms();
} else {
showNotification(response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión. Intente nuevamente.', 'error');
})
.always(function() {
$btn.html(originalText).prop('disabled', false);
});
});
// ===================================
// NIVELES
// ===================================
function loadLevels() {
$('#levels-loading').show();
$('#levels-content').hide();
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_levels',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
renderLevels(response.data);
$('#levels-content').show();
} else {
showNotification('Error al cargar niveles', 'error');
}
})
.always(function() {
$('#levels-loading').hide();
});
}
function renderLevels(levels) {
const tbody = $('#levels-tbody');
tbody.empty();
levels.forEach(level => {
const statusClass = level.status === 'active' ? 'success' : 'warning';
const statusText = level.status === 'active' ? 'Activo' : 'Inactivo';
tbody.append(`
<tr>
<td>${level.language_name}</td>
<td>${level.program_name}</td>
<td><strong>${level.order_number}</strong></td>
<td><strong>${level.code}</strong></td>
<td>${level.name}</td>
<td><span class="btn btn-${statusClass} btn-sm">${statusText}</span></td>
<td>
<button class="btn btn-primary btn-sm" onclick="editLevel(${level.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-sm" onclick="deleteLevel(${level.id})">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
`);
});
}
window.openLevelModal = function(levelId = 0) {
$('#level-id').val(levelId);
if (levelId > 0) {
$('#level-modal-title').text('Editar Nivel');
loadLevelData(levelId);
} else {
$('#level-modal-title').text('Nuevo Nivel');
$('#level-form')[0].reset();
$('#level-id').val('0');
}
$('#level-modal').addClass('show');
};
window.closeLevelModal = function() {
$('#level-modal').removeClass('show');
};
window.editLevel = function(levelId) {
openLevelModal(levelId);
};
window.deleteLevel = function(levelId) {
if (!confirm('¿Estás seguro de eliminar este nivel?')) return;
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_delete_level',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
level_id: levelId
})
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
loadLevels();
} else {
showNotification(response.data, 'error');
}
});
};
function loadLevelData(levelId) {
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_levels',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>'
})
.done(function(response) {
if (response.success) {
const level = response.data.find(l => l.id == levelId);
if (level) {
$('#level-program').val(level.program_id || '');
$('#level-name').val(level.name || '');
$('#level-code').val(level.code || '');
$('#level-order').val(level.order_number || 1);
}
}
});
}
$('#level-form').submit(function(e) {
e.preventDefault();
const formData = {
action: 'wes_save_level',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
level_id: $('#level-id').val(),
program_id: $('#level-program').val(),
name: $('#level-name').val(),
code: $('#level-code').val().toUpperCase(),
order_number: $('#level-order').val(),
status: 'active'
};
const $btn = $('#save-level-btn');
const originalText = $btn.html();
$btn.html('<i class="fas fa-spinner fa-spin"></i> Guardando…').prop('disabled', true);
$.post('<?php echo admin_url('admin-ajax.php'); ?>', formData)
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
closeLevelModal();
loadLevels();
} else {
showNotification(response.data, 'error');
}
})
.fail(function() {
showNotification('Error de conexión. Intente nuevamente.', 'error');
})
.always(function() {
$btn.html(originalText).prop('disabled', false);
});
});
// ===================================
// UTILIDADES
// ===================================
function showNotification(message, type = 'info') {
// Manejar respuestas de error mejoradas
let finalMessage = message;
let finalType = type;
if (typeof message === 'object' && message.type) {
finalMessage = message.message;
if (message.type === 'deleted_conflict') {
finalType = 'warning';
} else if (message.type === 'active_conflict') {
finalType = 'error';
}
}
// Crear notificación estilizada
const alertClass = finalType === 'success' ? 'success' :
finalType === 'error' ? 'danger' :
finalType === 'warning' ? 'warning' : 'info';
const iconClass = finalType === 'success' ? 'fas fa-check-circle' :
finalType === 'error' ? 'fas fa-exclamation-circle' :
finalType === 'warning' ? 'fas fa-exclamation-triangle' : 'fas fa-info-circle';
const notification = $(`
<div class="wes-notification alert-${alertClass}" style="
position: fixed;
top: 20px;
right: 20px;
z-index: 1000000;
min-width: 350px;
max-width: 500px;
background: white;
border-radius: 8px;
box-shadow: 0 6px 25px rgba(0,0,0,0.2);
border-left: 4px solid var(--alert-color);
padding: 16px 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
transform: translateX(100%);
transition: all 0.3s ease;
">
<div style="display: flex; align-items: flex-start; gap: 12px;">
<i class="${iconClass}" style="
color: var(--alert-color);
font-size: 18px;
margin-top: 2px;
flex-shrink: 0;
"></i>
<div style="flex-grow: 1;">
<div style="
font-weight: 600;
color: #333;
font-size: 14px;
line-height: 1.4;
margin-bottom: 4px;
">${getNotificationTitle(finalType)}</div>
<div style="
color: #666;
font-size: 13px;
line-height: 1.5;
">${finalMessage}</div>
</div>
<button type="button" class="notification-close" style="
background: none;
border: none;
font-size: 18px;
color: #999;
cursor: pointer;
padding: 0;
line-height: 1;
margin-left: 8px;
flex-shrink: 0;
">×</button>
</div>
</div>
`);
// Definir colores según el tipo
const colors = {
success: '#28a745',
danger: '#dc3545',
warning: '#ffc107',
info: '#17a2b8'
};
notification.css('--alert-color', colors[alertClass] || colors.info);
// Agregar al DOM
$('body').append(notification);
// Animar entrada
setTimeout(() => {
notification.css('transform', 'translateX(0)');
}, 100);
// Auto remove después de tiempo variable según tipo
const autoHideTime = finalType === 'warning' ? 8000 : 5000;
const autoHideTimeout = setTimeout(function() {
hideNotification(notification);
}, autoHideTime);
// Manual close
notification.find('.notification-close').click(function() {
clearTimeout(autoHideTimeout);
hideNotification(notification);
});
}
function getNotificationTitle(type) {
switch(type) {
case 'success': return 'Operación Exitosa';
case 'error': return 'Error';
case 'warning': return 'Atención - Código Duplicado';
default: return 'Información';
}
}
function hideNotification(notification) {
notification.css('transform', 'translateX(100%)');
setTimeout(function() {
notification.remove();
}, 300);
}
// Cerrar modales con ESC
$(document).keydown(function(e) {
if (e.keyCode === 27) { // ESC
$('.modal-overlay').removeClass('show');
}
});
// Cerrar modales al hacer clic fuera
$('.modal-overlay').click(function(e) {
if (e.target === this) {
$(this).removeClass('show');
}
});
// ===================================
// GESTIÓN SEDE-IDIOMAS (BOTÓN AMARILLO)
// ===================================
window.manageBranchLanguages = function(branchId, branchName) {
$('#branch-languages-modal-title').text(`Idiomas para: ${branchName}`);
$('#branch-languages-modal').addClass('show');
loadBranchLanguages(branchId);
};
window.closeBranchLanguagesModal = function() {
$('#branch-languages-modal').removeClass('show');
};
function loadBranchLanguages(branchId) {
$('#branch-languages-loading').show();
$('#branch-languages-content').hide();
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_get_branch_languages',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
branch_id: branchId
})
.done(function(response) {
if (response.success) {
renderBranchLanguages(response.data, branchId);
$('#branch-languages-content').show();
} else {
showNotification('Error al cargar idiomas de la sede', 'error');
}
})
.always(function() {
$('#branch-languages-loading').hide();
});
}
function renderBranchLanguages(languages, branchId) {
const container = $('#branch-languages-list');
container.empty();
languages.forEach(language => {
const isAssigned = language.assigned == 1;
const btnClass = isAssigned ? 'btn-success' : 'btn-secondary';
const btnText = isAssigned ? 'Asignado' : 'No Asignado';
const btnIcon = isAssigned ? 'fas fa-check' : 'fas fa-times';
container.append(`
<div class="language-assignment-item" style="display: flex; justify-content: space-between; align-items: center; padding: 10px; border: 1px solid #e0e0e0; margin-bottom: 5px; border-radius: 6px;">
<div>
<strong>${language.name}</strong> (${language.code})
</div>
<button class="btn ${btnClass} btn-sm" onclick="toggleBranchLanguage(${branchId}, ${language.id}, ${isAssigned ? 0 : 1}, this)">
<i class="${btnIcon}"></i> ${btnText}
</button>
</div>
`);
});
}
window.toggleBranchLanguage = function(branchId, languageId, assign, button) {
const $btn = $(button);
const originalHtml = $btn.html();
$btn.html('<i class="fas fa-spinner fa-spin"></i>').prop('disabled', true);
$.post('<?php echo admin_url('admin-ajax.php'); ?>', {
action: 'wes_toggle_branch_language',
nonce: '<?php echo wp_create_nonce('wes_nonce'); ?>',
branch_id: branchId,
language_id: languageId,
assign: assign
})
.done(function(response) {
if (response.success) {
showNotification(response.data, 'success');
loadBranchLanguages(branchId);
} else {
showNotification(response.data, 'error');
}
})
.always(function() {
$btn.html(originalHtml).prop('disabled', false);
});
};
});
</script>
<?php wp_footer(); ?>
</body>
</html>