Browse Source
			
			
			
			
				
		restringi el acceso de las funciones de administrador para aceptar prestamos y que solo se pueda hacer un nuevo prestamo y yamain
				 14 changed files with 326 additions and 41 deletions
			
			
		@ -0,0 +1,49 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace App\Http\Controllers; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Illuminate\Http\Request; | 
				
			||||
 | 
					use App\Models\SolicitudVehiculo; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class SolicitudVehiculoController extends Controller | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    public function __construct() | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        $this->middleware(['auth', 'profesor']); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public function index() | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        $solicitudes = SolicitudVehiculo::where('user_id', auth()->id())->get(); | 
				
			||||
 | 
					        return view('profesor.solicitudes.index', compact('solicitudes')); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public function create() | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        return view('profesor.solicitudes.create'); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public function store(Request $request) | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        $request->validate([ | 
				
			||||
 | 
					            'fecha_solicitud' => 'required|date', | 
				
			||||
 | 
					            'hora_salida' => 'required', | 
				
			||||
 | 
					            'hora_regreso' => 'required', | 
				
			||||
 | 
					            'destino' => 'required|string', | 
				
			||||
 | 
					            'motivo' => 'required|string', | 
				
			||||
 | 
					        ]); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        $solicitud = new SolicitudVehiculo(); | 
				
			||||
 | 
					        $solicitud->user_id = auth()->id(); | 
				
			||||
 | 
					        $solicitud->fecha_solicitud = $request->fecha_solicitud; | 
				
			||||
 | 
					        $solicitud->hora_salida = $request->hora_salida; | 
				
			||||
 | 
					        $solicitud->hora_regreso = $request->hora_regreso; | 
				
			||||
 | 
					        $solicitud->destino = $request->destino; | 
				
			||||
 | 
					        $solicitud->motivo = $request->motivo; | 
				
			||||
 | 
					        $solicitud->estado = 'pendiente'; | 
				
			||||
 | 
					        $solicitud->save(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        return redirect()->route('profesor.solicitudes.index') | 
				
			||||
 | 
					            ->with('success', 'Solicitud creada exitosamente'); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}  | 
				
			||||
@ -0,0 +1,19 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace App\Http\Middleware; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Closure; | 
				
			||||
 | 
					use Illuminate\Http\Request; | 
				
			||||
 | 
					use Symfony\Component\HttpFoundation\Response; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class CheckAdminRole | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    public function handle(Request $request, Closure $next): Response | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        if (!auth()->check() || auth()->user()->rol !== 'admin') { | 
				
			||||
 | 
					            return redirect('/')->with('error', 'No tienes permisos de administrador para acceder a esta sección.'); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        return $next($request); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}  | 
				
			||||
@ -0,0 +1,19 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace App\Http\Middleware; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Closure; | 
				
			||||
 | 
					use Illuminate\Http\Request; | 
				
			||||
 | 
					use Symfony\Component\HttpFoundation\Response; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class CheckProfesorRole | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    public function handle(Request $request, Closure $next): Response | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        if (!auth()->check() || auth()->user()->rol !== 'profesor') { | 
				
			||||
 | 
					            return redirect('/')->with('error', 'No tienes permiso para acceder a esta sección.'); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        return $next($request); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}  | 
				
			||||
@ -0,0 +1,26 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace App\Models; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Illuminate\Database\Eloquent\Factories\HasFactory; | 
				
			||||
 | 
					use Illuminate\Database\Eloquent\Model; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class SolicitudVehiculo extends Model | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    use HasFactory; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    protected $fillable = [ | 
				
			||||
 | 
					        'user_id', | 
				
			||||
 | 
					        'fecha_solicitud', | 
				
			||||
 | 
					        'hora_salida', | 
				
			||||
 | 
					        'hora_regreso', | 
				
			||||
 | 
					        'destino', | 
				
			||||
 | 
					        'motivo', | 
				
			||||
 | 
					        'estado' | 
				
			||||
 | 
					    ]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public function user() | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        return $this->belongsTo(User::class); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}  | 
				
			||||
@ -0,0 +1,28 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Illuminate\Database\Migrations\Migration; | 
				
			||||
 | 
					use Illuminate\Database\Schema\Blueprint; | 
				
			||||
 | 
					use Illuminate\Support\Facades\Schema; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					return new class extends Migration | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    public function up(): void | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        Schema::create('solicitud_vehiculos', function (Blueprint $table) { | 
				
			||||
 | 
					            $table->id(); | 
				
			||||
 | 
					            $table->foreignId('user_id')->constrained()->onDelete('cascade'); | 
				
			||||
 | 
					            $table->date('fecha_solicitud'); | 
				
			||||
 | 
					            $table->time('hora_salida'); | 
				
			||||
 | 
					            $table->time('hora_regreso'); | 
				
			||||
 | 
					            $table->string('destino'); | 
				
			||||
 | 
					            $table->text('motivo'); | 
				
			||||
 | 
					            $table->enum('estado', ['pendiente', 'aprobada', 'rechazada'])->default('pendiente'); | 
				
			||||
 | 
					            $table->timestamps(); | 
				
			||||
 | 
					        }); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    public function down(): void | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        Schema::dropIfExists('solicitud_vehiculos'); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					};  | 
				
			||||
