312 lines
12 KiB
HTML

{% load static %}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="author" content="Maom">
<title>{% block titulo %}Servicio de Transporte{% endblock %}</title>
<link rel="icon" href="{% static 'img/transporte.ico' %}" type="image/x-icon">
<!-- Fonts and Icons -->
<link rel="stylesheet" href="{% static 'assets/fonts/iconos/css/all.min.css' %}" />
<!-- En tu archivo base.html -->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> -->
<!-- CSS Files -->
<link rel="stylesheet" href="{% static 'assets/css/select2.min.css' %}" />
<link rel="stylesheet" href="{% static 'assets/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/plugins.min.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/kaiadmin.min.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/animate.min.css' %}" />
<style>
body { transition: background-color 0.3s, color 0.3s; font-family: 'Poppins', sans-serif; }
.dark-mode { background-color: #1a2035; color: #ffffff; }
.dark-mode .main-panel { background-color: #1a2035; }
.dark-mode .card { background-color: #2f3545; color: #ffffff; }
.dark-mode .table-dark { background-color: #2f3545; }
.dark-mode .badge.bg-dark { background-color: #ffffff !important; color: #000000 !important; }
.page-inner { animation: fadeIn 0.5s ease-in; padding: 20px; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.card { border-radius: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); transition: transform 0.3s ease; }
.card:hover { transform: translateY(-5px); }
.form-control:focus {
border-color: #0d6efd;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
.card { border-radius: 15px; }
.card-header { border-radius: 15px 15px 0 0 !important; }
</style>
{% block css %}{% endblock %}
</head>
<body>
<div class="wrapper" id="contenido">
<div class="modal fade" id="logoutWarning" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Sesión por expirar</h5>
</div>
<div class="modal-body">
La sesión se cerrará en <span id="countdown">{{ warning_time }}</span> segundos.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="resetTimer()">Continuar</button>
<button type="button" class="btn btn-primary" onclick="logoutUser()">Cerrar ahora</button>
</div>
</div>
</div>
</div>
{% block vertical %}{% include 'partes/vertical.html' %}{% endblock %}
<div class="main-panel">
{% block horizontal %}{% include 'partes/horizontal.html' %}{% endblock %}
<div class="container">
<div class="page-inner" id="page-content">
{% block seccion %}{% endblock %}
{% block contenido %}{% endblock %}
</div>
</div>
{% block pie %}{% include 'partes/pie.html' %}{% endblock %}
</div>
</div>
<!-- Core JS Files -->
<script src="{% static 'assets/js/core/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'assets/js/core/popper.min.js' %}"></script>
<script src="{% static 'assets/js/core/bootstrap.min.js' %}"></script>
<script src="{% static 'assets/js/plugin/datatables/datatables.min.js' %}"></script>
<!-- Plugin JS Files -->
<script src="{% static 'assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js' %}"></script>
<script src="{% static 'assets/js/plugin/jquery.sparkline/jquery.sparkline.min.js' %}"></script>
<script src="{% static 'assets/js/plugin/bootstrap-notify/bootstrap-notify.min.js' %}"></script>
<script src="{% static 'assets/js/plugin/jsvectormap/jsvectormap.min.js' %}"></script>
<script src="{% static 'assets/js/plugin/jsvectormap/world.js' %}"></script>
<script src="{% static 'assets/js/sweetalert211.js' %}"></script>
<!-- Chart JS -->
<script src="{% static 'assets/js/plugin/chart.js/chart.min.js' %}"></script>
<!-- Kaiadmin JS -->
<script src="{% static 'assets/js/kaiadmin.min.js' %}"></script>
<script src="{% static 'assets/js/select2.min.js' %}"></script>
<!-- Pasar mensajes de Django a JavaScript como atributo data -->
<div id="django-messages" data-messages='[
{% if messages %}
{% for message in messages %}
{"tags": "{{ message.tags }}", "text": "{{ message | escapejs }}"},
{% endfor %}
{% endif %}
]'>
</div>
<!-- Script personalizado global -->
<script>
// Definir función global al inicio
window.loadPageContent = function(url, pushState = true) {
console.log('Iniciando loadPageContent con URL:', url);
fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(response => {
console.log('Respuesta recibida:', response.status);
if (!response.ok) throw new Error('Network response was not ok');
return response.text();
})
.then(html => {
console.log('HTML recibido:', html.substring(0, 100));
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
// Extraer solo el contenido interno de #page-content si existe, o el body completo
const newContentElement = doc.querySelector('#page-content') || doc.body;
const newContent = newContentElement.innerHTML;
const pageContent = document.getElementById('page-content');
if (pageContent) {
pageContent.innerHTML = newContent; // Reemplazar solo el contenido interno
console.log('Contenido cargado en #page-content');
window.reinitializeScripts(); // Re-inicializar scripts después de cargar
} else {
console.error('No se encontró #page-content en el DOM');
}
if (pushState) window.history.pushState({ url: url }, document.title, url);
})
.catch(error => console.error('Error en loadPageContent:', error));
};
function reinitializeScripts() {
if (typeof $.fn.select2 !== 'undefined') {
$('.select2').select2({ theme: 'bootstrap4', width: '100%' });
}
initializeCustomTables();
if (typeof bootstrap !== 'undefined') {
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new bootstrap.Tooltip(el));
}
}
// Ejecutar después de cargar el DOM
document.addEventListener('DOMContentLoaded', function () {
// Tema oscuro
const toggleDarkMode = () => {
document.body.classList.toggle('dark-mode');
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
};
if (localStorage.getItem('darkMode') === 'true') {
document.body.classList.add('dark-mode');
}
document.getElementById('darkModeToggle')?.addEventListener('click', toggleDarkMode);
// Obtener mensajes desde el atributo data-messages
const messagesContainer = document.getElementById('django-messages');
let djangoMessages = [];
if (messagesContainer && messagesContainer.getAttribute('data-messages')) {
const messagesStr = messagesContainer.getAttribute('data-messages').replace(/,\s*]/, ']');
djangoMessages = JSON.parse(messagesStr);
}
// Mostrar mensajes con SweetAlert2
if (djangoMessages.length > 0) {
const Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
},
background: document.body.classList.contains('dark-mode') ? '#2f3545' : '#fff',
color: document.body.classList.contains('dark-mode') ? '#fff' : '#000'
});
djangoMessages.forEach(message => {
Toast.fire({
icon: message.tags,
title: message.text,
customClass: { popup: 'animate__animated animate__fadeInDown' }
});
});
}
});
document.addEventListener('DOMContentLoaded', function() {
const inputs = document.querySelectorAll('.form-control:not([type="number"])');
inputs.forEach(input => {
input.addEventListener('input', function() {
this.value = this.value.toUpperCase();
});
});
});
</script>
<script>
// Configuraciones de tiempo
const SESSION_TIMEOUT = parseInt("{{ session_timeout|default:1800 }}") * 1000; // 30 min
const WARNING_TIME = parseInt("{{ warning_time|default:300 }}") * 1000; // 5 min
// Variables de control
let timer;
let warningTimer;
let countdownInterval;
let isLoggingOut = false;
let modalVisible = false; // Nueva variable para controlar estado del modal
function resetTimer(forceReset = false) {
// Solo reiniciar si el modal no está visible o forzado
if (!modalVisible || forceReset) {
clearTimeout(timer);
clearTimeout(warningTimer);
clearInterval(countdownInterval);
$('#logoutWarning').modal('hide');
modalVisible = false;
warningTimer = setTimeout(() => {
$('#logoutWarning').modal('show');
modalVisible = true;
startCountdown();
}, SESSION_TIMEOUT - WARNING_TIME);
timer = setTimeout(logoutUser, SESSION_TIMEOUT);
}
}
function startCountdown() {
let seconds = Math.floor(WARNING_TIME / 1000);
const countdownElement = document.getElementById('countdown');
countdownElement.textContent = seconds;
countdownInterval = setInterval(() => {
seconds--;
countdownElement.textContent = seconds;
if (seconds <= 0) {
clearInterval(countdownInterval);
logoutUser();
}
}, 1000);
}
// Función de logout (sin cambios)
function logoutUser() {
if (isLoggingOut) return;
isLoggingOut = true;
const form = document.createElement('form');
form.method = 'POST';
form.action = "{% url 'logout' %}";
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = 'csrfmiddlewaretoken';
csrfInput.value = csrfToken;
form.appendChild(csrfInput);
document.body.appendChild(form);
form.submit();
}
document.addEventListener('DOMContentLoaded', function () {
// ... (tu código existente de temas y mensajes)
// Modificar el event listener para ignorar actividad cuando el modal está visible
const events = ['mousemove', 'keydown', 'click', 'scroll'];
events.forEach(e => window.addEventListener(e, () => {
if (!modalVisible) { // Solo resetear si el modal NO está visible
resetTimer();
}
}));
// Manejar el cierre del modal
$('#logoutWarning').on('hide.bs.modal', function () {
modalVisible = false;
});
// Iniciar temporizador
resetTimer();
// Botón continuar
document.querySelector('.btn-secondary')?.addEventListener('click', () => resetTimer(true));
});
</script>
{% block js %}{% endblock %}
</body>
</html>