Browse Source

envio de usuarios

usuarios completos
main
sergiomarquez778 6 days ago
parent
commit
33fbc7efbc
  1. 33
      app/Exports/DocentesExport.php
  2. 59
      app/Http/Controllers/DocentesController.php
  3. 67
      app/Http/Controllers/TiposLicenciasController.php
  4. 3
      app/Models/Docentes.php
  5. 2
      app/Models/tiposLicencias.php
  6. 5
      composer.json
  7. 16
      composer.lock
  8. 28
      database/migrations/2025_03_27_054337_add_status_to_docentes_table.php
  9. 28
      database/migrations/2025_03_27_143601_add_status_to_tipos_licencias_table.php
  10. 28
      database/migrations/2025_03_27_144121_rename_status_to_eliminado_in_tipos_licencias.php
  11. 69
      resources/views/docentes.blade.php
  12. 24
      resources/views/docentesCrearEditar.blade.php
  13. 47
      resources/views/exports/docentes.blade.php
  14. 4
      resources/views/tiposLicencia.blade.php
  15. 4
      routes/web.php

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'
];
}
}

59
app/Http/Controllers/DocentesController.php

@ -4,6 +4,9 @@ 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
{
@ -12,7 +15,26 @@ class DocentesController extends Controller
*/
public function index(Request $request)
{
$docentes = Docentes::all();
$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]);
}
@ -58,7 +80,8 @@ class DocentesController extends Controller
public function update(Request $request, $id)
{
$docente = Docentes::find($id);
$docente->update($request->all());
$docente->fill($request->all());
$docente->save();
return redirect()->route('docentes.index')->with('success', 'Docente actualizado correctamente');
}
@ -68,7 +91,35 @@ class DocentesController extends Controller
public function destroy($id)
{
$docente = Docentes::find($id);
$docente->delete();
return redirect()->route('docentes.index')->with('success', 'Docente eliminado correctamente');
$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');
}
}
}

67
app/Http/Controllers/TiposLicenciasController.php