@ -1,28 +0,0 @@ | 
				
			|||||
<?php | 
					 | 
				
			||||
 | 
					 | 
				
			||||
use Illuminate\Database\Migrations\Migration; | 
					 | 
				
			||||
use Illuminate\Database\Schema\Blueprint; | 
					 | 
				
			||||
use Illuminate\Support\Facades\Schema; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
return new class extends Migration | 
					 | 
				
			||||
{ | 
					 | 
				
			||||
    /** | 
					 | 
				
			||||
     * Run the migrations. | 
					 | 
				
			||||
     */ | 
					 | 
				
			||||
    public function up(): void | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
        Schema::table('prestamos', function (Blueprint $table) { | 
					 | 
				
			||||
            $table->enum('estado', ['pendiente', 'aceptado', 'rechazado'])->default('pendiente')->after('chofer'); | 
					 | 
				
			||||
        }); | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    /** | 
					 | 
				
			||||
     * Reverse the migrations. | 
					 | 
				
			||||
     */ | 
					 | 
				
			||||
    public function down(): void | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
        Schema::table('prestamos', function (Blueprint $table) { | 
					 | 
				
			||||
            $table->dropColumn('estado'); | 
					 | 
				
			||||
        }); | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
@ -0,0 +1,22 @@ | 
				
			|||||
 | 
					<?php | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace Database\Seeders; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					use Illuminate\Database\Seeder; | 
				
			||||
 | 
					use App\Models\User; | 
				
			||||
 | 
					use Illuminate\Support\Facades\Hash; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class ProfesorSeeder extends Seeder | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    public function run(): void | 
				
			||||
 | 
					    { | 
				
			||||
 | 
					        User::create([ | 
				
			||||
 | 
					            'name' => 'Profesor', | 
				
			||||
 | 
					            'email' => 'profesor@profesor.com', | 
				
			||||
 | 
					            'password' => Hash::make('12345678'), | 
				
			||||
 | 
					            'rol' => 'profesor', | 
				
			||||
 | 
					            'apellido' => 'Ejemplo', | 
				
			||||
 | 
					            'telefono' => '1234567890', | 
				
			||||
 | 
					        ]); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}  | 
				
			||||
@ -0,0 +1,78 @@ | 
				
			|||||
 | 
					@extends('layouts.dashboard') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@section('content') | 
				
			||||
 | 
					<div class="container mx-auto px-4 py-6"> | 
				
			||||
 | 
					    <div class="max-w-2xl mx-auto"> | 
				
			||||
 | 
					        <div class="bg-white rounded-lg shadow-lg overflow-hidden"> | 
				
			||||
 | 
					            <div class="p-6"> | 
				
			||||
 | 
					                <h2 class="text-2xl font-bold text-gray-800 mb-6">Nueva Solicitud de Vehículo</h2> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                @if($errors->any()) | 
				
			||||
 | 
					                <div class="mb-6 bg-red-50 border-l-4 border-red-500 p-4 rounded-r-lg"> | 
				
			||||
 | 
					                    <div class="flex items-center"> | 
				
			||||
 | 
					                        <div class="text-red-700"> | 
				
			||||
 | 
					                            <ul> | 
				
			||||
 | 
					                                @foreach($errors->all() as $error) | 
				
			||||
 | 
					                                    <li>{{ $error }}</li> | 
				
			||||
 | 
					                                @endforeach | 
				
			||||
 | 
					                            </ul> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </div> | 
				
			||||
 | 
					                @endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                <form action="{{ route('profesor.solicitudes.store') }}" method="POST"> | 
				
			||||
 | 
					                    @csrf | 
				
			||||
 | 
					                    <div class="space-y-6"> | 
				
			||||
 | 
					                        <div> | 
				
			||||
 | 
					                            <label for="fecha_solicitud" class="block text-sm font-medium text-gray-700 mb-2">Fecha de Solicitud</label> | 
				
			||||
 | 
					                            <input type="date" name="fecha_solicitud" id="fecha_solicitud" | 
				
			||||
 | 
					                                class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" | 
				
			||||
 | 
					                                required> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <div> | 
				
			||||
 | 
					                            <label for="hora_salida" class="block text-sm font-medium text-gray-700 mb-2">Hora de Salida</label> | 
				
			||||
 | 
					                            <input type="time" name="hora_salida" id="hora_salida" | 
				
			||||
 | 
					                                class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" | 
				
			||||
 | 
					                                required> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <div> | 
				
			||||
 | 
					                            <label for="hora_regreso" class="block text-sm font-medium text-gray-700 mb-2">Hora de Regreso</label> | 
				
			||||
 | 
					                            <input type="time" name="hora_regreso" id="hora_regreso" | 
				
			||||
 | 
					                                class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" | 
				
			||||
 | 
					                                required> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <div> | 
				
			||||
 | 
					                            <label for="destino" class="block text-sm font-medium text-gray-700 mb-2">Destino</label> | 
				
			||||
 | 
					                            <input type="text" name="destino" id="destino" | 
				
			||||
 | 
					                                class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" | 
				
			||||
 | 
					                                required> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <div> | 
				
			||||
 | 
					                            <label for="motivo" class="block text-sm font-medium text-gray-700 mb-2">Motivo</label> | 
				
			||||
 | 
					                            <textarea name="motivo" id="motivo" rows="4" | 
				
			||||
 | 
					                                class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" | 
				
			||||
 | 
					                                required></textarea> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <div class="flex justify-end space-x-4"> | 
				
			||||
 | 
					                            <a href="{{ route('profesor.solicitudes.index') }}" | 
				
			||||
 | 
					                                class="px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> | 
				
			||||
 | 
					                                Cancelar | 
				
			||||
 | 
					                            </a> | 
				
			||||
 | 
					                            <button type="submit" | 
				
			||||
 | 
					                                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"> | 
				
			||||
 | 
					                                Enviar Solicitud | 
				
			||||
 | 
					                            </button> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </form> | 
				
			||||
 | 
					            </div> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					@endsection  | 
				
			||||
@ -0,0 +1,51 @@ | 
				
			|||||
 | 
					@extends('layouts.dashboard') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@section('content') | 
				
			||||
 | 
					<div class="container mx-auto px-4 py-6"> | 
				
			||||
 | 
					    <div class="flex justify-between items-center mb-6"> | 
				
			||||
 | 
					        <h2 class="text-2xl font-bold text-gray-800">Mis Solicitudes de Vehículo</h2> | 
				
			||||
 | 
					        <a href="{{ route('profesor.solicitudes.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> | 
				
			||||
 | 
					            Nueva Solicitud | 
				
			||||
 | 
					        </a> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @if(session('success')) | 
				
			||||
 | 
					        <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4" role="alert"> | 
				
			||||
 | 
					            <span class="block sm:inline">{{ session('success') }}</span> | 
				
			||||
 | 
					        </div> | 
				
			||||
 | 
					    @endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    <div class="bg-white shadow-md rounded-lg overflow-hidden"> | 
				
			||||
 | 
					        <table class="min-w-full divide-y divide-gray-200"> | 
				
			||||
 | 
					            <thead class="bg-gray-50"> | 
				
			||||
 | 
					                <tr> | 
				
			||||
 | 
					                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Fecha</th> | 
				
			||||
 | 
					                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Hora Salida</th> | 
				
			||||
 | 
					                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Hora Regreso</th> | 
				
			||||
 | 
					                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Destino</th> | 
				
			||||
 | 
					                    <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Estado</th> | 
				
			||||
 | 
					                </tr> | 
				
			||||
 | 
					            </thead> | 
				
			||||
 | 
					            <tbody class="bg-white divide-y divide-gray-200"> | 
				
			||||
 | 
					                @foreach($solicitudes as $solicitud) | 
				
			||||
 | 
					                <tr> | 
				
			||||
 | 
					                    <td class="px-6 py-4 whitespace-nowrap">{{ $solicitud->fecha_solicitud }}</td> | 
				
			||||
 | 
					                    <td class="px-6 py-4 whitespace-nowrap">{{ $solicitud->hora_salida }}</td> | 
				
			||||
 | 
					                    <td class="px-6 py-4 whitespace-nowrap">{{ $solicitud->hora_regreso }}</td> | 
				
			||||
 | 
					                    <td class="px-6 py-4">{{ $solicitud->destino }}</td> | 
				
			||||
 | 
					                    <td class="px-6 py-4 whitespace-nowrap"> | 
				
			||||
 | 
					                        <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full  | 
				
			||||
 | 
					                            @if($solicitud->estado === 'aprobada') bg-green-100 text-green-800 | 
				
			||||
 | 
					                            @elseif($solicitud->estado === 'rechazada') bg-red-100 text-red-800 | 
				
			||||
 | 
					                            @else bg-yellow-100 text-yellow-800 | 
				
			||||
 | 
					                            @endif"> | 
				
			||||
 | 
					                            {{ ucfirst($solicitud->estado) }} | 
				
			||||
 | 
					                        </span> | 
				
			||||
 | 
					                    </td> | 
				
			||||
 | 
					                </tr> | 
				
			||||
 | 
					                @endforeach | 
				
			||||
 | 
					            </tbody> | 
				
			||||
 | 
					        </table> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					</div> | 
				
			||||
 | 
					@endsection  | 
				
			||||
					Loading…
					
					
				
		Reference in new issue