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 {
const variants = {
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',
coral: 'bg-coral/90 text-white font-bold',
cyan: 'bg-cyan/90 text-background font-bold',
ghost: 'bg-surface-2 border border-border text-text-primary font-semibold hover:border-gold/40 hover:bg-surface-3',
coral: 'bg-gradient-to-l from-coral to-coral/80 text-white font-bold shadow-md shadow-coral/15',
cyan: 'bg-gradient-to-l from-cyan to-cyan/80 text-background font-bold shadow-md shadow-cyan/15',
}
const sizes = {
sm: 'px-4 py-2 text-sm rounded-lg',
md: 'px-6 py-3 text-base rounded-xl',
lg: 'px-8 py-4 text-lg rounded-2xl',
sm: 'px-5 py-2.5 text-sm rounded-xl gap-2 min-w-[80px]',
md: 'px-7 py-3.5 text-base rounded-xl gap-2.5 min-w-[100px]',
lg: 'px-8 py-4.5 text-lg rounded-2xl gap-3 min-w-[120px]',
}
export function Button({
......@@ -41,8 +41,8 @@ export function Button({
type={type}
onClick={onClick}
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}`}
whileTap={!disabled ? { scale: 0.95 } : undefined}
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.96 } : undefined}
transition={{ type: 'spring', stiffness: 500, damping: 20 }}
>
{loading && <Loader2 size={18} className="animate-spin" />}
......
......@@ -11,7 +11,7 @@ interface CardProps {
export function Card({ children, className = '', glow = false, onClick }: CardProps) {
return (
<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}
whileTap={onClick ? { scale: 0.98 } : undefined}
onClick={onClick}
......
......@@ -39,29 +39,31 @@ export function BotSelectPage() {
if (loading) {
return (
<PageTransition className="px-4 py-6 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" />
<p className="mt-3 text-sm text-text-muted">جاري تحميل الروبوتات...</p>
<PageTransition className="px-5 py-8 flex flex-col items-center justify-center min-h-[60vh]">
<div className="w-10 h-10 border-2 border-gold/30 border-t-gold rounded-full animate-spin" />
<p className="mt-4 text-sm text-text-muted">جاري تحميل الروبوتات...</p>
</PageTransition>
)
}
return (
<PageTransition className="px-4 py-6 flex flex-col gap-5 pb-32">
{/* Header with back button */}
<div className="flex items-center gap-3">
<PageTransition className="px-5 py-6 flex flex-col gap-6 pb-36">
{/* Header */}
<div className="flex items-center gap-4">
<motion.button
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 }}
>
<ChevronRight size={18} className="text-text-secondary" />
<ChevronRight size={20} className="text-text-secondary" />
</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>
<p className="text-sm text-text-secondary">اختر خصمك حسب مستواك</p>
{/* Bot List */}
<div className="flex flex-col gap-3">
{bots.map((bot, i) => {
const isSelected = selectedBot === bot.id
......@@ -73,78 +75,66 @@ export function BotSelectPage() {
key={bot.id}
initial={{ opacity: 0, y: 15 }}
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
glow={isSelected}
onClick={() => setSelectedBot(bot.id)}
className={`flex items-center gap-3 transition-all ${
isSelected
? 'border-gold/60 scale-[1.02] border-r-4'
: ''
className={`flex items-center gap-4 transition-all ${
isSelected ? 'border-gold/60 scale-[1.01]' : ''
}`}
>
{/* Bot Portrait with colored fallback */}
{/* Portrait */}
<div
className="relative w-12 h-12 rounded-full overflow-hidden flex-shrink-0"
style={{ backgroundColor: `${diffColor}20` }}
className="relative w-14 h-14 rounded-full overflow-hidden flex-shrink-0 border-2"
style={{ backgroundColor: `${diffColor}15`, borderColor: `${diffColor}40` }}
>
<img
src={getBotPortraitUrl(bot.id)}
alt={bot.name}
className="w-full h-full object-cover relative z-10"
onError={(e) => {
(e.target as HTMLImageElement).style.display = 'none'
}}
onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
/>
<div
className="absolute inset-0 flex items-center justify-center"
style={{ color: diffColor }}
>
<span className="text-lg font-bold">{bot.name_ar?.charAt(0) || bot.name.charAt(0)}</span>
<div className="absolute inset-0 flex items-center justify-center" style={{ color: diffColor }}>
<span className="text-xl font-bold">{bot.name_ar?.charAt(0) || bot.name.charAt(0)}</span>
</div>
</div>
{/* Bot Info */}
<div className="flex-1 min-w-0">
{/* Info */}
<div className="flex-1 min-w-0 space-y-1.5">
<div className="flex items-center gap-2">
<h3 className="text-sm font-bold truncate">{bot.name_ar}</h3>
<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 }}
>
{bot.style_ar}
</span>
</div>
<p className="text-[11px] text-text-muted truncate mt-0.5">{bot.bio_ar}</p>
<div className="flex items-center gap-3 mt-1.5">
<span className="text-[10px] text-text-muted">
{bot.elo_min}-{bot.elo_max} تقييم
</span>
{/* Strength dots */}
<div className="flex items-center gap-0.5">
<p className="text-[11px] text-text-muted truncate leading-relaxed">{bot.bio_ar}</p>
<div className="flex items-center gap-3">
<span className="text-[10px] text-text-muted">{bot.elo_min}-{bot.elo_max} تقييم</span>
<div className="flex items-center gap-[3px]">
{Array.from({ length: TOTAL_STRENGTH_DOTS }).map((_, dotIndex) => (
<div
key={dotIndex}
className="w-1.5 h-1.5 rounded-full transition-colors"
style={{
backgroundColor: dotIndex < strengthLevel ? diffColor : `${diffColor}30`,
}}
className="w-[5px] h-[5px] rounded-full"
style={{ backgroundColor: dotIndex < strengthLevel ? diffColor : `${diffColor}25` }}
/>
))}
</div>
</div>
</div>
{/* Selection indicator */}
{/* Check */}
{isSelected && (
<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 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 500, damping: 20 }}
>
<Swords size={10} className="text-background" />
<Swords size={12} className="text-background" />
</motion.div>
)}
</Card>
......@@ -153,10 +143,10 @@ export function BotSelectPage() {
})}
</div>
{/* Bottom CTA with safe area */}
{/* CTA */}
{selectedBot && (
<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 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 400, damping: 25 }}
......
......@@ -365,10 +365,10 @@ export function GamePage() {
return (
<div className="flex flex-col min-h-dvh bg-background">
{/* 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
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 }}
>
<ChevronRight size={20} className="text-text-muted" />
......@@ -376,7 +376,7 @@ export function GamePage() {
{/* Turn indicator - glowing pill */}
<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
? 'bg-gold/20 text-gold border border-gold/40'
: 'bg-surface-2 text-text-secondary border border-border'
......@@ -402,10 +402,10 @@ export function GamePage() {
</div>
{/* 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) */}
<div className="w-full max-w-[min(100vw-16px,400px)] flex items-center gap-2 px-1 py-1.5">
<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-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-10 h-10 rounded-full overflow-hidden bg-surface-3 border border-border flex items-center justify-center shrink-0">
{isBot && botId ? (
<img
src={getBotPortraitUrl(botId)}
......@@ -444,14 +444,14 @@ export function GamePage() {
</div>
{/* File labels (bottom) */}
<div className="mr-4">
<div className="mr-4 mt-1">
{renderFileLabels()}
</div>
</div>
{/* 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-8 h-8 rounded-full bg-surface-3 border border-border flex items-center justify-center shrink-0 relative">
<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-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" />
<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>
......@@ -462,7 +462,7 @@ export function GamePage() {
</div>
{/* Action buttons */}
<div className="flex items-center gap-3 mt-3">
<div className="flex items-center gap-4 mt-5">
<Button
variant="coral"
size="md"
......@@ -478,7 +478,7 @@ export function GamePage() {
</div>
{/* 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="bg-surface-1 rounded-lg border border-border min-h-[36px] max-h-[56px] overflow-hidden">
{renderMoveList() || (
......@@ -490,7 +490,7 @@ export function GamePage() {
</div>
{/* 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() ? '- كش!' : ''}
</div>
</div>
......@@ -505,7 +505,7 @@ export function GamePage() {
exit={{ opacity: 0 }}
>
<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 }}
animate={{ scale: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 300, damping: 22 }}
......
This diff is collapsed.
......@@ -14,10 +14,10 @@ const CATEGORIES = [
] as const
const GAME_ICONS: Record<string, React.ReactNode> = {
backgammon: <span className="text-2xl font-bold text-gold">&#x2680;</span>,
dominoes: <span className="text-2xl font-bold text-gold">&#x1F0A1;</span>,
ludo: <span className="text-2xl font-bold text-gold">&#x2684;</span>,
trivia: <span className="text-2xl font-bold text-gold">?</span>,
backgammon: <span className="text-2xl font-bold text-text-muted">&#x2680;</span>,
dominoes: <span className="text-2xl font-bold text-text-muted">&#x1F0A1;</span>,
ludo: <span className="text-2xl font-bold text-text-muted">&#x2684;</span>,
trivia: <span className="text-lg font-bold text-text-muted">?</span>,
}
export function PlayPage() {
......@@ -28,59 +28,61 @@ export function PlayPage() {
const otherGames = GAMES.filter((g) => g.key !== 'chess')
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>
{/* Chess Hero Card - full width */}
{/* Chess Hero Card */}
<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 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 400, damping: 25 }}
whileTap={{ scale: 0.97 }}
>
<div className="w-14 h-14 rounded-xl bg-gold/10 border border-gold/30 flex items-center justify-center">
<Crown size={28} className="text-gold" />
<div className="w-16 h-16 rounded-2xl bg-gold/10 border border-gold/20 flex items-center justify-center shadow-inner">
<Crown size={32} className="text-gold" />
</div>
<div className="flex-1">
<span className="text-base font-bold">{chessGame.nameAr}</span>
<p className="text-xs text-text-secondary mt-1">العب شطرنج اونلاين ضد لاعبين حقيقيين</p>
<span className="text-lg font-bold">{chessGame.nameAr}</span>
<p className="text-xs text-text-secondary mt-1.5 leading-relaxed">العب شطرنج اونلاين ضد لاعبين حقيقيين</p>
</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>
{/* Other Games 2x2 Grid */}
{/* Other Games Grid */}
<div className="grid grid-cols-2 gap-3">
{otherGames.map((game, i) => (
<motion.div
key={game.key}
className={`relative rounded-2xl overflow-hidden border-2 ${
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`}
className="relative rounded-2xl overflow-hidden border border-border bg-surface-1 opacity-50 p-5 flex flex-col items-center gap-3"
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 }}
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}
</div>
<span className="text-sm font-bold">{game.nameAr}</span>
{!game.available && (
<div className="absolute inset-0 flex items-center justify-center bg-background/60 backdrop-blur-sm">
<Lock size={20} className="text-text-muted" />
<span className="mr-2 text-xs text-text-muted">قريبا</span>
<span className="text-sm font-bold text-text-secondary">{game.nameAr}</span>
<div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-[2px]">
<div className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-surface-2/80 border border-border">
<Lock size={12} className="text-text-muted" />
<span className="text-[11px] text-text-muted font-medium">قريبا</span>
</div>
)}
</div>
</motion.div>
))}
</div>
{/* Time Control Section */}
<div>
<h2 className="text-base font-bold mb-3">نظام الوقت</h2>
<div className="flex gap-3 mb-3">
{/* Time Control */}
<div className="space-y-4">
<h2 className="text-base font-bold">نظام الوقت</h2>
{/* Category Pills */}
<div className="flex gap-2 overflow-x-auto scrollbar-hide pb-1">
{CATEGORIES.map((cat) => {
const isActive = Object.entries(TIME_CONTROLS).find(
([k]) => k === selectedTC
......@@ -89,9 +91,9 @@ export function PlayPage() {
return (
<motion.button
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
? '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'
}`}
whileTap={{ scale: 0.93 }}
......@@ -100,14 +102,15 @@ export function PlayPage() {
if (first) setSelectedTC(first[0])
}}
>
<Icon size={12} />
<Icon size={14} />
{cat.label}
</motion.button>
)
})}
</div>
<div className="grid grid-cols-3 gap-2">
{/* Time Buttons */}
<div className="grid grid-cols-3 gap-2.5">
{Object.entries(TIME_CONTROLS)
.filter(([, v]) => {
const activeCategory = Object.entries(TIME_CONTROLS).find(
......@@ -118,9 +121,9 @@ export function PlayPage() {
.map(([key, tc]) => (
<motion.button
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
? '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'
}`}
whileTap={{ scale: 0.93 }}
......@@ -133,13 +136,12 @@ export function PlayPage() {
</div>
{/* 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>
<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>
</div>
......
......@@ -7,9 +7,7 @@ import { Card } from '../components/ui/Card'
import { supabase } from '../lib/supabase'
function SectionDivider() {
return (
<div className="w-full h-px bg-gradient-to-l from-transparent via-gold/20 to-transparent" />
)
return <div className="w-full h-px bg-gradient-to-l from-transparent via-border to-transparent my-1" />
}
export function ProfilePage() {
......@@ -28,41 +26,42 @@ export function ProfilePage() {
: 0
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-center gap-3">
<div className="flex items-center gap-4">
<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 }}
animate={{ scale: 1 }}
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) || '?'}
</span>
</motion.div>
<div>
<h1 className="text-lg font-bold">{profile.display_name}</h1>
<div className="space-y-1">
<h1 className="text-xl font-bold">{profile.display_name}</h1>
<p className="text-sm text-text-muted">@{profile.username}</p>
</div>
</div>
<motion.button
whileTap={{ scale: 0.9 }}
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" />
</motion.button>
</div>
<Card className="p-4">
{/* XP Card */}
<Card className="p-5">
<div className="flex items-center justify-between mb-3">
<h2 className="text-base font-bold text-text-primary">
المستوى {profile.level}
</h2>
<span className="text-sm text-gold font-semibold">{profile.xp} XP</span>
<h2 className="text-lg font-bold">المستوى {profile.level}</h2>
<span className="text-sm text-gold font-bold px-3 py-1 rounded-full bg-gold/10">{profile.xp} XP</span>
</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
className="h-full rounded-full bg-gradient-to-l from-gold to-gold-light"
initial={{ width: 0 }}
......@@ -70,16 +69,15 @@ export function ProfilePage() {
transition={{ duration: 1, ease: 'easeOut' }}
/>
</div>
<p className="text-[11px] text-text-muted mt-2">
{500 - (profile.xp % 500)} XP للمستوى التالي
</p>
<p className="text-xs text-text-muted mt-2.5">{500 - (profile.xp % 500)} XP للمستوى التالي</p>
</Card>
<SectionDivider />
{/* Ratings */}
<div>
<h2 className="text-sm font-bold text-text-secondary mb-2">التقييمات</h2>
<div className="grid grid-cols-2 gap-2">
<h2 className="text-sm font-bold text-text-secondary mb-3">التقييمات</h2>
<div className="grid grid-cols-2 gap-3">
{[
{ label: 'رصاصة', value: profile.elo_bullet, icon: '1+0' },
{ label: 'خاطف', value: profile.elo_blitz, icon: '5+0' },
......@@ -88,17 +86,17 @@ export function ProfilePage() {
].map((rating, i) => (
<motion.div
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 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 + i * 0.05 }}
>
<div className="w-8 h-8 rounded-lg bg-surface-3 flex items-center justify-center">
<span className="text-[10px] font-bold text-text-muted">{rating.icon}</span>
<div className="w-10 h-10 rounded-lg bg-surface-3 flex items-center justify-center">
<span className="text-[11px] font-bold text-text-muted">{rating.icon}</span>
</div>
<div>
<p className="text-base font-bold">{rating.value}</p>
<p className="text-[10px] text-text-muted">{rating.label}</p>
<p className="text-lg font-bold">{rating.value}</p>
<p className="text-[11px] text-text-muted">{rating.label}</p>
</div>
</motion.div>
))}
......@@ -107,21 +105,23 @@ export function ProfilePage() {
<SectionDivider />
{/* Stats */}
<div>
<h2 className="text-sm font-bold text-text-secondary mb-2">الاحصائيات</h2>
<div className="grid grid-cols-4 gap-2">
<StatMini icon={<Flame size={14} className="text-coral" />} value={profile.best_win_streak} label="افضل سلسلة" />
<StatMini icon={<Trophy size={14} className="text-gold" />} value={profile.total_wins} label="انتصارات" />
<StatMini icon={<Target size={14} className="text-cyan" />} value={`${winRate}%`} label="نسبة الفوز" />
<StatMini icon={<TrendingUp size={14} className="text-purple" />} value={profile.total_games_played} label="مباريات" />
<h2 className="text-sm font-bold text-text-secondary mb-3">الاحصائيات</h2>
<div className="grid grid-cols-4 gap-2.5">
<StatMini icon={<Flame size={16} className="text-coral" />} value={profile.best_win_streak} label="افضل سلسلة" />
<StatMini icon={<Trophy size={16} className="text-gold" />} value={profile.total_wins} label="انتصارات" />
<StatMini icon={<Target size={16} className="text-cyan" />} value={`${winRate}%`} label="نسبة الفوز" />
<StatMini icon={<TrendingUp size={16} className="text-purple" />} value={profile.total_games_played} label="مباريات" />
</div>
</div>
<SectionDivider />
{/* Achievements */}
<div>
<h2 className="text-sm font-bold text-text-secondary mb-2">الانجازات</h2>
<div className="grid grid-cols-3 gap-2">
<h2 className="text-sm font-bold text-text-secondary mb-3">الانجازات</h2>
<div className="grid grid-cols-3 gap-3">
{[
{ label: 'المحارب' },
{ label: 'البطل' },
......@@ -129,28 +129,29 @@ export function ProfilePage() {
].map((badge, i) => (
<motion.div
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 }}
animate={{ opacity: 0.6, scale: 1 }}
animate={{ opacity: 0.5, scale: 1 }}
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">
<Lock size={14} className="text-text-muted" />
<div className="w-12 h-12 rounded-full bg-surface-3/80 border border-border flex items-center justify-center">
<Lock size={16} className="text-text-muted/60" />
</div>
<span className="text-[10px] font-semibold text-text-muted">{badge.label}</span>
<span className="text-[9px] text-gold/60">قريبا</span>
<span className="text-[11px] font-semibold text-text-muted">{badge.label}</span>
<span className="text-[9px] text-gold/50 font-medium">قريبا</span>
</motion.div>
))}
</div>
</div>
<div className="mt-auto pt-6 flex justify-center">
{/* Logout */}
<div className="pt-4 pb-6 flex justify-center">
<motion.button
whileTap={{ scale: 0.95 }}
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>
</motion.button>
</div>
......@@ -160,10 +161,10 @@ export function ProfilePage() {
function StatMini({ icon, value, label }: { icon: React.ReactNode; value: number | string; label: string }) {
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}
<span className="text-sm font-bold">{value}</span>
<span className="text-[9px] text-text-muted text-center leading-tight">{label}</span>
<span className="text-base font-bold">{value}</span>
<span className="text-[9px] text-text-muted text-center leading-tight font-medium">{label}</span>
</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