diff --git a/src/components/pages/home.tsx b/src/components/pages/home.tsx index f127b33..a00f48b 100644 --- a/src/components/pages/home.tsx +++ b/src/components/pages/home.tsx @@ -1,6 +1,11 @@ import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; +interface CountResponse { + lastUpdateTime: string; + counts: PackageStats; +} + interface PackageStats { stale: number; missing: number; @@ -18,16 +23,21 @@ const Home: React.FC = () => { const fetchStats = async () => { try { const response = await fetch('/api/counts'); - const data: PackageStats = await response.json(); - setStats(data); - setLastUpdated(new Date().toLocaleString('en-GB', { + const data: CountResponse = await response.json(); + const counts = data.counts; + setStats(counts); + const dt = new Date(data.lastUpdateTime); + const dateLocale = dt.toLocaleDateString(navigator.language, { day: '2-digit', month: '2-digit', year: 'numeric', + }); + const timeLocale = dt.toLocaleTimeString(navigator.language, { hour: '2-digit', - minute: '2-digit', - second: '2-digit' - })); + minute: '2-digit' + }); + + setLastUpdated(`${timeLocale} on ${dateLocale}`); } catch (error) { console.error('Failed to fetch stats:', error); } diff --git a/src/components/pages/packages.tsx b/src/components/pages/packages.tsx index eddaa17..e1a7677 100644 --- a/src/components/pages/packages.tsx +++ b/src/components/pages/packages.tsx @@ -38,17 +38,8 @@ interface Package { }; } -interface CountsData { - stale: number; - missing: number; - built: number; - error: number; - queued: number; - building: number; -} - const Packages: React.FC = () => { - const { getParam } = useSearchParams(); + const { getParam, setParam } = useSearchParams(); const [packages, setPackages] = useState([]); const [totalCount, setTotalCount] = useState(0); const [currentPage, setCurrentPage] = useState( @@ -65,21 +56,12 @@ const Packages: React.FC = () => { }, [isMobile]); useEffect(() => { - fetchTotalCount(); fetchPackages(); + setParam("page", currentPage.toString()); + setParam("search", search); + setParam("filter", filter); }, [currentPage, search, filter, pageSize]); - const fetchTotalCount = async () => { - try { - const response = await fetch("/api/counts"); - const data: CountsData = await response.json(); - const total = Object.values(data).reduce((acc, curr) => acc + curr, 0); - setTotalCount(total); - } catch (error) { - console.error("Error fetching total count:", error); - setTotalCount(0); // Set to 0 if there's an error - } - }; const fetchPackages = async () => { setLoading(true); @@ -89,8 +71,10 @@ const Packages: React.FC = () => { `/api/packages?page=${currentPage}&pageSize=${pageSize}&search=${search}&filter=${filterParam}` ); const data = await response.json(); - setPackages(Object.values(data)); + setTotalCount(data.total); + setPackages(Object.values(data.packages)); } catch (error) { + setTotalCount(0); console.error("Error fetching packages:", error); } finally { setLoading(false); @@ -98,13 +82,24 @@ const Packages: React.FC = () => { }; const handleFilterChange = (value: string) => { - setFilter(value === "All" ? "" : value); + const newFilter = value === "All" ? "" : value; + setFilter(newFilter); setCurrentPage(1); + setParam("filter", newFilter); + setParam("page", "1"); }; const handleSearchChange = (e: React.ChangeEvent) => { - setSearch(e.target.value); + const newSearch = e.target.value; + setSearch(newSearch); setCurrentPage(1); + setParam("search", newSearch); + setParam("page", "1"); + }; + + const handlePageChange = (page: number) => { + setCurrentPage(page); + setParam("page", page.toString()); }; const totalPages = Math.ceil(totalCount / pageSize); @@ -145,154 +140,151 @@ const Packages: React.FC = () => { - {/* Table */} -
-
-
- - - - Name - Version - Status +{/* Table */} +
+
+
+
+ + + Name + Version + Status + + + + {loading ? ( + + + Loading... + + + ) : ( + packages.map((pkg) => { + const firstPackage = Object.values(pkg.Packages)[0]; + return ( + + +
+
+ {pkg.Name} + {firstPackage.Status} +
+
+ {firstPackage.Version} + {firstPackage.NewVersion && ( + → {firstPackage.NewVersion} + )} +
+
+
+ +
+ {firstPackage.Version} + {firstPackage.NewVersion && ( + + → {firstPackage.NewVersion} + + )} +
+
+ + {firstPackage.Status} +
- - - {loading ? ( - - - Loading... - - - ) : ( - packages.map((pkg) => { - const firstPackage = Object.values(pkg.Packages)[0]; - return ( - - -
-
-
{pkg.Name}
-
- {firstPackage.Status} -
-
-
- {firstPackage.Version} - {firstPackage.NewVersion && ( - <> → {firstPackage.NewVersion} - )} -
-
-
- -
-
- {firstPackage.Version} -
- {firstPackage.NewVersion && ( - - → {firstPackage.NewVersion} - - )} -
-
- - {firstPackage.Status} - -
- ); - }) - )} -
-
-
-
-
+ ); + }) + )} + + + + + - {/* Sticky Footer with Pagination */} -
-
- - - - - setCurrentPage((prev) => Math.max(prev - 1, 1)) - } - /> - +{/* Sticky Footer with Pagination */} +
+
+ + + + handlePageChange(Math.max(currentPage - 1, 1))} + /> + - {currentPage > 1 && ( - - setCurrentPage(1)} - > - 1 - - - )} + {currentPage > 2 && ( + + handlePageChange(1)}> + 1 + + + )} - {currentPage > 3 && } + {currentPage > 3 && ( + + + + )} - {currentPage > 2 && ( - - setCurrentPage(currentPage - 1)} - > - {currentPage - 1} - - - )} + {currentPage > 1 && ( + + handlePageChange(currentPage - 1)} + > + {currentPage - 1} + + + )} - - - {currentPage} - - + + + {currentPage} + + - {currentPage < totalPages - 1 && ( - - setCurrentPage(currentPage + 1)} - > - {currentPage + 1} - - - )} + {currentPage < totalPages && ( + + handlePageChange(currentPage + 1)} + > + {currentPage + 1} + + + )} - {currentPage < totalPages - 2 && } + {currentPage < totalPages - 2 && ( + + + + )} - {currentPage < totalPages && ( - - setCurrentPage(totalPages)} - > - {totalPages} - - - )} + {currentPage < totalPages - 1 && ( + + handlePageChange(totalPages)} + > + {totalPages} + + + )} - - - setCurrentPage((prev) => Math.min(prev + 1, totalPages)) - } - /> - - - -
-
+ + handlePageChange(Math.min(currentPage + 1, totalPages))} + /> + +
+
+
+
); };