diff --git a/backend/src/auth/jwt/jwt.strategy.ts b/backend/src/auth/jwt/jwt.strategy.ts index 7c74989..d11b349 100644 --- a/backend/src/auth/jwt/jwt.strategy.ts +++ b/backend/src/auth/jwt/jwt.strategy.ts @@ -29,6 +29,7 @@ export interface AuthenticatedRequestUser { * pending token is `isTwoFactorEnabled: true, tfa: 'pending'`. */ isTwoFactorEnabled: boolean; + avatar: string | null; } const cookieExtractor = (req: Request): string | null => { @@ -68,6 +69,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) { username: user.username, tfa: payload.tfa, isTwoFactorEnabled: user.isTwoFactorEnabled, + avatar: user.avatar, }; } } diff --git a/frontend/src/app/components/Avatar.tsx b/frontend/src/app/components/Avatar.tsx new file mode 100644 index 0000000..03c8186 --- /dev/null +++ b/frontend/src/app/components/Avatar.tsx @@ -0,0 +1,36 @@ +import { useState } from "react"; + +const isImageUrl = (avatar?: string | null): boolean => +!!avatar && /^(https?:\/\/|\/)/.test(avatar); + +interface AvatarProps { + src?: string | null; + alt?: string; + className?: string; +} + +export default function Avatar({ + src, + alt = "avatar", + className = "w-10 h-10 text-xl", +}: AvatarProps) { + const [failed, setFailed] = useState(false); + const showImage = isImageUrl(src) && !failed; + return ( +
Aucun message pour l'instant...
+No message for now...
) : ( Array.isArray(messages) && messages.map((msg, index) => { const authorName = msg.author?.username || msg.user || "Inconnu"; - return ({is2FARequired - ? "Vérification en deux étapes" - : (isSignUp ? "Créez votre compte pour commencer" : "Bienvenue ! Connectez-vous pour continuer")} + ? "Two steps verification" + : (isSignUp ? "Create your account to start" : "Welcome ! Log in to continue")}
{twoFAModal === "enable" - ? "Scannez ce QR Code avec Google Authenticator ou Authy." - : "Saisissez un code de votre application pour confirmer."} + ? "Scan the QR Code with Google Authenticator" + : "Write the code from your app to confirm"}
Chargement...
+Loading...
) : matchHistory.length === 0 ? (- Aucune partie 1v1 pour l'instant — lance-toi ! + No 1v1 game yet, launch a game! !
) : (Best players, ranked by XP
+Les meilleurs joueurs, classés par XP
-Chargement...
- ) : entries.length === 0 ? ( -Aucun joueur classé pour l'instant.
- ) : ( -Loading...
+ ) : entries.length === 0 ? ( +No players ranked yet.
+ ) : ( +- {entry.username} - {isMe(entry) && (toi)} -
-
-
- {entry.xp} -
-XP
-+ {entry.username} + {isMe(entry) && (you)} +
+
+
+ {entry.xp} +
+XP
+