Compare commits

...

No commits in common. 'bf207f1050e475b62e19b818a25f8888b6eae9c4' and '0cd425c2ce01573f17967d2a28886713a0712554' have entirely different histories.

  1. 0
      -i
  2. 58
      .env.example
  3. 25
      anotaciones
  4. 33
      app/Exports/DocentesExport.php
  5. 36
      app/Exports/MarcasExport.php
  6. 33
      app/Exports/PrestamosExport.php
  7. 32
      app/Exports/UsuariosExport.php
  8. 35
      app/Exports/tiposLicenciasExport.php
  9. 9
      app/Http/Controllers/Auth/LoginController.php
  10. 26
      app/Http/Controllers/Auth/RegisterController.php
  11. 99
      app/Http/Controllers/CapacidadController.php
  12. 125
      app/Http/Controllers/DocentesController.php
  13. 4
      app/Http/Controllers/HomeController.php
  14. 82
      app/Http/Controllers/MaintenanceController.php
  15. 108
      app/Http/Controllers/MarcaController.php
  16. 193
      app/Http/Controllers/PrestamoController.php
  17. 25
      app/Http/Controllers/TipoDeGasolinaController.php
  18. 149
      app/Http/Controllers/TiposLicenciasController.php
  19. 167
      app/Http/Controllers/TiposVeiculosController.php
  20. 162
      app/Http/Controllers/usuariosController.php
  21. 1
      app/Http/Kernel.php
  22. 19
      app/Http/Middleware/AdminMiddleware.php
  23. 14
      app/Models/Capacidad.php
  24. 20
      app/Models/Docentes.php
  25. 32
      app/Models/Maintenance.php
  26. 20
      app/Models/Marca.php
  27. 11
      app/Models/Tipo_de_Gasolina.php
  28. 10
      app/Models/User.php
  29. 11
      app/Models/marc.php
  30. 24
      app/Models/prestamo.php
  31. 11
      app/Models/puesto.php
  32. 15
      app/Models/tiposLicencias.php
  33. 16
      app/Models/tiposVeiculos.php
  34. 3
      app/Providers/RouteServiceProvider.php
  35. 4
      composer.json
  36. 1514
      composer.lock
  37. 3
      config/app.php
  38. 301
      config/dompdf.php
  39. 4
      config/session.php
  40. 23
      database/factories/CapacidadFactory.php
  41. 27
      database/factories/DocentesFactory.php
  42. 23
      database/factories/MarcaFactory.php
  43. 23
      database/factories/PrestamoFactory.php
  44. 23
      database/factories/TipoDeGasolinaFactory.php
  45. 23
      database/factories/TiposLicenciasFactory.php
  46. 25
      database/factories/TiposVeiculosFactory.php
  47. 32
      database/migrations/2013_03_27_235747_create_puestos_table.php
  48. 11
      database/migrations/2014_10_12_000000_create_users_table.php
  49. 62
      database/migrations/2025_01_18_230913_create_marcs_table.php
  50. 29
      database/migrations/2025_02_28_192615_create_marcas_table.php
  51. 32
      database/migrations/2025_03_05_172529_create_docentes_table.php
  52. 29
      database/migrations/2025_03_06_162928_create_tipos_veiculos_table.php
  53. 27
      database/migrations/2025_03_07_000000_add_plate_to_tipos_veiculos.php
  54. 27
      database/migrations/2025_03_07_194830_create_tipo_de__gasolinas_table.php
  55. 28
      database/migrations/2025_03_08_000000_create_maintenances_table.php
  56. 28
      database/migrations/2025_03_13_133629_create_capacidads_table.php
  57. 28
      database/migrations/2025_03_13_143153_create_tipos_licencias_table.php
  58. 29
      database/migrations/2025_03_19_030418_add_columneliminado_tomarcas.php
  59. 28
      database/migrations/2025_03_27_054337_add_status_to_docentes_table.php
  60. 28
      database/migrations/2025_03_27_135638_add_columneliminar_to_users.php
  61. 28
      database/migrations/2025_03_27_143601_add_status_to_tipos_licencias_table.php
  62. 28
      database/migrations/2025_03_27_144121_rename_status_to_eliminado_in_tipos_licencias.php
  63. 28
      database/migrations/2025_03_27_164635_add_status_to_tipos_veiculos_table.php
  64. 35
      database/migrations/2025_03_27_174121_create_prestamos_table.php
  65. 28
      database/migrations/2025_03_27_183714_add_columneliminado_toprestamos.php
  66. 28
      database/migrations/2025_03_27_183845_add_columneliminado_to_capacidads_table.php
  67. 28
      database/migrations/2025_03_28_175646_add_estado_to_prestamos_table.php
  68. 28
      database/migrations/2025_03_28_182126_add_estado_to_prestamos_table.php
  69. 28
      database/migrations/2025_03_28_183038_add_estado_to_prestamos_table.php
  70. 22
      database/migrations/2025_05_07_000000_add_rol_to_users_table.php
  71. 20
      database/seeders/CapacidadSeeder.php
  72. 17
      database/seeders/DocentesSeeder.php
  73. 17
      database/seeders/MarcaSeeder.php
  74. 17
      database/seeders/TipoDeGasolinaSeeder.php
  75. 17
      database/seeders/TiposLicenciasSeeder.php
  76. 17
      database/seeders/TiposVeiculosSeeder.php
  77. 347
      package-lock.json
  78. 7
      package.json
  79. BIN
      public/css/logo.png
  80. 0
      resources/css/app.css
  81. 143
      resources/js/components/dashboard/JorgeDashboard.jsx
  82. 151
      resources/js/components/dashboard/NewMaintenanceForm.jsx
  83. 10
      resources/js/maintenance-dashboard.js
  84. 131
      resources/views/auth/login.blade.php
  85. 154
      resources/views/auth/register.blade.php
  86. 100
      resources/views/capacidades.blade.php
  87. 132
      resources/views/capacidadesCrearEditar.blade.php
  88. 99
      resources/views/dashboard.blade.php
  89. 215
      resources/views/docentes.blade.php
  90. 71
      resources/views/docentesCrearEditar.blade.php
  91. 47
      resources/views/exports/docentes.blade.php
  92. 70
      resources/views/exports/marcas-pdf.blade.php
  93. 76
      resources/views/exports/prestamos-pdf.blade.php
  94. 63
      resources/views/exports/tiposLicencias-pdf.blade.php
  95. 75
      resources/views/exports/tipos_vehiculos_pdf.blade.php
  96. 48
      resources/views/exports/usuarios-pdf.blade.php
  97. 273
      resources/views/inicial.blade.php
  98. 24
      resources/views/layouts/app.blade.php
  99. 277
      resources/views/layouts/dashboard.blade.php
  100. 17
      resources/views/layouts/footer.blade.php

0
hola.txt → -i

58
.env.example

@ -1,58 +0,0 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

25
anotaciones

@ -0,0 +1,25 @@
yo
Docentes
Nombre
materia que imparte
no.tel
correo
tipo de licencia [es vigente la licencia o no] (opcional)
Chofer
Nombre
no.tel
correo
tipo de licencia [es vigente la licencia o no] (opcional)
Administradores
Nombre
no.tel
correo
yo rubi
yo

33
app/Exports/DocentesExport.php

@ -0,0 +1,33 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class DocentesExport implements FromCollection, WithHeadings
{
protected $docentes;
public function __construct($docentes)
{
$this->docentes = $docentes;
}
public function collection()
{
return $this->docentes;
}
public function headings(): array
{
return [
'ID',
'Nombre',
'Teléfono',
'Correo',
'Tipo de Licencia',
'Materia'
];
}
}

36
app/Exports/MarcasExport.php

@ -0,0 +1,36 @@
<?php
namespace App\Exports;
use App\Models\Marca;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class MarcasExport implements FromCollection, WithHeadings
{
/**
* Método que devuelve la colección de datos a exportar.
*
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return Marca::where('eliminado', 0)->get();
}
/**
* Método que define los encabezados de las columnas en el archivo Excel.
*
* @return array
*/
public function headings(): array
{
return [
'ID',
'Marca',
'Estado',
'Fecha de Creación',
'Última Actualización'
];
}
}

33
app/Exports/PrestamosExport.php

@ -0,0 +1,33 @@
<?php
namespace App\Exports;
use App\Models\Prestamo;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class PrestamosExport implements FromCollection, WithHeadings
{
public function collection()
{
return Prestamo::where('eliminado', 0)->get();
}
public function headings(): array
{
return [
'ID',
'Nombre Solicitante',
'Destino',
'Fecha y Hora Salida',
'Fecha y Hora Llegada',
'Motivo',
'Domicilio',
'Número de Personas',
'Chofer',
'Estado',
'Fecha de Creación',
'Última Actualización'
];
}
}

32
app/Exports/UsuariosExport.php

@ -0,0 +1,32 @@
<?php
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class UsuariosExport implements FromCollection, WithHeadings
{
public function collection()
{
return User::select( 'name', 'email','apellido',
'puesto',
'carrera',
'telefono',)->get();
}
public function headings(): array
{
return [
'nombre',
'correo',
'apellido',
'puesto',
'carrera',
'telefono',
'Fecha de Creación',
'Última Actualización'
];
}
}

35
app/Exports/tiposLicenciasExport.php

@ -0,0 +1,35 @@
<?php
namespace App\Exports;
use App\Models\tiposLicencias;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class TiposLicenciasExport implements FromCollection, WithHeadings
{
/**
* Método que devuelve la colección de datos a exportar.
*
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return tiposLicencias::where('eliminado', 0) // Solo marcas activas
->select('id', 'tipoLicencia') // Selecciona los campos que deseas exportar
->get();
}
/**
* Método que define los encabezados de las columnas en el archivo Excel.
*
* @return array
*/
public function headings(): array
{
return [
'ID', // Encabezado para la columna ID
'Tipo de licencia', // Encabezado para la columna Tipo de licencia
];
}
}

9
app/Http/Controllers/Auth/LoginController.php

@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller class LoginController extends Controller
{ {
@ -37,4 +38,12 @@ class LoginController extends Controller
$this->middleware('guest')->except('logout'); $this->middleware('guest')->except('logout');
$this->middleware('auth')->only('logout'); $this->middleware('auth')->only('logout');
} }
protected function authenticated(Request $request, $user)
{
if ($user->rol === 'mantenimiento') {
return redirect('/maintenance');
}
return redirect('/dashboard');
}
} }

26
app/Http/Controllers/Auth/RegisterController.php

@ -4,7 +4,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
@ -21,8 +21,6 @@ class RegisterController extends Controller
| |
*/ */
use RegistersUsers;
/** /**
* Where to redirect users after registration. * Where to redirect users after registration.
* *
@ -40,6 +38,28 @@ class RegisterController extends Controller
$this->middleware('guest'); $this->middleware('guest');
} }
// Método para mostrar el formulario de registro
public function showRegistrationForm()
{
return view('auth.register');
}
// Método para manejar el registro
public function register(Request $request)
{
// Validar los datos del usuario
$this->validator($request->all())->validate();
// Crear el usuario
$user = $this->create($request->all());
// Autenticar al usuario
auth()->login($user);
// Redirigir a la página principal
return redirect()->route('home')->with('success', 'Registro exitoso. Bienvenido!');
}
/** /**
* Get a validator for an incoming registration request. * Get a validator for an incoming registration request.
* *

99
app/Http/Controllers/CapacidadController.php

@ -0,0 +1,99 @@
<?php
namespace App\Http\Controllers;
use App\Models\Capacidad;
use Illuminate\Http\Request;
class CapacidadController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if($busqueda) {
$capacidades = Capacidad::where('cantidad', 'LIKE', "%{$busqueda}%")->where('eliminado', 1)->get();
if($capacidades->count() == 0) {
return redirect()->route('capacidades.index')
->with('error', 'No existe ninguna capacidad con la cantidad "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
if($capacidades->count() == 1) {
$capacidad = $capacidades->first();
return redirect()->route('capacidades.edit', $capacidad->id);
}
return view('capacidades', ["capacidades" => $capacidades]);
}
$capacidades = Capacidad::where('eliminado', 1)->get();
return view('capacidades', ["capacidades" => $capacidades]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('capacidadesCrearEditar');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$capacidad = new Capacidad($request->all());
$capacidad->eliminado = 1;
$capacidad->save();
return redirect()->route('capacidades.index')->with('success', 'Capacidad creada exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(Capacidad $capacidad)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$capacidad = Capacidad::find($id);
return view('capacidadesCrearEditar', ['capacidad' => $capacidad]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$capacidad = Capacidad::find($id);
$capacidad->fill($request->all());
$capacidad->eliminado = 1;
$capacidad->save();
return redirect()->route('capacidades.index')->with('success', 'Capacidad actualizada exitosamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$capacidad = Capacidad::find($id);
$capacidad->eliminado = 0;
if($capacidad->save()) {
return redirect()->route('capacidades.index')->with('success', 'Capacidad eliminada exitosamente.');
}
return redirect()->route('capacidades.index')->with('error', 'No se pudo eliminar la capacidad.');
}
}

125
app/Http/Controllers/DocentesController.php

@ -0,0 +1,125 @@
<?php
namespace App\Http\Controllers;
use App\Models\Docentes;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Barryvdh\DomPDF\Facade\Pdf;
use App\Exports\DocentesExport;
class DocentesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if ($busqueda) {
// Busca docentes que coincidan con el término de búsqueda
$docentes = Docentes::where(function($query) use ($busqueda) {
$query->where('nombre', 'LIKE', "%{$busqueda}%")
->orWhere('correo', 'LIKE', "%{$busqueda}%")
->orWhere('tipo_licencia', 'LIKE', "%{$busqueda}%")
->orWhere('materia', 'LIKE', "%{$busqueda}%");
})->get();
if ($docentes->isEmpty()) {
return redirect()->route('docentes.index')
->with('error', 'No existe ningún docente con el término "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
} else {
// Si no hay búsqueda, mostrar todos los docentes
$docentes = Docentes::all();
}
return view('docentes', ['docentes' => $docentes]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$docentes = Docentes::all();
return view('docentesCrearEditar',['docentes'=>$docentes]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$docente = new Docentes($request->all());
$docente->save();
return redirect()->route('docentes.index')->with('success', 'Docente creado exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(Docentes $docente)
{
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$docentes = Docentes::all();
$docente = Docentes::find($id);
return view('docentesCrearEditar', ['docentes' => $docentes, 'docente' => $docente]) ;
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$docente = Docentes::find($id);
$docente->fill($request->all());
$docente->save();
return redirect()->route('docentes.index')->with('success', 'Docente actualizado correctamente');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$docente = Docentes::find($id);
$docente->status = false;
$docente->save();
return redirect()->route('docentes.index')->with('success', 'Docente desactivado correctamente');
}
public function toggleStatus($id)
{
$docente = Docentes::find($id);
$docente->status = !$docente->status;
$docente->save();
$mensaje = $docente->status ? 'Docente activado correctamente' : 'Docente desactivado correctamente';
return redirect()->route('docentes.index')->with('success', $mensaje);
}
public function export($format)
{
$docentes = Docentes::all();
switch($format) {
case 'csv':
return Excel::download(new DocentesExport($docentes), 'docentes.csv', \Maatwebsite\Excel\Excel::CSV);
case 'excel':
return Excel::download(new DocentesExport($docentes), 'docentes.xlsx');
case 'pdf':
return PDF::loadView('exports.docentes', ['docentes' => $docentes])
->download('docentes.pdf');
default:
return redirect()->back()->with('error', 'Formato no soportado');
}
}
}

4
app/Http/Controllers/HomeController.php

@ -23,6 +23,8 @@ class HomeController extends Controller
*/ */
public function index() public function index()
{ {
return view('home');
return view('dashboard');
} }
} }

