diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 613a32e..914a69d 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -1,34 +1,8 @@ import React, { useState } from "react"; -import { - Container, - Box, - TextField, - Button, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - TablePagination, - Link, - CircularProgress, - Alert, - Tabs, - Tab, - Select, - MenuItem, - FormControl, - InputLabel, -} from "@mui/material"; -import { useTheme } from "@mui/material/styles"; -import { useGitHubAuth } from "../../hooks/useGitHubAuth"; -import { useGitHubData } from "../../hooks/useGitHubData"; -import { usePagination } from "../../hooks/usePagination"; const ROWS_PER_PAGE = 10; +// Define the shape of the data received from GitHub interface GitHubItem { id: number; title: string; @@ -39,8 +13,33 @@ interface GitHubItem { html_url: string; } +// Mock hooks for demonstration +const useGitHubAuth = () => ({ + username: "", + setUsername: (val: string) => {}, + token: "", + setToken: (val: string) => {}, + error: null, + getOctokit: () => null, +}); + +const useGitHubData = (octokit: any) => ({ + issues: [] as GitHubItem[], + prs: [] as GitHubItem[], + loading: false, + error: null, + fetchData: (username: string) => {}, +}); + +const usePagination = (rowsPerPage: number) => ({ + page: 0, + itemsPerPage: rowsPerPage, + handleChangePage: (event: unknown, newPage: number) => {}, + paginateData: (data: GitHubItem[]) => data.slice(0, rowsPerPage), +}); + const Home: React.FC = () => { - const theme = useTheme(); + // Hooks for managing user authentication const { username, setUsername, @@ -49,6 +48,7 @@ const Home: React.FC = () => { error: authError, getOctokit, } = useGitHubAuth(); + const octokit = getOctokit(); const { issues, @@ -57,9 +57,11 @@ const Home: React.FC = () => { error: dataError, fetchData, } = useGitHubData(octokit); + const { page, itemsPerPage, handleChangePage, paginateData } = usePagination(ROWS_PER_PAGE); + // State for various filters and tabs const [tab, setTab] = useState(0); const [issueFilter, setIssueFilter] = useState("all"); const [prFilter, setPrFilter] = useState("all"); @@ -68,229 +70,350 @@ const Home: React.FC = () => { const [startDate, setStartDate] = useState(""); const [endDate, setEndDate] = useState(""); + // Handle data submission to fetch GitHub data const handleSubmit = (e: React.FormEvent): void => { e.preventDefault(); fetchData(username); }; - const formatDate = (dateString: string): string => - new Date(dateString).toLocaleDateString(); + // Format date strings into a readable format + const formatDate = (dateString: string): string => { + return new Date(dateString).toLocaleDateString(); + }; + + // Filter data based on selected criteria + const filterData = ( + data: GitHubItem[], + filterType: string + ): GitHubItem[] => { + let filteredData = [...data]; - const filterData = (data: GitHubItem[], filterType: string): GitHubItem[] => { - let filtered = [...data]; - if (["open", "closed", "merged"].includes(filterType)) { - filtered = filtered.filter((item) => + if (filterType === "open" || filterType === "closed" || filterType === "merged") { + filteredData = filteredData.filter((item) => filterType === "merged" - ? !!item.pull_request?.merged_at + ? item.pull_request?.merged_at : item.state === filterType ); } + if (searchTitle) { - filtered = filtered.filter((item) => + filteredData = filteredData.filter((item) => item.title.toLowerCase().includes(searchTitle.toLowerCase()) ); } + if (selectedRepo) { - filtered = filtered.filter((item) => + filteredData = filteredData.filter((item) => item.repository_url.includes(selectedRepo) ); } + if (startDate) { - filtered = filtered.filter( + filteredData = filteredData.filter( (item) => new Date(item.created_at) >= new Date(startDate) ); } if (endDate) { - filtered = filtered.filter( + filteredData = filteredData.filter( (item) => new Date(item.created_at) <= new Date(endDate) ); } - return filtered; + + return filteredData; + }; + + // Get state chip color and icon + const getStateChip = (item: GitHubItem) => { + if (item.pull_request?.merged_at) { + return ( + + Merged + + ); + } + + const isOpen = item.state === 'open'; + return ( + + {item.state.charAt(0).toUpperCase() + item.state.slice(1)} + + ); }; + // Determine the current tab's data const currentData = tab === 0 ? filterData(issues, issueFilter) : filterData(prs, prFilter); + + // Paginate the filtered data const displayData = paginateData(currentData); + // Main UI rendering return ( - - -
- - setUsername(e.target.value)} - required - sx={{ flex: 1 }} - /> - setToken(e.target.value)} - type="password" - required - sx={{ flex: 1 }} - /> - - -
-
- - - 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 }} - /> - - - - setTab(newValue)} sx={{ flex: 1 }}> - - - - - State - - - - - {(authError || dataError) && ( - - {authError || dataError} - - )} - - {loading ? ( - - - - ) : ( - - - - - - Title - Repository - State - Created - - - - {displayData.map((item: GitHubItem) => ( - - - +
+ {/* Header */} +
+

+ GitHub Dashboard +

+

+ Track your issues and pull requests in style +

+
+ + {/* Authentication Card */} +
+

+ 🔐 GitHub Authentication +

+
+
+ + setUsername(e.target.value)} + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-purple-200 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + placeholder="Enter your username" + /> +
+
+ + setToken(e.target.value)} + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-purple-200 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + placeholder="Enter your token" + /> +
+ +
+
+ + {/* Filters Card */} +
+

+ 🔍 Filters & Search +

+ +
+
+ + setSearchTitle(e.target.value)} + placeholder="🔍 Search by title..." + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-purple-200 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + /> +
+ +
+ + setSelectedRepo(e.target.value)} + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white placeholder-purple-200 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + placeholder="Repository name" + /> +
+ +
+ + setStartDate(e.target.value)} + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + /> +
+ +
+ + setEndDate(e.target.value)} + className="w-full px-4 py-3 rounded-xl bg-white/20 border border-white/30 text-white focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent backdrop-blur-sm transition-all duration-300 hover:bg-white/25" + /> +
+
+ +
+ + {/* Tabs and State Filter */} +
+
+ + +
+ +
+ + +
+
+
+ + {/* Error Alert */} + {(authError || dataError) && ( +
+
+ ⚠️ + {authError || dataError} +
+
+ )} + + {/* Data Table Card */} +
+ {loading ? ( +
+
+

+ Loading your GitHub data... +

+
+ ) : ( +
+
+
+ + + + + + + + + + + {displayData.map((item: GitHubItem, index) => ( + - {item.title} - - - - {item.repository_url.split("/").slice(-1)[0]} - - - {item.pull_request?.merged_at ? "merged" : item.state} - - - {formatDate(item.created_at)} - - - ))} - -
TitleRepositoryStateCreatedActions
- -
-
- )} -
+ +
+ {item.title} +
+ + + + {item.repository_url.split("/").slice(-1)[0]} + + + + {getStateChip(item)} + + + + {formatDate(item.created_at)} + + + + + 🔗 View + + + + ))} + + + + {/* Pagination */} +
+
+ Showing 1 to {Math.min(itemsPerPage, currentData.length)} of {currentData.length} entries +
+
+ + +
+
+ + + )} + + + ); }; -export default Home; +export default Home; \ No newline at end of file