Skip to content
Open
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
63 changes: 35 additions & 28 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Footer from "./components/Footer";
import ScrollProgressBar from "./components/ScrollProgressBar";
import { Toaster } from "react-hot-toast";
import Router from "./Routes/Router";
import ScrollToTopButton from "./components/ScrollToTopButton";

const FULLSCREEN_ROUTES = ["/signup", "/login"];

Expand All @@ -12,35 +13,41 @@ function App() {
const isFullscreen = FULLSCREEN_ROUTES.includes(location.pathname);

return (
<div className="relative flex flex-col min-h-screen">
{!isFullscreen && <ScrollProgressBar />}

{!isFullscreen && <Navbar />}

<main className={`flex justify-center items-center ${isFullscreen ? "flex-1" : "flex-grow bg-gray-50 dark:bg-gray-800"}`}>
<Router />
</main>

{!isFullscreen && <Footer />}

<Toaster
position="top-center"
reverseOrder={false}
gutter={8}
containerClassName="mt-12"
toastOptions={{
className: "bg-white dark:bg-gray-800 text-black dark:text-white",
duration: 5000,
success: {
duration: 3000,
iconTheme: {
primary: "green",
secondary: "white",
},
<div className="relative flex flex-col min-h-screen">
{!isFullscreen && <ScrollProgressBar />}

{!isFullscreen && <Navbar />}

<main
className={`flex justify-center ${
isFullscreen
? "items-center flex-1"
: "flex-grow bg-gray-50 dark:bg-gray-800"
}`}
>
<Router />
</main>

{!isFullscreen && <Footer />}
{!isFullscreen && <ScrollToTopButton />}
<Toaster
position="top-center"
reverseOrder={false}
gutter={8}
containerClassName="mt-12"
toastOptions={{
className: "bg-white dark:bg-gray-800 text-black dark:text-white",
duration: 5000,
success: {
duration: 3000,
iconTheme: {
primary: "green",
secondary: "white",
},
}}
/>
</div>
},
}}
/>
</div>
);
}

Expand Down
55 changes: 55 additions & 0 deletions src/components/ScrollToTopButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useEffect, useState } from "react";
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";

const ScrollToTopButton = () => {
const [visible, setVisible] = useState(false);

useEffect(() => {
const toggleVisibility = () => {
if (window.scrollY > 10) {
setVisible(true);
} else {
setVisible(false);
}
};

window.addEventListener("scroll", toggleVisibility);

return () => {
window.removeEventListener("scroll", toggleVisibility);
};
}, []);

const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};

return (
visible && (
<button
onClick={scrollToTop}
className="
fixed
bottom-6
right-6
z-50
bg-blue-600
hover:bg-blue-700
text-white
p-3
rounded-full
shadow-lg
transition-all
duration-300
"
>
<KeyboardArrowUpIcon />
</button>
)
);
};

