| import React, { useState, useEffect } from "react"; |
| import { motion, AnimatePresence } from "framer-motion"; |
| import { Medal, Star, Shield, Award } from "lucide-react"; |
|
|
| interface ReputationSystemProps { |
| actionCount: number; |
| } |
|
|
| const ReputationSystem: React.FC<ReputationSystemProps> = ({ actionCount }) => { |
| |
| const [xp, setXp] = useState(() => parseInt(localStorage.getItem("ride_xp") || "0")); |
| const [level, setLevel] = useState(1); |
| const [showLevelUp, setShowLevelUp] = useState(false); |
|
|
| useEffect(() => { |
| |
| const newLevel = Math.floor(Math.sqrt(xp / 100)) + 1; |
| if (newLevel > level) { |
| setShowLevelUp(true); |
| setTimeout(() => setShowLevelUp(false), 3000); |
| } |
| setLevel(newLevel); |
| }, [xp]); |
|
|
| |
| useEffect(() => { |
| if (actionCount > 0) { |
| const gain = Math.floor(Math.random() * 20) + 10; |
| const newXp = xp + gain; |
| setXp(newXp); |
| localStorage.setItem("ride_xp", newXp.toString()); |
| } |
| }, [actionCount]); |
|
|
| const getRankTitle = (lvl: number) => { |
| if (lvl < 2) return "Novice Observer"; |
| if (lvl < 5) return "Data Scout"; |
| if (lvl < 10) return "Pattern Analyst"; |
| return "Neural Architect"; |
| }; |
|
|
| return ( |
| <div className="relative group cursor-default"> |
| {/* Level Up Notification */} |
| <AnimatePresence> |
| {showLevelUp && ( |
| <motion.div |
| initial={{ opacity: 0, scale: 0.5, y: 50 }} |
| animate={{ opacity: 1, scale: 1, y: 0 }} |
| exit={{ opacity: 0, scale: 0.5, y: -50 }} |
| className="fixed inset-0 z-50 flex items-center justify-center pointer-events-none" |
| > |
| <div className="bg-deep-bg/90 border-2 border-yellow-400 p-8 rounded-2xl flex flex-col items-center shadow-[0_0_50px_rgba(250,204,21,0.5)] backdrop-blur-xl"> |
| <Award size={64} className="text-yellow-400 mb-4 animate-bounce" /> |
| <h2 className="text-3xl font-bold text-white mb-2">LEVEL UP!</h2> |
| <p className="text-yellow-400 font-mono text-xl">Level {level}</p> |
| <p className="text-gray-400 mt-2">New privileges accessing...</p> |
| </div> |
| </motion.div> |
| )} |
| </AnimatePresence> |
| |
| <div className="flex items-center gap-3 bg-deep-card/50 px-3 py-1.5 rounded-lg border border-white/5 hover:border-neon-blue/30 transition-colors"> |
| <div className="relative"> |
| <Shield className="w-8 h-8 text-neon-blue" /> |
| <span className="absolute inset-0 flex items-center justify-center text-[10px] font-bold text-black">{level}</span> |
| </div> |
| <div> |
| <div className="text-xs text-gray-400 font-mono uppercase tracking-wider">{getRankTitle(level)}</div> |
| <div className="w-24 h-1.5 bg-gray-700 rounded-full mt-1 overflow-hidden"> |
| <motion.div |
| className="h-full bg-gradient-to-r from-neon-blue to-neon-purple" |
| initial={{ width: 0 }} |
| animate={{ width: `${(xp % 100)}%` }} // Simplified progress |
| /> |
| </div> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |
|
|
| export default ReputationSystem; |
|
|