Add badge system based on user impact scores
- Created badge utility with 5 levels (Beginner, Intermediate, Advanced, Expert, Master) - Badge thresholds: 0, 50, 100, 150, 200 points - Implemented BadgeDisplay component with progress tracking - Enhanced user profile statistics boxes with centered layout, gradients, and icons - Added badge progress section showing advancement to next level - Badge images reference existing assets in /public folder
This commit is contained in:
69
src/components/auth/BadgeDisplay.tsx
Normal file
69
src/components/auth/BadgeDisplay.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { getBadgeForScore, getNextBadgeProgress } from '@/utils/badges';
|
||||
|
||||
interface BadgeDisplayProps {
|
||||
impactScore: number;
|
||||
showProgress?: boolean;
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
}
|
||||
|
||||
/**
|
||||
* Display user's badge based on impact score
|
||||
*/
|
||||
export function BadgeDisplay({ impactScore, showProgress = false, size = 'medium' }: BadgeDisplayProps) {
|
||||
const { currentBadge, nextBadge, progress, pointsToNext } = getNextBadgeProgress(impactScore);
|
||||
|
||||
const sizeClasses = {
|
||||
small: 'h-12 w-12',
|
||||
medium: 'h-20 w-20',
|
||||
large: 'h-32 w-32',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center space-y-3">
|
||||
{/* Badge Image */}
|
||||
<div className="relative">
|
||||
<img
|
||||
src={currentBadge.image}
|
||||
alt={`${currentBadge.level} Badge`}
|
||||
className={`${sizeClasses[size]} object-contain`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Badge Info */}
|
||||
<div className="text-center">
|
||||
<span className={`inline-block px-3 py-1 rounded-full text-sm font-semibold ${currentBadge.color}`}>
|
||||
{currentBadge.level}
|
||||
</span>
|
||||
<p className="text-xs text-gray-600 mt-1">{currentBadge.description}</p>
|
||||
</div>
|
||||
|
||||
{/* Progress to Next Badge */}
|
||||
{showProgress && nextBadge && (
|
||||
<div className="w-full max-w-xs">
|
||||
<div className="flex justify-between text-xs text-gray-600 mb-1">
|
||||
<span>Progress to {nextBadge.level}</span>
|
||||
<span>{pointsToNext} points to go</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
||||
<div
|
||||
className="bg-gradient-to-r from-blue-500 to-purple-500 h-2 rounded-full transition-all duration-500"
|
||||
style={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between text-xs text-gray-500 mt-1">
|
||||
<span>{currentBadge.minScore}</span>
|
||||
<span>{nextBadge.minScore}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Master Badge - No Progress */}
|
||||
{showProgress && !nextBadge && (
|
||||
<div className="text-center">
|
||||
<p className="text-sm font-semibold text-yellow-600">🏆 Maximum Level Achieved!</p>
|
||||
<p className="text-xs text-gray-600">You're an environmental legend</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,4 +3,5 @@ export { UserProfile } from './UserProfile';
|
||||
export { SignInPage } from './SignInPage';
|
||||
export { SignUpPage } from './SignUpPage';
|
||||
export { NotificationSettings } from './NotificationSettings';
|
||||
export { BadgeDisplay } from './BadgeDisplay';
|
||||
export type { NotificationPreferences, AreaOfInterest } from './NotificationSettings';
|
||||
|
||||
Reference in New Issue
Block a user