7: Iniciar Sesión

 

7: Iniciar Sesión

1. Introducción

En este tutorial implementaremos el sistema de inicio de sesión para nuestra aplicación. Crearemos una vista personalizada de login, configuraremos las rutas y redirecciones, y prepararemos el dashboard principal que verán los usuarios después de autenticarse.


2. Objetivos

  • ✅ Crear vista personalizada de inicio de sesión

  • ✅ Configurar el formulario de login con CSRF

  • ✅ Crear el controlador y modelo de inicio

  • ✅ Configurar redirecciones después del login

  • ✅ Implementar validación de autenticación en el layout


3. Configuración de Rutas

Paso 1: Modificar routes/web.php

Actualizamos el archivo de rutas para incluir la nueva ruta de inicio:

php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\InicioController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
*/

// Ruta principal: mostrar selección de roles
Route::get('/', function () {
    return view('modulos.seleccionar');
});

// Ruta para el login personalizado
Route::get('/ingresar', function () {
    return view('modulos.ingresar');
});

// Rutas de autenticación de Laravel
Auth::routes();

// Dashboard (protegido por autenticación)
Route::get('/home', [HomeController::class, 'index'])->name('home');

// Ruta de inicio después del login
Route::get('/inicio', [InicioController::class, 'index'])->name('inicio');

4. Crear la Vista de Login Personalizada

Paso 1: Crear ingresar.blade.php

Crea el archivo resources/views/modulos/ingresar.blade.php:

php
@extends('layouts.app')

@section('title', 'Iniciar Sesión')

@section('content')
<div class="login-page">
    <div class="login-box">
        <!-- Logo -->
        <div class="login-logo">
            <a href="#"><b>Clínica</b> Médica</a>
        </div>
        <!-- /.login-logo -->
        
        <div class="login-box-body">
            <p class="login-box-msg">Ingresar al sistema</p>

            <!-- Formulario de Login -->
            <form method="POST" action="{{ route('login') }}">
                @csrf

                <!-- Campo: Email -->
                <div class="form-group has-feedback">
                    <input type="email" 
                           name="email" 
                           class="form-control" 
                           placeholder="Correo electrónico" 
                           value="{{ old('email') }}" 
                           required autofocus>
                    <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
                    
                    @error('email')
                        <span class="help-block text-danger">
                            <strong>{{ $message }}</strong>
                        </span>
                    @enderror
                </div>

                <!-- Campo: Password -->
                <div class="form-group has-feedback">
                    <input type="password" 
                           name="password" 
                           class="form-control" 
                           placeholder="Contraseña" 
                           required>
                    <span class="glyphicon glyphicon-lock form-control-feedback"></span>
                    
                    @error('password')
                        <span class="help-block text-danger">
                            <strong>{{ $message }}</strong>
                        </span>
                    @enderror
                </div>

                <!-- Opciones: Recordar y Olvidé contraseña -->
                <div class="row">
                    <div class="col-xs-8">
                        <div class="checkbox icheck">
                            <label>
                                <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}>
                                Recordarme
                            </label>
                        </div>
                    </div>
                    <!-- /.col -->
                    <div class="col-xs-4">
                        <button type="submit" class="btn btn-primary btn-block btn-flat">
                            <i class="fa fa-sign-in"></i> Ingresar
                        </button>
                    </div>
                    <!-- /.col -->
                </div>
            </form>

            <!-- Enlaces adicionales -->
            <div class="social-auth-links text-center">
                <p>- O -</p>
                <a href="{{ route('register') }}" class="btn btn-block btn-success btn-flat">
                    <i class="fa fa-user-plus"></i> Registrarse como nuevo usuario
                </a>
            </div>
            <!-- /.social-auth-links -->

            <a href="{{ url('/') }}" class="text-center">
                <i class="fa fa-arrow-left"></i> Volver a seleccionar
            </a>

        </div>
        <!-- /.login-box-body -->
    </div>
    <!-- /.login-box -->
</div>
<!-- /.login-page -->
@endsection

