diff --git a/app/feedback/[eventId]/page.tsx b/app/feedback/[eventId]/page.tsx index e188fd3..1e41cdb 100644 --- a/app/feedback/[eventId]/page.tsx +++ b/app/feedback/[eventId]/page.tsx @@ -9,241 +9,10 @@ interface FeedbackPageProps { }; } -export default async function FeedbackPage({ params }: FeedbackPageProps) { +export default async function FeedbackPage({ + params: _params, +}: FeedbackPageProps) { const backgroundImage = await getBackgroundImage("home", "/got-2.jpg"); return ; } - - const [event, setEvent] = useState(null); - const [existingFeedback, setExistingFeedback] = useState( - null - ); - const [loading, setLoading] = useState(true); - const [submitting, setSubmitting] = useState(false); - const [error, setError] = useState(""); - const [success, setSuccess] = useState(false); - - const [rating, setRating] = useState(0); - const [comment, setComment] = useState(""); - - const fetchEventAndFeedback = async () => { - try { - // Récupérer l'événement - const eventResponse = await fetch(`/api/events/${eventId}`); - if (!eventResponse.ok) { - setError("Événement introuvable"); - setLoading(false); - return; - } - const eventData = await eventResponse.json(); - setEvent(eventData); - - // Récupérer le feedback existant si disponible - const feedbackResponse = await fetch(`/api/feedback/${eventId}`); - if (feedbackResponse.ok) { - const feedbackData = await feedbackResponse.json(); - if (feedbackData.feedback) { - setExistingFeedback(feedbackData.feedback); - setRating(feedbackData.feedback.rating); - setComment(feedbackData.feedback.comment || ""); - } - } - } catch { - setError("Erreur lors du chargement des données"); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - if (status === "unauthenticated") { - router.push(`/login?redirect=/feedback/${eventId}`); - return; - } - - if (status === "authenticated" && eventId) { - fetchEventAndFeedback(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [status, eventId, router]); - - const handleSubmit = async (e: FormEvent) => { - e.preventDefault(); - setError(""); - setSuccess(false); - - if (rating === 0) { - setError("Veuillez sélectionner une note"); - return; - } - - setSubmitting(true); - - try { - const response = await fetch(`/api/feedback/${eventId}`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - rating, - comment: comment.trim() || null, - }), - }); - - const data = await response.json(); - - if (!response.ok) { - setError(data.error || "Erreur lors de l'enregistrement"); - return; - } - - setSuccess(true); - setExistingFeedback(data.feedback); - - // Rediriger après 2 secondes - setTimeout(() => { - router.push("/events"); - }, 2000); - } catch { - setError("Erreur lors de l'enregistrement"); - } finally { - setSubmitting(false); - } - }; - - if (status === "loading" || loading) { - return ( - - - - Chargement... - - - ); - } - - if (!event) { - return ( - - - - Événement introuvable - - - ); - } - - return ( - - - - {/* Background Image */} - - - - - {/* Feedback Form */} - - - - - FEEDBACK - - - - {existingFeedback - ? "Modifier votre feedback pour" - : "Donnez votre avis sur"} - - - {event.name} - - - {success && ( - - Feedback enregistré avec succès ! Redirection... - - )} - - {error && ( - - {error} - - )} - - - {/* Rating */} - - - Note - - - {[1, 2, 3, 4, 5].map((star) => ( - setRating(star)} - className={`text-4xl transition-transform hover:scale-110 ${ - star <= rating - ? "text-pixel-gold" - : "text-gray-600 hover:text-gray-500" - }`} - aria-label={`Noter ${star} étoile${star > 1 ? "s" : ""}`} - > - ★ - - ))} - - - {rating > 0 && `${rating}/5`} - - - - {/* Comment */} - - - Commentaire (optionnel) - - setComment(e.target.value)} - rows={6} - maxLength={1000} - className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition resize-none" - placeholder="Partagez votre expérience, vos suggestions..." - /> - - {comment.length}/1000 caractères - - - - {/* Submit Button */} - - {submitting - ? "Enregistrement..." - : existingFeedback - ? "Modifier le feedback" - : "Envoyer le feedback"} - - - - - - - ); -} diff --git a/components/Avatar.tsx b/components/Avatar.tsx index d94d07d..f39b636 100644 --- a/components/Avatar.tsx +++ b/components/Avatar.tsx @@ -35,6 +35,8 @@ export default function Avatar({ useEffect(() => { if (src !== prevSrcRef.current) { prevSrcRef.current = src; + // Reset error when src changes to allow retry + // eslint-disable-next-line react-hooks/set-state-in-effect setAvatarError(false); } }, [src]); diff --git a/components/BackgroundPreferences.tsx b/components/BackgroundPreferences.tsx index e58423d..37a727d 100644 --- a/components/BackgroundPreferences.tsx +++ b/components/BackgroundPreferences.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useMemo } from "react"; import ImageSelector from "@/components/ImageSelector"; interface SitePreferences { @@ -23,11 +23,6 @@ const DEFAULT_IMAGES = { export default function BackgroundPreferences({ initialPreferences, }: BackgroundPreferencesProps) { - const [preferences, setPreferences] = useState( - initialPreferences - ); - const [isEditing, setIsEditing] = useState(false); - // Helper pour obtenir la valeur à afficher dans le formulaire const getFormValue = ( dbValue: string | null | undefined, @@ -41,25 +36,13 @@ export default function BackgroundPreferences({ return formValue === defaultImage ? "" : formValue; }; - const [formData, setFormData] = useState({ - homeBackground: getFormValue( - initialPreferences.homeBackground, - DEFAULT_IMAGES.home - ), - eventsBackground: getFormValue( - initialPreferences.eventsBackground, - DEFAULT_IMAGES.events - ), - leaderboardBackground: getFormValue( - initialPreferences.leaderboardBackground, - DEFAULT_IMAGES.leaderboard - ), - }); + const [preferences, setPreferences] = useState( + initialPreferences + ); + const [isEditing, setIsEditing] = useState(false); - // Synchroniser les préférences quand initialPreferences change - useEffect(() => { - setPreferences(initialPreferences); - setFormData({ + const computedFormData = useMemo( + () => ({ homeBackground: getFormValue( initialPreferences.homeBackground, DEFAULT_IMAGES.home @@ -72,7 +55,17 @@ export default function BackgroundPreferences({ initialPreferences.leaderboardBackground, DEFAULT_IMAGES.leaderboard ), - }); + }), + [initialPreferences] + ); + + const [formData, setFormData] = useState(computedFormData); + + // Synchroniser les préférences quand initialPreferences change + useEffect(() => { + setPreferences(initialPreferences); + setFormData(computedFormData); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialPreferences]); const handleEdit = () => { diff --git a/components/FeedbackModal.tsx b/components/FeedbackModal.tsx index 5b6a0a4..a1176eb 100644 --- a/components/FeedbackModal.tsx +++ b/components/FeedbackModal.tsx @@ -24,7 +24,7 @@ interface FeedbackModalProps { export default function FeedbackModal({ eventId, - eventName, + eventName: _eventName, onClose, }: FeedbackModalProps) { const { status } = useSession();
- {existingFeedback - ? "Modifier votre feedback pour" - : "Donnez votre avis sur"} -
- {event.name} -
- {rating > 0 && `${rating}/5`} -
- {comment.length}/1000 caractères -