Files
dvdash/src/app/_components/docker-table.tsx
2025-09-06 16:22:22 +01:00

107 lines
3.3 KiB
TypeScript

"use client";
import type { dockerRouterType } from "@/server/api/routers/docker";
import { api } from "@/trpc/react";
import type { JSX } from "react";
function DockerCard({
containerInfo,
}: {
containerInfo: dockerRouterType["list"][number];
}) {
const { data: latest, isError, isLoading, error } = api.docker.latest.useQuery({ id: containerInfo.container.id }, { refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false });
let latestFragment: JSX.Element | null = null;
if (isError) {
latestFragment = (
<div className="flex flex-row flex-wrap *:basis-1/2">
<dt>Tag</dt>
<dd>Error: {error.message}</dd>
<dt>Short Hash</dt>
<dd>Error: {error.message}</dd>
</div>
);
} else if (isLoading) {
latestFragment = (
<div className="flex flex-row flex-wrap *:basis-1/2">
<dt>Tag</dt>
<dd className="loading loading-dots loading-sm" />
<dt>Short Hash</dt>
<dd className="loading loading-dots loading-sm" />
</div>
);
} else if (latest) {
latestFragment = (
<div className="flex flex-row flex-wrap *:basis-1/2">
<dt>Tag</dt>
<dd>{latest?.latest.tag ?? "Unknown"}</dd>
<dt>Short Hash</dt>
<dd>{latest?.latest.hash ?? "Unknown"}</dd>
</div>
);
}
const outdated = containerInfo.image.current.hash !== latest?.latest.hash;
const showWarning = isLoading || (!isError && !isLoading && (!latest?.latest.tag || !latest?.latest.hash));
return (
<div
key={containerInfo.container.name}
className={`card card-outline card-compact w-80 border-t-8 bg-base-300 shadow-md ${showWarning ? "border-t-warning/80" : outdated ? "border-t-error/80" : "border-t-info/80"}`}
>
<dl className="card-body flex flex-col flex-wrap items-center justify-around text-base">
<h2 className="text-center text-3xl">{containerInfo.container.name}</h2>
<p>{containerInfo.image.name}</p>
<div className="divider divider-primary m-1" />
<h3 className="text-xl underline decoration-1 underline-offset-4">Current</h3>
<div className="flex flex-row flex-wrap *:basis-1/2">
<dt>Tag</dt>
<dd>{containerInfo.image.current.tag}</dd>
<dt>Short Hash</dt>
<dd>{containerInfo.image.current.hash}</dd>
</div>
<div className="divider divider-primary m-0" />
<h3 className="text-xl underline decoration-1 underline-offset-4">Latest</h3>
{latestFragment}
</dl>
</div>
);
}
export function DockerTable() {
const { data: list, isLoading: listLoading, error } = api.docker.list.useQuery(undefined, { refetchOnMount: false, refetchOnWindowFocus: false, refetchOnReconnect: false });
return (
<>
{listLoading ? (
<>Loading docker container list...</>
) : (
<>
<div className={"flex flex-row flex-wrap justify-around gap-8"}>
{list ? (
list
.sort((ca, cb) => {
if (ca.container.name && cb.container.name) {
if (ca.container.name < cb.container.name) {
return -1;
}
if (ca.container.name > cb.container.name) {
return 1;
}
}
return 0;
})
.map((containerInfo) => <DockerCard key={containerInfo.container.name} containerInfo={containerInfo} />)
) : (
<>Error loading docker container list: {error?.message}</>
)}
</div>
</>
)}
</>
);
}