@push('styles')
<style>
    .login-page {
        background: #3c8dbc;
        background: -webkit-linear-gradient(to right, #3c8dbc, #2c3e50);
        background: linear-gradient(to right, #3c8dbc, #2c3e50);
        min-height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .login-box {
        width: 400px;
        margin: 0 auto;
    }
    
    .login-box-body {
        background: #ffffff;
        padding: 20px;
        border-top: 0;
        color: #666;
        border-radius: 4px;
        box-shadow: 0 5px 15px rgba(0,0,0,0.3);
    }
    
    .login-logo a {
        color: #fff;
        font-size: 35px;
        font-weight: 300;
        text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    
    .login-logo a b {
        font-weight: 700;
    }
    
    .login-box-msg {
        margin: 0;
        text-align: center;
        padding: 0 0 20px 0;
        font-size: 18px;
        border-bottom: 1px solid #f4f4f4;
        color: #444;
    }
    
    .has-feedback .form-control-feedback {
        top: 0;
        right: 0;
        color: #777;
        line-height: 34px;
    }
    
    .help-block.text-danger {
        color: #dd4b39;
        margin-top: 5px;
    }
    
    .icheck > label {
        padding-left: 0;
        font-weight: normal;
    }
    
    .social-auth-links {
        margin: 15px 0 10px 0;
    }
    
    .btn-flat {
        border-radius: 0;
    }
</style>
@endpush

5. Crear el Controlador de Inicio

Paso 1: Generar el controlador y modelo

Ejecuta el siguiente comando para crear el controlador y modelo juntos:

bash
php artisan make:model Inicio -c -r

Explicación del comando:

  • make:model Inicio → Crea el modelo Inicio

  • -c → Crea el controlador junto con el modelo

  • -r → Crea el controlador con métodos de recurso (index, create, store, etc.)

Paso 2: El controlador generado

Se generará app/Http/Controllers/InicioController.php:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class InicioController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // Vista de inicio después del login
        return view('modulos.inicio');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

6. Crear la Vista de Inicio

Paso 1: Crear inicio.blade.php

Crea el archivo resources/views/modulos/inicio.blade.php:

php
@extends('layouts.app')

@section('title', 'Inicio')

@section('page-title', 'Panel de Control')
@section('page-subtitle', 'Bienvenido al sistema')

@section('breadcrumb')
    <li class="active">Inicio</li>
@endsection

@section('content')
<div class="row">
    <div class="col-md-12">
        <div class="box box-primary">
            <div class="box-header with-border">
                <h3 class="box-title">
                    <i class="fa fa-dashboard"></i> Bienvenido al sistema
                </h3>
                <div class="box-tools pull-right">
                    <button type="button" class="btn btn-box-tool" data-widget="collapse">
                        <i class="fa fa-minus"></i>
                    </button>
                </div>
            </div>
            <!-- /.box-header -->
            
            <div class="box-body">
                <div class="row">
                    <div class="col-md-4 col-sm-6 col-xs-12">
                        <div class="info-box">
                            <span class="info-box-icon bg-aqua"><i class="fa fa-user-md"></i></span>
                            <div class="info-box-content">
                                <span class="info-box-text">Doctores</span>
                                <span class="info-box-number">5</span>
                            </div>
                            <!-- /.info-box-content -->
                        </div>
                        <!-- /.info-box -->
                    </div>
                    <!-- /.col -->
                    
                    <div class="col-md-4 col-sm-6 col-xs-12">
                        <div class="info-box">
                            <span class="info-box-icon bg-green"><i class="fa fa-users"></i></span>
                            <div class="info-box-content">
                                <span class="info-box-text">Pacientes</span>
                                <span class="info-box-number">12</span>
                            </div>
                            <!-- /.info-box-content -->
                        </div>
                        <!-- /.info-box -->
                    </div>
                    <!-- /.col -->
                    
                    <div class="col-md-4 col-sm-6 col-xs-12">
                        <div class="info-box">
                            <span class="info-box-icon bg-yellow"><i class="fa fa-calendar"></i></span>
                            <div class="info-box-content">
                                <span class="info-box-text">Citas Hoy</span>
                                <span class="info-box-number">3</span>
                            </div>
                            <!-- /.info-box-content -->
                        </div>
                        <!-- /.info-box -->
                    </div>
                    <!-- /.col -->
                </div>
                <!-- /.row -->
                
                <div class="row">
                    <div class="col-md-6">
                        <div class="box box-success">
                            <div class="box-header with-border">
                                <h3 class="box-title">
                                    <i class="fa fa-clock-o"></i> Actividad Reciente
                                </h3>
                            </div>
                            <div class="box-body">
                                <ul class="todo-list">
                                    <li>
                                        <span class="text">
                                            Bienvenido <strong>{{ Auth::user()->name }}</strong> al sistema de citas médicas
                                        </span>
                                        <small class="label label-info pull-right">
                                            <i class="fa fa-clock-o"></i> Ahora
                                        </small>
                                    </li>
                                    <li>
                                        <span class="text">
                                            Tu rol en el sistema es: <strong>{{ Auth::user()->rol }}</strong>
                                        </span>
                                        <small class="label label-success pull-right">
                                            <i class="fa fa-check"></i> Activo
                                        </small>
                                    </li>
                                </ul>
                            </div>
                        </div>
                    </div>
                    
                    <div class="col-md-6">
                        <div class="box box-warning">
                            <div class="box-header with-border">
                                <h3 class="box-title">
                                    <i class="fa fa-info-circle"></i> Información del Usuario
                                </h3>
                            </div>
                            <div class="box-body">
                                <table class="table table-striped">
                                    <tr>
                                        <th><i class="fa fa-user"></i> Nombre:</th>
                                        <td>{{ Auth::user()->name }}</td>
                                    </tr>
                                    <tr>
                                        <th><i class="fa fa-envelope"></i> Email:</th>
                                        <td>{{ Auth::user()->email }}</td>
                                    </tr>
                                    <tr>
                                        <th><i class="fa fa-id-card"></i> Documento:</th>
                                        <td>{{ Auth::user()->documento ?? 'No registrado' }}</td>
                                    </tr>
                                    <tr>
                                        <th><i class="fa fa-phone"></i> Teléfono:</th>
                                        <td>{{ Auth::user()->telefono ?? 'No registrado' }}</td>
                                    </tr>
                                    <tr>
                                        <th><i class="fa fa-tag"></i> Rol:</th>
                                        <td>
                                            <span class="label label-primary">{{ Auth::user()->rol }}</span>
                                        </td>
                                    </tr>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <!-- /.box-body -->
        </div>
        <!-- /.box -->
    </div>
</div>
@endsection

@push('styles')
<style>
    .info-box {
        min-height: 90px;
        background: #fff;
        box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        border-radius: 4px;
        transition: all 0.3s ease;
    }
    
    .info-box:hover {
        transform: translateY(-5px);
        box-shadow: 0 5px 15px rgba(0,0,0,0.15);
    }
    
    .info-box-icon {
        border-radius: 4px 0 0 4px;
        display: block;
        float: left;
        height: 90px;
        width: 90px;
        text-align: center;
        font-size: 45px;
        line-height: 90px;
        background: rgba(0,0,0,0.2);
    }
    
    .info-box-content {
        padding: 5px 10px;
        margin-left: 90px;
    }
    
    .info-box-number {
        display: block;
        font-weight: 700;
        font-size: 28px;
        color: #333;
    }
    
    .info-box-text {
        display: block;
        font-size: 14px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        text-transform: uppercase;
        color: #888;
    }
    
    .todo-list {
        margin: 0;
        padding: 0;
        list-style: none;
    }
    
    .todo-list > li {
        border-radius: 2px;
        padding: 10px 15px;
        background: #f4f4f4;
        margin-bottom: 2px;
        border-left: 2px solid #e6e7e8;
        color: #444;
        position: relative;
    }
    
    .todo-list > li .text {
        display: inline-block;
        font-weight: 600;
    }
    
    .todo-list > li .label {
        margin-left: 10px;
        font-size: 11px;
        padding: 3px 8px;
    }
    
    .table td, .table th {
        padding: 8px 12px;
        vertical-align: middle;
    }
</style>
@endpush

7. Modificar el Layout para Autenticación

Paso 1: Actualizar layouts/app.blade.php

Modificamos el layout para mostrar contenido diferente según si el usuario está autenticado:

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">
            
            <!-- Header -->
            <header class="main-header">
                <a href="{{ url('/inicio') }}" class="logo">
                    <span class="logo-mini"><b>C</b>L</span>
                    <span class="logo-lg"><b>Clínica</b> L8</span>
                </a>
                
                <nav class="navbar navbar-static-top">
                    <a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
                        <span class="sr-only">Toggle navigation</span>
                    </a>
                    
                    <div class="navbar-custom-menu">
                        <ul class="nav navbar-nav">
                            <li class="dropdown user user-menu">
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                    <img src="{{ asset('dist/img/user2-160x160.jpg') }}" class="user-image" alt="User Image">
                                    <span class="hidden-xs">{{ Auth::user()->name }}</span>
                                </a>
                                <ul class="dropdown-menu">
                                    <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>
                                    <li class="user-footer">
                                        <div class="pull-left">
                                            <a href="#" class="btn btn-default btn-flat">Perfil</a>
                                        </div>
                                        <div class="pull-right">
                                            <a href="{{ route('logout') }}" class="btn btn-default btn-flat"
                                               onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
                                                Cerrar Sesión
                                            </a>
                                            <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
                                                @csrf
                                            </form>
                                        </div>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </div>
                </nav>
            </header>

            <!-- Sidebar -->
            <aside class="main-sidebar">
                <section class="sidebar">
                    <!-- User Panel -->
                    <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>

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

                        @if(Auth::user()->rol == 'admin')
                            <li class="header">ADMINISTRACIÓN</li>
                            <li>
                                <a href="#">
                                    <i class="fa fa-cogs"></i> <span>Configuración</span>
                                </a>
                            </li>
                        @endif

                        @if(in_array(Auth::user()->rol, ['admin', 'secretaria']))
                            <li class="header">GESTIÓN</li>
                            <li>
                                <a href="#">
                                    <i class="fa fa-building"></i> <span>Consultorios</span>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <i class="fa fa-user-md"></i> <span>Doctores</span>
                                </a>
                            </li>
                            <li>
                                <a href="#">
                                    <i class="fa fa-users"></i> <span>Pacientes</span>
                                </a>
                            </li>
                        @endif
                    </ul>
                </section>
            </aside>

            <!-- Content Wrapper -->
            <div class="content-wrapper">
                <!-- Content 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>

8. Modificar el LoginController para Redirección

Paso 1: Actualizar app/Http/Controllers/Auth/LoginController.php

php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/inicio';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

9. Verificar el Sistema

Paso 1: Iniciar sesión

  1. Ve a http://127.0.0.1:8000

  2. Haz clic en cualquier tarjeta (ej: Secretaria)

  3. Serás redirigido a la página de login

  4. Ingresa tus credenciales:

    • Email: maria@example.com

    • Password: 123

Paso 2: Verificar el dashboard

Después del login, deberías ver el dashboard personalizado:

text
┌─────────────────────────────────────────────────────────────────┐
│  [C] Clínica L8                    👤 María [▼] [Cerrar]      │
├─────────────────────────────────────────────────────────────────┤
│  ☰ Dashboard                                                  │
│    MENÚ PRINCIPAL                                              │
│      Dashboard                                                 │
│    ADMINISTRACIÓN                                              │
│      Configuración                                             │
│    GESTIÓN                                                     │
│      Consultorios                                              │
│      Doctores                                                  │
│      Pacientes                                                 │
├─────────────────────────────────────────────────────────────────┤
│  Dashboard / Panel de control                                  │
│                                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │  👨‍⚕️      │  │  👥       │  │  📅        │          │
│  │  Doctores   │  │  Pacientes │  │  Citas Hoy │          │
│  │     5       │  │    12      │  │     3      │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
│                                                                 │
│  ┌──────────────────────────┐  ┌──────────────────────────┐  │
│  │  🕐 Actividad Reciente    │  │  ℹ️ Información Usuario  │  │
│  │  Bienvenido María ...     │  │  Nombre: María Gaspard  │  │
│  │  Rol: admin              │  │  Email: maria@...       │  │
│  └──────────────────────────┘  └──────────────────────────┘  │
│                                                                 │
│  Copyright © 2024 Clínica L8.                                   │
└─────────────────────────────────────────────────────────────────┘

10. Resumen de Archivos Creados/Modificados

ArchivoAcción
routes/web.phpModificado (nuevas rutas)
resources/views/modulos/ingresar.blade.phpCrear (login personalizado)
resources/views/modulos/inicio.blade.phpCrear (dashboard)
resources/views/layouts/app.blade.phpModificado (autenticación condicional)
app/Http/Controllers/InicioController.phpCrear (controlador)
app/Http/Controllers/Auth/LoginController.phpModificado (redirección)
app/Models/Inicio.phpCrear (modelo, no usado aún)

11. Comandos Útiles

bash
# Crear controlador con modelo
php artisan make:model Inicio -c -r

# Limpiar caché de vistas
php artisan view:clear

# Limpiar caché de rutas
php artisan route:clear

# Ver rutas registradas
php artisan route:list

12. Solución de Problemas

ProblemaSolución
Route [login] not definedEjecuta php artisan route:clear
Error 404 después del loginVerifica que la ruta /inicio esté registrada
No se ve el dashboardVerifica que InicioController::index exista
CSRF token mismatchAsegura @csrf en el formulario
Redirección a /homeCambia $redirectTo en LoginController

13. Conclusión

🎉 ¡Excelente trabajo! Hemos implementado:

  • ✅ Sistema de login personalizado con diseño AdminLTE

  • ✅ Dashboard de bienvenida con información del usuario

  • ✅ Redirección correcta después de la autenticación

  • ✅ Layout condicional (con/sin autenticación)

  • ✅ Menú dinámico según el rol del usuario

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

Comentarios