mirror of
https://github.com/sergi0g/cup.git
synced 2025-11-16 17:13:46 -05:00
V3
Many many many changes, honestly just read the release notes
This commit is contained in:
@@ -1,48 +1,73 @@
|
||||
import {
|
||||
IconCircleArrowUpFilled,
|
||||
IconCircleCheckFilled,
|
||||
IconEyeFilled,
|
||||
IconHelpCircleFilled,
|
||||
} from "@tabler/icons-react";
|
||||
import { CircleArrowUp, CircleCheck, Eye, HelpCircle } from "lucide-react";
|
||||
import { theme } from "../theme";
|
||||
import { Data } from "../types";
|
||||
|
||||
const metricsToShow = [
|
||||
"monitored_images",
|
||||
"up_to_date",
|
||||
"updates_available",
|
||||
"unknown",
|
||||
];
|
||||
|
||||
export default function Statistic({
|
||||
name,
|
||||
value,
|
||||
metrics,
|
||||
}: {
|
||||
name: string;
|
||||
value: number;
|
||||
name: keyof Data["metrics"];
|
||||
metrics: Data["metrics"];
|
||||
}) {
|
||||
name = name.replaceAll("_", " ");
|
||||
name = name.slice(0, 1).toUpperCase() + name.slice(1); // Capitalize name
|
||||
if (!metricsToShow.includes(name)) return null;
|
||||
const displayName = name.replaceAll("_", " ");
|
||||
return (
|
||||
<div
|
||||
className={`before:bg-${theme}-200 before:dark:bg-${theme}-800 after:bg-${theme}-200 after:dark:bg-${theme}-800 gi`}
|
||||
className={`before:bg-${theme}-200 before:dark:bg-${theme}-900 after:bg-${theme}-200 after:dark:bg-${theme}-900 gi`}
|
||||
>
|
||||
<div className="xl:px-8 px-6 py-4 gap-y-2 gap-x-4 justify-between align-baseline flex flex-col h-full">
|
||||
<div className="flex h-full flex-col justify-between gap-x-4 gap-y-2 px-6 py-4 align-baseline lg:min-h-32">
|
||||
<dt
|
||||
className={`text-${theme}-500 dark:text-${theme}-400 leading-6 font-medium`}
|
||||
className={`text-${theme}-500 dark:text-${theme}-400 text-sm font-semibold uppercase leading-6`}
|
||||
>
|
||||
{name}
|
||||
{displayName}
|
||||
</dt>
|
||||
<div className="flex gap-1 justify-between items-center">
|
||||
<dd className="text-black dark:text-white tracking-tight leading-10 font-medium text-3xl w-full">
|
||||
{value}
|
||||
<div className="flex items-center justify-between gap-1">
|
||||
<dd className="w-full text-3xl font-medium leading-10 tracking-tight text-black dark:text-white">
|
||||
{metrics[name]}
|
||||
</dd>
|
||||
{name == "Monitored images" && (
|
||||
<IconEyeFilled className="size-6 text-black dark:text-white shrink-0" />
|
||||
{name === "monitored_images" && (
|
||||
<Eye className="size-6 shrink-0 text-black dark:text-white" />
|
||||
)}
|
||||
{name == "Up to date" && (
|
||||
<IconCircleCheckFilled className="size-6 text-green-500 shrink-0" />
|
||||
{name === "up_to_date" && (
|
||||
<CircleCheck className="size-6 shrink-0 text-green-500" />
|
||||
)}
|
||||
{name == "Update available" && (
|
||||
<IconCircleArrowUpFilled className="size-6 text-blue-500 shrink-0" />
|
||||
)}
|
||||
{name == "Unknown" && (
|
||||
<IconHelpCircleFilled className="size-6 text-gray-500 shrink-0" />
|
||||
{name === "updates_available" && getUpdatesAvailableIcon(metrics)}
|
||||
{name === "unknown" && (
|
||||
<HelpCircle className="size-6 shrink-0 text-gray-500" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getUpdatesAvailableIcon(metrics: Data["metrics"]) {
|
||||
const filteredMetrics = Object.entries(metrics).filter(
|
||||
([key]) => !metricsToShow.includes(key),
|
||||
);
|
||||
const maxMetric = filteredMetrics.reduce((max, current) => {
|
||||
if (Number(current[1]) > Number(max[1])) {
|
||||
return current;
|
||||
}
|
||||
return max;
|
||||
}, filteredMetrics[0])[0];
|
||||
let color = "";
|
||||
switch (maxMetric) {
|
||||
case "major_updates":
|
||||
color = "text-red-500";
|
||||
break;
|
||||
case "minor_updates":
|
||||
color = "text-yellow-500";
|
||||
break;
|
||||
default:
|
||||
color = "text-blue-500";
|
||||
}
|
||||
return <CircleArrowUp className={`size-6 shrink-0 ${color}`} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user