"use client"; import { clsx } from "clsx"; import { formatMoney } from "~/lib/format.js"; import { trpc } from "~/lib/trpc/client.js"; import { BudgetStatusBar } from "./BudgetStatusBar.js"; import { InfoTooltip } from "~/components/ui/InfoTooltip.js"; interface BudgetStatusCardProps { projectId: string; } const formatEur = (cents: number) => formatMoney(cents, "EUR", 2); function WarningIcon({ level }: { level: string }) { if (level === "critical") { return ( ); } if (level === "warning") { return ( ); } return ( ); } function getWarningRowStyle(level: string): string { if (level === "critical") return "bg-red-50 dark:bg-red-900/30 border border-red-100 dark:border-red-800 text-red-800 dark:text-red-400"; if (level === "warning") return "bg-orange-50 dark:bg-orange-900/30 border border-orange-100 dark:border-orange-800 text-orange-800 dark:text-orange-400"; return "bg-blue-50 dark:bg-blue-900/30 border border-blue-100 dark:border-blue-800 text-blue-800 dark:text-blue-400"; } export function BudgetStatusCard({ projectId }: BudgetStatusCardProps) { const { data, isLoading, error } = trpc.timeline.getBudgetStatus.useQuery({ projectId }); if (isLoading) { return (
{[0, 1, 2, 3].map((i) => (
))}
); } if (error) { return (

Failed to load budget status: {error.message}

); } if (!data) return null; const { budgetCents, allocatedCents, confirmedCents, proposedCents, remainingCents, winProbabilityWeightedCents, warnings, } = data; return (

Budget Status

{/* Progress bar */} {/* Numeric details grid */}

Total Budget

{formatEur(budgetCents)}

Confirmed

{formatEur(confirmedCents)}

Proposed

{formatEur(proposedCents)}

Remaining

{formatEur(remainingCents)}

{/* Win-probability weighted amount */}
Win-probability weighted cost: {formatEur(winProbabilityWeightedCents)}
{/* Warnings list */} {warnings.length > 0 && (

Warnings

{warnings.map((warning, idx) => (
{warning.message}
))}
)}
); }