Browse Source

Servicios

Funcionaminetos Exclusivos para Jorge y restricciones, agregamos vehiculos al CRUD de prestamos y choferes para cuando marquen la casilla de "requiere chofer?"
main
TheSilva7 6 days ago
parent
commit
54d76658f8
  1. 24
      app/Exports/ChoferesExport.php
  2. 97
      app/Http/Controllers/ChoferController.php
  3. 35
      app/Http/Controllers/PrestamoController.php
  4. 1
      app/Http/Kernel.php
  5. 23
      app/Http/Middleware/AdminOrServiciosRole.php
  6. 5
      app/Http/Middleware/CheckAdminRole.php
  7. 18
      app/Models/Chofer.php
  8. 8
      app/Models/prestamo.php
  9. 11
      app/Providers/AuthServiceProvider.php
  10. 1
      database/migrations/2025_03_27_174121_create_prestamos_table.php
  11. 28
      database/migrations/2025_03_28_182126_add_estado_to_prestamos_table.php
  12. 28
      database/migrations/2025_03_28_183038_add_estado_to_prestamos_table.php
  13. 15
      database/migrations/2025_04_01_191325_add_estado_to_prestamos_table.php
  14. 19
      database/migrations/2025_05_22_205902_create_chofers_table.php
  15. 25
      database/migrations/2025_05_22_212123_add_chofer_id_to_prestamos_table.php
  16. 95
      resources/views/choferes.blade.php
  17. 62
      resources/views/choferesCrearEditar.blade.php
  18. 55
      resources/views/exports/choferes-pdf.blade.php
  19. 4
      resources/views/layouts/dashboard.blade.php
  20. 7
      resources/views/prestamos.blade.php
  21. 52
      resources/views/prestamosCrearEditar.blade.php
  22. 152
      resources/views/tiposLicencia.blade.php
  23. 85
      resources/views/tiposLicenciaCrearEditar.blade.php
  24. 72
      routes/web.php

24
app/Exports/ChoferesExport.php

@ -0,0 +1,24 @@
<?php
namespace App\Exports;
use App\Models\Chofer;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class ChoferesExport implements FromCollection, WithHeadings
{
public function collection()
{
return Chofer::select('id', 'nombre', 'tipo_licencia')->get();
}
public function headings(): array
{
return [
'ID',
'Nombre',
'Tipo de Licencia',
];
}
}

97
app/Http/Controllers/ChoferController.php

