Enhance UI components and animations: Introduce a shimmer animation effect in globals.css, refactor FeedbackPageClient, LoginPage, RegisterPage, and AdminPanel components to utilize new UI components for improved consistency and maintainability. Update event and feedback handling in EventsPageSection and FeedbackModal, ensuring a cohesive user experience across the application.
This commit is contained in:
495
app/admin/style-guide/page.tsx
Normal file
495
app/admin/style-guide/page.tsx
Normal file
@@ -0,0 +1,495 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Navigation from "@/components/Navigation";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Textarea,
|
||||
Card,
|
||||
Badge,
|
||||
Alert,
|
||||
Modal,
|
||||
ProgressBar,
|
||||
StarRating,
|
||||
Avatar,
|
||||
SectionTitle,
|
||||
BackgroundSection,
|
||||
CloseButton,
|
||||
} from "@/components/ui";
|
||||
|
||||
export default function StyleGuidePage() {
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [textareaValue, setTextareaValue] = useState("");
|
||||
const [rating, setRating] = useState(0);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<Navigation />
|
||||
<BackgroundSection backgroundImage="/got-2.jpg" className="pt-24 pb-16">
|
||||
<div className="w-full max-w-6xl mx-auto px-8">
|
||||
<SectionTitle variant="gradient" size="xl" className="mb-12">
|
||||
STYLE GUIDE
|
||||
</SectionTitle>
|
||||
<p className="text-gray-400 text-center mb-12 max-w-3xl mx-auto">
|
||||
Guide de style complet avec tous les composants UI disponibles et
|
||||
leurs variantes
|
||||
</p>
|
||||
|
||||
{/* Buttons */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Buttons
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Variantes</h3>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Button variant="primary">Primary</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="success">Success</Button>
|
||||
<Button variant="danger">Danger</Button>
|
||||
<Button variant="ghost">Ghost</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<Button variant="primary" size="sm">
|
||||
Small
|
||||
</Button>
|
||||
<Button variant="primary" size="md">
|
||||
Medium
|
||||
</Button>
|
||||
<Button variant="primary" size="lg">
|
||||
Large
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">États</h3>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Button variant="primary">Normal</Button>
|
||||
<Button variant="primary" disabled>
|
||||
Disabled
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Inputs */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Inputs</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Types</h3>
|
||||
<div className="space-y-4 max-w-md">
|
||||
<Input
|
||||
label="Text Input"
|
||||
type="text"
|
||||
placeholder="Entrez du texte"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
/>
|
||||
<Input
|
||||
label="Email Input"
|
||||
type="email"
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
<Input
|
||||
label="Password Input"
|
||||
type="password"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
<Input
|
||||
label="Number Input"
|
||||
type="number"
|
||||
placeholder="123"
|
||||
/>
|
||||
<Input
|
||||
label="Date Input"
|
||||
type="date"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Avec erreur</h3>
|
||||
<div className="max-w-md">
|
||||
<Input
|
||||
label="Input avec erreur"
|
||||
type="text"
|
||||
error="Ce champ est requis"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Textarea */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Textarea
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Basique</h3>
|
||||
<div className="max-w-md">
|
||||
<Textarea
|
||||
label="Commentaire"
|
||||
placeholder="Écrivez votre commentaire..."
|
||||
value={textareaValue}
|
||||
onChange={(e) => setTextareaValue(e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">
|
||||
Avec compteur de caractères
|
||||
</h3>
|
||||
<div className="max-w-md">
|
||||
<Textarea
|
||||
label="Bio"
|
||||
placeholder="Parlez-nous de vous..."
|
||||
value={textareaValue}
|
||||
onChange={(e) => setTextareaValue(e.target.value)}
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
showCharCount
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Avec erreur</h3>
|
||||
<div className="max-w-md">
|
||||
<Textarea
|
||||
label="Textarea avec erreur"
|
||||
placeholder="Écrivez quelque chose..."
|
||||
error="Ce champ est requis"
|
||||
value={textareaValue}
|
||||
onChange={(e) => setTextareaValue(e.target.value)}
|
||||
rows={4}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Badges */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Badges</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Variantes</h3>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Badge variant="default">Default</Badge>
|
||||
<Badge variant="success">Success</Badge>
|
||||
<Badge variant="warning">Warning</Badge>
|
||||
<Badge variant="danger">Danger</Badge>
|
||||
<Badge variant="info">Info</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<Badge variant="default" size="sm">
|
||||
Small
|
||||
</Badge>
|
||||
<Badge variant="default" size="md">
|
||||
Medium
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Alerts */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Alerts</h2>
|
||||
<div className="space-y-4 max-w-md">
|
||||
<Alert variant="success">
|
||||
Opération réussie ! Votre action a été effectuée avec succès.
|
||||
</Alert>
|
||||
<Alert variant="error">
|
||||
Une erreur est survenue. Veuillez réessayer.
|
||||
</Alert>
|
||||
<Alert variant="warning">
|
||||
Attention ! Cette action est irréversible.
|
||||
</Alert>
|
||||
<Alert variant="info">
|
||||
Information : Voici quelques informations utiles.
|
||||
</Alert>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Cards */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Cards</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Card variant="default" className="p-4">
|
||||
<h3 className="text-lg font-bold text-pixel-gold mb-2">
|
||||
Card Default
|
||||
</h3>
|
||||
<p className="text-gray-300 text-sm">
|
||||
Contenu de la carte avec variant default
|
||||
</p>
|
||||
</Card>
|
||||
<Card variant="dark" className="p-4">
|
||||
<h3 className="text-lg font-bold text-pixel-gold mb-2">
|
||||
Card Dark
|
||||
</h3>
|
||||
<p className="text-gray-300 text-sm">
|
||||
Contenu de la carte avec variant dark
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Progress Bars */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Progress Bars
|
||||
</h2>
|
||||
<div className="space-y-6 max-w-md">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">HP Bar (High)</h3>
|
||||
<ProgressBar
|
||||
value={75}
|
||||
max={100}
|
||||
variant="hp"
|
||||
showLabel
|
||||
label="HP"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">HP Bar (Medium)</h3>
|
||||
<ProgressBar
|
||||
value={45}
|
||||
max={100}
|
||||
variant="hp"
|
||||
showLabel
|
||||
label="HP"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">HP Bar (Low)</h3>
|
||||
<ProgressBar
|
||||
value={20}
|
||||
max={100}
|
||||
variant="hp"
|
||||
showLabel
|
||||
label="HP"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">XP Bar</h3>
|
||||
<ProgressBar
|
||||
value={60}
|
||||
max={100}
|
||||
variant="xp"
|
||||
showLabel
|
||||
label="XP"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Default</h3>
|
||||
<ProgressBar
|
||||
value={50}
|
||||
max={100}
|
||||
variant="default"
|
||||
showLabel
|
||||
label="Progress"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Sans label</h3>
|
||||
<ProgressBar value={60} max={100} variant="default" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Star Rating */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Star Rating
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Interactif</h3>
|
||||
<StarRating
|
||||
value={rating}
|
||||
onChange={setRating}
|
||||
showValue
|
||||
/>
|
||||
<p className="text-gray-400 text-sm mt-2">
|
||||
Note sélectionnée : {rating}/5
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<p className="text-gray-400 text-sm mb-2">Small</p>
|
||||
<StarRating value={4} size="sm" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-400 text-sm mb-2">Medium</p>
|
||||
<StarRating value={4} size="md" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-400 text-sm mb-2">Large</p>
|
||||
<StarRating value={4} size="lg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Avatar */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Avatar</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<Avatar
|
||||
src="/avatar-1.jpg"
|
||||
username="User"
|
||||
size="sm"
|
||||
/>
|
||||
<Avatar
|
||||
src="/avatar-2.jpg"
|
||||
username="User"
|
||||
size="md"
|
||||
/>
|
||||
<Avatar
|
||||
src="/avatar-3.jpg"
|
||||
username="User"
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">
|
||||
Sans image (fallback)
|
||||
</h3>
|
||||
<Avatar username="John Doe" size="lg" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Section Title */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Section Title
|
||||
</h2>
|
||||
<div className="space-y-8">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Variantes</h3>
|
||||
<div className="space-y-4">
|
||||
<SectionTitle variant="default" size="md">
|
||||
Default Title
|
||||
</SectionTitle>
|
||||
<SectionTitle variant="gradient" size="md">
|
||||
Gradient Title
|
||||
</SectionTitle>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="space-y-4">
|
||||
<SectionTitle variant="gradient" size="sm">
|
||||
Small Title
|
||||
</SectionTitle>
|
||||
<SectionTitle variant="gradient" size="md">
|
||||
Medium Title
|
||||
</SectionTitle>
|
||||
<SectionTitle variant="gradient" size="lg">
|
||||
Large Title
|
||||
</SectionTitle>
|
||||
<SectionTitle variant="gradient" size="xl">
|
||||
Extra Large Title
|
||||
</SectionTitle>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Avec sous-titre</h3>
|
||||
<SectionTitle
|
||||
variant="gradient"
|
||||
size="lg"
|
||||
subtitle="Un sous-titre descriptif"
|
||||
>
|
||||
Title with Subtitle
|
||||
</SectionTitle>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Modal */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Modal</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<Button onClick={() => setModalOpen(true)}>
|
||||
Ouvrir Modal
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Close Button */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">
|
||||
Close Button
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<CloseButton onClick={() => {}} size="sm" />
|
||||
<CloseButton onClick={() => {}} size="md" />
|
||||
<CloseButton onClick={() => {}} size="lg" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Disabled</h3>
|
||||
<CloseButton onClick={() => {}} disabled />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Modal Demo */}
|
||||
<Modal
|
||||
isOpen={modalOpen}
|
||||
onClose={() => setModalOpen(false)}
|
||||
size="md"
|
||||
>
|
||||
<div className="p-8">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold">
|
||||
Exemple de Modal
|
||||
</h2>
|
||||
<CloseButton onClick={() => setModalOpen(false)} />
|
||||
</div>
|
||||
<p className="text-gray-300 mb-6">
|
||||
Ceci est un exemple de modal avec différentes tailles
|
||||
disponibles.
|
||||
</p>
|
||||
<div className="flex gap-4">
|
||||
<Button onClick={() => setModalOpen(false)}>Fermer</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</BackgroundSection>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,15 @@ 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;
|
||||
@@ -156,25 +165,17 @@ export default function FeedbackPageClient({
|
||||
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">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: `url('${backgroundImage}')`,
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||
</div>
|
||||
|
||||
<BackgroundSection backgroundImage={backgroundImage} className="pt-24">
|
||||
{/* Feedback Form */}
|
||||
<div className="relative z-10 w-full max-w-2xl mx-auto px-8">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-8 backdrop-blur-sm">
|
||||
<h1 className="text-4xl font-gaming font-black mb-2 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
FEEDBACK
|
||||
</span>
|
||||
</h1>
|
||||
<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"
|
||||
@@ -185,15 +186,15 @@ export default function FeedbackPageClient({
|
||||
</p>
|
||||
|
||||
{success && (
|
||||
<div className="bg-green-900/50 border border-green-500/50 text-green-400 px-4 py-3 rounded text-sm mb-6">
|
||||
<Alert variant="success" className="mb-6">
|
||||
Feedback enregistré avec succès ! Redirection...
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm mb-6">
|
||||
<Alert variant="error" className="mb-6">
|
||||
{error}
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
@@ -202,66 +203,44 @@ export default function FeedbackPageClient({
|
||||
<label className="block text-sm font-semibold text-gray-300 mb-4 uppercase tracking-wider">
|
||||
Note
|
||||
</label>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
{[1, 2, 3, 4, 5].map((star) => (
|
||||
<button
|
||||
key={star}
|
||||
type="button"
|
||||
onClick={() => 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" : ""}`}
|
||||
>
|
||||
★
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-gray-500 text-xs text-center mt-2">
|
||||
{rating > 0 && `${rating}/5`}
|
||||
</p>
|
||||
<StarRating
|
||||
value={rating}
|
||||
onChange={setRating}
|
||||
size="lg"
|
||||
showValue
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Comment */}
|
||||
<div>
|
||||
<label
|
||||
htmlFor="comment"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Commentaire (optionnel)
|
||||
</label>
|
||||
<textarea
|
||||
id="comment"
|
||||
value={comment}
|
||||
onChange={(e) => 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..."
|
||||
/>
|
||||
<p className="text-gray-500 text-xs mt-1 text-right">
|
||||
{comment.length}/1000 caractères
|
||||
</p>
|
||||
</div>
|
||||
<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
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
disabled={submitting || rating === 0}
|
||||
className="w-full px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="w-full"
|
||||
>
|
||||
{submitting
|
||||
? "Enregistrement..."
|
||||
: existingFeedback
|
||||
? "Modifier le feedback"
|
||||
: "Envoyer le feedback"}
|
||||
</button>
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
</BackgroundSection>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,4 +31,17 @@
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-shimmer {
|
||||
animation: shimmer 2s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ import { signIn } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Navigation from "@/components/Navigation";
|
||||
import {
|
||||
Input,
|
||||
Button,
|
||||
Alert,
|
||||
Card,
|
||||
BackgroundSection,
|
||||
SectionTitle,
|
||||
} from "@/components/ui";
|
||||
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
@@ -46,79 +54,53 @@ export default function LoginPage() {
|
||||
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">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: `url('/got-2.jpg')`,
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||
</div>
|
||||
|
||||
<BackgroundSection backgroundImage="/got-2.jpg" className="pt-24">
|
||||
{/* Login Form */}
|
||||
<div className="relative z-10 w-full max-w-md mx-auto px-8">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-8 backdrop-blur-sm">
|
||||
<h1 className="text-4xl font-gaming font-black mb-2 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
CONNEXION
|
||||
</span>
|
||||
</h1>
|
||||
<div className="w-full max-w-md mx-auto px-8">
|
||||
<Card variant="dark" className="p-8">
|
||||
<SectionTitle
|
||||
variant="gradient"
|
||||
size="lg"
|
||||
className="mb-2 text-center"
|
||||
>
|
||||
CONNEXION
|
||||
</SectionTitle>
|
||||
<p className="text-gray-400 text-sm text-center mb-8">
|
||||
Connectez-vous à votre compte
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
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"
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
label="Email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
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"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
label="Mot de passe"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
|
||||
<button
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
disabled={loading}
|
||||
className="w-full px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="w-full"
|
||||
>
|
||||
{loading ? "Connexion..." : "Se connecter"}
|
||||
</button>
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
@@ -132,9 +114,9 @@ export default function LoginPage() {
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
</BackgroundSection>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,16 @@ import { useState, useRef, type ChangeEvent, type FormEvent } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Navigation from "@/components/Navigation";
|
||||
import Avatar from "@/components/Avatar";
|
||||
import {
|
||||
Avatar,
|
||||
Input,
|
||||
Textarea,
|
||||
Button,
|
||||
Alert,
|
||||
Card,
|
||||
BackgroundSection,
|
||||
SectionTitle,
|
||||
} from "@/components/ui";
|
||||
|
||||
export default function RegisterPage() {
|
||||
const router = useRouter();
|
||||
@@ -162,25 +171,17 @@ export default function RegisterPage() {
|
||||
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">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: `url('/got-2.jpg')`,
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||
</div>
|
||||
|
||||
<BackgroundSection backgroundImage="/got-2.jpg" className="pt-24">
|
||||
{/* Register Form */}
|
||||
<div className="relative z-10 w-full max-w-md mx-auto px-8">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-8 backdrop-blur-sm">
|
||||
<h1 className="text-4xl font-gaming font-black mb-2 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
INSCRIPTION
|
||||
</span>
|
||||
</h1>
|
||||
<div className="w-full max-w-md mx-auto px-8">
|
||||
<Card variant="dark" className="p-8">
|
||||
<SectionTitle
|
||||
variant="gradient"
|
||||
size="lg"
|
||||
className="mb-2 text-center"
|
||||
>
|
||||
INSCRIPTION
|
||||
</SectionTitle>
|
||||
<p className="text-gray-400 text-sm text-center mb-4">
|
||||
{step === 1
|
||||
? "Créez votre compte pour commencer"
|
||||
@@ -216,103 +217,65 @@ export default function RegisterPage() {
|
||||
|
||||
{step === 1 ? (
|
||||
<form onSubmit={handleStep1Submit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
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"
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
label="Email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="username"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Nom d'utilisateur
|
||||
</label>
|
||||
<input
|
||||
id="username"
|
||||
name="username"
|
||||
type="text"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
required
|
||||
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"
|
||||
placeholder="VotrePseudo"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="username"
|
||||
name="username"
|
||||
type="text"
|
||||
label="Nom d'utilisateur"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="VotrePseudo"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
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"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
label="Mot de passe"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="confirmPassword"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Confirmer le mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="confirmPassword"
|
||||
name="confirmPassword"
|
||||
type="password"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleChange}
|
||||
required
|
||||
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"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="confirmPassword"
|
||||
name="confirmPassword"
|
||||
type="password"
|
||||
label="Confirmer le mot de passe"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
|
||||
<button
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
disabled={loading}
|
||||
className="w-full px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="w-full"
|
||||
>
|
||||
{loading ? "Création..." : "Suivant"}
|
||||
</button>
|
||||
</Button>
|
||||
</form>
|
||||
) : (
|
||||
<form onSubmit={handleStep2Submit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
|
||||
{/* Avatar Selection */}
|
||||
<div>
|
||||
@@ -387,61 +350,47 @@ export default function RegisterPage() {
|
||||
className="hidden"
|
||||
id="avatar-upload"
|
||||
/>
|
||||
<label
|
||||
htmlFor="avatar-upload"
|
||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition cursor-pointer inline-block"
|
||||
>
|
||||
{uploadingAvatar
|
||||
? "Upload en cours..."
|
||||
: "Upload un avatar custom"}
|
||||
<label htmlFor="avatar-upload">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="md"
|
||||
as="span"
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{uploadingAvatar
|
||||
? "Upload en cours..."
|
||||
: "Upload un avatar custom"}
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="username-step2"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Nom d'utilisateur
|
||||
</label>
|
||||
<input
|
||||
id="username-step2"
|
||||
name="username"
|
||||
type="text"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
required
|
||||
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"
|
||||
placeholder="VotrePseudo"
|
||||
minLength={3}
|
||||
maxLength={20}
|
||||
/>
|
||||
<p className="text-gray-500 text-xs mt-1">3-20 caractères</p>
|
||||
</div>
|
||||
<Input
|
||||
id="username-step2"
|
||||
name="username"
|
||||
type="text"
|
||||
label="Nom d'utilisateur"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
required
|
||||
placeholder="VotrePseudo"
|
||||
minLength={3}
|
||||
maxLength={20}
|
||||
/>
|
||||
<p className="text-gray-500 text-xs mt-1">3-20 caractères</p>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="bio"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Bio (optionnel)
|
||||
</label>
|
||||
<textarea
|
||||
id="bio"
|
||||
name="bio"
|
||||
value={formData.bio}
|
||||
onChange={handleChange}
|
||||
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"
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
placeholder="Parlez-nous de vous..."
|
||||
/>
|
||||
<p className="text-gray-500 text-xs mt-1">
|
||||
{formData.bio.length}/500 caractères
|
||||
</p>
|
||||
</div>
|
||||
<Textarea
|
||||
id="bio"
|
||||
name="bio"
|
||||
label="Bio (optionnel)"
|
||||
value={formData.bio}
|
||||
onChange={handleChange}
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
showCharCount
|
||||
placeholder="Parlez-nous de vous..."
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-gray-300 mb-3 uppercase tracking-wider">
|
||||
@@ -500,20 +449,24 @@ export default function RegisterPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
onClick={() => setStep(1)}
|
||||
className="flex-1 px-6 py-3 border border-gray-600/50 bg-black/40 text-gray-400 uppercase text-sm tracking-widest rounded hover:bg-gray-900/40 hover:border-gray-500 transition"
|
||||
className="flex-1"
|
||||
>
|
||||
Retour
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
disabled={loading}
|
||||
className="flex-1 px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="flex-1"
|
||||
>
|
||||
{loading ? "Finalisation..." : "Terminer"}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)}
|
||||
@@ -529,9 +482,9 @@ export default function RegisterPage() {
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
</BackgroundSection>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user