Create Staff Achievements tracking page
cgen-47a31ef5b51d42cbb76fc43aca296bdf
This commit is contained in:
parent
4c7f3a146a
commit
26d2e636c1
1 changed files with 327 additions and 0 deletions
327
client/pages/StaffAchievements.tsx
Normal file
327
client/pages/StaffAchievements.tsx
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Layout from "@/components/Layout";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Progress } from "@/components/ui/progress";
|
||||
import { Trophy, Star, Target, ExternalLink } from "lucide-react";
|
||||
|
||||
const ACHIEVEMENTS = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Developer Leader",
|
||||
description: "Lead 5+ engineering projects",
|
||||
progress: 3,
|
||||
total: 5,
|
||||
icon: "👨💻",
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Community Builder",
|
||||
description: "Mentor 10+ team members",
|
||||
progress: 8,
|
||||
total: 10,
|
||||
icon: "🤝",
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Innovator",
|
||||
description: "Launch 3 new features",
|
||||
progress: 2,
|
||||
total: 3,
|
||||
icon: "💡",
|
||||
unlocked: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Excellence",
|
||||
description: "Maintain 95%+ team satisfaction",
|
||||
progress: 92,
|
||||
total: 95,
|
||||
icon: "⭐",
|
||||
unlocked: false,
|
||||
},
|
||||
];
|
||||
|
||||
const MILESTONES = [
|
||||
{
|
||||
id: 1,
|
||||
title: "1 Year Anniversary",
|
||||
description: "Celebrate 1 year with the team",
|
||||
date: "2025-06-15",
|
||||
achieved: false,
|
||||
daysLeft: 145,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "100 Mentorship Sessions",
|
||||
description: "Complete 100 one-on-one mentorship sessions",
|
||||
date: "2025-03-20",
|
||||
achieved: false,
|
||||
daysLeft: 58,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "First Leadership Role",
|
||||
description: "Lead your first major team initiative",
|
||||
date: "2024-12-01",
|
||||
achieved: true,
|
||||
daysLeft: 0,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "5 Successful Launches",
|
||||
description: "Ship 5 major features to production",
|
||||
date: "2025-04-10",
|
||||
achieved: false,
|
||||
daysLeft: 79,
|
||||
},
|
||||
];
|
||||
|
||||
export default function StaffAchievements() {
|
||||
const navigate = useNavigate();
|
||||
const [expandedAchievement, setExpandedAchievement] = useState<string | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const unlockedCount = ACHIEVEMENTS.filter((a) => a.unlocked).length;
|
||||
const achievedMilestones = MILESTONES.filter((m) => m.achieved).length;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-purple-900/20 to-slate-950 py-12 px-4">
|
||||
<div className="max-w-6xl mx-auto space-y-8">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold text-white mb-2">Achievements</h1>
|
||||
<p className="text-gray-300 flex items-center gap-2">
|
||||
<Trophy className="w-4 h-4" />
|
||||
Track your progress and accomplishments
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => navigate("/staff/dashboard")}
|
||||
variant="outline"
|
||||
className="border-purple-500/30 hover:bg-purple-500/10"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4 mr-2" />
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<Card className="bg-slate-900/50 border-purple-500/20">
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-gray-400 text-sm">Achievements Unlocked</p>
|
||||
<p className="text-3xl font-bold text-yellow-400">
|
||||
{unlockedCount}/{ACHIEVEMENTS.length}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900/50 border-purple-500/20">
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-gray-400 text-sm">Milestones Completed</p>
|
||||
<p className="text-3xl font-bold text-green-400">
|
||||
{achievedMilestones}/{MILESTONES.length}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900/50 border-purple-500/20">
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-gray-400 text-sm">Total Points</p>
|
||||
<p className="text-3xl font-bold text-blue-400">2,480</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-slate-900/50 border-purple-500/20">
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-gray-400 text-sm">Level</p>
|
||||
<p className="text-3xl font-bold text-purple-400">12</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Achievements */}
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-4">
|
||||
<Trophy className="w-6 h-6 inline mr-2" />
|
||||
Achievements
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{ACHIEVEMENTS.map((achievement) => (
|
||||
<Card
|
||||
key={achievement.id}
|
||||
className="bg-slate-900/50 border-purple-500/20 cursor-pointer hover:border-purple-500/50 transition-all"
|
||||
onClick={() =>
|
||||
setExpandedAchievement(
|
||||
expandedAchievement === achievement.id
|
||||
? null
|
||||
: achievement.id
|
||||
)
|
||||
}
|
||||
>
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-start gap-3 flex-1">
|
||||
<span className="text-3xl">{achievement.icon}</span>
|
||||
<div>
|
||||
<h3 className="text-white font-bold">
|
||||
{achievement.name}
|
||||
</h3>
|
||||
<p className="text-gray-400 text-sm">
|
||||
{achievement.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{achievement.unlocked && (
|
||||
<Badge className="bg-yellow-500/20 text-yellow-300 ml-2">
|
||||
Unlocked
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between text-sm">
|
||||
<span className="text-gray-400">Progress</span>
|
||||
<span className="text-purple-400">
|
||||
{achievement.progress}/{achievement.total}
|
||||
</span>
|
||||
</div>
|
||||
<Progress
|
||||
value={
|
||||
(achievement.progress / achievement.total) * 100
|
||||
}
|
||||
className="h-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Milestones */}
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-4">
|
||||
<Target className="w-6 h-6 inline mr-2" />
|
||||
Milestones
|
||||
</h2>
|
||||
<div className="space-y-3">
|
||||
{MILESTONES.map((milestone) => (
|
||||
<Card
|
||||
key={milestone.id}
|
||||
className={`${
|
||||
milestone.achieved
|
||||
? "bg-green-500/10 border-green-500/20"
|
||||
: "bg-slate-900/50 border-purple-500/20"
|
||||
}`}
|
||||
>
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<h3 className="text-white font-bold">
|
||||
{milestone.title}
|
||||
</h3>
|
||||
{milestone.achieved && (
|
||||
<Badge className="bg-green-500/20 text-green-300">
|
||||
Achieved
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-gray-400 text-sm">
|
||||
{milestone.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-right ml-4">
|
||||
{milestone.achieved ? (
|
||||
<p className="text-green-400 font-semibold">
|
||||
Completed ✓
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-gray-400 text-sm">
|
||||
{milestone.daysLeft} days left
|
||||
</p>
|
||||
<p className="text-gray-500 text-xs">
|
||||
{milestone.date}
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Leaderboard Preview */}
|
||||
<Card className="bg-slate-900/50 border-purple-500/20">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Star className="w-5 h-5 text-yellow-400" />
|
||||
Top Achievers This Month
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
{[
|
||||
{ name: "Sarah Dev", points: 2850, rank: 1 },
|
||||
{ name: "You", points: 2480, rank: 2 },
|
||||
{ name: "Mike Operations", points: 2340, rank: 3 },
|
||||
{ name: "Emma Design", points: 2100, rank: 4 },
|
||||
].map((user) => (
|
||||
<div
|
||||
key={user.rank}
|
||||
className="flex items-center justify-between py-2 border-b border-purple-500/10 last:border-0"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<Badge
|
||||
className={`${
|
||||
user.rank === 1
|
||||
? "bg-yellow-500/20 text-yellow-300"
|
||||
: user.rank === 2
|
||||
? "bg-gray-400/20 text-gray-300"
|
||||
: "bg-orange-500/20 text-orange-300"
|
||||
}`}
|
||||
>
|
||||
#{user.rank}
|
||||
</Badge>
|
||||
<span className="text-white">{user.name}</span>
|
||||
</div>
|
||||
<span className="text-purple-400 font-semibold">
|
||||
{user.points} pts
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue