Modificación del de vista de dopcumentos del alumno
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Docente;
|
||||
use App\Models\Evaluacion;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class EvaluacionReporteController extends Controller
|
||||
{
|
||||
public function show(Evaluacion $evaluacion)
|
||||
{
|
||||
$datos = $this->buildDatos($evaluacion);
|
||||
$totalSubmissions = $evaluacion->submissions()->count();
|
||||
|
||||
return view('evaluacion.reporte', compact('evaluacion', 'datos', 'totalSubmissions'));
|
||||
}
|
||||
|
||||
public function pdf(Evaluacion $evaluacion)
|
||||
{
|
||||
$datos = $this->buildDatos($evaluacion);
|
||||
$totalSubmissions = $evaluacion->submissions()->count();
|
||||
|
||||
// Fetch chart images from QuickChart and embed as base64
|
||||
foreach ($datos as &$item) {
|
||||
if ($item['tipo'] === 'texto_libre') continue;
|
||||
|
||||
if ($item['es_docente']) {
|
||||
foreach ($item['por_docente'] as &$pd) {
|
||||
if (isset($pd['chart_config'])) {
|
||||
$pd['chart_img'] = $this->fetchChartBase64($pd['chart_config']);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($item['chart_config'])) {
|
||||
$item['chart_img'] = $this->fetchChartBase64($item['chart_config']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = Pdf::loadView('evaluacion.reporte_pdf', compact('evaluacion', 'datos', 'totalSubmissions'))
|
||||
->setPaper('a4', 'portrait');
|
||||
|
||||
return $pdf->download('reporte-' . $evaluacion->id . '.pdf');
|
||||
}
|
||||
|
||||
// ─── Data builder ───────────────────────────────────────────────────────────
|
||||
|
||||
private function buildDatos(Evaluacion $evaluacion): array
|
||||
{
|
||||
$preguntas = $evaluacion->preguntas()
|
||||
->with(['tipo', 'opciones', 'respuestas.opcion'])
|
||||
->get();
|
||||
|
||||
$datos = [];
|
||||
|
||||
foreach ($preguntas as $pregunta) {
|
||||
$tipoSlug = $pregunta->tipo->slug;
|
||||
$respuestas = $pregunta->respuestas;
|
||||
|
||||
if ($pregunta->es_docente) {
|
||||
$docenteIds = $respuestas->pluck('docente_id')->unique()->filter();
|
||||
$porDocente = [];
|
||||
|
||||
foreach ($docenteIds as $docenteId) {
|
||||
$rsp = $respuestas->where('docente_id', $docenteId);
|
||||
$docente = Docente::with('docentes')->find($docenteId);
|
||||
$user = $docente?->docentes->first();
|
||||
$nombre = $user
|
||||
? trim("{$user->apellidoPaterno} {$user->apellidoMaterno} {$user->name}")
|
||||
: "Docente #{$docenteId}";
|
||||
|
||||
$chart = $this->procesarRespuestas($rsp, $tipoSlug, $pregunta);
|
||||
|
||||
$porDocente[] = [
|
||||
'docente_nombre' => $nombre,
|
||||
'chart_config' => $chart['config'] ?? null,
|
||||
'textos' => $chart['textos'] ?? [],
|
||||
'promedio' => $chart['promedio'] ?? null,
|
||||
'total' => $rsp->count(),
|
||||
];
|
||||
}
|
||||
|
||||
$datos[] = [
|
||||
'pregunta' => $pregunta,
|
||||
'tipo' => $tipoSlug,
|
||||
'es_docente' => true,
|
||||
'por_docente' => $porDocente,
|
||||
];
|
||||
} else {
|
||||
$chart = $this->procesarRespuestas($respuestas, $tipoSlug, $pregunta);
|
||||
|
||||
$datos[] = [
|
||||
'pregunta' => $pregunta,
|
||||
'tipo' => $tipoSlug,
|
||||
'es_docente' => false,
|
||||
'chart_config' => $chart['config'] ?? null,
|
||||
'textos' => $chart['textos'] ?? [],
|
||||
'promedio' => $chart['promedio'] ?? null,
|
||||
'total' => $respuestas->count(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $datos;
|
||||
}
|
||||
|
||||
private function procesarRespuestas($respuestas, string $tipoSlug, $pregunta): array
|
||||
{
|
||||
switch ($tipoSlug) {
|
||||
|
||||
case 'si_no':
|
||||
$si = $respuestas->where('valor', 'si')->count();
|
||||
$no = $respuestas->where('valor', 'no')->count();
|
||||
return ['config' => [
|
||||
'type' => 'doughnut',
|
||||
'data' => [
|
||||
'labels' => ['Sí', 'No'],
|
||||
'datasets' => [[
|
||||
'data' => [$si, $no],
|
||||
'backgroundColor' => ['#1cc88a', '#e74a3b'],
|
||||
'borderWidth' => 2,
|
||||
]],
|
||||
],
|
||||
'options' => [
|
||||
'plugins' => [
|
||||
'legend' => ['position' => 'bottom'],
|
||||
'datalabels' => ['display' => false],
|
||||
],
|
||||
],
|
||||
]];
|
||||
|
||||
case 'opcion_multiple':
|
||||
$labels = [];
|
||||
$counts = [];
|
||||
$colors = ['#4e73df','#1cc88a','#36b9cc','#f6c23e','#e74a3b','#858796','#5a5c69'];
|
||||
foreach ($pregunta->opciones as $idx => $opcion) {
|
||||
$labels[] = $opcion->texto;
|
||||
$counts[] = $respuestas->where('opcion_id', $opcion->id)->count();
|
||||
}
|
||||
return ['config' => [
|
||||
'type' => 'bar',
|
||||
'data' => [
|
||||
'labels' => $labels,
|
||||
'datasets' => [[
|
||||
'label' => 'Respuestas',
|
||||
'data' => $counts,
|
||||
'backgroundColor' => array_slice(array_merge($colors, $colors), 0, count($labels)),
|
||||
'borderRadius' => 4,
|
||||
]],
|
||||
],
|
||||
'options' => [
|
||||
'plugins' => ['legend' => ['display' => false]],
|
||||
'scales' => ['y' => ['beginAtZero' => true, 'ticks' => ['stepSize' => 1]]],
|
||||
],
|
||||
]];
|
||||
|
||||
case 'escala_5':
|
||||
case 'escala_10':
|
||||
$max = $tipoSlug === 'escala_5' ? 5 : 10;
|
||||
$labels = range(1, $max);
|
||||
$counts = [];
|
||||
foreach ($labels as $val) {
|
||||
$counts[] = $respuestas->filter(fn($r) => (int)$r->valor === $val)->count();
|
||||
}
|
||||
$total = $respuestas->count();
|
||||
$suma = $respuestas->sum(fn($r) => (int)$r->valor);
|
||||
$prom = $total > 0 ? round($suma / $total, 2) : null;
|
||||
|
||||
return [
|
||||
'config' => [
|
||||
'type' => 'bar',
|
||||
'data' => [
|
||||
'labels' => $labels,
|
||||
'datasets' => [[
|
||||
'label' => 'Respuestas',
|
||||
'data' => $counts,
|
||||
'backgroundColor' => '#36b9cc',
|
||||
'borderRadius' => 4,
|
||||
]],
|
||||
],
|
||||
'options' => [
|
||||
'plugins' => ['legend' => ['display' => false]],
|
||||
'scales' => ['y' => ['beginAtZero' => true, 'ticks' => ['stepSize' => 1]]],
|
||||
],
|
||||
],
|
||||
'promedio' => $prom,
|
||||
];
|
||||
|
||||
case 'texto_libre':
|
||||
return ['textos' => $respuestas->pluck('valor')->filter()->values()->toArray()];
|
||||
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// ─── QuickChart helper ───────────────────────────────────────────────────────
|
||||
|
||||
private function fetchChartBase64(array $config): ?string
|
||||
{
|
||||
try {
|
||||
$response = Http::timeout(15)->post('https://quickchart.io/chart', [
|
||||
'chart' => $config,
|
||||
'width' => 500,
|
||||
'height' => 280,
|
||||
'backgroundColor' => 'white',
|
||||
'format' => 'png',
|
||||
]);
|
||||
|
||||
if ($response->successful()) {
|
||||
return 'data:image/png;base64,' . base64_encode($response->body());
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// QuickChart no disponible; la imagen simplemente no aparece
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user