@ -0,0 +1,97 @@
<?php
namespace App\Http\Controllers;
use App\Models\Chofer;
use Illuminate\Http\Request;
use PDF;
use App\Exports\ChoferesExport;
use Maatwebsite\Excel\Facades\Excel;
class ChoferController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$choferes = Chofer::all();
return view('choferes', compact('choferes'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('choferesCrearEditar', ['chofer' => null]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
'nombre' => 'required|string|max:255',
'tipo_licencia' => 'required|string|max:255',
]);
Chofer::create($request->all());
return redirect()->route('choferes.index')->with('success', 'Chofer creado exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(Chofer $chofer)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$chofer = Chofer::findOrFail($id);
return view('choferesCrearEditar', compact('chofer'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$request->validate([
'nombre' => 'required|string|max:255',
'tipo_licencia' => 'required|string|max:255',
]);
$chofer = Chofer::findOrFail($id);
$chofer->update($request->all());
return redirect()->route('choferes.index')->with('success', 'Chofer actualizado exitosamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$chofer = Chofer::findOrFail($id);
$chofer->delete();
return redirect()->route('choferes.index')->with('success', 'Chofer eliminado exitosamente.');
}
public function exportExcel()
{
return \Maatwebsite\Excel\Facades\Excel::download(new \App\Exports\ChoferesExport, 'choferes.xlsx');
}
public function exportPDF()
{
$choferes = \App\Models\Chofer::all();
$pdf = \PDF::loadView('exports.choferes-pdf', ['choferes' => $choferes]);
return $pdf->download('choferes.pdf');
}
}

35
app/Http/Controllers/PrestamoController.php

@ -40,7 +40,13 @@ class PrestamoController extends Controller
*/
public function create()
{
return view('prestamosCrearEditar', ['prestamo' => null]); // No se necesita pasar préstamos
$vehiculos = \App\Models\tiposVeiculos::where('status', true)->get();
$choferes = \App\Models\Chofer::all();
return view('prestamosCrearEditar', [
'prestamo' => null,
'vehiculos' => $vehiculos,
'choferes' => $choferes
]);
}
/**
@ -48,16 +54,27 @@ class PrestamoController extends Controller
*/
public function store(Request $request)
{
// Validación de datos
$request->validate([
'nombre_solicitante' => 'required|string|max:255',
'chofer_id' => 'required|exists:choferes,id',
'destino' => 'required|string|max:255',
'fecha_hora_salida' => 'required|date',
'fecha_hora_llegada' => 'required|date',
'motivo' => 'required|string|max:255',
'domicilio' => 'required|string|max:255',
'numero_personas' => 'required|integer',
'vehiculo_id' => 'required|exists:tipos_veiculos,id'
]);
// Preparar los datos
$datos = $request->all();
$datos['chofer'] = $request->has('chofer') ? 1 : 0; // Convertir 'on' a 1, o ausencia a 0
$datos['chofer'] = $request->has('chofer') ? 1 : 0;
$prestamo = new Prestamo($datos);
$prestamo->estado = 'pendiente'; // Estado inicial
$prestamo->estado = 'pendiente';
$prestamo->save();
// Aquí puedes agregar notificaciones para los administradores
return redirect()->route('prestamos.index')
->with('success', 'Préstamo solicitado correctamente. Esperando aprobación.');
}
@ -68,7 +85,13 @@ class PrestamoController extends Controller
public function edit($id)
{
$prestamo = Prestamo::findOrFail($id); // Busca el préstamo por ID
return view('prestamosCrearEditar', ['prestamo' => $prestamo]); // Pasa el préstamo a la vista
$vehiculos = \App\Models\tiposVeiculos::where('status', true)->get();
$choferes = \App\Models\Chofer::all();
return view('prestamosCrearEditar', [
'prestamo' => $prestamo,
'vehiculos' => $vehiculos,
'choferes' => $choferes
]); // Pasa el préstamo a la vista
}
/**

1
app/Http/Kernel.php

@ -67,5 +67,6 @@ class Kernel extends HttpKernel
'profesor' => \App\Http\Middleware\CheckProfesorRole::class,
'admin' => \App\Http\Middleware\CheckAdminRole::class,
'servicios' => \App\Http\Middleware\CheckServiciosRole::class,
'adminOrServicios' => \App\Http\Middleware\AdminOrServiciosRole::class,
];
}

23
app/Http/Middleware/AdminOrServiciosRole.php

@ -0,0 +1,23 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AdminOrServiciosRole
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle($request, Closure $next)
{
if (!auth()->check() || !in_array(auth()->user()->rol, ['admin', 'servicios'])) {
return redirect()->route('dashboard')->with('error', 'No tienes permisos para acceder a esta sección.');
}
return $next($request);
}
}

5
app/Http/Middleware/CheckAdminRole.php

@ -11,9 +11,10 @@ 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 redirect()->route('dashboard')
->with('error', 'No tienes permisos de administrador para acceder a esta sección.');
}
return $next($request);
}
}
}

18
app/Models/Chofer.php

@ -0,0 +1,18 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Chofer extends Model
{
use HasFactory;
protected $table = 'choferes';
protected $fillable = [
'nombre',
'tipo_licencia',
];
}

8
app/Models/prestamo.php

@ -20,6 +20,12 @@ protected $fillable = [
'numero_personas',
'chofer',
'estado',
'eliminado'
'eliminado',
'vehiculo_id'
];
public function vehiculo()
{
return $this->belongsTo(\App\Models\tiposVeiculos::class, 'vehiculo_id');
}
}

11
app/Providers/AuthServiceProvider.php

@ -4,6 +4,7 @@ namespace App\Providers;
// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
@ -20,9 +21,11 @@ class AuthServiceProvider extends ServiceProvider
* Register any authentication / authorization services.
*/
public function boot(): void
{
$this->registerPolicies();
{
$this->registerPolicies();
//
}
Gate::define('gestionar-prestamos', function ($user) {
return in_array($user->rol, ['admin', 'servicios']);
});
}
}

1
database/migrations/2025_03_27_174121_create_prestamos_table.php

@ -21,6 +21,7 @@ return new class extends Migration
$table->string('domicilio');
$table->integer('numero_personas');
$table->boolean('chofer')->default(false); // Opción de sí (true) o no (false)
$table->foreignId('vehiculo_id')->constrained('tipos_veiculos')->onDelete('cascade');
$table->timestamps();
});
}

