350 lines
10 KiB
TypeScript
350 lines
10 KiB
TypeScript
'use client'
|
|
|
|
import { useApp } from '@/contexts/AppContext'
|
|
import { Badge } from '@/types'
|
|
|
|
export function UserProfile() {
|
|
const { state } = useApp()
|
|
const { user } = state
|
|
|
|
if (!user) return null
|
|
|
|
const getXPProgress = () => {
|
|
const xpForNextLevel = user.level * 100 // Simple formula: level * 100 XP needed
|
|
const currentLevelXP = (user.level - 1) * 100
|
|
const progressXP = user.xp - currentLevelXP
|
|
const neededXP = xpForNextLevel - currentLevelXP
|
|
return {
|
|
progress: progressXP,
|
|
needed: neededXP,
|
|
percentage: (progressXP / neededXP) * 100
|
|
}
|
|
}
|
|
|
|
const getBadgeRarityColor = (rarity: Badge['rarity']) => {
|
|
switch (rarity) {
|
|
case 'common': return '#8B7D6B'
|
|
case 'rare': return '#C89C2B'
|
|
case 'legendary': return '#7B2E2E'
|
|
default: return '#8B7D6B'
|
|
}
|
|
}
|
|
|
|
const xpProgress = getXPProgress()
|
|
|
|
return (
|
|
<div style={{
|
|
background: 'linear-gradient(135deg, #233043 0%, #2D6A6A 100%)',
|
|
color: '#F7F1E1',
|
|
padding: '24px',
|
|
borderRadius: '8px',
|
|
position: 'relative',
|
|
overflow: 'hidden'
|
|
}}>
|
|
{/* Background Pattern */}
|
|
<div style={{
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
backgroundImage: 'radial-gradient(circle at 20% 80%, rgba(200, 156, 43, 0.1) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(123, 46, 46, 0.1) 0%, transparent 50%)',
|
|
pointerEvents: 'none'
|
|
}} />
|
|
|
|
<div style={{ position: 'relative', zIndex: 1 }}>
|
|
{/* Header */}
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '16px', marginBottom: '24px' }}>
|
|
{/* Avatar */}
|
|
<div style={{
|
|
width: '60px',
|
|
height: '60px',
|
|
borderRadius: '50%',
|
|
background: 'linear-gradient(135deg, #C89C2B, #7B2E2E)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontSize: '24px',
|
|
fontWeight: 'bold',
|
|
color: '#F7F1E1',
|
|
border: '3px solid rgba(247, 241, 225, 0.2)'
|
|
}}>
|
|
{user.username.charAt(0).toUpperCase()}
|
|
</div>
|
|
|
|
{/* User Info */}
|
|
<div style={{ flex: 1 }}>
|
|
<h3 style={{
|
|
fontFamily: 'Abril Fatface, serif',
|
|
fontSize: '24px',
|
|
margin: '0 0 4px 0',
|
|
color: '#F7F1E1'
|
|
}}>
|
|
{user.username}
|
|
</h3>
|
|
<div style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '12px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: 'rgba(247, 241, 225, 0.7)'
|
|
}}>
|
|
Level {user.level} Collector • {user.xp} XP
|
|
</div>
|
|
</div>
|
|
|
|
{/* Streak */}
|
|
<div style={{
|
|
textAlign: 'center',
|
|
padding: '8px 12px',
|
|
background: 'rgba(247, 241, 225, 0.1)',
|
|
borderRadius: '8px',
|
|
border: '1px solid rgba(247, 241, 225, 0.2)'
|
|
}}>
|
|
<div style={{ fontSize: '20px', marginBottom: '4px' }}>🔥</div>
|
|
<div style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '12px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em'
|
|
}}>
|
|
{user.streak} Day Streak
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* XP Progress Bar */}
|
|
<div style={{ marginBottom: '24px' }}>
|
|
<div style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: '8px'
|
|
}}>
|
|
<span style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '12px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: 'rgba(247, 241, 225, 0.7)'
|
|
}}>
|
|
Progress to Level {user.level + 1}
|
|
</span>
|
|
<span style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '12px',
|
|
color: '#C89C2B'
|
|
}}>
|
|
{xpProgress.progress}/{xpProgress.needed} XP
|
|
</span>
|
|
</div>
|
|
<div style={{
|
|
width: '100%',
|
|
height: '8px',
|
|
backgroundColor: 'rgba(247, 241, 225, 0.1)',
|
|
borderRadius: '4px',
|
|
overflow: 'hidden'
|
|
}}>
|
|
<div style={{
|
|
width: `${Math.min(xpProgress.percentage, 100)}%`,
|
|
height: '100%',
|
|
background: 'linear-gradient(90deg, #C89C2B, #7B2E2E)',
|
|
borderRadius: '4px',
|
|
transition: 'width 0.3s ease'
|
|
}} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Grid */}
|
|
<div style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
gap: '16px',
|
|
marginBottom: '24px'
|
|
}}>
|
|
<div style={{
|
|
textAlign: 'center',
|
|
padding: '12px',
|
|
background: 'rgba(247, 241, 225, 0.05)',
|
|
borderRadius: '8px',
|
|
border: '1px solid rgba(247, 241, 225, 0.1)'
|
|
}}>
|
|
<div style={{
|
|
fontSize: '24px',
|
|
fontWeight: 'bold',
|
|
color: '#C89C2B',
|
|
marginBottom: '4px'
|
|
}}>
|
|
{user.wishlist.length}
|
|
</div>
|
|
<div style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '11px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: 'rgba(247, 241, 225, 0.7)'
|
|
}}>
|
|
Wishlisted
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{
|
|
textAlign: 'center',
|
|
padding: '12px',
|
|
background: 'rgba(247, 241, 225, 0.05)',
|
|
borderRadius: '8px',
|
|
border: '1px solid rgba(247, 241, 225, 0.1)'
|
|
}}>
|
|
<div style={{
|
|
fontSize: '24px',
|
|
fontWeight: 'bold',
|
|
color: '#C89C2B',
|
|
marginBottom: '4px'
|
|
}}>
|
|
{user.badges.length}
|
|
</div>
|
|
<div style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '11px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: 'rgba(247, 241, 225, 0.7)'
|
|
}}>
|
|
Badges
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{
|
|
textAlign: 'center',
|
|
padding: '12px',
|
|
background: 'rgba(247, 241, 225, 0.05)',
|
|
borderRadius: '8px',
|
|
border: '1px solid rgba(247, 241, 225, 0.1)'
|
|
}}>
|
|
<div style={{
|
|
fontSize: '24px',
|
|
fontWeight: 'bold',
|
|
color: '#C89C2B',
|
|
marginBottom: '4px'
|
|
}}>
|
|
{user.collections.length}
|
|
</div>
|
|
<div style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '11px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: 'rgba(247, 241, 225, 0.7)'
|
|
}}>
|
|
Collections
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Badges */}
|
|
{user.badges.length > 0 && (
|
|
<div>
|
|
<h4 style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '14px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: '#C89C2B',
|
|
marginBottom: '12px'
|
|
}}>
|
|
Recent Badges
|
|
</h4>
|
|
<div style={{
|
|
display: 'flex',
|
|
flexWrap: 'wrap',
|
|
gap: '8px'
|
|
}}>
|
|
{user.badges.slice(0, 4).map((badge) => (
|
|
<div
|
|
key={badge.id}
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '8px',
|
|
padding: '8px 12px',
|
|
background: 'rgba(247, 241, 225, 0.1)',
|
|
borderRadius: '8px',
|
|
border: `1px solid ${getBadgeRarityColor(badge.rarity)}`,
|
|
position: 'relative'
|
|
}}
|
|
title={badge.description}
|
|
>
|
|
<span style={{ fontSize: '16px' }}>{badge.icon}</span>
|
|
<span style={{
|
|
fontFamily: 'Space Mono, monospace',
|
|
fontSize: '11px',
|
|
textTransform: 'uppercase',
|
|
letterSpacing: '0.1em',
|
|
color: getBadgeRarityColor(badge.rarity)
|
|
}}>
|
|
{badge.name}
|
|
</span>
|
|
{badge.rarity === 'legendary' && (
|
|
<div style={{
|
|
position: 'absolute',
|
|
top: '-4px',
|
|
right: '-4px',
|
|
width: '8px',
|
|
height: '8px',
|
|
borderRadius: '50%',
|
|
background: '#7B2E2E',
|
|
animation: 'pulse 2s infinite'
|
|
}} />
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Quick Actions */}
|
|
<div style={{
|
|
display: 'flex',
|
|
gap: '8px',
|
|
marginTop: '20px',
|
|
paddingTop: '20px',
|
|
borderTop: '1px solid rgba(247, 241, 225, 0.1)'
|
|
}}>
|
|
<button
|
|
className="stamp-button"
|
|
style={{
|
|
fontSize: '11px',
|
|
padding: '8px 12px',
|
|
backgroundColor: 'rgba(247, 241, 225, 0.1)',
|
|
borderColor: 'rgba(247, 241, 225, 0.3)',
|
|
color: '#F7F1E1'
|
|
}}
|
|
>
|
|
View Wishlist
|
|
</button>
|
|
<button
|
|
className="stamp-button"
|
|
style={{
|
|
fontSize: '11px',
|
|
padding: '8px 12px',
|
|
backgroundColor: 'rgba(247, 241, 225, 0.1)',
|
|
borderColor: 'rgba(247, 241, 225, 0.3)',
|
|
color: '#F7F1E1'
|
|
}}
|
|
>
|
|
Settings
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* CSS Animation for legendary badge pulse */}
|
|
<style jsx>{`
|
|
@keyframes pulse {
|
|
0% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
100% { opacity: 1; }
|
|
}
|
|
`}</style>
|
|
</div>
|
|
)
|
|
} |