user()->classes()->pluck('id'); $fils = FilConversation::whereIn('classe_id', $classeIds) ->whereHas('messages') ->with(['eleve', 'classe']) ->get() ->map(fn (FilConversation $f) => [ 'id' => $f->id, 'eleve' => $f->eleve->nomAffiche(), 'classe' => $f->classe->nom, 'non_lus' => $f->nonLusPourProf(), 'dernier_message_a' => $f->messages->last()?->created_at->toIso8601String(), ]) ->sortByDesc('dernier_message_a') ->values(); return response()->json(['fils' => $fils]); } public function etat(FilConversation $fil): JsonResponse { $this->verifierProprietaire($fil); $fil->update(['lu_par_prof_a' => now()]); return response()->json([ 'eleve' => $fil->eleve->nomAffiche(), 'actif' => $fil->classe->chat_actif, 'messages' => $fil->messages->map(fn (MessageChat $m) => [ 'id' => $m->id, 'expediteur' => $m->expediteur, 'contenu' => $m->contenu, 'envoye_a' => $m->created_at->toIso8601String(), ]), ]); } public function envoyer(Request $request, FilConversation $fil): JsonResponse { $this->verifierProprietaire($fil); abort_unless($fil->classe->chat_actif, 403, 'Le chat est désactivé pour cette classe.'); $donnees = $request->validate(['contenu' => ['required', 'string', 'max:2000']]); // Pas de mise à jour de lu_par_prof_a ici : nonLusPourProf() ne // compte que les messages de l'élève, jamais les siens. $message = $fil->messages()->create([ 'expediteur' => MessageChat::PROF, 'contenu' => $donnees['contenu'], ]); return response()->json(['id' => $message->id], 201); } private function verifierProprietaire(FilConversation $fil): void { abort_if($fil->classe->user_id !== Auth::guard('web')->id(), 403); } }