T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.ca/public_html/src/components/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/public_html/src/components/AchievementSystem.tsx
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { 
  Trophy, 
  Star, 
  Award, 
  Target, 
  TrendingUp, 
  Users, 
  MessageSquare, 
  ThumbsUp,
  Eye,
  Calendar,
  Zap,
  Crown,
  Medal,
  Shield,
  Heart
} from 'lucide-react';

interface Achievement {
  id: string;
  title: string;
  description: string;
  icon: string;
  category: 'social' | 'professional' | 'engagement' | 'milestone';
  rarity: 'common' | 'rare' | 'epic' | 'legendary';
  progress: number;
  maxProgress: number;
  unlocked: boolean;
  unlockedAt?: Date;
  xpReward: number;
}

interface UserLevel {
  level: number;
  currentXP: number;
  xpToNext: number;
  totalXP: number;
  title: string;
  badge: string;
}

interface AchievementSystemProps {
  userId: string;
  stats?: {
    followers: number;
    following: number;
    cases: number;
    endorsements: number;
    profileViews: number;
    messages: number;
    daysActive: number;
  };
}

const AchievementSystem: React.FC<AchievementSystemProps> = ({ userId, stats }) => {
  const [achievements, setAchievements] = useState<Achievement[]>([]);
  const [userLevel, setUserLevel] = useState<UserLevel>({
    level: 1,
    currentXP: 0,
    xpToNext: 100,
    totalXP: 0,
    title: 'Novice',
    badge: '🌱'
  });
  const [showUnlockAnimation, setShowUnlockAnimation] = useState(false);
  const [recentUnlock, setRecentUnlock] = useState<Achievement | null>(null);

  // Provide default stats if undefined
  const defaultStats = {
    followers: 0,
    following: 0,
    cases: 0,
    endorsements: 0,
    profileViews: 0,
    messages: 0,
    daysActive: 0,
    ...(stats || {})
  };

  console.log('AchievementSystem render:', { userId, stats, defaultStats });

  useEffect(() => {
    console.log('AchievementSystem useEffect triggered:', { defaultStats });
    generateAchievements();
    calculateUserLevel();
  }, [defaultStats]);

  const generateAchievements = () => {
    console.log('generateAchievements called with defaultStats:', defaultStats);
    
    const baseAchievements: Achievement[] = [
      // Social Achievements
      {
        id: 'first_follower',
        title: 'First Steps',
        description: 'Gain your first follower',
        icon: '👥',
        category: 'social',
        rarity: 'common',
        progress: Math.min(defaultStats.followers, 1),
        maxProgress: 1,
        unlocked: defaultStats.followers >= 1,
        xpReward: 50
      },
      {
        id: 'social_butterfly',
        title: 'Social Butterfly',
        description: 'Reach 10 followers',
        icon: '🦋',
        category: 'social',
        rarity: 'common',
        progress: Math.min(defaultStats.followers, 10),
        maxProgress: 10,
        unlocked: defaultStats.followers >= 10,
        xpReward: 100
      },
      {
        id: 'influencer',
        title: 'Influencer',
        description: 'Reach 100 followers',
        icon: '⭐',
        category: 'social',
        rarity: 'rare',
        progress: Math.min(defaultStats.followers, 100),
        maxProgress: 100,
        unlocked: defaultStats.followers >= 100,
        xpReward: 500
      },
      {
        id: 'celebrity',
        title: 'Celebrity',
        description: 'Reach 1000 followers',
        icon: '👑',
        category: 'social',
        rarity: 'epic',
        progress: Math.min(defaultStats.followers, 1000),
        maxProgress: 1000,
        unlocked: defaultStats.followers >= 1000,
        xpReward: 2000
      },

      // Professional Achievements
      {
        id: 'first_case',
        title: 'Case Handler',
        description: 'Participate in your first case',
        icon: '📋',
        category: 'professional',
        rarity: 'common',
        progress: Math.min(defaultStats.cases, 1),
        maxProgress: 1,
        unlocked: defaultStats.cases >= 1,
        xpReward: 100
      },
      {
        id: 'case_expert',
        title: 'Case Expert',
        description: 'Participate in 10 cases',
        icon: '🎯',
        category: 'professional',
        rarity: 'rare',
        progress: Math.min(defaultStats.cases, 10),
        maxProgress: 10,
        unlocked: defaultStats.cases >= 10,
        xpReward: 300
      },
      {
        id: 'legal_legend',
        title: 'Legal Legend',
        description: 'Participate in 50 cases',
        icon: '⚖️',
        category: 'professional',
        rarity: 'epic',
        progress: Math.min(defaultStats.cases, 50),
        maxProgress: 50,
        unlocked: defaultStats.cases >= 50,
        xpReward: 1000
      },

      // Engagement Achievements
      {
        id: 'first_endorsement',
        title: 'Endorsed',
        description: 'Receive your first endorsement',
        icon: '👍',
        category: 'engagement',
        rarity: 'common',
        progress: Math.min(defaultStats.endorsements, 1),
        maxProgress: 1,
        unlocked: defaultStats.endorsements >= 1,
        xpReward: 75
      },
      {
        id: 'highly_endorsed',
        title: 'Highly Endorsed',
        description: 'Receive 25 endorsements',
        icon: '🏆',
        category: 'engagement',
        rarity: 'rare',
        progress: Math.min(defaultStats.endorsements, 25),
        maxProgress: 25,
        unlocked: defaultStats.endorsements >= 25,
        xpReward: 400
      },
      {
        id: 'trusted_professional',
        title: 'Trusted Professional',
        description: 'Receive 100 endorsements',
        icon: '🛡️',
        category: 'engagement',
        rarity: 'epic',
        progress: Math.min(defaultStats.endorsements, 100),
        maxProgress: 100,
        unlocked: defaultStats.endorsements >= 100,
        xpReward: 1500
      },

      // Milestone Achievements
      {
        id: 'first_view',
        title: 'Noticed',
        description: 'Receive your first profile view',
        icon: '👁️',
        category: 'milestone',
        rarity: 'common',
        progress: Math.min(defaultStats.profileViews, 1),
        maxProgress: 1,
        unlocked: defaultStats.profileViews >= 1,
        xpReward: 25
      },
      {
        id: 'popular',
        title: 'Popular',
        description: 'Reach 100 profile views',
        icon: '🔥',
        category: 'milestone',
        rarity: 'common',
        progress: Math.min(defaultStats.profileViews, 100),
        maxProgress: 100,
        unlocked: defaultStats.profileViews >= 100,
        xpReward: 200
      },
      {
        id: 'viral',
        title: 'Viral',
        description: 'Reach 1000 profile views',
        icon: '🚀',
        category: 'milestone',
        rarity: 'rare',
        progress: Math.min(defaultStats.profileViews, 1000),
        maxProgress: 1000,
        unlocked: defaultStats.profileViews >= 1000,
        xpReward: 800
      },
      {
        id: 'week_warrior',
        title: 'Week Warrior',
        description: 'Stay active for 7 days',
        icon: '📅',
        category: 'milestone',
        rarity: 'common',
        progress: Math.min(defaultStats.daysActive, 7),
        maxProgress: 7,
        unlocked: defaultStats.daysActive >= 7,
        xpReward: 150
      },
      {
        id: 'month_master',
        title: 'Month Master',
        description: 'Stay active for 30 days',
        icon: '📆',
        category: 'milestone',
        rarity: 'rare',
        progress: Math.min(defaultStats.daysActive, 30),
        maxProgress: 30,
        unlocked: defaultStats.daysActive >= 30,
        xpReward: 600
      }
    ];

    setAchievements(baseAchievements);
  };

  const calculateUserLevel = () => {
    const totalXP = achievements
      .filter(a => a.unlocked)
      .reduce((sum, a) => sum + a.xpReward, 0);

    const level = Math.floor(totalXP / 1000) + 1;
    const currentXP = totalXP % 1000;
    const xpToNext = 1000 - currentXP;

    const titles = [
      'Novice', 'Apprentice', 'Practitioner', 'Specialist', 'Expert',
      'Master', 'Grandmaster', 'Legend', 'Mythic', 'Divine'
    ];

    const badges = ['🌱', '🌿', '🌳', '🌲', '⭐', '🌟', '💫', '✨', '👑', '🏆'];

    setUserLevel({
      level: Math.min(level, 10),
      currentXP,
      xpToNext,
      totalXP,
      title: titles[Math.min(level - 1, 9)],
      badge: badges[Math.min(level - 1, 9)]
    });
  };

  const getRarityColor = (rarity: string) => {
    switch (rarity) {
      case 'common': return 'text-gray-600 bg-gray-100';
      case 'rare': return 'text-blue-600 bg-blue-100';
      case 'epic': return 'text-purple-600 bg-purple-100';
      case 'legendary': return 'text-yellow-600 bg-yellow-100';
      default: return 'text-gray-600 bg-gray-100';
    }
  };

  const getCategoryIcon = (category: string) => {
    switch (category) {
      case 'social': return <Users className="h-4 w-4" />;
      case 'professional': return <Target className="h-4 w-4" />;
      case 'engagement': return <ThumbsUp className="h-4 w-4" />;
      case 'milestone': return <TrendingUp className="h-4 w-4" />;
      default: return <Star className="h-4 w-4" />;
    }
  };

  const unlockedCount = achievements.filter(a => a.unlocked).length;
  const totalCount = achievements.length;

  return (
    <div className="bg-white rounded-xl shadow p-6">
      <div className="flex items-center justify-between mb-6">
        <h2 className="text-xl font-semibold flex items-center gap-2">
          <Trophy className="h-6 w-6 text-yellow-500" />
          Achievements & Level
        </h2>
        <div className="text-sm text-gray-500">
          {unlockedCount}/{totalCount} unlocked
        </div>
      </div>

      {/* Level Progress */}
      <div className="bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg p-4 mb-6 text-white">
        <div className="flex items-center justify-between mb-2">
          <div className="flex items-center gap-2">
            <span className="text-2xl">{userLevel.badge}</span>
            <div>
              <div className="font-semibold">Level {userLevel.level}</div>
              <div className="text-sm opacity-90">{userLevel.title}</div>
            </div>
          </div>
          <div className="text-right">
            <div className="font-semibold">{userLevel.totalXP} XP</div>
            <div className="text-sm opacity-90">Total Experience</div>
          </div>
        </div>
        <div className="w-full bg-white/20 rounded-full h-2 mb-2">
          <div 
            className="bg-white h-2 rounded-full transition-all duration-500"
            style={{ width: `${(userLevel.currentXP / 1000) * 100}%` }}
          ></div>
        </div>
        <div className="text-sm opacity-90">
          {userLevel.currentXP} / 1000 XP to next level
        </div>
      </div>

      {/* Achievement Categories */}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
        {['social', 'professional', 'engagement', 'milestone'].map(category => {
          const categoryAchievements = achievements.filter(a => a.category === category);
          const unlocked = categoryAchievements.filter(a => a.unlocked).length;
          const total = categoryAchievements.length;
          
          return (
            <div key={category} className="bg-gray-50 rounded-lg p-3">
              <div className="flex items-center gap-2 mb-2">
                {getCategoryIcon(category)}
                <span className="font-medium capitalize">{category}</span>
              </div>
              <div className="text-sm text-gray-600">
                {unlocked}/{total} completed
              </div>
              <div className="w-full bg-gray-200 rounded-full h-1 mt-1">
                <div 
                  className="bg-blue-500 h-1 rounded-full"
                  style={{ width: `${(unlocked / total) * 100}%` }}
                ></div>
              </div>
            </div>
          );
        })}
      </div>

      {/* Achievements Grid */}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {achievements.map(achievement => (
          <motion.div
            key={achievement.id}
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.3 }}
            className={`border rounded-lg p-4 transition-all duration-300 ${
              achievement.unlocked 
                ? 'border-green-200 bg-green-50' 
                : 'border-gray-200 bg-gray-50'
            }`}
          >
            <div className="flex items-start justify-between mb-2">
              <div className="flex items-center gap-2">
                <span className="text-2xl">{achievement.icon}</span>
                <div>
                  <h3 className="font-semibold text-sm">{achievement.title}</h3>
                  <p className="text-xs text-gray-600">{achievement.description}</p>
                </div>
              </div>
              {achievement.unlocked && (
                <div className="text-green-500">
                  <Award className="h-4 w-4" />
                </div>
              )}
            </div>
            
            <div className="flex items-center justify-between mb-2">
              <span className={`text-xs px-2 py-1 rounded-full ${getRarityColor(achievement.rarity)}`}>
                {achievement.rarity}
              </span>
              <span className="text-xs text-gray-500">
                +{achievement.xpReward} XP
              </span>
            </div>

            <div className="w-full bg-gray-200 rounded-full h-1">
              <div 
                className={`h-1 rounded-full transition-all duration-500 ${
                  achievement.unlocked ? 'bg-green-500' : 'bg-blue-500'
                }`}
                style={{ width: `${(achievement.progress / achievement.maxProgress) * 100}%` }}
              ></div>
            </div>
            <div className="text-xs text-gray-500 mt-1">
              {achievement.progress}/{achievement.maxProgress}
            </div>
          </motion.div>
        ))}
      </div>

      {/* Unlock Animation */}
      <AnimatePresence>
        {showUnlockAnimation && recentUnlock && (
          <motion.div
            initial={{ opacity: 0, scale: 0.8 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.8 }}
            className="fixed inset-0 flex items-center justify-center z-50 bg-black/50"
            onClick={() => setShowUnlockAnimation(false)}
          >
            <motion.div
              initial={{ y: 50 }}
              animate={{ y: 0 }}
              className="bg-white rounded-xl p-6 max-w-sm mx-4 text-center"
            >
              <div className="text-6xl mb-4">🎉</div>
              <h3 className="text-xl font-bold mb-2">Achievement Unlocked!</h3>
              <div className="text-3xl mb-2">{recentUnlock.icon}</div>
              <h4 className="font-semibold mb-1">{recentUnlock.title}</h4>
              <p className="text-gray-600 text-sm mb-4">{recentUnlock.description}</p>
              <div className="text-green-600 font-semibold">+{recentUnlock.xpReward} XP</div>
            </motion.div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default AchievementSystem; 

CasperSecurity Mini