export default ScrollToTopButton;
183 changes: 126 additions & 57 deletions src/pages/Contributors/Contributors.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useEffect, useState } from "react";
import { TextField, InputAdornment } from "@mui/material";
import { FaSearch } from "react-icons/fa";
import {
Container,
Grid,
Expand Down Expand Up @@ -28,6 +30,7 @@ const ContributorsPage = () => {
const [contributors, setContributors] = useState<Contributor[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const [searchTerm, setSearchTerm] = useState<string>("");

// Fetch contributors from GitHub API
useEffect(() => {
Expand All @@ -47,6 +50,10 @@ const ContributorsPage = () => {
fetchContributors();
}, []);

const filteredContributors = contributors.filter((contributor) =>
contributor.login.toLowerCase().includes(searchTerm.toLowerCase()),
);

if (loading) {
return (
<Box sx={{ display: "flex", justifyContent: "center", mt: 4 }}>
Expand All @@ -65,74 +72,136 @@ const ContributorsPage = () => {

return (
<div className="bg-white dark:bg-gray-900 text-black dark:text-white min-h-screen p-4 mt-4">
<Container>
<Container maxWidth="lg">
<Typography sx={{ pb: 2 }} variant="h4" align="center" gutterBottom>
🤝 Contributors
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "center",
mb: 4,
width: "100%",
}}
>
<TextField
placeholder="Search contributors..."
variant="outlined"
autoFocus
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
sx={{
width: {
xs: "100%",
sm: "400px",
},
maxWidth: "100%",
backgroundColor: "white",
borderRadius: "10px",
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<FaSearch />
</InputAdornment>
),
}}
/>
</Box>

<Grid container spacing={4}>
{contributors.map((contributor) => (
<Grid item xs={12} sm={6} md={3} key={contributor.id}>
<Card
sx={{
textAlign: "center",
p: 2,
borderRadius: "10px",
border: "1px solid #E0E0E0",
boxShadow: "0 4px 10px rgba(0,0,0,0.1)",
transition: "transform 0.3s ease-in-out",
"&:hover": {
transform: "scale(1.05)",
boxShadow: "0 8px 15px rgba(0,0,0,0.2)",
borderColor: "#C0C0C0",
outlineColor: "#B3B3B3",
},
}}
<Grid container spacing={4} justifyContent="center">
{filteredContributors.length === 0 && (
<Typography
variant="h6"
align="center"
sx={{
mt: 4,
color: "gray",
fontWeight: 500,
}}
>
No contributors found.
</Typography>
)}
{filteredContributors.map((contributor) => (
<Grid
item
xs={12}
sm={6}
md={
filteredContributors.length === 1
? 12
: filteredContributors.length === 2
? 6
: filteredContributors.length === 3
? 4
: 3
}
key={contributor.id}
>
<Card
sx={{
textAlign: "center",
p: 2,
maxWidth: "300px",
mx: "auto",
borderRadius: "10px",
border: "1px solid #E0E0E0",
boxShadow: "0 4px 10px rgba(0,0,0,0.1)",
transition: "transform 0.3s ease-in-out",
"&:hover": {
transform: "scale(1.05)",
boxShadow: "0 8px 15px rgba(0,0,0,0.2)",
borderColor: "#C0C0C0",
outlineColor: "#B3B3B3",
},
}}
>
<Link
to={`/contributor/${contributor.login}`}
style={{ textDecoration: "none" }}
>
<Link
to={`/contributor/${contributor.login}`}
style={{ textDecoration: "none" }}
>
<Avatar
src={contributor.avatar_url}
alt={contributor.login}
sx={{ width: 100, height: 100, mx: "auto", mb: 2 }}
/>
<CardContent>
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
{contributor.login}
</Typography>
<Avatar
src={contributor.avatar_url}
alt={contributor.login}
sx={{ width: 100, height: 100, mx: "auto", mb: 2 }}
/>
<CardContent>
<Typography variant="h6" sx={{ fontWeight: "bold" }}>
{contributor.login}
</Typography>

<Typography variant="body2" color="text.secondary">
{contributor.contributions} Contributions
</Typography>
{/*
<Typography variant="body2" color="text.secondary">
{contributor.contributions} Contributions
</Typography>
{/*
<Typography variant="body2" sx={{ mt: 2 }}>
Thank you for your valuable contributions to our
community!
</Typography> */}
</CardContent>
</Link>
</CardContent>
</Link>

<Box sx={{ mt: 2 }}>
<Button
variant="contained"
startIcon={<FaGithub />}
href={contributor.html_url}
target="_blank"
sx={{
backgroundColor: "#333333",
textTransform: "none",
color: "#FFFFFF",
"&:hover": {
backgroundColor: "#555555",
},
}}
>
GitHub
</Button>
</Box>
</Card>
<Box sx={{ mt: 2 }}>
<Button
variant="contained"
startIcon={<FaGithub />}
href={contributor.html_url}
target="_blank"
rel="noopener noreferrer"
sx={{
backgroundColor: "#333333",
textTransform: "none",
color: "#FFFFFF",
"&:hover": {
backgroundColor: "#555555",
},
}}
>
GitHub
</Button>
</Box>
</Card>
</Grid>
))}
</Grid>
Expand Down
Loading
Loading