import { Box, Text, Popover, Progress, Title, Image } from "@mantine/core"; import { usePlayerBadges, useAllBadges } from "../queries"; import { useAuth } from "@/contexts/auth-context"; import { Badge, BadgeProgress } from "../types"; import { useMemo, useState } from "react"; import { MedalIcon, LockKeyIcon } from "@phosphor-icons/react"; interface BadgeShowcaseProps { playerId: string; } interface BadgeDisplay { badge: Badge; progress?: BadgeProgress; earned: boolean; progressText: string; } interface BadgeIconProps { badge: Badge; earned: boolean; } const BadgeIcon = ({ badge, earned }: BadgeIconProps) => { const [imageError, setImageError] = useState(false); const imagePath = `/static/img/${badge.key}.png`; if (imageError) { // Fallback to icon if image fails to load return earned ? ( ) : ( ); } return ( {badge.name} setImageError(true)} style={{ objectFit: 'contain', opacity: earned ? 1 : 0.4, }} /> ); }; const BadgeShowcase = ({ playerId }: BadgeShowcaseProps) => { const { user } = useAuth(); const { data: badgeProgress } = usePlayerBadges(playerId); const { data: allBadges } = useAllBadges(); const isCurrentUser = user?.id === playerId; const badgesToDisplay = useMemo(() => { const displays: BadgeDisplay[] = []; if (isCurrentUser) { for (const badge of allBadges) { const progress = badgeProgress.find(bp => bp.badge.id === badge.id); const earned = progress?.earned || false; if (badge.type === 'manual' && !earned) { continue; } const isVeteranBadge = /^veteran_\d+_badge$/.test(badge.key); if (isVeteranBadge && !earned) { continue; } if (badge.key === 'new_player_badge') { continue; } let progressText = ""; if (progress) { const target = getTargetProgress(badge); progressText = `${progress.progress} / ${target}`; } else { const target = getTargetProgress(badge); progressText = `0 / ${target}`; } displays.push({ badge, progress, earned, progressText, }); } displays.sort((a, b) => { if (a.earned && !b.earned) return -1; if (!a.earned && b.earned) return 1; return a.badge.order - b.badge.order; }); } else { const earnedProgress = badgeProgress.filter(bp => bp.earned); for (const progress of earnedProgress) { const badge: Badge = { ...progress.badge, criteria: {}, created: progress.created, updated: progress.updated, }; const target = getTargetProgress(badge); displays.push({ badge, progress, earned: true, progressText: `${progress.progress} / ${target}`, }); } displays.sort((a, b) => a.badge.order - b.badge.order); } return displays; }, [allBadges, badgeProgress, isCurrentUser]); if (badgesToDisplay.length === 0) { return null; } return ( {badgesToDisplay.map((display) => { const isStackableBadge = ['winner_badge', 'silver_medal_badge', 'bronze_medal_badge'].includes(display.badge.key); const stackCount = display.earned && isStackableBadge ? (display.progress?.progress || 0) : 1; const showStack = stackCount > 1; return ( {showStack && ( <> {[...Array(Math.min(stackCount - 1, 2))].map((_, i) => ( ))} )} {showStack && ( x{stackCount} )} {display.badge.name} {display.badge.name} {display.badge.description} {isCurrentUser && ( Progress {display.progressText} )} ); })} ); }; function getTargetProgress(badge: Badge): number { const criteria = badge.criteria; return ( criteria.matches_played || criteria.tournament_wins || criteria.tournaments_attended || criteria.overtime_matches || criteria.overtime_wins || criteria.consecutive_wins || 1 ); } export default BadgeShowcase;