"use client";
import type { TimelineDemandEntry } from "./TimelineContext.js";
import { formatCents, formatDateLong } from "~/lib/format.js";
import { useViewportPopover } from "~/hooks/useViewportPopover.js";
interface DemandPopoverProps {
demand: TimelineDemandEntry;
onClose: () => void;
onOpenPanel: (projectId: string) => void;
onFillDemand: (demand: TimelineDemandEntry) => void;
anchorX: number;
anchorY: number;
}
export function DemandPopover({
demand,
onClose,
onOpenPanel,
onFillDemand,
anchorX,
anchorY,
}: DemandPopoverProps) {
const { ref, style } = useViewportPopover({
anchor: { kind: "point", x: anchorX, y: anchorY },
width: 300,
estimatedHeight: 340,
onClose,
});
const roleName = demand.roleEntity?.name ?? demand.role ?? "Unspecified";
const roleColor = demand.roleEntity?.color ?? "#f59e0b";
const startDate = new Date(demand.startDate);
const endDate = new Date(demand.endDate);
const days = Math.max(1, Math.round((endDate.getTime() - startDate.getTime()) / 86_400_000) + 1);
const totalHours = demand.hoursPerDay * days;
const budgetCents = demand.dailyCostCents * days;
return (
{/* Header */}
{/* Project */}
Project:{" "}
{demand.project.name}
{" "}
({demand.project.shortCode})
{/* Status badge */}
Open Demand
{demand.status}
{/* Headcount */}
Requested
{demand.requestedHeadcount} {demand.requestedHeadcount === 1 ? "person" : "people"}
Unfilled
{demand.unfilledHeadcount} remaining
{/* Date range */}
Start
{formatDateLong(startDate)}
End
{formatDateLong(endDate)}
{/* Hours */}
Hours / day
{demand.hoursPerDay}h
Total hours
{totalHours}h ({days}d)
{/* Budget */}
{budgetCents > 0 && (
<>
Daily cost
{formatCents(demand.dailyCostCents)} EUR
Total cost
{formatCents(budgetCents)} EUR
>
)}
{/* Percentage */}
{demand.percentage > 0 && (
Percentage
{demand.percentage}%
)}
{/* Actions */}
{demand.unfilledHeadcount > 0 && (
)}
);
}