diff --git a/app/Exports/UsuariosExport.php b/app/Exports/UsuariosExport.php index f7b83e5..f73f6f9 100644 --- a/app/Exports/UsuariosExport.php +++ b/app/Exports/UsuariosExport.php @@ -10,23 +10,37 @@ class UsuariosExport implements FromCollection, WithHeadings { public function collection() { - return User::select( 'name', 'email','apellido', - 'puesto', - 'carrera', - 'telefono',)->get(); + $usuarios = User::with(['puesto', 'tipo', 'departamento'])->get(); + + $data = []; + $contador = 1; + foreach ($usuarios as $usuario) { + $data[] = [ + 'No.' => $contador++, + 'Nombre' => $usuario->name, + 'Correo' => $usuario->email, + 'Apellido' => $usuario->apellido, + 'Puesto' => $usuario->puesto->nombre ?? '', + 'Tipo' => $usuario->tipo->nombre ?? '', + 'Departamento' => $usuario->departamento->departamento ?? '', + 'Teléfono' => $usuario->telefono, + ]; + } + + return collect($data); } public function headings(): array { return [ - 'nombre', - 'correo', - 'apellido', - 'puesto', - 'carrera', - 'telefono', - 'Fecha de Creación', - 'Última Actualización' + 'No.', + 'Nombre', + 'Correo', + 'Apellido', + 'Puesto', + 'Tipo', + 'Departamento', + 'Teléfono', ]; } } diff --git a/app/Exports/puestosExport.php b/app/Exports/puestosExport.php new file mode 100644 index 0000000..54f3270 --- /dev/null +++ b/app/Exports/puestosExport.php @@ -0,0 +1,44 @@ +puestos = $puestos; + } + + public function collection() + { + // Obtén los puestos + $puestos = $this->puestos ?: Puesto::where('eliminado', 0)->get(['nombre']); + + // Construye la colección con número consecutivo + $data = []; + $contador = 1; + foreach ($puestos as $puesto) { + $data[] = [ + 'ID' => $contador++, + 'Nombre del Puesto' => $puesto->nombre, + ]; + } + + return collect($data); + } + + public function headings(): array + { + return [ + 'ID', + 'Nombre del Puesto', + ]; + } +} diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php new file mode 100644 index 0000000..6d39e23 --- /dev/null +++ b/app/Http/Controllers/AdminController.php @@ -0,0 +1,13 @@ +eliminado = 1; // Cambia el estado a inactivo - $despartamento->save(); // Guarda los cambios + $despartamento = despartamento::findOrFail($id); + \App\Models\User::where('departamento_id', $id)->update(['departamento_id' => null]); + $despartamento->eliminado = 1; + $despartamento->save(); - return redirect()->route('despartamentos.index')->with('success', 'Departamento inactivado correctamente.'); + return redirect()->route('despartamentos.index') + ->with('success', 'Departamento eliminado exitosamente. Los usuarios afectados necesitan ser reasignados.'); } public function exportExcel() diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 8c90f0f..190b646 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -23,8 +23,36 @@ class HomeController extends Controller */ public function index() { + $user = auth()->user(); - return view('dashboard'); + // Validar que el usuario tenga tipo asignado y que sea Administrador + if (!$user->tipo || $user->tipo->nombre !== 'Administrador') { + // Cerrar la sesión del usuario + auth()->logout(); + // Redirigir con mensaje de error + return redirect()->route('login')->with('error', 'No tienes permisos para acceder al sistema. Solo los administradores pueden acceder en este momento.'); + } + // Notificaciones si el usuario no tiene puesto o departamento asignado + $notificaciones = []; + if (is_null($user->puesto_id)) { + $notificaciones[] = 'No tienes un puesto asignado. Contacta al administrador para que te asigne uno.'; + } + if (is_null($user->departamento_id)) { + $notificaciones[] = 'No tienes un departamento asignado. Contacta al administrador para que te asigne uno.'; + } + + // Si es administrador, mostrar el dashboard con datos reales + $adminData = [ + 'totalUsers' => \App\Models\User::count(), + 'totalPrestamos' => \App\Models\Prestamo::count(), + 'prestamosPendientes' => \App\Models\Prestamo::where('estado', 'pendiente')->count(), + 'prestamosAceptados' => \App\Models\Prestamo::where('estado', 'aceptado')->count(), + ]; + + return view('dashboard', [ + 'adminData' => $adminData, + 'notificaciones' => $notificaciones + ]); } } diff --git a/app/Http/Controllers/PuestoController.php b/app/Http/Controllers/PuestoController.php new file mode 100644 index 0000000..2268cba --- /dev/null +++ b/app/Http/Controllers/PuestoController.php @@ -0,0 +1,128 @@ +busqueda; + + if ($busqueda) { + $puestos = Puesto::where('nombre', 'LIKE', "%{$busqueda}%") + ->where('eliminado', 0) + ->get(); + + if ($puestos->isEmpty()) { + return redirect()->route('puestos.index') + ->with('error', 'No existe ningún puesto con el nombre "' . $busqueda . '". Por favor, inténtalo de nuevo.'); + } + } else { + $puestos = Puesto::where('eliminado', 0)->get(); + } + + return view('puestos', ['puestos' => $puestos]); + } + + public function create() + { + return view('puestosCrearEditar', ['puesto' => null]); + } + + public function store(Request $request) + { + $validated = $request->validate([ + 'nombre' => ['required', 'string', 'max:255'], + ], [ + 'nombre.required' => 'El campo nombre es obligatorio.', + 'nombre.string' => 'El campo nombre debe ser una cadena de texto.', + 'nombre.max' => 'El campo nombre no debe exceder 255 caracteres.', + ]); + $puesto = new Puesto($validated); + $puesto->eliminado = 0; + $puesto->save(); + + return redirect()->route('puestos.index') + ->with('success', 'Puesto creado exitosamente'); + } + + + public function edit($id) + { + $puesto = Puesto::findOrFail($id); + return view('puestosCrearEditar', ['puesto' => $puesto]); + } + + public function update(Request $request, $id) + { + $validated = $request->validate([ + 'nombre' => ['required', 'string', 'max:255'], + ], [ + 'nombre.required' => 'El campo nombre es obligatorio.', + 'nombre.string' => 'El campo nombre debe ser una cadena de texto.', + 'nombre.max' => 'El campo nombre no debe exceder 255 caracteres.', + ]); + + $puesto = Puesto::findOrFail($id); + $puesto->update($validated); + + return redirect()->route('puestos.index') + ->with('success', 'Puesto actualizado exitosamente'); + } + + public function destroy($id) + { + $puesto = Puesto::findOrFail($id); + \App\Models\User::where('puesto_id', $id)->update(['puesto_id' => null]); + $puesto->eliminado = 1; + $puesto->save(); + + return redirect()->route('puestos.index') + ->with('success', 'Puesto eliminado exitosamente. Los usuarios afectados necesitan ser reasignados.'); + } + + public function exportExcel() + { + return Excel::download(new PuestosExport, 'puestos.xlsx'); + } + + public function exportPDF() + { + $puestos = Puesto::where('eliminado', 0)->get(); + $pdf = PDF::loadView('exports.puestos', ['puestos' => $puestos]); + return $pdf->download('puestos.pdf'); + } + + public function export($format) + { + $puestos = Puesto::where('eliminado', 0) + ->orderBy('updated_at', 'desc') + ->get(); + + switch($format) { + case 'excel': + return Excel::download(new PuestosExport($puestos), 'puestos.xlsx'); + case 'pdf': + $pdf = PDF::loadView('exports.puestos', ['puestos' => $puestos]); + return $pdf->download('puestos.pdf'); + default: + return redirect()->back()->with('error', 'Formato no soportado'); + } + } + + public function toggleStatus($id) + { + $puesto = Puesto::findOrFail($id); + $puesto->eliminado = !$puesto->eliminado; + $puesto->save(); + + return redirect()->route('puestos.index') + ->with('success', 'Estado del puesto actualizado correctamente'); + } +} diff --git a/app/Http/Controllers/TipoController.php b/app/Http/Controllers/TipoController.php new file mode 100644 index 0000000..8f8bf32 --- /dev/null +++ b/app/Http/Controllers/TipoController.php @@ -0,0 +1,65 @@ + null, 'puestos' => $puestos, 'despartamentos'=> $despartamentos]); + return view('usuariosCrearEditar', ['usuario' => null, 'puestos' => $puestos, 'despartamentos'=> $despartamentos, 'tipos' => $tipos]); } /** @@ -50,24 +52,47 @@ class usuariosController extends Controller */ public function store(Request $request) { - // Validación de datos + // Validación de datos en español $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', - 'departamento_id' => 'required|exists:despartamentos,id', - 'telefono' => 'required|string|max:255', - 'password' => 'required|string|min:8|confirmed', + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], + 'apellido' => ['required', 'string', 'max:255'], + 'tipos_id' => ['required', 'exists:tipos,id'], + 'puesto_id' => ['required', 'exists:puestos,id'], + 'departamento_id' => ['required', 'exists:despartamentos,id'], + 'telefono' => ['required', 'string', 'max:255'], + 'password' => ['required', 'string', 'min:8', 'confirmed'], ], [ 'name.required' => 'El campo nombre es obligatorio.', - 'email.required' => 'El campo email es obligatorio.', - 'email.unique' => 'El email ya está registrado.', + 'name.string' => 'El campo nombre debe ser una cadena de texto.', + 'name.max' => 'El campo nombre no debe exceder 255 caracteres.', + + 'email.required' => 'El campo correo electrónico es obligatorio.', + 'email.string' => 'El campo correo electrónico debe ser una cadena de texto.', + 'email.email' => 'El campo correo electrónico debe ser una dirección de correo válida.', + 'email.max' => 'El campo correo electrónico no debe exceder 255 caracteres.', + 'email.unique' => 'El correo electrónico ya está registrado.', + 'apellido.required' => 'El campo apellido es obligatorio.', + 'apellido.string' => 'El campo apellido debe ser una cadena de texto.', + 'apellido.max' => 'El campo apellido no debe exceder 255 caracteres.', + + 'tipos_id.required' => 'El campo tipo es obligatorio.', + 'tipos_id.exists' => 'El tipo seleccionado no es válido.', + 'puesto_id.required' => 'El campo puesto es obligatorio.', + 'puesto_id.exists' => 'El puesto seleccionado no es válido.', + 'departamento_id.required' => 'El campo departamento es obligatorio.', + 'departamento_id.exists' => 'El departamento seleccionado no es válido.', + 'telefono.required' => 'El campo teléfono es obligatorio.', + 'telefono.string' => 'El campo teléfono debe ser una cadena de texto.', + 'telefono.max' => 'El campo teléfono no debe exceder 255 caracteres.', + 'password.required' => 'El campo contraseña es obligatorio.', + 'password.string' => 'El campo contraseña debe ser una cadena de texto.', + 'password.min' => 'La contraseña debe tener al menos 8 caracteres.', 'password.confirmed' => 'Las contraseñas no coinciden.', ]); @@ -76,6 +101,7 @@ class usuariosController extends Controller $usuario->name = $request->name; $usuario->email = $request->email; $usuario->apellido = $request->apellido; + $usuario->tipos_id = $request->tipos_id; $usuario->puesto_id = $request->puesto_id; $usuario->departamento_id = $request->departamento_id; $usuario->telefono = $request->telefono; @@ -101,7 +127,8 @@ class usuariosController extends Controller $user = User::findOrFail($id); $puestos = Puesto::all(); $despartamentos = Despartamento::all(); - return view('usuariosCrearEditar',['usuario' => $user, 'puestos' => $puestos,'despartamentos'=> $despartamentos]); // Asegúrate de que la clave sea 'usuario' + $tipos = Tipo::all(); + return view('usuariosCrearEditar',['usuario' => $user, 'puestos' => $puestos,'despartamentos'=> $despartamentos, 'tipos' => $tipos]); // Asegúrate de que la clave sea 'usuario' } /** @@ -109,24 +136,47 @@ class usuariosController extends Controller */ public function update(Request $request, $id) { - // Validación de datos + // Validación de datos (reglas y mensajes personalizados en español) $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', - 'departamento_id' => 'required|exists:despartamentos,id', - 'telefono' => 'required|string|max:255', - 'password' => 'required|string|min:8|confirmed', + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email,'.$id], + 'apellido' => ['required', 'string', 'max:255'], + 'tipos_id' => ['required', 'exists:tipos,id'], + 'puesto_id' => ['required', 'exists:puestos,id'], + 'departamento_id' => ['required', 'exists:despartamentos,id'], + 'telefono' => ['required', 'string', 'max:255'], + 'password' => ['nullable', 'string', 'min:8', 'confirmed'], ], [ 'name.required' => 'El campo nombre es obligatorio.', - 'email.required' => 'El campo email es obligatorio.', - 'email.unique' => 'El email ya está registrado.', + 'name.string' => 'El campo nombre debe ser una cadena de texto.', + 'name.max' => 'El campo nombre no debe exceder 255 caracteres.', + + 'email.required' => 'El campo correo electrónico es obligatorio.', + 'email.string' => 'El campo correo electrónico debe ser una cadena de texto.', + 'email.email' => 'El campo correo electrónico debe ser una dirección válida.', + 'email.max' => 'El campo correo electrónico no debe exceder 255 caracteres.', + 'email.unique' => 'El correo electrónico ya está registrado.', + 'apellido.required' => 'El campo apellido es obligatorio.', + 'apellido.string' => 'El campo apellido debe ser una cadena de texto.', + 'apellido.max' => 'El campo apellido no debe exceder 255 caracteres.', + + 'tipos_id.required' => 'El campo tipo es obligatorio.', + 'tipos_id.exists' => 'El tipo seleccionado no es válido.', + 'puesto_id.required' => 'El campo puesto es obligatorio.', + 'puesto_id.exists' => 'El puesto seleccionado no es válido.', + 'departamento_id.required' => 'El campo departamento es obligatorio.', + 'departamento_id.exists' => 'El departamento seleccionado no es válido.', + 'telefono.required' => 'El campo teléfono es obligatorio.', + 'telefono.string' => 'El campo teléfono debe ser una cadena de texto.', + 'telefono.max' => 'El campo teléfono no debe exceder 255 caracteres.', + 'password.required' => 'El campo contraseña es obligatorio.', + 'password.string' => 'El campo contraseña debe ser una cadena de texto.', + 'password.min' => 'La contraseña debe tener al menos 8 caracteres.', 'password.confirmed' => 'Las contraseñas no coinciden.', ]); @@ -135,6 +185,7 @@ class usuariosController extends Controller $usuario->name = $request->name; $usuario->email = $request->email; $usuario->apellido = $request->apellido; + $usuario->tipos_id = $request->tipos_id; $usuario->puesto_id = $request->puesto_id; $usuario->departamento_id = $request->departamento_id; $usuario->telefono = $request->telefono; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c34cdcf..4e233af 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -64,4 +64,9 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, ]; + + protected $routeMiddleware = [ + // ... otros middlewares + 'admin' => \App\Http\Middleware\AdminMiddleware::class, + ]; } diff --git a/app/Http/Middleware/AdminMiddleware.php b/app/Http/Middleware/AdminMiddleware.php new file mode 100644 index 0000000..40072de --- /dev/null +++ b/app/Http/Middleware/AdminMiddleware.php @@ -0,0 +1,24 @@ +check() || auth()->user()->tipo->nombre !== 'Administrador') { + return redirect('/')->with('error', 'No tienes permisos para acceder a esta página.'); + } + + return $next($request); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 57af47e..eafb383 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -23,6 +23,7 @@ class User extends Authenticatable 'name', 'email', 'apellido', + 'tipos_id', 'puesto_id', 'departamento_id', 'telefono', @@ -49,10 +50,7 @@ class User extends Authenticatable 'email_verified_at' => 'datetime', ]; - public function puesto():HasOne{ - return $this->hasOne(Puesto::class, 'id','puesto_id'); - } - public function despartamento():HasOne{ - return $this->hasOne(Despartamento::class, 'id','departamento_id'); - } + public function puesto() { return $this->belongsTo(\App\Models\Puesto::class, 'puesto_id'); } + public function tipo() { return $this->belongsTo(\App\Models\Tipo::class, 'tipos_id'); } + public function departamento() { return $this->belongsTo(\App\Models\Despartamento::class, 'departamento_id'); } } diff --git a/app/Models/puesto.php b/app/Models/puesto.php index 70b90a4..57088c9 100644 --- a/app/Models/puesto.php +++ b/app/Models/puesto.php @@ -8,4 +8,5 @@ use Illuminate\Database\Eloquent\Model; class puesto extends Model { use HasFactory; + protected $fillable = ['nombre', 'eliminado']; } diff --git a/app/Models/tipo.php b/app/Models/tipo.php new file mode 100644 index 0000000..d115002 --- /dev/null +++ b/app/Models/tipo.php @@ -0,0 +1,13 @@ + + */ +class TipoFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2013_02_20_022824_create_tipos_table.php b/database/migrations/2013_02_20_022824_create_tipos_table.php new file mode 100644 index 0000000..9c4f86a --- /dev/null +++ b/database/migrations/2013_02_20_022824_create_tipos_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('nombre'); + $table->timestamps(); + + }); + DB::table('tipos')->insert(['nombre'=> 'Administrador']); + DB::table('tipos')->insert(['nombre'=> 'Usuario']); + DB::table('tipos')->insert(['nombre'=> 'Jefe de Departamento']); + DB::table('tipos')->insert(['nombre'=> 'Servicios Generales']); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tipos'); + } +}; diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 8d71422..82450c6 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -18,7 +18,7 @@ return new class extends Migration $table->timestamp('email_verified_at')->nullable(); $table->string('apellido')->nullable(); $table->unsignedBigInteger('puesto_id')->nullable(); - + $table->unsignedBigInteger('tipos_id')->nullable(); $table->unsignedBigInteger('departamento_id')->nullable(); $table->string('telefono')->nullable(); @@ -26,15 +26,64 @@ return new class extends Migration $table->rememberToken(); $table->timestamps(); $table->foreign('puesto_id')->references('id')->on('puestos'); - + $table->foreign('tipos_id')->references('id')->on('tipos'); $table->foreign('departamento_id')->references('id')->on('despartamentos'); }); + + DB::table('users')->insert([ + 'name' => 'silva', + 'email' => 'silva@silva.com', + 'apellido' => 'anael', + 'tipos_id' => 2, // Asegúrate que este ID corresponde a "Usuario" en la tabla tipos + 'puesto_id' => 2, // Asegúrate que este ID corresponde a "docente" en la tabla puestos + 'departamento_id' => 2, // Asegúrate que este ID corresponde a "wfaf" en la tabla despartamentos + 'telefono' => '33652147821', + 'password' => bcrypt('12345678'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); DB::table('users')->insert([ - 'name'=> 'Administrador', - 'email'=> 'admin@admin.com', - 'password'=> bcrypt('12345678') + 'name' => 'monse', + 'email' => 'monse@monse.com', + 'apellido' => 'martinez', + 'tipos_id' => 1, + 'puesto_id' => 1, + 'departamento_id' => 3, + 'telefono' => null, + 'password' => bcrypt('12345678'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), ]); + DB::table('users')->insert([ + 'name' => 'usuario_tipo3', + 'email' => 'tipo3@ejemplo.com', + 'apellido' => 'apellido3', + 'tipos_id' => 3, // Tercer tipo restante + 'puesto_id' => 1, // Puedes ajustar el puesto según corresponda + 'departamento_id' => 1, // Puedes ajustar el departamento según corresponda + 'telefono' => '3333333333', + 'password' => bcrypt('12345678'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); + DB::table('users')->insert([ + 'name' => 'usuario_tipo4', + 'email' => 'tipo4@ejemplo.com', + 'apellido' => 'apellido4', + 'tipos_id' => 4, // Cuarto tipo restante + 'puesto_id' => 1, // Puedes ajustar el puesto según corresponda + 'departamento_id' => 1, // Puedes ajustar el departamento según corresponda + 'telefono' => '4444444444', + 'password' => bcrypt('12345678'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + ]); + } /** diff --git a/database/migrations/2025_05_08_175205_add_estado_to_prestamos_table.php b/database/migrations/2025_05_20_032155_add_columneliminado_topuestos.php similarity index 53% rename from database/migrations/2025_05_08_175205_add_estado_to_prestamos_table.php rename to database/migrations/2025_05_20_032155_add_columneliminado_topuestos.php index c47e8b3..84ac675 100644 --- a/database/migrations/2025_05_08_175205_add_estado_to_prestamos_table.php +++ b/database/migrations/2025_05_20_032155_add_columneliminado_topuestos.php @@ -11,9 +11,9 @@ return new class extends Migration */ public function up(): void { - Schema::table('prestamos', function (Blueprint $table) { - $table->enum('estado', ['pendiente', 'aceptado', 'rechazado'])->default('pendiente')->after('chofer'); - }); + Schema::table('puestos', function (Blueprint $table) { + $table->boolean('eliminado')->default(false); + }); } /** @@ -21,8 +21,8 @@ return new class extends Migration */ public function down(): void { - Schema::table('prestamos', function (Blueprint $table) { - $table->dropColumn('estado'); - }); + Schema::table('puestos', function (Blueprint $table) { + $table->dropColumn('eliminado'); + }); } }; diff --git a/hilads b/hilads new file mode 100644 index 0000000..e69de29 diff --git a/hollla.txt b/hollla.txt new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index ef7aad8..8f500d2 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -29,6 +29,14 @@ @endif + @if(session('error')) +
+
+ {{ session('error') }} +
+
+ @endif +
@csrf @@ -44,6 +52,12 @@ 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"> + + @error('email') + + {{ $message }} + + @enderror @@ -58,6 +72,12 @@ + + @error('password') + + {{ $message }} + + @enderror diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 6872ebf..7d72c75 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -1,6 +1,15 @@ @extends('layouts.dashboard') @section('content') +@if(!empty($notificaciones)) +
+
    + @foreach($notificaciones as $nota) +
  • {{ $nota }}
  • + @endforeach +
+
+@endif
@@ -10,8 +19,8 @@
-

25

-

↑ 12% desde el mes pasado

+

{{ $adminData['prestamosAceptados'] }}

+

Préstamos actualmente activos

@@ -22,32 +31,32 @@ -

150

-

↑ 5% desde el mes pasado

+

{{ $adminData['totalUsers'] }}

+

Total de usuarios en el sistema

- +
-

Préstamos Vencidos

+

Préstamos Pendientes

-

3

-

↓ 2% desde el mes pasado

+

{{ $adminData['prestamosPendientes'] }}

+

Préstamos por revisar

- +
-

Préstamos del Mes

+

Total Préstamos

-

42

-

↑ 8% desde el mes pasado

+

{{ $adminData['totalPrestamos'] }}

+

Total de préstamos registrados

@@ -66,34 +75,37 @@ - - -
-
- -
-
-
Juan Pérez
-
juan@example.com
-
-
- - -
Solicitó préstamo
- - -
Hace 2 horas
- - - - Aprobado - - - - + + + + @endsection diff --git a/resources/views/exports/puestos.blade.php b/resources/views/exports/puestos.blade.php new file mode 100644 index 0000000..23b90f6 --- /dev/null +++ b/resources/views/exports/puestos.blade.php @@ -0,0 +1,53 @@ + + + + Reporte de Puestos + + + +
+

Reporte de Puestos

+

Fecha de generación: {{ date('d/m/Y H:i:s') }}

+
+ + + + + + + + + + + @foreach($puestos as $index => $puesto) + + + + + + @endforeach + +
#Nombre del Puesto
{{ $index + 1 }}{{ $puesto->nombre }}
+ + diff --git a/resources/views/exports/tipos_vehiculos_pdf.blade.php b/resources/views/exports/tipos_vehiculos_pdf.blade.php index 9bed25e..93e2966 100644 --- a/resources/views/exports/tipos_vehiculos_pdf.blade.php +++ b/resources/views/exports/tipos_vehiculos_pdf.blade.php @@ -72,4 +72,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/views/exports/usuarios-pdf.blade.php b/resources/views/exports/usuarios-pdf.blade.php index 29b1550..879f478 100644 --- a/resources/views/exports/usuarios-pdf.blade.php +++ b/resources/views/exports/usuarios-pdf.blade.php @@ -4,45 +4,60 @@ Lista de Usuarios +

Lista de Usuarios

+

Fecha de generación: {{ date('d/m/Y H:i:s') }}

+
- + - + + - @foreach($usuarios as $usuario) + @foreach($usuarios as $index => $usuario) - + - - + + + @endforeach
IDNo. Nombre Email Apellido PuestoCarreraTipoDepartamento Teléfono
{{ $usuario->id }}{{ $index + 1 }} {{ $usuario->name }} {{ $usuario->email }} {{ $usuario->apellido }}{{ $usuario->puesto }}{{ $usuario->carrera }}{{ $usuario->puesto->nombre ?? '' }}{{ $usuario->tipo->nombre ?? '' }}{{ $usuario->departamento->departamento ?? '' }} {{ $usuario->telefono }}
- \ No newline at end of file + diff --git a/resources/views/layouts/dashboard.blade.php b/resources/views/layouts/dashboard.blade.php index 36a44bc..ef5b4f1 100644 --- a/resources/views/layouts/dashboard.blade.php +++ b/resources/views/layouts/dashboard.blade.php @@ -144,6 +144,13 @@ Marca + +
  • + + + Puestos + +
  • @@ -153,6 +160,7 @@
  • +
  • diff --git a/resources/views/puestos.blade.php b/resources/views/puestos.blade.php new file mode 100644 index 0000000..bc6450b --- /dev/null +++ b/resources/views/puestos.blade.php @@ -0,0 +1,142 @@ +@extends('layouts.dashboard') + +@section('content') +
    + + @if(session('success')) + + @endif + + @if(session('error')) + + @endif + +
    + + + + +
    + +
    + +
    + +
    +
    + + @if(request('busqueda')) + + Limpiar + + @endif + +
    + + +
    + + + + + + + + + + @foreach($puestos as $index => $puesto) + + + + + + @endforeach + +
    NúmeroPuestoAcciones
    {{ $index + 1 }} + + {{ $puesto->nombre }} + + + + +
    + @csrf + @method('DELETE') + + + +
    +
    +
    +
    +
    + + +@endsection diff --git a/resources/views/puestosCrearEditar.blade.php b/resources/views/puestosCrearEditar.blade.php new file mode 100644 index 0000000..5e581ff --- /dev/null +++ b/resources/views/puestosCrearEditar.blade.php @@ -0,0 +1,84 @@ +@extends('layouts.dashboard') + +@section('content') +
    +
    +
    +
    + +
    +

    + {{ isset($puesto) ? 'Editar Puesto' : 'Nuevo Puesto' }} +

    +
    + +
    +
    + + + @if($errors->any()) +
    +
    + +
    +
      + @foreach($errors->all() as $error) +
    • {{ $error }}
    • + @endforeach +
    +
    +
    +
    + @endif + +
    + @csrf + @if(isset($puesto)) + @method('PUT') + @endif + +
    + +
    + +
    +
    + +
    + +
    + @error('nombre') +

    {{ $message }}

    + @enderror +
    + + + + +
    + + Cancelar + + +
    +
    +
    +
    +
    +
    +
    +@endsection diff --git a/resources/views/usuarios.blade.php b/resources/views/usuarios.blade.php index bf4dcdd..485d21a 100644 --- a/resources/views/usuarios.blade.php +++ b/resources/views/usuarios.blade.php @@ -83,6 +83,7 @@ Nombre Email Apellido + Tipo Puesto Departamento Teléfono @@ -97,7 +98,7 @@ @else @foreach($usuarios as $index => $usuario) - + {{ $index + 1 }} @@ -109,16 +110,30 @@ {{ $usuario->apellido }} + +
    + + {{ $usuario->tipo->nombre ?? 'Sin tipo asignado' }} +
    + + + + @if(is_null($usuario->puesto_id) || is_null($usuario->departamento_id)) + + @endif
    {{ $usuario->puesto->nombre ?? 'Sin puesto asignado' }}
    + @if(is_null($usuario->puesto_id) || is_null($usuario->departamento_id)) + + @endif
    - {{ $usuario->despartamento->departamento ?? 'Sin departamento asignado' }} + {{ $usuario->departamento->departamento ?? 'Sin departamento asignado' }}
    diff --git a/resources/views/usuariosCrearEditar.blade.php b/resources/views/usuariosCrearEditar.blade.php index 31ebece..d091c36 100644 --- a/resources/views/usuariosCrearEditar.blade.php +++ b/resources/views/usuariosCrearEditar.blade.php @@ -70,7 +70,23 @@ required value="{{ isset($usuario) ? $usuario->apellido : old('apellido') }}"> - +
    + +
    +
    + +
    + +
    +
    diff --git a/routes/web.php b/routes/web.php index dbffc48..7a57874 100644 --- a/routes/web.php +++ b/routes/web.php @@ -10,6 +10,7 @@ use App\Http\Controllers\TiposLicenciasController; use App\Http\Controllers\CapacidadController; use App\Http\Controllers\PrestamoController; use App\Http\Controllers\DespartamentoController; +use App\Http\Controllers\PuestoController; /* @@ -31,6 +32,7 @@ use App\Http\Controllers\DespartamentoController; Route::resource('marca', MarcaController::class); Route::resource('docentes', DocentesController::class); + Route::resource('puestos', PuestoController::class); Route::resource('despartamentos', DespartamentoController::class); @@ -55,6 +57,9 @@ use App\Http\Controllers\DespartamentoController; Route::get('/despartamento/export/excel', [DespartamentoController::class, 'exportExcel'])->name('despartamentos.excel'); Route::get('/despartamento/export/pdf', [DespartamentoController::class, 'exportPDF'])->name('despartamentos.pdf'); + Route::get('/puestos/export/excel', [PuestoController::class, 'exportExcel'])->name('puestos.excel'); + Route::get('/puestos/export/pdf', [PuestoController::class, 'exportPDF'])->name('puestos.pdf'); + // Primero las rutas de exportación (más específicas) Route::get('/prestamos/excel', [PrestamoController::class, 'exportExcel'])->name('prestamos.excel'); Route::get('/prestamos/pdf', [PrestamoController::class, 'exportPDF'])->name('prestamos.pdf'); @@ -84,6 +89,7 @@ use App\Http\Controllers\DespartamentoController; Route::get('/usuarios/nuevo', [usuariosController::class, 'create'])->name('usuarios.create'); Route::post('/usuarios/store', [usuariosController::class,'store'])->name('usuarios.store'); + Route::get('/usuarios/edit/{id}', [usuariosController::class, 'edit'])->name('usuarios.edit'); Route::put('/usuarios/{id}', [usuariosController::class, 'update'])->name('usuarios.update'); Route::delete('/usuarios/destroy/{id}', [usuariosController::class, 'destroy'])->name('usuarios.destroy');