Bot Discord - Commit completo con todos los cambios
This commit is contained in:
134
templates/admin/language_form.php
Executable file
134
templates/admin/language_form.php
Executable file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
$isEdit = isset($language) && !empty($language);
|
||||
$pageTitle = $isEdit ? 'Editar Idioma' : 'Agregar Idioma';
|
||||
$formAction = $isEdit ? "?action=edit&code=" . urlencode($language['code']) : '?action=add';
|
||||
$submitText = $isEdit ? 'Actualizar Idioma' : 'Agregar Idioma';
|
||||
|
||||
require_once __DIR__ . '/../header.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0" data-translate="<?php echo $isEdit ? 'edit_language' : 'add_language'; ?>">
|
||||
<?php echo $isEdit ? 'Editar Idioma' : 'Agregar Idioma'; ?>
|
||||
</h1>
|
||||
<a href="languages.php" class="btn btn-outline-secondary" data-translate="back_to_languages">Volver a Idiomas</a>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($error)): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="<?php echo $formAction; ?>" id="languageForm">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label" data-translate="language_name">Nombre del Idioma</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required
|
||||
value="<?php echo htmlspecialchars($language['name'] ?? ''); ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="native_name" class="form-label" data-translate="native_name">Nombre Nativo</label>
|
||||
<input type="text" class="form-control" id="native_name" name="native_name" required
|
||||
value="<?php echo htmlspecialchars($language['native_name'] ?? ''); ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="code" class="form-label" data-translate="language_code">Código de Idioma (ej: es, en, fr)</label>
|
||||
<input type="text" class="form-control" id="code" name="code" required
|
||||
pattern="[a-z]{2}(-[A-Z]{2})?"
|
||||
title="El código debe tener 2 letras minúsculas (ej: es, en, fr) o formato de localización (ej: es-ES, en-US)"
|
||||
<?php echo $isEdit ? 'readonly' : ''; ?>
|
||||
value="<?php echo htmlspecialchars($language['code'] ?? ''); ?>">
|
||||
<div class="form-text" data-translate="language_code_help">
|
||||
Usa códigos ISO 639-1 (ej: es, en, fr) o códigos de localización (ej: es-ES, en-US)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="flag_emoji" class="form-label" data-translate="flag_emoji">Emoji de Bandera</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" id="flag-preview"><?php echo htmlspecialchars($language['flag_emoji'] ?? '🏳️'); ?></span>
|
||||
<input type="text" class="form-control" id="flag_emoji" name="flag_emoji" required
|
||||
maxlength="4"
|
||||
value="<?php echo htmlspecialchars($language['flag_emoji'] ?? ''); ?>">
|
||||
</div>
|
||||
<div class="form-text" data-translate="flag_emoji_help">
|
||||
Ingresa un emoji de bandera (ej: 🇪🇸, 🇬🇧, 🇫🇷). Puedes copiarlos de <a href="https://emojicopy.com/" target="_blank">emojicopy.com</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-check">
|
||||
<input type="checkbox" class="form-check-input" id="is_active" name="is_active" value="1"
|
||||
<?php echo (isset($language['is_active']) && $language['is_active']) ? 'checked' : ''; ?>>
|
||||
<label class="form-check-label" for="is_active" data-translate="is_active">Activo</label>
|
||||
<div class="form-text" data-translate="is_active_help">
|
||||
Los idiomas inactivos no estarán disponibles para los usuarios
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<a href="languages.php" class="btn btn-secondary me-md-2" data-translate="cancel">Cancelar</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo $isEdit ? 'Actualizar Idioma' : 'Agregar Idioma'; ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Actualizar vista previa del emoji de bandera
|
||||
const flagEmojiInput = document.getElementById('flag_emoji');
|
||||
const flagPreview = document.getElementById('flag-preview');
|
||||
|
||||
if (flagEmojiInput && flagPreview) {
|
||||
flagEmojiInput.addEventListener('input', function() {
|
||||
flagPreview.textContent = this.value || '🏳️';
|
||||
});
|
||||
}
|
||||
|
||||
// Validación del formulario
|
||||
const form = document.getElementById('languageForm');
|
||||
if (form) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
// Validar código de idioma
|
||||
const codeInput = document.getElementById('code');
|
||||
if (codeInput && !/^[a-z]{2}(-[A-Z]{2})?$/.test(codeInput.value)) {
|
||||
e.preventDefault();
|
||||
alert('Por favor ingresa un código de idioma válido (ej: es, en, fr, es-ES, en-US)');
|
||||
codeInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validar emoji de bandera
|
||||
if (flagEmojiInput && !flagEmojiInput.value.trim()) {
|
||||
e.preventDefault();
|
||||
alert('Por favor ingresa un emoji de bandera');
|
||||
flagEmojiInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Traducir elementos con el atributo data-translate
|
||||
const elements = document.querySelectorAll('[data-translate]');
|
||||
elements.forEach(element => {
|
||||
const key = element.getAttribute('data-translate');
|
||||
if (translations[key]) {
|
||||
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
|
||||
element.placeholder = translations[key];
|
||||
} else {
|
||||
element.textContent = translations[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once __DIR__ . '/../footer.php'; ?>
|
||||
144
templates/admin/languages.php
Executable file
144
templates/admin/languages.php
Executable file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
$pageTitle = 'Gestión de Idiomas';
|
||||
require_once __DIR__ . '/../header.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0" data-translate="language_management">Gestión de Idiomas</h1>
|
||||
<a href="languages.php?action=add" class="btn btn-primary" data-translate="add_language">Agregar Idioma</a>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($message)): ?>
|
||||
<div class="alert alert-success"><?php echo htmlspecialchars($message); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($error)): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<?php if (empty($languages)): ?>
|
||||
<div class="text-center py-4">
|
||||
<p class="text-muted" data-translate="no_languages_found">No se encontraron idiomas configurados.</p>
|
||||
<a href="languages.php?action=add" class="btn btn-primary" data-translate="add_first_language">Agregar primer idioma</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-translate="flag">Bandera</th>
|
||||
<th data-translate="language_name">Nombre</th>
|
||||
<th data-translate="native_name">Nombre Nativo</th>
|
||||
<th data-translate="language_code">Código</th>
|
||||
<th data-translate="is_active">Activo</th>
|
||||
<th data-translate="actions">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($languages as $lang): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($lang['flag_emoji']); ?></td>
|
||||
<td><?php echo htmlspecialchars($lang['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($lang['native_name']); ?></td>
|
||||
<td><code><?php echo htmlspecialchars($lang['code']); ?></code></td>
|
||||
<td>
|
||||
<?php if ($lang['is_active']): ?>
|
||||
<span class="badge bg-success" data-translate="yes">Sí</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-secondary" data-translate="no">No</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="languages.php?action=translations&code=<?php echo urlencode($lang['code']); ?>"
|
||||
class="btn btn-outline-primary"
|
||||
title="Editar traducciones"
|
||||
data-translate="edit_translations">
|
||||
<i class="bi bi-translate"></i>
|
||||
</a>
|
||||
<a href="languages.php?action=edit&code=<?php echo urlencode($lang['code']); ?>"
|
||||
class="btn btn-outline-secondary"
|
||||
title="Editar idioma"
|
||||
data-translate="edit">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<?php if ($lang['code'] !== 'es' && $lang['code'] !== 'en'): ?>
|
||||
<a href="#"
|
||||
class="btn btn-outline-danger delete-language"
|
||||
data-code="<?php echo htmlspecialchars($lang['code']); ?>"
|
||||
title="Eliminar idioma"
|
||||
data-translate="delete">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<button class="btn btn-outline-secondary" disabled>
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de confirmación para eliminar idioma -->
|
||||
<div class="modal fade" id="deleteLanguageModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-translate="confirm_delete">Confirmar eliminación</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" data-translate="are_you_sure_delete_language">
|
||||
¿Estás seguro de que deseas eliminar este idioma? Todas sus traducciones también se eliminarán.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" data-translate="cancel">Cancelar</button>
|
||||
<a href="#" id="confirmDeleteBtn" class="btn btn-danger" data-translate="delete">Eliminar</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Manejar clic en botón de eliminar idioma
|
||||
document.querySelectorAll('.delete-language').forEach(button => {
|
||||
button.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const languageCode = this.getAttribute('data-code');
|
||||
const modal = new bootstrap.Modal(document.getElementById('deleteLanguageModal'));
|
||||
|
||||
// Actualizar el enlace de confirmación
|
||||
document.getElementById('confirmDeleteBtn').href = `languages.php?action=delete&code=${encodeURIComponent(languageCode)}`;
|
||||
|
||||
// Mostrar el modal
|
||||
modal.show();
|
||||
});
|
||||
});
|
||||
|
||||
// Traducir elementos con el atributo data-translate
|
||||
const elements = document.querySelectorAll('[data-translate]');
|
||||
elements.forEach(element => {
|
||||
const key = element.getAttribute('data-translate');
|
||||
if (translations[key]) {
|
||||
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
|
||||
element.placeholder = translations[key];
|
||||
} else {
|
||||
element.textContent = translations[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once __DIR__ . '/../footer.php'; ?>
|
||||
209
templates/admin/translations.php
Executable file
209
templates/admin/translations.php
Executable file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
$pageTitle = 'Traducciones: ' . htmlspecialchars($language['name']);
|
||||
require_once __DIR__ . '/../../includes/url_helper.php';
|
||||
require_once __DIR__ . '/../header.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0">
|
||||
<span data-translate="edit_translations">Editar Traducciones</span>:
|
||||
<?php echo htmlspecialchars($language['native_name'] . ' ' . $language['flag_emoji']); ?>
|
||||
</h1>
|
||||
<div>
|
||||
<a href="languages.php" class="btn btn-outline-secondary me-2" data-translate="back_to_languages">Volver a Idiomas</a>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addTranslationModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-translate="add_translation">Agregar Traducción</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($message)): ?>
|
||||
<div class="alert alert-success"><?php echo htmlspecialchars($message); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($error)): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<form method="POST" action="?action=translations&code=<?php echo urlencode($language['code']); ?>">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 40%;" data-translate="translation_key">Clave</th>
|
||||
<th style="width: 55%;" data-translate="translation_value">Valor</th>
|
||||
<th style="width: 5%;" data-translate="actions">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($translations)): ?>
|
||||
<tr>
|
||||
<td colspan="3" class="text-center py-4 text-muted" data-translate="no_translations_found">
|
||||
No se encontraron traducciones para este idioma.
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($translations as $translation): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" class="form-control form-control-sm"
|
||||
value="<?php echo htmlspecialchars($translation['key']); ?>"
|
||||
readonly>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control"
|
||||
name="translations[<?php echo $translation['id']; ?>]"
|
||||
value="<?php echo htmlspecialchars($translation['value']); ?>">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="?action=delete_translation&code=<?php echo urlencode($language['code']); ?>&id=<?php echo $translation['id']; ?>"
|
||||
class="btn btn-sm btn-outline-danger delete-translation"
|
||||
title="Eliminar traducción">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($translations)): ?>
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end mt-3">
|
||||
<button type="submit" name="update_translations" class="btn btn-primary" data-translate="save_changes">
|
||||
Guardar Cambios
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sección de ayuda -->
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header" data-translate="help_section">Ayuda</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" data-translate="how_to_use">¿Cómo usar las traducciones?</h5>
|
||||
<p data-translate="translation_help_1">
|
||||
Las claves de traducción se utilizan en todo el sistema para mostrar textos en diferentes idiomas.
|
||||
</p>
|
||||
<p data-translate="translation_help_2">
|
||||
Para usar una traducción en el código, utiliza la función <code>__('clave_de_traduccion')</code>.
|
||||
</p>
|
||||
<p data-translate="translation_help_3">
|
||||
En las plantillas, usa el atributo <code>data-translate="clave_de_traduccion"</code> en cualquier elemento HTML.
|
||||
</p>
|
||||
<div class="alert alert-info mt-3">
|
||||
<i class="bi bi-info-circle-fill me-2"></i>
|
||||
<span data-translate="translation_tip">
|
||||
Consejo: Usa nombres descriptivos para las claves de traducción, como 'welcome_message' o 'save_button'.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal para agregar nueva traducción -->
|
||||
<div class="modal fade" id="addTranslationModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST" action="?action=translations&code=<?php echo urlencode($language['code']); ?>">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-translate="add_translation">Agregar Traducción</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="new_key" class="form-label" data-translate="translation_key">Clave</label>
|
||||
<input type="text" class="form-control" id="new_key" name="key" required
|
||||
placeholder="Ej: welcome_message" pattern="[a-z0-9_]+(\.?[a-z0-9_]+)*"
|
||||
title="Usa solo letras minúsculas, números y guiones bajos">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="new_value" class="form-label" data-translate="translation_value">Valor</label>
|
||||
<input type="text" class="form-control" id="new_value" name="value" required
|
||||
placeholder="Ingresa el texto traducido">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" data-translate="cancel">Cancelar</button>
|
||||
<button type="submit" name="add_translation" class="btn btn-primary" data-translate="add">Agregar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de confirmación para eliminar traducción -->
|
||||
<div class="modal fade" id="deleteTranslationModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-translate="confirm_delete">Confirmar eliminación</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" data-translate="are_you_sure_delete_translation">
|
||||
¿Estás seguro de que deseas eliminar esta traducción?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" data-translate="cancel">Cancelar</button>
|
||||
<a href="#" id="confirmDeleteBtn" class="btn btn-danger" data-translate="delete">Eliminar</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Manejar clic en botón de eliminar traducción
|
||||
document.querySelectorAll('.delete-translation').forEach(button => {
|
||||
button.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const deleteUrl = this.getAttribute('href');
|
||||
const modal = new bootstrap.Modal(document.getElementById('deleteTranslationModal'));
|
||||
|
||||
// Actualizar el enlace de confirmación
|
||||
document.getElementById('confirmDeleteBtn').href = deleteUrl;
|
||||
|
||||
// Mostrar el modal
|
||||
modal.show();
|
||||
});
|
||||
});
|
||||
|
||||
// Validar formulario de agregar traducción
|
||||
const addTranslationForm = document.querySelector('#addTranslationModal form');
|
||||
if (addTranslationForm) {
|
||||
addTranslationForm.addEventListener('submit', function(e) {
|
||||
const keyInput = this.querySelector('input[name="key"]');
|
||||
if (keyInput && !/^[a-z0-9_]+(\.[a-z0-9_]+)*$/.test(keyInput.value)) {
|
||||
e.preventDefault();
|
||||
alert('La clave solo puede contener letras minúsculas, números, puntos y guiones bajos.');
|
||||
keyInput.focus();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Traducir elementos con el atributo data-translate
|
||||
const elements = document.querySelectorAll('[data-translate]');
|
||||
elements.forEach(element => {
|
||||
const key = element.getAttribute('data-translate');
|
||||
if (translations[key]) {
|
||||
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') {
|
||||
element.placeholder = translations[key];
|
||||
} else if (element.tagName === 'BUTTON' || element.tagName === 'A') {
|
||||
element.textContent = translations[key];
|
||||
} else {
|
||||
element.textContent = translations[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once __DIR__ . '/../footer.php'; ?>
|
||||
159
templates/footer.php
Executable file
159
templates/footer.php
Executable file
@@ -0,0 +1,159 @@
|
||||
</main>
|
||||
</div>
|
||||
<!-- /#page-content-wrapper -->
|
||||
</div>
|
||||
<!-- /#wrapper -->
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
||||
</main>
|
||||
</div>
|
||||
<!-- /#page-content-wrapper -->
|
||||
</div>
|
||||
<!-- /#wrapper -->
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
||||
<script src="<?php echo asset('js/summernote-bs5.min.js'); ?>" defer></script>
|
||||
<script src="<?php echo asset('js/main.js'); ?>" defer></script>
|
||||
|
||||
<!-- Script para el menú desplegable -->
|
||||
<script>
|
||||
// Función para inicializar el menú
|
||||
function initMenu() {
|
||||
const menuToggle = document.getElementById('menu-toggle');
|
||||
const wrapper = document.getElementById('wrapper');
|
||||
const sidebar = document.getElementById('sidebar-wrapper');
|
||||
const overlay = document.querySelector('.overlay');
|
||||
let isMobile = window.innerWidth <= 768;
|
||||
let isTransitioning = false;
|
||||
|
||||
// Función para abrir el menú
|
||||
function openMenu() {
|
||||
if (isTransitioning || !wrapper || !overlay) return;
|
||||
|
||||
isTransitioning = true;
|
||||
wrapper.classList.add('toggled');
|
||||
overlay.classList.add('show'); // Usar la clase 'show'
|
||||
isTransitioning = false;
|
||||
}
|
||||
|
||||
// Función para cerrar el menú
|
||||
function closeMenu() {
|
||||
if (isTransitioning || !wrapper || !overlay) return;
|
||||
|
||||
isTransitioning = true;
|
||||
overlay.classList.remove('show'); // Usar la clase 'show'
|
||||
|
||||
// Esperar a que termine la transición antes de ocultar
|
||||
const onTransitionEnd = () => {
|
||||
if (!overlay.classList.contains('show')) { // Verificar si la clase 'show' ya no está
|
||||
wrapper.classList.remove('toggled');
|
||||
overlay.removeEventListener('transitionend', onTransitionEnd);
|
||||
isTransitioning = false;
|
||||
}
|
||||
};
|
||||
|
||||
overlay.addEventListener('transitionend', onTransitionEnd, { once: true });
|
||||
}
|
||||
|
||||
// Función para alternar el menú
|
||||
function toggleMenu() {
|
||||
if (wrapper.classList.contains('toggled')) {
|
||||
closeMenu();
|
||||
} else {
|
||||
openMenu();
|
||||
}
|
||||
}
|
||||
|
||||
// Evento para el botón de menú
|
||||
if (menuToggle) {
|
||||
menuToggle.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleMenu();
|
||||
});
|
||||
}
|
||||
|
||||
// Cerrar el menú al hacer clic en el overlay
|
||||
if (overlay) {
|
||||
overlay.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
closeMenu();
|
||||
});
|
||||
}
|
||||
|
||||
// Cerrar el menú al hacer clic en un enlace en pantallas pequeñas
|
||||
const navLinks = document.querySelectorAll('.list-group-item');
|
||||
navLinks.forEach(function(link) {
|
||||
link.addEventListener('click', function() {
|
||||
if (window.innerWidth <= 768) {
|
||||
toggleMenu();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Ajustar el menú al cambiar el tamaño de la ventana
|
||||
function handleResize() {
|
||||
if (isTransitioning) return;
|
||||
|
||||
const newIsMobile = window.innerWidth <= 768;
|
||||
|
||||
if (newIsMobile !== isMobile) {
|
||||
isMobile = newIsMobile;
|
||||
|
||||
if (!isMobile) {
|
||||
// En pantallas grandes, asegurarse de que el menú esté visible
|
||||
if (wrapper) wrapper.classList.remove('toggled');
|
||||
if (overlay) {
|
||||
overlay.classList.remove('show'); // Usar la clase 'show'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// En móviles, asegurarse de que el menú esté cerrado al inicio
|
||||
if (wrapper) wrapper.classList.remove('toggled');
|
||||
if (overlay) {
|
||||
overlay.classList.remove('show'); // Usar la clase 'show'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manejar el evento de redimensionamiento
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// Inicializar el estado del menú
|
||||
handleResize();
|
||||
}
|
||||
|
||||
// Inicializar el menú cuando el DOM esté listo
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initMenu);
|
||||
} else {
|
||||
initMenu();
|
||||
}
|
||||
|
||||
// Manejar el evento de carga completa para asegurar que todo esté listo
|
||||
window.addEventListener('load', function() {
|
||||
// Asegurarse de que el menú se inicialice correctamente
|
||||
if (typeof initMenu === 'function') {
|
||||
initMenu();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="/assets/js/translate_frontend.js"></script>
|
||||
|
||||
<!-- Script para eliminar el Debug Language List -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const debugList = document.getElementById('debug-language-list');
|
||||
if (debugList) {
|
||||
debugList.remove();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
129
templates/header.php
Executable file
129
templates/header.php
Executable file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
// Incluir los helpers necesarios
|
||||
require_once __DIR__ . '/../includes/url_helper.php';
|
||||
require_once __DIR__ . '/../includes/translation_helper.php';
|
||||
|
||||
// Inicializar el idioma de la sesión si no está definido
|
||||
if (!isset($_SESSION['language'])) {
|
||||
$_SESSION['language'] = 'es'; // Idioma por defecto
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bot Discord</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<!-- Bootstrap Icons -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||
<!-- Estilos personalizados -->
|
||||
<link rel="stylesheet" href="<?php echo asset('css/style.css'); ?>" type="text/css">
|
||||
<!-- Contenido extra del head (opcional) -->
|
||||
<?php if (isset($extraHead)) echo $extraHead; ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="d-flex" id="wrapper">
|
||||
<!-- Sidebar -->
|
||||
<div class="bg-dark border-right" id="sidebar-wrapper">
|
||||
<div class="sidebar-heading text-white">
|
||||
Bot Discord
|
||||
<img src="<?php echo asset('images/logo.png'); ?>" alt="Logo" id="sidebar-logo" class="ms-2">
|
||||
</div>
|
||||
<div class="text-white px-3 py-2 small">
|
||||
Bienvenido, <?php echo htmlspecialchars($_SESSION['username']); ?>!
|
||||
</div>
|
||||
<div class="list-group list-group-flush">
|
||||
<a href="<?php echo site_url('index.php'); ?>" data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-house-door-fill me-2"></i>Inicio
|
||||
</a>
|
||||
<a href="<?php echo site_url('create_message.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-plus-square-fill me-2" ></i>Crear Mensaje
|
||||
</a>
|
||||
<a href="<?php echo site_url('scheduled_messages.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-clock-fill me-2"></i>Programados
|
||||
</a>
|
||||
<a href="<?php echo site_url('recurrentes.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-arrow-repeat me-2"></i>Plantillas
|
||||
</a>
|
||||
<a href="<?php echo site_url('sent_messages.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-send-fill me-2"></i>Enviados
|
||||
</a>
|
||||
<a href="<?php echo site_url('gallery.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-images me-2"></i>Galería
|
||||
</a>
|
||||
<?php if ($_SESSION['role'] === 'admin'): ?>
|
||||
<a href="<?php echo site_url('admin/users.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-people-fill me-2"></i>Admin Usuarios
|
||||
</a>
|
||||
<a href="<?php echo site_url('admin/recipients.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-person-rolodex me-2"></i>Admin Destinatarios
|
||||
</a>
|
||||
<a href="<?php echo site_url('admin/languages.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-translate me-2"></i>Idiomas y Traducciones
|
||||
</a>
|
||||
<a href="<?php echo site_url('admin/comandos.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-terminal-fill me-2"></i>Comandos
|
||||
</a>
|
||||
<a href="<?php echo site_url('telegram/admin/telegram_welcome.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-telegram me-2"></i>Configuración de Telegram
|
||||
</a>
|
||||
<a href="<?php echo site_url('telegram/admin/telegram_bot_interactions.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-robot me-2"></i>Interacciones Bot
|
||||
</a>
|
||||
<a href="<?php echo site_url('admin/activity.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-clipboard-data-fill me-2"></i>Actividad
|
||||
</a>
|
||||
<a href="<?php echo site_url('admin/test_discord_connection.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-bug-fill me-2"></i>Test
|
||||
</a>
|
||||
<a href="<?php echo site_url('telegram/admin/chat_telegram.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-chat-dots-fill me-2"></i>Chat Telegram
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo site_url('profile.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-person-circle me-2"></i>Perfil
|
||||
</a>
|
||||
<a href="<?php echo site_url('logout.php'); ?>"data-translate="true" class="list-group-item list-group-item-action bg-dark text-white">
|
||||
<i class="bi bi-box-arrow-right me-2"></i>Cerrar Sesión
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /#sidebar-wrapper -->
|
||||
|
||||
<!-- Page Content -->
|
||||
<div id="page-content-wrapper">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
|
||||
<div class="container-fluid" style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<button class="btn btn-primary" id="menu-toggle"><i class="bi bi-list"></i></button>
|
||||
<select class="form-select w-auto" id="language-selector">
|
||||
<!-- Options will be populated by translate_frontend.js -->
|
||||
</select>
|
||||
</div>
|
||||
<?php if ($_SESSION['role'] === 'admin'): ?>
|
||||
<div class="card border-info bg-light" style="width: 180px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); margin: 0; flex-shrink: 0;">
|
||||
<div class="card-body p-2 text-center">
|
||||
<div class="mb-1">
|
||||
<i class="bi bi-database text-info" style="font-size: 16px;"></i>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<small class="text-muted d-block fw-semibold" style="font-size: 10px;">BASE DE DATOS</small>
|
||||
<strong class="d-block text-dark" style="font-size: 12px;"><?php echo htmlspecialchars(DB_NAME); ?></strong>
|
||||
</div>
|
||||
<hr class="my-1">
|
||||
<div>
|
||||
<small class="text-muted d-block fw-semibold" style="font-size: 10px;">SERVIDOR</small>
|
||||
<code class="text-info" style="font-size: 11px;"><?php echo htmlspecialchars(DB_HOST); ?>:<?php echo htmlspecialchars(DB_PORT); ?></code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="container-fluid p-4">
|
||||
|
||||
<!-- Conflicting language script removed -->
|
||||
Reference in New Issue
Block a user