Carpeta includes

This commit is contained in:
Axel Axt
2026-08-04 19:21:56 -03:00
parent 9ef9194f9e
commit ea2a40d0d5
5 changed files with 302 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
<?php
class Footer {
public function render() {
return '
<!-- Jquery JS -->
<script src="libs/jquery/jquery-3.7.1.min.js"></script>
<!-- Bootstrap JS -->
<script src="libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Datatables JS -->
<script src="libs/datatables/js/jquery.dataTables.min.js"></script>
<script src="libs/datatables/js/dataTables.bootstrap5.min.js"></script>
<!-- Chartjs JS -->
<script src="libs/chartjs/chart.umd.js"></script>
<!-- Loader global (animación de carga) -->
<script>
// Espera a que cargue la vista (HTML)
document.addEventListener("DOMContentLoaded", function () {
// Se obtiene el laoder
const loader = document.getElementById("page-loader");
// Retorna (corta ejecución) si no lo encuentra
if (!loader) return;
// Se guarda el momento en el que empezó y el minimo que debe mostrarse (100ms)
const MIN_TIME = 100;
const startTime = Date.now();
// Función para ocultarlo (acá se define)
const hideLoader = () => {
// Calcula cuanto tiempo pasó y cuanto falta para llegar al minimo
const elapsed = Date.now() - startTime;
const remaining = MIN_TIME - elapsed;
// Se oculta con delay controlado (espera lo que falta para cumplir el minimo)
setTimeout(() => {
// Animacioón
loader.classList.add("fade-out");
// Espera a que termine la animación (300ms) y lo saca del flujo
setTimeout(() => {
loader.style.display = "none";
}, 300);
}, Math.max(0, remaining)); // Espera a que remaining llegue a 0 (si ya pasó el tiempo no espera)
};
hideLoader();
});
</script>
</body>
</html>';
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
class Header {
public function render() {
return '
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="libs/bootstrap/css/bootstrap.min.css">
<!-- Datatables CSS -->
<link rel="stylesheet" href="libs/datatables/css/dataTables.bootstrap5.min.css">
<!-- Fontawesome CSS -->
<link rel="stylesheet" href="libs/fontawesome/css/all.min.css">
<!-- Estilos propios -->
<link rel="stylesheet" href="css/styles.css">
<title>ByteCenter</title>
<link rel="icon" href="imgs/favicon.ico" type="image/x-icon">
</head>
<body class="min-vh-100 d-flex flex-column">
<div id="page-loader">
<div class="spinner"></div>
</div>';
}
}
+58
View File
@@ -0,0 +1,58 @@
<div class="modal fade" id="modalConfirmacion" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<!-- HEADER -->
<div class="modal-header">
<!-- Se completa dinámicamente desde JS (data-titulo) -->
<h5 id="modalTitulo"></h5>
</div>
<!-- BODY -->
<div class="modal-body">
<!-- Mensaje dinámico desde data-mensaje -->
<p id="modalMensaje"></p>
</div>
<!-- FORM REUTILIZABLE -->
<form id="formConfirmacionGlobal" method="POST">
<!-- Este form se usa para todas las acciones del modal -->
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<!-- Contenedor en donde JS inserta los inputs hidden con los valores pasados a travéz de data-* -->
<div id="modalDynamicInputs"></div>
<!-- Botón Cancelar -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Cancelar
</button>
<!-- Botón Confirmar -->
<button type="submit" id="modalBtnConfirmar" class="btn btn-primary">
<!-- Este botón es interceptado por JS -->
<!-- preventDefault() evita el submit automático -->
<!-- JS arma el form y luego hace submit manual -->
Confirmar
</button>
</div>
</form>
</div>
</div>
</div>
+89
View File
@@ -0,0 +1,89 @@
<?php
if (!isset($_SESSION['user'])) {
return;
}
$rol = $_SESSION['user']['rol'];
$inicio = $rol === 'admin' ? 'inicio_admin' : 'inicio_operador';
?>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container-fluid">
<a class="navbar-brand text-white fw-bold" href="?opt=<?= $inicio ?>">
<img src="imgs/logo.png" width="30" height="30" class="d-inline-block align-center me-2">
ByteCenter
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<!-- INICIO -->
<li class="nav-item">
<a class="nav-link text-white" href="?opt=<?= $inicio ?>">
<i class="fas fa-home"></i>
Inicio
</a>
</li>
<!-- ASISTENTE -->
<li class="nav-item">
<a class="nav-link text-white" href="index.php?opt=chatbot" target="chatbot_window">
<i class="fas fa-comment-dots"></i>
Asistente
</a>
</li>
<!-- DATOS DEL NEGOCIO -->
<?php if ($_SESSION['user']['rol'] === 'admin'): ?>
<li class="nav-item">
<a class="nav-link text-white" href="?opt=configuracion">
<i class="fa-solid fa-store"></i>
Datos del Negocio
</a>
</li>
<?php endif; ?>
<!-- USUARIO -->
<li class="nav-item">
<a class="nav-link text-white" href="?opt=datos_usuario">
<i class="fas fa-user-circle"></i>
<?= $_SESSION['user']['nombre'] ?>
</a>
</li>
<!-- LOGOUT -->
<li class="nav-item">
<a class="nav-link text-white" href="?opt=logout">
<i class="fas fa-sign-out-alt"></i>
Cerrar Sesión
</a>
</li>
</ul>
</div>
</div>
</nav>
<?
+37
View File
@@ -0,0 +1,37 @@
<?php
// Requiere el header y footer
require_once __DIR__ . '/header.php';
require_once __DIR__ . '/footer.php';
class Page {
private $header;
private $footer;
private $body = '';
// Setea el header y footer
function __construct() {
$this->header = new Header();
$this->footer = new Footer();
}
// Setea el body obtenido por pageController
public function setBody($html) {
$this->body = $html;
}
// Retorna layout HTML
public function getHTML() {
$page = $this->header->render();
$page .= $this->body;
$page .= $this->footer->render();
return $page;
}
}
?>