Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 36 additions & 26 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
// /** @type {import('next').NextConfig} */
// const nextConfig = {
// images: {
// unoptimized: true,
// },
// output: "export",
// // distDir: "build" // Optional: Change the output directory `out` -> `build`
// };

// module.exports = nextConfig;

const { PHASE_PRODUCTION_BUILD } = require("next/constants");

module.exports = (phase, { defaultConfig }) => {
if (phase === PHASE_PRODUCTION_BUILD) {
return {
images: {
unoptimized: true,
},
output: "export",
distDir: "build"
};
}

return {};
};
// /** @type {import('next').NextConfig} */
// const nextConfig = {
// images: {
// unoptimized: true,
// },
// output: "export",
// // distDir: "build" // Optional: Change the output directory `out` -> `build`
// };

// module.exports = nextConfig;

const { PHASE_PRODUCTION_BUILD } = require("next/constants");

module.exports = (phase, { defaultConfig }) => {
const images = {
unoptimized: true,
remotePatterns: [
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com',
},
],
};

if (phase === PHASE_PRODUCTION_BUILD) {
return {
images,
output: "export",
distDir: "build"
};
}

return {
images,
};
};
72 changes: 72 additions & 0 deletions src/app/contributors/components/TopContributors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";

import React from "react";
import Image from "next/image";
import Link from "next/link";

interface Contributor {
login: string;
avatar_url: string;
html_url: string;
contributions: number;
lastActiveDays: number | null;
}

interface TopContributorsProps {
contributors: Contributor[];
}

const TopContributors = ({ contributors }: TopContributorsProps) => {
const getLastActiveText = (days: number | null): string => {
if (days === null) return "No recent activity";
if (days === 0) return "Active today";
if (days === 1) return "Active yesterday";
return `Active ${days} days ago`;
};

return (
<div className='relative items-center max-w-5xl mx-auto px-4 py-8'>
{/* Contributors scroll container */}
<div className='flex gap-6 overflow-x-auto scrollbar-hide snap-x snap-mandatory scroll-px-6 px-8'>
{contributors.slice(0, 6).map((contributor) => (
<Link
key={contributor.login}
href={contributor.html_url}
target='_blank'
className='flex-shrink-0 snap-center group'
>
<div className='flex flex-col items-center gap-2'>
{/* Avatar with gradient border */}
<div className='p-1 rounded-full bg-gradient-to-tr from-mindfire-text-red via-orange-500 to-yellow-500'>
<div className='p-0.5 rounded-full bg-white'>
<div className='relative w-20 h-20 rounded-full overflow-hidden group-hover:scale-105 transition-transform'>
<Image
src={contributor.avatar_url}
alt={contributor.login}
fill
className='object-cover'
/>
</div>
</div>
</div>
{/* Username and contributions */}
<div className='text-center'>
<p className='font-medium text-sm text-gray-800 truncate max-w-[100px]'>
{contributor.login}
</p>
<p className='text-xs text-gray-500'>
{contributor.contributions} contributions
</p>
<p className='text-xs text-gray-400'>
{getLastActiveText(contributor.lastActiveDays)}
</p>
</div>
</div>
</Link>
))}
</div>
</div>
);
};

export default TopContributors;
242 changes: 142 additions & 100 deletions src/app/contributors/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,32 @@ import issueImg from "../../../public/images/social-media/git-issue.svg";
import Image from "next/image";
import contributorList from "../projects/assets/contributors.json";
import ContributorCount from "./components/ContributorCount";
import TopContributors from "./components/TopContributors";

interface Contributor {
id: number;
contributions: number;
html_url: string;
avatar_url: string;
login: string;
lastActiveDays: number | null;
}

