Refactor UI components for improved responsiveness and consistency: Update styles in AdminPanel, EventManagement, FeedbackManagement, HeroSection, ImageSelector, LeaderboardSection, Navigation, PlayerStats, and UserManagement to enhance mobile and desktop layouts. Adjust text sizes, padding, and button styles for better user experience across devices.
This commit is contained in:
@@ -69,18 +69,64 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
|
||||
return (
|
||||
<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">
|
||||
<h1 className="text-4xl font-gaming font-black mb-8 text-center">
|
||||
<div className="relative z-10 w-full max-w-6xl mx-auto px-4 sm:px-8 py-16">
|
||||
<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">
|
||||
ADMIN
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
{/* 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
|
||||
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"
|
||||
? "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"
|
||||
@@ -90,7 +136,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
? "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"
|
||||
@@ -100,7 +146,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
? "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"
|
||||
@@ -110,7 +156,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
? "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"
|
||||
@@ -119,27 +165,28 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
Feedbacks
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{activeSection === "preferences" && (
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
||||
<h2 className="text-2xl font-gaming font-bold mb-6 text-pixel-gold">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-4 sm:p-6 backdrop-blur-sm">
|
||||
<h2 className="text-xl sm:text-2xl font-gaming font-bold mb-6 text-pixel-gold break-words">
|
||||
Préférences UI Globales
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="bg-black/60 border border-pixel-gold/20 rounded p-4">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div>
|
||||
<h3 className="text-pixel-gold font-bold text-lg">
|
||||
<div className="bg-black/60 border border-pixel-gold/20 rounded p-3 sm:p-4">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3 mb-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<h3 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||
Images de fond du site
|
||||
</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
|
||||
</p>
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
@@ -178,7 +225,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
}
|
||||
label="Background Leaderboard"
|
||||
/>
|
||||
<div className="flex gap-2 pt-4">
|
||||
<div className="flex flex-col sm:flex-row gap-2 pt-4">
|
||||
<button
|
||||
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"
|
||||
@@ -195,70 +242,76 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||
Home:
|
||||
</span>
|
||||
{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
|
||||
src={preferences.homeBackground}
|
||||
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) => {
|
||||
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}
|
||||
</span>
|
||||
</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 className="flex items-center gap-4">
|
||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||
Events:
|
||||
</span>
|
||||
{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
|
||||
src={preferences.eventsBackground}
|
||||
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) => {
|
||||
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}
|
||||
</span>
|
||||
</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 className="flex items-center gap-4">
|
||||
<span className="text-pixel-gold font-bold min-w-[120px]">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
||||
<span className="text-pixel-gold font-bold text-sm sm:text-base min-w-0 sm:min-w-[120px] flex-shrink-0">
|
||||
Leaderboard:
|
||||
</span>
|
||||
{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
|
||||
src={preferences.leaderboardBackground}
|
||||
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) => {
|
||||
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}
|
||||
</span>
|
||||
</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>
|
||||
@@ -269,7 +322,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
)}
|
||||
|
||||
{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">
|
||||
Gestion des Utilisateurs
|
||||
</h2>
|
||||
@@ -278,7 +331,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
)}
|
||||
|
||||
{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">
|
||||
Gestion des Événements
|
||||
</h2>
|
||||
@@ -287,7 +340,7 @@ export default function AdminPanel({ initialPreferences }: AdminPanelProps) {
|
||||
)}
|
||||
|
||||
{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">
|
||||
Gestion des Feedbacks
|
||||
</h2>
|
||||
|
||||
@@ -213,14 +213,14 @@ export default function EventManagement() {
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h3 className="text-xl font-gaming font-bold text-pixel-gold">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4">
|
||||
<h3 className="text-lg sm:text-xl font-gaming font-bold text-pixel-gold break-words">
|
||||
Événements ({events.length})
|
||||
</h3>
|
||||
{!isCreating && !editingEvent && (
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
@@ -228,24 +228,28 @@ export default function EventManagement() {
|
||||
</div>
|
||||
|
||||
{(isCreating || editingEvent) && (
|
||||
<div className="bg-black/60 border border-pixel-gold/20 rounded p-4 mb-4">
|
||||
<h4 className="text-pixel-gold font-bold 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 text-base sm:text-lg break-words">
|
||||
{isCreating ? "Créer un événement" : "Modifier l'événement"}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
<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
|
||||
type="date"
|
||||
value={formData.date}
|
||||
onChange={(e) =>
|
||||
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>
|
||||
<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
|
||||
type="text"
|
||||
value={formData.name}
|
||||
@@ -253,11 +257,11 @@ export default function EventManagement() {
|
||||
setFormData({ ...formData, name: e.target.value })
|
||||
}
|
||||
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>
|
||||
<label className="block text-sm text-gray-300 mb-1">
|
||||
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||
Description
|
||||
</label>
|
||||
<textarea
|
||||
@@ -267,12 +271,14 @@ export default function EventManagement() {
|
||||
}
|
||||
placeholder="Description de l'événement"
|
||||
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 className="grid grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<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
|
||||
value={formData.type}
|
||||
onChange={(e) =>
|
||||
@@ -281,7 +287,7 @@ export default function EventManagement() {
|
||||
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) => (
|
||||
<option key={type} value={type}>
|
||||
@@ -291,9 +297,9 @@ export default function EventManagement() {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<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
|
||||
</label>
|
||||
<input
|
||||
@@ -303,11 +309,11 @@ export default function EventManagement() {
|
||||
setFormData({ ...formData, room: e.target.value })
|
||||
}
|
||||
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>
|
||||
<label className="block text-sm text-gray-300 mb-1">
|
||||
<label className="block text-xs sm:text-sm text-gray-300 mb-1">
|
||||
Heure
|
||||
</label>
|
||||
<input
|
||||
@@ -317,11 +323,11 @@ export default function EventManagement() {
|
||||
setFormData({ ...formData, time: e.target.value })
|
||||
}
|
||||
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>
|
||||
<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
|
||||
</label>
|
||||
<input
|
||||
@@ -336,11 +342,11 @@ export default function EventManagement() {
|
||||
})
|
||||
}
|
||||
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 className="flex gap-2">
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={saving}
|
||||
@@ -368,19 +374,19 @@ export default function EventManagement() {
|
||||
{events.map((event) => (
|
||||
<div
|
||||
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-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h4 className="text-pixel-gold font-bold text-lg">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-3">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex flex-wrap items-center gap-2 sm:gap-3 mb-2">
|
||||
<h4 className="text-pixel-gold font-bold text-base sm:text-lg break-words">
|
||||
{event.name}
|
||||
</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)}
|
||||
</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);
|
||||
return status === "UPCOMING"
|
||||
? "bg-green-900/50 border border-green-500/50 text-green-400"
|
||||
@@ -392,45 +398,45 @@ export default function EventManagement() {
|
||||
{getStatusLabel(calculateEventStatus(event.date))}
|
||||
</span>
|
||||
</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}
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center gap-4 mt-2">
|
||||
<p className="text-gray-500 text-xs">
|
||||
<div className="flex flex-wrap items-center gap-2 sm:gap-4 mt-2">
|
||||
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||
Date: {new Date(event.date).toLocaleDateString("fr-FR")}
|
||||
</p>
|
||||
{event.room && (
|
||||
<p className="text-gray-500 text-xs">
|
||||
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||
📍 Salle: {event.room}
|
||||
</p>
|
||||
)}
|
||||
{event.time && (
|
||||
<p className="text-gray-500 text-xs">
|
||||
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||
🕐 Heure: {event.time}
|
||||
</p>
|
||||
)}
|
||||
{event.maxPlaces && (
|
||||
<p className="text-gray-500 text-xs">
|
||||
<p className="text-gray-500 text-[10px] sm:text-xs whitespace-nowrap">
|
||||
👥 Places: {event.maxPlaces}
|
||||
</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 !== 1 ? "s" : ""}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{!isCreating && !editingEvent && (
|
||||
<div className="flex gap-2 ml-4">
|
||||
<div className="flex gap-2 sm:ml-4 flex-shrink-0">
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
|
||||
@@ -74,18 +74,20 @@ export default function FeedbackManagement() {
|
||||
|
||||
const renderStars = (rating: number) => {
|
||||
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) => (
|
||||
<span
|
||||
key={star}
|
||||
className={`text-lg ${
|
||||
className={`text-sm sm:text-lg ${
|
||||
star <= rating ? "text-pixel-gold" : "text-gray-600"
|
||||
}`}
|
||||
>
|
||||
★
|
||||
</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>
|
||||
);
|
||||
};
|
||||
@@ -96,25 +98,25 @@ export default function FeedbackManagement() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-8">
|
||||
<p className="text-gray-400 text-center">Chargement...</p>
|
||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-4 sm:p-8">
|
||||
<p className="text-gray-400 text-center text-sm">Chargement...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-4 sm:space-y-6">
|
||||
{/* Statistiques par événement */}
|
||||
{statistics.length > 0 && (
|
||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-6">
|
||||
<h3 className="text-pixel-gold font-bold text-lg mb-4">
|
||||
<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-base sm:text-lg mb-4 break-words">
|
||||
Statistiques par événement
|
||||
</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) => (
|
||||
<div
|
||||
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
|
||||
? "border-pixel-gold bg-pixel-gold/10"
|
||||
: "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">
|
||||
<h4 className="text-white font-semibold text-sm">
|
||||
<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-xs sm:text-sm break-words">
|
||||
{stat.eventName}
|
||||
</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)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
{renderStars(Math.round(stat.averageRating))}
|
||||
</div>
|
||||
<div className="text-gray-400 text-xs">
|
||||
<div className="text-gray-400 text-[10px] sm:text-xs">
|
||||
Moyenne: {stat.averageRating.toFixed(2)}/5
|
||||
</div>
|
||||
<div className="text-gray-400 text-xs">
|
||||
<div className="text-gray-400 text-[10px] sm:text-xs">
|
||||
{stat.feedbackCount} feedback
|
||||
{stat.feedbackCount > 1 ? "s" : ""}
|
||||
</div>
|
||||
@@ -149,7 +151,7 @@ export default function FeedbackManagement() {
|
||||
{selectedEvent && (
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
@@ -158,8 +160,8 @@ export default function FeedbackManagement() {
|
||||
)}
|
||||
|
||||
{/* Liste des feedbacks */}
|
||||
<div className="bg-black/60 border border-pixel-gold/30 rounded-lg p-6">
|
||||
<h3 className="text-pixel-gold font-bold text-lg mb-4">
|
||||
<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-base sm:text-lg mb-4 break-words">
|
||||
{selectedEvent
|
||||
? `Feedbacks pour: ${
|
||||
statistics.find((s) => s.eventId === selectedEvent)?.eventName
|
||||
@@ -168,36 +170,36 @@ export default function FeedbackManagement() {
|
||||
</h3>
|
||||
|
||||
{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}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{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
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
{filteredFeedbacks.map((feedback) => (
|
||||
<div
|
||||
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-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h4 className="text-white font-semibold">
|
||||
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3 mb-3">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3 mb-2">
|
||||
<h4 className="text-white font-semibold text-sm sm:text-base break-words">
|
||||
{feedback.user.username}
|
||||
</h4>
|
||||
<span className="text-gray-500 text-xs">
|
||||
<span className="text-gray-500 text-[10px] sm:text-xs break-all">
|
||||
{feedback.user.email}
|
||||
</span>
|
||||
</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}
|
||||
</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(
|
||||
"fr-FR",
|
||||
{
|
||||
@@ -210,11 +212,13 @@ export default function FeedbackManagement() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>{renderStars(feedback.rating)}</div>
|
||||
<div className="flex-shrink-0">
|
||||
{renderStars(feedback.rating)}
|
||||
</div>
|
||||
</div>
|
||||
{feedback.comment && (
|
||||
<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}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -45,10 +45,10 @@ export default function HeroSection() {
|
||||
</div>
|
||||
|
||||
{/* 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 */}
|
||||
<div className="w-full flex justify-center mb-4">
|
||||
<h1 className="text-6xl md:text-8xl lg:text-9xl xl:text-9xl font-gaming font-black tracking-tight relative">
|
||||
<div className="w-full flex justify-center mb-4 overflow-hidden">
|
||||
<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
|
||||
ref={titleRef}
|
||||
className="title-animated inline-block relative z-10"
|
||||
|
||||
@@ -76,13 +76,15 @@ export default function ImageSelector({
|
||||
|
||||
return (
|
||||
<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 */}
|
||||
<div className="flex-shrink-0">
|
||||
<div className="flex-shrink-0 flex justify-center sm:justify-start">
|
||||
{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
|
||||
src={value}
|
||||
alt="Preview"
|
||||
@@ -99,34 +101,34 @@ export default function ImageSelector({
|
||||
</button>
|
||||
</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>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Colonne droite - Contrôles */}
|
||||
<div className="flex-1 space-y-3">
|
||||
<div className="flex-1 space-y-3 min-w-0">
|
||||
{/* Input URL */}
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={urlInput}
|
||||
onChange={(e) => setUrlInput(e.target.value)}
|
||||
onKeyPress={(e) => e.key === "Enter" && handleUrlSubmit()}
|
||||
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
|
||||
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
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Upload depuis le disque */}
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
@@ -137,7 +139,7 @@ export default function ImageSelector({
|
||||
/>
|
||||
<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" : ""
|
||||
}`}
|
||||
>
|
||||
@@ -145,22 +147,26 @@ export default function ImageSelector({
|
||||
</label>
|
||||
<button
|
||||
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"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 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>
|
||||
|
||||
{/* Galerie d'images */}
|
||||
{showGallery && (
|
||||
<div className="mt-4 p-4 bg-black/40 border border-pixel-gold/20 rounded">
|
||||
<h4 className="text-sm text-gray-300 mb-3">Images disponibles</h4>
|
||||
<div className="grid grid-cols-3 md:grid-cols-4 gap-3 max-h-64 overflow-y-auto">
|
||||
<div className="mt-4 p-3 sm:p-4 bg-black/40 border border-pixel-gold/20 rounded">
|
||||
<h4 className="text-xs sm:text-sm text-gray-300 mb-3">
|
||||
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 ? (
|
||||
<div className="col-span-full text-center text-gray-400 text-sm py-4">
|
||||
Aucune image disponible
|
||||
|
||||
@@ -45,10 +45,10 @@ export default function LeaderboardSection({
|
||||
</div>
|
||||
|
||||
{/* 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 */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-5xl md:text-7xl font-gaming font-black mb-4 tracking-tight">
|
||||
<div className="text-center mb-12 overflow-hidden">
|
||||
<h1 className="text-3xl sm:text-4xl md:text-7xl font-gaming font-black mb-4 tracking-tight break-words">
|
||||
<span
|
||||
className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent"
|
||||
style={{
|
||||
@@ -66,11 +66,11 @@ export default function LeaderboardSection({
|
||||
</div>
|
||||
|
||||
{/* 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 */}
|
||||
<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="col-span-1 text-center">Rank</div>
|
||||
<div className="col-span-6">Player</div>
|
||||
<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-2 sm:col-span-1 text-center">Rank</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-2 text-right">Level</div>
|
||||
</div>
|
||||
@@ -80,16 +80,16 @@ export default function LeaderboardSection({
|
||||
{leaderboard.map((entry) => (
|
||||
<div
|
||||
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
|
||||
? "bg-gradient-to-r from-pixel-gold/10 via-pixel-gold/5 to-transparent"
|
||||
: "bg-black/40"
|
||||
}`}
|
||||
>
|
||||
{/* 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
|
||||
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
|
||||
? "bg-gradient-to-br from-pixel-gold to-orange-500 text-black shadow-lg shadow-pixel-gold/50"
|
||||
: entry.rank === 2
|
||||
@@ -104,9 +104,9 @@ export default function LeaderboardSection({
|
||||
</div>
|
||||
|
||||
{/* 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 ? (
|
||||
<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
|
||||
src={entry.avatar}
|
||||
alt={entry.username}
|
||||
@@ -114,18 +114,18 @@ export default function LeaderboardSection({
|
||||
/>
|
||||
</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">
|
||||
<span className="text-pixel-gold text-xs font-bold">
|
||||
<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-[10px] sm:text-xs font-bold">
|
||||
{entry.username.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</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)}
|
||||
>
|
||||
<span
|
||||
className={`font-bold ${
|
||||
className={`font-bold text-xs sm:text-sm truncate ${
|
||||
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
||||
}`}
|
||||
>
|
||||
@@ -153,14 +153,14 @@ export default function LeaderboardSection({
|
||||
|
||||
{/* Score */}
|
||||
<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)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Level */}
|
||||
<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}
|
||||
</span>
|
||||
</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"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="p-8">
|
||||
<div className="p-4 sm:p-8">
|
||||
{/* Header */}
|
||||
<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}
|
||||
</h2>
|
||||
<button
|
||||
@@ -205,9 +205,9 @@ export default function LeaderboardSection({
|
||||
</div>
|
||||
|
||||
{/* 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 ? (
|
||||
<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
|
||||
src={selectedEntry.avatar}
|
||||
alt={selectedEntry.username}
|
||||
@@ -215,8 +215,8 @@ export default function LeaderboardSection({
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-24 h-24 rounded-full border-4 border-pixel-gold/50 bg-gray-900 flex items-center justify-center">
|
||||
<span className="text-pixel-gold text-4xl font-bold">
|
||||
<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-2xl sm:text-4xl font-bold">
|
||||
{selectedEntry.username.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { useSession, signOut } from "next-auth/react";
|
||||
import { useState } from "react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import PlayerStats from "./PlayerStats";
|
||||
|
||||
interface UserData {
|
||||
@@ -24,29 +26,37 @@ export default function Navigation({
|
||||
initialIsAdmin,
|
||||
}: NavigationProps) {
|
||||
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
|
||||
// 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";
|
||||
|
||||
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">
|
||||
{/* Logo - Left */}
|
||||
<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
|
||||
</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>Peaksys</span>
|
||||
<span>✦</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Links - Center */}
|
||||
<div className="flex items-center gap-6">
|
||||
{/* Navigation Links - Center (Desktop) */}
|
||||
<div className="hidden md:flex items-center gap-6">
|
||||
<Link
|
||||
href="/"
|
||||
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||
@@ -76,17 +86,23 @@ export default function Navigation({
|
||||
</div>
|
||||
|
||||
{/* Right Side */}
|
||||
<div className="flex items-center gap-4">
|
||||
{isAuthenticated ? (
|
||||
<>
|
||||
<div className="flex items-center gap-2 sm:gap-4">
|
||||
{/* PlayerStats - Hidden on mobile */}
|
||||
{isAuthenticated && !isAuthPage && (
|
||||
<div className="hidden lg:block">
|
||||
<PlayerStats initialUserData={initialUserData} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Desktop Auth Buttons */}
|
||||
<div className="hidden md:flex items-center gap-4">
|
||||
{isAuthenticated ? (
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className="text-gray-400 hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||
>
|
||||
Déconnexion
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link
|
||||
@@ -104,7 +120,111 @@ export default function Navigation({
|
||||
</>
|
||||
)}
|
||||
</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>
|
||||
|
||||
{/* 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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ export default function PlayerStats({ initialUserData }: PlayerStatsProps) {
|
||||
</Link>
|
||||
|
||||
{/* 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 */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Link
|
||||
|
||||
@@ -174,12 +174,12 @@ export default function UserManagement() {
|
||||
return (
|
||||
<div
|
||||
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 gap-3 items-center flex-1 min-w-0">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-2">
|
||||
<div className="flex gap-2 sm:gap-3 items-center flex-1 min-w-0">
|
||||
{/* 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 ? (
|
||||
<img
|
||||
src={user.avatar}
|
||||
@@ -194,7 +194,7 @@ export default function UserManagement() {
|
||||
/>
|
||||
) : null}
|
||||
<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" : ""
|
||||
}`}
|
||||
>
|
||||
@@ -202,18 +202,18 @@ export default function UserManagement() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<h3 className="text-pixel-gold font-bold text-base">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 flex-wrap">
|
||||
<h3 className="text-pixel-gold font-bold text-sm sm:text-base break-words">
|
||||
{user.username}
|
||||
</h3>
|
||||
<span className="text-xs text-gray-500">
|
||||
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap">
|
||||
Niveau {user.level}
|
||||
</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
<span className="text-[10px] sm:text-xs text-gray-500 whitespace-nowrap">
|
||||
Score: {formatNumber(user.score)}
|
||||
</span>
|
||||
<span
|
||||
className={`text-xs ${
|
||||
className={`text-[10px] sm:text-xs whitespace-nowrap ${
|
||||
user.role === "ADMIN"
|
||||
? "text-pixel-gold"
|
||||
: "text-gray-500"
|
||||
@@ -222,23 +222,23 @@ export default function UserManagement() {
|
||||
{user.role}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-gray-400 text-xs truncate">
|
||||
<p className="text-gray-400 text-[10px] sm:text-xs truncate">
|
||||
{user.email}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<div className="flex gap-2 flex-shrink-0 ml-2">
|
||||
<div className="flex gap-2 flex-shrink-0 sm:ml-2">
|
||||
<button
|
||||
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
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDelete(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
|
||||
? "Suppression..."
|
||||
@@ -253,14 +253,14 @@ export default function UserManagement() {
|
||||
{/* HP Section */}
|
||||
<div>
|
||||
<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)
|
||||
</label>
|
||||
<span className="text-xs text-gray-400">
|
||||
<span className="text-[10px] sm:text-xs text-gray-400">
|
||||
{previewHp} / {user.maxHp}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||
<button
|
||||
onClick={() =>
|
||||
setEditingUser({
|
||||
@@ -268,7 +268,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -279,7 +279,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -292,7 +292,7 @@ export default function UserManagement() {
|
||||
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
|
||||
onClick={() =>
|
||||
@@ -301,7 +301,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -312,7 +312,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -333,14 +333,14 @@ export default function UserManagement() {
|
||||
{/* XP Section */}
|
||||
<div>
|
||||
<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)
|
||||
</label>
|
||||
<span className="text-xs text-gray-400">
|
||||
<span className="text-[10px] sm:text-xs text-gray-400">
|
||||
{formatNumber(previewXp)} / {formatNumber(user.maxXp)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||
<button
|
||||
onClick={() =>
|
||||
setEditingUser({
|
||||
@@ -348,7 +348,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -359,7 +359,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -372,7 +372,7 @@ export default function UserManagement() {
|
||||
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
|
||||
onClick={() =>
|
||||
@@ -381,7 +381,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -392,7 +392,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -412,10 +412,10 @@ export default function UserManagement() {
|
||||
|
||||
{/* Score Section */}
|
||||
<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
|
||||
</label>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-1 sm:gap-2 flex-wrap">
|
||||
<button
|
||||
onClick={() =>
|
||||
setEditingUser({
|
||||
@@ -423,7 +423,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -434,7 +434,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -447,7 +447,7 @@ export default function UserManagement() {
|
||||
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
|
||||
onClick={() =>
|
||||
@@ -456,7 +456,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -467,7 +467,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -476,10 +476,10 @@ export default function UserManagement() {
|
||||
|
||||
{/* Level Section */}
|
||||
<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
|
||||
</label>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-1 sm:gap-2">
|
||||
<button
|
||||
onClick={() =>
|
||||
setEditingUser({
|
||||
@@ -487,7 +487,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -501,7 +501,7 @@ export default function UserManagement() {
|
||||
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
|
||||
onClick={() =>
|
||||
@@ -510,7 +510,7 @@ export default function UserManagement() {
|
||||
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
|
||||
</button>
|
||||
@@ -519,7 +519,7 @@ export default function UserManagement() {
|
||||
|
||||
{/* Role Section */}
|
||||
<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
|
||||
</label>
|
||||
<div className="flex gap-2">
|
||||
@@ -530,7 +530,7 @@ export default function UserManagement() {
|
||||
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"
|
||||
? "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"
|
||||
@@ -545,7 +545,7 @@ export default function UserManagement() {
|
||||
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"
|
||||
? "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"
|
||||
@@ -556,7 +556,7 @@ export default function UserManagement() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 pt-2">
|
||||
<div className="flex flex-col sm:flex-row gap-2 pt-2">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={saving}
|
||||
@@ -573,7 +573,7 @@ export default function UserManagement() {
|
||||
</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 justify-between items-center mb-0.5">
|
||||
<span className="text-gray-400">HP</span>
|
||||
|
||||
Reference in New Issue
Block a user