"use client"; import { trpc } from "~/lib/trpc/client.js"; import { InfoTooltip } from "~/components/ui/InfoTooltip.js"; import { ProgressRing } from "~/components/ui/ProgressRing.js"; interface BalanceCardProps { resourceId: string; year?: number; compact?: boolean; } export function BalanceCard({ resourceId, year = new Date().getFullYear(), compact = false }: BalanceCardProps) { const { data: balance, isLoading } = trpc.entitlement.getBalanceDetail.useQuery( { resourceId, year }, { staleTime: 30_000 }, ); if (isLoading) { return (
); } if (!balance) return null; const pct = balance.entitlement > 0 ? Math.round((balance.taken / balance.entitlement) * 100) : 0; if (compact) { return (
{balance.remaining}d remaining · {balance.taken}d used of {balance.entitlement}d {balance.pending > 0 && ( <> · {balance.pending}d pending )}
); } const ringColor = pct > 90 ? "var(--color-red-500, #ef4444)" : pct >= 70 ? "var(--color-amber-500, #f59e0b)" : "var(--color-emerald-500, #10b981)"; const holidayBasisVariants = balance.deductionSummary?.holidayBasisVariants ?? []; const excludedHolidayCount = balance.deductionSummary?.excludedHolidayDates.length ?? 0; const excludedHolidayTooltip = (balance.vacations ?? []) .flatMap((vacation) => vacation.holidayDetails.map((detail) => `${detail.date} · ${detail.source}`)) .join("\n"); return (
{balance.remaining}d

Vacation Balance {year}

{balance.taken} of {balance.entitlement} days used

{balance.carryOver > 0 && ( +{balance.carryOver}d carried over )}
{/* Progress bar */}
{balance.pending > 0 && (
)}
{balance.sickDays > 0 && (

{balance.sickDays} sick day{balance.sickDays !== 1 ? "s" : ""} recorded (not deducted from annual leave)

)} {!!balance.deductionSummary && (balance.deductionSummary.approvedVacationCount > 0 || balance.deductionSummary.pendingVacationCount > 0) && (
Formula Vacation deductions: {balance.deductionSummary.approvedDeductedDays}d approved {balance.deductionSummary.pendingDeductedDays > 0 ? ` · ${balance.deductionSummary.pendingDeductedDays}d pending` : ""} Requested: {balance.deductionSummary.approvedRequestedDays + balance.deductionSummary.pendingRequestedDays}d {excludedHolidayCount > 0 && ( Excluded holidays: {excludedHolidayCount} {excludedHolidayTooltip.length > 0 && } )}
{holidayBasisVariants.length > 0 && (
Holiday basis: {holidayBasisVariants.join(" · ")}
)}
)}
); } function Stat({ label, value, color, tooltip }: { label: string; value: number; color: string; tooltip?: string }) { return (

{value}

{label}{tooltip && }

); }