Compare commits
2 Commits
f0c9a9e4cc
...
6c08789555
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c08789555 | ||
|
|
7dbd044859 |
@@ -69,18 +69,64 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative w-full min-h-screen flex flex-col items-center overflow-hidden pt-24 pb-16">
|
<section className="relative w-full min-h-screen flex flex-col items-center overflow-hidden pt-24 pb-16">
|
||||||
<div className="relative z-10 w-full max-w-6xl mx-auto px-8 py-16">
|
<div className="relative z-10 w-full max-w-6xl mx-auto px-4 sm:px-8 py-16">
|
||||||
<h1 className="text-4xl font-gaming font-black mb-8 text-center">
|
<h1 className="text-2xl sm:text-4xl font-gaming font-black mb-8 text-center break-words">
|
||||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||||
ADMIN
|
ADMIN
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{/* Navigation Tabs */}
|
{/* Navigation Tabs */}
|
||||||
<div className="flex gap-4 mb-8 justify-center">
|
<div className="mb-8">
|
||||||
|
{/* Mobile: Grid layout */}
|
||||||
|
<div className="grid grid-cols-2 sm:hidden gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveSection("preferences")}
|
onClick={() => setActiveSection("preferences")}
|
||||||
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition ${
|
className={`px-3 py-2.5 border uppercase text-xs tracking-wider rounded transition ${
|
||||||
|
activeSection === "preferences"
|
||||||
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold font-semibold"
|
||||||
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Préférences
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveSection("users")}
|
||||||
|
className={`px-3 py-2.5 border uppercase text-xs tracking-wider rounded transition ${
|
||||||
|
activeSection === "users"
|
||||||
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold font-semibold"
|
||||||
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Utilisateurs
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveSection("events")}
|
||||||
|
className={`px-3 py-2.5 border uppercase text-xs tracking-wider rounded transition ${
|
||||||
|
activeSection === "events"
|
||||||
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold font-semibold"
|
||||||
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Événements
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveSection("feedbacks")}
|
||||||
|
className={`px-3 py-2.5 border uppercase text-xs tracking-wider rounded transition ${
|
||||||
|
activeSection === "feedbacks"
|
||||||
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold font-semibold"
|
||||||
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Feedbacks
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop: Horizontal tabs */}
|
||||||
|
<div className="hidden sm:flex gap-4 justify-center">
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveSection("preferences")}
|
||||||
|
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition whitespace-nowrap ${
|
||||||
activeSection === "preferences"
|
activeSection === "preferences"
|
||||||
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
||||||
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
@@ -90,7 +136,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveSection("users")}
|
onClick={() => setActiveSection("users")}
|
||||||
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition ${
|
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition whitespace-nowrap ${
|
||||||
activeSection === "users"
|
activeSection === "users"
|
||||||
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
||||||
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
@@ -100,7 +146,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveSection("events")}
|
onClick={() => setActiveSection("events")}
|
||||||
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition ${
|
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition whitespace-nowrap ${
|
||||||
activeSection === "events"
|
activeSection === "events"
|
||||||
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
||||||
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
@@ -110,7 +156,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveSection("feedbacks")}
|
onClick={() => setActiveSection("feedbacks")}
|
||||||
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition ${
|
className={`px-6 py-3 border uppercase text-xs tracking-widest rounded transition whitespace-nowrap ${
|
||||||
activeSection === "feedbacks"
|
activeSection === "feedbacks"
|
||||||
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/10 text-pixel-gold"
|
||||||
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
: "border-pixel-gold/30 bg-black/60 text-gray-400 hover:border-pixel-gold/50"
|
||||||
@@ -119,27 +165,28 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
Feedbacks
|
Feedbacks
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{activeSection === "preferences" && (
|
{activeSection === "preferences" && (
|
||||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-4 sm:p-6 backdrop-blur-sm">
|
||||||
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
<h2 className="text-xl sm:text-2xl font-gaming font-bold mb-6 text-pixel-gold break-words">
|
||||||
Préférences UI Globales
|
Préférences UI Globales
|
||||||
</h2>
|
</h2>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="bg-black/60 border border-pixel-gold/20 rounded p-4">
|
<div className="bg-black/60 border border-pixel-gold/20 rounded p-3 sm:p-4">
|
||||||
<div className="flex justify-between items-start mb-4">
|
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-4">
|
||||||
<div>
|
<div className="min-w-0 flex-1">
|
||||||
<h3 className="text-pixel-gold font-bold text-lg">
|
<h3 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||||
Images de fond du site
|
Images de fond du site
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-gray-400 text-sm">
|
<p className="text-gray-400 text-xs sm:text-sm">
|
||||||
Ces préférences s'appliquent à tous les utilisateurs
|
Ces préférences s'appliquent à tous les utilisateurs
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{!isEditing && (
|
{!isEditing && (
|
||||||
<button
|
<button
|
||||||
onClick={handleEdit}
|
onClick={handleEdit}
|
||||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
className="px-3 sm:px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap flex-shrink-0"
|
||||||
>
|
>
|
||||||
Modifier
|
Modifier
|
||||||
</button>
|
</button>
|
||||||
@@ -178,7 +225,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
}
|
}
|
||||||
label="Background Leaderboard"
|
label="Background Leaderboard"
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-2 pt-4">
|
<div className="flex flex-col sm:flex-row gap-2 pt-4">
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
className="px-4 py-2 border border-green-500/50 bg-green-900/20 text-green-400 uppercase text-xs tracking-widest rounded hover:bg-green-900/30 transition"
|
className="px-4 py-2 border border-green-500/50 bg-green-900/20 text-green-400 uppercase text-xs tracking-widest rounded hover:bg-green-900/30 transition"
|
||||||
@@ -195,70 +242,76 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||||
Home:
|
Home:
|
||||||
</span>
|
</span>
|
||||||
{preferences?.homeBackground ? (
|
{preferences?.homeBackground ? (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-2 sm:gap-3 min-w-0 flex-1">
|
||||||
<img
|
<img
|
||||||
src={preferences.homeBackground}
|
src={preferences.homeBackground}
|
||||||
alt="Home background"
|
alt="Home background"
|
||||||
className="w-20 h-12 object-cover rounded border border-pixel-gold/30"
|
className="w-16 h-10 sm:w-20 sm:h-12 object-cover rounded border border-pixel-gold/30 flex-shrink-0"
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
e.currentTarget.src = "/got-2.jpg";
|
e.currentTarget.src = "/got-2.jpg";
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-gray-400 truncate max-w-xs">
|
<span className="text-xs text-gray-400 truncate min-w-0">
|
||||||
{preferences.homeBackground}
|
{preferences.homeBackground}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-gray-400">Par défaut</span>
|
<span className="text-gray-400 text-sm sm:text-base">
|
||||||
|
Par défaut
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||||
Events:
|
Events:
|
||||||
</span>
|
</span>
|
||||||
{preferences?.eventsBackground ? (
|
{preferences?.eventsBackground ? (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-2 sm:gap-3 min-w-0 flex-1">
|
||||||
<img
|
<img
|
||||||
src={preferences.eventsBackground}
|
src={preferences.eventsBackground}
|
||||||
alt="Events background"
|
alt="Events background"
|
||||||
className="w-20 h-12 object-cover rounded border border-pixel-gold/30"
|
className="w-16 h-10 sm:w-20 sm:h-12 object-cover rounded border border-pixel-gold/30 flex-shrink-0"
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
e.currentTarget.src = "/got-2.jpg";
|
e.currentTarget.src = "/got-2.jpg";
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-gray-400 truncate max-w-xs">
|
<span className="text-xs text-gray-400 truncate min-w-0">
|
||||||
{preferences.eventsBackground}
|
{preferences.eventsBackground}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-gray-400">Par défaut</span>
|
<span className="text-gray-400 text-sm sm:text-base">
|
||||||
|
Par défaut
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||||
Leaderboard:
|
Leaderboard:
|
||||||
</span>
|
</span>
|
||||||
{preferences?.leaderboardBackground ? (
|
{preferences?.leaderboardBackground ? (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-2 sm:gap-3 min-w-0 flex-1">
|
||||||
<img
|
<img
|
||||||
src={preferences.leaderboardBackground}
|
src={preferences.leaderboardBackground}
|
||||||
alt="Leaderboard background"
|
alt="Leaderboard background"
|
||||||
className="w-20 h-12 object-cover rounded border border-pixel-gold/30"
|
className="w-16 h-10 sm:w-20 sm:h-12 object-cover rounded border border-pixel-gold/30 flex-shrink-0"
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
e.currentTarget.src = "/got-2.jpg";
|
e.currentTarget.src = "/got-2.jpg";
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-gray-400 truncate max-w-xs">
|
<span className="text-xs text-gray-400 truncate min-w-0">
|
||||||
{preferences.leaderboardBackground}
|
{preferences.leaderboardBackground}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-gray-400">Par défaut</span>
|
<span className="text-gray-400 text-sm sm:text-base">
|
||||||
|
Par défaut
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -269,7 +322,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeSection === "users" && (
|
{activeSection === "users" && (
|
||||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-4 sm:p-6 backdrop-blur-sm">
|
||||||
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
||||||
Gestion des Utilisateurs
|
Gestion des Utilisateurs
|
||||||
</h2>
|
</h2>
|
||||||
@@ -278,7 +331,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeSection === "events" && (
|
{activeSection === "events" && (
|
||||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-4 sm:p-6 backdrop-blur-sm">
|
||||||
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
||||||
Gestion des Événements
|
Gestion des Événements
|
||||||
</h2>
|
</h2>
|
||||||
@@ -287,7 +340,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeSection === "feedbacks" && (
|
{activeSection === "feedbacks" && (
|
||||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-4 sm:p-6 backdrop-blur-sm">
|
||||||
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
||||||
Gestion des Feedbacks
|
Gestion des Feedbacks
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -213,14 +213,14 @@ export default function EventManagement() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4">
|
||||||
<h3 className="text-xl font-gaming font-bold text-pixel-gold">
|
<h3 className="text-lg sm:text-xl font-gaming font-bold text-pixel-gold break-words">
|
||||||
Événements ({events.length})
|
Événements ({events.length})
|
||||||
</h3>
|
</h3>
|
||||||
{!isCreating && !editingEvent && (
|
{!isCreating && !editingEvent && (
|
||||||
<button
|
<button
|
||||||
onClick={handleCreate}
|
onClick={handleCreate}
|
||||||
className="px-4 py-2 border border-green-500/50 bg-green-900/20 text-green-400 uppercase text-xs tracking-widest rounded hover:bg-green-900/30 transition"
|
className="px-3 sm:px-4 py-2 border border-green-500/50 bg-green-900/20 text-green-400 uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-green-900/30 transition whitespace-nowrap flex-shrink-0"
|
||||||
>
|
>
|
||||||
+ Nouvel événement
|
+ Nouvel événement
|
||||||
</button>
|
</button>
|
||||||
@@ -228,24 +228,28 @@ export default function EventManagement() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(isCreating || editingEvent) && (
|
{(isCreating || editingEvent) && (
|
||||||
<div className="bg-black/60 border border-pixel-gold/20 rounded p-4 mb-4">
|
<div className="bg-black/60 border border-pixel-gold/20 rounded p-3 sm:p-4 mb-4">
|
||||||
<h4 className="text-pixel-gold font-bold mb-4">
|
<h4 className="text-pixel-gold font-bold mb-4 text-base sm:text-lg break-words">
|
||||||
{isCreating ? "Créer un événement" : "Modifier l'événement"}
|
{isCreating ? "Créer un événement" : "Modifier l'événement"}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">Date</label>
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
|
Date
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
value={formData.date}
|
value={formData.date}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setFormData({ ...formData, date: e.target.value })
|
setFormData({ ...formData, date: e.target.value })
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">Nom</label>
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
|
Nom
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.name}
|
value={formData.name}
|
||||||
@@ -253,11 +257,11 @@ export default function EventManagement() {
|
|||||||
setFormData({ ...formData, name: e.target.value })
|
setFormData({ ...formData, name: e.target.value })
|
||||||
}
|
}
|
||||||
placeholder="Nom de l'événement"
|
placeholder="Nom de l'événement"
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
Description
|
Description
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -267,12 +271,14 @@ export default function EventManagement() {
|
|||||||
}
|
}
|
||||||
placeholder="Description de l'événement"
|
placeholder="Description de l'événement"
|
||||||
rows={4}
|
rows={4}
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">Type</label>
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
|
Type
|
||||||
|
</label>
|
||||||
<select
|
<select
|
||||||
value={formData.type}
|
value={formData.type}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -281,7 +287,7 @@ export default function EventManagement() {
|
|||||||
type: e.target.value as Event["type"],
|
type: e.target.value as Event["type"],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
>
|
>
|
||||||
{eventTypes.map((type) => (
|
{eventTypes.map((type) => (
|
||||||
<option key={type} value={type}>
|
<option key={type} value={type}>
|
||||||
@@ -291,9 +297,9 @@ export default function EventManagement() {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
Salle
|
Salle
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -303,11 +309,11 @@ export default function EventManagement() {
|
|||||||
setFormData({ ...formData, room: e.target.value })
|
setFormData({ ...formData, room: e.target.value })
|
||||||
}
|
}
|
||||||
placeholder="Ex: Nautilus"
|
placeholder="Ex: Nautilus"
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
Heure
|
Heure
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -317,11 +323,11 @@ export default function EventManagement() {
|
|||||||
setFormData({ ...formData, time: e.target.value })
|
setFormData({ ...formData, time: e.target.value })
|
||||||
}
|
}
|
||||||
placeholder="Ex: 11h-12h"
|
placeholder="Ex: 11h-12h"
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-1">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||||
Places max
|
Places max
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -336,11 +342,11 @@ export default function EventManagement() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
placeholder="Ex: 25"
|
placeholder="Ex: 25"
|
||||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex flex-col sm:flex-row gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -368,19 +374,19 @@ export default function EventManagement() {
|
|||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<div
|
<div
|
||||||
key={event.id}
|
key={event.id}
|
||||||
className="bg-black/60 border border-pixel-gold/20 rounded p-4"
|
className="bg-black/60 border border-pixel-gold/20 rounded p-3 sm:p-4"
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3">
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-3 mb-2">
|
<div className="flex flex-wrap items-center gap-2 sm:gap-3 mb-2">
|
||||||
<h4 className="text-pixel-gold font-bold text-lg">
|
<h4 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||||
{event.name}
|
{event.name}
|
||||||
</h4>
|
</h4>
|
||||||
<span className="px-2 py-1 bg-pixel-gold/20 border border-pixel-gold/50 text-pixel-gold text-xs uppercase rounded">
|
<span className="px-2 py-1 bg-pixel-gold/20 border border-pixel-gold/50 text-pixel-gold text-[10px] sm:text-xs uppercase rounded whitespace-nowrap flex-shrink-0">
|
||||||
{getEventTypeLabel(event.type)}
|
{getEventTypeLabel(event.type)}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`px-2 py-1 text-xs uppercase rounded ${(() => {
|
className={`px-2 py-1 text-[10px] sm:text-xs uppercase rounded whitespace-nowrap flex-shrink-0 ${(() => {
|
||||||
const status = calculateEventStatus(event.date);
|
const status = calculateEventStatus(event.date);
|
||||||
return status === "UPCOMING"
|
return status === "UPCOMING"
|
||||||
? "bg-green-900/50 border border-green-500/50 text-green-400"
|
? "bg-green-900/50 border border-green-500/50 text-green-400"
|
||||||
@@ -392,45 +398,45 @@ export default function EventManagement() {
|
|||||||
{getStatusLabel(calculateEventStatus(event.date))}
|
{getStatusLabel(calculateEventStatus(event.date))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-gray-400 text-sm mb-2">
|
<p className="text-gray-400 text-xs sm:text-sm mb-2 break-words">
|
||||||
{event.description}
|
{event.description}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap items-center gap-4 mt-2">
|
<div className="flex flex-wrap items-center gap-2 sm:gap-4 mt-2">
|
||||||
<p className="text-gray-500 text-xs">
|
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||||
Date: {new Date(event.date).toLocaleDateString("fr-FR")}
|
Date: {new Date(event.date).toLocaleDateString("fr-FR")}
|
||||||
</p>
|
</p>
|
||||||
{event.room && (
|
{event.room && (
|
||||||
<p className="text-gray-500 text-xs">
|
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||||
📍 Salle: {event.room}
|
📍 Salle: {event.room}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{event.time && (
|
{event.time && (
|
||||||
<p className="text-gray-500 text-xs">
|
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||||
🕐 Heure: {event.time}
|
🕐 Heure: {event.time}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{event.maxPlaces && (
|
{event.maxPlaces && (
|
||||||
<p className="text-gray-500 text-xs">
|
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||||
👥 Places: {event.maxPlaces}
|
👥 Places: {event.maxPlaces}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<span className="px-2 py-1 bg-blue-900/30 border border-blue-500/50 text-blue-400 text-xs rounded">
|
<span className="px-2 py-1 bg-blue-900/30 border border-blue-500/50 text-blue-400 text-[10px] sm:text-xs rounded whitespace-nowrap flex-shrink-0">
|
||||||
{event.registrationsCount || 0} inscrit
|
{event.registrationsCount || 0} inscrit
|
||||||
{event.registrationsCount !== 1 ? "s" : ""}
|
{event.registrationsCount !== 1 ? "s" : ""}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!isCreating && !editingEvent && (
|
{!isCreating && !editingEvent && (
|
||||||
<div className="flex gap-2 ml-4">
|
<div className="flex gap-2 sm:ml-4 flex-shrink-0">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdit(event)}
|
onClick={() => handleEdit(event)}
|
||||||
className="px-3 py-1 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
className="px-2 sm:px-3 py-1 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap"
|
||||||
>
|
>
|
||||||
Modifier
|
Modifier
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDelete(event.id)}
|
onClick={() => handleDelete(event.id)}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-xs tracking-widest rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-red-900/30 transition whitespace-nowrap"
|
||||||
>
|
>
|
||||||
Supprimer
|
Supprimer
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -74,18 +74,20 @@ export default function FeedbackManagement() {
|
|||||||
|
|
||||||
const renderStars = (rating: number) => {
|
const renderStars = (rating: number) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-0.5 sm:gap-1">
|
||||||
{[1, 2, 3, 4, 5].map((star) => (
|
{[1, 2, 3, 4, 5].map((star) => (
|
||||||
<span
|
<span
|
||||||
key={star}
|
key={star}
|
||||||
className={`text-lg ${
|
className={`text-sm sm:text-lg ${
|
||||||
star <= rating ? "text-pixel-gold" : "text-gray-600"
|
star <= rating ? "text-pixel-gold" : "text-gray-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
★
|
★
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
<span className="text-gray-400 text-sm ml-2">({rating}/5)</span>
|
<span className="text-gray-400 text-xs sm:text-sm ml-1 sm:ml-2">
|
||||||
|
({rating}/5)
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -96,25 +98,25 @@ export default function FeedbackManagement() {
|
|||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-8">
|
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-4 sm:p-8">
|
||||||
<p className="text-gray-400 text-center">Chargement...</p>
|
<p className="text-gray-400 text-center text-sm">Chargement...</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-4 sm:space-y-6">
|
||||||
{/* Statistiques par événement */}
|
{/* Statistiques par événement */}
|
||||||
{statistics.length > 0 && (
|
{statistics.length > 0 && (
|
||||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-6">
|
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-3 sm:p-6">
|
||||||
<h3 className="text-pixel-gold font-bold text-lg mb-4">
|
<h3 className="text-pixel-gold font-bold text-base sm:text-lg mb-4 break-words">
|
||||||
Statistiques par événement
|
Statistiques par événement
|
||||||
</h3>
|
</h3>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4">
|
||||||
{statistics.map((stat) => (
|
{statistics.map((stat) => (
|
||||||
<div
|
<div
|
||||||
key={stat.eventId}
|
key={stat.eventId}
|
||||||
className={`bg-black/40 border rounded p-4 cursor-pointer transition ${
|
className={`bg-black/40 border rounded p-3 sm:p-4 cursor-pointer transition ${
|
||||||
selectedEvent === stat.eventId
|
selectedEvent === stat.eventId
|
||||||
? "border-pixel-gold bg-pixel-gold/10"
|
? "border-pixel-gold bg-pixel-gold/10"
|
||||||
: "border-pixel-gold/30 hover:border-pixel-gold/50"
|
: "border-pixel-gold/30 hover:border-pixel-gold/50"
|
||||||
@@ -125,21 +127,21 @@ export default function FeedbackManagement() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex items-start justify-between mb-2">
|
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-2 mb-2">
|
||||||
<h4 className="text-white font-semibold text-sm">
|
<h4 className="text-white font-semibold text-xs sm:text-sm break-words">
|
||||||
{stat.eventName}
|
{stat.eventName}
|
||||||
</h4>
|
</h4>
|
||||||
<span className="text-pixel-gold text-xs uppercase">
|
<span className="text-pixel-gold text-[10px] sm:text-xs uppercase whitespace-nowrap flex-shrink-0">
|
||||||
{stat.eventType && getEventTypeLabel(stat.eventType)}
|
{stat.eventType && getEventTypeLabel(stat.eventType)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
{renderStars(Math.round(stat.averageRating))}
|
{renderStars(Math.round(stat.averageRating))}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-400 text-xs">
|
<div className="text-gray-400 text-[10px] sm:text-xs">
|
||||||
Moyenne: {stat.averageRating.toFixed(2)}/5
|
Moyenne: {stat.averageRating.toFixed(2)}/5
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-400 text-xs">
|
<div className="text-gray-400 text-[10px] sm:text-xs">
|
||||||
{stat.feedbackCount} feedback
|
{stat.feedbackCount} feedback
|
||||||
{stat.feedbackCount > 1 ? "s" : ""}
|
{stat.feedbackCount > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
@@ -149,7 +151,7 @@ export default function FeedbackManagement() {
|
|||||||
{selectedEvent && (
|
{selectedEvent && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelectedEvent(null)}
|
onClick={() => setSelectedEvent(null)}
|
||||||
className="mt-4 text-pixel-gold text-sm hover:text-orange-400 transition"
|
className="mt-4 text-pixel-gold text-xs sm:text-sm hover:text-orange-400 transition"
|
||||||
>
|
>
|
||||||
Voir tous les feedbacks
|
Voir tous les feedbacks
|
||||||
</button>
|
</button>
|
||||||
@@ -158,8 +160,8 @@ export default function FeedbackManagement() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Liste des feedbacks */}
|
{/* Liste des feedbacks */}
|
||||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-6">
|
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-3 sm:p-6">
|
||||||
<h3 className="text-pixel-gold font-bold text-lg mb-4">
|
<h3 className="text-pixel-gold font-bold text-base sm:text-lg mb-4 break-words">
|
||||||
{selectedEvent
|
{selectedEvent
|
||||||
? `Feedbacks pour: ${
|
? `Feedbacks pour: ${
|
||||||
statistics.find((s) => s.eventId === selectedEvent)?.eventName
|
statistics.find((s) => s.eventId === selectedEvent)?.eventName
|
||||||
@@ -168,36 +170,36 @@ export default function FeedbackManagement() {
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm mb-4">
|
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-3 sm:px-4 py-2 sm:py-3 rounded text-xs sm:text-sm mb-4">
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{filteredFeedbacks.length === 0 ? (
|
{filteredFeedbacks.length === 0 ? (
|
||||||
<p className="text-gray-400 text-center py-8">
|
<p className="text-gray-400 text-center py-8 text-sm">
|
||||||
Aucun feedback pour le moment
|
Aucun feedback pour le moment
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-4">
|
<div className="space-y-3 sm:space-y-4">
|
||||||
{filteredFeedbacks.map((feedback) => (
|
{filteredFeedbacks.map((feedback) => (
|
||||||
<div
|
<div
|
||||||
key={feedback.id}
|
key={feedback.id}
|
||||||
className="bg-black/40 border border-pixel-gold/20 rounded p-4"
|
className="bg-black/40 border border-pixel-gold/20 rounded p-3 sm:p-4"
|
||||||
>
|
>
|
||||||
<div className="flex items-start justify-between mb-3">
|
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3">
|
||||||
<div className="flex-1">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-3 mb-2">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3 mb-2">
|
||||||
<h4 className="text-white font-semibold">
|
<h4 className="text-white font-semibold text-sm sm:text-base break-words">
|
||||||
{feedback.user.username}
|
{feedback.user.username}
|
||||||
</h4>
|
</h4>
|
||||||
<span className="text-gray-500 text-xs">
|
<span className="text-gray-500 text-[10px] sm:text-xs break-all">
|
||||||
{feedback.user.email}
|
{feedback.user.email}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-pixel-gold text-sm font-semibold mb-2">
|
<div className="text-pixel-gold text-xs sm:text-sm font-semibold mb-2 break-words">
|
||||||
{feedback.event.name}
|
{feedback.event.name}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-500 text-xs mb-2">
|
<div className="text-gray-500 text-[10px] sm:text-xs mb-2">
|
||||||
{new Date(feedback.createdAt).toLocaleDateString(
|
{new Date(feedback.createdAt).toLocaleDateString(
|
||||||
"fr-FR",
|
"fr-FR",
|
||||||
{
|
{
|
||||||
@@ -210,11 +212,13 @@ export default function FeedbackManagement() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>{renderStars(feedback.rating)}</div>
|
<div className="flex-shrink-0">
|
||||||
|
{renderStars(feedback.rating)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{feedback.comment && (
|
{feedback.comment && (
|
||||||
<div className="mt-3 pt-3 border-t border-pixel-gold/20">
|
<div className="mt-3 pt-3 border-t border-pixel-gold/20">
|
||||||
<p className="text-gray-300 text-sm whitespace-pre-wrap">
|
<p className="text-gray-300 text-xs sm:text-sm whitespace-pre-wrap break-words">
|
||||||
{feedback.comment}
|
{feedback.comment}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,34 +2,9 @@
|
|||||||
|
|
||||||
import { useBackgroundImage } from "@/hooks/usePreferences";
|
import { useBackgroundImage } from "@/hooks/usePreferences";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState, useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
export default function HeroSection() {
|
export default function HeroSection() {
|
||||||
const backgroundImage = useBackgroundImage("home", "/got-2.jpg");
|
const backgroundImage = useBackgroundImage("home", "/got-2.jpg");
|
||||||
const titleRef = useRef<HTMLSpanElement>(null);
|
|
||||||
const [mousePosition, setMousePosition] = useState({ x: 50, y: 50 });
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
|
||||||
if (titleRef.current) {
|
|
||||||
const rect = titleRef.current.getBoundingClientRect();
|
|
||||||
const x = ((e.clientX - rect.left) / rect.width) * 100;
|
|
||||||
const y = ((e.clientY - rect.top) / rect.height) * 100;
|
|
||||||
setMousePosition({
|
|
||||||
x: Math.max(0, Math.min(100, x)),
|
|
||||||
y: Math.max(0, Math.min(100, y)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("mousemove", handleMouseMove);
|
|
||||||
return () => window.removeEventListener("mousemove", handleMouseMove);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Calculer la position du gradient basée sur la souris avec plus d'amplitude
|
|
||||||
const gradientPosition = mousePosition.x;
|
|
||||||
const glowIntensity = 12 + mousePosition.x / 5;
|
|
||||||
const glowOpacity = 0.4 + mousePosition.y / 250;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
|
||||||
@@ -45,49 +20,24 @@ export default function HeroSection() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Hero Content */}
|
{/* Hero Content */}
|
||||||
<div className="relative z-10 w-full max-w-5xl xl:max-w-6xl mx-auto px-8 py-16 text-center flex flex-col items-center">
|
<div className="relative z-10 w-full max-w-5xl xl:max-w-6xl mx-auto px-4 sm:px-8 py-16 text-center flex flex-col items-center">
|
||||||
{/* Game Title */}
|
{/* Game Title */}
|
||||||
<div className="w-full flex justify-center mb-4">
|
<div className="w-full flex justify-center mb-4 overflow-hidden">
|
||||||
<h1 className="text-6xl md:text-8xl lg:text-9xl xl:text-9xl font-gaming font-black tracking-tight relative">
|
<h1 className="text-4xl sm:text-5xl md:text-8xl lg:text-9xl xl:text-9xl font-gaming font-black tracking-tight relative break-words">
|
||||||
<span
|
<span
|
||||||
ref={titleRef}
|
|
||||||
className="title-animated inline-block relative z-10"
|
className="title-animated inline-block relative z-10"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `linear-gradient(90deg, #daa520 0%, #ffa500 ${Math.max(
|
backgroundImage: `linear-gradient(90deg, #daa520 0%, #ffa500 30%, #ff8c00 50%, #ffa500 70%, #daa520 100%)`,
|
||||||
10,
|
|
||||||
gradientPosition - 20
|
|
||||||
)}%, #ff8c00 ${gradientPosition}%, #ffa500 ${Math.min(
|
|
||||||
90,
|
|
||||||
gradientPosition + 20
|
|
||||||
)}%, #daa520 100%)`,
|
|
||||||
backgroundSize: "200% auto",
|
backgroundSize: "200% auto",
|
||||||
WebkitBackgroundClip: "text",
|
WebkitBackgroundClip: "text",
|
||||||
WebkitTextFillColor: "transparent",
|
WebkitTextFillColor: "transparent",
|
||||||
backgroundClip: "text",
|
backgroundClip: "text",
|
||||||
color: "transparent",
|
color: "transparent",
|
||||||
transition: "background-image 0.15s ease-out",
|
filter: `drop-shadow(0 0 12px rgba(255, 140, 0, 0.4))`,
|
||||||
filter: `drop-shadow(0 0 ${glowIntensity}px rgba(255, 140, 0, ${glowOpacity}))`,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
GAME.OF.TECH
|
GAME.OF.TECH
|
||||||
</span>
|
</span>
|
||||||
{/* Glow effect qui suit la souris */}
|
|
||||||
<span
|
|
||||||
className="absolute inset-0 pointer-events-none"
|
|
||||||
style={{
|
|
||||||
backgroundImage: `linear-gradient(90deg, transparent 0%, rgba(255, 140, 0, 0.3) ${gradientPosition}%, transparent 100%)`,
|
|
||||||
WebkitBackgroundClip: "text",
|
|
||||||
WebkitTextFillColor: "transparent",
|
|
||||||
backgroundClip: "text",
|
|
||||||
filter: `blur(${10 + mousePosition.x / 20}px)`,
|
|
||||||
opacity: 0.5,
|
|
||||||
zIndex: 0,
|
|
||||||
transition: "all 0.15s ease-out",
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
GAME.OF.TECH
|
|
||||||
</span>
|
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -76,13 +76,15 @@ export default function ImageSelector({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<label className="block text-sm text-gray-300 mb-1">{label}</label>
|
<label className="block text-xs sm:text-sm text-gray-300 mb-1 break-words">
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="flex gap-4">
|
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4">
|
||||||
{/* Colonne gauche - Image */}
|
{/* Colonne gauche - Image */}
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0 flex justify-center sm:justify-start">
|
||||||
{value ? (
|
{value ? (
|
||||||
<div className="relative w-48 h-32 border border-pixel-gold/30 rounded overflow-hidden bg-black/60">
|
<div className="relative w-full sm:w-48 h-40 sm:h-32 border border-pixel-gold/30 rounded overflow-hidden bg-black/60">
|
||||||
<img
|
<img
|
||||||
src={value}
|
src={value}
|
||||||
alt="Preview"
|
alt="Preview"
|
||||||
@@ -99,34 +101,34 @@ export default function ImageSelector({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-48 h-32 border border-pixel-gold/30 rounded bg-black/60 flex items-center justify-center">
|
<div className="w-full sm:w-48 h-40 sm:h-32 border border-pixel-gold/30 rounded bg-black/60 flex items-center justify-center">
|
||||||
<span className="text-xs text-gray-500">Aucune</span>
|
<span className="text-xs text-gray-500">Aucune</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Colonne droite - Contrôles */}
|
{/* Colonne droite - Contrôles */}
|
||||||
<div className="flex-1 space-y-3">
|
<div className="flex-1 space-y-3 min-w-0">
|
||||||
{/* Input URL */}
|
{/* Input URL */}
|
||||||
<div className="flex gap-2">
|
<div className="flex flex-col sm:flex-row gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={urlInput}
|
value={urlInput}
|
||||||
onChange={(e) => setUrlInput(e.target.value)}
|
onChange={(e) => setUrlInput(e.target.value)}
|
||||||
onKeyPress={(e) => e.key === "Enter" && handleUrlSubmit()}
|
onKeyPress={(e) => e.key === "Enter" && handleUrlSubmit()}
|
||||||
placeholder="https://example.com/image.jpg ou /image.jpg"
|
placeholder="https://example.com/image.jpg ou /image.jpg"
|
||||||
className="flex-1 px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
className="flex-1 px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm min-w-0"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={handleUrlSubmit}
|
onClick={handleUrlSubmit}
|
||||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
className="px-3 sm:px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap flex-shrink-0"
|
||||||
>
|
>
|
||||||
URL
|
URL
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Upload depuis le disque */}
|
{/* Upload depuis le disque */}
|
||||||
<div className="flex gap-2">
|
<div className="flex flex-col sm:flex-row gap-2">
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
@@ -137,7 +139,7 @@ export default function ImageSelector({
|
|||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`file-${label}`}
|
htmlFor={`file-${label}`}
|
||||||
className={`flex-1 px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition text-center cursor-pointer ${
|
className={`flex-1 px-3 sm:px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition text-center cursor-pointer ${
|
||||||
uploading ? "opacity-50 cursor-not-allowed" : ""
|
uploading ? "opacity-50 cursor-not-allowed" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -145,22 +147,26 @@ export default function ImageSelector({
|
|||||||
</label>
|
</label>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowGallery(!showGallery)}
|
onClick={() => setShowGallery(!showGallery)}
|
||||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
className="px-3 sm:px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{showGallery ? "Masquer" : "Galerie"}
|
{showGallery ? "Masquer" : "Galerie"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Chemin de l'image */}
|
{/* Chemin de l'image */}
|
||||||
{value && <p className="text-xs text-gray-400 truncate">{value}</p>}
|
{value && (
|
||||||
|
<p className="text-xs text-gray-400 truncate break-all">{value}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Galerie d'images */}
|
{/* Galerie d'images */}
|
||||||
{showGallery && (
|
{showGallery && (
|
||||||
<div className="mt-4 p-4 bg-black/40 border border-pixel-gold/20 rounded">
|
<div className="mt-4 p-3 sm:p-4 bg-black/40 border border-pixel-gold/20 rounded">
|
||||||
<h4 className="text-sm text-gray-300 mb-3">Images disponibles</h4>
|
<h4 className="text-xs sm:text-sm text-gray-300 mb-3">
|
||||||
<div className="grid grid-cols-3 md:grid-cols-4 gap-3 max-h-64 overflow-y-auto">
|
Images disponibles
|
||||||
|
</h4>
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2 sm:gap-3 max-h-64 overflow-y-auto">
|
||||||
{availableImages.length === 0 ? (
|
{availableImages.length === 0 ? (
|
||||||
<div className="col-span-full text-center text-gray-400 text-sm py-4">
|
<div className="col-span-full text-center text-gray-400 text-sm py-4">
|
||||||
Aucune image disponible
|
Aucune image disponible
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ export default function LeaderboardSection({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="relative z-10 w-full max-w-6xl mx-auto px-8 py-16">
|
<div className="relative z-10 w-full max-w-6xl mx-auto px-4 sm:px-8 py-16">
|
||||||
{/* Title Section */}
|
{/* Title Section */}
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12 overflow-hidden">
|
||||||
<h1 className="text-5xl md:text-7xl font-gaming font-black mb-4 tracking-tight">
|
<h1 className="text-3xl sm:text-4xl md:text-7xl font-gaming font-black mb-4 tracking-tight break-words">
|
||||||
<span
|
<span
|
||||||
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
||||||
style={{
|
style={{
|
||||||
@@ -66,11 +66,11 @@ export default function LeaderboardSection({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Leaderboard Table */}
|
{/* Leaderboard Table */}
|
||||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg backdrop-blur-sm">
|
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg backdrop-blur-sm overflow-x-auto">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="bg-gray-900/80 border-b border-pixel-gold/30 grid grid-cols-12 gap-4 p-4 font-bold text-xs uppercase tracking-widest text-gray-300">
|
<div className="bg-gray-900/80 border-b border-pixel-gold/30 grid grid-cols-12 gap-2 sm:gap-4 p-2 sm:p-4 font-bold text-[10px] sm:text-xs uppercase tracking-widest text-gray-300">
|
||||||
<div className="col-span-1 text-center">Rank</div>
|
<div className="col-span-2 sm:col-span-1 text-center">Rank</div>
|
||||||
<div className="col-span-6">Player</div>
|
<div className="col-span-5 sm:col-span-6">Player</div>
|
||||||
<div className="col-span-3 text-right">Score</div>
|
<div className="col-span-3 text-right">Score</div>
|
||||||
<div className="col-span-2 text-right">Level</div>
|
<div className="col-span-2 text-right">Level</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,16 +80,16 @@ export default function LeaderboardSection({
|
|||||||
{leaderboard.map((entry) => (
|
{leaderboard.map((entry) => (
|
||||||
<div
|
<div
|
||||||
key={entry.rank}
|
key={entry.rank}
|
||||||
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition relative ${
|
className={`grid grid-cols-12 gap-2 sm:gap-4 p-2 sm:p-4 hover:bg-gray-900/50 transition relative ${
|
||||||
entry.rank <= 3
|
entry.rank <= 3
|
||||||
? "bg-gradient-to-r from-pixel-gold/10 via-pixel-gold/5 to-transparent"
|
? "bg-gradient-to-r from-pixel-gold/10 via-pixel-gold/5 to-transparent"
|
||||||
: "bg-black/40"
|
: "bg-black/40"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* Rank */}
|
{/* Rank */}
|
||||||
<div className="col-span-1 flex items-center justify-center">
|
<div className="col-span-2 sm:col-span-1 flex items-center justify-center">
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center justify-center w-10 h-10 rounded-full font-bold text-sm ${
|
className={`inline-flex items-center justify-center w-8 h-8 sm:w-10 sm:h-10 rounded-full font-bold text-xs sm:text-sm ${
|
||||||
entry.rank === 1
|
entry.rank === 1
|
||||||
? "bg-gradient-to-br from-pixel-gold to-orange-500 text-black shadow-lg shadow-pixel-gold/50"
|
? "bg-gradient-to-br from-pixel-gold to-orange-500 text-black shadow-lg shadow-pixel-gold/50"
|
||||||
: entry.rank === 2
|
: entry.rank === 2
|
||||||
@@ -104,9 +104,9 @@ export default function LeaderboardSection({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Player */}
|
{/* Player */}
|
||||||
<div className="col-span-6 flex items-center gap-3">
|
<div className="col-span-5 sm:col-span-6 flex items-center gap-2 sm:gap-3 min-w-0">
|
||||||
{entry.avatar ? (
|
{entry.avatar ? (
|
||||||
<div className="w-10 h-10 rounded-full border border-pixel-gold/30 overflow-hidden">
|
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-full border border-pixel-gold/30 overflow-hidden flex-shrink-0">
|
||||||
<img
|
<img
|
||||||
src={entry.avatar}
|
src={entry.avatar}
|
||||||
alt={entry.username}
|
alt={entry.username}
|
||||||
@@ -114,18 +114,18 @@ export default function LeaderboardSection({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-gray-800 to-gray-900 border border-pixel-gold/30 flex items-center justify-center">
|
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-full bg-gradient-to-br from-gray-800 to-gray-900 border border-pixel-gold/30 flex items-center justify-center flex-shrink-0">
|
||||||
<span className="text-pixel-gold text-xs font-bold">
|
<span className="text-pixel-gold text-[10px] sm:text-xs font-bold">
|
||||||
{entry.username.charAt(0).toUpperCase()}
|
{entry.username.charAt(0).toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className="flex items-center gap-2 cursor-pointer hover:opacity-80 transition"
|
className="flex items-center gap-1 sm:gap-2 cursor-pointer hover:opacity-80 transition min-w-0"
|
||||||
onClick={() => setSelectedEntry(entry)}
|
onClick={() => setSelectedEntry(entry)}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className={`font-bold ${
|
className={`font-bold text-xs sm:text-sm truncate ${
|
||||||
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -153,14 +153,14 @@ export default function LeaderboardSection({
|
|||||||
|
|
||||||
{/* Score */}
|
{/* Score */}
|
||||||
<div className="col-span-3 flex items-center justify-end">
|
<div className="col-span-3 flex items-center justify-end">
|
||||||
<span className="font-mono text-gray-300">
|
<span className="font-mono text-gray-300 text-xs sm:text-sm">
|
||||||
{formatScore(entry.score)}
|
{formatScore(entry.score)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Level */}
|
{/* Level */}
|
||||||
<div className="col-span-2 flex items-center justify-end">
|
<div className="col-span-2 flex items-center justify-end">
|
||||||
<span className="font-bold text-gray-400">
|
<span className="font-bold text-gray-400 text-xs sm:text-sm">
|
||||||
Lv.{entry.level}
|
Lv.{entry.level}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -190,10 +190,10 @@ export default function LeaderboardSection({
|
|||||||
className="bg-black border-2 border-pixel-gold/70 rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto shadow-2xl"
|
className="bg-black border-2 border-pixel-gold/70 rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto shadow-2xl"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div className="p-8">
|
<div className="p-4 sm:p-8">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<h2 className="text-3xl font-bold text-pixel-gold uppercase tracking-wider">
|
<h2 className="text-xl sm:text-3xl font-bold text-pixel-gold uppercase tracking-wider break-words">
|
||||||
{selectedEntry.username}
|
{selectedEntry.username}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button
|
||||||
@@ -205,9 +205,9 @@ export default function LeaderboardSection({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Avatar and Class */}
|
{/* Avatar and Class */}
|
||||||
<div className="flex items-center gap-6 mb-6">
|
<div className="flex items-center gap-4 sm:gap-6 mb-6">
|
||||||
{selectedEntry.avatar ? (
|
{selectedEntry.avatar ? (
|
||||||
<div className="w-24 h-24 rounded-full border-4 border-pixel-gold/50 overflow-hidden">
|
<div className="w-16 h-16 sm:w-24 sm:h-24 rounded-full border-2 sm:border-4 border-pixel-gold/50 overflow-hidden flex-shrink-0">
|
||||||
<img
|
<img
|
||||||
src={selectedEntry.avatar}
|
src={selectedEntry.avatar}
|
||||||
alt={selectedEntry.username}
|
alt={selectedEntry.username}
|
||||||
@@ -215,8 +215,8 @@ export default function LeaderboardSection({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-24 h-24 rounded-full border-4 border-pixel-gold/50 bg-gray-900 flex items-center justify-center">
|
<div className="w-16 h-16 sm:w-24 sm:h-24 rounded-full border-2 sm:border-4 border-pixel-gold/50 bg-gray-900 flex items-center justify-center flex-shrink-0">
|
||||||
<span className="text-pixel-gold text-4xl font-bold">
|
<span className="text-pixel-gold text-2xl sm:text-4xl font-bold">
|
||||||
{selectedEntry.username.charAt(0).toUpperCase()}
|
{selectedEntry.username.charAt(0).toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useSession, signOut } from "next-auth/react";
|
import { useSession, signOut } from "next-auth/react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
import PlayerStats from "./PlayerStats";
|
import PlayerStats from "./PlayerStats";
|
||||||
|
|
||||||
interface UserData {
|
interface UserData {
|
||||||
@@ -24,29 +26,37 @@ export default function Navigation({
|
|||||||
initialIsAdmin,
|
initialIsAdmin,
|
||||||
}: NavigationProps) {
|
}: NavigationProps) {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
// Ne pas afficher le profil sur les pages login/register
|
||||||
|
const isAuthPage = pathname === "/login" || pathname === "/register";
|
||||||
|
|
||||||
// Utiliser initialUserData pour déterminer l'état de connexion pendant l'hydratation
|
// Utiliser initialUserData pour déterminer l'état de connexion pendant l'hydratation
|
||||||
// Cela évite le clignottement au reload
|
// Cela évite le clignottement au reload
|
||||||
const isAuthenticated = initialUserData !== null || session !== null;
|
// Vérifier explicitement que initialUserData n'est pas undefined
|
||||||
|
const isAuthenticated =
|
||||||
|
(initialUserData !== undefined && initialUserData !== null) ||
|
||||||
|
session !== null;
|
||||||
const isAdmin = initialIsAdmin ?? session?.user?.role === "ADMIN";
|
const isAdmin = initialIsAdmin ?? session?.user?.role === "ADMIN";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="w-full fixed top-0 left-0 z-50 px-8 py-3 bg-black/80 backdrop-blur-sm border-b border-gray-800/30">
|
<nav className="w-full fixed top-0 left-0 z-50 px-4 sm:px-8 py-3 bg-black/80 backdrop-blur-sm border-b border-gray-800/30">
|
||||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||||
{/* Logo - Left */}
|
{/* Logo - Left */}
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="text-white text-xl font-gaming font-bold tracking-tight">
|
<div className="text-white text-lg sm:text-xl font-gaming font-bold tracking-tight">
|
||||||
GAME.OF.TECH
|
GAME.OF.TECH
|
||||||
</div>
|
</div>
|
||||||
<div className="text-pixel-gold text-xs font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide">
|
<div className="text-pixel-gold text-[10px] sm:text-xs font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide">
|
||||||
<span>✦</span>
|
<span>✦</span>
|
||||||
<span>Peaksys</span>
|
<span>Peaksys</span>
|
||||||
<span>✦</span>
|
<span>✦</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation Links - Center */}
|
{/* Navigation Links - Center (Desktop) */}
|
||||||
<div className="flex items-center gap-6">
|
<div className="hidden md:flex items-center gap-6">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||||
@@ -76,17 +86,23 @@ export default function Navigation({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Side */}
|
{/* Right Side */}
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-2 sm:gap-4">
|
||||||
{isAuthenticated ? (
|
{/* PlayerStats - Hidden on mobile */}
|
||||||
<>
|
{isAuthenticated && !isAuthPage && (
|
||||||
|
<div className="hidden lg:block">
|
||||||
<PlayerStats initialUserData={initialUserData} />
|
<PlayerStats initialUserData={initialUserData} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Desktop Auth Buttons */}
|
||||||
|
<div className="hidden md:flex items-center gap-4">
|
||||||
|
{isAuthenticated ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => signOut()}
|
onClick={() => signOut()}
|
||||||
className="text-gray-400 hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
className="text-gray-400 hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||||
>
|
>
|
||||||
Déconnexion
|
Déconnexion
|
||||||
</button>
|
</button>
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
@@ -104,7 +120,111 @@ export default function Navigation({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||||
|
className="md:hidden text-white hover:text-pixel-gold transition p-2"
|
||||||
|
aria-label="Toggle menu"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-6 h-6"
|
||||||
|
fill="none"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
{isMenuOpen ? (
|
||||||
|
<path d="M6 18L18 6M6 6l12 12" />
|
||||||
|
) : (
|
||||||
|
<path d="M4 6h16M4 12h16M4 18h16" />
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu */}
|
||||||
|
{isMenuOpen && (
|
||||||
|
<div className="md:hidden absolute top-full left-0 w-full bg-black/95 backdrop-blur-sm border-b border-gray-800/30">
|
||||||
|
<div className="px-4 py-4 flex flex-col gap-4">
|
||||||
|
{/* Mobile Navigation Links */}
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest py-2"
|
||||||
|
>
|
||||||
|
HOME
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/events"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest py-2"
|
||||||
|
>
|
||||||
|
EVENTS
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/leaderboard"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest py-2"
|
||||||
|
>
|
||||||
|
LEADERBOARD
|
||||||
|
</Link>
|
||||||
|
{isAdmin && (
|
||||||
|
<Link
|
||||||
|
href="/admin"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="text-pixel-gold hover:text-orange-400 transition text-xs font-normal uppercase tracking-widest py-2"
|
||||||
|
>
|
||||||
|
ADMIN
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile PlayerStats */}
|
||||||
|
{isAuthenticated && !isAuthPage && (
|
||||||
|
<div className="lg:hidden pt-2 border-t border-gray-800/30">
|
||||||
|
<PlayerStats initialUserData={initialUserData} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Mobile Auth Buttons */}
|
||||||
|
<div className="flex flex-col gap-3 pt-2 border-t border-gray-800/30">
|
||||||
|
{isAuthenticated ? (
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
signOut();
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}}
|
||||||
|
className="text-gray-400 hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest text-left py-2"
|
||||||
|
>
|
||||||
|
Déconnexion
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link
|
||||||
|
href="/login"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest py-2"
|
||||||
|
>
|
||||||
|
Connexion
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/register"
|
||||||
|
onClick={() => setIsMenuOpen(false)}
|
||||||
|
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition text-center"
|
||||||
|
>
|
||||||
|
Inscription
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export default function PlayerStats({ initialUserData }: PlayerStatsProps) {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* Stats */}
|
||||||
<div className="flex flex-col gap-1.5 min-w-[200px]">
|
<div className="flex flex-col gap-1.5 min-w-[180px] sm:min-w-[200px]">
|
||||||
{/* Username & Level */}
|
{/* Username & Level */}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -174,12 +174,12 @@ export default function UserManagement() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={user.id}
|
key={user.id}
|
||||||
className="bg-black/60 border border-pixel-gold/20 rounded p-3"
|
className="bg-black/60 border border-pixel-gold/20 rounded p-3 sm:p-4"
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-center mb-2">
|
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-2">
|
||||||
<div className="flex gap-3 items-center flex-1 min-w-0">
|
<div className="flex gap-2 sm:gap-3 items-center flex-1 min-w-0">
|
||||||
{/* Avatar */}
|
{/* Avatar */}
|
||||||
<div className="w-10 h-10 rounded-full border-2 border-pixel-gold/50 overflow-hidden bg-black/60 flex-shrink-0">
|
<div className="w-8 h-8 sm:w-10 sm:h-10 rounded-full border-2 border-pixel-gold/50 overflow-hidden bg-black/60 flex-shrink-0">
|
||||||
{user.avatar ? (
|
{user.avatar ? (
|
||||||
<img
|
<img
|
||||||
src={user.avatar}
|
src={user.avatar}
|
||||||
@@ -194,7 +194,7 @@ export default function UserManagement() {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<div
|
<div
|
||||||
className={`w-full h-full flex items-center justify-center text-pixel-gold text-sm font-bold ${
|
className={`w-full h-full flex items-center justify-center text-pixel-gold text-xs sm:text-sm font-bold ${
|
||||||
user.avatar ? "hidden" : ""
|
user.avatar ? "hidden" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -202,18 +202,18 @@ export default function UserManagement() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-1.5 sm:gap-2 flex-wrap">
|
||||||
<h3 className="text-pixel-gold font-bold text-base">
|
<h3 className="text-pixel-gold font-bold text-sm sm:text-base break-words">
|
||||||
{user.username}
|
{user.username}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="text-xs text-gray-500">
|
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap">
|
||||||
Niveau {user.level}
|
Niveau {user.level}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-xs text-gray-500">
|
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap">
|
||||||
Score: {formatNumber(user.score)}
|
Score: {formatNumber(user.score)}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`text-xs ${
|
className={`text-[10px] sm:text-xs whitespace-nowrap ${
|
||||||
user.role === "ADMIN"
|
user.role === "ADMIN"
|
||||||
? "text-pixel-gold"
|
? "text-pixel-gold"
|
||||||
: "text-gray-500"
|
: "text-gray-500"
|
||||||
@@ -222,23 +222,23 @@ export default function UserManagement() {
|
|||||||
{user.role}
|
{user.role}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-gray-400 text-xs truncate">
|
<p className="text-gray-400 text-[10px] sm:text-xs truncate">
|
||||||
{user.email}
|
{user.email}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!isEditing && (
|
{!isEditing && (
|
||||||
<div className="flex gap-2 flex-shrink-0 ml-2">
|
<div className="flex gap-2 flex-shrink-0 sm:ml-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdit(user)}
|
onClick={() => handleEdit(user)}
|
||||||
className="px-3 py-1.5 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
className="px-2 sm:px-3 py-1.5 border border-pixel-gold/50 bg-black/60 text-white uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition whitespace-nowrap"
|
||||||
>
|
>
|
||||||
Modifier
|
Modifier
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDelete(user.id)}
|
onClick={() => handleDelete(user.id)}
|
||||||
disabled={deletingUserId === user.id}
|
disabled={deletingUserId === user.id}
|
||||||
className="px-3 py-1.5 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-xs tracking-widest rounded hover:bg-red-900/30 transition disabled:opacity-50"
|
className="px-2 sm:px-3 py-1.5 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-[10px] sm:text-xs tracking-widest rounded hover:bg-red-900/30 transition disabled:opacity-50 whitespace-nowrap"
|
||||||
>
|
>
|
||||||
{deletingUserId === user.id
|
{deletingUserId === user.id
|
||||||
? "Suppression..."
|
? "Suppression..."
|
||||||
@@ -253,14 +253,14 @@ export default function UserManagement() {
|
|||||||
{/* HP Section */}
|
{/* HP Section */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-center mb-2">
|
<div className="flex justify-between items-center mb-2">
|
||||||
<label className="text-sm text-gray-300">
|
<label className="text-xs sm:text-sm text-gray-300">
|
||||||
Points de Vie (HP)
|
Points de Vie (HP)
|
||||||
</label>
|
</label>
|
||||||
<span className="text-xs text-gray-400">
|
<span className="text-[10px] sm:text-xs text-gray-400">
|
||||||
{previewHp} / {user.maxHp}
|
{previewHp} / {user.maxHp}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setEditingUser({
|
setEditingUser({
|
||||||
@@ -268,7 +268,7 @@ export default function UserManagement() {
|
|||||||
hpDelta: editingUser.hpDelta - 100,
|
hpDelta: editingUser.hpDelta - 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-100
|
-100
|
||||||
</button>
|
</button>
|
||||||
@@ -279,7 +279,7 @@ export default function UserManagement() {
|
|||||||
hpDelta: editingUser.hpDelta - 10,
|
hpDelta: editingUser.hpDelta - 10,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-10
|
-10
|
||||||
</button>
|
</button>
|
||||||
@@ -292,7 +292,7 @@ export default function UserManagement() {
|
|||||||
hpDelta: parseInt(e.target.value) || 0,
|
hpDelta: parseInt(e.target.value) || 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="flex-1 px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm text-center"
|
className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -301,7 +301,7 @@ export default function UserManagement() {
|
|||||||
hpDelta: editingUser.hpDelta + 10,
|
hpDelta: editingUser.hpDelta + 10,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+10
|
+10
|
||||||
</button>
|
</button>
|
||||||
@@ -312,7 +312,7 @@ export default function UserManagement() {
|
|||||||
hpDelta: editingUser.hpDelta + 100,
|
hpDelta: editingUser.hpDelta + 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+100
|
+100
|
||||||
</button>
|
</button>
|
||||||
@@ -333,14 +333,14 @@ export default function UserManagement() {
|
|||||||
{/* XP Section */}
|
{/* XP Section */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-center mb-2">
|
<div className="flex justify-between items-center mb-2">
|
||||||
<label className="text-sm text-gray-300">
|
<label className="text-xs sm:text-sm text-gray-300">
|
||||||
Expérience (XP)
|
Expérience (XP)
|
||||||
</label>
|
</label>
|
||||||
<span className="text-xs text-gray-400">
|
<span className="text-[10px] sm:text-xs text-gray-400">
|
||||||
{formatNumber(previewXp)} / {formatNumber(user.maxXp)}
|
{formatNumber(previewXp)} / {formatNumber(user.maxXp)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setEditingUser({
|
setEditingUser({
|
||||||
@@ -348,7 +348,7 @@ export default function UserManagement() {
|
|||||||
xpDelta: editingUser.xpDelta - 1000,
|
xpDelta: editingUser.xpDelta - 1000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-1000
|
-1000
|
||||||
</button>
|
</button>
|
||||||
@@ -359,7 +359,7 @@ export default function UserManagement() {
|
|||||||
xpDelta: editingUser.xpDelta - 100,
|
xpDelta: editingUser.xpDelta - 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-100
|
-100
|
||||||
</button>
|
</button>
|
||||||
@@ -372,7 +372,7 @@ export default function UserManagement() {
|
|||||||
xpDelta: parseInt(e.target.value) || 0,
|
xpDelta: parseInt(e.target.value) || 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="flex-1 px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm text-center"
|
className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -381,7 +381,7 @@ export default function UserManagement() {
|
|||||||
xpDelta: editingUser.xpDelta + 100,
|
xpDelta: editingUser.xpDelta + 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+100
|
+100
|
||||||
</button>
|
</button>
|
||||||
@@ -392,7 +392,7 @@ export default function UserManagement() {
|
|||||||
xpDelta: editingUser.xpDelta + 1000,
|
xpDelta: editingUser.xpDelta + 1000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+1000
|
+1000
|
||||||
</button>
|
</button>
|
||||||
@@ -412,10 +412,10 @@ export default function UserManagement() {
|
|||||||
|
|
||||||
{/* Score Section */}
|
{/* Score Section */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-2">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-2">
|
||||||
Score
|
Score
|
||||||
</label>
|
</label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setEditingUser({
|
setEditingUser({
|
||||||
@@ -423,7 +423,7 @@ export default function UserManagement() {
|
|||||||
score: (editingUser.score || 0) - 1000,
|
score: (editingUser.score || 0) - 1000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-1000
|
-1000
|
||||||
</button>
|
</button>
|
||||||
@@ -434,7 +434,7 @@ export default function UserManagement() {
|
|||||||
score: (editingUser.score || 0) - 100,
|
score: (editingUser.score || 0) - 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-100
|
-100
|
||||||
</button>
|
</button>
|
||||||
@@ -447,7 +447,7 @@ export default function UserManagement() {
|
|||||||
score: parseInt(e.target.value) || 0,
|
score: parseInt(e.target.value) || 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="flex-1 px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm text-center"
|
className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -456,7 +456,7 @@ export default function UserManagement() {
|
|||||||
score: (editingUser.score || 0) + 100,
|
score: (editingUser.score || 0) + 100,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+100
|
+100
|
||||||
</button>
|
</button>
|
||||||
@@ -467,7 +467,7 @@ export default function UserManagement() {
|
|||||||
score: (editingUser.score || 0) + 1000,
|
score: (editingUser.score || 0) + 1000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+1000
|
+1000
|
||||||
</button>
|
</button>
|
||||||
@@ -476,10 +476,10 @@ export default function UserManagement() {
|
|||||||
|
|
||||||
{/* Level Section */}
|
{/* Level Section */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-2">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-2">
|
||||||
Niveau
|
Niveau
|
||||||
</label>
|
</label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-1 sm:gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setEditingUser({
|
setEditingUser({
|
||||||
@@ -487,7 +487,7 @@ export default function UserManagement() {
|
|||||||
level: Math.max(1, (editingUser.level || 1) - 1),
|
level: Math.max(1, (editingUser.level || 1) - 1),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-xs rounded hover:bg-red-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-red-500/50 bg-red-900/20 text-red-400 text-[10px] sm:text-xs rounded hover:bg-red-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
-1
|
-1
|
||||||
</button>
|
</button>
|
||||||
@@ -501,7 +501,7 @@ export default function UserManagement() {
|
|||||||
level: Math.max(1, parseInt(e.target.value) || 1),
|
level: Math.max(1, parseInt(e.target.value) || 1),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="flex-1 px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm text-center"
|
className="flex-1 min-w-[60px] px-2 sm:px-3 py-1 bg-black/60 border border-pixel-gold/30 rounded text-white text-xs sm:text-sm text-center"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -510,7 +510,7 @@ export default function UserManagement() {
|
|||||||
level: (editingUser.level || 1) + 1,
|
level: (editingUser.level || 1) + 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-xs rounded hover:bg-green-900/30 transition"
|
className="px-2 sm:px-3 py-1 border border-green-500/50 bg-green-900/20 text-green-400 text-[10px] sm:text-xs rounded hover:bg-green-900/30 transition flex-shrink-0"
|
||||||
>
|
>
|
||||||
+1
|
+1
|
||||||
</button>
|
</button>
|
||||||
@@ -519,7 +519,7 @@ export default function UserManagement() {
|
|||||||
|
|
||||||
{/* Role Section */}
|
{/* Role Section */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm text-gray-300 mb-2">
|
<label className="block text-xs sm:text-sm text-gray-300 mb-2">
|
||||||
Rôle
|
Rôle
|
||||||
</label>
|
</label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
@@ -530,7 +530,7 @@ export default function UserManagement() {
|
|||||||
role: "USER",
|
role: "USER",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className={`flex-1 px-4 py-2 border rounded text-xs uppercase tracking-widest transition ${
|
className={`flex-1 px-3 sm:px-4 py-2 border rounded text-[10px] sm:text-xs uppercase tracking-widest transition ${
|
||||||
editingUser.role === "USER"
|
editingUser.role === "USER"
|
||||||
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold"
|
||||||
: "border-gray-600/50 bg-gray-900/20 text-gray-400 hover:bg-gray-900/30"
|
: "border-gray-600/50 bg-gray-900/20 text-gray-400 hover:bg-gray-900/30"
|
||||||
@@ -545,7 +545,7 @@ export default function UserManagement() {
|
|||||||
role: "ADMIN",
|
role: "ADMIN",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className={`flex-1 px-4 py-2 border rounded text-xs uppercase tracking-widest transition ${
|
className={`flex-1 px-3 sm:px-4 py-2 border rounded text-[10px] sm:text-xs uppercase tracking-widest transition ${
|
||||||
editingUser.role === "ADMIN"
|
editingUser.role === "ADMIN"
|
||||||
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold"
|
? "border-pixel-gold bg-pixel-gold/20 text-pixel-gold"
|
||||||
: "border-gray-600/50 bg-gray-900/20 text-gray-400 hover:bg-gray-900/30"
|
: "border-gray-600/50 bg-gray-900/20 text-gray-400 hover:bg-gray-900/30"
|
||||||
@@ -556,7 +556,7 @@ export default function UserManagement() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2 pt-2">
|
<div className="flex flex-col sm:flex-row gap-2 pt-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -573,7 +573,7 @@ export default function UserManagement() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-4 text-xs">
|
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 text-[10px] sm:text-xs">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex justify-between items-center mb-0.5">
|
<div className="flex justify-between items-center mb-0.5">
|
||||||
<span className="text-gray-400">HP</span>
|
<span className="text-gray-400">HP</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user