import { useState } from "react"; import { trpc } from "@/lib/trpc"; import { useLocalAuth } from "@/contexts/LocalAuthContext"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { toast } from "sonner"; import { Lightbulb, Plus, MessageSquare, Calendar, User, ChevronDown, ChevronUp, Send, Clock, CheckCircle2, XCircle, AlertCircle, } from "lucide-react"; import { format } from "date-fns"; import { fr } from "date-fns/locale"; type Statut = "ouvert" | "en_cours" | "resolu" | "ferme"; const STATUT_CONFIG: Record = { ouvert: { label: "Ouvert", color: "bg-blue-100 text-blue-700 border-blue-200", icon: , }, en_cours: { label: "En cours", color: "bg-amber-100 text-amber-700 border-amber-200", icon: , }, resolu: { label: "Résolu", color: "bg-emerald-100 text-emerald-700 border-emerald-200", icon: , }, ferme: { label: "Fermé", color: "bg-slate-100 text-slate-600 border-slate-200", icon: , }, }; type Idea = { id: number; userId: number; userName: string; titre: string; message: string; statut: Statut; reponseAdmin: string | null; reponduPar: string | null; reponduAt: Date | null; createdAt: Date; updatedAt: Date; }; export default function BoiteAIdees() { const { user } = useLocalAuth(); const isAdmin = user?.role === "admin"; const { data: ideas = [], refetch } = trpc.ideas.list.useQuery(); const createMutation = trpc.ideas.create.useMutation({ onSuccess: () => { toast.success("Votre demande a été envoyée avec succès !"); setNewDialogOpen(false); setNewTitre(""); setNewMessage(""); refetch(); }, onError: (e) => toast.error(e.message), }); const reponseMutation = trpc.ideas.repondre.useMutation({ onSuccess: () => { toast.success("Réponse enregistrée !"); setReponseDialogOpen(false); setReponseText(""); setSelectedIdea(null); refetch(); }, onError: (e) => toast.error(e.message), }); // État nouvelle demande const [newDialogOpen, setNewDialogOpen] = useState(false); const [newTitre, setNewTitre] = useState(""); const [newMessage, setNewMessage] = useState(""); // État réponse admin const [reponseDialogOpen, setReponseDialogOpen] = useState(false); const [selectedIdea, setSelectedIdea] = useState(null); const [reponseText, setReponseText] = useState(""); const [reponseStatut, setReponseStatut] = useState("resolu"); // État expansion des cartes const [expandedIds, setExpandedIds] = useState>(new Set()); // Filtre statut const [filtreStatut, setFiltreStatut] = useState("tous"); const [filtreRecherche, setFiltreRecherche] = useState(""); const toggleExpand = (id: number) => { setExpandedIds((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); }; const handleRepondre = (idea: Idea) => { setSelectedIdea(idea); setReponseText(idea.reponseAdmin ?? ""); setReponseStatut(idea.statut === "ouvert" ? "en_cours" : idea.statut); setReponseDialogOpen(true); }; const filteredIdeas = (ideas as Idea[]).filter((idea) => { const matchStatut = filtreStatut === "tous" || idea.statut === filtreStatut; const matchRecherche = !filtreRecherche || idea.titre.toLowerCase().includes(filtreRecherche.toLowerCase()) || idea.message.toLowerCase().includes(filtreRecherche.toLowerCase()) || idea.userName.toLowerCase().includes(filtreRecherche.toLowerCase()); return matchStatut && matchRecherche; }); const counts = { tous: (ideas as Idea[]).length, ouvert: (ideas as Idea[]).filter((i) => i.statut === "ouvert").length, en_cours: (ideas as Idea[]).filter((i) => i.statut === "en_cours").length, resolu: (ideas as Idea[]).filter((i) => i.statut === "resolu").length, ferme: (ideas as Idea[]).filter((i) => i.statut === "ferme").length, }; return (
{/* En-tête */}

Boîte à idées

{isAdmin ? "Gérez les questions et suggestions des utilisateurs" : "Posez vos questions et partagez vos suggestions"}

{/* Filtres */}
setFiltreRecherche(e.target.value)} className="bg-white border-slate-200" />
{(["tous", "ouvert", "en_cours", "resolu", "ferme"] as const).map((s) => ( ))}
{/* Liste des demandes */} {filteredIdeas.length === 0 ? (

Aucune demande pour le moment

Soyez le premier à soumettre une question ou une suggestion.

) : (
{filteredIdeas.map((idea) => { const isExpanded = expandedIds.has(idea.id); const cfg = STATUT_CONFIG[idea.statut]; return (
{/* En-tête de la carte */}
toggleExpand(idea.id)} >
{cfg.icon} {cfg.label}

{idea.titre}

{idea.userName} {format(new Date(idea.createdAt), "d MMM yyyy à HH:mm", { locale: fr })} {idea.reponseAdmin && ( Réponse disponible )}
{isAdmin && ( )} {isExpanded ? ( ) : ( )}
{/* Contenu développé */} {isExpanded && (
{/* Message */}

Message

{idea.message}

{/* Réponse admin */} {idea.reponseAdmin && (

Réponse de l'équipe {idea.reponduPar && ( — {idea.reponduPar} )} {idea.reponduAt && ( ({format(new Date(idea.reponduAt), "d MMM yyyy", { locale: fr })}) )}

{idea.reponseAdmin}

)}
)}
); })}
)} {/* Dialog : Nouvelle demande */} Nouvelle demande
setNewTitre(e.target.value)} className="mt-1" />