28
database/migrations/2025_03_28_182126_add_estado_to_prestamos_table.php

@ -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) {
//
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('prestamos', function (Blueprint $table) {
//
});
}
};

28
database/migrations/2025_03_28_183038_add_estado_to_prestamos_table.php

@ -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->string('estado')->default('pendiente'); // pendiente, aceptado, rechazado
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('prestamos', function (Blueprint $table) {
$table->dropColumn('estado');
});
}
};

15
database/migrations/2025_04_01_191325_add_estado_to_prestamos_table.php

@ -9,21 +9,22 @@ return new class extends Migration
/**
* Run the migrations.
*/
public function up(): void
public function up()
{
Schema::table('prestamos', function (Blueprint $table) {
// $table->enum('estado', ['pendiente', 'aceptado', 'rechazado'])->default('pendiente')->after('chofer');
// Línea comentada porque la columna ya existe
$table->string('estado')->default('pendiente');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('prestamos', function (Blueprint $table) {
public function down()
{
Schema::table('prestamos', function (Blueprint $table) {
if (Schema::hasColumn('prestamos', 'estado')) {
$table->dropColumn('estado');
});
}
});
}
};

19
database/migrations/2025_03_28_175646_add_estado_to_prestamos_table.php → database/migrations/2025_05_22_205902_create_chofers_table.php

@ -9,20 +9,21 @@ return new class extends Migration
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('prestamos', function (Blueprint $table) {
//
});
}
public function up()
{
Schema::create('choferes', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->string('tipo_licencia');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('prestamos', function (Blueprint $table) {
//
});
Schema::dropIfExists('choferes');
}
};

25
database/migrations/2025_05_22_212123_add_chofer_id_to_prestamos_table.php

@ -0,0 +1,25 @@
<?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()
{
Schema::table('prestamos', function (Blueprint $table) {
$table->foreignId('chofer_id')->nullable()->constrained('choferes')->onDelete('set null');
});
}
public function down()
{
Schema::table('prestamos', function (Blueprint $table) {
$table->dropForeign(['chofer_id']);
$table->dropColumn('chofer_id');
});
}
};

95
resources/views/choferes.blade.php

@ -0,0 +1,95 @@
@extends('layouts.dashboard')
@section('content')
<div class="container mx-auto px-4 py-6">
@if(session('success'))
<div id="success-message" 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
@if(session('error'))
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert">
<span class="block sm:inline">{{ session('error') }}</span>
</div>
@endif
<div class="bg-white rounded-lg shadow-lg">
<div class="p-4 border-b border-gray-200 flex justify-between items-center">
<h2 class="text-2xl font-bold">Gestión de Choferes</h2>
<div class="flex items-center gap-4">
<a href="{{ route('choferes.excel') }}" class="text-green-600 hover:text-green-800 text-2xl" title="Exportar Excel">
<i class="fas fa-file-excel"></i>
</a>
<a href="{{ route('choferes.pdf') }}" class="text-red-600 hover:text-red-800 text-2xl" title="Exportar PDF">
<i class="fas fa-file-pdf"></i>
</a>
<a href="{{ route('choferes.create') }}" class="text-blue-600 hover:text-blue-800 text-2xl" title="Agregar Chofer">
<i class="fas fa-plus"></i>
</a>
</div>
</div>
<div class="p-4 border-b border-gray-200 bg-gray-50">
<form action="{{ route('choferes.index') }}" method="GET" class="flex gap-2">
<div class="relative w-full sm:w-64">
<input type="text" name="busqueda" placeholder="Buscar chofer..." value="{{ request('busqueda') }}" class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<div class="absolute left-3 top-2.5 text-gray-400">
<i class="fas fa-search"></i>
</div>
</div>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600">Buscar/Actualizar</button>
@if(request('busqueda'))
<a href="{{ route('choferes.index') }}" class="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600">Limpiar</a>
@endif
</form>
</div>
<div class="overflow-x-auto">
<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">ID</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nombre</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo de Licencia</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Acciones</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($choferes as $chofer)
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $chofer->id }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<i class="fas fa-id-card text-blue-500 mr-2"></i>
{{ $chofer->nombre }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ $chofer->tipo_licencia }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<div class="flex space-x-2">
<a href="{{ route('choferes.edit', $chofer->id) }}" class="text-blue-600 hover:text-blue-900"><i class="fas fa-edit"></i></a>
<form action="{{ route('choferes.destroy', $chofer->id) }}" method="POST" class="inline">
@csrf
@method('DELETE')
<button type="submit" class="text-red-600 hover:text-red-900" onclick="return confirm('¿Estás seguro de que deseas eliminar este chofer?')">
<i class="fas fa-trash"></i>
</button>
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<script>
// Desaparecer el mensaje después de 3 segundos
setTimeout(function() {
var message = document.getElementById('success-message');
if (message) {
message.style.transition = 'opacity 0.5s ease';
message.style.opacity = '0';
setTimeout(function() {
message.remove();
}, 500);
}
}, 3000);
</script>
@endsection

