Commit 5512a11d authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: overhaul UI spacing, padding, and breathing room across all pages

Buttons: larger padding, min-widths, better gradient variants
Cards: increased p-5 default, softer borders
All pages: px-5 padding, generous gaps, larger touch targets,
proper text hierarchy, section breathing room, bottom clearance.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent bace79f0
...@@ -15,15 +15,15 @@ interface ButtonProps { ...@@ -15,15 +15,15 @@ interface ButtonProps {
const variants = { const variants = {
gold: 'bg-gradient-to-l from-gold to-gold-light text-background font-bold shadow-lg shadow-gold/20', gold: 'bg-gradient-to-l from-gold to-gold-light text-background font-bold shadow-lg shadow-gold/20',
ghost: 'bg-surface-2 border border-border text-text-primary hover:border-gold/40', ghost: 'bg-surface-2 border border-border text-text-primary font-semibold hover:border-gold/40 hover:bg-surface-3',
coral: 'bg-coral/90 text-white font-bold', coral: 'bg-gradient-to-l from-coral to-coral/80 text-white font-bold shadow-md shadow-coral/15',
cyan: 'bg-cyan/90 text-background font-bold', cyan: 'bg-gradient-to-l from-cyan to-cyan/80 text-background font-bold shadow-md shadow-cyan/15',
} }
const sizes = { const sizes = {
sm: 'px-4 py-2 text-sm rounded-lg', sm: 'px-5 py-2.5 text-sm rounded-xl gap-2 min-w-[80px]',
md: 'px-6 py-3 text-base rounded-xl', md: 'px-7 py-3.5 text-base rounded-xl gap-2.5 min-w-[100px]',
lg: 'px-8 py-4 text-lg rounded-2xl', lg: 'px-8 py-4.5 text-lg rounded-2xl gap-3 min-w-[120px]',
} }
export function Button({ export function Button({
...@@ -41,8 +41,8 @@ export function Button({ ...@@ -41,8 +41,8 @@ export function Button({
type={type} type={type}
onClick={onClick} onClick={onClick}
disabled={disabled || loading} disabled={disabled || loading}
className={`inline-flex items-center justify-center gap-2 transition-colors ${variants[variant]} ${sizes[size]} ${disabled ? 'opacity-50 cursor-not-allowed' : ''} ${className}`} className={`inline-flex items-center justify-center transition-all duration-200 ${variants[variant]} ${sizes[size]} ${disabled ? 'opacity-50 cursor-not-allowed' : ''} ${className}`}
whileTap={!disabled ? { scale: 0.95 } : undefined} whileTap={!disabled ? { scale: 0.96 } : undefined}
transition={{ type: 'spring', stiffness: 500, damping: 20 }} transition={{ type: 'spring', stiffness: 500, damping: 20 }}
> >
{loading && <Loader2 size={18} className="animate-spin" />} {loading && <Loader2 size={18} className="animate-spin" />}
......
...@@ -11,7 +11,7 @@ interface CardProps { ...@@ -11,7 +11,7 @@ interface CardProps {
export function Card({ children, className = '', glow = false, onClick }: CardProps) { export function Card({ children, className = '', glow = false, onClick }: CardProps) {
return ( return (
<motion.div <motion.div
className={`rounded-2xl bg-surface-1 border border-border p-4 ${glow ? 'border-border-gold shadow-[0_0_15px_rgba(212,168,67,0.1)]' : ''} ${onClick ? 'cursor-pointer' : ''} ${className}`} className={`rounded-2xl bg-surface-1 border border-border/80 p-5 ${glow ? 'border-gold/50 shadow-[0_0_20px_rgba(212,168,67,0.12)]' : ''} ${onClick ? 'cursor-pointer active:scale-[0.98]' : ''} ${className}`}
whileHover={onClick ? { y: -2, boxShadow: '0 8px 30px rgba(212,168,67,0.12)' } : undefined} whileHover={onClick ? { y: -2, boxShadow: '0 8px 30px rgba(212,168,67,0.12)' } : undefined}
whileTap={onClick ? { scale: 0.98 } : undefined} whileTap={onClick ? { scale: 0.98 } : undefined}
onClick={onClick} onClick={onClick}
......
...@@ -39,29 +39,31 @@ export function BotSelectPage() { ...@@ -39,29 +39,31 @@ export function BotSelectPage() {
if (loading) { if (loading) {
return ( return (
<PageTransition className="px-4 py-6 flex flex-col items-center justify-center min-h-[60vh]"> <PageTransition className="px-5 py-8 flex flex-col items-center justify-center min-h-[60vh]">
<div className="w-8 h-8 border-2 border-gold/30 border-t-gold rounded-full animate-spin" /> <div className="w-10 h-10 border-2 border-gold/30 border-t-gold rounded-full animate-spin" />
<p className="mt-3 text-sm text-text-muted">جاري تحميل الروبوتات...</p> <p className="mt-4 text-sm text-text-muted">جاري تحميل الروبوتات...</p>
</PageTransition> </PageTransition>
) )
} }
return ( return (
<PageTransition className="px-4 py-6 flex flex-col gap-5 pb-32"> <PageTransition className="px-5 py-6 flex flex-col gap-6 pb-36">
{/* Header with back button */} {/* Header */}
<div className="flex items-center gap-3"> <div className="flex items-center gap-4">
<motion.button <motion.button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
className="w-9 h-9 rounded-full bg-surface-2 border border-border flex items-center justify-center" className="w-10 h-10 rounded-full bg-surface-2 border border-border flex items-center justify-center"
whileTap={{ scale: 0.9 }} whileTap={{ scale: 0.9 }}
> >
<ChevronRight size={18} className="text-text-secondary" /> <ChevronRight size={20} className="text-text-secondary" />
</motion.button> </motion.button>
<h1 className="text-xl font-bold">العب ضد الروبوت</h1> <div>
<h1 className="text-xl font-bold">العب ضد الروبوت</h1>
<p className="text-xs text-text-muted mt-1">اختر خصمك حسب مستواك</p>
</div>
</div> </div>
<p className="text-sm text-text-secondary">اختر خصمك حسب مستواك</p> {/* Bot List */}
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{bots.map((bot, i) => { {bots.map((bot, i) => {
const isSelected = selectedBot === bot.id const isSelected = selectedBot === bot.id
...@@ -73,78 +75,66 @@ export function BotSelectPage() { ...@@ -73,78 +75,66 @@ export function BotSelectPage() {
key={bot.id} key={bot.id}
initial={{ opacity: 0, y: 15 }} initial={{ opacity: 0, y: 15 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ delay: i * 0.06, type: 'spring', stiffness: 400, damping: 25 }} transition={{ delay: i * 0.05, type: 'spring', stiffness: 400, damping: 25 }}
> >
<Card <Card
glow={isSelected} glow={isSelected}
onClick={() => setSelectedBot(bot.id)} onClick={() => setSelectedBot(bot.id)}
className={`flex items-center gap-3 transition-all ${ className={`flex items-center gap-4 transition-all ${
isSelected isSelected ? 'border-gold/60 scale-[1.01]' : ''
? 'border-gold/60 scale-[1.02] border-r-4'
: ''
}`} }`}
> >
{/* Bot Portrait with colored fallback */} {/* Portrait */}
<div <div
className="relative w-12 h-12 rounded-full overflow-hidden flex-shrink-0" className="relative w-14 h-14 rounded-full overflow-hidden flex-shrink-0 border-2"
style={{ backgroundColor: `${diffColor}20` }} style={{ backgroundColor: `${diffColor}15`, borderColor: `${diffColor}40` }}
> >
<img <img
src={getBotPortraitUrl(bot.id)} src={getBotPortraitUrl(bot.id)}
alt={bot.name} alt={bot.name}
className="w-full h-full object-cover relative z-10" className="w-full h-full object-cover relative z-10"
onError={(e) => { onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
(e.target as HTMLImageElement).style.display = 'none'
}}
/> />
<div <div className="absolute inset-0 flex items-center justify-center" style={{ color: diffColor }}>
className="absolute inset-0 flex items-center justify-center" <span className="text-xl font-bold">{bot.name_ar?.charAt(0) || bot.name.charAt(0)}</span>
style={{ color: diffColor }}
>
<span className="text-lg font-bold">{bot.name_ar?.charAt(0) || bot.name.charAt(0)}</span>
</div> </div>
</div> </div>
{/* Bot Info */} {/* Info */}
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0 space-y-1.5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="text-sm font-bold truncate">{bot.name_ar}</h3> <h3 className="text-sm font-bold truncate">{bot.name_ar}</h3>
<span <span
className="px-1.5 py-0.5 rounded text-[9px] font-bold" className="px-2 py-0.5 rounded-md text-[9px] font-bold"
style={{ backgroundColor: `${diffColor}20`, color: diffColor }} style={{ backgroundColor: `${diffColor}20`, color: diffColor }}
> >
{bot.style_ar} {bot.style_ar}
</span> </span>
</div> </div>
<p className="text-[11px] text-text-muted truncate mt-0.5">{bot.bio_ar}</p> <p className="text-[11px] text-text-muted truncate leading-relaxed">{bot.bio_ar}</p>
<div className="flex items-center gap-3 mt-1.5"> <div className="flex items-center gap-3">
<span className="text-[10px] text-text-muted"> <span className="text-[10px] text-text-muted">{bot.elo_min}-{bot.elo_max} تقييم</span>
{bot.elo_min}-{bot.elo_max} تقييم <div className="flex items-center gap-[3px]">
</span>
{/* Strength dots */}
<div className="flex items-center gap-0.5">
{Array.from({ length: TOTAL_STRENGTH_DOTS }).map((_, dotIndex) => ( {Array.from({ length: TOTAL_STRENGTH_DOTS }).map((_, dotIndex) => (
<div <div
key={dotIndex} key={dotIndex}
className="w-1.5 h-1.5 rounded-full transition-colors" className="w-[5px] h-[5px] rounded-full"
style={{ style={{ backgroundColor: dotIndex < strengthLevel ? diffColor : `${diffColor}25` }}
backgroundColor: dotIndex < strengthLevel ? diffColor : `${diffColor}30`,
}}
/> />
))} ))}
</div> </div>
</div> </div>
</div> </div>
{/* Selection indicator */} {/* Check */}
{isSelected && ( {isSelected && (
<motion.div <motion.div
className="w-5 h-5 rounded-full bg-gold flex items-center justify-center flex-shrink-0" className="w-7 h-7 rounded-full bg-gold flex items-center justify-center flex-shrink-0"
initial={{ scale: 0 }} initial={{ scale: 0 }}
animate={{ scale: 1 }} animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 500, damping: 20 }} transition={{ type: 'spring', stiffness: 500, damping: 20 }}
> >
<Swords size={10} className="text-background" /> <Swords size={12} className="text-background" />
</motion.div> </motion.div>
)} )}
</Card> </Card>
...@@ -153,10 +143,10 @@ export function BotSelectPage() { ...@@ -153,10 +143,10 @@ export function BotSelectPage() {
})} })}
</div> </div>
{/* Bottom CTA with safe area */} {/* CTA */}
{selectedBot && ( {selectedBot && (
<motion.div <motion.div
className="fixed bottom-0 left-0 right-0 p-4 pb-8 bg-gradient-to-t from-background via-background to-transparent" className="fixed bottom-0 left-0 right-0 px-5 pt-4 pb-10 bg-gradient-to-t from-background via-background/95 to-transparent"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 400, damping: 25 }} transition={{ type: 'spring', stiffness: 400, damping: 25 }}
......
...@@ -365,10 +365,10 @@ export function GamePage() { ...@@ -365,10 +365,10 @@ export function GamePage() {
return ( return (
<div className="flex flex-col min-h-dvh bg-background"> <div className="flex flex-col min-h-dvh bg-background">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-4 py-2 bg-surface-1 border-b border-border"> <div className="flex items-center justify-between px-5 py-3 bg-surface-1 border-b border-border">
<motion.button <motion.button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
className="flex items-center gap-0.5 text-text-muted p-2 -m-2" className="flex items-center gap-0.5 text-text-muted p-2"
whileTap={{ scale: 0.9 }} whileTap={{ scale: 0.9 }}
> >
<ChevronRight size={20} className="text-text-muted" /> <ChevronRight size={20} className="text-text-muted" />
...@@ -376,7 +376,7 @@ export function GamePage() { ...@@ -376,7 +376,7 @@ export function GamePage() {
{/* Turn indicator - glowing pill */} {/* Turn indicator - glowing pill */}
<motion.div <motion.div
className={`flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-bold ${ className={`flex items-center gap-1.5 px-4 py-1.5 rounded-full text-xs font-bold ${
isPlayerTurn isPlayerTurn
? 'bg-gold/20 text-gold border border-gold/40' ? 'bg-gold/20 text-gold border border-gold/40'
: 'bg-surface-2 text-text-secondary border border-border' : 'bg-surface-2 text-text-secondary border border-border'
...@@ -402,10 +402,10 @@ export function GamePage() { ...@@ -402,10 +402,10 @@ export function GamePage() {
</div> </div>
{/* Main content */} {/* Main content */}
<div className="flex-1 flex flex-col items-center px-2 pt-2 pb-4"> <div className="flex-1 flex flex-col items-center px-2 pt-2 pb-4 gap-2">
{/* Opponent panel (top) */} {/* Opponent panel (top) */}
<div className="w-full max-w-[min(100vw-16px,400px)] flex items-center gap-2 px-1 py-1.5"> <div className="w-full max-w-[min(100vw-16px,400px)] flex items-center gap-2 px-2 py-2.5 bg-surface-1/30 rounded-xl">
<div className="w-8 h-8 rounded-full overflow-hidden bg-surface-3 border border-border flex items-center justify-center shrink-0"> <div className="w-10 h-10 rounded-full overflow-hidden bg-surface-3 border border-border flex items-center justify-center shrink-0">
{isBot && botId ? ( {isBot && botId ? (
<img <img
src={getBotPortraitUrl(botId)} src={getBotPortraitUrl(botId)}
...@@ -444,14 +444,14 @@ export function GamePage() { ...@@ -444,14 +444,14 @@ export function GamePage() {
</div> </div>
{/* File labels (bottom) */} {/* File labels (bottom) */}
<div className="mr-4"> <div className="mr-4 mt-1">
{renderFileLabels()} {renderFileLabels()}
</div> </div>
</div> </div>
{/* Player panel (bottom) */} {/* Player panel (bottom) */}
<div className="w-full max-w-[min(100vw-16px,400px)] flex items-center gap-2 px-1 py-1.5"> <div className="w-full max-w-[min(100vw-16px,400px)] flex items-center gap-2 px-2 py-2.5 bg-surface-1/30 rounded-xl">
<div className="w-8 h-8 rounded-full bg-surface-3 border border-border flex items-center justify-center shrink-0 relative"> <div className="w-10 h-10 rounded-full bg-surface-3 border border-border flex items-center justify-center shrink-0 relative">
<Crown size={14} className="text-gold" /> <Crown size={14} className="text-gold" />
<div className="absolute -bottom-0.5 -left-0.5 w-2.5 h-2.5 rounded-full bg-green-500 border-2 border-background" /> <div className="absolute -bottom-0.5 -left-0.5 w-2.5 h-2.5 rounded-full bg-green-500 border-2 border-background" />
</div> </div>
...@@ -462,7 +462,7 @@ export function GamePage() { ...@@ -462,7 +462,7 @@ export function GamePage() {
</div> </div>
{/* Action buttons */} {/* Action buttons */}
<div className="flex items-center gap-3 mt-3"> <div className="flex items-center gap-4 mt-5">
<Button <Button
variant="coral" variant="coral"
size="md" size="md"
...@@ -478,7 +478,7 @@ export function GamePage() { ...@@ -478,7 +478,7 @@ export function GamePage() {
</div> </div>
{/* Move list */} {/* Move list */}
<div className="w-full max-w-[min(100vw-16px,400px)] mt-3"> <div className="w-full max-w-[min(100vw-16px,400px)] mt-4">
<div className="text-[10px] text-text-muted/50 px-1 mb-0.5">النقلات</div> <div className="text-[10px] text-text-muted/50 px-1 mb-0.5">النقلات</div>
<div className="bg-surface-1 rounded-lg border border-border min-h-[36px] max-h-[56px] overflow-hidden"> <div className="bg-surface-1 rounded-lg border border-border min-h-[36px] max-h-[56px] overflow-hidden">
{renderMoveList() || ( {renderMoveList() || (
...@@ -490,7 +490,7 @@ export function GamePage() { ...@@ -490,7 +490,7 @@ export function GamePage() {
</div> </div>
{/* Move counter */} {/* Move counter */}
<div className="mt-2 text-[11px] text-text-muted text-center"> <div className="mt-3 text-[11px] text-text-muted text-center">
النقلة {game.moveNumber()} {game.inCheck() ? '- كش!' : ''} النقلة {game.moveNumber()} {game.inCheck() ? '- كش!' : ''}
</div> </div>
</div> </div>
...@@ -505,7 +505,7 @@ export function GamePage() { ...@@ -505,7 +505,7 @@ export function GamePage() {
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
> >
<motion.div <motion.div
className="bg-surface-1 border border-border rounded-2xl p-8 flex flex-col items-center gap-4 mx-6" className="bg-surface-1 border border-border rounded-2xl p-10 flex flex-col items-center gap-4 mx-6"
initial={{ scale: 0.8, y: 30 }} initial={{ scale: 0.8, y: 30 }}
animate={{ scale: 1, y: 0 }} animate={{ scale: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 300, damping: 22 }} transition={{ type: 'spring', stiffness: 300, damping: 22 }}
......
This diff is collapsed.
...@@ -14,10 +14,10 @@ const CATEGORIES = [ ...@@ -14,10 +14,10 @@ const CATEGORIES = [
] as const ] as const
const GAME_ICONS: Record<string, React.ReactNode> = { const GAME_ICONS: Record<string, React.ReactNode> = {
backgammon: <span className="text-2xl font-bold text-gold">&#x2680;</span>, backgammon: <span className="text-2xl font-bold text-text-muted">&#x2680;</span>,
dominoes: <span className="text-2xl font-bold text-gold">&#x1F0A1;</span>, dominoes: <span className="text-2xl font-bold text-text-muted">&#x1F0A1;</span>,
ludo: <span className="text-2xl font-bold text-gold">&#x2684;</span>, ludo: <span className="text-2xl font-bold text-text-muted">&#x2684;</span>,
trivia: <span className="text-2xl font-bold text-gold">?</span>, trivia: <span className="text-lg font-bold text-text-muted">?</span>,
} }
export function PlayPage() { export function PlayPage() {
...@@ -28,59 +28,61 @@ export function PlayPage() { ...@@ -28,59 +28,61 @@ export function PlayPage() {
const otherGames = GAMES.filter((g) => g.key !== 'chess') const otherGames = GAMES.filter((g) => g.key !== 'chess')
return ( return (
<PageTransition className="px-4 py-6 flex flex-col gap-6"> <PageTransition className="px-5 py-6 flex flex-col gap-7">
<h1 className="text-xl font-bold">اختر اللعبة</h1> <h1 className="text-xl font-bold">اختر اللعبة</h1>
{/* Chess Hero Card - full width */} {/* Chess Hero Card */}
<motion.div <motion.div
className="relative rounded-2xl overflow-hidden border-2 border-gold/40 bg-gradient-to-br from-surface-2 via-surface-1 to-gold/5 p-5 flex items-center gap-4" className="relative rounded-2xl overflow-hidden border-2 border-gold/30 bg-gradient-to-br from-surface-2 via-surface-1 to-gold/5 p-6 flex items-center gap-5"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 400, damping: 25 }} transition={{ type: 'spring', stiffness: 400, damping: 25 }}
whileTap={{ scale: 0.97 }} whileTap={{ scale: 0.97 }}
> >
<div className="w-14 h-14 rounded-xl bg-gold/10 border border-gold/30 flex items-center justify-center"> <div className="w-16 h-16 rounded-2xl bg-gold/10 border border-gold/20 flex items-center justify-center shadow-inner">
<Crown size={28} className="text-gold" /> <Crown size={32} className="text-gold" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<span className="text-base font-bold">{chessGame.nameAr}</span> <span className="text-lg font-bold">{chessGame.nameAr}</span>
<p className="text-xs text-text-secondary mt-1">العب شطرنج اونلاين ضد لاعبين حقيقيين</p> <p className="text-xs text-text-secondary mt-1.5 leading-relaxed">العب شطرنج اونلاين ضد لاعبين حقيقيين</p>
</div> </div>
<motion.div
className="absolute top-3 left-3 w-2 h-2 rounded-full bg-green-500"
animate={{ opacity: [1, 0.4, 1] }}
transition={{ duration: 2, repeat: Infinity }}
/>
</motion.div> </motion.div>
{/* Other Games 2x2 Grid */} {/* Other Games Grid */}
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
{otherGames.map((game, i) => ( {otherGames.map((game, i) => (
<motion.div <motion.div
key={game.key} key={game.key}
className={`relative rounded-2xl overflow-hidden border-2 ${ className="relative rounded-2xl overflow-hidden border border-border bg-surface-1 opacity-50 p-5 flex flex-col items-center gap-3"
game.available
? 'border-gold/40 bg-gradient-to-br from-surface-2 to-surface-1'
: 'border-border bg-surface-1 opacity-60'
} p-4 flex flex-col items-center gap-2`}
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 0.5, y: 0 }}
transition={{ delay: 0.08 + i * 0.08, type: 'spring', stiffness: 400, damping: 25 }} transition={{ delay: 0.08 + i * 0.08, type: 'spring', stiffness: 400, damping: 25 }}
whileTap={game.available ? { scale: 0.95 } : undefined}
> >
<div className="w-12 h-12 rounded-xl bg-surface-3 flex items-center justify-center"> <div className="w-12 h-12 rounded-xl bg-surface-3/80 flex items-center justify-center">
{GAME_ICONS[game.key] || null} {GAME_ICONS[game.key] || null}
</div> </div>
<span className="text-sm font-bold">{game.nameAr}</span> <span className="text-sm font-bold text-text-secondary">{game.nameAr}</span>
{!game.available && ( <div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-[2px]">
<div className="absolute inset-0 flex items-center justify-center bg-background/60 backdrop-blur-sm"> <div className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-surface-2/80 border border-border">
<Lock size={20} className="text-text-muted" /> <Lock size={12} className="text-text-muted" />
<span className="mr-2 text-xs text-text-muted">قريبا</span> <span className="text-[11px] text-text-muted font-medium">قريبا</span>
</div> </div>
)} </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
{/* Time Control Section */} {/* Time Control */}
<div> <div className="space-y-4">
<h2 className="text-base font-bold mb-3">نظام الوقت</h2> <h2 className="text-base font-bold">نظام الوقت</h2>
<div className="flex gap-3 mb-3">
{/* Category Pills */}
<div className="flex gap-2 overflow-x-auto scrollbar-hide pb-1">
{CATEGORIES.map((cat) => { {CATEGORIES.map((cat) => {
const isActive = Object.entries(TIME_CONTROLS).find( const isActive = Object.entries(TIME_CONTROLS).find(
([k]) => k === selectedTC ([k]) => k === selectedTC
...@@ -89,9 +91,9 @@ export function PlayPage() { ...@@ -89,9 +91,9 @@ export function PlayPage() {
return ( return (
<motion.button <motion.button
key={cat.key} key={cat.key}
className={`flex items-center gap-1.5 px-4 py-2 rounded-full text-xs font-semibold border ${ className={`flex items-center gap-2 px-4 py-2.5 rounded-full text-xs font-bold border whitespace-nowrap ${
isActive isActive
? 'bg-gold/10 border-gold/40 text-gold' ? 'bg-gold/15 border-gold/50 text-gold shadow-sm shadow-gold/10'
: 'bg-surface-2 border-border text-text-muted' : 'bg-surface-2 border-border text-text-muted'
}`} }`}
whileTap={{ scale: 0.93 }} whileTap={{ scale: 0.93 }}
...@@ -100,14 +102,15 @@ export function PlayPage() { ...@@ -100,14 +102,15 @@ export function PlayPage() {
if (first) setSelectedTC(first[0]) if (first) setSelectedTC(first[0])
}} }}
> >
<Icon size={12} /> <Icon size={14} />
{cat.label} {cat.label}
</motion.button> </motion.button>
) )
})} })}
</div> </div>
<div className="grid grid-cols-3 gap-2"> {/* Time Buttons */}
<div className="grid grid-cols-3 gap-2.5">
{Object.entries(TIME_CONTROLS) {Object.entries(TIME_CONTROLS)
.filter(([, v]) => { .filter(([, v]) => {
const activeCategory = Object.entries(TIME_CONTROLS).find( const activeCategory = Object.entries(TIME_CONTROLS).find(
...@@ -118,9 +121,9 @@ export function PlayPage() { ...@@ -118,9 +121,9 @@ export function PlayPage() {
.map(([key, tc]) => ( .map(([key, tc]) => (
<motion.button <motion.button
key={key} key={key}
className={`py-3 rounded-xl text-center font-bold border ${ className={`py-3.5 rounded-xl text-center font-bold text-sm border transition-all ${
selectedTC === key selectedTC === key
? 'bg-gold/15 border-gold text-gold' ? 'bg-gold/15 border-gold text-gold shadow-sm shadow-gold/10'
: 'bg-surface-2 border-border text-text-secondary' : 'bg-surface-2 border-border text-text-secondary'
}`} }`}
whileTap={{ scale: 0.93 }} whileTap={{ scale: 0.93 }}
...@@ -133,13 +136,12 @@ export function PlayPage() { ...@@ -133,13 +136,12 @@ export function PlayPage() {
</div> </div>
{/* Action Buttons */} {/* Action Buttons */}
<div className="flex flex-col gap-3 mt-2"> <div className="flex flex-col gap-3 mt-2 pb-4">
<Button onClick={() => navigate('/matchmaking')} className="w-full" size="lg"> <Button onClick={() => navigate('/matchmaking')} className="w-full" size="lg">
البحث عن خصم البحث عن خصم
</Button> </Button>
<Button onClick={() => navigate('/bot-select')} variant="ghost" className="w-full" size="md"> <Button onClick={() => navigate('/bot-select')} variant="ghost" className="w-full" size="md">
<Cpu size={16} className="text-gold" /> <Cpu size={18} className="text-gold" />
العب ضد الروبوت العب ضد الروبوت
</Button> </Button>
</div> </div>
......
...@@ -7,9 +7,7 @@ import { Card } from '../components/ui/Card' ...@@ -7,9 +7,7 @@ import { Card } from '../components/ui/Card'
import { supabase } from '../lib/supabase' import { supabase } from '../lib/supabase'
function SectionDivider() { function SectionDivider() {
return ( return <div className="w-full h-px bg-gradient-to-l from-transparent via-border to-transparent my-1" />
<div className="w-full h-px bg-gradient-to-l from-transparent via-gold/20 to-transparent" />
)
} }
export function ProfilePage() { export function ProfilePage() {
...@@ -28,41 +26,42 @@ export function ProfilePage() { ...@@ -28,41 +26,42 @@ export function ProfilePage() {
: 0 : 0
return ( return (
<PageTransition className="px-4 py-6 flex flex-col gap-5"> <PageTransition className="px-5 py-6 flex flex-col gap-6">
{/* Avatar + Name */}
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-4">
<motion.div <motion.div
className="w-16 h-16 rounded-full bg-gradient-to-br from-gold/30 to-purple/20 border-2 border-gold flex items-center justify-center" className="w-18 h-18 rounded-full bg-gradient-to-br from-gold/30 to-purple/20 border-2 border-gold flex items-center justify-center shadow-lg shadow-gold/10"
style={{ width: 72, height: 72 }}
initial={{ scale: 0 }} initial={{ scale: 0 }}
animate={{ scale: 1 }} animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 300, damping: 20 }} transition={{ type: 'spring', stiffness: 300, damping: 20 }}
> >
<span className="text-2xl font-black text-gold"> <span className="text-3xl font-black text-gold">
{profile.display_name?.charAt(0) || '?'} {profile.display_name?.charAt(0) || '?'}
</span> </span>
</motion.div> </motion.div>
<div> <div className="space-y-1">
<h1 className="text-lg font-bold">{profile.display_name}</h1> <h1 className="text-xl font-bold">{profile.display_name}</h1>
<p className="text-sm text-text-muted">@{profile.username}</p> <p className="text-sm text-text-muted">@{profile.username}</p>
</div> </div>
</div> </div>
<motion.button <motion.button
whileTap={{ scale: 0.9 }} whileTap={{ scale: 0.9 }}
onClick={() => navigate('/settings')} onClick={() => navigate('/settings')}
className="p-2 rounded-lg bg-surface-2 mr-auto ml-0" className="p-2.5 rounded-xl bg-surface-2 border border-border"
> >
<Settings size={18} className="text-text-muted" /> <Settings size={18} className="text-text-muted" />
</motion.button> </motion.button>
</div> </div>
<Card className="p-4"> {/* XP Card */}
<Card className="p-5">
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<h2 className="text-base font-bold text-text-primary"> <h2 className="text-lg font-bold">المستوى {profile.level}</h2>
المستوى {profile.level} <span className="text-sm text-gold font-bold px-3 py-1 rounded-full bg-gold/10">{profile.xp} XP</span>
</h2>
<span className="text-sm text-gold font-semibold">{profile.xp} XP</span>
</div> </div>
<div className="w-full h-2.5 rounded-full bg-surface-3 overflow-hidden"> <div className="w-full h-3 rounded-full bg-surface-3 overflow-hidden">
<motion.div <motion.div
className="h-full rounded-full bg-gradient-to-l from-gold to-gold-light" className="h-full rounded-full bg-gradient-to-l from-gold to-gold-light"
initial={{ width: 0 }} initial={{ width: 0 }}
...@@ -70,16 +69,15 @@ export function ProfilePage() { ...@@ -70,16 +69,15 @@ export function ProfilePage() {
transition={{ duration: 1, ease: 'easeOut' }} transition={{ duration: 1, ease: 'easeOut' }}
/> />
</div> </div>
<p className="text-[11px] text-text-muted mt-2"> <p className="text-xs text-text-muted mt-2.5">{500 - (profile.xp % 500)} XP للمستوى التالي</p>
{500 - (profile.xp % 500)} XP للمستوى التالي
</p>
</Card> </Card>
<SectionDivider /> <SectionDivider />
{/* Ratings */}
<div> <div>
<h2 className="text-sm font-bold text-text-secondary mb-2">التقييمات</h2> <h2 className="text-sm font-bold text-text-secondary mb-3">التقييمات</h2>
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-3">
{[ {[
{ label: 'رصاصة', value: profile.elo_bullet, icon: '1+0' }, { label: 'رصاصة', value: profile.elo_bullet, icon: '1+0' },
{ label: 'خاطف', value: profile.elo_blitz, icon: '5+0' }, { label: 'خاطف', value: profile.elo_blitz, icon: '5+0' },
...@@ -88,17 +86,17 @@ export function ProfilePage() { ...@@ -88,17 +86,17 @@ export function ProfilePage() {
].map((rating, i) => ( ].map((rating, i) => (
<motion.div <motion.div
key={rating.label} key={rating.label}
className="p-3 rounded-xl bg-surface-1 border border-border flex items-center gap-3" className="p-4 rounded-xl bg-surface-1 border border-border/80 flex items-center gap-3"
initial={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 + i * 0.05 }} transition={{ delay: 0.1 + i * 0.05 }}
> >
<div className="w-8 h-8 rounded-lg bg-surface-3 flex items-center justify-center"> <div className="w-10 h-10 rounded-lg bg-surface-3 flex items-center justify-center">
<span className="text-[10px] font-bold text-text-muted">{rating.icon}</span> <span className="text-[11px] font-bold text-text-muted">{rating.icon}</span>
</div> </div>
<div> <div>
<p className="text-base font-bold">{rating.value}</p> <p className="text-lg font-bold">{rating.value}</p>
<p className="text-[10px] text-text-muted">{rating.label}</p> <p className="text-[11px] text-text-muted">{rating.label}</p>
</div> </div>
</motion.div> </motion.div>
))} ))}
...@@ -107,21 +105,23 @@ export function ProfilePage() { ...@@ -107,21 +105,23 @@ export function ProfilePage() {
<SectionDivider /> <SectionDivider />
{/* Stats */}
<div> <div>
<h2 className="text-sm font-bold text-text-secondary mb-2">الاحصائيات</h2> <h2 className="text-sm font-bold text-text-secondary mb-3">الاحصائيات</h2>
<div className="grid grid-cols-4 gap-2"> <div className="grid grid-cols-4 gap-2.5">
<StatMini icon={<Flame size={14} className="text-coral" />} value={profile.best_win_streak} label="افضل سلسلة" /> <StatMini icon={<Flame size={16} className="text-coral" />} value={profile.best_win_streak} label="افضل سلسلة" />
<StatMini icon={<Trophy size={14} className="text-gold" />} value={profile.total_wins} label="انتصارات" /> <StatMini icon={<Trophy size={16} className="text-gold" />} value={profile.total_wins} label="انتصارات" />
<StatMini icon={<Target size={14} className="text-cyan" />} value={`${winRate}%`} label="نسبة الفوز" /> <StatMini icon={<Target size={16} className="text-cyan" />} value={`${winRate}%`} label="نسبة الفوز" />
<StatMini icon={<TrendingUp size={14} className="text-purple" />} value={profile.total_games_played} label="مباريات" /> <StatMini icon={<TrendingUp size={16} className="text-purple" />} value={profile.total_games_played} label="مباريات" />
</div> </div>
</div> </div>
<SectionDivider /> <SectionDivider />
{/* Achievements */}
<div> <div>
<h2 className="text-sm font-bold text-text-secondary mb-2">الانجازات</h2> <h2 className="text-sm font-bold text-text-secondary mb-3">الانجازات</h2>
<div className="grid grid-cols-3 gap-2"> <div className="grid grid-cols-3 gap-3">
{[ {[
{ label: 'المحارب' }, { label: 'المحارب' },
{ label: 'البطل' }, { label: 'البطل' },
...@@ -129,28 +129,29 @@ export function ProfilePage() { ...@@ -129,28 +129,29 @@ export function ProfilePage() {
].map((badge, i) => ( ].map((badge, i) => (
<motion.div <motion.div
key={badge.label} key={badge.label}
className="flex flex-col items-center gap-2 p-3 rounded-xl bg-surface-1 border border-border/50 opacity-60" className="flex flex-col items-center gap-2.5 p-4 rounded-xl bg-surface-1 border border-border/60 opacity-50"
initial={{ opacity: 0, scale: 0.9 }} initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 0.6, scale: 1 }} animate={{ opacity: 0.5, scale: 1 }}
transition={{ delay: 0.2 + i * 0.08 }} transition={{ delay: 0.2 + i * 0.08 }}
> >
<div className="w-10 h-10 rounded-full bg-surface-3 border border-border flex items-center justify-center"> <div className="w-12 h-12 rounded-full bg-surface-3/80 border border-border flex items-center justify-center">
<Lock size={14} className="text-text-muted" /> <Lock size={16} className="text-text-muted/60" />
</div> </div>
<span className="text-[10px] font-semibold text-text-muted">{badge.label}</span> <span className="text-[11px] font-semibold text-text-muted">{badge.label}</span>
<span className="text-[9px] text-gold/60">قريبا</span> <span className="text-[9px] text-gold/50 font-medium">قريبا</span>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div> </div>
<div className="mt-auto pt-6 flex justify-center"> {/* Logout */}
<div className="pt-4 pb-6 flex justify-center">
<motion.button <motion.button
whileTap={{ scale: 0.95 }} whileTap={{ scale: 0.95 }}
onClick={handleLogout} onClick={handleLogout}
className="flex items-center gap-1.5 px-3 py-1.5 text-xs text-coral/80 hover:text-coral transition-colors" className="flex items-center gap-2 px-4 py-2 rounded-lg text-xs text-coral/70 hover:text-coral transition-colors"
> >
<LogOut size={13} /> <LogOut size={14} />
<span>تسجيل الخروج</span> <span>تسجيل الخروج</span>
</motion.button> </motion.button>
</div> </div>
...@@ -160,10 +161,10 @@ export function ProfilePage() { ...@@ -160,10 +161,10 @@ export function ProfilePage() {
function StatMini({ icon, value, label }: { icon: React.ReactNode; value: number | string; label: string }) { function StatMini({ icon, value, label }: { icon: React.ReactNode; value: number | string; label: string }) {
return ( return (
<div className="flex flex-col items-center gap-1 p-2 rounded-lg bg-surface-1 border border-border"> <div className="flex flex-col items-center gap-1.5 p-3 rounded-xl bg-surface-1 border border-border/80">
{icon} {icon}
<span className="text-sm font-bold">{value}</span> <span className="text-base font-bold">{value}</span>
<span className="text-[9px] text-text-muted text-center leading-tight">{label}</span> <span className="text-[9px] text-text-muted text-center leading-tight font-medium">{label}</span>
</div> </div>
) )
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment