metis-desk/modules/companies/src/web/infrastructure/shared/ui/asset-printer-usage.tsx

119 lines
4.4 KiB
TypeScript
Raw Normal View History

2026-10-17 15:01:16 +00:00
import { inventoryApi, inventoryKeys } from "@metis/assets/client";
import { BrowserLink, useListQuery } from "@metis/core/client";
import { Button } from "@repo/shadcn-ui/components/button";
import { useTranslation } from "react-i18next";
import type { CompanyDTO } from "../../../../common";
import { printerApi, printerKeys } from "../../../printer-configurations/shared/api";
import { profileApi, profileKeys } from "../../../work-profiles/shared/api";
import { printerUsage } from "../helpers/printer-usage";
export function AssetPrinterUsage({ company, assetId }: { company: CompanyDTO; assetId: string }) {
const { t } = useTranslation("companies");
const printers = useListQuery({
queryKey: printerKeys.company(company.id),
queryFn: () => printerApi.get(company.id),
});
const profiles = useListQuery({
queryKey: profileKeys.company(company.id),
queryFn: () => profileApi.get(company.id),
});
const inventory = useListQuery({
queryKey: inventoryKeys.company(company.id),
queryFn: () => inventoryApi.get(company.id),
});
const failed = printers.isError || profiles.isError || inventory.isError;
const usage = printerUsage(
assetId,
printers.data?.configurations ?? [],
profiles.data?.profiles ?? [],
inventory.data?.assets ?? []
);
if (printers.isPending || profiles.isPending || inventory.isPending) {
return <p role="status">{t("loading")}</p>;
}
if (failed) {
return (
<div>
<p role="alert">{t("infrastructureUsage.error")}</p>
<Button
onClick={() => {
Promise.all([printers.refetch(), profiles.refetch(), inventory.refetch()]).catch(
() => undefined
);
}}
size="sm"
variant="outline"
>
{t("retry")}
</Button>
</div>
);
}
return (
<div className="space-y-3">
{!usage.groups.length && (
<p className="text-sm text-muted-foreground">{t("infrastructureUsage.empty")}</p>
)}
{usage.unresolved.length > 0 && <p role="alert">{t("infrastructureUsage.incomplete")}</p>}
<ul className="space-y-3">
{usage.groups.map((group) => (
<li className="rounded-md border p-3 text-sm" key={group.id}>
<BrowserLink
className="font-medium"
href={`/companies/${company.id}/assets/${group.id}`}
>
{group.name}
</BrowserLink>
<ul className="mt-2 space-y-2">
{group.configurations.map(({ profile, configuration }) => (
<li key={configuration.id}>
<BrowserLink href={`/companies/${company.id}/work-profiles/${profile.id}`}>
{profile.values.name}
</BrowserLink>{" "}
·{" "}
{company.people.find((person) => person.id === profile.values.personId)?.name ??
"—"}
<p className="text-muted-foreground">
{t(`mail.${configuration.values.state}`)} ·{" "}
{t(`printers.${configuration.values.connection}`)}
{configuration.values.isDefault ? ` · ${t("infrastructureUsage.default")}` : ""}
</p>
{(!profile.values.active || configuration.needsReview) && (
<p className="text-amber-700 dark:text-amber-400">
{t("infrastructureUsage.review")}
</p>
)}
</li>
))}
</ul>
</li>
))}
</ul>
{usage.history.length > 0 && (
<details>
<summary className="cursor-pointer text-sm">
{t("infrastructureUsage.history", { count: usage.history.length })}
</summary>
<ul className="mt-2 space-y-2">
{usage.history.map((item) => (
<li className="text-sm" key={item.id}>
<BrowserLink
href={`/companies/${company.id}/work-profiles/${item.values.profileId}`}
>
{profiles.data?.profiles.find((profile) => profile.id === item.values.profileId)
?.values.name ?? "—"}
</BrowserLink>{" "}
· {t(`mail.${item.values.state}`)}
</li>
))}
</ul>
</details>
)}
<p className="text-xs text-muted-foreground">{t("infrastructureUsage.notice")}</p>
</div>
);
}