const Contributors = () => {
const contributorsArray = Object.values(contributorList);
const contributorsArray = Object.values(contributorList) as Contributor[];

// Filter and sort contributors for top section (active in last 30 days)
const activeTopContributors = [...contributorsArray]
.filter(
(contributor) =>
contributor.lastActiveDays === null || contributor.lastActiveDays <= 30
)
.sort((a, b) => b.contributions - a.contributions);

// Sort all contributors by contributions for the main grid
const sortedAllContributors = [...contributorsArray].sort(
(a, b) => b.contributions - a.contributions
);

return (
<>
Expand All @@ -21,110 +44,129 @@ const Contributors = () => {
</h1>
<ContributorCount totalContributors={contributorsArray.length} />
</div>
<p className='mt-6 text-xl text-mf-light-grey tracking-wide mb-10'>
We’re a dynamic group of individuals who are passionate about what
we do.
</p>
{contributorsArray ? (
<div className='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4'>
{contributorsArray.map((contributor) => (
<div
key={contributor.id}
className='bg-white border border-gray-200 rounded-lg shadow-lg transition-transform duration-300 transform hover:scale-105'
>
<div className='p-4'>
<img
className='w-24 h-24 mb-3 rounded-full shadow-lg mx-auto transition-transform duration-300 transform hover:scale-105'
src={contributor.avatar_url}
alt={`Contributor ${contributor.login}`}
/>
<div className='flex justify-center items-center gap-2 mt-4 '>
<Link href={contributor.html_url!} target='_blank'>
<Image
src={github}
height={20}
width={20}
alt='github_img'
loading='lazy'
quality={75}
/>
</Link>
<Link href={contributor.html_url!} target='_blank'>
<h5 className='text-xl font-medium text-gray-900 text-center'>
{contributor.login}
</h5>
</Link>
</div>
<footer>
<div className='grid grid-cols-3 divide-x'>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={contributorImg}
height={20}
width={20}
alt='contributor'
loading='lazy'
quality={75}
title='Contributions'
/>

{/* Top Contributors Section */}
<div className='mt-12 flex flex-col items-center justify-center'>
<h2 className='text-2xl font-medium text-gray-800 mb-6'>
Top Active Contributors
</h2>
<p className='text-xl text-mf-light-grey tracking-wide mb-2'>
Meet our top six contributors — the people who help turn ideas
into impact.
</p>
<TopContributors contributors={activeTopContributors} />
</div>

{/* All Contributors Section */}
<div className='mt-12 flex flex-col items-center justify-center'>
<h2 className='text-2xl font-medium text-gray-800 mb-6'>
All Contributors
</h2>
<p className='text-xl text-mf-light-grey tracking-wide mb-10'>
We&apos;re a dynamic group of individuals who are passionate about
what we do.
</p>
{contributorsArray ? (
<div className='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4'>
{sortedAllContributors.map((contributor) => (
<div
key={contributor.id}
className='bg-white border border-gray-200 rounded-lg shadow-lg transition-transform duration-300 transform hover:scale-105'
>
<div className='p-4'>
<img
className='w-24 h-24 mb-3 rounded-full shadow-lg mx-auto transition-transform duration-300 transform hover:scale-105'
src={contributor.avatar_url}
alt={`Contributor ${contributor.login}`}
/>
<div className='flex justify-center items-center gap-2 mt-4 '>
<Link href={contributor.html_url!} target='_blank'>
<Image
src={github}
height={20}
width={20}
alt='github_img'
loading='lazy'
quality={75}
/>
</Link>
<Link href={contributor.html_url!} target='_blank'>
<h5 className='text-xl font-medium text-gray-900 text-center'>
{contributor.login}
</h5>
</Link>
</div>
<footer>
<div className='grid grid-cols-3 divide-x'>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={contributorImg}
height={20}
width={20}
alt='contributor'
loading='lazy'
quality={75}
title='Contributions'
/>
</div>
<p className='text-sm text-gray-500 text-center'>
{contributor.contributions}
</p>
</div>
<p className='text-sm text-gray-500 text-center'>
{contributor.contributions}
</p>
</div>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={prImg}
height={20}
width={20}
alt='pull request'
loading='lazy'
quality={75}
title='Pull Requests'
/>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={prImg}
height={20}
width={20}
alt='pull request'
loading='lazy'
quality={75}
title='Pull Requests'
/>
</div>
<p className='text-sm text-gray-500 text-center'>
{Math.floor(contributor.contributions / 2)}
</p>
</div>
<p className='text-sm text-gray-500 text-center'>
{Math.floor(contributor.contributions / 2)}
</p>
</div>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={issueImg}
height={20}
width={20}
alt='issue'
loading='lazy'
quality={75}
title='Issues'
/>
<div className='flex justify-center items-center gap-1 mt-4 '>
<div>
<Image
src={issueImg}
height={20}
width={20}
alt='issue'
loading='lazy'
quality={75}
title='Issues'
/>
</div>
<p className='text-sm text-gray-500 text-center'>
{Math.floor(contributor.contributions / 4)}
</p>
</div>
<p className='text-sm text-gray-500 text-center'>
{Math.floor(contributor.contributions / 4)}
</p>
</div>
</div>
</footer>
</footer>
</div>
</div>
</div>
))}
</div>
) : (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "50vh",
}}
>
<p className='mt-6 text-xl text-mf-light-grey tracking-wide mb-10'>
No records found!
</p>
</div>
)}
))}
</div>
) : (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "50vh",
}}
>
<p className='mt-6 text-xl text-mf-light-grey tracking-wide mb-10'>
No records found!
</p>
</div>
)}
</div>
</div>
</section>
</>
Expand Down
Loading