diff --git a/src/pages/Tracker/Tracker.tsx b/src/pages/Tracker/Tracker.tsx index 0d9899b7..5bd06463 100644 --- a/src/pages/Tracker/Tracker.tsx +++ b/src/pages/Tracker/Tracker.tsx @@ -1,12 +1,12 @@ -import React, { useState, useEffect } from "react" -import Dashboard from "../../components/Dashboard"; -import { useDebounce } from "../../hooks/useDebounce"; +import React, { useState, useEffect } from "react"; import { IssueOpenedIcon, IssueClosedIcon, GitPullRequestIcon, GitPullRequestClosedIcon, GitMergeIcon, + KeyIcon, + MarkGithubIcon, } from '@primer/octicons-react'; import { Container, @@ -32,10 +32,26 @@ import { InputLabel, Skeleton, Typography, + Chip, + IconButton, + InputAdornment, + Tooltip, + Fade, + Card, + CardContent, + Divider, + Stack, } from "@mui/material"; import { useTheme } from "@mui/material/styles"; import { useGitHubAuth } from "../../hooks/useGitHubAuth"; import { useGitHubData } from "../../hooks/useGitHubData"; +import { + Visibility, + VisibilityOff, + Refresh, + FilterList, + ClearAll, +} from "@mui/icons-material"; const ROWS_PER_PAGE = 10; @@ -49,9 +65,10 @@ interface GitHubItem { html_url: string; } -const Tracker: React.FC = () => { - +const Home: React.FC = () => { const theme = useTheme(); + const [showToken, setShowToken] = useState(false); + const [showFilters, setShowFilters] = useState(true); const { username, @@ -122,122 +139,308 @@ const Tracker: React.FC = () => { setPage(newPage); }; - const formatDate = (dateString: string): string => - new Date(dateString).toLocaleDateString(); + const clearFilters = () => { + setSearchTitle(""); + setSelectedRepo(""); + setStartDate(""); + setEndDate(""); + setIssueFilter("all"); + setPrFilter("all"); + }; + const formatDate = (dateString: string): string => + new Date(dateString).toLocaleDateString(undefined, { + year: "numeric", + month: "short", + day: "numeric", + }); + + 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 { + 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.toLowerCase().includes(selectedRepo.toLowerCase()) + ); + } + 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) - return ; - - if (item.state === 'closed') - return ; - - return ; + if (item.pull_request.merged_at) + return ; + if (item.state === "closed") + return ; + return ; } - - if (item.state === 'closed') - return ; - + if (item.state === "closed") + return ; return ; }; + const getStatusChip = (item: GitHubItem) => { + let status = item.pull_request?.merged_at ? "merged" : item.state; + let color: "success" | "error" | "warning" | "default" = "default"; + + if (status === "open") { + color = "success"; + status = "Open"; + } else if (status === "closed") { + color = "error"; + status = "Closed"; + } else if (status === "merged") { + color = "warning"; + status = "Merged"; + } - // Current data according to tab - const currentFilteredData = tab === 0 ? issues : prs; + return ; + }; + + // 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; + const hasActiveFilters = + searchTitle || selectedRepo || startDate || endDate || issueFilter !== "all" || prFilter !== "all"; + return ( - + + {/* Header */} + {/* + + + GitHub Activity Dashboard + + + Track issues and pull requests across GitHub repositories + + */} + {/* Auth Form */} - -
- - setUsername(e.target.value)} - required - sx={{ flex: 1, minWidth: 150 }} - /> - setToken(e.target.value)} - type="password" - sx={{ flex: 1, minWidth: 150 }} - // Helper link to guide users on generating a GitHub Personal Access Token - helperText={ - + + + + setUsername(e.target.value)} + required + fullWidth + variant="outlined" + placeholder="e.g., octocat" + InputProps={{ + startAdornment: ( + + + + ), + }} + /> + setToken(e.target.value)} + type={showToken ? "text" : "password"} + fullWidth + variant="outlined" + placeholder="ghp_xxxxxxxxxxxx" + helperText={ + + + + Generate new token + + {" • "} + + Learn more + + + } + InputProps={{ + startAdornment: ( + + + + ), + endAdornment: ( + + setShowToken(!showToken)} + edge="end" + size="small" + > + {showToken ? : } + + + ), + }} + /> + - -
-
- - {/* Dashboard Summary */} - {username && ( - - )} - - {/* Filters */} - - setSearchTitle(e.target.value)} - sx={{ minWidth: 200 }} - /> - setSelectedRepo(e.target.value)} - sx={{ minWidth: 200 }} - /> - setStartDate(e.target.value)} - InputLabelProps={{ shrink: true }} - sx={{ minWidth: 150 }} - /> - setEndDate(e.target.value)} - InputLabelProps={{ shrink: true }} - sx={{ minWidth: 150 }} - /> + minWidth: "140px", + borderRadius: 2, + textTransform: "none", + fontSize: "1rem", + px: 3, + }} + > + {loading ? "Loading..." : "Fetch Data"} + + + + + + + {/* Filter Header with Toggle */} + + + + + Filters + + setShowFilters(!showFilters)}> + + {showFilters ? "Hide" : "Show"} + + + + {hasActiveFilters && ( + + )} + {/* Filters Section */} + + + + + setSearchTitle(e.target.value)} + size="small" + placeholder="Filter by title..." + sx={{ minWidth: 180, flex: 2 }} + /> + setSelectedRepo(e.target.value)} + size="small" + placeholder="Filter by repo name..." + sx={{ minWidth: 160, flex: 2 }} + /> + setStartDate(e.target.value)} + InputLabelProps={{ shrink: true }} + size="small" + sx={{ minWidth: 140 }} + /> + setEndDate(e.target.value)} + InputLabelProps={{ shrink: true }} + size="small" + sx={{ minWidth: 140 }} + /> + + + + + {/* Tabs + State Filter */} { setTab(v); setPage(0); }} - sx={{ flex: 1 }} + sx={{ + "& .MuiTab-root": { + textTransform: "none", + fontWeight: 600, + fontSize: "0.9rem", + }, + }} > - - + + + Issues + + + } + /> + + + Pull Requests + + + } + /> - - State + + State Filter