rapproche encore le tableau de bord de la démo /cockpit : avancement par vérification, mains levées avec action réelle, progression de la séance
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
0573894721
commit
ee079ddffb
6 changed files with 178 additions and 6 deletions
|
|
@ -3,11 +3,13 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Classe;
|
||||
use App\Models\Correction;
|
||||
use App\Models\DemandeInscription;
|
||||
use App\Models\Eleve;
|
||||
use App\Models\LabSession;
|
||||
use App\Models\Seance;
|
||||
use App\Services\GenerateurCompteEleve;
|
||||
use App\Services\Labs\DefinitionLab;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -48,17 +50,44 @@ class ClasseController extends Controller
|
|||
->sortByDesc(fn ($s) => $s->statut === Seance::EN_COURS)
|
||||
->first();
|
||||
|
||||
// Déjà chargées par le eager loading ci-dessus (labSessions.derniereCorrection) :
|
||||
// repasser par une requête séparée perdait le type précis pour l'analyse statique.
|
||||
$corrections = $seance
|
||||
? LabSession::query()->whereIn('id', $seance->labSessions->pluck('id'))->whereHas('derniereCorrection')->with('derniereCorrection')->get()->pluck('derniereCorrection')
|
||||
? $seance->labSessions->map(fn (LabSession $ls) => $ls->derniereCorrection)->filter()->values()
|
||||
: collect();
|
||||
|
||||
// Répartition par vérification du lab (équivalent réel du « répartition
|
||||
// par étape » de la démo) : l'ordre et les titres viennent du lab.yaml,
|
||||
// le compte de réussite des vraies corrections. Jamais de bonus ici
|
||||
// (ils ajoutent des points, ils ne font pas partie du parcours normal).
|
||||
$avancement = collect();
|
||||
if ($seance && $corrections->isNotEmpty()) {
|
||||
$definition = DefinitionLab::depuis($seance->lab->identifiant);
|
||||
$avancement = collect($definition->verifications)
|
||||
->reject(fn ($v) => $v['bonus'])
|
||||
->map(fn ($v) => [
|
||||
'titre' => $v['titre'],
|
||||
'reussi' => $corrections->filter(fn (Correction $c) => collect($c->details)->firstWhere('id', $v['id'])['reussi'] ?? false)->count(),
|
||||
'total' => $corrections->count(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Progression dans le temps de la séance, d'après la durée estimée
|
||||
// du lab (Lab::duree_min) : absente si l'une des deux manque, jamais
|
||||
// une estimation inventée.
|
||||
$progressionSeance = ($seance?->demarree_a && $seance->lab->duree_min)
|
||||
? min(100, (int) round($seance->demarree_a->diffInMinutes(now()) / $seance->lab->duree_min * 100))
|
||||
: null;
|
||||
|
||||
return view('mes-classes.show', [
|
||||
'classes' => Auth::guard('web')->user()->classes()->withCount('eleves')->orderBy('nom')->get(),
|
||||
'classe' => $classe->load('eleves'),
|
||||
'demandes' => $classe->demandesInscription()->where('statut', DemandeInscription::EN_ATTENTE)->oldest()->get(),
|
||||
'seance' => $seance,
|
||||
'avancement' => $avancement,
|
||||
'progressionSeance' => $progressionSeance,
|
||||
'reussiteMoyenne' => $corrections->isNotEmpty() ? (int) round($corrections->avg(fn ($c) => $c->note_max > 0 ? $c->note / $c->note_max * 100 : 0)) : null,
|
||||
'mainsLevees' => ($seance && $seance->visioOuverte()) ? VisioController::nombreMainsLevees($seance) : null,
|
||||
'mains' => ($seance && $seance->visioOuverte()) ? VisioController::mainsLevees($seance) : [],
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,7 +214,26 @@ class VisioController extends Controller
|
|||
|
||||
public static function nombreMainsLevees(Seance $seance): int
|
||||
{
|
||||
return count((Cache::get(self::cleEtat($seance)) ?? [])['mains'] ?? []);
|
||||
return count(self::mainsLevees($seance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mains levées, premier arrivé en premier (même tri que etatProf) : nom
|
||||
* déjà minimisé (prénom + initiale), rien de plus que ce qu'affiche
|
||||
* déjà la page de visio.
|
||||
*
|
||||
* @return list<array{eleve_id: int, nom: string, depuis: int}>
|
||||
*/
|
||||
public static function mainsLevees(Seance $seance): array
|
||||
{
|
||||
/** @var array<int, array{nom: string, depuis: int}> $mains */
|
||||
$mains = (Cache::get(self::cleEtat($seance)) ?? [])['mains'] ?? [];
|
||||
|
||||
return collect($mains)
|
||||
->sortBy('depuis')
|
||||
->map(fn ($m, $id) => ['eleve_id' => (int) $id, 'nom' => $m['nom'], 'depuis' => $m['depuis']])
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function cle(Seance $seance): string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue