Styling Fixes

This commit is contained in:
ferreo 2024-07-29 16:08:29 +01:00
parent 4774f15f3f
commit cb46826770
2 changed files with 171 additions and 169 deletions

View File

@ -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);
}

View File

@ -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<Package[]>([]);
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<HTMLInputElement>) => {
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 = () => {
</div>
</div>
{/* Table */}
<div className="flex-grow overflow-hidden">
<div className="container mx-0 px-0 h-full">
<div className="h-full">
<Table className="">
<TableHeader className="top-0 bg-background z-10 hidden md:table-header-group">
<TableRow>
<TableHead className="w-1/2 text-left">Name</TableHead>
<TableHead className="w-1/4 text-left">Version</TableHead>
<TableHead className="w-1/4 text-left">Status</TableHead>
{/* Table */}
<div className="flex-grow overflow-hidden">
<div className="container mx-0 px-0 h-full">
<div className="h-full">
<Table className="w-full">
<TableHeader className="top-0 bg-background z-10 hidden md:table-header-group">
<TableRow>
<TableHead className="w-1/2 text-left">Name</TableHead>
<TableHead className="w-1/4 text-left">Version</TableHead>
<TableHead className="w-1/4 text-left">Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{loading ? (
<TableRow>
<TableCell colSpan={3} className="text-center">
Loading...
</TableCell>
</TableRow>
) : (
packages.map((pkg) => {
const firstPackage = Object.values(pkg.Packages)[0];
return (
<TableRow
key={pkg.Name}
className="md:table-row border-b last:border-b-0"
>
<TableCell className="w-full md:w-1/2 py-2 md:py-4">
<div className="flex flex-col h-full md:h-auto">
<div className="flex justify-between items-start mb-2 md:mb-0">
<span className="font-medium truncate mr-2">{pkg.Name}</span>
<span className="text-sm md:hidden truncate">{firstPackage.Status}</span>
</div>
<div className="md:hidden text-sm text-muted-foreground text-center">
<span className="truncate">{firstPackage.Version}</span>
{firstPackage.NewVersion && (
<span className="truncate block"> {firstPackage.NewVersion}</span>
)}
</div>
</div>
</TableCell>
<TableCell className="hidden md:table-cell md:w-1/4 py-4 text-left">
<div className="flex flex-col">
<span className="truncate">{firstPackage.Version}</span>
{firstPackage.NewVersion && (
<span className="text-sm text-muted-foreground truncate">
{firstPackage.NewVersion}
</span>
)}
</div>
</TableCell>
<TableCell className="hidden md:table-cell md:w-1/4 py-2 md:py-4 text-left">
<span className="truncate">{firstPackage.Status}</span>
</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{loading ? (
<TableRow>
<TableCell colSpan={3} className="text-center">
Loading...
</TableCell>
</TableRow>
) : (
packages.map((pkg) => {
const firstPackage = Object.values(pkg.Packages)[0];
return (
<TableRow
key={pkg.Name}
className="flex justify-between flex-row md:table-row"
>
<TableCell className="w-full md:w-1/2 py-2 md:py-4">
<div className="flex flex-col justify-center">
<div className="font-medium truncate md:text-left flex flex-row justify-between">
<div className="flex w-1/2">{pkg.Name}</div>
<div className="md:hidden flex w/2">
{firstPackage.Status}
</div>
</div>
<div className="md:hidden text-sm text-muted-foreground truncate">
{firstPackage.Version}
{firstPackage.NewVersion && (
<> {firstPackage.NewVersion}</>
)}
</div>
</div>
</TableCell>
<TableCell className="hidden md:table-cell md:w-1/4 py-4 md:text-left">
<div className="flex flex-col">
<div className="text-foreground truncate">
{firstPackage.Version}
</div>
{firstPackage.NewVersion && (
<span className="text-sm text-muted-foreground truncate">
{firstPackage.NewVersion}
</span>
)}
</div>
</TableCell>
<TableCell className="hidden md:block md:w-1/4 py-2 md:py-4 text-right md:text-left">
{firstPackage.Status}
</TableCell>
</TableRow>
);
})
)}
</TableBody>
</Table>
</div>
</div>
</div>
);
})
)}
</TableBody>
</Table>
</div>
</div>
</div>
{/* Sticky Footer with Pagination */}
<div className="sticky bottom-0 w-full bg-background border-t border-border py-4">
<div className="container mx-auto">
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious
size="default"
onClick={() =>
setCurrentPage((prev) => Math.max(prev - 1, 1))
}
/>
</PaginationItem>
{/* Sticky Footer with Pagination */}
<div className="sticky bottom-0 w-full bg-background border-t border-border py-4">
<div className="container mx-auto px-2">
<Pagination>
<PaginationContent className="flex flex-wrap justify-center items-center gap-1">
<PaginationItem>
<PaginationPrevious
size="default"
onClick={() => handlePageChange(Math.max(currentPage - 1, 1))}
/>
</PaginationItem>
{currentPage > 1 && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => setCurrentPage(1)}
>
1
</PaginationLink>
</PaginationItem>
)}
{currentPage > 2 && (
<PaginationItem className="hidden sm:inline-block">
<PaginationLink size="default" onClick={() => handlePageChange(1)}>
1
</PaginationLink>
</PaginationItem>
)}
{currentPage > 3 && <PaginationEllipsis />}
{currentPage > 3 && (
<PaginationItem className="hidden sm:inline-flex items-center">
<PaginationEllipsis />
</PaginationItem>
)}
{currentPage > 2 && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => setCurrentPage(currentPage - 1)}
>
{currentPage - 1}
</PaginationLink>
</PaginationItem>
)}
{currentPage > 1 && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => handlePageChange(currentPage - 1)}
>
{currentPage - 1}
</PaginationLink>
</PaginationItem>
)}
<PaginationItem>
<PaginationLink size="default" isActive>
{currentPage}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink size="default" isActive>
{currentPage}
</PaginationLink>
</PaginationItem>
{currentPage < totalPages - 1 && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => setCurrentPage(currentPage + 1)}
>
{currentPage + 1}
</PaginationLink>
</PaginationItem>
)}
{currentPage < totalPages && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => handlePageChange(currentPage + 1)}
>
{currentPage + 1}
</PaginationLink>
</PaginationItem>
)}
{currentPage < totalPages - 2 && <PaginationEllipsis />}
{currentPage < totalPages - 2 && (
<PaginationItem className="hidden sm:inline-flex items-center">
<PaginationEllipsis />
</PaginationItem>
)}
{currentPage < totalPages && (
<PaginationItem>
<PaginationLink
size="default"
onClick={() => setCurrentPage(totalPages)}
>
{totalPages}
</PaginationLink>
</PaginationItem>
)}
{currentPage < totalPages - 1 && (
<PaginationItem className="hidden sm:inline-block">
<PaginationLink
size="default"
onClick={() => handlePageChange(totalPages)}
>
{totalPages}
</PaginationLink>
</PaginationItem>
)}
<PaginationItem>
<PaginationNext
size="default"
onClick={() =>
setCurrentPage((prev) => Math.min(prev + 1, totalPages))
}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</div>
<PaginationItem>
<PaginationNext
size="default"
onClick={() => handlePageChange(Math.min(currentPage + 1, totalPages))}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</div>
</div>
);
};