"use client"; import { useMemo } from "react"; import Link from "next/link"; import { trpc } from "~/lib/trpc/client.js"; import type { WidgetProps } from "~/components/dashboard/widget-registry.js"; import { InfoTooltip } from "~/components/ui/InfoTooltip.js"; import { ShoringBadge } from "~/components/projects/ShoringIndicator.js"; import { WidgetFilterBar, type WidgetFilter } from "~/components/dashboard/WidgetFilterBar.js"; import { useWidgetFilterOptions } from "~/hooks/useWidgetFilterOptions.js"; function healthDot(value: number): string { if (value >= 70) return "bg-green-500"; if (value >= 40) return "bg-amber-400"; return "bg-red-500"; } function scoreBadge(score: number): string { if (score >= 70) return "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300"; if (score >= 40) return "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300"; return "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300"; } export function ProjectHealthWidget({ config, onConfigChange }: WidgetProps) { const { clients } = useWidgetFilterOptions(); const filters = useMemo( () => [ { type: "search", key: "search", placeholder: "Search project..." }, { type: "select", key: "clientId", label: "Client", options: clients }, ], [clients], ); const { data, isLoading } = trpc.dashboard.getProjectHealth.useQuery( undefined, { staleTime: 60_000, placeholderData: (prev) => prev }, ); const search = ((config.search as string) ?? "").toLowerCase(); const clientId = (config.clientId as string) ?? ""; const rows = useMemo(() => { const all = data ?? []; return all.filter((r) => { if (search && !r.projectName.toLowerCase().includes(search) && !r.shortCode.toLowerCase().includes(search)) return false; if (clientId && r.clientId !== clientId) return false; return true; }); }, [data, search, clientId]); if (isLoading && !data) { return (
{[...Array(5)].map((_, i) => (
))}
); } if (rows.length === 0) { return (
{})} />
No active projects found.
); } return (
{})} />
{rows.map((row) => ( ))}
Project B / S / T Shoring Score
{row.shortCode} {row.projectName}
{row.compositeScore}
); }