Skip to content

Commit a2401eb

Browse files
authored
Merge pull request #584 from Adez017/Experiment
Added PR's to the leaderboard
2 parents 7cfe0fb + a5d3961 commit a2401eb

File tree

5 files changed

+869
-20
lines changed

5 files changed

+869
-20
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// src/components/dashboard/LeaderBoard/PRListModal.tsx
2+
import React from "react";
3+
import { motion, AnimatePresence } from "framer-motion";
4+
import { FaTimes, FaExternalLinkAlt, FaGithub } from "react-icons/fa";
5+
import { useColorMode } from "@docusaurus/theme-common";
6+
7+
interface PRDetails {
8+
title: string;
9+
url: string;
10+
mergedAt: string;
11+
repoName: string;
12+
number: number;
13+
}
14+
15+
interface Contributor {
16+
username: string;
17+
avatar: string;
18+
profile: string;
19+
points: number;
20+
prs: number;
21+
prDetails?: PRDetails[];
22+
}
23+
24+
interface PRListModalProps {
25+
contributor: Contributor | null;
26+
isOpen: boolean;
27+
onClose: () => void;
28+
}
29+
30+
export default function PRListModal({ contributor, isOpen, onClose }: PRListModalProps): JSX.Element | null {
31+
const { colorMode } = useColorMode();
32+
const isDark = colorMode === "dark";
33+
34+
if (!contributor) return null;
35+
36+
const formatDate = (dateString: string) => {
37+
const date = new Date(dateString);
38+
return date.toLocaleDateString('en-US', {
39+
year: 'numeric',
40+
month: 'short',
41+
day: 'numeric'
42+
});
43+
};
44+
45+
const handleBackdropClick = (e: React.MouseEvent) => {
46+
if (e.target === e.currentTarget) {
47+
onClose();
48+
}
49+
};
50+
51+
const handleKeyDown = (e: React.KeyboardEvent) => {
52+
if (e.key === 'Escape') {
53+
onClose();
54+
}
55+
};
56+
57+
return (
58+
<AnimatePresence>
59+
{isOpen && (
60+
<motion.div
61+
className={`pr-modal-backdrop ${isDark ? "dark" : "light"}`}
62+
initial={{ opacity: 0 }}
63+
animate={{ opacity: 1 }}
64+
exit={{ opacity: 0 }}
65+
onClick={handleBackdropClick}
66+
onKeyDown={handleKeyDown}
67+
tabIndex={0}
68+
role="dialog"
69+
aria-modal="true"
70+
aria-labelledby="pr-modal-title"
71+
>
72+
<motion.div
73+
className={`pr-modal-container ${isDark ? "dark" : "light"}`}
74+
initial={{ opacity: 0, scale: 0.9, y: 20 }}
75+
animate={{ opacity: 1, scale: 1, y: 0 }}
76+
exit={{ opacity: 0, scale: 0.9, y: 20 }}
77+
transition={{ type: "spring", damping: 25, stiffness: 300 }}
78+
>
79+
{/* Modal Header */}
80+
<div className={`pr-modal-header ${isDark ? "dark" : "light"}`}>
81+
<div className="pr-modal-user-info">
82+
<img
83+
src={contributor.avatar}
84+
alt={contributor.username}
85+
className="pr-modal-avatar"
86+
/>
87+
<div>
88+
<h2 id="pr-modal-title" className={`pr-modal-title ${isDark ? "dark" : "light"}`}>
89+
{contributor.username}'s Pull Requests
90+
</h2>
91+
<p className={`pr-modal-subtitle ${isDark ? "dark" : "light"}`}>
92+
{contributor.prs} merged PR{contributor.prs !== 1 ? 's' : ''}{contributor.points} points
93+
</p>
94+
</div>
95+
</div>
96+
<button
97+
className={`pr-modal-close ${isDark ? "dark" : "light"}`}
98+
onClick={onClose}
99+
aria-label="Close modal"
100+
>
101+
<FaTimes />
102+
</button>
103+
</div>
104+
105+
{/* Modal Body */}
106+
<div className={`pr-modal-body ${isDark ? "dark" : "light"}`}>
107+
{contributor.prDetails && contributor.prDetails.length > 0 ? (
108+
<div className="pr-list">
109+
{contributor.prDetails.map((pr, index) => (
110+
<motion.div
111+
key={`${pr.repoName}-${pr.number}`}
112+
className={`pr-item ${isDark ? "dark" : "light"}`}
113+
initial={{ opacity: 0, x: -20 }}
114+
animate={{ opacity: 1, x: 0 }}
115+
transition={{ delay: index * 0.05 }}
116+
>
117+
<div className="pr-item-header">
118+
<h3 className={`pr-item-title ${isDark ? "dark" : "light"}`}>
119+
{pr.title}
120+
</h3>
121+
<div className="pr-item-actions">
122+
<a
123+
href={pr.url}
124+
target="_blank"
125+
rel="noopener noreferrer"
126+
className={`pr-item-link ${isDark ? "dark" : "light"}`}
127+
aria-label={`Open PR #${pr.number} in GitHub`}
128+
>
129+
<FaExternalLinkAlt />
130+
</a>
131+
</div>
132+
</div>
133+
<div className="pr-item-meta">
134+
<span className={`pr-item-repo ${isDark ? "dark" : "light"}`}>
135+
<FaGithub />
136+
{pr.repoName}
137+
</span>
138+
<span className={`pr-item-number ${isDark ? "dark" : "light"}`}>
139+
#{pr.number}
140+
</span>
141+
<span className={`pr-item-date ${isDark ? "dark" : "light"}`}>
142+
Merged on {formatDate(pr.mergedAt)}
143+
</span>
144+
</div>
145+
</motion.div>
146+
))}
147+
</div>
148+
) : (
149+
<div className={`pr-empty-state ${isDark ? "dark" : "light"}`}>
150+
<FaGithub className="pr-empty-icon" />
151+
<p>No pull request details available</p>
152+
<p className="pr-empty-subtitle">
153+
PR details might not be loaded yet or this contributor has no merged PRs.
154+
</p>
155+
</div>
156+
)}
157+
</div>
158+
159+
{/* Modal Footer */}
160+
<div className={`pr-modal-footer ${isDark ? "dark" : "light"}`}>
161+
<a
162+
href={contributor.profile}
163+
target="_blank"
164+
rel="noopener noreferrer"
165+
className={`pr-modal-profile-link ${isDark ? "dark" : "light"}`}
166+
>
167+
<FaGithub />
168+
View GitHub Profile
169+
</a>
170+
</div>
171+
</motion.div>
172+
</motion.div>
173+
)}
174+
</AnimatePresence>
175+
);
176+
}

0 commit comments

Comments
 (0)