metis-desk/modules/companies/src/web/dashboard/detail/ui/dashboard-details-dialog.tsx

162 lines
5.7 KiB
TypeScript
Raw Normal View History

import { EntityTable } from "@repo/rdx-ui/components/entity-list";
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
import { entityListLabels } from "@repo/rdx-ui/lib/entity-list";
import { Button } from "@repo/shadcn-ui/components/button";
import { useTranslation } from "react-i18next";
2026-10-09 08:18:00 +00:00
import { CompanyIdentity } from "../../../companies/shared/ui/company-identity";
import { BlockState, DashboardNavigationButton, DashboardTable } from "../../shared";
import { entryDestination } from "../../shared/helpers";
import { useDashboardDetailsDialogController } from "../controllers";
import { detailsTitle } from "../helpers";
import type { DashboardDetailsDialogProps } from "../types";
export function DashboardDetailsDialog(props: DashboardDetailsDialogProps) {
const { details, onClose, onNavigate } = props;
const { page, setPage, query, companies, total } = useDashboardDetailsDialogController(props);
const { t, i18n } = useTranslation("companies");
const title = t(detailsTitle(details));
const labels = entityListLabels(i18n.language);
const range = labels.range(
total ? (page - 1) * 10 + 1 : 0,
Math.min(page * 10, total),
total,
t("dashboard.records")
);
2026-10-10 10:01:58 +00:00
return (
<FormDialog
cancelLabel={t("cancel")}
onOpenChange={(open) => {
if (!open) {
onClose();
}
}}
open
title={title}
wide
>
{details.companies ? (
<BlockState
empty={!companies.data?.items.length}
emptyText={t("noCompanies")}
query={companies}
>
<EntityTable
columns={[
{
id: "name",
hideable: false,
label: t("name"),
value: (item) => item.name,
render: (item) => (
<DashboardNavigationButton
onClick={() =>
onNavigate({ area: "company", id: item.id, section: "inventory" })
}
>
<CompanyIdentity companyId={item.id} name={item.name} />
</DashboardNavigationButton>
),
},
{
id: "assets",
label: t("dashboard.registeredAssets"),
value: (item) => item.assets,
render: (item) => item.assets,
},
{
id: "people",
label: t("people"),
value: (item) => item.people,
render: (item) => item.people,
},
]}
entityLabel={t("title")}
items={companies.data?.items ?? []}
locale={i18n.language}
title={title}
/>
</BlockState>
) : (
<>
<BlockState
empty={!query.data?.items.length}
emptyText={t("dashboard.noMatches")}
query={query}
>
<p className="text-sm text-muted-foreground">{range}</p>
<div className="rounded-panel bg-card">
<DashboardTable caption={title}>
<thead>
<tr>
<th scope="col">{t("name")}</th>
<th scope="col">{t("companyLabel")}</th>
{details.activity && <th scope="col">{t("dashboard.recordedAt")}</th>}
{details.activity && <th scope="col">{t("dashboard.recordedBy")}</th>}
</tr>
</thead>
<tbody>
{query.data?.items.map((item) => (
<tr key={item.eventId ?? item.id}>
<td>
<DashboardNavigationButton
onClick={() => onNavigate(entryDestination(item))}
>
{item.name}
</DashboardNavigationButton>
</td>
<td>
<CompanyIdentity companyId={item.companyId} name={item.companyName} />
</td>
{details.activity && (
<td>
{item.recordedAt
? new Intl.DateTimeFormat(i18n.language, {
dateStyle: "medium",
timeStyle: "short",
}).format(new Date(item.recordedAt))
: "—"}
</td>
)}
{details.activity && <td>{item.actorName ?? "—"}</td>}
</tr>
))}
</tbody>
</DashboardTable>
</div>
</BlockState>
{!details.activity && query.isSuccess && (
<footer className="flex flex-wrap items-center justify-between gap-3 border-t pt-4 text-sm">
<span>{range}</span>
<div className="flex items-center gap-2">
<Button
aria-label={labels.previous}
disabled={page === 1}
onClick={() => setPage(page - 1)}
size="sm"
variant="outline"
>
‹
</Button>
<span>
{labels.page} {page}
</span>
<Button
aria-label={labels.next}
disabled={page * 10 >= total}
onClick={() => setPage(page + 1)}
size="sm"
variant="outline"
>
›
</Button>
</div>
</footer>
)}
</>
)}
</FormDialog>
);
}