82
app/Http/Controllers/MaintenanceController.php

@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers;
use App\Models\Maintenance;
use App\Models\Vehicle;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MaintenanceController extends Controller
{
public function index()
{
return view('maintenance.dashboard');
}
public function getMaintenanceHistory()
{
$maintenances = Maintenance::with('vehicle')
->orderBy('date', 'desc')
->get();
return response()->json($maintenances);
}
public function getPendingAlerts()
{
$alerts = Maintenance::with('vehicle')
->where('status', 'Pendiente')
->where('next_maintenance_date', '<=', now()->addDays(30))
->orderBy('next_maintenance_date', 'asc')
->get();
return response()->json($alerts);
}
public function store(Request $request)
{
$validated = $request->validate([
'vehicle_id' => 'required|exists:vehicles,id',
'maintenance_type' => 'required|string',
'date' => 'required|date',
'description' => 'required|string',
'cost' => 'required|numeric|min:0',
'status' => 'required|in:Pendiente,En Proceso,Completado',
'next_maintenance_date' => 'nullable|date'
]);
$maintenance = Maintenance::create($validated);
return response()->json([
'message' => 'Mantenimiento registrado exitosamente',
'maintenance' => $maintenance
], 201);
}
public function update(Request $request, Maintenance $maintenance)
{
$validated = $request->validate([
'vehicle_id' => 'required|exists:vehicles,id',
'maintenance_type' => 'required|string',
'date' => 'required|date',
'description' => 'required|string',
'cost' => 'required|numeric|min:0',
'status' => 'required|in:Pendiente,En Proceso,Completado',
'next_maintenance_date' => 'nullable|date'
]);
$maintenance->update($validated);
return response()->json([
'message' => 'Mantenimiento actualizado exitosamente',
'maintenance' => $maintenance
]);
}
public function getVehicles()
{
$vehicles = Vehicle::where('status', 'Activo')->get();
return response()->json($vehicles);
}
}

108
app/Http/Controllers/MarcaController.php

