30 changed files with 969 additions and 106 deletions
@ -0,0 +1,44 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Exports; |
||||
|
|
||||
|
use App\Models\Puesto; |
||||
|
use Maatwebsite\Excel\Concerns\FromCollection; |
||||
|
use Maatwebsite\Excel\Concerns\WithHeadings; |
||||
|
|
||||
|
class PuestosExport implements FromCollection, WithHeadings |
||||
|
{ |
||||
|
protected $puestos; |
||||
|
|
||||
|
// Permite pasar una colección personalizada si lo deseas |
||||
|
public function __construct($puestos = null) |
||||
|
{ |
||||
|
$this->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', |
||||
|
]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers; |
||||
|
|
||||
|
use Illuminate\Http\Request; |
||||
|
|
||||
|
class AdminController extends Controller |
||||
|
{ |
||||
|
public function dashboard() |
||||
|
{ |
||||
|
return view('admin.dashboard'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,128 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers; |
||||
|
|
||||
|
use App\Models\Puesto; |
||||
|
use Illuminate\Http\Request; |
||||
|
use App\Exports\PuestosExport; |
||||
|
use Maatwebsite\Excel\Facades\Excel; |
||||
|
use PDF; |
||||
|
|
||||
|
class PuestoController extends Controller |
||||
|
{ |
||||
|
public function index(Request $request) |
||||
|
{ |
||||
|
$busqueda = $request->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'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers; |
||||
|
|
||||
|
use App\Models\tipo; |
||||
|
use Illuminate\Http\Request; |
||||
|
|
||||
|
class TipoController extends Controller |
||||
|
{ |
||||
|
/** |
||||
|
* Display a listing of the resource. |
||||
|
*/ |
||||
|
public function index() |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Show the form for creating a new resource. |
||||
|
*/ |
||||
|
public function create() |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Store a newly created resource in storage. |
||||
|
*/ |
||||
|
public function store(Request $request) |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Display the specified resource. |
||||
|
*/ |
||||
|
public function show(tipo $tipo) |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Show the form for editing the specified resource. |
||||
|
*/ |
||||
|
public function edit(tipo $tipo) |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Update the specified resource in storage. |
||||
|
*/ |
||||
|
public function update(Request $request, tipo $tipo) |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Remove the specified resource from storage. |
||||
|
*/ |
||||
|
public function destroy(tipo $tipo) |
||||
|
{ |
||||
|
// |
||||
|
} |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Middleware; |
||||
|
|
||||
|
use Closure; |
||||
|
use Illuminate\Http\Request; |
||||
|
use Symfony\Component\HttpFoundation\Response; |
||||
|
|
||||
|
class AdminMiddleware |
||||
|
{ |
||||
|
/** |
||||
|
* Handle an incoming request. |
||||
|
* |
||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next |
||||
|
*/ |
||||
|
public function handle(Request $request, Closure $next): Response |
||||
|
{ |
||||
|
if (!auth()->check() || auth()->user()->tipo->nombre !== 'Administrador') { |
||||
|
return redirect('/')->with('error', 'No tienes permisos para acceder a esta página.'); |
||||
|
} |
||||
|
|
||||
|
return $next($request); |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Models; |
||||
|
|
||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
|
use Illuminate\Database\Eloquent\Model; |
||||
|
|
||||
|
class tipo extends Model |
||||
|
{ |
||||
|
use HasFactory; |
||||
|
protected $table = 'tipos'; |
||||
|
protected $fillable = ['nombre']; |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace Database\Factories; |
||||
|
|
||||
|
use Illuminate\Database\Eloquent\Factories\Factory; |
||||
|
|
||||
|
/** |
||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\tipo> |
||||
|
*/ |
||||
|
class TipoFactory extends Factory |
||||
|
{ |
||||
|
/** |
||||
|
* Define the model's default state. |
||||
|
* |
||||
|
* @return array<string, mixed> |
||||
|
*/ |
||||
|
public function definition(): array |
||||
|
{ |
||||
|
return [ |
||||
|
// |
||||
|
]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
<?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', function (Blueprint $table) { |
||||
|
$table->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'); |
||||
|
} |
||||
|
}; |
@ -0,0 +1,53 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>Reporte de Puestos</title> |
||||
|
<style> |
||||
|
body { |
||||
|
font-family: Arial, sans-serif; |
||||
|
} |
||||
|
table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
margin-top: 20px; |
||||
|
} |
||||
|
th, td { |
||||
|
border: 1px solid #ddd; |
||||
|
padding: 8px; |
||||
|
text-align: left; |
||||
|
} |
||||
|
th { |
||||
|
background-color: #f2f2f2; |
||||
|
} |
||||
|
.header { |
||||
|
text-align: center; |
||||
|
margin-bottom: 30px; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="header"> |
||||
|
<h1>Reporte de Puestos</h1> |
||||
|
<p>Fecha de generación: {{ date('d/m/Y H:i:s') }}</p> |
||||
|
</div> |
||||
|
|
||||
|
<table> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>#</th> |
||||
|
<th>Nombre del Puesto</th> |
||||
|
|
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
@foreach($puestos as $index => $puesto) |
||||
|
<tr> |
||||
|
<td>{{ $index + 1 }}</td> |
||||
|
<td>{{ $puesto->nombre }}</td> |
||||
|
|
||||
|
</tr> |
||||
|
@endforeach |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,142 @@ |
|||||
|
@extends('layouts.dashboard') |
||||
|
|
||||
|
@section('content') |
||||
|
<div class="container mx-auto px-4 py-6"> |
||||
|
<!-- Mensajes de éxito y error --> |
||||
|
@if(session('success')) |
||||
|
<div id="success-message" class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-4" role="alert"> |
||||
|
<span class="block sm:inline">{{ session('success') }}</span> |
||||
|
</div> |
||||
|
@endif |
||||
|
|
||||
|
@if(session('error')) |
||||
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert"> |
||||
|
<span class="block sm:inline">{{ session('error') }}</span> |
||||
|
</div> |
||||
|
@endif |
||||
|
|
||||
|
<div class="bg-white rounded-lg shadow-lg"> |
||||
|
<!-- Encabezado con título y botones de acción --> |
||||
|
<div class="p-4 border-b border-gray-200 flex justify-between items-center"> |
||||
|
<h2 class="text-2xl font-bold">Gestión de Puestos</h2> |
||||
|
<div class="flex items-center space-x-6"> |
||||
|
<!-- Íconos de agregar --> |
||||
|
<div class="flex space-x-4"> |
||||
|
<a href="{{ route('puestos.excel') }}" |
||||
|
class="text-green-600 hover:text-green-700 transition-colors duration-200" |
||||
|
title="Exportar a Excel"> |
||||
|
<i class="fas fa-file-excel text-xl"></i> |
||||
|
</a> |
||||
|
|
||||
|
<a href="{{ route('puestos.pdf') }}" |
||||
|
class="text-red-600 hover:text-red-700 transition-colors duration-200" |
||||
|
title="Exportar a PDF"> |
||||
|
<i class="fas fa-file-pdf text-xl"></i> |
||||
|
</a> |
||||
|
<!-- Agregar nuevo puesto --> |
||||
|
<a href="{{ route('puestos.create') }}" |
||||
|
class="text-blue-500 hover:text-blue-600 transition-colors duration-200" |
||||
|
title="Agregar nuevo puesto"> |
||||
|
<i class="fas fa-plus text-xl"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Barra de búsqueda --> |
||||
|
<div class="p-4 border-b border-gray-200 bg-gray-50"> |
||||
|
<form action="{{ route('puestos.index') }}" method="GET" class="flex gap-2"> |
||||
|
<div class="relative w-full sm:w-64"> |
||||
|
<input type="text" |
||||
|
name="busqueda" |
||||
|
placeholder="Buscar puesto..." |
||||
|
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('puestos.index') }}" class="px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600"> |
||||
|
Limpiar |
||||
|
</a> |
||||
|
@endif |
||||
|
</form> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Tabla de puestos --> |
||||
|
<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">Número</th> |
||||
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Puesto</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($puestos as $index => $puesto) |
||||
|
<tr class="hover:bg-gray-50"> |
||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $index + 1 }}</td> |
||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> |
||||
|
<i class="fas fa-briefcase text-blue-500 mr-2"></i> |
||||
|
{{ $puesto->nombre }} |
||||
|
</td> |
||||
|
<td class="flex space-x-2 px-6 py-4 whitespace-nowrap text-sm"> |
||||
|
<a href="{{ route('puestos.edit', $puesto->id) }}" |
||||
|
class="text-yellow-600 hover:text-yellow-700 transition-colors duration-200" |
||||
|
title="Editar puesto"> |
||||
|
<i class="fas fa-edit"></i> |
||||
|
</a> |
||||
|
<form action="{{ route('puestos.destroy', $puesto->id) }}" method="POST" class="d-inline"> |
||||
|
@csrf |
||||
|
@method('DELETE') |
||||
|
<a href="#" onclick="event.preventDefault(); confirmarEliminacion(this);" |
||||
|
class="text-red-600 hover:text-red-700 transition-colors duration-200" |
||||
|
title="Eliminar puesto"> |
||||
|
<i class="fas fa-trash"></i> |
||||
|
</a> |
||||
|
</form> |
||||
|
</td> |
||||
|
</tr> |
||||
|
@endforeach |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<script> |
||||
|
// Desaparecer el mensaje después de 3 segundos |
||||
|
setTimeout(function() { |
||||
|
var message = document.getElementById('success-message'); |
||||
|
if (message) { |
||||
|
message.style.transition = 'opacity 0.5s ease'; |
||||
|
message.style.opacity = '0'; |
||||
|
setTimeout(function() { |
||||
|
message.remove(); |
||||
|
}, 500); |
||||
|
} |
||||
|
}, 3000); |
||||
|
|
||||
|
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').submit(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
@endsection |
@ -0,0 +1,84 @@ |
|||||
|
@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($puesto) ? 'Editar Puesto' : 'Nuevo Puesto' }} |
||||
|
</h2> |
||||
|
<div class="h-10 w-10 bg-blue-100 rounded-full flex items-center justify-center"> |
||||
|
<i class="fas fa-briefcase 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="puestoForm" |
||||
|
action="{{ isset($puesto) ? route('puestos.update', $puesto->id) : route('puestos.store') }}" |
||||
|
method="POST"> |
||||
|
@csrf |
||||
|
@if(isset($puesto)) |
||||
|
@method('PUT') |
||||
|
@endif |
||||
|
|
||||
|
<div class="space-y-6"> |
||||
|
<!-- Campo Nombre --> |
||||
|
<div> |
||||
|
<label for="nombre" class="block text-sm font-medium text-gray-700 mb-2"> |
||||
|
Nombre del Puesto |
||||
|
</label> |
||||
|
<div class="relative rounded-md shadow-sm"> |
||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> |
||||
|
<i class="fas fa-tag text-gray-400"></i> |
||||
|
</div> |
||||
|
<input type="text" |
||||
|
name="nombre" |
||||
|
id="nombre" |
||||
|
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" |
||||
|
required |
||||
|
placeholder="Ingresa el nombre del puesto" |
||||
|
value="{{ isset($puesto) ? $puesto->nombre : old('nombre') }}"> |
||||
|
</div> |
||||
|
@error('nombre') |
||||
|
<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('puestos.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($puesto) ? 'Actualizar' : 'Guardar' }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
@endsection |
Loading…
Reference in new issue