feat: módulo de evaluaciones para admin con constructor dinámico

- Modelos completos: Evaluacion, EvaluacionTipo, Pregunta, PreguntaTipo,
  PreguntaOpcion, EvaluacionSubmission, Respuesta (con $table explícito
  para nombres en español que Laravel pluraliza incorrectamente)
- Relaciones evaluaciones() añadidas a Plantel y Nivel
- EvaluacionBuilder (Livewire): constructor interactivo con preguntas
  de tipo texto libre, opción múltiple, escala 1-5/1-10 y sí/no;
  reorden con flechas, vista previa por tipo, selección de planteles
  y niveles, configuración de estado, fechas y flag de anónima
- EvaluacionController: CRUD completo + toggleStatus
- Vistas: index, create/edit (con Livewire builder), show con detalle
  de preguntas y cambio de estado
- Rutas resource /evaluacion + PATCH /evaluacion/{id}/status
- Migraciones: evaluaciones, preguntas, pregunta_opciones,
  evaluacion_submissions, respuestas, evaluacion_plantel, evaluacion_nivel
- Menú: enlace Evaluaciones en panel de Administrador

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 18:09:48 -06:00
parent f81237b23c
commit 2af36ea272
27 changed files with 1471 additions and 21 deletions
+34 -1
View File
@@ -2,6 +2,7 @@
use App\Events\MessageSent;
use App\Http\Controllers\AlumnoController;
use App\Http\Controllers\AnuncioController;
use App\Http\Controllers\AreaCodeController;
use App\Http\Controllers\AreaController;
use App\Http\Controllers\CampanController;
@@ -15,6 +16,9 @@ use App\Http\Controllers\UserSearchController;
use App\Http\Controllers\CodeController;
use App\Http\Controllers\ConceptoController;
use App\Http\Controllers\DocenteController;
use App\Http\Controllers\EntregaController;
use App\Http\Controllers\EvaluacionController;
use App\Http\Controllers\TareaController;
use App\Http\Controllers\DocumentoController;
use App\Http\Controllers\DocumentoTipoController;
use App\Http\Controllers\DurationController;
@@ -52,7 +56,12 @@ Route::middleware(['auth:sanctum',config('jetstream.auth_session'),'verified',
Route::resource('/alumno',AlumnoController::class);
Route::resource('/area',AreaController::class);
Route::resource('/areacode',AreaCodeController::class);
Route::get('/dashboard', function () {return view('dashboard');})->name('dashboard');
Route::get('/dashboard', function () {
$user = auth()->user();
$roles = $user->getRoleNames()->toArray();
$anuncios = \App\Models\Anuncio::vigentes()->paraRoles($roles)->latest()->get();
return view('dashboard', compact('anuncios'));
})->name('dashboard');
Route::resource('/campan',CampanController::class);
Route::resource('/carrera',CarreraController::class);
Route::resource('/code',CodeController::class);
@@ -78,6 +87,14 @@ Route::middleware(['auth:sanctum',config('jetstream.auth_session'),'verified',
Route::post('/friends/{user}/toggle', [FriendshipController::class, 'toggle'])->name('friendships.toggle');
Route::get('/search', UserSearchController::class)->name('users.search');
// Evaluaciones
Route::resource('/evaluacion', EvaluacionController::class);
Route::patch('/evaluacion/{evaluacion}/status', [EvaluacionController::class, 'toggleStatus'])->name('evaluacion.toggleStatus');
// Anuncios (gestión: solo Admin)
Route::resource('/anuncio', AnuncioController::class);
Route::patch('/anuncio/{anuncio}/toggle', [AnuncioController::class, 'toggleActive'])->name('anuncio.toggleActive');
Route::get('/perfil/{user}', [SocialProfileController::class, 'show'])->name('social.profile');
Route::resource('/docente',DocenteController::class);
@@ -87,6 +104,22 @@ Route::middleware(['auth:sanctum',config('jetstream.auth_session'),'verified',
Route::resource('/documentoTipo',DocumentoTipoController::class);
Route::resource('/duration',DurationController::class);
Route::resource('/grupo', GrupoController::class);
Route::get('/grupo/{grupo}/administrar', [GrupoController::class, 'administrar'])->name('grupo.administrar');
Route::get('/grupo/{grupo}/ver-materias', [GrupoController::class, 'verMaterias'])->name('grupo.ver.materias');
// Tareas (docente)
Route::get('/grupo/{grupo}/material/{material}/tareas', [TareaController::class, 'index'])->name('grupo.material.tareas');
Route::get('/grupo/{grupo}/material/{material}/tareas/create', [TareaController::class, 'create'])->name('grupo.material.tareas.create');
Route::post('/grupo/{grupo}/material/{material}/tareas', [TareaController::class, 'store'])->name('grupo.material.tareas.store');
Route::get('/grupo/{grupo}/material/{material}/tareas/{tarea}', [TareaController::class, 'show'])->name('grupo.material.tareas.show');
Route::get('/grupo/{grupo}/material/{material}/tareas/{tarea}/edit', [TareaController::class, 'edit'])->name('grupo.material.tareas.edit');
Route::put('/grupo/{grupo}/material/{material}/tareas/{tarea}', [TareaController::class, 'update'])->name('grupo.material.tareas.update');
Route::delete('/grupo/{grupo}/material/{material}/tareas/{tarea}', [TareaController::class, 'destroy'])->name('grupo.material.tareas.destroy');
Route::post('/tareas/{tarea}/calificar/{alumno}', [TareaController::class, 'calificar'])->name('tarea.calificar');
// Entregas (alumno)
Route::get('/mis-tareas', [EntregaController::class, 'index'])->name('mis.tareas');
Route::post('/tareas/{tarea}/entregar', [EntregaController::class, 'store'])->name('tarea.entregar');
Route::get('/horario', [HorarioController::class, 'index'])->name('horario.index');
Route::get('/horario/create', [HorarioController::class, 'create'])->name('horario.create');
Route::post('/horario', [HorarioController::class, 'store'])->name('horario.store');