validate([ 'type' => ['required', Rule::in(['Modification', 'Ajout', 'Correction'])], 'titre' => ['required', 'string', 'min:5', 'max:120'], 'description' => ['required', 'string', 'min:10', 'max:5000'], ], [ 'type.required' => 'Veuillez choisir un type de demande.', 'type.in' => 'Type de demande invalide.', 'titre.required' => 'Le titre est requis.', 'titre.min' => 'Le titre doit contenir au moins 5 caractères.', 'titre.max' => 'Le titre ne peut pas dépasser 120 caractères.', 'description.required' => 'La description est requise.', 'description.min' => 'Merci de détailler un peu plus votre suggestion (10 caractères minimum).', ]); /** @var Utilisateur $user */ $user = Auth::user(); $auteur = $user->Pseudo ?? 'Utilisateur'; $title = "[{$data['type']}] {$data['titre']}"; $body = "**Type de demande :** {$data['type']}\n" ."**Proposé par :** {$auteur} (via le site (RE)Sources Relationnelles)\n\n" ."### Description\n" .$data['description']."\n\n" ."---\n" .'_Ticket créé automatiquement depuis le formulaire de suggestions du site._'; $numero = $gitea->createIssue($title, $body); if ($numero === null) { return back()->withInput()->withErrors([ 'gitea' => "L'envoi de votre suggestion a échoué. Merci de réessayer plus tard.", ]); } // La suggestion est conservée en base, liée au ticket, pour le suivi. Suggestion::create([ 'ID_Utilisateur' => $user->ID_Utilisateur, 'Type' => $data['type'], 'Titre' => $data['titre'], 'Description' => $data['description'], 'GiteaIssueNumber' => $numero, ]); return redirect()->route('suggestions.index') ->with('success', 'Merci ! Votre suggestion a bien été transmise à l\'équipe. Vous pouvez suivre sa prise en compte ici.'); } // Liste des suggestions de l'utilisateur, avec l'état de chaque ticket public function index(GiteaIssueService $gitea) { $suggestions = Suggestion::where('ID_Utilisateur', Auth::user()->ID_Utilisateur) ->orderByDesc('DateCreation') ->get(); // État des tickets (ouvert/fermé, nb de réponses), mis en cache 60 s // pour ne pas appeler l'API Gitea à chaque affichage de la page. $etats = []; foreach ($suggestions as $suggestion) { if ($suggestion->GiteaIssueNumber === null) { continue; } $etat = Cache::remember( 'gitea.issue.'.$suggestion->GiteaIssueNumber, 60, fn () => $gitea->getIssue($suggestion->GiteaIssueNumber) ?? false, ); $etats[$suggestion->ID_Suggestion] = $etat ?: null; } return view('suggestions.index', compact('suggestions', 'etats')); } // Détail d'une suggestion : fil de discussion du ticket Gitea public function show(Suggestion $suggestion, GiteaIssueService $gitea) { abort_unless($suggestion->ID_Utilisateur === Auth::user()->ID_Utilisateur, 403); $issue = null; $commentaires = []; if ($suggestion->GiteaIssueNumber !== null) { $issue = $gitea->getIssue($suggestion->GiteaIssueNumber); $commentaires = $gitea->getComments($suggestion->GiteaIssueNumber); // Tout est lu : le badge « nouvelle réponse » disparaît de la liste. $suggestion->CommentairesVus = count($commentaires); $suggestion->save(); } return view('suggestions.show', compact('suggestion', 'issue', 'commentaires')); } // Répondre sur le ticket : le commentaire est publié sur Gitea public function repondre(Request $request, Suggestion $suggestion, GiteaIssueService $gitea) { abort_unless($suggestion->ID_Utilisateur === Auth::user()->ID_Utilisateur, 403); abort_if($suggestion->GiteaIssueNumber === null, 404); $data = $request->validate([ 'message' => ['required', 'string', 'min:2', 'max:2000'], ], [ 'message.required' => 'Votre message est vide.', 'message.min' => 'Votre message est trop court.', 'message.max' => 'Votre message ne peut pas dépasser 2000 caractères.', ]); /** @var Utilisateur $user */ $user = Auth::user(); $corps = '**'.($user->Pseudo ?? 'Utilisateur')."** (via le site) :\n\n".$data['message']; if (! $gitea->addComment($suggestion->GiteaIssueNumber, $corps)) { return back()->withInput()->withErrors([ 'gitea' => "L'envoi de votre réponse a échoué. Merci de réessayer plus tard.", ]); } // L'état du ticket a changé : on invalide le cache de la liste. Cache::forget('gitea.issue.'.$suggestion->GiteaIssueNumber); return redirect()->route('suggestions.show', $suggestion) ->with('success', 'Votre réponse a été publiée sur le ticket.'); } }