feat: admin panel login, layout, and styles

Add the admin CRM panel foundation including:
- Login/logout authentication flow with CSRF protection
- Sidebar layout with navigation for all CRM modules
- Comprehensive admin.css (1680+ lines) with components for
  cards, tables, badges, forms, buttons, alerts, modals,
  pagination, search, responsive breakpoints, and print styles
- admin.js with sidebar toggle, confirm dialogs, auto-dismiss
  alerts, and table search filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gestoría LP
2026-03-02 00:19:09 +00:00
parent 0ef344b67a
commit fbf1b31dc0
6 changed files with 1887 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
</div><!-- /.admin-content -->
</div><!-- /.admin-main -->
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<script src="../assets/js/admin.js"></script>
</body>
</html>

View File

@@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/../../includes/auth.php';
require_once __DIR__ . '/../../includes/csrf.php';
authRequire();
authStart();
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= isset($pageTitle) ? htmlspecialchars($pageTitle) : 'Admin' ?> - Gestoría LP</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="stylesheet" href="../assets/css/admin.css">
</head>
<body class="admin-body">
<!-- Sidebar -->
<aside class="sidebar" id="sidebar">
<div class="sidebar__brand">
<i class="fas fa-balance-scale"></i>
<span>Gestoría LP</span>
</div>
<nav class="sidebar__nav">
<a href="index.php" class="sidebar__link <?= $currentPage === 'index' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-tachometer-alt"></i> <span>Dashboard</span>
</a>
<a href="clientes.php" class="sidebar__link <?= $currentPage === 'clientes' || $currentPage === 'cliente-detalle' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-users"></i> <span>Clientes</span>
</a>
<a href="tramites.php" class="sidebar__link <?= $currentPage === 'tramites' || $currentPage === 'tramite-detalle' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-file-alt"></i> <span>Trámites</span>
</a>
<a href="solicitudes.php" class="sidebar__link <?= $currentPage === 'solicitudes' || $currentPage === 'solicitud-detalle' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-inbox"></i> <span>Solicitudes</span>
</a>
<a href="recordatorios.php" class="sidebar__link <?= $currentPage === 'recordatorios' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-bell"></i> <span>Recordatorios</span>
</a>
<a href="testimonios.php" class="sidebar__link <?= $currentPage === 'testimonios' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-star"></i> <span>Testimonios</span>
</a>
<a href="carga-historial.php" class="sidebar__link <?= $currentPage === 'carga-historial' ? 'sidebar__link--active' : '' ?>">
<i class="fas fa-upload"></i> <span>Carga Historial</span>
</a>
</nav>
<div class="sidebar__footer">
<a href="logout.php" class="sidebar__link sidebar__link--logout">
<i class="fas fa-sign-out-alt"></i> <span>Cerrar Sesión</span>
</a>
</div>
</aside>
<!-- Main Content -->
<div class="admin-main">
<header class="admin-topbar">
<button class="sidebar-toggle" id="sidebarToggle">
<i class="fas fa-bars"></i>
</button>
<div class="admin-topbar__right">
<span class="admin-topbar__user">
<i class="fas fa-user-circle"></i> <?= htmlspecialchars($_SESSION['username'] ?? 'Admin') ?>
</span>
</div>
</header>
<div class="admin-content">

68
admin/login.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/csrf.php';
authStart();
// Already logged in?
if (authCheck()) {
header('Location: index.php');
exit;
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!csrfValidate()) {
$error = 'Token de seguridad inválido.';
} else {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
if (authLogin($username, $password)) {
header('Location: index.php');
exit;
} else {
$error = 'Usuario o contraseña incorrectos.';
}
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Gestoría LP Admin</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="stylesheet" href="../assets/css/admin.css">
</head>
<body class="login-page">
<div class="login-container">
<div class="login-card">
<div class="login-card__header">
<i class="fas fa-balance-scale"></i>
<h1>Gestoría LP</h1>
<p>Panel de Administración</p>
</div>
<?php if ($error): ?>
<div class="alert alert--danger"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="POST" class="login-form">
<?= csrfField() ?>
<div class="form-group">
<label for="username"><i class="fas fa-user"></i> Usuario</label>
<input type="text" id="username" name="username" required autofocus placeholder="Ingresa tu usuario">
</div>
<div class="form-group">
<label for="password"><i class="fas fa-lock"></i> Contraseña</label>
<input type="password" id="password" name="password" required placeholder="Ingresa tu contraseña">
</div>
<button type="submit" class="btn btn--primary btn--block">
<i class="fas fa-sign-in-alt"></i> Iniciar Sesión
</button>
</form>
</div>
</div>
</body>
</html>

5
admin/logout.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
require_once __DIR__ . '/../includes/auth.php';
authLogout();
header('Location: login.php');
exit;