@ -0,0 +1,108 @@
<?php
namespace App\Http\Controllers;
use App\Models\Marca;
use Illuminate\Http\Request;
use App\Exports\MarcasExport;
use Maatwebsite\Excel\Facades\Excel;
use PDF;
class MarcaController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if ($busqueda) {
// Busca en la columna 'marca' de la tabla 'marcas'
$marcas = Marca::where('marca', 'LIKE', "%{$busqueda}%")->where('eliminado', 0)->get();
if ($marcas->isEmpty()) {
return redirect()->route('marca.index')
->with('error', 'No existe ninguna marca con el nombre "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
} else {
// Si no hay búsqueda, mostrar todas las marcas
$marcas = Marca::where('eliminado', 0)->get();
}
return view('marcas', ['marcas' => $marcas]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('marcasCrearEditar', ['marca' => null]); // No se necesita pasar marcas
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Validación de datos
$request->validate([
'marca' => 'required|string|max:255|unique:marcas,marca', // Asegúrate de que 'marca' sea único
]);
// Crea una nueva marca
$marca = new Marca();
$marca->marca = $request->marca; // Asigna el nombre ingresado por el usuario
$marca->eliminado = 0; // Marca como activa por defecto
$marca->save();
return redirect()->route('marca.index')->with('success', 'Marca creada exitosamente.');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$marca = Marca::findOrFail($id); // Busca la marca por ID
return view('marcasCrearEditar', ['marca' => $marca]); // Pasa la marca a la vista
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$marca = Marca::findOrFail($id); // Encuentra la marca por ID
$marca->marca = $request->marca; // Actualiza el nombre de la marca
$marca->eliminado = 0; // Cambia el estado a activo si se está editando
$marca->save(); // Guarda los cambios
return redirect()->route('marca.index')->with('success', 'Marca actualizada correctamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$marca = Marca::findOrFail($id); // Encuentra la marca por ID
$marca->eliminado = 1; // Cambia el estado a inactivo
$marca->save(); // Guarda los cambios
return redirect()->route('marca.index')->with('success', 'Marca inactivada correctamente.');
}
public function exportExcel()
{
return Excel::download(new MarcasExport, 'marcas.xlsx');
}
public function exportPDF()
{
$marcas = Marca::where('eliminado', 0)->get();
$pdf = PDF::loadView('exports.marcas-pdf', ['marcas' => $marcas]);
return $pdf->download('marcas.pdf');
}
}

193
app/Http/Controllers/PrestamoController.php

@ -0,0 +1,193 @@
<?php
namespace App\Http\Controllers;
use App\Models\Prestamo; // Asegúrate de que el modelo esté correctamente nombrado
use Illuminate\Http\Request;
use App\Exports\PrestamosExport; // Asegúrate de tener esta clase de exportación
use Maatwebsite\Excel\Facades\Excel;
use PDF;
class PrestamoController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if ($busqueda) {
// Busca en la columna 'nombre_solicitante' de la tabla 'prestamos'
$prestamos = Prestamo::where('nombre_solicitante', 'LIKE', "%{$busqueda}%")
->where('eliminado', 0)
->where('estado', 'pendiente')
->get();
if ($prestamos->isEmpty()) {
return redirect()->route('prestamos.index')
->with('error', 'No existe ningún préstamo con el solicitante "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
} else {
// Si no hay búsqueda, mostrar todos los préstamos pendientes
$prestamos = Prestamo::where('eliminado', 0)
->where('estado', 'pendiente')
->get();
}
return view('prestamos', ['prestamos' => $prestamos]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('prestamosCrearEditar', ['prestamo' => null]); // No se necesita pasar préstamos
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Validación de datos
$request->validate([
'nombre_solicitante' => 'required|string|max:255',
'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',
]);
// Crea un nuevo préstamo
$prestamo = new Prestamo();
$prestamo->nombre_solicitante = $request->nombre_solicitante;
$prestamo->destino = $request->destino;
$prestamo->fecha_hora_salida = $request->fecha_hora_salida;
$prestamo->fecha_hora_llegada = $request->fecha_hora_llegada;
$prestamo->motivo = $request->motivo;
$prestamo->domicilio = $request->domicilio;
$prestamo->numero_personas = $request->numero_personas;
$prestamo->chofer = $request->has('chofer') ? 1 : 0; // Manejo del checkbox
$prestamo->eliminado = 0; // Marca como activo por defecto
$prestamo->save();
return redirect()->route('prestamos.index')->with('success', 'Préstamo creado exitosamente.');
}
/**
* Show the form for editing the specified resource.
*/
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
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
// Validación de datos
$request->validate([
'nombre_solicitante' => 'required|string|max:255',
'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',
]);
$prestamo = Prestamo::findOrFail($id); // Encuentra el préstamo por ID
$prestamo->nombre_solicitante = $request->nombre_solicitante; // Actualiza el nombre del solicitante
$prestamo->destino = $request->destino; // Actualiza el destino
$prestamo->fecha_hora_salida = $request->fecha_hora_salida; // Actualiza la fecha y hora de salida
$prestamo->fecha_hora_llegada = $request->fecha_hora_llegada; // Actualiza la fecha y hora de llegada
$prestamo->motivo = $request->motivo; // Actualiza el motivo
$prestamo->domicilio = $request->domicilio; // Actualiza el domicilio
$prestamo->numero_personas = $request->numero_personas; // Actualiza el número de personas
$prestamo->chofer = $request->has('chofer') ? 1 : 0; // Manejo del checkbox
$prestamo->eliminado = 0; // Cambia el estado a activo si se está editando
$prestamo->save(); // Guarda los cambios
return redirect()->route('prestamos.index')->with('success', 'Préstamo actualizado correctamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$prestamo = Prestamo::findOrFail($id); // Encuentra el préstamo por ID
$prestamo->eliminado = 1; // Cambia el estado a inactivo
$prestamo->save(); // Guarda los cambios
return redirect()->route('prestamos.index')->with('success', 'Préstamo inactivado correctamente.');
}
/**
* Export to Excel.
*/
public function exportExcel()
{
return Excel::download(new PrestamosExport, 'prestamos.xlsx');
}
/**
* Export to PDF.
*/
public function exportPDF()
{
$prestamos = Prestamo::where('eliminado', 0)->get();
$pdf = PDF::loadView('exports.prestamos-pdf', ['prestamos' => $prestamos]);
return $pdf->download('prestamos.pdf');
}
public function aceptados(Request $request)
{
$busqueda = $request->busqueda;
if ($busqueda) {
$prestamos = Prestamo::where('nombre_solicitante', 'LIKE', "%{$busqueda}%")
->where('eliminado', 0)
->where('estado', 'aceptado')
->get();
if ($prestamos->isEmpty()) {
return redirect()->route('prestamos.aceptados')
->with('error', 'No existe ningún préstamo aceptado con el solicitante "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
} else {
$prestamos = Prestamo::where('eliminado', 0)
->where('estado', 'aceptado')
->get();
}
return view('prestamos.aceptados', ['prestamos' => $prestamos]);
}
public function aceptar($id)
{
$prestamo = Prestamo::findOrFail($id);
$prestamo->estado = 'aceptado';
$prestamo->save();
return redirect()->route('prestamos.index')
->with('success', 'Préstamo aceptado exitosamente.');
}
public function rechazar($id)
{
$prestamo = Prestamo::findOrFail($id);
$prestamo->estado = 'rechazado';
$prestamo->save();
return redirect()->route('prestamos.index')
->with('success', 'Préstamo rechazado exitosamente.');
}
}

25
app/Http/usuariosController.php → app/Http/Controllers/TipoDeGasolinaController.php

@ -2,20 +2,17 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\User; use App\Models\Tipo_de_Gasolina;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class TipoDeGasolinaController extends Controller
class usuariosController extends Controller
{ {
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
public function index() public function index()
{ {
$user=User::all(); //
return view('usuarios',['user'=>$user]);
} }
/** /**
@ -23,8 +20,7 @@ class usuariosController extends Controller
*/ */
public function create() public function create()
{ {
return view('usuariosCrearEditar'); //
} }
/** /**
@ -32,16 +28,13 @@ class usuariosController extends Controller
*/ */
public function store(Request $request) public function store(Request $request)
{ {
//
$user = new User($request->all());
$user->save();
return redirect()->route('usuarios');
} }
/** /**
* Display the specified resource. * Display the specified resource.
*/ */
public function show(string $id) public function show(Tipo_de_Gasolina $tipo_de_Gasolina)
{ {
// //
} }
@ -49,7 +42,7 @@ class usuariosController extends Controller
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
*/ */
public function edit(string $id) public function edit(Tipo_de_Gasolina $tipo_de_Gasolina)
{ {
// //
} }
@ -57,7 +50,7 @@ class usuariosController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
*/ */
public function update(Request $request, string $id) public function update(Request $request, Tipo_de_Gasolina $tipo_de_Gasolina)
{ {
// //
} }
@ -65,7 +58,7 @@ class usuariosController extends Controller
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
*/ */
public function destroy(string $id) public function destroy(Tipo_de_Gasolina $tipo_de_Gasolina)
{ {
// //
} }

149
app/Http/Controllers/TiposLicenciasController.php

@ -0,0 +1,149 @@
<?php
namespace App\Http\Controllers;
use App\Models\tiposLicencias;
use App\Exports\TiposLicenciasExport;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Barryvdh\DomPDF\Facade\Pdf;
class TiposLicenciasController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if($busqueda) {
$tiposLicencias = TiposLicencias::where('tipoLicencia', 'LIKE', "%{$busqueda}%")->where('eliminado', 1)->get();
if($tiposLicencias->count() == 0) {
return redirect()->route('tiposLicencias.index')
->with('error', 'No existe ningún tipo de licencia con el nombre "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
if($tiposLicencias->count() == 1) {
$tipoLicencia = $tiposLicencias->first();
return redirect()->route('tiposLicencias.edit', $tipoLicencia->id);
}
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]);
}
$tiposLicencias = TiposLicencias::where('eliminado', 1)->get();
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]);
}
/**
* Display the specified resource.
*/
public function show(tiposLicencias $tiposLicencias)
{
return view('tiposLicencia', ['tiposLicencias' => [$tiposLicencias]]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
// No es necesario obtener todos los tipos de licencias aquí
return view('tiposLicenciaCrearEditar', ['tipoLicencia' => null]); // Crea una nueva instancia para el formulario
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Verificar si ya existe un tipo de licencia con el mismo nombre
$existe = tiposLicencias::where('tipoLicencia', $request->tipoLicencia)
->where('eliminado', 1)
->exists();
if ($existe) {
return redirect()->route('tiposLicencias.create')
->with('error', 'Ya existe un tipo de licencia con el nombre "' . $request->tipoLicencia . '". Por favor, ingrese un nombre diferente.')
->withInput();
}
$tipoLicencia = new TiposLicencias();
$tipoLicencia->tipoLicencia = $request->tipoLicencia;
$tipoLicencia->eliminado = 1;
$tipoLicencia->save();
return redirect()->route('tiposLicencias.index')->with('success', 'Tipo de licencia creado exitosamente.');
}
public function edit($id)
{
// Busca el tipo de licencia por ID
$tipoLicencia = TiposLicencias::findOrFail($id);
// Retorna la vista con el tipo de licencia para editar
return view('tiposLicenciaCrearEditar', ['tipoLicencia' => $tipoLicencia]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
// Verificar si ya existe otro tipo de licencia con el mismo nombre
$existe = tiposLicencias::where('tipoLicencia', $request->tipoLicencia)
->where('id', '!=', $id)
->where('eliminado', 1)
->exists();
if ($existe) {
return redirect()->route('tiposLicencias.edit', $id)
->with('error', 'Ya existe un tipo de licencia con el nombre "' . $request->tipoLicencia . '". Por favor, ingrese un nombre diferente.')
->withInput();
}
$tipoLicencia = TiposLicencias::findOrFail($id);
$tipoLicencia->tipoLicencia = $request->tipoLicencia;
if ($request->has('eliminado')) {
$tipoLicencia->eliminado = $request->eliminado;
}
$tipoLicencia->save();
return redirect()->route('tiposLicencias.index')->with('success', 'Tipo de licencia actualizado exitosamente.');
}
public function toggleStatus($id)
{
$tipoLicencia = TiposLicencias::findOrFail($id);
$tipoLicencia->eliminado = !$tipoLicencia->eliminado;
$tipoLicencia->save();
$mensaje = $tipoLicencia->eliminado ? 'Tipo de licencia activado exitosamente.' : 'Tipo de licencia desactivado exitosamente.';
return redirect()->route('tiposLicencias.index')->with('success', $mensaje);
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$tipoLicencia = TiposLicencias::findOrFail($id);
$tipoLicencia->eliminado = 0;
$tipoLicencia->save();
return redirect()->route('tiposLicencias.index')->with('success', 'Tipo de licencia eliminado exitosamente.');
}
public function exportExcel()
{
return Excel::download(new TiposLicenciasExport(), 'tiposLicencias.xlsx');
}
public function exportPDF()
{
$tiposLicencias = TiposLicencias::where('eliminado', 1)->get();
$pdf = PDF::loadView('exports.tiposlicencias-pdf', ['tiposLicencias' => $tiposLicencias]);
return $pdf->download('tipos_licencias.pdf');
}
}

167
app/Http/Controllers/TiposVeiculosController.php

@ -0,0 +1,167 @@
<?php
namespace App\Http\Controllers;
use App\Models\tiposVeiculos;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;
class TiposVeiculosController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if($busqueda) {
$tiposVeiculos = tiposVeiculos::where('nombre', 'LIKE', "%{$busqueda}%")->where('status', true)->get();
if($tiposVeiculos->count() == 0) {
return redirect()->route('tiposVeiculos.index')
->with('error', value: 'No existe ningun tipo de vehiculo con el nombre "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
// Si solo hay una marca, mostrar sus detalles
if($tiposVeiculos->count() == 1) {
$tiposVeiculos = $tiposVeiculos->first();
return redirect()->route('vehiculos.edit', $tiposVeiculos->id);
}
// Si hay múltiples coincidencias, mostrar la lista filtrada
return view('vehiculos', ["tiposVeiculos" => $tiposVeiculos]);
}
// Si no hay búsqueda, mostrar todas las marcas
$tiposVeiculos = tiposVeiculos::where('status', true)->get();
return view('vehiculos', ["tiposVeiculos" => $tiposVeiculos]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$tiposVeiculos = tiposVeiculos::all();
return view('vehiculosCrearEditar',['tiposVeiculos'=>$tiposVeiculos]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$tiposVeiculos = new tiposVeiculos($request->all());
$tiposVeiculos->status = true;
$tiposVeiculos->save();
return redirect()->route('vehiculos.index')->with('success', 'Tipo de vehiculo creado exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(tiposVeiculos $tiposVeiculos)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$tipoVehiculo = tiposVeiculos::find($id);
return view('vehiculosCrearEditar', ['tipoVehiculo' => $tipoVehiculo]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$tipoVehiculo = tiposVeiculos::find($id);
$tipoVehiculo->fill($request->all());
if ($request->has('status')) {
$tipoVehiculo->status = $request->status;
}
$tipoVehiculo->save();
return redirect()->route('vehiculos.index')->with('success', 'Vehículo actualizado exitosamente.');
}
public function toggleStatus($id)
{
$tipoVehiculo = tiposVeiculos::findOrFail($id);
$tipoVehiculo->status = !$tipoVehiculo->status;
$tipoVehiculo->save();
$mensaje = $tipoVehiculo->status ? 'Tipo de vehículo activado exitosamente.' : 'Tipo de vehículo desactivado exitosamente.';
return redirect()->route('vehiculos.index')->with('success', $mensaje);
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$tiposVeiculos = tiposVeiculos::find($id);
$tiposVeiculos->status = false;
$tiposVeiculos->save();
return redirect()->route('vehiculos.index')->with('success', 'Vehiculo eliminado exitosamente.');
}
public function exportExcel()
{
$tiposVeiculos = tiposVeiculos::all();
$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="tipos_vehiculos.csv"',
];
$callback = function() use ($tiposVeiculos) {
$file = fopen('php://output', 'w');
// Encabezados
fputcsv($file, ['ID', 'Nombre', 'Tipo de Combustible', 'Estado', 'Fecha de Creación']);
// Datos
foreach ($tiposVeiculos as $vehiculo) {
$estado = $vehiculo->status ? 'Activo' : 'Inactivo';
$tipoCombustible = '';
switch($vehiculo->tipo_combustible) {
case 'gasolina_verde':
$tipoCombustible = 'Gasolina Verde';
break;
case 'gasolina_roja':
$tipoCombustible = 'Gasolina Roja';
break;
case 'diesel':
$tipoCombustible = 'Diesel';
break;
default:
$tipoCombustible = 'No especificado';
}
fputcsv($file, [
$vehiculo->id,
$vehiculo->nombre,
$tipoCombustible,
$estado,
$vehiculo->created_at->format('d/m/Y')
]);
}
fclose($file);
};
return response()->stream($callback, 200, $headers);
}
public function exportPDF()
{
$tiposVeiculos = tiposVeiculos::all();
$pdf = PDF::loadView('exports.tipos_vehiculos_pdf', ['tiposVeiculos' => $tiposVeiculos]);
return $pdf->download('tipos_vehiculos.pdf');
}
}

162
app/Http/Controllers/usuariosController.php

@ -0,0 +1,162 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use App\Exports\UsuariosExport;
use Maatwebsite\Excel\Facades\Excel;
use PDF; // Asegúrate de incluir la clase PDF
use App\Models\Puesto;
class usuariosController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$busqueda = $request->busqueda;
if ($busqueda) {
// Busca en la columna 'name' de la tabla 'users'
$usuarios = User::where('name', 'LIKE', "%{$busqueda}%")->where('eliminado', 0)->get();
if ($usuarios->isEmpty()) {
return redirect()->route('usuarios')
->with('error', 'No existe ningún usuario con el nombre "' . $busqueda . '". Por favor, inténtalo de nuevo.');
}
} else {
// Si no hay búsqueda, mostrar todos los usuarios
$usuarios = User::where('eliminado', 0)->get();
}
return view('usuarios', ['usuarios' => $usuarios]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$puestos = Puesto::all();
return view('usuariosCrearEditar', ['usuario' => null, 'puestos' => $puestos]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Validación de datos
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'apellido' => 'required|string|max:255',
'puesto_id' => 'required|exists:puestos,id',
'carrera' => 'required|string|max:255',
'telefono' => 'required|string|max:255',
'password' => 'required|string|min:8|confirmed',
]);
// Si la validación pasa, crea el usuario
$usuario = new User();
$usuario->name = $request->name;
$usuario->email = $request->email;
$usuario->apellido = $request->apellido;
$usuario->puesto_id = $request->puesto_id;
$usuario->carrera = $request->carrera;
$usuario->telefono = $request->telefono;
$usuario->password = bcrypt($request->password);
$usuario->save();
return redirect()->route('usuarios')->with('success', 'Usuario creado exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
// Implementar si es necesario
}
/**
* Show the form for editing the specified resource.
*/
// ... existing code ...
public function edit($id)
{
$user = User::findOrFail($id);
$puestos = Puesto::all();
return view('usuariosCrearEditar',['usuario' => $user, 'puestos' => $puestos]); // Asegúrate de que la clave sea 'usuario'
}
// ... existing code ...
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
// Validación de datos
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'apellido' => 'required|string|max:255',
//'puesto_id' => 'required|exists:puesto_id',
'carrera' => 'required|string|max:255',
'telefono' => 'required|string|max:255',
'password' => 'nullable|string|min:8|confirmed',
]);
// Actualizar usuario
$usuario = User::findOrFail($id);
$usuario->name = $request->name;
$usuario->email = $request->email;
$usuario->apellido = $request->apellido;
$usuario->puesto_id = $request->puesto_id;
$usuario->carrera = $request->carrera;
$usuario->telefono = $request->telefono;
if ($request->filled('password')) {
$usuario->password = bcrypt($request->password);
}
$usuario->save();
return redirect()->route('usuarios')->with('success', 'Usuario actualizado exitosamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
// Buscar el usuario por ID
$usuario = User::findOrFail($id);
// Cambiar el estado de eliminado a 1
$usuario->eliminado = 1; // Asumiendo que 'eliminado' es el campo que indica el estado
$usuario->save(); // Guardar los cambios
// Redirigir a la lista de usuarios con un mensaje de éxito
return redirect()->route('usuarios')->with('success', 'Usuario eliminado exitosamente.');
}
public function exportExcel()
{
return Excel::download(new UsuariosExport, 'usuarios.xlsx');
}
public function exportPDF()
{
$usuarios = User::where('eliminado', 0)->get();
$pdf = PDF::loadView('exports.usuarios-pdf', ['usuarios' => $usuarios]);
return $pdf->download('usuarios.pdf');
}
}

1
app/Http/Kernel.php

@ -63,5 +63,6 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class, 'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'admin' => \App\Http\Middleware\AdminMiddleware::class,
]; ];
} }

19
app/Http/Middleware/AdminMiddleware.php

@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminMiddleware
{
public function handle(Request $request, Closure $next)
{
if (Auth::check() && Auth::user()->email === 'monse@admin.com') {
return $next($request);
}
return redirect('/')->with('error', 'Acceso denegado. Solo los administradores pueden acceder a esta página.');
}
}

14
app/Models/Capacidad.php

@ -0,0 +1,14 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Capacidad extends Model
{
use HasFactory;
protected $table = 'capacidades';
protected $fillable = ['capacidad'];
}

20
app/Models/Docentes.php

@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Docentes extends Model
{
use HasFactory;
protected $fillable = [
'nombre',
'telefono',
'correo',
'tipo_licencia',
'materia',
'status'
];
}

32
app/Models/Maintenance.php

@ -0,0 +1,32 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Maintenance extends Model
{
use HasFactory;
protected $fillable = [
'vehicle_id',
'maintenance_type',
'date',
'description',
'cost',
'status',
'next_maintenance_date'
];
protected $casts = [
'date' => 'date',
'next_maintenance_date' => 'date',
'cost' => 'decimal:2'
];
public function vehicle()
{
return $this->belongsTo(TiposVeiculo::class, 'vehicle_id');
}
}

20
app/Models/Marca.php

@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Marca extends Model
{
use HasFactory;
protected $table = 'marcas';
protected $fillable = ['marca'];
/*public function Marc():HasOne{
return $this->hasOne(marc::class, 'id','marcs_id');
}*/
}

11
app/Models/Tipo_de_Gasolina.php

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Tipo_de_Gasolina extends Model
{
use HasFactory;
}

10
app/Models/User.php

@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Relations\HasOne;
class User extends Authenticatable class User extends Authenticatable
{ {
@ -20,9 +21,14 @@ class User extends Authenticatable
protected $fillable = [ protected $fillable = [
'name', 'name',
'email', 'email',
'apellido',
'puesto_id',
'carrera',
'telefono',
'password', 'password',
]; ];
/** /**
* The attributes that should be hidden for serialization. * The attributes that should be hidden for serialization.
* *
@ -41,4 +47,8 @@ class User extends Authenticatable
protected $casts = [ protected $casts = [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
]; ];
public function puesto():HasOne{
return $this->hasOne(Puesto::class, 'id','puesto_id');
}
} }

11
app/Models/marc.php

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class marc extends Model
{
use HasFactory;
}

24
app/Models/prestamo.php

@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class prestamo extends Model
{
use HasFactory;
protected $table = 'prestamos';
protected $fillable = [
'nombre_solicitante',
'destino',
'fecha_hora_salida',
'fecha_hora_llegada',
'motivo',
'domicilio',
'numero_personas',
'chofer',
];
}

11
app/Models/puesto.php

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class puesto extends Model
{
use HasFactory;
}

15
app/Models/tiposLicencias.php

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

16
app/Models/tiposVeiculos.php

@ -0,0 +1,16 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class tiposVeiculos extends Model
{
use HasFactory;
protected $fillable = [
'nombre',
'tipo_combustible',
'status',
];
}

3
app/Providers/RouteServiceProvider.php

@ -16,8 +16,7 @@ class RouteServiceProvider extends ServiceProvider
* Typically, users are redirected here after authentication. * Typically, users are redirected here after authentication.
* *
* @var string * @var string
*/ */ public const HOME = '/dashboard';
public const HOME = '/home';
/** /**
* Define your route model bindings, pattern filters, and other route configuration. * Define your route model bindings, pattern filters, and other route configuration.

4
composer.json

@ -6,11 +6,13 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"barryvdh/laravel-dompdf": "^3.1",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0", "laravel/framework": "^10.0",
"laravel/sanctum": "^3.2", "laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",
"laravel/ui": "^4.6" "laravel/ui": "^4.6",
"maatwebsite/excel": "^3.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",

1514
composer.lock

File diff suppressed because it is too large

3
config/app.php

@ -2,6 +2,7 @@
use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\Facade;
return [ return [
/* /*
@ -194,6 +195,7 @@ return [
// App\Providers\BroadcastServiceProvider::class, // App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
Barryvdh\DomPDF\ServiceProvider::class,
], ],
@ -210,6 +212,7 @@ return [
'aliases' => Facade::defaultAliases()->merge([ 'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class, // 'ExampleClass' => App\Example\ExampleClass::class,
'PDF' => Barryvdh\DomPDF\Facade\Pdf::class,
])->toArray(), ])->toArray(),
]; ];

301
config/dompdf.php

@ -0,0 +1,301 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Settings
|--------------------------------------------------------------------------
|
| Set some default values. It is possible to add all defines that can be set
| in dompdf_config.inc.php. You can also override the entire config file.
|
*/
'show_warnings' => false, // Throw an Exception on warnings from dompdf
'public_path' => null, // Override the public path if needed
/*
* Dejavu Sans font is missing glyphs for converted entities, turn it off if you need to show € and £.
*/
'convert_entities' => true,
'options' => [
/**
* The location of the DOMPDF font directory
*
* The location of the directory where DOMPDF will store fonts and font metrics
* Note: This directory must exist and be writable by the webserver process.
* *Please note the trailing slash.*
*
* Notes regarding fonts:
* Additional .afm font metrics can be added by executing load_font.php from command line.
*
* Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
* be embedded in the pdf file or the PDF may not display correctly. This can significantly
* increase file size unless font subsetting is enabled. Before embedding a font please
* review your rights under the font license.
*
* Any font specification in the source HTML is translated to the closest font available
* in the font directory.
*
* The pdf standard "Base 14 fonts" are:
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
* Symbol, ZapfDingbats.
*/
'font_dir' => storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
/**
* The location of the DOMPDF font cache directory
*
* This directory contains the cached font metrics for the fonts used by DOMPDF.
* This directory can be the same as DOMPDF_FONT_DIR
*
* Note: This directory must exist and be writable by the webserver process.
*/
'font_cache' => storage_path('fonts'),
/**
* The location of a temporary directory.
*
* The directory specified must be writeable by the webserver process.
* The temporary directory is required to download remote images and when
* using the PDFLib back end.
*/
'temp_dir' => sys_get_temp_dir(),
/**
* ==== IMPORTANT ====
*
* dompdf's "chroot": Prevents dompdf from accessing system files or other
* files on the webserver. All local files opened by dompdf must be in a
* subdirectory of this directory. DO NOT set it to '/' since this could
* allow an attacker to use dompdf to read any files on the server. This
* should be an absolute path.
* This is only checked on command line call by dompdf.php, but not by
* direct class use like:
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
*/
'chroot' => realpath(base_path()),
/**
* Protocol whitelist
*
* Protocols and PHP wrappers allowed in URIs, and the validation rules
* that determine if a resouce may be loaded. Full support is not guaranteed
* for the protocols/wrappers specified
* by this array.
*
* @var array
*/
'allowed_protocols' => [
'data://' => ['rules' => []],
'file://' => ['rules' => []],
'http://' => ['rules' => []],
'https://' => ['rules' => []],
],
/**
* Operational artifact (log files, temporary files) path validation
*/
'artifactPathValidation' => null,
/**
* @var string
*/
'log_output_file' => null,
/**
* Whether to enable font subsetting or not.
*/
'enable_font_subsetting' => false,
/**
* The PDF rendering backend to use
*
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
* fall back on CPDF. 'GD' renders PDFs to graphic files.
* {@link * Canvas_Factory} ultimately determines which rendering class to
* instantiate based on this setting.
*
* Both PDFLib & CPDF rendering backends provide sufficient rendering
* capabilities for dompdf, however additional features (e.g. object,
* image and font support, etc.) differ between backends. Please see
* {@link PDFLib_Adapter} for more information on the PDFLib backend
* and {@link CPDF_Adapter} and lib/class.pdf.php for more information
* on CPDF. Also see the documentation for each backend at the links
* below.
*
* The GD rendering backend is a little different than PDFLib and
* CPDF. Several features of CPDF and PDFLib are not supported or do
* not make any sense when creating image files. For example,
* multiple pages are not supported, nor are PDF 'objects'. Have a
* look at {@link GD_Adapter} for more information. GD support is
* experimental, so use it at your own risk.
*
* @link http://www.pdflib.com
* @link http://www.ros.co.nz/pdf
* @link http://www.php.net/image
*/
'pdf_backend' => 'CPDF',
/**
* html target media view which should be rendered into pdf.
* List of types and parsing rules for future extensions:
* http://www.w3.org/TR/REC-html40/types.html
* screen, tty, tv, projection, handheld, print, braille, aural, all
* Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
* Note, even though the generated pdf file is intended for print output,
* the desired content might be different (e.g. screen or projection view of html file).
* Therefore allow specification of content here.
*/
'default_media_type' => 'screen',
/**
* The default paper size.
*
* North America standard is "letter"; other countries generally "a4"
*
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
*/
'default_paper_size' => 'a4',
/**
* The default paper orientation.
*
* The orientation of the page (portrait or landscape).
*
* @var string
*/
'default_paper_orientation' => 'portrait',
/**
* The default font family
*
* Used if no suitable fonts can be found. This must exist in the font folder.
*
* @var string
*/
'default_font' => 'serif',
/**
* Image DPI setting
*
* This setting determines the default DPI setting for images and fonts. The
* DPI may be overridden for inline images by explictly setting the
* image's width & height style attributes (i.e. if the image's native
* width is 600 pixels and you specify the image's width as 72 points,
* the image will have a DPI of 600 in the rendered PDF. The DPI of
* background images can not be overridden and is controlled entirely
* via this parameter.
*
* For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
* If a size in html is given as px (or without unit as image size),
* this tells the corresponding size in pt.
* This adjusts the relative sizes to be similar to the rendering of the
* html page in a reference browser.
*
* In pdf, always 1 pt = 1/72 inch
*
* Rendering resolution of various browsers in px per inch:
* Windows Firefox and Internet Explorer:
* SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
* Linux Firefox:
* about:config *resolution: Default:96
* (xorg screen dimension in mm and Desktop font dpi settings are ignored)
*
* Take care about extra font/image zoom factor of browser.
*
* In images, <img> size in pixel attribute, img css style, are overriding
* the real image dimension in px for rendering.
*
* @var int
*/
'dpi' => 96,
/**
* Enable embedded PHP
*
* If this setting is set to true then DOMPDF will automatically evaluate embedded PHP contained
* within <script type="text/php"> ... </script> tags.
*
* ==== IMPORTANT ==== Enabling this for documents you do not trust (e.g. arbitrary remote html pages)
* is a security risk.
* Embedded scripts are run with the same level of system access available to dompdf.
* Set this option to false (recommended) if you wish to process untrusted documents.
* This setting may increase the risk of system exploit.
* Do not change this settings without understanding the consequences.
* Additional documentation is available on the dompdf wiki at:
* https://github.com/dompdf/dompdf/wiki
*
* @var bool
*/
'enable_php' => false,
/**
* Rnable inline JavaScript
*
* If this setting is set to true then DOMPDF will automatically insert JavaScript code contained
* within <script type="text/javascript"> ... </script> tags as written into the PDF.
* NOTE: This is PDF-based JavaScript to be executed by the PDF viewer,
* not browser-based JavaScript executed by Dompdf.
*
* @var bool
*/
'enable_javascript' => true,
/**
* Enable remote file access
*
* If this setting is set to true, DOMPDF will access remote sites for
* images and CSS files as required.
*
* ==== IMPORTANT ====
* This can be a security risk, in particular in combination with isPhpEnabled and
* allowing remote html code to be passed to $dompdf = new DOMPDF(); $dompdf->load_html(...);
* This allows anonymous users to download legally doubtful internet content which on
* tracing back appears to being downloaded by your server, or allows malicious php code
* in remote html pages to be executed by your server with your account privileges.
*
* This setting may increase the risk of system exploit. Do not change
* this settings without understanding the consequences. Additional
* documentation is available on the dompdf wiki at:
* https://github.com/dompdf/dompdf/wiki
*
* @var bool
*/
'enable_remote' => false,
/**
* List of allowed remote hosts
*
* Each value of the array must be a valid hostname.
*
* This will be used to filter which resources can be loaded in combination with
* isRemoteEnabled. If enable_remote is FALSE, then this will have no effect.
*
* Leave to NULL to allow any remote host.
*
* @var array|null
*/
'allowed_remote_hosts' => null,
/**
* A ratio applied to the fonts height to be more like browsers' line height
*/
'font_height_ratio' => 1.1,
/**
* Use the HTML5 Lib parser
*
* @deprecated This feature is now always on in dompdf 2.x
*
* @var bool
*/
'enable_html5_parser' => true,
],
];

4
config/session.php

@ -31,9 +31,9 @@ return [
| |
*/ */
'lifetime' => env('SESSION_LIFETIME', 120), 'lifetime' => env('SESSION_LIFETIME', 0.1),
'expire_on_close' => false, 'expire_on_close' => true,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

23
database/factories/CapacidadFactory.php

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Capacidad>
*/
class CapacidadFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

27
database/factories/DocentesFactory.php

@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Docentes>
*/
class DocentesFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'nombre' => $this->faker->name,
'telefono' => $this->faker->phoneNumber,
'correo' => $this->faker->email,
'tipo_licencia' => $this->faker->randomElement(['Vigente', 'No Vigente']),
'materia' => $this->faker->randomElement(['Matemáticas', 'Programación', 'Base de datos', 'Sistemas Operativos', 'Redes']),
];
}
}