@ -16,26 +16,23 @@ class TiposLicenciasController extends Controller
$busqueda = $request->busqueda;
if($busqueda) {
$tiposLicencias = TiposLicencias::where('tipoLicencia', 'LIKE', "%{$busqueda}%")->get();
$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.');
}
// Si solo hay un tipo de licencia, mostrar sus detalles
if($tiposLicencias->count() == 1) {
$tipoLicencia = $tiposLicencias->first();
return redirect()->route('tiposLicencias.edit', $tipoLicencia->id);
}
// Si hay múltiples coincidencias, mostrar la lista filtrada
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]); // Cambiado aquí
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]);
}
// Si no hay búsqueda, mostrar todos los tipos de licencias
$tiposLicencias = TiposLicencias::all();
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]); // Cambiado aquí
$tiposLicencias = TiposLicencias::where('eliminado', 1)->get();
return view('tiposLicencia', ["tiposLicencias" => $tiposLicencias]);
}
/**
@ -51,47 +48,57 @@ class TiposLicenciasController extends Controller
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Crear una nueva instancia de TiposLicencias
$tipoLicencia = new TiposLicencias();
$tipoLicencia->tipoLicencia = $request->tipoLicencia; // Asigna el nombre ingresado por el usuario
$tipoLicencia->save(); // Guarda el nuevo tipo de licencia en la base de datos
{
$tipoLicencia = new TiposLicencias();
$tipoLicencia->tipoLicencia = $request->tipoLicencia;
$tipoLicencia->eliminado = 1;
$tipoLicencia->save();
// Redirige a la lista de tipos de licencias con un mensaje de éxito
return redirect()->route('tiposLicencias.index')->with('success', 'Tipo de licencia creado exitosamente.');
}
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);
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]);
}
// 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)
{
// Busca el tipo de licencia por ID
$tipoLicencia = TiposLicencias::findOrFail($id);
$tipoLicencia->tipoLicencia = $request->tipoLicencia;
if ($request->has('eliminado')) {
$tipoLicencia->eliminado = $request->eliminado;
}
$tipoLicencia->save();
// Actualiza el nombre del tipo de licencia
$tipoLicencia->tipoLicencia = $request->tipoLicencia; // Asigna el nuevo nombre ingresado por el usuario
$tipoLicencia->save(); // Guarda los cambios
// Redirige a la lista de tipos de licencias con un mensaje de éxito
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::find($id);
$tipoLicencia->delete();
$tipoLicencia = TiposLicencias::findOrFail($id);
$tipoLicencia->eliminado = 0;
$tipoLicencia->save();
return redirect()->route('tiposLicencias.index')->with('success', 'Tipo de licencia eliminado exitosamente.');
}
}

3
app/Models/Docentes.php

@ -14,6 +14,7 @@ class Docentes extends Model
'telefono',
'correo',
'tipo_licencia',
'materia'
'materia',
'status'
];
}

2
app/Models/tiposLicencias.php

@ -11,5 +11,5 @@ class tiposLicencias extends Model
protected $table = 'tiposLicencias';
protected $fillable = ['nombre'];
protected $fillable = ['nombre', 'eliminado'];
}

5
composer.json

@ -13,7 +13,12 @@
"laravel/tinker": "^2.8",
"laravel/ui": "^4.6",
"maatwebsite/excel": "^1.1",
<<<<<<< HEAD
"phpoffice/phpspreadsheet": "^4.1"
=======
"phpoffice/phpspreadsheet": "^4.1",
"psr/simple-cache": "2.0"
>>>>>>> 808a4a99e0ba6f66a69b363ca9c10dd59496c060
},
"require-dev": {
"fakerphp/faker": "^1.9.1",

16
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "acb583cdead6464e77a88f1ff4c131d6",
"content-hash": "c0f0a026d64d98ad86849a80b4a5135b",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
@ -3680,16 +3680,16 @@
},
{
"name": "psr/simple-cache",
"version": "3.0.0",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
"reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a",
"reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a",
"shasum": ""
},
"require": {
@ -3698,7 +3698,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
"dev-master": "2.0.x-dev"
}
},
"autoload": {
@ -3725,9 +3725,9 @@
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
"source": "https://github.com/php-fig/simple-cache/tree/2.0.0"
},
"time": "2021-10-29T13:26:27+00:00"
"time": "2021-10-29T13:22:09+00:00"
},
{
"name": "psy/psysh",

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_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');
});
}
};

69
resources/views/docentes.blade.php

@ -30,7 +30,25 @@
</a>
</div>
<!-- Barra de búsqueda -->
<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">
@ -44,7 +62,7 @@
</div>
</div>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600">
Buscar/Actualizar
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">
@ -64,6 +82,7 @@
<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>
@ -79,25 +98,20 @@
<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="#"
onclick="confirmarEdicion('{{ route('docentes.edit', $docente->id) }}')"
class="text-blue-600 hover:text-blue-900">
<a href="{{ route('docentes.edit', $docente->id) }}" class="text-blue-600 hover:text-blue-900">
<i class="fas fa-edit"></i>
</a>
<form action="{{ route('docentes.destroy', $docente->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>
<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>
@ -172,10 +186,29 @@ document.addEventListener('DOMContentLoaded', function() {
new DataTable('#docentes-table', {
layout: {
topStart: {
buttons: ['copy', 'csv', 'excel', 'pdf', 'print']
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

24
resources/views/docentesCrearEditar.blade.php

@ -25,9 +25,27 @@
<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>
<label for="tipo_licencia" class="block text-sm font-medium text-gray-700">Tipo de Licencia</label>
<input type="text" name="tipo_licencia" id="tipo_licencia" value="{{ old('tipo_licencia', $docente->tipo_licencia ?? '') }}" 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 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>

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>

4
resources/views/tiposLicencia.blade.php

@ -72,6 +72,10 @@
class="text-blue-600 hover:text-blue-900">
<i class="fas fa-edit"></i>
</a>
<a href="{{ route('tiposLicencias.toggle-status', $tipoLicencia->id) }}"
class="{{ $tipoLicencia->eliminado ? 'text-green-600 hover:text-green-900' : 'text-yellow-600 hover:text-yellow-900' }}">
<i class="fas {{ $tipoLicencia->eliminado ? 'fa-check-circle' : 'fa-times-circle' }}"></i>
</a>
<form action="{{ route('tiposLicencias.destroy', $tipoLicencia->id) }}"
method="POST"
class="inline"

4
routes/web.php

@ -35,13 +35,15 @@ Route::resource('vehiculos', TiposVeiculosController::class);
Route::resource('tiposLicencias', TiposLicenciasController::class);
Route::get('/tiposLicencias/{id}/toggle-status', [TiposLicenciasController::class, 'toggleStatus'])->name('tiposLicencias.toggle-status');
Route::resource('capacidades', CapacidadController::class);
Route::get('marcas/excel', [MarcaController::class, 'exportExcel'])->name('marcas.excel');
Route::get('marcas/pdf', [MarcaController::class, 'exportPDF'])->name('marcas.pdf');
Route::get('/docentes/export/{format}', [DocentesController::class, 'export'])->name('docentes.export');
Route::get('/docentes/{id}/toggle-status', [DocentesController::class, 'toggleStatus'])->name('docentes.toggle-status');
// Rutas protegidas que requieren autenticación
Route::middleware(['auth'])->group(function () {

Loading…
Cancel
Save