Skip to content

Commit

Permalink
Merge pull request #346 from Sawan-Kushwah/feat/openIssueSection
Browse files Browse the repository at this point in the history
Added open issue section in our contributor page
  • Loading branch information
GUNJESH843 authored Nov 4, 2024
2 parents 78a0de5 + 704c7ad commit d8adb5e
Showing 1 changed file with 178 additions and 37 deletions.
215 changes: 178 additions & 37 deletions client/src/component/Contributors.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,111 @@ ContributorCard.propTypes = {
type: PropTypes.string.isRequired,
};

const StatCard = ({ label, value, icon, mode }) => (

const IssueCard = ({
title,
number,
html_url,
user,
state,
mode,
}) => (
<motion.div
whileHover={{ y: -5 }}
transition={{ type: 'spring', stiffness: 300 }}
className={`rounded-lg overflow-hidden border transition-all duration-300 ${mode === 'dark'
? 'bg-black/30 backdrop-blur-md border-white/10'
: 'bg-white backdrop-blur-sm border-gray-300'
}`}
style={{ minHeight: '350px' }} // Set a minimum height
data-aos="fade-up"
data-aos-duration='1500'
>
<div className='flex flex-col justify-between pt-6' style={{ height: '100%' }}>
<div className='text-center flex-grow'>
<img
src={user.avatar_url}
alt={user.login}
className={`w-24 h-24 rounded-full mx-auto mb-4 border-4 ${mode === 'dark' ? 'border-primary' : 'border-blue-500'
}`}
/>
<h3 className={`font-bold text-xl px-3 ${mode === 'dark' ? 'text-white' : 'text-gray-800'}`} style={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
{title}
</h3>
<p className={`text-sm ${mode === 'dark' ? 'text-primary' : 'text-gray-600'} mb-2`}>
Status: {state}
</p>
<div className={`mt-4 rounded-full py-2 px-4 inline-block ${mode === 'dark' ? 'bg-white/10' : 'bg-blue-100'
}`}>
<span className={`font-semibold ${mode === 'dark' ? 'text-primary' : 'text-blue-600'
}`}>
Issue : #{number}
</span>
</div>
</div>
<div className={`flex justify-between items-center p-2 ${mode === 'dark' ? 'bg-white/5' : 'bg-blue-200'
}`} style={{ padding: '0', margin: '0' }}>
<a
href={html_url}
target='_blank'
rel='noopener noreferrer'
className={`text-primary hover:text-primary/80 transition-colors flex items-center ${mode === 'dark' ? 'text-white' : 'text-blue-800'
}`}
style={{ flexGrow: 1, padding: '8px 0' }} // Remove padding left and right
>
<svg
xmlns='http://www.w3.org/2000/svg'
className='h-5 w-5 mr-2'
viewBox='0 0 20 20'
fill='currentColor'
>
<path d='M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z' />
<path d='M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z' />
</svg>
View Issue
</a>
<svg
xmlns='http://www.w3.org/2000/svg'
width='24'
height='24'
viewBox='0 0 24 24'
fill='none'
stroke='currentColor'
strokeWidth='2'
strokeLinecap='round'
strokeLinejoin='round'
className='text-white/50'
>
<path d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22'></path>
</svg>
</div>
</div>
</motion.div>
);

IssueCard.propTypes = {
title: PropTypes.string.isRequired,
number: PropTypes.number.isRequired,
html_url: PropTypes.string.isRequired, // Add validation for html_url
user: PropTypes.shape({
login: PropTypes.string.isRequired,
avatar_url: PropTypes.string.isRequired,
}).isRequired,
state: PropTypes.string.isRequired,
mode: PropTypes.string.isRequired,
};

const StatCard = ({ label, value, icon, mode, onClick }) => (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className={`rounded-lg p-6 flex items-center border transition-all duration-300 ${
mode === "dark"
? "bg-black/30 backdrop-blur-md border-white/10"
: "bg-white backdrop-blur-sm border-gray-300"
}`}
className={`rounded-lg p-6 flex items-center border transition-all duration-300 cup ${mode === 'dark'
? 'bg-black/30 backdrop-blur-md border-white/10'
: 'bg-white backdrop-blur-sm border-gray-300'
}`}
onClick={onClick}

>
<div
className={`rounded-full p-3 mr-4 ${
Expand Down Expand Up @@ -135,38 +230,51 @@ StatCard.propTypes = {
mode: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
icon: PropTypes.node.isRequired,
onClick: PropTypes.func,
};

export default function Contributor(props) {
const [contributors, setContributors] = useState([]);
const [openIssues, setOpenIssues] = useState([]);
const [showIssue, setShowIssue] = useState(true); // Determine which section to show
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 9; // Set the number of items per page (for both contributors and issues)

const [repoStats, setRepoStats] = useState({
stars: 0,
forks: 0,
openIssues: 0,
});
const [loading, setLoading] = useState(true);


useEffect(() => {
const fetchData = async () => {
try {
const contributorsResponse = await fetch(
"https://api.github.com/repos/Bitbox-Connect/Bitbox/contributors?page=1&per_page=100"
);
// Fetch contributors
const contributorsResponse = await fetch("https://api.github.com/repos/Bitbox-Connect/Bitbox/contributors?page=1&per_page=100");

if (!contributorsResponse.ok) {
throw new Error("Failed to fetch contributors data");
}
const contributorsData = await contributorsResponse.json();
setContributors(contributorsData);

const repoResponse = await fetch(
"https://api.github.com/repos/Bitbox-Connect/Bitbox"
);

// Fetch repo stats
const repoResponse = await fetch('https://api.github.com/repos/Bitbox-Connect/Bitbox');

const repoData = await repoResponse.json();
setRepoStats({
stars: repoData.stargazers_count,
forks: repoData.forks_count,
openIssues: repoData.open_issues_count,
});

// Fetch issues
const issueResponse = await fetch('https://api.github.com/repos/Bitbox-Connect/Bitbox/issues');
const issueData = await issueResponse.json();
setOpenIssues(issueData);
} catch (error) {
console.error("Error fetching data:", error);
} finally {
Expand All @@ -177,6 +285,19 @@ export default function Contributor(props) {
fetchData();
}, []);

// Calculate pagination indices
const indexOfLastItem = currentPage * itemsPerPage;
const indexOfFirstItem = indexOfLastItem - itemsPerPage;

// Get current items based on selected section
const currentItems = showIssue ? openIssues.slice(indexOfFirstItem, indexOfLastItem) : contributors.slice(indexOfFirstItem, indexOfLastItem);

// Determine total pages
const totalPages = showIssue ? Math.ceil(openIssues.length / itemsPerPage) : Math.ceil(contributors.length / itemsPerPage);

const paginate = (pageNumber) => setCurrentPage(pageNumber);


return (
<div
className={`min-h-screen ${
Expand Down Expand Up @@ -257,6 +378,10 @@ export default function Contributor(props) {
/>
</svg>
}
onClick={() => {
setShowIssue(false);
setCurrentPage(1); // Reset pagination when switching to contributors
}}
/>
<StatCard
mode={props.mode}
Expand Down Expand Up @@ -306,40 +431,56 @@ export default function Contributor(props) {
<path d="M5.05 3.05A7 7 0 1018 10a7.002 7.002 0 00-12.95 0A5.001 5.001 0 115 3.05zm0 2A3.001 3.001 0 105 10a3.001 3.001 0 000-4.95z" />
</svg>
}
onClick={() => {
setShowIssue(true);
setCurrentPage(1); // Reset pagination when switching to contributors
}}
/>
</div>
</div>
</section>

<section className="container mx-auto px-4 py-8">
<h2
className={`text-3xl font-bold text-center ${
props.mode === "dark" ? "text-white" : "text-black"
}`}
>
Meet Our Contributors
</h2>
{loading ? (
<p className="text-center mt-8">
{props.mode === "dark" ? "Loading..." : "Loading..."}
</p>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-8 mt-8">
{contributors.map((contributor, index) => (
<section className="py-16 px-4 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
<h2 className="text-3xl font-bold text-center mb-12">{showIssue ? 'Your contribution is valuable see all Issues' : 'Contributors'}</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
{currentItems.map(item => showIssue ? (
<IssueCard
key={item.id}
title={item.title}
number={item.number}
html_url={item.html_url}
user={item.user}
state={item.state}
mode={props.mode}
/>
) : (
<ContributorCard
key={index}
key={item.id}
login={item.login}
avatar_url={item.avatar_url}
html_url={item.html_url}
contributions={item.contributions}
type={item.type}
mode={props.mode}
login={contributor.login}
avatar_url={contributor.avatar_url}
html_url={contributor.html_url}
contributions={contributor.contributions}
type={contributor.type}
className="p-2 text-sm"
/>
))}
</div>
)}
<div className="flex justify-center mt-8">
{Array.from({ length: totalPages }, (_, i) => (
<button
key={i}
onClick={() => paginate(i + 1)}
className={`px-4 py-2 mx-1 rounded text-black ${i + 1 === currentPage ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-900'}`}
>
{i + 1}
</button>
))}
</div>
</div>
</section>
</div>
</div >


);
}

0 comments on commit d8adb5e

Please sign in to comment.