metis-desk/modules/companies/src/web/components/dashboard-activity-panel.tsx
2026-10-08 16:43:34 +02:00

72 lines
2.5 KiB
TypeScript

import { ClockIcon } from "@repo/shadcn-ui/lib/icons";
import { useQuery } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import type { DashboardNavigation } from "./dashboard-api";
import { dashboardApi, dashboardKeys, entryDestination } from "./dashboard-api";
import { BlockState } from "./dashboard-block";
import { KIND_ICONS } from "./dashboard-kind-icons";
import { DashboardPanel } from "./dashboard-panel";
export function DashboardActivityPanel({
companyId,
onDetails,
onNavigate,
}: {
companyId: string | undefined;
onDetails: () => void;
onNavigate: (destination: DashboardNavigation) => void;
}) {
const { t, i18n } = useTranslation("companies");
const activity = useQuery({
queryKey: dashboardKeys.block("activity", companyId),
queryFn: ({ signal }) => dashboardApi.activity(signal, companyId),
staleTime: 0,
});
const date = (value: string | null) =>
value
? new Intl.DateTimeFormat(i18n.language, { dateStyle: "medium", timeStyle: "short" }).format(
new Date(value)
)
: "—";
return (
<DashboardPanel action={onDetails} icon={<ClockIcon />} title={t("dashboard.recentActivity")}>
<BlockState
empty={!activity.data?.items.length}
emptyText={t("dashboard.noRecentActivity")}
query={activity}
>
<ol className="dashboard-timeline">
{activity.data?.items.slice(0, 4).map((item) => {
const Icon = KIND_ICONS[item.kind];
return (
<li key={item.eventId ?? item.id}>
<time
className="text-xs text-muted-foreground"
dateTime={item.recordedAt ?? undefined}
>
{date(item.recordedAt)}
</time>
<Icon aria-hidden="true" className="size-5 text-primary shrink-0" />
<div>
<button
className="dashboard-link"
onClick={() => onNavigate(entryDestination(item))}
type="button"
>
{t("dashboard.recordUpdated", { name: item.reference ?? item.name })}
</button>
<p className="text-xs text-muted-foreground">
{item.companyName}
{item.actorName ? ` · ${item.actorName}` : ""}
</p>
</div>
</li>
);
})}
</ol>
</BlockState>
</DashboardPanel>
);
}