import { MouseEventHandler, useEffect, useState } from "react"; import axios from "axios"; import { Game } from "@/types/Game"; import { games } from "@/data/games"; import { WAGER_PRIZE_MULT } from "@/shared/constants"; import { EXPLORER_ADDRESS_TEMPLATE, API_URL } from "@/data/shared"; interface GameHistory { address: string; master_score: string; client_score: string; winner: string; wager: string; master_id: string; client_id: string; game: string; // game ID } interface Opponent { username: string; x_profile_url: string; } interface GameHistoryModalProps { userId: string | undefined; isOpen: boolean; onClose: MouseEventHandler; } export default function GameHistoryModal({ userId, isOpen, onClose, }: GameHistoryModalProps) { const [gamesHistory, setGamesHistory] = useState([]); const [opponentInfo, setOpponentInfo] = useState<{ [key: string]: Opponent; }>({}); const [gameImages, setGameImages] = useState<{ [key: string]: string }>({}); const [loading, setLoading] = useState(false); useEffect(() => { if (!isOpen || !userId) return; const fetchGames = async () => { setLoading(true); try { const res = await axios.get( `${API_URL}get_game_history.php?uid=${userId}` ); const gameData = res.data || []; setGamesHistory(gameData); const opponentIds: string[] = gameData.map((game: GameHistory) => game.master_id === userId ? game.client_id : game.master_id ); const uniqueOpponentIds: string[] = Array.from(new Set(opponentIds)); const fetchedOpponentInfo: { [key: string]: Opponent } = {}; await Promise.all( uniqueOpponentIds.map(async (uid) => { try { const response = await axios.get( `${API_URL}get_user_by_id.php?id=${uid}` ); const { username, x_profile_url } = response.data; fetchedOpponentInfo[uid] = { username, x_profile_url, }; } catch (err) { console.error("Failed to fetch opponent info for", uid, err); } }) ); setOpponentInfo(fetchedOpponentInfo); const gameDataWithImages: { [key: string]: string } = {}; await Promise.all( gameData.map(async (gameHistory: GameHistory) => { try { const gameImage = games.find((game: Game) => game.id == gameHistory.game); gameDataWithImages[gameHistory.game] = gameImage?.thumbnail ?? ""; } catch (err) { console.error("Failed to fetch game image for", gameHistory.game, err); } }) ); setGameImages(gameDataWithImages); } catch (err) { console.error("Error fetching game history", err); } finally { setLoading(false); } }; fetchGames(); }, [isOpen, userId]); const handleViewTxClick = (address: string) => { // Open the transaction in a new tab (you can modify this URL to dynamically handle the TX) window.open(`${EXPLORER_ADDRESS_TEMPLATE.replace("{address}",address)}`, "_blank"); }; if (!isOpen) return null; return (

Game History

{loading ? (

Loading...

) : gamesHistory.length === 0 ? (

No games played yet.

) : (
{gamesHistory.map((game, idx) => { const isUserMaster = game.master_id === userId; const userScore = isUserMaster ? game.master_score : game.client_score; const opponentScore = isUserMaster ? game.client_score : game.master_score; const opponentId = isUserMaster ? game.client_id : game.master_id; const didUserWin = (isUserMaster && game.winner === "master") || (!isUserMaster && game.winner === "client"); const opponent = opponentInfo[opponentId]; const profileUrl = opponent?.x_profile_url || (opponent?.username ? `${API_URL}profile_picture/${opponent.username}.jpg` : "/duelfiassets/default-avatar.png"); const gameImageUrl = gameImages[game.game] || "/duelfiassets/default-game-thumbnail.png"; const wagerAmount = parseFloat(game.wager); const outcomeText = didUserWin ? `+${(wagerAmount / 1e8) * 2 * WAGER_PRIZE_MULT} SOL` : `-${(wagerAmount / 1e8)} SOL`; return (
{/* Card content */}

{opponent?.username || "Unknown Opponent"}

Score: {userScore} - {opponentScore}

{didUserWin ? "You won" : "You lost"}

{outcomeText}

Profile Game Thumbnail {/* View TX Action */}
); })}
)}
); }