"use client"; import { createPortal } from "react-dom"; import { useEffect, useMemo, useRef, useState, type ReactNode, type UIEvent } from "react"; import { trpc } from "~/lib/trpc/client.js"; import type { WidgetProps } from "~/components/dashboard/widget-registry.js"; import { InfoTooltip } from "~/components/ui/InfoTooltip.js"; import { AnimatedNumber } from "~/components/ui/AnimatedNumber.js"; import { WidgetFilterBar, type WidgetFilter } from "~/components/dashboard/WidgetFilterBar.js"; import { useWidgetFilterOptions } from "~/hooks/useWidgetFilterOptions.js"; import { useReferenceData } from "~/hooks/useReferenceData.js"; import { useAnchoredOverlay } from "~/hooks/useAnchoredOverlay.js"; function UtilizationBar({ percent }: { percent: number }) { const barColor = percent >= 80 ? "bg-green-500" : percent >= 50 ? "bg-amber-500" : "bg-red-500"; return (
Period: {month}
Countries
{selectedCountryIds.length > 0 ? ( ) : null}Empty selection means all countries are included.
No data available.
) : (| # |
|
|
|
|---|---|---|---|
| {i + 1} |
{r.displayName}
{r.chapter && · {r.chapter}}
{showDetails ? |
{formatHours(r.derivation?.actualBookedHours)} / {formatHours(r.derivation?.effectiveAvailableHours)}
) : null}
|
{formatHours(r.derivation?.expectedBookedHours)} / {formatHours(r.derivation?.effectiveAvailableHours)}
) : null}
|
All resources at or near target.
) : (|
|
|
|
|---|---|---|
|
{r.displayName}
{r.chapter && · {r.chapter}}
{showDetails ? |
{formatHours(r.derivation?.actualBookedHours)} / {formatHours(r.derivation?.effectiveAvailableHours)}
) : null}
|
Target {formatHours(r.derivation?.targetBookedHours)} · Free {formatHours(r.derivation?.unassignedHours)}
) : null}
|