fix(web): open project demand strips in demand popover

This commit is contained in:
2026-03-30 13:26:54 +02:00
parent 5a345cd2e4
commit fcfe09ac1d
3 changed files with 31 additions and 5 deletions
@@ -44,7 +44,7 @@ interface TimelineProjectPanelProps {
onRowMouseDown: (e: React.MouseEvent, info: RowMouseDownInfo) => void;
onRowTouchStart: (e: React.TouchEvent, info: RowMouseDownInfo) => void;
onOpenPanel: (projectId: string) => void;
onOpenDemandClick: (demand: OpenDemandAssignment) => void;
onOpenDemandClick: (demand: TimelineDemandEntry, anchorX: number, anchorY: number) => void;
onAllocationContextMenu: (
info: { allocationId: string; projectId: string },
anchorX: number,
@@ -911,7 +911,7 @@ function renderOpenDemandRow(
toLeft: (d: Date) => number,
toWidth: (s: Date, e: Date) => number,
rowGridLines: React.ReactNode,
_onOpenDemandClick: (demand: OpenDemandAssignment) => void,
onOpenDemandClick: (demand: TimelineDemandEntry, anchorX: number, anchorY: number) => void,
onAllocMouseDown: (e: React.MouseEvent, info: AllocMouseDownInfo) => void,
onAllocTouchStart: (e: React.TouchEvent, info: AllocMouseDownInfo) => void,
onAllocationContextMenu: (
@@ -1056,6 +1056,22 @@ function renderOpenDemandRow(
);
}}
onMouseMove={(e) => onDemandHoverMove(e, alloc)}
onClick={(e) => {
e.stopPropagation();
onOpenDemandClick(alloc, e.clientX, e.clientY);
}}
onKeyDown={(e) => {
if (e.key !== "Enter" && e.key !== " ") {
return;
}
e.preventDefault();
e.stopPropagation();
const rect = e.currentTarget.getBoundingClientRect();
onOpenDemandClick(alloc, rect.left + rect.width / 2, rect.top + rect.height / 2);
}}
role="button"
tabIndex={0}
aria-label={`Open demand details for ${roleName} on ${alloc.project.name}`}
>
{/* Left resize handle */}
<div
@@ -117,11 +117,15 @@ export function TimelineTooltip({
<div className="mt-2 grid grid-cols-2 gap-x-4 gap-y-1.5 text-[11px]">
<div>
<div className="text-gray-500">Requested</div>
<div className="font-medium text-gray-100">{demandHover.requestedHeadcount}</div>
<div className="font-medium text-gray-100">
{demandHover.requestedHeadcount} {demandHover.requestedHeadcount === 1 ? "seat" : "seats"}
</div>
</div>
<div>
<div className="text-gray-500">Open</div>
<div className="font-medium text-amber-300">{demandHover.unfilledHeadcount}</div>
<div className="font-medium text-amber-300">
{demandHover.unfilledHeadcount} {demandHover.unfilledHeadcount === 1 ? "seat" : "seats"}
</div>
</div>
<div>
<div className="text-gray-500">Range</div>
@@ -153,6 +157,10 @@ export function TimelineTooltip({
</div>
) : null}
</div>
<div className="mt-2 border-t border-gray-800/90 pt-2 text-[10px] uppercase tracking-[0.14em] text-gray-500">
Click for details and actions
</div>
</div>,
);
}
@@ -706,7 +706,9 @@ function TimelineViewContent({
onRowMouseDown={isSelfServiceTimeline ? () => undefined : onRowMouseDown}
onRowTouchStart={isSelfServiceTimeline ? () => undefined : onRowTouchStart}
onOpenPanel={isSelfServiceTimeline ? () => undefined : setOpenPanelProjectId}
onOpenDemandClick={isSelfServiceTimeline ? () => undefined : setOpenDemandToAssign}
onOpenDemandClick={isSelfServiceTimeline ? () => undefined : (demand, anchorX, anchorY) => {
setDemandPopover({ demand, x: anchorX, y: anchorY });
}}
onAllocationContextMenu={isSelfServiceTimeline ? () => undefined : openAllocationPopoverAt}
CELL_WIDTH={CELL_WIDTH}
dates={dates}