// Reusable UI chunks: avatar, badge pill, bottom nav, player card const { useState } = React; function Avatar({ player, size = 68, showTag = true }) { const s = size; return (
{player.nick} {showTag && s >= 60 && PHOTO}
); } // darken/lighten hex function shade(hex, pct) { const h = hex.replace('#',''); const n = parseInt(h, 16); let r = (n >> 16) + Math.round(255 * pct/100); let g = ((n >> 8) & 0xff) + Math.round(255 * pct/100); let b = (n & 0xff) + Math.round(255 * pct/100); r = Math.max(0, Math.min(255, r)); g = Math.max(0, Math.min(255, g)); b = Math.max(0, Math.min(255, b)); return '#' + ((r<<16) | (g<<8) | b).toString(16).padStart(6,'0'); } function MiniAvatar({ player, size = 26 }) { return ( {player.nick} ); } function BadgePill({ badge }) { return ( {badge.icon} {badge.label} ); } function BottomNav({ page, onNav }) { const items = [ { id: "leaderboard", label: "الأبطال", ico: "♛" }, { id: "history", label: "المباريات", ico: "♦" }, { id: "profile", label: "البروفايل", ico: "♥" }, { id: "admin", label: "إدارة", ico: "♠" }, ]; return ( ); } function PlayerCard({ player, rank, onClick, dealIndex = 0 }) { const tiltClass = `tilt-${(rank % 4) + 1}`; const isTop = rank === 0; const crown = rank === 0 ? "المتصدّر" : rank === 1 ? "الثاني" : rank === 2 ? "الثالث" : null; const total = player.wins + player.losses; const wr = total ? Math.round((player.wins / total) * 100) : 0; const myBadges = badgesFor(player.id); return (
{rank + 1} {crown && {crown}}
{player.name}
{player.wins}فوز {player.losses}خسارة {wr}٪نسبة
{myBadges.length > 0 && (
{myBadges.slice(0,2).map(b => ( {b.icon} {b.label} ))}
)}
{rank + 1} RANK
); } Object.assign(window, { Avatar, MiniAvatar, BadgePill, BottomNav, PlayerCard, shade });