72 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|