import { Button } from "@repo/shadcn-ui/components/button"; import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action"; import { StatisticCard } from "@repo/shadcn-ui/components/statistic-card"; import { BoxIcon, Building2Icon, ChevronRightIcon, ClockIcon, DatabaseIcon, FileKeyIcon, LaptopIcon, TicketIcon, TriangleAlertIcon, UserRoundXIcon, UsersIcon, WrenchIcon, } from "@repo/shadcn-ui/lib/icons"; import { useQuery } from "@tanstack/react-query"; import type { ReactNode } from "react"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import type { DashboardIssue } from "../../common/dashboard"; import { companyApi, companyKeys } from "../api/company-api"; import { type DashboardNavigation, dashboardApi, dashboardKeys, entryDestination, } from "./dashboard-api"; import { BlockState } from "./dashboard-block"; import { DashboardDetailsDialog } from "./dashboard-details-dialog"; import { DashboardQuickCreate } from "./dashboard-quick-create"; const ISSUE_ICONS = { certificate: FileKeyIcon, license: FileKeyIcon, profile: UsersIcon, missing_site: BoxIcon, inactive_person: UserRoundXIcon, }; const KIND_ICONS = { ticket: TicketIcon, intervention: WrenchIcon, asset: LaptopIcon, resource: DatabaseIcon, person: UsersIcon, profile: UsersIcon, }; export function DashboardPage({ onNavigate, csrfToken, }: { onNavigate: (destination: DashboardNavigation) => void; csrfToken: string; }) { const { t, i18n } = useTranslation("companies"); const [companyId, setCompanyId] = useState(""); const scope = companyId || undefined; const [details, setDetails] = useState<{ kind?: "asset" | "resource"; issue?: DashboardIssue; work?: boolean; activity?: boolean; companies?: boolean; }>(); const [quick, setQuick] = useState< "company" | "ticket" | "intervention" | "asset" | "resource" >(); const companies = useQuery({ queryKey: companyKeys.list, queryFn: companyApi.list }); const summary = useQuery({ queryKey: dashboardKeys.block("summary", scope), queryFn: ({ signal }) => dashboardApi.summary(signal, scope), staleTime: 0, }); const work = useQuery({ queryKey: dashboardKeys.block("work", scope), queryFn: ({ signal }) => dashboardApi.work(signal, scope), staleTime: 0, }); const attention = useQuery({ queryKey: dashboardKeys.block("attention", scope), queryFn: ({ signal }) => dashboardApi.attention(signal, scope), staleTime: 0, }); const activity = useQuery({ queryKey: dashboardKeys.block("activity", scope), queryFn: ({ signal }) => dashboardApi.activity(signal, scope), staleTime: 0, }); const totals = useQuery({ queryKey: dashboardKeys.block("companies", scope), queryFn: ({ signal }) => dashboardApi.companies(signal, scope), staleTime: 0, }); const date = (value: string | null) => value ? new Intl.DateTimeFormat(i18n.language, { dateStyle: "medium", timeStyle: "short" }).format( new Date(value) ) : "—"; const statStatus = summary.isPending ? t("loading") : summary.isError ? t("dashboard.blockError") : undefined; const kpis = [ { key: "companies", label: "activeCompanies", Icon: Building2Icon, tone: "teal", action: () => onNavigate({ area: "directory", companyId: scope, activeOnly: true }), }, { key: "tickets", label: "openTickets", Icon: TicketIcon, tone: "rose", action: () => onNavigate({ area: "tickets", companyId: scope, pendingOnly: true }), }, { key: "interventions", label: "pendingInterventions", Icon: WrenchIcon, tone: "amber", action: () => onNavigate({ area: "interventions", companyId: scope, pendingOnly: true }), }, { key: "assets", label: "registeredAssets", Icon: LaptopIcon, tone: "green", action: () => setDetails({ kind: "asset" }), }, { key: "resources", label: "registeredResources", Icon: DatabaseIcon, tone: "violet", action: () => setDetails({ kind: "resource" }), }, ] as const; return (

{t("dashboard.title")}

{t("dashboard.description")}

({ value: item.id, label: item.name })) ?? []), ]} placeholder={t("interventions.allCompanies")} value={companyId} /> {summary.isSuccess && (

)}
{kpis.map(({ key, label, Icon, tone, action }) => ( } key={key} label={t(`dashboard.${label}`)} onClick={action} status={statStatus} tone={tone} value={summary.isError ? undefined : summary.data?.[key]} /> ))}
setDetails({ work: true })} icon={} title={t("dashboard.pendingWork")} >
{[ t("dashboard.type"), t("tickets.reference"), t("tickets.subject"), t("tickets.company"), t("tickets.priority"), t("tickets.state"), ].map((label) => ( ))} {work.data?.items.slice(0, 6).map((item) => { const Icon = KIND_ICONS[item.kind]; return ( ); })}
{t("dashboard.pendingWork")}
{label}
{item.name} {item.companyName} {item.priority ? ( {t(`tickets.priorities.${item.priority}`)} ) : ( "—" )} {t( (item.kind === "ticket" ? "tickets.states." : "interventions.states.") + item.state )}
} title={t("dashboard.attention")} >
    {attention.data?.items.map((item) => { const Icon = ISSUE_ICONS[item.kind]; return (
  • ); })}
setDetails({ activity: true })} icon={} title={t("dashboard.recentActivity")} >
    {activity.data?.items.slice(0, 4).map((item) => { const Icon = KIND_ICONS[item.kind]; return (
  1. ); })}
setDetails({ companies: true })} icon={} title={t("dashboard.companySummary")} >
{[ t("tickets.company"), t("dashboard.openTickets"), t("dashboard.pendingInterventions"), t("dashboard.registeredAssets"), t("people"), ].map((label) => ( ))} {totals.data?.items.slice(0, 5).map((item) => ( ))}
{t("dashboard.companySummary")}
{label}
{(["ticket", "intervention", "company", "asset", "resource"] as const).map((kind) => { const Icon = kind === "company" ? Building2Icon : KIND_ICONS[kind]; return ( ); })}
{details && ( setDetails(undefined)} onNavigate={onNavigate} /> )} {quick && ( setQuick(undefined)} onNavigate={onNavigate} /> )}
); } function DashboardPanel({ title, icon, action, children, }: { title: string; icon?: ReactNode; action?: () => void; children: ReactNode; }) { const { t } = useTranslation("companies"); return (

{icon && ( )} {title}

{action && ( )}
{children}
); }