Refactor character class handling across components: Replace hardcoded character class definitions with a centralized CHARACTER_CLASSES import, enhancing maintainability and consistency. Update ProfileForm, Leaderboard, and LeaderboardSection components to utilize new utility functions for character class icons and names, improving code clarity and reducing duplication.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m48s

This commit is contained in:
Julien Froidefond
2025-12-15 10:08:12 +01:00
parent 7dfd426d1f
commit 1e865330a0
7 changed files with 191 additions and 199 deletions

View File

@@ -1,22 +1,23 @@
"use client";
import { useState, useRef, useTransition, type ChangeEvent } from "react";
import { Avatar, Input, Textarea, Button, Alert, Card, BackgroundSection, SectionTitle, ProgressBar } from "@/components/ui";
import {
Avatar,
Input,
Textarea,
Button,
Alert,
Card,
BackgroundSection,
SectionTitle,
ProgressBar,
} from "@/components/ui";
import { updateProfile } from "@/actions/profile/update-profile";
import { updatePassword } from "@/actions/profile/update-password";
type CharacterClass =
| "WARRIOR"
| "MAGE"
| "ROGUE"
| "RANGER"
| "PALADIN"
| "ENGINEER"
| "MERCHANT"
| "SCHOLAR"
| "BERSERKER"
| "NECROMANCER"
| null;
import {
CHARACTER_CLASSES,
type CharacterClass,
} from "@/lib/character-classes";
interface UserProfile {
id: string;
@@ -24,7 +25,7 @@ interface UserProfile {
username: string;
avatar: string | null;
bio: string | null;
characterClass: CharacterClass;
characterClass: CharacterClass | null;
hp: number;
maxHp: number;
xp: number;
@@ -55,7 +56,7 @@ export default function ProfileForm({
const [username, setUsername] = useState(initialProfile.username);
const [avatar, setAvatar] = useState<string | null>(initialProfile.avatar);
const [bio, setBio] = useState<string | null>(initialProfile.bio || null);
const [characterClass, setCharacterClass] = useState<CharacterClass>(
const [characterClass, setCharacterClass] = useState<CharacterClass | null>(
initialProfile.characterClass || null
);
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -120,12 +121,15 @@ export default function ProfileForm({
if (result.success && result.data) {
setProfile({
...result.data,
createdAt: result.data.createdAt instanceof Date
? result.data.createdAt.toISOString()
: result.data.createdAt,
createdAt:
result.data.createdAt instanceof Date
? result.data.createdAt.toISOString()
: result.data.createdAt,
} as UserProfile);
setBio(result.data.bio || null);
setCharacterClass(result.data.characterClass as CharacterClass || null);
setCharacterClass(
(result.data.characterClass as CharacterClass) || null
);
setSuccess("Profil mis à jour avec succès");
setTimeout(() => setSuccess(null), 3000);
} else {
@@ -154,7 +158,9 @@ export default function ProfileForm({
setShowPasswordForm(false);
setTimeout(() => setSuccess(null), 3000);
} else {
setError(result.error || "Erreur lors de la modification du mot de passe");
setError(
result.error || "Erreur lors de la modification du mot de passe"
);
}
});
};
@@ -163,7 +169,12 @@ export default function ProfileForm({
<BackgroundSection backgroundImage={backgroundImage}>
<div className="w-full max-w-4xl mx-auto px-8">
{/* Title Section */}
<SectionTitle variant="gradient" size="lg" subtitle="Gérez votre profil" className="mb-12">
<SectionTitle
variant="gradient"
size="lg"
subtitle="Gérez votre profil"
className="mb-12"
>
PROFIL
</SectionTitle>
@@ -238,8 +249,15 @@ export default function ProfileForm({
id="avatar-upload"
/>
<label htmlFor="avatar-upload">
<Button variant="primary" size="md" as="span" className="cursor-pointer">
{uploadingAvatar ? "Upload en cours..." : "Upload un avatar custom"}
<Button
variant="primary"
size="md"
as="span"
className="cursor-pointer"
>
{uploadingAvatar
? "Upload en cours..."
: "Upload un avatar custom"}
</Button>
</label>
</div>
@@ -276,68 +294,7 @@ export default function ProfileForm({
Classe de Personnage
</label>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{[
{
value: "WARRIOR",
name: "Guerrier",
icon: "⚔️",
desc: "Maître du combat au corps à corps",
},
{
value: "MAGE",
name: "Mage",
icon: "🔮",
desc: "Manipulateur des arcanes",
},
{
value: "ROGUE",
name: "Voleur",
icon: "🗡️",
desc: "Furtif et mortel",
},
{
value: "RANGER",
name: "Rôdeur",
icon: "🏹",
desc: "Chasseur des terres sauvages",
},
{
value: "PALADIN",
name: "Paladin",
icon: "🛡️",
desc: "Protecteur sacré",
},
{
value: "ENGINEER",
name: "Ingénieur",
icon: "⚙️",
desc: "Créateur d'artefacts",
},
{
value: "MERCHANT",
name: "Marchand",
icon: "💰",
desc: "Maître du commerce",
},
{
value: "SCHOLAR",
name: "Érudit",
icon: "📚",
desc: "Gardien du savoir",
},
{
value: "BERSERKER",
name: "Berserker",
icon: "🔥",
desc: "Rage destructrice",
},
{
value: "NECROMANCER",
name: "Nécromancien",
icon: "💀",
desc: "Maître des morts",
},
].map((cls) => (
{CHARACTER_CLASSES.map((cls) => (
<button
key={cls.value}
type="button"
@@ -435,8 +392,15 @@ export default function ProfileForm({
{/* Submit Button */}
<div className="flex justify-end gap-4 pt-4 border-t border-pixel-gold/20">
<Button type="submit" variant="primary" size="md" disabled={isPending}>
{isPending ? "Enregistrement..." : "Enregistrer les modifications"}
<Button
type="submit"
variant="primary"
size="md"
disabled={isPending}
>
{isPending
? "Enregistrement..."
: "Enregistrer les modifications"}
</Button>
</div>
</form>