62
resources/views/choferesCrearEditar.blade.php

@ -0,0 +1,62 @@
{{-- Start of Selection --}}
@extends('layouts.dashboard')
@section('content')
<div class="container mx-auto px-4 py-6">
<div class="max-w-lg mx-auto">
<div class="bg-white rounded-lg shadow-lg overflow-hidden">
<div class="p-6">
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-gray-800">
{{ isset($chofer) ? 'Editar Chofer' : 'Nuevo Chofer' }}
</h2>
<div class="h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas fa-id-card text-blue-600"></i>
</div>
</div>
@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">
<i class="fas fa-exclamation-circle text-red-500 mr-3"></i>
<div class="text-red-700">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
<form action="{{ isset($chofer) ? route('choferes.update', $chofer->id) : route('choferes.store') }}" method="POST">
@csrf
@if(isset($chofer))
@method('PUT')
@endif
<div class="space-y-6">
<div>
<label for="nombre" class="block text-sm font-medium text-gray-700 mb-2">Nombre del Chofer</label>
<div class="relative">
<i class="fas fa-user absolute left-3 top-2.5 text-gray-400"></i>
<input type="text" name="nombre" id="nombre" class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" required placeholder="Ingresa el nombre del chofer" value="{{ old('nombre', $chofer->nombre ?? '') }}">
</div>
</div>
<div>
<label for="tipo_licencia" class="block text-sm font-medium text-gray-700 mb-2">Tipo de Licencia</label>
<div class="relative">
<i class="fas fa-id-badge absolute left-3 top-2.5 text-gray-400"></i>
<input type="text" name="tipo_licencia" id="tipo_licencia" class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" required placeholder="Ingresa el tipo de licencia" value="{{ old('tipo_licencia', $chofer->tipo_licencia ?? '') }}">
</div>
</div>
<div class="flex justify-end space-x-2 pt-4 border-t border-gray-200">
<a href="{{ route('choferes.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">{{ isset($chofer) ? 'Actualizar' : 'Guardar' }}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
{{-- End of Selection --}}

