diff --git a/src/App.tsx b/src/App.tsx index ccc6c670..d6ab9121 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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"]; @@ -12,35 +13,41 @@ function App() { const isFullscreen = FULLSCREEN_ROUTES.includes(location.pathname); return ( -
- {!isFullscreen && } - - {!isFullscreen && } - -
- -
- - {!isFullscreen &&
+ }, + }} + /> + ); } diff --git a/src/components/ScrollToTopButton.tsx b/src/components/ScrollToTopButton.tsx new file mode 100644 index 00000000..9d877da6 --- /dev/null +++ b/src/components/ScrollToTopButton.tsx @@ -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 && ( + + ) + ); +}; + +export default ScrollToTopButton; diff --git a/src/pages/Contributors/Contributors.tsx b/src/pages/Contributors/Contributors.tsx index d4fee52c..56816ad1 100644 --- a/src/pages/Contributors/Contributors.tsx +++ b/src/pages/Contributors/Contributors.tsx @@ -1,4 +1,6 @@ import { useEffect, useState } from "react"; +import { TextField, InputAdornment } from "@mui/material"; +import { FaSearch } from "react-icons/fa"; import { Container, Grid, @@ -28,6 +30,7 @@ const ContributorsPage = () => { const [contributors, setContributors] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const [searchTerm, setSearchTerm] = useState(""); // Fetch contributors from GitHub API useEffect(() => { @@ -47,6 +50,10 @@ const ContributorsPage = () => { fetchContributors(); }, []); + const filteredContributors = contributors.filter((contributor) => + contributor.login.toLowerCase().includes(searchTerm.toLowerCase()), + ); + if (loading) { return ( @@ -65,74 +72,136 @@ const ContributorsPage = () => { return (
- + 🤝 Contributors + + setSearchTerm(e.target.value)} + sx={{ + width: { + xs: "100%", + sm: "400px", + }, + maxWidth: "100%", + backgroundColor: "white", + borderRadius: "10px", + }} + InputProps={{ + startAdornment: ( + + + + ), + }} + /> + - - {contributors.map((contributor) => ( - - + {filteredContributors.length === 0 && ( + + No contributors found. + + )} + {filteredContributors.map((contributor) => ( + + + - - - - - {contributor.login} - + + + + {contributor.login} + - - {contributor.contributions} Contributions - - {/* + + {contributor.contributions} Contributions + + {/* Thank you for your valuable contributions to our community! */} - - + + - - - - + + + + ))} diff --git a/src/pages/Tracker/Tracker.tsx b/src/pages/Tracker/Tracker.tsx index b03eb5a4..2ee04866 100644 --- a/src/pages/Tracker/Tracker.tsx +++ b/src/pages/Tracker/Tracker.tsx @@ -6,7 +6,6 @@ import { GitPullRequestClosedIcon, GitMergeIcon, } from "@primer/octicons-react"; - import { Container, Box, @@ -161,37 +160,58 @@ const Home: React.FC = () => { const formatDate = (dateString: string): string => new Date(dateString).toLocaleDateString(); + const filterData = (data: GitHubItem[], filterType: string): GitHubItem[] => { + let filtered = [...data]; + if (["open", "closed", "merged"].includes(filterType)) { + filtered = filtered.filter((item) => { + if (filterType === "merged") { + return !!item.pull_request?.merged_at; + } else if (filterType === "closed") { + return item.state === "closed" && !item.pull_request?.merged_at; + } else { + //open + return item.state === "open"; + } + }); + } + if (searchTitle) { + filtered = filtered.filter((item) => + item.title.toLowerCase().includes(searchTitle.toLowerCase()), + ); + } + if (selectedRepo) { + filtered = filtered.filter((item) => + item.repository_url.includes(selectedRepo), + ); + } + if (startDate) { + filtered = filtered.filter( + (item) => new Date(item.created_at) >= new Date(startDate), + ); + } + if (endDate) { + filtered = filtered.filter( + (item) => new Date(item.created_at) <= new Date(endDate), + ); + } + return filtered; + }; + const getStatusIcon = (item: GitHubItem) => { if (item.pull_request) { - if (item.pull_request.merged_at) { + if (item.pull_request.merged_at) return ; - } - if (item.state === "closed") { + if (item.state === "closed") return ( - + ); - } - return ( - - ); + return ; } - if (item.state === "closed") { - return ( - - ); - } + if (item.state === "closed") + return ; return ( { ); }; - const currentData = tab === 0 ? issues : prs; + // Current data and filtered data according to tab and filters + const currentRawData = tab === 0 ? issues : prs; + const currentFilteredData = filterData( + currentRawData, + tab === 0 ? issueFilter : prFilter, + ); const totalCount = tab === 0 ? totalIssues : totalPrs; return ( - {/* Auth Inputs */} + {/* Auth Form */} - - setUsername(e.target.value)} - placeholder="Start typing to search..." - sx={{ flex: 1, minWidth: 150 }} - /> - - setToken(e.target.value)} - type="password" - sx={{ flex: 1, minWidth: 150 }} - helperText={ - - - - Generate new token - - +
+ + setUsername(e.target.value)} + required + sx={{ flex: 1, minWidth: 150 }} + /> + setToken(e.target.value)} + type="password" + required + sx={{ flex: 1, minWidth: 150 }} + helperText={ - • - - - - Learn more - - - } - /> - + + + Generate new token + + + + • + + + + Learn more + + + } + /> + + +
{/* Filters */} @@ -406,20 +427,11 @@ const Home: React.FC = () => { )} {loading ? ( - + ) : ( - + @@ -442,23 +454,15 @@ const Home: React.FC = () => { {currentData.map((item) => ( {getStatusIcon(item)} - {item.title} @@ -478,9 +482,7 @@ const Home: React.FC = () => { : item.state} - - {formatDate(item.created_at)} - + {formatDate(item.created_at)} ))}