23
database/factories/MarcaFactory.php

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Marca>
*/
class MarcaFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

23
database/factories/PrestamoFactory.php

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\prestamo>
*/
class PrestamoFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

23
database/factories/TipoDeGasolinaFactory.php

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tipo_de_Gasolina>
*/
class TipoDeGasolinaFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

23
database/factories/TiposLicenciasFactory.php

@ -0,0 +1,23 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\tiposLicencias>
*/
class TiposLicenciasFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}

25
database/factories/TiposVeiculosFactory.php

@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\tiposVeiculos>
*/
class TiposVeiculosFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
"nombre"=> $this->faker->name(),
"Tipo de Combustible"=> $this->faker->sentence(),
//
];
}
}

32
database/migrations/2013_03_27_235747_create_puestos_table.php

@ -0,0 +1,32 @@
<?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::create('puestos', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->timestamps();
});
DB::table('puestos')->insert(['nombre'=> 'Administrativo']);
DB::table('puestos')->insert(['nombre'=> 'docente']);
DB::table('puestos')->insert(['nombre'=> 'coordinador']);
DB::table('puestos')->insert(['nombre'=> 'personal general']);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('puestos');
}
};

11
database/migrations/2014_10_12_000000_create_users_table.php

@ -16,10 +16,21 @@ return new class extends Migration
$table->string('name'); $table->string('name');
$table->string('email')->unique(); $table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable(); $table->timestamp('email_verified_at')->nullable();
$table->string('apellido')->nullable();
$table->unsignedBigInteger('puesto_id')->nullable();
$table->string('carrera')->nullable();
$table->string('telefono')->nullable();
$table->string('password'); $table->string('password');
$table->rememberToken(); $table->rememberToken();
$table->timestamps(); $table->timestamps();
$table->foreign('puesto_id')->references('id')->on('puestos');
}); });
DB::table('users')->insert([
'name'=> 'monse',
'email'=> 'monse@admin.com',
'password'=> bcrypt('tecmm2025')
]);
} }
/** /**

62
database/migrations/2025_01_18_230913_create_marcs_table.php

@ -0,0 +1,62 @@
<?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::create('marcs', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
DB::table('marcs')->insert([
['name' => 'chevrolet'],
['name' => 'nissan'],
['name' => 'ford'],
['name' => 'toyota'],
['name' => 'honda'],
['name' => 'bmw'],
['name' => 'audi'],
['name' => 'mercedes-benz'],
['name' => 'volkswagen'],
['name' => 'hyundai'],
['name' => 'kia'],
['name' => 'subaru'],
['name' => 'mazda'],
['name' => 'peugeot'],
['name' => 'renault'],
['name' => 'fiat'],
['name' => 'land rover'],
['name' => 'jaguar'],
['name' => 'tesla'],
['name' => 'porsche'],
['name' => 'volvo'],
['name' => 'mitsubishi'],
['name' => 'chrysler'],
['name' => 'dodge'],
['name' => 'jeep'],
['name' => 'buick'],
['name' => 'gmc'],
['name' => 'infiniti'],
['name' => 'lexus'],
['name' => 'acura'],
['name' => 'alfa romeo'],
// Agrega más marcas según sea necesario
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('marcs');
}
};

29
database/migrations/2025_02_28_192615_create_marcas_table.php

@ -0,0 +1,29 @@
<?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::create('marcas', function (Blueprint $table) {
$table->id();
$table->string('marca');
$table->timestamps();
// funciona como enlace de una tabla a otra par agregar valores ya definidos $table->foreign('marcs_id')->references('id')->on('marcs');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('marcas');
}
};

32
database/migrations/2025_03_05_172529_create_docentes_table.php

@ -0,0 +1,32 @@
<?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::create('docentes', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->string('telefono');
$table->string('correo');
$table->string('tipo_licencia');
$table->string('materia');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('docentes');
}
};

29
database/migrations/2025_03_06_162928_create_tipos_veiculos_table.php

@ -0,0 +1,29 @@
<?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::create('tipos_veiculos', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->string('tipo_combustible');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tipos_veiculos');
}
};

27
database/migrations/2025_03_07_000000_add_plate_to_tipos_veiculos.php

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('tipos_veiculos', function (Blueprint $table) {
if (!Schema::hasColumn('tipos_veiculos', 'plate')) {
$table->string('plate')->after('nombre')->nullable();
}
if (!Schema::hasColumn('tipos_veiculos', 'model')) {
$table->string('model')->after('plate')->nullable();
}
});
}
public function down()
{
Schema::table('tipos_veiculos', function (Blueprint $table) {
$table->dropColumn(['plate', 'model']);
});
}
};

27
database/migrations/2025_03_07_194830_create_tipo_de__gasolinas_table.php

@ -0,0 +1,27 @@
<?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::create('tipo_de__gasolinas', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tipo_de__gasolinas');
}
};

28
database/migrations/2025_03_08_000000_create_maintenances_table.php

@ -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()
{
Schema::create('maintenances', function (Blueprint $table) {
$table->id();
$table->foreignId('vehicle_id')->constrained('tipos_veiculos')->onDelete('cascade');
$table->string('maintenance_type');
$table->date('date');
$table->text('description');
$table->decimal('cost', 10, 2);
$table->enum('status', ['Pendiente', 'En Proceso', 'Completado'])->default('Pendiente');
$table->date('next_maintenance_date')->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('maintenances');
}
};

28
database/migrations/2025_03_13_133629_create_capacidads_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('capacidades', function (Blueprint $table) {
$table->id();
$table->integer('capacidad');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('capacidades');
}
};

28
database/migrations/2025_03_13_143153_create_tipos_licencias_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tiposLicencias', function (Blueprint $table) {
$table->id();
$table->string('tipoLicencia');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tiposLicencias');
}
};

29
database/migrations/2025_03_19_030418_add_columneliminado_tomarcas.php

@ -0,0 +1,29 @@
<?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('marcas', function (Blueprint $table) {
$table->boolean('eliminado')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('marcas', function (Blueprint $table) {
$table->dropColumn('eliminado');
});
}
};

28
database/migrations/2025_03_27_054337_add_status_to_docentes_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('docentes', function (Blueprint $table) {
$table->boolean('status')->default(true)->after('materia');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('docentes', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};

28
database/migrations/2025_03_27_135638_add_columneliminar_to_users.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('eliminado')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('eliminado');
});
}
};

28
database/migrations/2025_03_27_143601_add_status_to_tipos_licencias_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tiposLicencias', function (Blueprint $table) {
$table->boolean('status')->default(true);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tiposLicencias', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};

28
database/migrations/2025_03_27_144121_rename_status_to_eliminado_in_tipos_licencias.php

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

28
database/migrations/2025_03_27_164635_add_status_to_tipos_veiculos_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tipos_veiculos', function (Blueprint $table) {
$table->boolean('status')->default(true);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tipos_veiculos', function (Blueprint $table) {
$table->dropColumn('status');
});
}
};

35
database/migrations/2025_03_27_174121_create_prestamos_table.php

@ -0,0 +1,35 @@
<?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::create('prestamos', function (Blueprint $table) {
$table->id();
$table->string('nombre_solicitante');
$table->string('destino');
$table->dateTime('fecha_hora_salida');
$table->dateTime('fecha_hora_llegada');
$table->text('motivo');
$table->string('domicilio');
$table->integer('numero_personas');
$table->boolean('chofer')->default(false); // Opción de sí (true) o no (false)
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('prestamos');
}
};

28
database/migrations/2025_03_27_183714_add_columneliminado_toprestamos.php

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

28
database/migrations/2025_03_27_183845_add_columneliminado_to_capacidads_table.php

@ -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
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('capacidades', function (Blueprint $table) {
$table->boolean('eliminado')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('capacidades', function (Blueprint $table) {
$table->dropColumn('eliminado');
});
}
};

28
database/migrations/2025_03_28_175646_add_estado_to_prestamos_table.php

@ -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
{
/**
* 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_182126_add_estado_to_prestamos_table.php

@ -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
{
/**
* 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

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

22
database/migrations/2025_05_07_000000_add_rol_to_users_table.php

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('rol')->default('usuario')->after('email');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('rol');
});
}
};

20
database/seeders/CapacidadSeeder.php

@ -0,0 +1,20 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Capacidad;
class CapacidadSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

17
database/seeders/DocentesSeeder.php

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DocentesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

17
database/seeders/MarcaSeeder.php

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class MarcaSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

17
database/seeders/TipoDeGasolinaSeeder.php

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TipoDeGasolinaSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

17
database/seeders/TiposLicenciasSeeder.php

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TiposLicenciasSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

17
database/seeders/TiposVeiculosSeeder.php

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TiposVeiculosSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

347
package-lock.json

@ -4,15 +4,27 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"dependencies": {
"react-bootstrap": "^2.10.9"
},
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"axios": "^1.1.2", "axios": "^1.9.0",
"bootstrap": "^5.2.3", "bootstrap": "^5.3.6",
"laravel-vite-plugin": "^0.7.2", "laravel-vite-plugin": "^0.7.2",
"sass": "^1.56.1", "sass": "^1.56.1",
"vite": "^4.0.0" "vite": "^4.0.0"
} }
}, },
"node_modules/@babel/runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@ -701,13 +713,120 @@
"version": "2.11.8", "version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@react-aria/ssr": {
"version": "3.9.8",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.8.tgz",
"integrity": "sha512-lQDE/c9uTfBSDOjaZUJS8xP2jCKVk4zjQeIlCH90xaLhHDgbpCdns3xvFpJJujfj3nI4Ll9K7A+ONUBDCASOuw==",
"license": "Apache-2.0",
"dependencies": {
"@swc/helpers": "^0.5.0"
},
"engines": {
"node": ">= 12"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
"node_modules/@restart/hooks": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
"integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
"license": "MIT",
"dependencies": {
"dequal": "^2.0.3"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@restart/ui": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz",
"integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.26.0",
"@popperjs/core": "^2.11.8",
"@react-aria/ssr": "^3.5.0",
"@restart/hooks": "^0.5.0",
"@types/warning": "^3.0.3",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"uncontrollable": "^8.0.4",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
}
},
"node_modules/@restart/ui/node_modules/@restart/hooks": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz",
"integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==",
"license": "MIT",
"dependencies": {
"dequal": "^2.0.3"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@restart/ui/node_modules/uncontrollable": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz",
"integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.14.0"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
"integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.14",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
"integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
"license": "MIT"
},
"node_modules/@types/react": {
"version": "19.1.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz",
"integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==",
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
"integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*"
}
},
"node_modules/@types/warning": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==",
"license": "MIT"
},
"node_modules/asynckit": { "node_modules/asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -716,9 +835,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.8.1", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -728,9 +847,9 @@
} }
}, },
"node_modules/bootstrap": { "node_modules/bootstrap": {
"version": "5.3.3", "version": "5.3.6",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz",
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -791,6 +910,12 @@
"url": "https://paulmillr.com/funding/" "url": "https://paulmillr.com/funding/"
} }
}, },
"node_modules/classnames": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
"license": "MIT"
},
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -804,6 +929,12 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
},
"node_modules/delayed-stream": { "node_modules/delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -814,6 +945,15 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
@ -828,6 +968,16 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dunder-proto": { "node_modules/dunder-proto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@ -1107,6 +1257,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -1143,6 +1302,12 @@
"node": ">=0.12.0" "node": ">=0.12.0"
} }
}, },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
"node_modules/laravel-vite-plugin": { "node_modules/laravel-vite-plugin": {
"version": "0.7.8", "version": "0.7.8",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.7.8.tgz", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.7.8.tgz",
@ -1160,6 +1325,18 @@
"vite": "^3.0.0 || ^4.0.0" "vite": "^3.0.0 || ^4.0.0"
} }
}, },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/math-intrinsics": { "node_modules/math-intrinsics": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@ -1235,6 +1412,15 @@
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -1284,6 +1470,30 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
"node_modules/prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"license": "MIT",
"dependencies": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
},
"peerDependencies": {
"react": ">=0.14.0"
}
},
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@ -1291,6 +1501,88 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/react": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-bootstrap": {
"version": "2.10.9",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.9.tgz",
"integrity": "sha512-TJUCuHcxdgYpOqeWmRApM/Dy0+hVsxNRFvq2aRFQuxhNi/+ivOxC5OdWIeHS3agxvzJ4Ev4nDw2ZdBl9ymd/JQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.7",
"@restart/hooks": "^0.4.9",
"@restart/ui": "^1.9.4",
"@types/prop-types": "^15.7.12",
"@types/react-transition-group": "^4.4.6",
"classnames": "^2.3.2",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.8.1",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.5",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"@types/react": ">=16.14.8",
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-dom": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
"peerDependencies": {
"react": "^19.1.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==",
"license": "MIT"
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"license": "BSD-3-Clause",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/readdirp": { "node_modules/readdirp": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@ -1343,6 +1635,13 @@
"@parcel/watcher": "^2.4.1" "@parcel/watcher": "^2.4.1"
} }
}, },
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT",
"peer": true
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -1367,6 +1666,27 @@
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.6.3",
"@types/react": ">=16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
},
"peerDependencies": {
"react": ">=15.0.0"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "4.5.9", "version": "4.5.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.9.tgz",
@ -1433,6 +1753,15 @@
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
} }
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.0.0"
}
} }
} }
} }

7
package.json

@ -6,10 +6,13 @@
}, },
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"axios": "^1.1.2", "axios": "^1.9.0",
"bootstrap": "^5.2.3", "bootstrap": "^5.3.6",
"laravel-vite-plugin": "^0.7.2", "laravel-vite-plugin": "^0.7.2",
"sass": "^1.56.1", "sass": "^1.56.1",
"vite": "^4.0.0" "vite": "^4.0.0"
},
"dependencies": {
"react-bootstrap": "^2.10.9"
} }
} }

BIN
public/css/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

0
resources/css/app.css

143
resources/js/components/dashboard/JorgeDashboard.jsx

@ -0,0 +1,143 @@
import React, { useState, useEffect } from 'react';
import { Card, Row, Col, Button, Table, Alert } from 'react-bootstrap';
import NewMaintenanceForm from './NewMaintenanceForm';
import axios from 'axios';
const JorgeDashboard = () => {
const [maintenanceHistory, setMaintenanceHistory] = useState([]);
const [pendingAlerts, setPendingAlerts] = useState([]);
const [showNewMaintenanceForm, setShowNewMaintenanceForm] = useState(false);
const [vehicles, setVehicles] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
try {
setLoading(true);
const [historyRes, alertsRes, vehiclesRes] = await Promise.all([
axios.get('/api/maintenance/history'),
axios.get('/api/maintenance/alerts'),
axios.get('/api/maintenance/vehicles')
]);
setMaintenanceHistory(historyRes.data);
setPendingAlerts(alertsRes.data);
setVehicles(vehiclesRes.data);
setError(null);
} catch (err) {
setError('Error al cargar los datos. Por favor, intente nuevamente.');
console.error('Error fetching data:', err);
} finally {
setLoading(false);
}
};
const handleNewMaintenance = async (formData) => {
try {
const response = await axios.post('/api/maintenance', formData);
setMaintenanceHistory(prev => [response.data.maintenance, ...prev]);
setShowNewMaintenanceForm(false);
} catch (err) {
setError('Error al guardar el mantenimiento. Por favor, intente nuevamente.');
console.error('Error saving maintenance:', err);
}
};
if (loading) {
return <div className="text-center p-5">Cargando...</div>;
}
if (error) {
return <Alert variant="danger">{error}</Alert>;
}
return (
<div className="container-fluid">
<h2 className="mb-4">Panel de Control - Mantenimiento de Vehículos</h2>
{/* Alertas Pendientes */}
<Row className="mb-4">
<Col>
<Card>
<Card.Header>
<h4>Alertas de Mantenimiento Pendiente</h4>
</Card.Header>
<Card.Body>
{pendingAlerts.length === 0 ? (
<Alert variant="success">No hay alertas pendientes</Alert>
) : (
pendingAlerts.map(alert => (
<Alert key={alert.id} variant="warning">
<strong>{alert.vehicle.plate}</strong> - {alert.maintenance_type} pendiente para: {new Date(alert.next_maintenance_date).toLocaleDateString()}
</Alert>
))
)}
</Card.Body>
</Card>
</Col>
</Row>
{/* Historial de Mantenimientos */}
<Row>
<Col>
<Card>
<Card.Header className="d-flex justify-content-between align-items-center">
<h4>Historial de Mantenimientos</h4>
<Button
variant="primary"
onClick={() => setShowNewMaintenanceForm(true)}
>
Nuevo Mantenimiento
</Button>
</Card.Header>
<Card.Body>
<Table striped bordered hover>
<thead>
<tr>
<th>Vehículo</th>
<th>Fecha</th>
<th>Tipo</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{maintenanceHistory.map(record => (
<tr key={record.id}>
<td>{record.vehicle.plate}</td>
<td>{new Date(record.date).toLocaleDateString()}</td>
<td>{record.maintenance_type}</td>
<td>{record.status}</td>
<td>
<Button variant="info" size="sm" className="me-2">
Ver Detalles
</Button>
<Button variant="secondary" size="sm">
Editar
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Card.Body>
</Card>
</Col>
</Row>
{/* Modal de Nuevo Mantenimiento */}
<NewMaintenanceForm
show={showNewMaintenanceForm}
handleClose={() => setShowNewMaintenanceForm(false)}
onSubmit={handleNewMaintenance}
vehicles={vehicles}
/>
</div>
);
};
export default JorgeDashboard;

151
resources/js/components/dashboard/NewMaintenanceForm.jsx

@ -0,0 +1,151 @@
import React, { useState } from 'react';
import { Modal, Form, Button } from 'react-bootstrap';
const NewMaintenanceForm = ({ show, handleClose, onSubmit, vehicles }) => {
const [formData, setFormData] = useState({
vehicle_id: '',
maintenance_type: '',
date: '',
description: '',
cost: '',
status: 'Pendiente',
next_maintenance_date: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
const handleSubmit = (e) => {
e.preventDefault();
onSubmit(formData);
// Resetear el formulario
setFormData({
vehicle_id: '',
maintenance_type: '',
date: '',
description: '',
cost: '',
status: 'Pendiente',
next_maintenance_date: ''
});
};
return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Nuevo Registro de Mantenimiento</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3">
<Form.Label>Vehículo</Form.Label>
<Form.Select
name="vehicle_id"
value={formData.vehicle_id}
onChange={handleChange}
required
>
<option value="">Seleccione un vehículo</option>
{vehicles.map(vehicle => (
<option key={vehicle.id} value={vehicle.id}>
{vehicle.plate} - {vehicle.model}
</option>
))}
</Form.Select>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Tipo de Mantenimiento</Form.Label>
<Form.Select
name="maintenance_type"
value={formData.maintenance_type}
onChange={handleChange}
required
>
<option value="">Seleccione un tipo</option>
<option value="Preventivo">Preventivo</option>
<option value="Correctivo">Correctivo</option>
<option value="Cambio de Aceite">Cambio de Aceite</option>
<option value="Revisión General">Revisión General</option>
</Form.Select>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Fecha</Form.Label>
<Form.Control
type="date"
name="date"
value={formData.date}
onChange={handleChange}
required
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Descripción</Form.Label>
<Form.Control
as="textarea"
rows={3}
name="description"
value={formData.description}
onChange={handleChange}
required
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Costo</Form.Label>
<Form.Control
type="number"
step="0.01"
name="cost"
value={formData.cost}
onChange={handleChange}
required
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Estado</Form.Label>
<Form.Select
name="status"
value={formData.status}
onChange={handleChange}
required
>
<option value="Pendiente">Pendiente</option>
<option value="En Proceso">En Proceso</option>
<option value="Completado">Completado</option>
</Form.Select>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Próxima Fecha de Mantenimiento</Form.Label>
<Form.Control
type="date"
name="next_maintenance_date"
value={formData.next_maintenance_date}
onChange={handleChange}
/>
</Form.Group>
<div className="d-flex justify-content-end gap-2">
<Button variant="secondary" onClick={handleClose}>
Cancelar
</Button>
<Button variant="primary" type="submit">
Guardar
</Button>
</div>
</Form>
</Modal.Body>
</Modal>
);
};
export default NewMaintenanceForm;

10
resources/js/maintenance-dashboard.js

@ -0,0 +1,10 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import { createRoot } from 'react-dom/client';
import JorgeDashboard from './components/dashboard/JorgeDashboard';
const container = document.getElementById('maintenance-dashboard');
if (container) {
const root = createRoot(container);
root.render(<JorgeDashboard />);
}

131
resources/views/auth/login.blade.php

@ -1,73 +1,106 @@
@extends('layouts.app') <!DOCTYPE html>
<html lang="es">
@section('content') <head>
<div class="container"> <meta charset="UTF-8">
<div class="row justify-content-center"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="col-md-8"> <title>Login - PrestamosTecmm</title>
<div class="card"> <!-- Tailwind CSS desde CDN -->
<div class="card-header">{{ __('Login') }}</div> <script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<div class="card-body"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<form method="POST" action="{{ route('login') }}"> </head>
@csrf <body class="bg-gradient-to-br from-blue-600 to-blue-800 min-h-screen flex items-center justify-center p-4">
<div class="max-w-md w-full bg-white rounded-lg shadow-xl overflow-hidden">
<div class="row mb-3"> <div class="p-6">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div class="text-center mb-8">
<h2 class="text-3xl font-bold text-gray-800">PrestamosTecmm</h2>
<div class="col-md-6"> <p class="text-gray-600 mt-2">Inicia sesión en tu cuenta</p>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus> </div>
@error('email') @if ($errors->any())
<span class="invalid-feedback" role="alert"> <div class="mb-4 bg-red-50 border-l-4 border-red-500 p-4">
<strong>{{ $message }}</strong> <div class="text-red-700">
</span> <ul>
@enderror @foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div> </div>
</div> </div>
@endif
<div class="row mb-3"> <form method="POST" action="{{ route('login') }}" class="space-y-6">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> @csrf
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password') <div>
<span class="invalid-feedback" role="alert"> <label for="email" class="block text-sm font-medium text-gray-700">
<strong>{{ $message }}</strong> Correo Electrónico
</span> </label>
@enderror <div class="mt-1 relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-envelope text-gray-400"></i>
</div>
<input id="email" name="email" type="email" required
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
value="{{ old('email') }}"
placeholder="tu@email.com">
</div> </div>
</div> </div>
<div class="row mb-3"> <div>
<div class="col-md-6 offset-md-4"> <label for="password" class="block text-sm font-medium text-gray-700">
<div class="form-check"> Contraseña
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember">
{{ __('Remember Me') }}
</label> </label>
<div class="mt-1 relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-lock text-gray-400"></i>
</div> </div>
<input id="password" name="password" type="password" required
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500"
placeholder="••••••••">
</div> </div>
</div> </div>
<div class="row mb-0"> <div class="flex items-center justify-between">
<div class="col-md-8 offset-md-4"> <div class="flex items-center">
<button type="submit" class="btn btn-primary"> <input id="remember_me" name="remember" type="checkbox"
{{ __('Login') }} class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
</button> <label for="remember_me" class="ml-2 block text-sm text-gray-700">
Recordarme
</label>
</div>
@if (Route::has('password.request')) @if (Route::has('password.request'))
<a class="btn btn-link" href="{{ route('password.request') }}"> <a href="{{ route('password.request') }}" class="text-sm text-blue-600 hover:text-blue-500">
{{ __('Forgot Your Password?') }} ¿Olvidaste tu contraseña?
</a> </a>
@endif @endif
</div> </div>
<div>
<button type="submit" class="w-full flex justify-center py-2 px-4 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">
Iniciar Sesión
</button>
</div> </div>
</form> </form>
@if (Route::has('register'))
<div class="mt-6 text-center">
<p class="text-sm text-gray-600">
¿No tienes una cuenta?
<a href="{{ route('register') }}" class="font-medium text-blue-600 hover:text-blue-500">
Regístrate aquí
</a>
</p>
</div> </div>
@endif
</div> </div>
</div> </div>
<!-- Decoración de fondo -->
<div class="absolute top-0 left-0 w-full h-full pointer-events-none overflow-hidden">
<div class="absolute -top-1/2 -left-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-10 transform rotate-45"></div>
<div class="absolute -bottom-1/2 -right-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-10 transform -rotate-45"></div>
</div> </div>
</div> </body>
@endsection </html>

154
resources/views/auth/register.blade.php

@ -1,77 +1,123 @@
@extends('layouts.app') <!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registro - PrestamosTecmm</title>
<!-- Tailwind CSS desde CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>
<body class="bg-gradient-to-br from-blue-600 to-blue-800 min-h-screen flex items-center justify-center p-4">
<div class="max-w-md w-full bg-white rounded-lg shadow-xl overflow-hidden">
<div class="p-8">
<div class="text-center mb-8">
<h2 class="text-3xl font-bold text-gray-800">PrestamosTecmm</h2>
<p class="text-gray-600 mt-2">Crea tu cuenta para comenzar</p>
</div>
@section('content') @if ($errors->any())
<div class="container"> <div class="mb-6 bg-red-50 border-l-4 border-red-500 p-4">
<div class="row justify-content-center"> <div class="text-red-700">
<div class="col-md-8"> <ul>
<div class="card"> @foreach ($errors->all() as $error)
<div class="card-header">{{ __('Register') }}</div> <li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
@endif
<div class="card-body"> <form method="POST" action="{{ route('register') }}" class="space-y-6">
<form method="POST" action="{{ route('register') }}">
@csrf @csrf
<div class="row mb-3"> <!-- Nombre -->
<label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label> <div>
<label for="name" class="block text-sm font-medium text-gray-700">
<div class="col-md-6"> Nombre Completo
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus> </label>
<div class="mt-1 relative rounded-md shadow-sm">
@error('name') <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="invalid-feedback" role="alert"> <i class="fas fa-user text-gray-400"></i>
<strong>{{ $message }}</strong> </div>
</span> <input type="text" name="name" id="name" required
@enderror class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
value="{{ old('name') }}"
placeholder="Juan Pérez">
</div> </div>
</div> </div>
<div class="row mb-3"> <!-- Email -->
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label> <div>
<label for="email" class="block text-sm font-medium text-gray-700">
<div class="col-md-6"> Correo Electrónico
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email"> </label>
<div class="mt-1 relative rounded-md shadow-sm">
@error('email') <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="invalid-feedback" role="alert"> <i class="fas fa-envelope text-gray-400"></i>
<strong>{{ $message }}</strong> </div>
</span> <input type="email" name="email" id="email" required
@enderror class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
value="{{ old('email') }}"
placeholder="tu@email.com">
</div> </div>
</div> </div>
<div class="row mb-3"> <!-- Contraseña -->
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label> <div>
<label for="password" class="block text-sm font-medium text-gray-700">
<div class="col-md-6"> Contraseña
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password"> </label>
<div class="mt-1 relative rounded-md shadow-sm">
@error('password') <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="invalid-feedback" role="alert"> <i class="fas fa-lock text-gray-400"></i>
<strong>{{ $message }}</strong> </div>
</span> <input type="password" name="password" id="password" required
@enderror class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
placeholder="••••••••">
</div> </div>
</div> </div>
<div class="row mb-3"> <!-- Confirmar Contraseña -->
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label> <div>
<label for="password_confirmation" class="block text-sm font-medium text-gray-700">
<div class="col-md-6"> Confirmar Contraseña
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password"> </label>
<div class="mt-1 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-lock text-gray-400"></i>
</div>
<input type="password" name="password_confirmation" id="password_confirmation" required
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
placeholder="••••••••">
</div> </div>
</div> </div>
<div class="row mb-0"> <div>
<div class="col-md-6 offset-md-4"> <button type="submit"
<button type="submit" class="btn btn-primary"> href="{{ route('dashboard') }}" class="w-full flex justify-center py-3 px-4 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 transition-colors duration-200">
{{ __('Register') }} <i class="fas fa-user-plus mr-2"></i>
Crear Cuenta
</button> </button>
</div> </div>
</div>
</form> </form>
<div class="mt-6 text-center">
<p class="text-sm text-gray-600">
¿Ya tienes una cuenta?
<a href="{{ route('login') }}" class="font-medium text-blue-600 hover:text-blue-500 transition-colors duration-200">
Inicia sesión aquí
</a>
</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Decoración de fondo -->
<div class="absolute top-0 left-0 w-full h-full pointer-events-none overflow-hidden">
<div class="absolute -top-1/2 -left-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-10 transform rotate-45"></div>
<div class="absolute -bottom-1/2 -right-1/4 w-96 h-96 bg-blue-400 rounded-full opacity-10 transform -rotate-45"></div>
</div> </div>
</div> </body>
@endsection </html>

100
resources/views/capacidades.blade.php

@ -0,0 +1,100 @@
@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 Capacidades</h2>
<a href="{{ route('capacidades.create') }}"
class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 flex items-center gap-2">
<i class="fas fa-plus"></i>
</a>
</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">Capacidad</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($capacidades as $capacidad)
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $capacidad->id }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ $capacidad->capacidad }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<div class="flex gap-2">
<a href="{{ route('capacidades.edit', $capacidad->id) }}"
class="text-blue-600 hover:text-blue-900">
<i class="fas fa-edit"></i>
</a>
<form action="{{ route('capacidades.destroy', $capacidad->id) }}"
method="POST"
class="inline"
onsubmit="return false;">
@csrf
@method('DELETE')
<button type="button"
onclick="confirmarEliminacion(this)"
class="text-red-600 hover:text-red-900">
<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); // Tiempo para remover el elemento después de la transición
}
}, 3000); // Tiempo en milisegundos antes de comenzar a desaparecer
function confirmarEliminacion(button) {
Swal.fire({
title: '¿Estás seguro?',
text: "Esta acción no se puede deshacer",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
button.closest('form').onsubmit = null;
button.closest('form').submit();
}
});
}
</script>
@endsection

