134 lines
5.4 KiB
TypeScript
134 lines
5.4 KiB
TypeScript
import { inventoryApi, inventoryKeys } from "@metis/assets/client";
|
|
import { BrowserLink, useEntryState, useListQuery } from "@metis/core/client";
|
|
import { EntityListStatus } from "@repo/rdx-ui/components/entity-list-status";
|
|
import { useRef } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { z } from "zod/v4";
|
|
|
|
import type { CompanyDTO } from "../../../../common";
|
|
import { printerApi, printerKeys } from "../../../printer-configurations/shared/api";
|
|
import { useCompanyListState } from "../../../shared/hooks/use-company-list-state";
|
|
import { profileApi, profileKeys } from "../../../work-profiles/shared/api";
|
|
import { printerUsage } from "../helpers/printer-usage";
|
|
|
|
const HistorySchema = z.boolean();
|
|
|
|
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 rootRef = useRef<HTMLDivElement>(null);
|
|
const [historyOpen, setHistoryOpen] = useEntryState({
|
|
scope: `/companies/${company.id}/assets/${assetId}`,
|
|
key: "printer-usage-history",
|
|
schema: HistorySchema,
|
|
initialValue: false,
|
|
});
|
|
const { state, denied } = useCompanyListState([printers, profiles, inventory]);
|
|
const available = state.status !== "loading" && state.status !== "unavailable";
|
|
const usage = printerUsage(
|
|
assetId,
|
|
printers.data?.configurations ?? [],
|
|
profiles.data?.profiles ?? [],
|
|
inventory.data?.assets ?? []
|
|
);
|
|
|
|
return (
|
|
<div className="min-w-0 space-y-3" ref={rootRef} tabIndex={-1}>
|
|
<EntityListStatus
|
|
onRetry={
|
|
denied
|
|
? undefined
|
|
: () => Promise.all([printers.refetch(), profiles.refetch(), inventory.refetch()])
|
|
}
|
|
retryFocus={() => rootRef.current}
|
|
retryLabel={t("retry")}
|
|
state={state}
|
|
/>
|
|
{available && (
|
|
<>
|
|
{!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="min-w-0 rounded-md border p-3 text-sm [overflow-wrap:anywhere]"
|
|
data-entity-id={group.id}
|
|
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 data-entity-id={configuration.id} 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
|
|
onToggle={(event) => setHistoryOpen(event.currentTarget.open)}
|
|
open={historyOpen}
|
|
>
|
|
<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" data-entity-id={item.id} 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>
|
|
);
|
|
}
|