diff --git a/src/pages/Tracker/Tracker.tsx b/src/pages/Tracker/Tracker.tsx index ce4116f..249cfd4 100644 --- a/src/pages/Tracker/Tracker.tsx +++ b/src/pages/Tracker/Tracker.tsx @@ -1,10 +1,12 @@ -import React, { useState, useEffect } from "react" +import React, { useState, useEffect } from "react"; import { IssueOpenedIcon, IssueClosedIcon, GitPullRequestIcon, GitPullRequestClosedIcon, GitMergeIcon, + KeyIcon, + MarkGithubIcon, } from '@primer/octicons-react'; import { Container, @@ -29,10 +31,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; @@ -47,8 +65,9 @@ interface GitHubItem { } const Home: React.FC = () => { - const theme = useTheme(); + const [showToken, setShowToken] = useState(false); + const [showFilters, setShowFilters] = useState(true); const { username, @@ -96,22 +115,32 @@ const Home: React.FC = () => { setPage(newPage); }; + const clearFilters = () => { + setSearchTitle(""); + setSelectedRepo(""); + setStartDate(""); + setEndDate(""); + setIssueFilter("all"); + setPrFilter("all"); + }; + const formatDate = (dateString: string): string => - new Date(dateString).toLocaleDateString(); + 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 { - //open - return item.state === "open" + return !!item.pull_request?.merged_at; + } else if (filterType === "closed") { + return item.state === "closed" && !item.pull_request?.merged_at; + } else { + return item.state === "open"; } }); } @@ -122,7 +151,7 @@ const Home: React.FC = () => { } if (selectedRepo) { filtered = filtered.filter((item) => - item.repository_url.includes(selectedRepo) + item.repository_url.toLowerCase().includes(selectedRepo.toLowerCase()) ); } if (startDate) { @@ -139,108 +168,255 @@ const Home: React.FC = () => { }; 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"; + } + + 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 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 ? : } + + + ), + }} + /> + - -
-
- - {/* 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