132
resources/views/capacidadesCrearEditar.blade.php

@ -0,0 +1,132 @@
@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($capacidad) ? 'Editar Capacidad' : 'Nueva Capacidad' }}
</h2>
<div class="h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas fa-database 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="capacidadForm"
action="{{ isset($capacidad) ? route('capacidades.update', $capacidad->id) : route('capacidades.store') }}"
method="POST">
@csrf
@if(isset($capacidad))
@method('PUT')
@endif
<div class="space-y-6">
<!-- Campo Cantidad -->
<div>
<label for="cantidad" class="block text-sm font-medium text-gray-700 mb-2">
Cantidad
</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-hashtag text-gray-400"></i>
</div>
<input type="number"
name="capacidad"
id="capacidad"
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($capacidad) ? $capacidad->capacidad : old('capacidad') }}"
placeholder="Ingrese la cantidad"
min="0"
required>
</div>
@error('capacidad')
<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('capacidades.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($capacidad) ? 'Actualizar' : 'Guardar' }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
function confirmarAccion() {
const esEdicion = {{ isset($capacidad) ? 'true' : 'false' }};
const cantidad = document.getElementById('cantidad').value.trim();
if (!cantidad) {
Swal.fire({
title: 'Error',
text: 'La cantidad es obligatoria',
icon: 'error',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Entendido'
});
return;
}
Swal.fire({
title: esEdicion ? '¿Editar capacidad?' : '¿Guardar capacidad?',
html: esEdicion ?
`¿Estás seguro de editar la capacidad a:<br><strong>${cantidad}</strong>?` :
`¿Estás seguro de guardar la capacidad:<br><strong>${cantidad}</strong>?`,
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: esEdicion ? 'Sí, editar' : 'Sí, guardar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
document.getElementById('capacidadForm').submit();
}
});
}
// Prevenir envío del formulario con Enter
document.getElementById('capacidadForm').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
confirmarAccion();
}
});
// Focus en el campo cantidad al cargar la página
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('cantidad').focus();
});
</script>
@endsection

