Skip to content

Commit c1bc8e4

Browse files
authored
Merge pull request #68 from Ankita0325/search-bar
fix implement search bar
2 parents 09a01f0 + 10a3341 commit c1bc8e4

9 files changed

Lines changed: 408 additions & 108 deletions

File tree

src/components/dashboard/RankPreview.jsx

Lines changed: 86 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,125 @@
11
import React, { useState, useEffect } from "react";
22
import { Link } from "react-router-dom";
3-
import { Trophy, ChevronRight } from "lucide-react";
4-
import { collection, query, where, onSnapshot } from "firebase/firestore";
5-
import { db } from "../../lib/firebase";
3+
import { ChevronRight, Lock, CheckCircle2 } from "lucide-react";
64
import { useAuth } from "../../context/AuthContext";
5+
import { systemBadges } from "../../constants";
76
import Card from "../ui/Card";
87

98
export const RankPreview = () => {
10-
const { user } = useAuth();
11-
const [topThree, setTopThree] = useState([]);
9+
const { userData } = useAuth();
1210
const [loading, setLoading] = useState(true);
1311

14-
const medalColors = {
15-
1: "bg-amber-500 text-white shadow-[0_0_15px_rgba(245,158,11,0.4)]",
16-
2: "bg-slate-300 text-slate-900 border border-slate-400/30",
17-
3: "bg-orange-600 text-white"
18-
};
12+
// Extract metrics dynamically from the live Firestore user document
13+
const commits = userData?.githubStats?.commits || 0;
14+
const streak = userData?.streak || 0;
15+
const codingVersePoints = userData?.points?.codingVersePoints || 0;
1916

20-
useEffect(() => {
21-
if (!user) {
22-
const timer = setTimeout(() => {
23-
setLoading(false);
24-
}, 0);
25-
return () => clearTimeout(timer);
17+
// Calculate dynamic progress mapping for the 4 badges (same as Achievements.jsx)
18+
const badgeProgress = {
19+
b1: { unlocked: true, progress: 100, current: 1, target: 1 },
20+
b2: {
21+
unlocked: commits >= 100,
22+
progress: Math.min(100, Math.round((commits / 100) * 100)),
23+
current: commits,
24+
target: 100
25+
},
26+
b3: {
27+
unlocked: streak >= 10,
28+
progress: Math.min(100, Math.round((streak / 10) * 100)),
29+
current: streak,
30+
target: 10
31+
},
32+
b4: {
33+
unlocked: codingVersePoints >= 100,
34+
progress: Math.min(100, Math.round((codingVersePoints / 100) * 100)),
35+
current: codingVersePoints,
36+
target: 100
2637
}
38+
};
2739

28-
const q = query(
29-
collection(db, "users"),
30-
where("onboardingStatus", "==", "complete")
31-
);
32-
33-
const unsubscribe = onSnapshot(
34-
q,
35-
(snapshot) => {
36-
const users = [];
37-
snapshot.forEach((doc) => {
38-
users.push(doc.data());
39-
});
40-
41-
// Sort by totalPoints descending
42-
users.sort((a, b) => (b.points?.totalPoints || 0) - (a.points?.totalPoints || 0));
43-
44-
// Slice top 3
45-
const top3 = users.slice(0, 3).map((u, i) => ({
46-
...u,
47-
rank: i + 1
48-
}));
49-
50-
setTopThree(top3);
51-
setLoading(false);
52-
},
53-
(error) => {
54-
console.error("RankPreview query failed:", error);
55-
setLoading(false);
56-
}
57-
);
40+
useEffect(() => {
41+
// Simulate loading delay for consistency
42+
const timer = setTimeout(() => {
43+
setLoading(false);
44+
}, 300);
45+
return () => clearTimeout(timer);
46+
}, [userData]);
5847

59-
return () => unsubscribe();
60-
}, [user]);
48+
const unlockedCount = Object.values(badgeProgress).filter((b) => b.unlocked).length;
6149

6250
return (
6351
<Card className="flex flex-col h-full">
6452
{/* Header */}
6553
<div className="flex items-center justify-between pb-4 border-b border-slate-100 dark:border-slate-800">
6654
<div>
67-
<h3 className="font-extrabold text-lg text-slate-900 dark:text-white my-0">Leaderboard Preview</h3>
68-
<p className="text-xs text-slate-400 dark:text-slate-500">Top performers this week</p>
55+
<h3 className="font-extrabold text-lg text-slate-900 dark:text-white my-0">Achievement Preview</h3>
56+
<p className="text-xs text-slate-400 dark:text-slate-500">{unlockedCount} of 4 badges unlocked</p>
6957
</div>
7058
<Link
71-
to="/gitrank"
59+
to="/dashboard/achievements"
7260
className="text-xs font-bold text-violet-600 dark:text-violet-400 hover:underline flex items-center gap-1 group cursor-pointer"
7361
>
7462
View all <ChevronRight className="w-3.5 h-3.5 group-hover:translate-x-0.5 transition-transform" />
7563
</Link>
7664
</div>
7765

78-
{/* Ranks Cards List */}
79-
<div className="flex-1 mt-6 space-y-4">
66+
{/* Achievements List */}
67+
<div className="flex-1 mt-6 space-y-3">
8068
{loading ? (
8169
<div className="h-full flex items-center justify-center py-10">
8270
<div className="w-5 h-5 border-2 border-violet-500 border-t-transparent rounded-full animate-spin" />
8371
</div>
84-
) : topThree.length > 0 ? (
85-
topThree.map((user) => (
86-
<div
87-
key={user.uid}
88-
className="flex items-center justify-between p-3 rounded-xl border border-slate-200/40 dark:border-slate-800/40 bg-slate-50/50 dark:bg-slate-950/30 hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors"
89-
>
90-
<div className="flex items-center gap-3">
91-
{/* Rank Medal */}
92-
<div className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold ${medalColors[user.rank] || "bg-slate-200"}`}>
93-
{user.rank === 1 ? <Trophy className="w-3.5 h-3.5" /> : user.rank}
94-
</div>
72+
) : systemBadges.length > 0 ? (
73+
systemBadges.map((badge) => {
74+
const info = badgeProgress[badge.id] || { unlocked: false, progress: 0 };
9575

96-
{/* User Info */}
97-
<div className="w-9 h-9 rounded-lg overflow-hidden flex-shrink-0">
98-
<img src={user.avatar} alt={user.name} className="w-full h-full object-cover" />
99-
</div>
76+
return (
77+
<div
78+
key={badge.id}
79+
className="flex items-center justify-between p-3 rounded-xl border border-slate-200/40 dark:border-slate-800/40 bg-slate-50/50 dark:bg-slate-950/30 hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors"
80+
>
81+
<div className="flex items-center gap-3 flex-1 min-w-0">
82+
{/* Badge Icon */}
83+
<div
84+
className={`w-10 h-10 rounded-lg bg-gradient-to-br ${badge.color} flex items-center justify-center text-xs font-bold text-white flex-shrink-0 ${
85+
!info.unlocked ? "brightness-75 saturate-50" : ""
86+
}`}
87+
>
88+
{badge.name[0]}
89+
</div>
10090

101-
<div>
102-
<span className="text-sm font-extrabold text-slate-900 dark:text-slate-200 block leading-tight">
103-
{user.name}
104-
</span>
105-
<span className="text-[10px] font-semibold text-slate-400 dark:text-slate-500 block">
106-
@{user.githubUsername}{user.githubStats?.primaryLanguage || "JavaScript"}
107-
</span>
91+
{/* Badge Info */}
92+
<div className="flex-1 min-w-0">
93+
<span className="text-sm font-extrabold text-slate-900 dark:text-slate-200 block leading-tight">
94+
{badge.name}
95+
</span>
96+
<div className="flex items-center justify-between mt-1">
97+
<span className="text-[10px] font-semibold text-slate-400 dark:text-slate-500 truncate">
98+
{info.current} / {info.target}
99+
</span>
100+
<div className="w-16 h-1 bg-slate-200 dark:bg-slate-700 rounded-full overflow-hidden">
101+
<div
102+
className="h-full bg-gradient-to-r from-violet-500 to-indigo-500 rounded-full transition-all duration-500"
103+
style={{ width: `${info.progress}%` }}
104+
/>
105+
</div>
106+
</div>
107+
</div>
108108
</div>
109-
</div>
110109

111-
{/* Points / Streak */}
112-
<div className="text-right">
113-
<span className="block text-sm font-extrabold text-slate-900 dark:text-white leading-tight">
114-
{user.points?.totalPoints?.toLocaleString() || 0}
115-
</span>
116-
<span className="inline-flex items-center gap-0.5 text-[10px] font-bold text-orange-500 dark:text-orange-400">
117-
🔥 {user.streak ?? 0}d streak
118-
</span>
110+
{/* Lock / Unlock Status */}
111+
<div className="flex-shrink-0 ml-2">
112+
{info.unlocked ? (
113+
<CheckCircle2 className="w-5 h-5 text-emerald-500" />
114+
) : (
115+
<Lock className="w-5 h-5 text-slate-400 dark:text-slate-600" />
116+
)}
117+
</div>
119118
</div>
120-
</div>
121-
))
119+
);
120+
})
122121
) : (
123-
<p className="text-xs text-center text-slate-400 py-10">No ranked users yet</p>
122+
<p className="text-xs text-center text-slate-400 py-10">No achievements yet</p>
124123
)}
125124
</div>
126125
</Card>

0 commit comments

Comments
 (0)