8: Creando Cabecera y Menú

 

8: Creando Cabecera y Menú

1. Introducción

En este tutorial crearemos la cabecera (header) y el menú lateral (sidebar) de nuestro sistema utilizando AdminLTE. Estos componentes serán dinámicos y mostrarán diferentes opciones según el rol del usuario autenticado (secretaria, doctor, paciente o administrador).


2. Objetivos

  • ✅ Crear cabecera personalizada con logo y usuario

  • ✅ Implementar menú lateral dinámico por rol

  • ✅ Incluir componentes mediante Blade partials

  • ✅ Configurar redirecciones y protección de rutas


3. Proteger el Controlador de Inicio

Paso 1: Modificar InicioController.php

Para que solo usuarios autenticados puedan acceder al dashboard:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class InicioController extends Controller
{
    /**
     * Constructor: aplica middleware de autenticación
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('modulos.inicio');
    }

    // ... resto de métodos
}

4. Crear la Cabecera (Header)

Paso 1: Crear el archivo header.blade.php

Crea resources/views/modulos/header.blade.php:

php
<!-- ========================================== -->
<!--              HEADER (Navbar)               -->
<!-- ========================================== -->
<header class="main-header">
    
    <!-- Logo -->
    <a href="{{ route('inicio') }}" class="logo">
        <!-- Logo versión mini (sidebar colapsado) -->
        <span class="logo-mini"><b>C</b>L</span>
        <!-- Logo versión completa -->
        <span class="logo-lg"><b>Clínica</b> Médica</span>
    </a>

    <!-- Barra de navegación -->
    <nav class="navbar navbar-static-top" role="navigation">
        <!-- Botón toggle para colapsar sidebar -->
        <a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </a>

        <!-- Menú de la derecha -->
        <div class="navbar-custom-menu">
            <ul class="nav navbar-nav">
                
                <!-- ====================================== -->
                <!--    MENÚ DE USUARIO (Dropdowon)        -->
                <!-- ====================================== -->
                <li class="dropdown user user-menu">
                    <!-- Enlace del dropdown -->
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        <!-- Avatar del usuario -->
                        <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                             class="user-image" 
                             alt="User Image">
                        <!-- Nombre del usuario -->
                        <span class="hidden-xs">{{ Auth::user()->name }}</span>
                    </a>
                    
                    <!-- Contenido del dropdown -->
                    <ul class="dropdown-menu">
                        <!-- Cabecera del usuario -->
                        <li class="user-header">
                            <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                                 class="img-circle" 
                                 alt="User Image">
                            <p>
                                {{ Auth::user()->name }}
                                <small>{{ Auth::user()->rol }}</small>
                            </p>
                        </li>
                        
                        <!-- Footer con acciones -->
                        <li class="user-footer">
                            <div class="pull-left">
                                <a href="#" class="btn btn-default btn-flat">
                                    <i class="fa fa-user"></i> Perfil
                                </a>
                            </div>
                            <div class="pull-right">
                                <a href="#" 
                                   class="btn btn-default btn-flat"
                                   onclick="event.preventDefault(); 
                                            document.getElementById('logout-form').submit();">
                                    <i class="fa fa-sign-out"></i> Salir
                                </a>
                                <!-- Formulario oculto para logout -->
                                <form id="logout-form" 
                                      action="{{ route('logout') }}" 
                                      method="POST" 
                                      style="display: none;">
                                    @csrf
                                </form>
                            </div>
                        </li>
                    </ul>
                </li>
                
            </ul>
        </div>
    </nav>
</header>

5. Crear los Menús por Rol

5.1 Menú de Secretaria

Crea resources/views/modulos/menu_secretaria.blade.php:

php
<!-- ========================================== -->
<!--         MENÚ SECRETARIA                    -->
<!-- ========================================== -->
<aside class="main-sidebar">
    <section class="sidebar">
        
        <!-- Panel del usuario -->
        <div class="user-panel">
            <div class="pull-left image">
                <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                     class="img-circle" 
                     alt="User Image">
            </div>
            <div class="pull-left info">
                <p>{{ Auth::user()->name }}</p>
                <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
            </div>
        </div>

        <!-- Formulario de búsqueda -->
        <form action="#" method="get" class="sidebar-form">
            <div class="input-group">
                <input type="text" name="q" class="form-control" placeholder="Buscar...">
                <span class="input-group-btn">
                    <button type="submit" name="search" id="search-btn" class="btn btn-flat">
                        <i class="fa fa-search"></i>
                    </button>
                </span>
            </div>
        </form>

        <!-- Menú principal -->
        <ul class="sidebar-menu" data-widget="tree">
            <li class="header">MENÚ PRINCIPAL</li>
            
            <!-- Dashboard -->
            <li class="{{ request()->routeIs('inicio') ? 'active' : '' }}">
                <a href="{{ route('inicio') }}">
                    <i class="fa fa-dashboard"></i> <span>Dashboard</span>
                </a>
            </li>

            <!-- Consultorios -->
            <li class="{{ request()->routeIs('consultorios*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-building"></i> <span>Consultorios</span>
                </a>
            </li>

            <!-- Doctores -->
            <li class="{{ request()->routeIs('doctores*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-user-md"></i> <span>Doctores</span>
                </a>
            </li>

            <!-- Pacientes -->
            <li class="{{ request()->routeIs('pacientes*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-users"></i> <span>Pacientes</span>
                </a>
            </li>

            <!-- Citas -->
            <li class="header">CITAS MÉDICAS</li>
            <li class="{{ request()->routeIs('citas*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-calendar"></i> <span>Agenda de Citas</span>
                </a>
            </li>
        </ul>
    </section>
</aside>

5.2 Menú de Doctor

Crea resources/views/modulos/menu_doctor.blade.php:

php
<!-- ========================================== -->
<!--           MENÚ DOCTOR                      -->
<!-- ========================================== -->
<aside class="main-sidebar">
    <section class="sidebar">
        
        <!-- Panel del usuario -->
        <div class="user-panel">
            <div class="pull-left image">
                <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                     class="img-circle" 
                     alt="User Image">
            </div>
            <div class="pull-left info">
                <p>{{ Auth::user()->name }}</p>
                <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
            </div>
        </div>

        <!-- Menú principal -->
        <ul class="sidebar-menu" data-widget="tree">
            <li class="header">MENÚ DOCTOR</li>
            
            <!-- Dashboard -->
            <li class="{{ request()->routeIs('inicio') ? 'active' : '' }}">
                <a href="{{ route('inicio') }}">
                    <i class="fa fa-dashboard"></i> <span>Dashboard</span>
                </a>
            </li>

            <!-- Mis Pacientes -->
            <li class="{{ request()->routeIs('mis-pacientes*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-users"></i> <span>Mis Pacientes</span>
                </a>
            </li>

            <!-- Mi Agenda -->
            <li class="header">AGENDA</li>
            <li class="{{ request()->routeIs('mi-agenda*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-calendar"></i> <span>Mi Agenda</span>
                </a>
            </li>

            <!-- Horarios -->
            <li class="{{ request()->routeIs('horarios*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-clock-o"></i> <span>Horarios</span>
                </a>
            </li>
        </ul>
    </section>
</aside>

5.3 Menú de Paciente

Crea resources/views/modulos/menu_paciente.blade.php:

php
<!-- ========================================== -->
<!--           MENÚ PACIENTE                    -->
<!-- ========================================== -->
<aside class="main-sidebar">
    <section class="sidebar">
        
        <!-- Panel del usuario -->
        <div class="user-panel">
            <div class="pull-left image">
                <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                     class="img-circle" 
                     alt="User Image">
            </div>
            <div class="pull-left info">
                <p>{{ Auth::user()->name }}</p>
                <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
            </div>
        </div>

        <!-- Menú principal -->
        <ul class="sidebar-menu" data-widget="tree">
            <li class="header">MENÚ PACIENTE</li>
            
            <!-- Dashboard -->
            <li class="{{ request()->routeIs('inicio') ? 'active' : '' }}">
                <a href="{{ route('inicio') }}">
                    <i class="fa fa-dashboard"></i> <span>Dashboard</span>
                </a>
            </li>

            <!-- Buscar Doctor -->
            <li class="{{ request()->routeIs('buscar-doctor*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-search"></i> <span>Buscar Doctor</span>
                </a>
            </li>

            <!-- Mis Citas -->
            <li class="header">MIS CITAS</li>
            <li class="{{ request()->routeIs('mis-citas*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-calendar-check-o"></i> <span>Mis Citas</span>
                </a>
            </li>

            <!-- Historial -->
            <li class="{{ request()->routeIs('historial*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-history"></i> <span>Historial</span>
                </a>
            </li>
        </ul>
    </section>
</aside>

5.4 Menú de Administrador

Crea resources/views/modulos/menu_admin.blade.php:

php
<!-- ========================================== -->
<!--          MENÚ ADMINISTRADOR                -->
<!-- ========================================== -->
<aside class="main-sidebar">
    <section class="sidebar">
        
        <!-- Panel del usuario -->
        <div class="user-panel">
            <div class="pull-left image">
                <img src="{{ asset('dist/img/user2-160x160.jpg') }}" 
                     class="img-circle" 
                     alt="User Image">
            </div>
            <div class="pull-left info">
                <p>{{ Auth::user()->name }}</p>
                <a href="#"><i class="fa fa-circle text-success"></i> Online</a>
            </div>
        </div>

        <!-- Formulario de búsqueda -->
        <form action="#" method="get" class="sidebar-form">
            <div class="input-group">
                <input type="text" name="q" class="form-control" placeholder="Buscar...">
                <span class="input-group-btn">
                    <button type="submit" name="search" id="search-btn" class="btn btn-flat">
                        <i class="fa fa-search"></i>
                    </button>
                </span>
            </div>
        </form>

        <!-- Menú principal -->
        <ul class="sidebar-menu" data-widget="tree">
            <li class="header">MENÚ PRINCIPAL</li>
            
            <!-- Dashboard -->
            <li class="{{ request()->routeIs('inicio') ? 'active' : '' }}">
                <a href="{{ route('inicio') }}">
                    <i class="fa fa-dashboard"></i> <span>Dashboard</span>
                </a>
            </li>

            <!-- Configuración -->
            <li class="header">ADMINISTRACIÓN</li>
            <li class="{{ request()->routeIs('configuracion*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-cogs"></i> <span>Configuración</span>
                </a>
            </li>

            <!-- Gestión -->
            <li class="header">GESTIÓN</li>
            <li class="{{ request()->routeIs('consultorios*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-building"></i> <span>Consultorios</span>
                </a>
            </li>
            <li class="{{ request()->routeIs('doctores*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-user-md"></i> <span>Doctores</span>
                </a>
            </li>
            <li class="{{ request()->routeIs('pacientes*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-users"></i> <span>Pacientes</span>
                </a>
            </li>
            <li class="{{ request()->routeIs('secretarias*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-user-plus"></i> <span>Secretarias</span>
                </a>
            </li>

            <!-- Citas -->
            <li class="header">CITAS MÉDICAS</li>
            <li class="{{ request()->routeIs('citas*') ? 'active' : '' }}">
                <a href="#">
                    <i class="fa fa-calendar"></i> <span>Agenda de Citas</span>
                </a>
            </li>
        </ul>
    </section>
</aside>

6. Actualizar el Layout Principal

Paso 1: Modificar layouts/app.blade.php

php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>@yield('title', 'Clínica L8') - Sistema de Citas Médicas</title>

    <!-- Google Font: Source Sans Pro -->
    <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">

    <!-- AdminLTE CSS -->
    <link rel="stylesheet" href="{{ asset('bower_components/bootstrap/dist/css/bootstrap.min.css') }}">
    <link rel="stylesheet" href="{{ asset('bower_components/font-awesome/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ asset('bower_components/Ionicons/css/ionicons.min.css') }}">
    <link rel="stylesheet" href="{{ asset('dist/css/AdminLTE.min.css') }}">
    <link rel="stylesheet" href="{{ asset('dist/css/skins/_all-skins.min.css') }}">

    @stack('styles')
</head>

<body class="hold-transition skin-blue {{ Auth::check() ? 'sidebar-mini' : '' }}">
    
    @auth
        <!-- ========================================== -->
        <!--          LAYOUT CON AUTENTICACIÓN          -->
        <!-- ========================================== -->
        <div class="wrapper">
            
            <!-- ====================================== -->
            <!--          INCLUIR CABECERA             -->
            <!-- ====================================== -->
            @include('modulos.header')

            <!-- ====================================== -->
            <!--          MENÚ POR ROL                 -->
            <!-- ====================================== -->
            @if(Auth::user()->rol == 'admin')
                @include('modulos.menu_admin')
            @elseif(Auth::user()->rol == 'secretaria')
                @include('modulos.menu_secretaria')
            @elseif(Auth::user()->rol == 'doctor')
                @include('modulos.menu_doctor')
            @elseif(Auth::user()->rol == 'paciente')
                @include('modulos.menu_paciente')
            @else
                @include('modulos.menu_secretaria') <!-- Menú por defecto -->
            @endif

            <!-- ====================================== -->
            <!--         CONTENIDO PRINCIPAL           -->
            <!-- ====================================== -->
            <div class="content-wrapper">
                <!-- Content Header (Page header) -->
                <section class="content-header">
                    <h1>
                        @yield('page-title', 'Dashboard')
                        <small>@yield('page-subtitle', 'Panel de control')</small>
                    </h1>
                    <ol class="breadcrumb">
                        <li>
                            <a href="{{ route('inicio') }}">
                                <i class="fa fa-dashboard"></i> Inicio
                            </a>
                        </li>
                        @yield('breadcrumb')
                    </ol>
                </section>

                <!-- Main content -->
                <section class="content">
                    @yield('content')
                </section>
            </div>

            <!-- ====================================== -->
            <!--              FOOTER                   -->
            <!-- ====================================== -->
            <footer class="main-footer">
                <div class="pull-right hidden-xs">
                    <b>Versión</b> 1.0.0
                </div>
                <strong>Copyright &copy; 2024 <a href="#">Clínica L8</a>.</strong> 
                Todos los derechos reservados.
            </footer>

        </div>

    @else
        <!-- ========================================== -->
        <!--         LAYOUT SIN AUTENTICACIÓN           -->
        <!-- ========================================== -->
        @yield('content')
    @endauth

    <!-- Scripts -->
    <script src="{{ asset('bower_components/jquery/dist/jquery.min.js') }}"></script>
    <script src="{{ asset('bower_components/bootstrap/dist/js/bootstrap.min.js') }}"></script>
    <script src="{{ asset('dist/js/adminlte.min.js') }}"></script>
    
    @stack('scripts')
</body>
</html>

7. Estructura de Archivos

text
📁 resources/
   └── 📁 views/
       ├── 📁 layouts/
       │   └── app.blade.php           ← Modificado
       ├── 📁 modulos/
       │   ├── header.blade.php        ← NUEVO
       │   ├── menu_admin.blade.php    ← NUEVO
       │   ├── menu_secretaria.blade.php ← NUEVO
       │   ├── menu_doctor.blade.php   ← NUEVO
       │   ├── menu_paciente.blade.php ← NUEVO
       │   ├── seleccionar.blade.php
       │   ├── ingresar.blade.php
       │   └── inicio.blade.php
       └── 📁 auth/

8. Verificar el Resultado

Paso 1: Iniciar sesión

  1. Ve a http://127.0.0.1:8000

  2. Haz clic en cualquier tarjeta de rol

  3. Ingresa tus credenciales

Paso 2: Verificar el menú según el rol

Administrador verá:

  • Dashboard

  • Configuración

  • Consultorios, Doctores, Pacientes, Secretarias

  • Agenda de Citas

Secretaria verá:

  • Dashboard

  • Consultorios, Doctores, Pacientes

  • Agenda de Citas

Doctor verá:

  • Dashboard

  • Mis Pacientes

  • Mi Agenda, Horarios

Paciente verá:

  • Dashboard

  • Buscar Doctor

  • Mis Citas, Historial


9. Solución de Problemas

ProblemaSolución
Error View [modulos.header] not foundVerifica que el archivo header.blade.php existe
Error Undefined variable en el menúAsegura Auth::user() antes de usarlo
El menú no se colapsaVerifica que sidebar-toggle tenga los atributos correctos
No se ve el avatar del usuarioVerifica la ruta de la imagen en asset()
Error de logoutAsegura que route('logout') esté definido

10. Comandos Útiles

bash
# Verificar que las rutas están definidas
php artisan route:list

# Limpiar caché de vistas
php artisan view:clear

# Limpiar caché de configuración
php artisan config:clear

# Ver el usuario autenticado en Tinker
php artisan tinker
>>> auth()->user()

11. Conclusión

🎉 ¡Excelente trabajo! Hemos creado:

  • ✅ Cabecera personalizada con logo y usuario

  • ✅ Menús dinámicos según el rol del usuario (admin, secretaria, doctor, paciente)

  • ✅ Sistema de partials con @include para componentes reutilizables

  • ✅ Protección de rutas con middleware de autenticación

En el próximo tutorial comenzaremos a desarrollar el módulo de secretaria, empezando con la gestión de consultorios (CRUD)

Comentarios