99
resources/views/dashboard.blade.php

@ -0,0 +1,99 @@
@extends('layouts.dashboard')
@section('content')
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Tarjeta de Préstamos Activos -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">Préstamos Activos</h3>
<span class="text-blue-600 bg-blue-100 rounded-full p-2">
<i class="fas fa-book-reader"></i>
</span>
</div>
<p class="text-3xl font-bold text-gray-900">25</p>
<p class="text-sm text-gray-500 mt-2">↑ 12% desde el mes pasado</p>
</div>
<!-- Tarjeta de Usuarios Registrados -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">Usuarios Registrados</h3>
<span class="text-green-600 bg-green-100 rounded-full p-2">
<i class="fas fa-users"></i>
</span>
</div>
<p class="text-3xl font-bold text-gray-900">150</p>
<p class="text-sm text-gray-500 mt-2">↑ 5% desde el mes pasado</p>
</div>
<!-- Tarjeta de Préstamos Vencidos -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">Préstamos Vencidos</h3>
<span class="text-red-600 bg-red-100 rounded-full p-2">
<i class="fas fa-exclamation-circle"></i>
</span>
</div>
<p class="text-3xl font-bold text-gray-900">3</p>
<p class="text-sm text-gray-500 mt-2">↓ 2% desde el mes pasado</p>
</div>
<!-- Tarjeta de Préstamos del Mes -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">Préstamos del Mes</h3>
<span class="text-purple-600 bg-purple-100 rounded-full p-2">
<i class="fas fa-chart-line"></i>
</span>
</div>
<p class="text-3xl font-bold text-gray-900">42</p>
<p class="text-sm text-gray-500 mt-2">↑ 8% desde el mes pasado</p>
</div>
</div>
<!-- Sección de Actividad Reciente -->
<div class="mt-8 bg-white rounded-lg shadow">
<div class="p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Actividad Reciente</h2>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Usuario</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Acción</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Fecha</th>
<th class="px-6 py-3 bg-gray-50 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">
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" src="https://ui-avatars.com/api/?name=Juan+Pérez" alt="">
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Juan Pérez</div>
<div class="text-sm text-gray-500">juan@example.com</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Solicitó préstamo</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Hace 2 horas</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
Aprobado
</span>
</td>
</tr>
<!-- Más filas de actividad aquí -->
</tbody>
</table>
</div>
</div>
</div>
@endsection

215
resources/views/docentes.blade.php

