Files
got-gaming/app/feedback/[eventId]/FeedbackPageClient.tsx

247 lines
6.8 KiB
TypeScript

"use client";
import { useState, useEffect, useTransition, type FormEvent } from "react";
import { useSession } from "next-auth/react";
import { useRouter, useParams } from "next/navigation";
import Navigation from "@/components/Navigation";
import { createFeedback } from "@/actions/events/feedback";
import {
StarRating,
Textarea,
Button,
Alert,
Card,
BackgroundSection,
SectionTitle,
} from "@/components/ui";
interface Event {
id: string;
name: string;
date: string;
description: string;
}
interface Feedback {
id: string;
rating: number;
comment: string | null;
}
interface FeedbackPageClientProps {
backgroundImage: string;
}
export default function FeedbackPageClient({
backgroundImage,
}: FeedbackPageClientProps) {
const { status } = useSession();
const router = useRouter();
const params = useParams();
const eventId = params?.eventId as string;
const [event, setEvent] = useState<Event | null>(null);
const [existingFeedback, setExistingFeedback] = useState<Feedback | null>(
null
);
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const [, startTransition] = useTransition();
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);
startTransition(async () => {
try {
const result = await createFeedback(eventId, {
rating,
comment: comment.trim() || null,
});
if (!result.success) {
setError(result.error || "Erreur lors de l'enregistrement");
setSubmitting(false);
return;
}
setSuccess(true);
if (result.data) {
setExistingFeedback({
id: result.data.id,
rating: result.data.rating,
comment: result.data.comment,
});
}
// 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 (
<main className="min-h-screen bg-black relative">
<Navigation />
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
<div className="text-white">Chargement...</div>
</section>
</main>
);
}
if (!event) {
return (
<main className="min-h-screen bg-black relative">
<Navigation />
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
<div className="text-red-400">Événement introuvable</div>
</section>
</main>
);
}
return (
<main className="min-h-screen bg-black relative">
<Navigation />
<BackgroundSection backgroundImage={backgroundImage} className="pt-24">
{/* Feedback Form */}
<div className="w-full max-w-2xl mx-auto px-8">
<Card variant="dark" className="p-8">
<SectionTitle
variant="gradient"
size="lg"
className="mb-2 text-center"
>
FEEDBACK
</SectionTitle>
<p className="text-gray-400 text-sm text-center mb-2">
{existingFeedback
? "Modifier votre feedback pour"
: "Donnez votre avis sur"}
</p>
<p className="text-pixel-gold text-lg font-semibold text-center mb-8">
{event.name}
</p>
{success && (
<Alert variant="success" className="mb-6">
Feedback enregistré avec succès ! Redirection...
</Alert>
)}
{error && (
<Alert variant="error" className="mb-6">
{error}
</Alert>
)}
<form onSubmit={handleSubmit} className="space-y-6">
{/* Rating */}
<div>
<label className="block text-sm font-semibold text-gray-300 mb-4 uppercase tracking-wider">
Note
</label>
<StarRating
value={rating}
onChange={setRating}
size="lg"
showValue
/>
</div>
{/* Comment */}
<Textarea
id="comment"
label="Commentaire (optionnel)"
value={comment}
onChange={(e) => setComment(e.target.value)}
rows={6}
maxLength={1000}
showCharCount
placeholder="Partagez votre expérience, vos suggestions..."
/>
{/* Submit Button */}
<Button
type="submit"
variant="primary"
size="lg"
disabled={submitting || rating === 0}
className="w-full"
>
{submitting
? "Enregistrement..."
: existingFeedback
? "Modifier le feedback"
: "Envoyer le feedback"}
</Button>
</form>
</Card>
</div>
</BackgroundSection>
</main>
);
}