55
resources/views/exports/choferes-pdf.blade.php

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>Choferes</title>
<style>
body {
font-family: Arial, sans-serif;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
.header {
text-align: center;
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="header">
<h1>Reporte de Choferes</h1>
<p>Fecha de generación: {{ date('d/m/Y H:i:s') }}</p>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Nombre</th>
<th>Tipo de Licencia</th>
<th>Fecha de Creación</th>
</tr>
</thead>
<tbody>
@foreach($choferes as $chofer)
<tr>
<td>{{ $chofer->id }}</td>
<td>{{ $chofer->nombre }}</td>
<td>{{ $chofer->tipo_licencia }}</td>
<td>{{ $chofer->created_at->format('d/m/Y') }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

4
resources/views/layouts/dashboard.blade.php

@ -163,9 +163,9 @@
<!-- Tipos de Licencia -->
<li>
<a href="{{ route('tiposLicencias.index') }}" class="nav-item-hover flex items-center space-x-3 px-4 py-3 rounded-lg hover:bg-white/10 backdrop-blur-sm {{ request()->is('tiposLicencias*') ? 'bg-white/20' : '' }}">
<a href="{{ route('choferes.index') }}" class="nav-item-hover flex items-center space-x-3 px-4 py-3 rounded-lg hover:bg-white/10 backdrop-blur-sm {{ request()->is('choferes*') ? 'bg-white/20' : '' }}">
<i class="fas fa-id-card text-white/80"></i>
<span class="font-light">Tipos de Licencia</span>
<span class="font-light">Choferes</span>
</a>
</li>

7
resources/views/prestamos.blade.php

@ -86,6 +86,7 @@
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Número</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Vehiculo</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nombre Solicitante</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">Fecha y Hora Salida</th>
@ -110,6 +111,12 @@
{{ $prestamo->nombre_solicitante }}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<div class="flex items-center">
<i class="fas fa-truck text-green-500 mr-2"></i>
{{ $prestamo->vehiculo->nombre }}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<div class="flex items-center">
<i class="fas fa-map-marker-alt text-red-500 mr-2"></i>

52
resources/views/prestamosCrearEditar.blade.php

@ -61,6 +61,30 @@
@enderror
</div>
<!-- Campo Vehículo -->
<div>
<label for="vehiculo_id" class="block text-sm font-medium text-gray-700 mb-2">
Vehículo
</label>
<div class="relative">
<i class="fas fa-car absolute left-3 top-2.5 text-gray-400"></i>
<select name="vehiculo_id"
id="vehiculo_id"
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
required>
<option value="">Seleccione un vehículo</option>
@foreach($vehiculos as $vehiculo)
<option value="{{ $vehiculo->id }}" {{ old('vehiculo_id') == $vehiculo->id ? 'selected' : '' }}>
{{ $vehiculo->nombre }} - {{ ucfirst(str_replace('_', ' ', $vehiculo->tipo_combustible)) }}
</option>
@endforeach
</select>
</div>
@error('vehiculo_id')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Campo Destino -->
<div>
<label for="destino" class="block text-sm font-medium text-gray-700 mb-2">
@ -179,14 +203,20 @@
<!-- Campo Chofer -->
<div class="flex items-center">
<input type="checkbox"
name="chofer"
id="chofer"
class="rounded border-gray-300 text-blue-600 shadow-sm focus:ring-blue-500"
{{ isset($prestamo) && $prestamo->chofer ? 'checked' : '' }}>
<input type="checkbox" name="chofer" id="chofer" {{ old('chofer') ? 'checked' : '' }} onchange="toggleChoferCatalogo()">
<label for="chofer" class="ml-2 text-sm text-gray-700">¿Requiere chofer?</label>
</div>
<div id="catalogo-choferes" style="display:none; margin-top: 1em;">
<label for="chofer_id" class="block text-sm font-medium text-gray-700 mb-2">Chofer</label>
<select name="chofer_id" id="chofer_id" class="block w-full border border-gray-300 rounded-md">
<option value="">Seleccione un chofer</option>
@foreach($choferes as $chofer)
<option value="{{ $chofer->id }}">{{ $chofer->nombre }} - {{ $chofer->tipo_licencia }}</option>
@endforeach
</select>
</div>
<!-- Botones de acción -->
<div class="flex justify-end space-x-2 pt-4 border-t border-gray-200">
<a href="{{ route('prestamos.index') }}"
@ -204,4 +234,14 @@
</div>
</div>
</div>
@endsection
<script>
function toggleChoferCatalogo() {
var check = document.getElementById('chofer').checked;
document.getElementById('catalogo-choferes').style.display = check ? 'block' : 'none';
}
document.addEventListener('DOMContentLoaded', function() {
toggleChoferCatalogo();
});
</script>
@endsection

152
resources/views/tiposLicencia.blade.php

@ -1,152 +0,0 @@
@extends('layouts.dashboard')
@section('content')
<div class="container mx-auto px-4 py-6">
<!-- Mensajes de éxito y error -->
@if(session('success'))
<div id="success-message" 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
@if(session('error'))
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert">
<span class="block sm:inline">{{ session('error') }}</span>
</div>
@endif
<div class="bg-white rounded-lg shadow-lg">
<!-- Encabezado con título y botones de acción -->
<div class="p-4 border-b border-gray-200 flex justify-between items-center">
<h2 class="text-2xl font-bold">Gestión de Tipos de Licencias</h2>
<div class="flex items-center space-x-6">
<!-- Íconos de exportación y agregar -->
<div class="flex space-x-4">
<!-- Exportar a Excel -->
<a href="{{ route('tiposLicencias.excel') }}"
class="text-green-600 hover:text-green-700 transition-colors duration-200"
title="Exportar a Excel">
<i class="fas fa-file-excel text-xl"></i>
</a>
<!-- Exportar a PDF -->
<a href="{{ route('tiposLicencias.pdf') }}"
class="text-red-600 hover:text-red-700 transition-colors duration-200"
title="Exportar a PDF">
<i class="fas fa-file-pdf text-xl"></i>
</a>
<!-- Agregar nuevo tipo de licencia -->
<a href="{{ route('tiposLicencias.create') }}"
class="text-blue-500 hover:text-blue-600 transition-colors duration-200"
title="Agregar nuevo tipo de licencia">
<i class="fas fa-plus text-xl"></i>
</a>
</div>
</div>
</div>
<!-- Barra de búsqueda -->
<div class="p-4 border-b border-gray-200 bg-gray-50">
<form action="{{ route('tiposLicencias.index') }}" method="GET" class="flex gap-2">
<div class="relative w-full sm:w-64">
<input type="text"
name="busqueda"
placeholder="Buscar tipo de licencia..."
value="{{ request('busqueda') }}"
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<div class="absolute left-3 top-2.5 text-gray-400">
<i class="fas fa-search"></i>
</div>
</div>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600">
Buscar/Actualizar
</button>
@if(request('busqueda'))
<a href="{{ route('tiposLicencias.index') }}" class="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600">
Limpiar
</a>
@endif
</form>
</div>
<!-- Tabla de tipos de licencias -->
<div class="overflow-x-auto">
<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">ID</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo de Licencia</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Estado</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Acciones</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($tiposLicencias as $tipoLicencia)
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $tipoLicencia->id }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<i class="fas fa-id-card text-blue-500 mr-2"></i>
{{ $tipoLicencia->tipoLicencia }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
@if($tipoLicencia->eliminado == 1)
<span class="flex items-center">
<span class="h-2 w-2 bg-green-500 rounded-full mr-2"></span> Activo
</span>
@else
<span class="flex items-center">
<span class="h-2 w-2 bg-red-500 rounded-full mr-2"></span> Inactivo
</span>
@endif
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<div class="flex gap-2">
@if($tipoLicencia->eliminado == 0)
<a href="{{ route('tiposLicencias.toggle-status', ['id' => $tipoLicencia->id]) }}"
class="text-green-600 hover:text-green-700 transition-colors duration-200"
title="Recuperar tipo de licencia">
<i class="fas fa-undo"></i>
</a>
@else
<a href="{{ route('tiposLicencias.edit', $tipoLicencia->id) }}"
class="text-yellow-600 hover:text-yellow-700 transition-colors duration-200"
title="Editar tipo de licencia">
<i class="fas fa-edit"></i>
</a>
<form action="{{ route('tiposLicencias.destroy', $tipoLicencia->id) }}"
method="POST"
class="inline">
@csrf
@method('DELETE')
<button type="submit"
class="text-red-600 hover:text-red-700 transition-colors duration-200"
title="Eliminar tipo de licencia">
<i class="fas fa-trash"></i>
</button>
</form>
@endif
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<script>
// Desaparecer el mensaje después de 3 segundos
setTimeout(function() {
var message = document.getElementById('success-message');
if (message) {
message.style.transition = 'opacity 0.5s ease';
message.style.opacity = '0';
setTimeout(function() {
message.remove();
}, 500);
}
}, 3000);
</script>
@endsection

85
resources/views/tiposLicenciaCrearEditar.blade.php

@ -1,85 +0,0 @@
{{-- Start of Selection --}}
@extends('layouts.dashboard')
@section('content')
<div class="container mx-auto px-4 py-6">
<div class="max-w-lg mx-auto">
<div class="bg-white rounded-lg shadow-lg overflow-hidden">
<div class="p-6">
<!-- Encabezado del formulario -->
<div class="flex items-center justify-between mb-6">
<h2 class="text-2xl font-bold text-gray-800">
{{ isset($tipoLicencia) ? 'Editar Tipo de Licencia' : 'Nuevo Tipo de Licencia' }}
</h2>
<div class="h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas fa-car text-blue-600"></i>
</div>
</div>
<!-- Mensajes de error -->
@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">
<i class="fas fa-exclamation-circle text-red-500 mr-3"></i>
<div class="text-red-700">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
<!-- Formulario -->
<form id="tipoLicenciaForm"
action="{{ isset($tipoLicencia) ? route('tiposLicencias.update', $tipoLicencia->id) : route('tiposLicencias.store') }}"
method="POST">
@csrf
@if(isset($tipoLicencia))
@method('PUT')
@endif
<div class="space-y-6">
<!-- Campo Tipo de Licencia -->
<div>
<label for="tipoLicencia" class="block text-sm font-medium text-gray-700 mb-2">
Tipo de Licencia
</label>
<div class="relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-tag text-gray-400"></i>
</div>
<input type="text"
name="tipoLicencia"
id="tipoLicencia"
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
value="{{ isset($tipoLicencia) ? $tipoLicencia->tipoLicencia : old('tipoLicencia') }}"
placeholder="Ingrese el tipo de licencia"
required>
</div>
@error('tipoLicencia')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Botones de acción -->
<div class="flex justify-end space-x-2 pt-4 border-t border-gray-200">
<a href="{{ route('tiposLicencias.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">
{{ isset($tipoLicencia) ? 'Actualizar' : 'Guardar' }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
{{-- End of Selection --}}

72
routes/web.php

@ -11,6 +11,7 @@ use App\Http\Controllers\CapacidadController;
use App\Http\Controllers\PrestamoController;
use App\Http\Controllers\DespartamentoController;
use App\Http\Controllers\SolicitudVehiculoController;
use App\Http\Controllers\ChoferController;
/*
@ -56,7 +57,7 @@ use App\Http\Controllers\SolicitudVehiculoController;
Route::get('/despartamento/export/excel', [DespartamentoController::class, 'exportExcel'])->name('despartamentos.excel');
Route::get('/despartamento/export/pdf', [DespartamentoController::class, 'exportPDF'])->name('despartamentos.pdf');
// Rutas de préstamos protegidas para administradores
// Rutas de préstamos protegidas solo para administradores (historial, aceptar, rechazar, etc.)
Route::middleware(['auth', 'admin'])->group(function () {
Route::get('/prestamos/aceptados', [PrestamoController::class, 'aceptados'])->name('prestamos.aceptados');
Route::post('/prestamos/{id}/aceptar', [PrestamoController::class, 'aceptar'])->name('prestamos.aceptar');
@ -69,49 +70,48 @@ use App\Http\Controllers\SolicitudVehiculoController;
Route::get('/prestamos/export/{format}', [PrestamoController::class, 'export'])->name('prestamos.export');
});
// Ruta general de préstamos (accesible para todos los usuarios autenticados)
Route::resource('prestamos', PrestamoController::class);
// Rutas de gestión de préstamos (crear, editar, eliminar) para admin y servicios
Route::middleware(['auth', 'can:gestionar-prestamos'])->resource('prestamos', PrestamoController::class);
// Ruta general de préstamos (solo para ver)
Route::middleware(['auth'])->group(function () {
Route::get('/prestamos', [PrestamoController::class, 'index'])->name('prestamos.index');
Route::get('/prestamos/{id}', [PrestamoController::class, 'show'])->name('prestamos.show');
});
Route::get('/docentes/export/{format}', [DocentesController::class, 'export'])->name('docentes.export');
Route::get('/docentes/{id}/toggle-status', [DocentesController::class, 'toggleStatus'])->name('docentes.toggle-status');
// Rutas protegidas que requieren autenticación
// Rutas protegidas que requieren autenticación
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [HomeController::class, 'index'])->name('dashboard');
Route::get('/usuarios', [usuariosController::class,'index'])->name('usuarios');
Route::get('/usuarios/nuevo', [usuariosController::class, 'create'])->name('usuarios.create');
Route::post('/usuarios/store', [usuariosController::class,'store'])->name('usuarios.store');
Route::get('/usuarios/edit/{id}', [usuariosController::class, 'edit'])->name('usuarios.edit');
Route::put('/usuarios/{id}', [usuariosController::class, 'update'])->name('usuarios.update');
Route::delete('/usuarios/destroy/{id}', [usuariosController::class, 'destroy'])->name('usuarios.destroy');
Route::get('usuarios/excel', [usuariosController::class, 'exportExcel'])->name('usuarios.excel');
Route::get('usuarios/pdf', [usuariosController::class, 'exportPDF'])->name('usuarios.pdf');
Route::get('/home', [HomeController::class, 'index'])->name('home');
});
Route::get('/dashboard', [HomeController::class, 'index'])->name('dashboard');
Route::get('/usuarios', [usuariosController::class,'index'])->name('usuarios');
Route::get('/usuarios/nuevo', [usuariosController::class, 'create'])->name('usuarios.create');
Route::post('/usuarios/store', [usuariosController::class,'store'])->name('usuarios.store');
Route::get('/usuarios/edit/{id}', [usuariosController::class, 'edit'])->name('usuarios.edit');
Route::put('/usuarios/{id}', [usuariosController::class, 'update'])->name('usuarios.update');
Route::delete('/usuarios/destroy/{id}', [usuariosController::class, 'destroy'])->name('usuarios.destroy');
Route::get('usuarios/excel', [usuariosController::class, 'exportExcel'])->name('usuarios.excel');
Route::get('usuarios/pdf', [usuariosController::class, 'exportPDF'])->name('usuarios.pdf');
Route::get('/home', [HomeController::class, 'index'])->name('home');
////corerecion rubi
});
// Rutas para profesores
Route::middleware(['auth', 'profesor'])->prefix('profesor')->name('profesor.')->group(function () {
Route::get('/solicitudes', [SolicitudVehiculoController::class, 'index'])->name('solicitudes.index');
Route::get('/solicitudes/create', [SolicitudVehiculoController::class, 'create'])->name('solicitudes.create');
Route::post('/solicitudes', [SolicitudVehiculoController::class, 'store'])->name('solicitudes.store');
});
// Rutas para profesores
Route::middleware(['auth', 'profesor'])->prefix('profesor')->name('profesor.')->group(function () {
Route::get('/solicitudes', [SolicitudVehiculoController::class, 'index'])->name('solicitudes.index');
Route::get('/solicitudes/create', [SolicitudVehiculoController::class, 'create'])->name('solicitudes.create');
Route::post('/solicitudes', [SolicitudVehiculoController::class, 'store'])->name('solicitudes.store');
});
// Ruta para el dashboard de usuarios
Route::get('/user-dashboard', [App\Http\Controllers\UserDashboardController::class, 'index'])->name('user.dashboard');
// Ruta para el dashboard de usuarios
Route::get('/user-dashboard', [App\Http\Controllers\UserDashboardController::class, 'index'])->name('user.dashboard');
// Ruta para el cuestionario del dashboard de usuario
Route::get('/user-dashboard/cuestionario', function () {
return view('user-dashboard.cuestionario');
})->middleware('auth');
// Ruta para el cuestionario del dashboard de usuario
Route::get('/user-dashboard/cuestionario', function () {
return view('user-dashboard.cuestionario');
})->middleware('auth');
Route::resource('choferes', ChoferController::class);
// Rutas protegidas para el rol servicios
Route::middleware(['auth', 'servicios'])->resource('prestamos', PrestamoController::class);
Route::get('choferes/excel', [App\Http\Controllers\ChoferController::class, 'exportExcel'])->name('choferes.excel');
Route::get('choferes/pdf', [App\Http\Controllers\ChoferController::class, 'exportPDF'])->name('choferes.pdf');

Loading…
Cancel
Save