@ -0,0 +1,215 @@
<!-- Start Generation Here -->
@extends('layouts.dashboard')
@section('content')
<!-- Agregar los CSS en el encabezado -->
<link rel="stylesheet" href="https://cdn.datatables.net/2.2.2/css/dataTables.dataTables.css">
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/3.2.2/css/buttons.dataTables.css">
<div class="container mx-auto px-4 py-6">
<!-- Encabezado -->
@if(session('success'))
<div id="success-message" class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
{{ session('success') }}
</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 Docentes</h2>
<a href="{{ route('docentes.create') }}"
class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 flex items-center gap-2">
<i class="fas fa-plus"></i>
Agregar
</a>
</div>
<div class="flex gap-2 mb-4">
<button onclick="copyToClipboard()" class="text-gray-600 hover:text-blue-600 p-2" title="Copiar">
<i class="fas fa-copy"></i>
</button>
<a href="{{ route('docentes.export', ['format' => 'csv']) }}" class="text-gray-600 hover:text-green-600 p-2" title="Exportar a CSV">
<i class="fas fa-file-csv"></i>
</a>
<a href="{{ route('docentes.export', ['format' => 'excel']) }}" class="text-gray-600 hover:text-green-700 p-2" title="Exportar a Excel">
<i class="fas fa-file-excel"></i>
</a>
<a href="{{ route('docentes.export', ['format' => 'pdf']) }}" class="text-gray-600 hover:text-red-600 p-2" title="Exportar a PDF">
<i class="fas fa-file-pdf"></i>
</a>
<button onclick="window.print()" class="text-gray-600 hover:text-gray-800 p-2" title="Imprimir">
<i class="fas fa-print"></i>
</button>
</div>
<!-- Barra de búsqueda en su propia sección -->
<div class="p-4 border-b border-gray-200 bg-gray-50">
<form action="{{ route('docentes.index') }}" method="GET" class="flex gap-2">
<div class="relative w-full sm:w-64">
<input type="text"
name="busqueda"
placeholder="Buscar docente..."
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
</button>
@if(request('busqueda'))
<a href="{{ route('docentes.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 id="docentes-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">Teléfono</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Correo</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">Materia</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($docentes as $docente)
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $docente->id }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<i class="fas fa-user text-blue-500 mr-2"></i>
{{ $docente->nombre }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">{{ $docente->telefono }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">{{ $docente->correo }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">{{ $docente->tipo_licencia }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">{{ $docente->materia }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $docente->status ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' }}">
{{ $docente->status ? 'Activo' : 'Inactivo' }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<div class="flex gap-2">
<a href="{{ route('docentes.edit', $docente->id) }}" class="text-blue-600 hover:text-blue-900">
<i class="fas fa-edit"></i>
</a>
<a href="{{ route('docentes.toggle-status', $docente->id) }}"
class="{{ $docente->status ? 'text-red-600 hover:text-red-900' : 'text-green-600 hover:text-green-900' }}">
<i class="fas {{ $docente->status ? 'fa-ban' : 'fa-check' }}"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<!-- Agregar los scripts necesarios -->
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.datatables.net/2.2.2/js/dataTables.js"></script>
<script src="https://cdn.datatables.net/buttons/3.2.2/js/dataTables.buttons.js"></script>
<script src="https://cdn.datatables.net/buttons/3.2.2/js/buttons.dataTables.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/buttons/3.2.2/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/3.2.2/js/buttons.print.min.js"></script>
<script>
function confirmarEdicion(url) {
Swal.fire({
title: '¿Editar docente?',
text: "¿Estás seguro de que deseas editar este docente?",
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí, editar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
window.location.href = url;
}
});
}
function confirmarEliminacion(button) {
Swal.fire({
title: '¿Estás seguro?',
text: "Esta acción no se puede deshacer",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
button.closest('form').onsubmit = null;
button.closest('form').submit();
}
});
}
document.addEventListener('DOMContentLoaded', function() {
var message = document.getElementById('success-message');
if (message) {
setTimeout(function() {
message.style.transition = 'opacity 0.5s ease';
message.style.opacity = '0';
setTimeout(function() {
message.remove();
}, 500);
}, 3000);
}
});
// Inicializar DataTable con botones
new DataTable('#docentes-table', {
layout: {
topStart: {
buttons: ['copy', 'csv', 'excel', 'pdf']
}
}
});
function copyToClipboard() {
const table = document.querySelector('table');
const range = document.createRange();
range.selectNode(table);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
document.execCommand('copy');
window.getSelection().removeAllRanges();
// Mostrar mensaje de éxito
Swal.fire({
icon: 'success',
title: 'Copiado',
text: 'La tabla ha sido copiada al portapapeles',
timer: 1500,
showConfirmButton: false
});
}
</script>
@endsection
<!-- End Generation Here -->

71
resources/views/docentesCrearEditar.blade.php

@ -0,0 +1,71 @@
@extends('layouts.dashboard')
@section('content')
<div class="container mx-auto px-4 py-6">
<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">{{ isset($docente) ? 'Editar Docente' : 'Crear Docente' }}</h2>
</div>
<div class="p-4">
<form action="{{ isset($docente) ? route('docentes.update', $docente->id) : route('docentes.store') }}" method="POST">
@csrf
@if(isset($docente))
@method('PUT')
@endif
<div class="grid grid-cols-1 gap-6">
<div>
<label for="nombre" class="block text-sm font-medium text-gray-700">Nombre</label>
<input type="text" name="nombre" id="nombre" value="{{ old('nombre', $docente->nombre ?? '') }}" class="mt-1 block w-full border border-gray-300 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label for="telefono" class="block text-sm font-medium text-gray-700">Teléfono</label>
<input type="text" name="telefono" id="telefono" value="{{ old('telefono', $docente->telefono ?? '') }}" class="mt-1 block w-full border border-gray-300 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label for="correo" class="block text-sm font-medium text-gray-700">Correo</label>
<input type="email" name="correo" id="correo" value="{{ old('correo', $docente->correo ?? '') }}" class="mt-1 block w-full border border-gray-300 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
</div>
<div class="mb-4">
<label for="tipo_licencia" class="block text-sm font-medium text-gray-700 mb-2">
Tipo de Licencia
</label>
<div class="relative rounded-md shadow-sm">
<select name="tipo_licencia"
id="tipo_licencia"
class="block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
required>
<option value="">Seleccione un tipo de licencia</option>
<option value="A" {{ isset($docente) && $docente->tipo_licencia == 'A' ? 'selected' : '' }}>Licencia A</option>
<option value="B" {{ isset($docente) && $docente->tipo_licencia == 'B' ? 'selected' : '' }}>Licencia B</option>
<option value="C" {{ isset($docente) && $docente->tipo_licencia == 'C' ? 'selected' : '' }}>Licencia C</option>
</select>
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
<i class="fas fa-id-card text-gray-400"></i>
</div>
</div>
@error('tipo_licencia')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="materia" class="block text-sm font-medium text-gray-700">Materia</label>
<select name="materia" id="materia" class="mt-1 block w-full border border-gray-300 rounded-lg shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<option value="">Seleccione una materia</option>
<option value="Matemáticas" {{ old('materia', $docente->materia ?? '') == 'Matemáticas' ? 'selected' : '' }}>Matemáticas</option>
<option value="Programación" {{ old('materia', $docente->materia ?? '') == 'Programación' ? 'selected' : '' }}>Programación</option>
<option value="Base de datos" {{ old('materia', $docente->materia ?? '') == 'Base de datos' ? 'selected' : '' }}>Base de datos</option>
<option value="Sistemas Operativos" {{ old('materia', $docente->materia ?? '') == 'Sistemas Operativos' ? 'selected' : '' }}>Sistemas Operativos</option>
<option value="Redes" {{ old('materia', $docente->materia ?? '') == 'Redes' ? 'selected' : '' }}>Redes</option>
</select>
</div>
</div>
<div class="mt-6 flex justify-end">
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600">
{{ isset($docente) ? 'Actualizar' : 'Crear' }}
</button>
</div>
</form>
</div>
</div>
</div>
@endsection

47
resources/views/exports/docentes.blade.php

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Docentes</title>
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h2>Lista de Docentes</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>Nombre</th>
<th>Teléfono</th>
<th>Correo</th>
<th>Tipo de Licencia</th>
<th>Materia</th>
</tr>
</thead>
<tbody>
@foreach($docentes as $docente)
<tr>
<td>{{ $docente->id }}</td>
<td>{{ $docente->nombre }}</td>
<td>{{ $docente->telefono }}</td>
<td>{{ $docente->correo }}</td>
<td>{{ $docente->tipo_licencia }}</td>
<td>{{ $docente->materia }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

70
resources/views/exports/marcas-pdf.blade.php

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<title>Lista de Marcas</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 12px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
.header {
margin-bottom: 20px;
}
.footer {
margin-top: 20px;
text-align: right;
font-size: 10px;
}
</style>
</head>
<body>
<div class="header">
<h1>Lista de Marcas</h1>
<p>Fecha de generación: {{ date('d/m/Y H:i:s') }}</p>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Marca</th>
<th>Estado</th>
<th>Fecha de Creación</th>
<th>Última Actualización</th>
</tr>
</thead>
<tbody>
@foreach($marcas as $marca)
<tr>
<td>{{ $marca->id }}</td>
<td>{{ $marca->marca }}</td>
<td>{{ $marca->eliminado == 0 ? 'Activo' : 'Inactivo' }}</td>
<td>{{ $marca->created_at->format('d/m/Y H:i:s') }}</td>
<td>{{ $marca->updated_at->format('d/m/Y H:i:s') }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="footer">
<p>Página {{ $loop->iteration }} de {{ $loop->count }}</p>
</div>
</body>
</html>

76
resources/views/exports/prestamos-pdf.blade.php

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<title>Lista de Préstamos</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 12px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
.header {
margin-bottom: 20px;
}
.footer {
margin-top: 20px;
text-align: right;
font-size: 10px;
}
</style>
</head>
<body>
<div class="header">
<h1>Lista de Préstamos</h1>
<p>Fecha de generación: {{ date('d/m/Y H:i:s') }}</p>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Solicitante</th>
<th>Destino</th>
<th>Salida</th>
<th>Llegada</th>
<th>Motivo</th>
<th>Domicilio</th>
<th>Personas</th>
<th>Chofer</th>
<th>Estado</th>
</tr>
</thead>
<tbody>
@foreach($prestamos as $prestamo)
<tr>
<td>{{ $prestamo->id }}</td>
<td>{{ $prestamo->nombre_solicitante }}</td>
<td>{{ $prestamo->destino }}</td>
<td>{{ $prestamo->fecha_hora_salida }}</td>
<td>{{ $prestamo->fecha_hora_llegada }}</td>
<td>{{ $prestamo->motivo }}</td>
<td>{{ $prestamo->domicilio }}</td>
<td>{{ $prestamo->numero_personas }}</td>
<td>{{ $prestamo->chofer ? 'Sí' : 'No' }}</td>
<td>{{ $prestamo->eliminado == 0 ? 'Activo' : 'Inactivo' }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

63
resources/views/exports/tiposLicencias-pdf.blade.php

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<title>Tipos de Licencias</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;
}
.status-active {
color: green;
}
.status-inactive {
color: red;
}
</style>
</head>
<body>
<div class="header">
<h1>Reporte de Tipos de Licencias</h1>
<p>Fecha de generación: {{ date('d/m/Y H:i:s') }}</p>
</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Tipo de Licencia</th>
<th>Estado</th>
<th>Fecha de Creación</th>
</tr>
</thead>
<tbody>
@foreach($tiposLicencias as $licencia)
<tr>
<td>{{ $licencia->id }}</td>
<td>{{ $licencia->tipoLicencia }}</td>
<td class="{{ $licencia->eliminado == 1 ? 'status-active' : 'status-inactive' }}">
{{ $licencia->eliminado == 1 ? 'Activo' : 'Inactivo' }}
</td>
<td>{{ $licencia->created_at->format('d/m/Y') }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

75
resources/views/exports/tipos_vehiculos_pdf.blade.php

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<title>Tipos de Vehículos</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;
}
.status-active {
color: green;
}
.status-inactive {
color: red;
}
</style>
</head>
<body>
<div class="header">
<h1>Reporte de Tipos de Vehículos</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 Combustible</th>
<th>Estado</th>
<th>Fecha de Creación</th>
</tr>
</thead>
<tbody>
@foreach($tiposVeiculos as $vehiculo)
<tr>
<td>{{ $vehiculo->id }}</td>
<td>{{ $vehiculo->nombre }}</td>
<td>
@if($vehiculo->tipo_combustible == 'gasolina_verde')
Gasolina Verde
@elseif($vehiculo->tipo_combustible == 'gasolina_roja')
Gasolina Roja
@elseif($vehiculo->tipo_combustible == 'diesel')
Diesel
@else
No especificado
@endif
</td>
<td class="{{ $vehiculo->status ? 'status-active' : 'status-inactive' }}">
{{ $vehiculo->status ? 'Activo' : 'Inactivo' }}
</td>
<td>{{ $vehiculo->created_at->format('d/m/Y') }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

48
resources/views/exports/usuarios-pdf.blade.php

@ -0,0 +1,48 @@
<!-- resources/views/exports/usuarios-pdf.blade.php -->
<!DOCTYPE html>
<html>
<head>
<title>Lista de Usuarios</title>
<style>
/* Estilos opcionales para el PDF */
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 8px;
text-align: left;
}
</style>
</head>
<body>
<h1>Lista de Usuarios</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Nombre</th>
<th>Email</th>
<th>Apellido</th>
<th>Puesto</th>
<th>Carrera</th>
<th>Teléfono</th>
</tr>
</thead>
<tbody>
@foreach($usuarios as $usuario)
<tr>
<td>{{ $usuario->id }}</td>
<td>{{ $usuario->name }}</td>
<td>{{ $usuario->email }}</td>
<td>{{ $usuario->apellido }}</td>
<td>{{ $usuario->puesto }}</td>
<td>{{ $usuario->carrera }}</td>
<td>{{ $usuario->telefono }}</td>
</tr>
@endforeach
</tbody>
</table>
</body>
</html>

273
resources/views/inicial.blade.php

@ -1,273 +0,0 @@
@extends('layouts.plantilla')
@section('titulo')
Inicio
@endsection
@section('contenido')
<!-- Sale & Revenue Start -->
<div class="container-fluid pt-4 px-4">
<div class="row g-4">
<div class="col-sm-6 col-xl-3">
<div class="bg-light rounded d-flex align-items-center justify-content-between p-4">
<i class="fa fa-chart-line fa-3x text-primary"></i>
<div class="ms-3">
<p class="mb-2">Today Sale</p>
<h6 class="mb-0">$1234</h6>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="bg-light rounded d-flex align-items-center justify-content-between p-4">
<i class="fa fa-chart-bar fa-3x text-primary"></i>
<div class="ms-3">
<p class="mb-2">Total Sale</p>
<h6 class="mb-0">$1234</h6>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="bg-light rounded d-flex align-items-center justify-content-between p-4">
<i class="fa fa-chart-area fa-3x text-primary"></i>
<div class="ms-3">
<p class="mb-2">Today Revenue</p>
<h6 class="mb-0">$1234</h6>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="bg-light rounded d-flex align-items-center justify-content-between p-4">
<i class="fa fa-chart-pie fa-3x text-primary"></i>
<div class="ms-3">
<p class="mb-2">Total Revenue</p>
<h6 class="mb-0">$1234</h6>
</div>
</div>
</div>
</div>
</div>
<!-- Sale & Revenue End -->
<!-- Sales Chart Start -->
<div class="container-fluid pt-4 px-4">
<div class="row g-4">
<div class="col-sm-12 col-xl-6">
<div class="bg-light text-center rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-4">
<h6 class="mb-0">Worldwide Sales</h6>
<a href="">Show All</a>
</div>
<canvas id="worldwide-sales"></canvas>
</div>
</div>
<div class="col-sm-12 col-xl-6">
<div class="bg-light text-center rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-4">
<h6 class="mb-0">Salse & Revenue</h6>
<a href="">Show All</a>
</div>
<canvas id="salse-revenue"></canvas>
</div>
</div>
</div>
</div>
<!-- Sales Chart End -->
<!-- Recent Sales Start -->
<div class="container-fluid pt-4 px-4">
<div class="bg-light text-center rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-4">
<h6 class="mb-0">Recent Salse</h6>
<a href="">Show All</a>
</div>
<div class="table-responsive">
<table class="table text-start align-middle table-bordered table-hover mb-0">
<thead>
<tr class="text-dark">
<th scope="col"><input class="form-check-input" type="checkbox"></th>
<th scope="col">Date</th>
<th scope="col">Invoice</th>
<th scope="col">Customer</th>
<th scope="col">Amount</th>
<th scope="col">Status</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="form-check-input" type="checkbox"></td>
<td>01 Jan 2045</td>
<td>INV-0123</td>
<td>Jhon Doe</td>
<td>$123</td>
<td>Paid</td>
<td><a class="btn btn-sm btn-primary" href="">Detail</a></td>
</tr>
<tr>
<td><input class="form-check-input" type="checkbox"></td>
<td>01 Jan 2045</td>
<td>INV-0123</td>
<td>Jhon Doe</td>
<td>$123</td>
<td>Paid</td>
<td><a class="btn btn-sm btn-primary" href="">Detail</a></td>
</tr>
<tr>
<td><input class="form-check-input" type="checkbox"></td>
<td>01 Jan 2045</td>
<td>INV-0123</td>
<td>Jhon Doe</td>
<td>$123</td>
<td>Paid</td>
<td><a class="btn btn-sm btn-primary" href="">Detail</a></td>
</tr>
<tr>
<td><input class="form-check-input" type="checkbox"></td>
<td>01 Jan 2045</td>
<td>INV-0123</td>
<td>Jhon Doe</td>
<td>$123</td>
<td>Paid</td>
<td><a class="btn btn-sm btn-primary" href="">Detail</a></td>
</tr>
<tr>
<td><input class="form-check-input" type="checkbox"></td>
<td>01 Jan 2045</td>
<td>INV-0123</td>
<td>Jhon Doe</td>
<td>$123</td>
<td>Paid</td>
<td><a class="btn btn-sm btn-primary" href="">Detail</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Recent Sales End -->
<!-- Widgets Start -->
<div class="container-fluid pt-4 px-4">
<div class="row g-4">
<div class="col-sm-12 col-md-6 col-xl-4">
<div class="h-100 bg-light rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-2">
<h6 class="mb-0">Messages</h6>
<a href="">Show All</a>
</div>
<div class="d-flex align-items-center border-bottom py-3">
<img class="rounded-circle flex-shrink-0" src="img/user.jpg" alt="" style="width: 40px; height: 40px;">
<div class="w-100 ms-3">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-0">Jhon Doe</h6>
<small>15 minutes ago</small>
</div>
<span>Short message goes here...</span>
</div>
</div>
<div class="d-flex align-items-center border-bottom py-3">
<img class="rounded-circle flex-shrink-0" src="img/user.jpg" alt="" style="width: 40px; height: 40px;">
<div class="w-100 ms-3">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-0">Jhon Doe</h6>
<small>15 minutes ago</small>
</div>
<span>Short message goes here...</span>
</div>
</div>
<div class="d-flex align-items-center border-bottom py-3">
<img class="rounded-circle flex-shrink-0" src="img/user.jpg" alt="" style="width: 40px; height: 40px;">
<div class="w-100 ms-3">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-0">Jhon Doe</h6>
<small>15 minutes ago</small>
</div>
<span>Short message goes here...</span>
</div>
</div>
<div class="d-flex align-items-center pt-3">
<img class="rounded-circle flex-shrink-0" src="img/user.jpg" alt="" style="width: 40px; height: 40px;">
<div class="w-100 ms-3">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-0">Jhon Doe</h6>
<small>15 minutes ago</small>
</div>
<span>Short message goes here...</span>
</div>
</div>
</div>
</div>
<div class="col-sm-12 col-md-6 col-xl-4">
<div class="h-100 bg-light rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-4">
<h6 class="mb-0">Calender</h6>
<a href="">Show All</a>
</div>
<div id="calender"></div>
</div>
</div>
<div class="col-sm-12 col-md-6 col-xl-4">
<div class="h-100 bg-light rounded p-4">
<div class="d-flex align-items-center justify-content-between mb-4">
<h6 class="mb-0">To Do List</h6>
<a href="">Show All</a>
</div>
<div class="d-flex mb-2">
<input class="form-control bg-transparent" type="text" placeholder="Enter task">
<button type="button" class="btn btn-primary ms-2">Add</button>
</div>
<div class="d-flex align-items-center border-bottom py-2">
<input class="form-check-input m-0" type="checkbox">
<div class="w-100 ms-3">
<div class="d-flex w-100 align-items-center justify-content-between">
<span>Short task goes here...</span>
<button class="btn btn-sm"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
<div class="d-flex align-items-center border-bottom py-2">
<input class="form-check-input m-0" type="checkbox">
<div class="w-100 ms-3">
<div class="d-flex w-100 align-items-center justify-content-between">
<span>Short task goes here...</span>
<button class="btn btn-sm"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
<div class="d-flex align-items-center border-bottom py-2">
<input class="form-check-input m-0" type="checkbox" checked>
<div class="w-100 ms-3">
<div class="d-flex w-100 align-items-center justify-content-between">
<span><del>Short task goes here...</del></span>
<button class="btn btn-sm text-primary"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
<div class="d-flex align-items-center border-bottom py-2">
<input class="form-check-input m-0" type="checkbox">
<div class="w-100 ms-3">
<div class="d-flex w-100 align-items-center justify-content-between">
<span>Short task goes here...</span>
<button class="btn btn-sm"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
<div class="d-flex align-items-center pt-2">
<input class="form-check-input m-0" type="checkbox">
<div class="w-100 ms-3">
<div class="d-flex w-100 align-items-center justify-content-between">
<span>Short task goes here...</span>
<button class="btn btn-sm"><i class="fa fa-times"></i></button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Widgets End -->
@endsection

24
resources/views/layouts/app.blade.php

@ -14,7 +14,9 @@
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet"> <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
<!-- Scripts --> <!-- Scripts -->
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<script src="{{ asset('js/app.js') }}" defer></script>
</head> </head>
<body> <body>
<div id="app"> <div id="app">
@ -49,22 +51,14 @@
</li> </li>
@endif @endif
@else @else
<li class="nav-item dropdown"> <li class="nav-item d-flex align-items-center">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> <span class="me-2">{{ Auth::user()->name }}</span>
{{ Auth::user()->name }} <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: inline; margin: 0;">
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf @csrf
<button type="submit" class="btn btn-link text-danger p-0 m-0 align-baseline" title="Cerrar Sesión" style="font-size: 1.2rem; vertical-align: middle;">
<i class="fas fa-sign-out-alt"></i>
</button>
</form> </form>
</div>
</li> </li>
@endguest @endguest
</ul> </ul>

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

@ -0,0 +1,277 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - PrestamosTec</title>
<link rel="icon" href="{{ asset('css/logo.png') }}">
<!-- Tailwind CSS desde CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Alpine.js -->
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- En el head, después de los otros scripts -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Agregamos animate.css para más animaciones -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<style>
/* Animaciones personalizadas */
.nav-item-hover {
@apply transition-all duration-300 ease-in-out transform hover:translate-x-2;
}
.sidebar {
@apply transition-all duration-300 ease-in-out;
}
.menu-item {
@apply transition-colors duration-200 ease-in-out;
}
</style>
</head>
<body class="bg-gray-50">
<div class="min-h-screen flex">
<!-- Sidebar modernizado -->
<aside class="sidebar bg-gradient-to-b from-[#1E40AF] to-[#6B5B9A] text-white w-64 min-h-screen px-4 py-6 hidden md:block shadow-xl">
<div class="flex items-center justify-center mb-12">
<span class="text-2xl font-bold tracking-wider animate__animated animate__fadeIn">PrestamosTecmm</span>
</div>
<nav>
<ul class="space-y-4">
<!-- Inicio -->
<li>
<a href="/dashboard" 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('dashboard') ? 'bg-white/20' : '' }}">
<i class="fas fa-home text-white/80"></i>
<span class="font-light">Inicio</span>
</a>
</li>
<!-- Préstamos -->
<li x-data="{ open: false }" class="relative">
<button @click="open = !open"
class="nav-item-hover flex items-center justify-between w-full px-4 py-3 rounded-lg hover:bg-white/10 backdrop-blur-sm {{ request()->is('prestamos*') ? 'bg-white/20' : '' }}">
<div class="flex items-center space-x-3">
<i class="fas fa-book text-white/80"></i>
<span class="font-light">Préstamos</span>
</div>
<i class="fas fa-chevron-down text-sm transition-transform duration-200"
:class="{ 'transform rotate-180': open }"></i>
</button>
<!-- Submenú de Préstamos -->
<ul x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 transform -translate-y-2"
x-transition:enter-end="opacity-100 transform translate-y-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform translate-y-0"
x-transition:leave-end="opacity-0 transform -translate-y-2"
class="pl-4 mt-2 space-y-1 text-sm">
<li>
<a href="{{ route('prestamos.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' : '' }}">
<i class="fas fa-plus text-white/80"></i>
<span class="font-light">Nuevo Préstamo</span>
</a>
</li>
<li>
<a href="/prestamos/pendientes" 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('prestamos/pendientes') ? 'bg-white/20' : '' }}">
<i class="fas fa-clock text-white/80"></i>
<span class="font-light">Préstamos Pendientes</span>
</a>
</li>
<li>
<a href="/prestamos/rechazados" 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('prestamos/rechazados') ? 'bg-white/20' : '' }}">
<i class="fas fa-times text-white/80"></i>
<span class="font-light">Préstamos Rechazados</span>
</a>
</li>
<li>
<a href="/prestamos/aceptados" 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('prestamos/aceptados') ? 'bg-white/20' : '' }}">
<i class="fas fa-check text-white/80"></i>
<span class="font-light">Préstamos Aceptados</span>
</a>
</li>
<li>
<a href="/prestamos/historial" 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('prestamos/historial') ? 'bg-white/20' : '' }}">
<i class="fas fa-history text-white/80"></i>
<span class="font-light">Historial</span>
</a>
</li>
</ul>
</li>
<!-- Usuarios -->
<li>
<a href="/usuarios" 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('usuarios') ? 'bg-white/20' : '' }}">
<i class="fas fa-users text-white/80"></i>
<span class="font-light">Usuarios</span>
</a>
</li>
<!-- Mantenimiento -->
<li>
<a href="/maintenance" 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('maintenance') ? 'bg-white/20' : '' }}">
<i class="fas fa-tools text-white/80"></i>
<span class="font-light">Mantenimiento</span>
</a>
</li>
<!-- Configuración con Submenú -->
<li x-data="{ open: false }" class="relative">
<button @click="open = !open"
class="nav-item-hover flex items-center justify-between w-full px-4 py-3 rounded-lg hover:bg-white/10 backdrop-blur-sm">
<div class="flex items-center space-x-2">
<i class="fas fa-cog text-white/80"></i>
<span class="font-light">Configuración</span>
</div>
<i class="fas fa-chevron-down text-sm transition-transform duration-200"
:class="{ 'transform rotate-180': open }"></i>
</button>
<!-- Submenú de Configuración -->
<ul x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 transform -translate-y-2"
x-transition:enter-end="opacity-100 transform translate-y-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform translate-y-0"
x-transition:leave-end="opacity-0 transform -translate-y-2"
class="pl-4 mt-2 space-y-1 text-sm">
<!-- Marca -->
<li>
<a href="{{ route('marca.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('marca*') ? 'bg-white/20' : '' }}">
<i class="fas fa-trademark text-white/80"></i>
<span class="font-light">Marca</span>
</a>
</li>
<!-- Tipos -->
<li>
<a href="{{ route('vehiculos.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('vehiculos*') ? 'bg-white/20' : '' }}">
<i class="fas fa-car text-white/80"></i>
<span class="font-light">Tipos de Vehiculos</span>
</a>
</li>
<!-- 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' : '' }}">
<i class="fas fa-id-card text-white/80"></i>
<span class="font-light">Tipos de Licencia</span>
</a>
</li>
<!-- Capacidad -->
<li>
<a href="{{ route('capacidades.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('capacidades*') ? 'bg-white/20' : '' }}">
<i class="fas fa-database text-white/80"></i>
<span class="font-light">Capacidad</span>
</a>
</li>
<li>
<a href="/configuracion/capacidad" 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('configuracion/capacidad') ? 'bg-white/20' : '' }}">
<i class="fas fa-gas-pump text-white/80"></i>
<span class="font-light">Tipo de Gasolina</span>
</a>
</li>
<!-- Puestos -->
<li x-data="{ openPuestos: false }" class="relative">
<button @click="openPuestos = !openPuestos"
class="nav-item-hover flex items-center justify-between w-full px-4 py-3 rounded-lg hover:bg-white/10 backdrop-blur-sm">
<div class="flex items-center space-x-2">
<i class="fas fa-user-tie text-white/80"></i>
<span class="font-light">Puestos</span>
</div>
<i class="fas fa-chevron-right text-xs"
:class="{ 'transform rotate-90': openPuestos }"></i>
</button>
<!-- Submenú de Puestos -->
<ul x-show="openPuestos"
class="pl-4 mt-1 space-y-1">
<li>
<a href="{{ route('docentes.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('docentes*') ? 'bg-white/20' : '' }}">
<i class="fas fa-chalkboard-teacher text-white/80"></i>
<span class="font-light">Docentes</span>
</a>
</li>
<li>
<a href="/configuracion/puestos/choferes" 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('configuracion/puestos/choferes') ? 'bg-white/20' : '' }}">
<i class="fas fa-car text-white/80"></i>
<span class="font-light">Choferes</span>
</a>
</li>
<li>
<a href="/configuracion/puestos/admin" 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('configuracion/puestos/admin') ? 'bg-white/20' : '' }}">
<i class="fas fa-user-shield text-white/80"></i>
<span class="font-light">Administradores</span>
</a>
</li>
</ul>
</li>
<!-- Estatus -->
<li>
<a href="/configuracion/estatus" 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('configuracion/estatus') ? 'bg-white/20' : '' }}">
<i class="fas fa-toggle-on text-white/80"></i>
<span class="font-light">Estatus</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
</aside>
<div class="flex-1 flex flex-col">
<!-- Navbar modernizado -->
<header class="bg-white/80 backdrop-blur-md shadow-sm">
<div class="flex items-center justify-between px-8 py-4">
<div class="flex items-center bg-gray-100 rounded-full px-3 py-1 shadow-sm">
<img src="https://ui-avatars.com/api/?name={{ Auth::user()->name }}&background=E5E7EB&color=374151&rounded=true&size=32" alt="Avatar" class="w-8 h-8 rounded-full mr-2">
<span class="font-semibold text-gray-800">{{ Auth::user()->name }}</span>
</div>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: inline; margin: 0;">
@csrf
<button type="submit" class="flex items-center text-red-600 hover:text-red-800 font-semibold px-3 py-1 rounded transition-colors duration-150" title="Cerrar Sesión">
<i class="fas fa-sign-out-alt mr-2"></i> Cerrar Sesión
</button>
</form>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 p-8 animate__animated animate__fadeIn">
@yield('content')
</main>
<!-- Footer modernizado -->
<footer class="bg-white/80 backdrop-blur-md shadow-sm mt-auto">
<div class="max-w-7xl mx-auto py-4 px-8">
<div class="flex justify-between items-center">
<p class="text-gray-600 text-sm">&copy; 2024 PrestamosTecmm</p>
<div class="flex space-x-6">
<a href="#" class="text-gray-400 hover:text-[#1E40AF] transition-colors duration-200">
<i class="fab fa-facebook"></i>
</a>
<a href="#" class="text-gray-400 hover:text-[#1E40AF] transition-colors duration-200">
<i class="fab fa-twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-[#1E40AF] transition-colors duration-200">
<i class="fab fa-instagram"></i>
</a>
</div>
</div>
</div>
</footer>
</div>
</div>
</body>
</html>

17
resources/views/layouts/footer.blade.php

@ -1,17 +0,0 @@
<!-- Footer Start -->
<div class="container-fluid pt-4 px-4">
<div class="bg-light rounded-top p-4">
<div class="row">
<div class="col-12 col-sm-6 text-center text-sm-start">
&copy; <a href="#">Your Site Name</a>, All Right Reserved.
</div>
<div class="col-12 col-sm-6 text-center text-sm-end">
<!--/*** This template is free as long as you keep the footer author’s credit link/attribution link/backlink. If you'd like to use the template without the footer author’s credit link/attribution link/backlink, you can purchase the Credit Removal License from "https://htmlcodex.com/credit-removal". Thank you for your support. ***/-->
Designed By <a href="https://htmlcodex.com">HTML Codex</a>
</br>
Distributed By <a class="border-bottom" href="https://themewagon.com" target="_blank">ThemeWagon</a>
</div>
</div>
</div>
</div>
<!-- Footer End -->

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save