import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useMockStore } from '../data/mockStore';
import { GamificationProvider, useGamification } from '../context/GamificationContext';
import { useGamification as useOldGamification } from '../hooks/useGamification';
import { useTheme } from '../context/ThemeContext';
import FloatingXPManager from '../components/ProCanvas/gamification/FloatingXPManager';
import LevelUpModal from '../components/ProCanvas/gamification/LevelUpModal';
import profilePic from '../assets/images/Profile_Pic_1_Agent.png';
import {
Trophy, Flame, Target, Star, Gift, Camera,
Map as MapIcon, Users, Crosshair, Award, MapPin,
CheckCircle, ChevronRight, X, Home, Shield, Lock,
ClipboardList, Handshake, DoorOpen, UserPlus, Zap, Activity, TrendingUp, Hexagon, Calendar
} from 'lucide-react';
/*
* ==========================================
* UTILS & THEME
* ==========================================
*/
const C = {
gold: '#FFD700',
neon: '#AAFF00',
blue: '#3B82F6',
fire: '#FF4500',
cyan: '#00E5FF',
purple: '#B388FF',
glass: 'rgba(24, 24, 27, 0.65)',
border: 'rgba(255, 255, 255, 0.08)'
};
// CountUp Component for animated numbers (0 to end)
const CountUp = ({ to, suffix = "", duration = 1500 }) => {
const [count, setCount] = useState(0);
useEffect(() => {
let start = 0;
const end = parseInt(to, 10);
if (isNaN(end)) return;
let startTime = null;
const animate = (timestamp) => {
if (!startTime) startTime = timestamp;
const progress = timestamp - startTime;
const percentage = Math.min(progress / duration, 1);
const ease = 1 - Math.pow(1 - percentage, 4);
setCount(Math.floor(start + (end - start) * ease));
if (percentage < 1) {
requestAnimationFrame(animate);
} else {
setCount(end);
}
};
requestAnimationFrame(animate);
}, [to, duration]);
return <>{count.toLocaleString()}{suffix}>;
};
const useMonthResetCountdown = () => {
const [timeLeft, setTimeLeft] = useState('');
useEffect(() => {
const updateTimer = () => {
const now = new Date();
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59);
const diff = endOfMonth - now;
const d = Math.floor(diff / (1000 * 60 * 60 * 24));
const h = Math.floor((diff / (1000 * 60 * 60)) % 24);
const m = Math.floor((diff / 1000 / 60) % 60);
const s = Math.floor((diff / 1000) % 60);
setTimeLeft(`${d}d ${h}h ${m}m ${s}s`);
};
updateTimer();
const interval = setInterval(updateTimer, 1000);
return () => clearInterval(interval);
}, []);
return timeLeft;
};
const LOG_ACTIONS = [
{ key: 'knock', label: 'Door Knocked', icon: DoorOpen, color: C.cyan },
{ key: 'lead', label: 'Lead Gained', icon: UserPlus, color: C.neon },
{ key: 'appt', label: 'Appointment', icon: Target, color: C.gold },
{ key: 'meeting', label: 'Client Meet', icon: Handshake, color: C.purple },
];
/*
* ==========================================
* PREMIUM COMPONENTS (SPORTS UI)
* ==========================================
*/
// Hexagonal level badge (Like FIFA overall rating)
const HexLevelBadge = ({ level, color = C.gold, size = 100, mobileSize = 85 }) => (
);
// Fut-style Player Card
const OperatorCard = ({ user, gamestate }) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
return (
{/* Card Background (Elite Gold Theme) */}
{/* Glossy overlay */}
{/* Dynamic Light rays */}
{/* Inner Content Container */}
{/* Header Row: OVR and 3 Badges */}
{/* Player Cutout / Photo */}
{/* Name & Title Board */}
{user.name}
{gamestate.currentTitle || 'LVL 12 - FIELD RUNNER'}
{/* Bottom Card Flare */}
);
};
// Sleek Glass Panel (base container for UI)
function GlassPanel({ children, className = '', accentColor = 'transparent', title, icon: Icon, extra }) {
const { theme } = useTheme();
const isDark = theme === 'dark';
const hasAccent = accentColor !== 'transparent';
return (
{/* Dark mode: subtle accent glow line at top */}
{isDark && hasAccent && (
)}
{/* Header */}
{(title || Icon || extra) && (
isDark ? (
{Icon && }
{title}
{extra &&
{extra}
}
) : (
{Icon && }
{title}
{extra &&
{extra}
}
)
)}
{children}
);
}
// Progress Bar (Sleek, bright energy bar)
const EnergyBar = ({ current, max, color = C.neon, label }) => {
const pct = Math.min((current / max) * 100, 100);
return (
{label && (
{label}
/ {max}
)}
);
};
/*
* ==========================================
* MODALS
* ==========================================
*/
const LogActionModal = ({ actionKey, onClose, gs }) => {
const action = LOG_ACTIONS.find(a => a.key === actionKey) || LOG_ACTIONS[0];
const Icon = action.icon;
const [xpReward, setXpReward] = useState(actionKey === 'knock' ? 10 : actionKey === 'lead' ? 50 : 150);
const handleSubmit = (e) => {
e.preventDefault();
const coords = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
if (actionKey === 'knock') gs.logKnock(xpReward > 10, coords);
else if (actionKey === 'lead' || actionKey === 'meeting') gs.logLead(coords);
else if (actionKey === 'appt') gs.logInspection(coords);
onClose();
};
return (
Log {action.label}
Gain XP instantly
);
};
const BadgesModal = ({ onClose, gs }) => (
Trophy Room
View all unlockable badges and progress
{/* Unlocked */}
Unlocked
Hot Spot Hunter
You established a 10-day consistent canvassing streak.
ACHIEVED
Unlocked
Storm Chaser
Reached the top 3 on the daily leaderboard.
ACHIEVED
{/* Locked */}
Locked
Star Closer
Set 50 total appointments.
Locked
Map Master
Cover 10 different neighborhoods entirely.
);
const RewardsModal = ({ onClose, gs }) => (
Season Rewards
Your milestone roadmap for the month
{[
{ title: 'Daily Grind', target: 'Reach 1,000 XP', reward: '+400 XP Bonus', done: true, claimable: false },
{ title: 'Door Warrior', target: 'Reach 2,500 XP', reward: '$25 Gift Card', done: true, claimable: false },
{ title: 'Lead Machine', target: 'Reach 4,800 XP', reward: '$50 Cash Bonus', active: true, claimable: false },
{ title: 'Closer Mode', target: 'Reach 7,500 XP', reward: '$100 Amazon Card', locked: true },
{ title: 'Legend Run', target: 'Reach 12,000 XP', reward: '$250 Cash Bonus', locked: true }
].map((tier, i) => (
{tier.done && }
{tier.title}
{tier.target}
Reward: {tier.reward}
))}
);
/*
* ==========================================
* MAIN LAYOUT MODULE
* ==========================================
*/
const ProCanvasContent = () => {
const { user } = useAuth();
const { users } = useMockStore();
const mockDbUser = {
...(users.find(u => u.email === user?.email) || users.find(u => u.roles?.includes('FIELD_AGENT')) || { name: user?.name || 'Jason T.', empId: 'OP-00' }),
profilePhoto: profilePic,
};
// Hooks
const gs = useGamification() || { xp: 3360, streak: 4, level: 12 };
const oldGamestate = useOldGamification(mockDbUser) || { badges: [], stages: [] };
const resetCountdown = useMonthResetCountdown();
const navigate = useNavigate();
// Modals
const [logAction, setLogAction] = useState(null);
const [showBadges, setShowBadges] = useState(false);
const [showRewards, setShowRewards] = useState(false);
return (
{/* Ambient Background Glows */}
{/* TOP NAVIGATION */}
{/* MAIN DASHBOARD */}
{/* LEFT: PLAYER CARD & LIVE ACTIONS */}
{/* The Ultimate Player Card */}
{/* Quick Stat Bar (Detailed XP/Streak) */}
{/* Detailed XP Progress */}
XP Progress
Next: {gs.nextLevelTitle || 'Field Trooper'}
/ {4800}
{4800 - (gs.xp || 3360)} XP TO NEXT LEVEL
{/* Streak Flow */}
{/* Action Hub */}
{LOG_ACTIONS.map(({ key, label, icon: I, color }) => (
setLogAction(key)}
className="flex flex-col items-center justify-center p-5 rounded-2xl bg-white dark:bg-black/40 border border-zinc-200 dark:border-white/5 hover:bg-zinc-50 dark:hover:bg-white/5 transition-all gap-3 relative overflow-hidden group shadow-sm dark:shadow-[inset_0_0_20px_rgba(0,0,0,0.5)]">
{label}
))}
{/* Missing Card Restored: Daily Missions */}
{/* Weekly Challenge */}
{/* Daily Quests List */}
{/* Hit the Map CTA */}
Hit The Map
{/* RIGHT: LIVE EVENTS & CAMPAIGNS */}
{/* HERO LIVE EVENT BANNER (Today's Mission) */}
navigate('/emp/fa/maps')}
>
{/* Event Background Image/Gradient */}
LIVE EVENT ACTIVE
Knock 20 Doors
Pineland Heights
{/* Play Button */}
START PLAY
{/* Overlay Flare */}
{/* THREE GRID: Showdown, Streak, Challenge */}
{/* Showdown Event Card */}
Leaderboard Event
1ST
18 Leads Today
+250 XP
{/* Streak Event Card */}
Consistency Tracker
{/* Weekly Challenge Card */}
Weekly Objective
{/* SEASON PASS / REWARD PATH (Restored to larger size, scrollable on mobile) */}
48% Complete}>
setShowRewards(true)} className="absolute inset-0 z-20" />
{/* Track Background */}
{/* Track Fill */}
{/* Nodes */}
{[
{ title: 'Daily Grind', reward: '+400 XP' },
{ title: 'Door Warrior', reward: '$25 Gift Card' },
{ title: 'Lead Machine', reward: '$50 Bonus' },
{ title: 'Closer Mode', reward: '$100 Amazon' },
{ title: 'Legend Run', reward: '$250 Bonus' }
].map((node, i) => {
const done = i < 2;
const active = i === 2;
return (
{/* Node Circle */}
{done ? :
active ? :
}
{/* Reward Label (floating below) */}
{node.title}
{node.reward}
);
})}
{/* Restored: Badges & Achievements Grid */}
setShowBadges(true)} className="absolute inset-0 z-20" />
{/* Badge 1 */}
{/* Badge 2 */}
{/* Badge 3 Locked */}
{/* Badge 4 Locked */}
{/* Badge 5 Locked */}
{/* Restored: Full Leaderboard List */}
Resets in {resetCountdown} }>
{/* Table Header */}
Rank
Agent
XP Total
{(gs.leaderboard || []).slice(0, 10).map((row, i) => (
{row.isUser && (
)}
{i === 0 ? (
) : i === 1 ? (
) : i === 2 ? (
) : (
{i + 1}.
)}
))}
{/* FIXED BOTTOM NAVIGATION */}
{[
{ label: 'Map', icon: MapIcon, active: true },
{ label: 'Leads', icon: Users, active: false },
{ label: 'Missions', icon: Target, active: false },
{ label: 'Ranks', icon: Trophy, active: false },
{ label: 'Rewards', icon: Gift, active: false },
].map((item, i) => (
))}
{/* Background Texture Overlay */}
{/* Modal Injection */}
{logAction && setLogAction(null)} gs={gs} />}
{showBadges && setShowBadges(false)} gs={gs} />}
{showRewards && setShowRewards(false)} gs={gs} />}
);
};
export default function ProCanvas() {
return (
);
}