Refactor API routes and component logic: Remove unused event and user management routes, streamline feedback handling in components, and enhance state management with transitions for improved user experience. Update service layer methods for better organization and maintainability across the application.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m38s

This commit is contained in:
Julien Froidefond
2025-12-12 16:28:07 +01:00
parent 494ac3f503
commit db01c25de7
26 changed files with 747 additions and 743 deletions

View File

@@ -1,7 +1,9 @@
"use client";
import { useState, useRef, type ChangeEvent } from "react";
import { useState, useRef, useTransition, type ChangeEvent } from "react";
import Avatar from "./Avatar";
import { updateProfile } from "@/actions/profile/update-profile";
import { updatePassword } from "@/actions/profile/update-password";
type CharacterClass =
| "WARRIOR"
@@ -46,7 +48,7 @@ export default function ProfileForm({
backgroundImage,
}: ProfileFormProps) {
const [profile, setProfile] = useState<UserProfile>(initialProfile);
const [saving, setSaving] = useState(false);
const [isPending, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
@@ -64,7 +66,7 @@ export default function ProfileForm({
const [currentPassword, setCurrentPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [changingPassword, setChangingPassword] = useState(false);
const [isChangingPassword, startPasswordTransition] = useTransition();
const handleAvatarUpload = async (e: ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
@@ -104,81 +106,57 @@ export default function ProfileForm({
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true);
setError(null);
setSuccess(null);
try {
const response = await fetch("/api/profile", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
avatar,
bio,
characterClass,
}),
startTransition(async () => {
const result = await updateProfile({
username,
avatar,
bio,
characterClass,
});
if (response.ok) {
const data = await response.json();
setProfile(data);
setBio(data.bio || null);
setCharacterClass(data.characterClass || null);
if (result.success && result.data) {
setProfile({
...result.data,
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);
setSuccess("Profil mis à jour avec succès");
setTimeout(() => setSuccess(null), 3000);
} else {
const errorData = await response.json();
setError(errorData.error || "Erreur lors de la mise à jour");
setError(result.error || "Erreur lors de la mise à jour");
}
} catch (err) {
console.error("Error updating profile:", err);
setError("Erreur lors de la mise à jour du profil");
} finally {
setSaving(false);
}
});
};
const handlePasswordChange = async (e: React.FormEvent) => {
e.preventDefault();
setChangingPassword(true);
setError(null);
setSuccess(null);
try {
const response = await fetch("/api/profile/password", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
currentPassword,
newPassword,
confirmPassword,
}),
startPasswordTransition(async () => {
const result = await updatePassword({
currentPassword,
newPassword,
confirmPassword,
});
if (response.ok) {
setSuccess("Mot de passe modifié avec succès");
if (result.success) {
setSuccess(result.message || "Mot de passe modifié avec succès");
setCurrentPassword("");
setNewPassword("");
setConfirmPassword("");
setShowPasswordForm(false);
setTimeout(() => setSuccess(null), 3000);
} else {
const errorData = await response.json();
setError(
errorData.error || "Erreur lors de la modification du mot de passe"
);
setError(result.error || "Erreur lors de la modification du mot de passe");
}
} catch (err) {
console.error("Error changing password:", err);
setError("Erreur lors de la modification du mot de passe");
} finally {
setChangingPassword(false);
}
});
};
const hpPercentage = (profile.hp / profile.maxHp) * 100;
@@ -529,10 +507,10 @@ export default function ProfileForm({
<div className="flex justify-end gap-4 pt-4 border-t border-pixel-gold/20">
<button
type="submit"
disabled={saving}
disabled={isPending}
className="px-6 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
>
{saving ? "Enregistrement..." : "Enregistrer les modifications"}
{isPending ? "Enregistrement..." : "Enregistrer les modifications"}
</button>
</div>
</form>
@@ -616,10 +594,10 @@ export default function ProfileForm({
</button>
<button
type="submit"
disabled={changingPassword}
disabled={isChangingPassword}
className="px-4 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
>
{changingPassword
{isChangingPassword
? "Modification..."
: "Modifier le mot de passe"}
</button>