From fcfe09ac1d0dc86fbed8805bad2bdf05709d6c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Mon, 30 Mar 2026 13:26:54 +0200 Subject: [PATCH] fix(web): open project demand strips in demand popover --- .../timeline/TimelineProjectPanel.tsx | 20 +++++++++++++++++-- .../components/timeline/TimelineTooltip.tsx | 12 +++++++++-- .../src/components/timeline/TimelineView.tsx | 4 +++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/timeline/TimelineProjectPanel.tsx b/apps/web/src/components/timeline/TimelineProjectPanel.tsx index d67515f..c7d10c9 100644 --- a/apps/web/src/components/timeline/TimelineProjectPanel.tsx +++ b/apps/web/src/components/timeline/TimelineProjectPanel.tsx @@ -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 */}
Requested
-
{demandHover.requestedHeadcount}
+
+ {demandHover.requestedHeadcount} {demandHover.requestedHeadcount === 1 ? "seat" : "seats"} +
Open
-
{demandHover.unfilledHeadcount}
+
+ {demandHover.unfilledHeadcount} {demandHover.unfilledHeadcount === 1 ? "seat" : "seats"} +
Range
@@ -153,6 +157,10 @@ export function TimelineTooltip({
) : null}
+ +
+ Click for details and actions +
, ); } diff --git a/apps/web/src/components/timeline/TimelineView.tsx b/apps/web/src/components/timeline/TimelineView.tsx index 6c7240f..17b0a24 100644 --- a/apps/web/src/components/timeline/TimelineView.tsx +++ b/apps/web/src/components/timeline/TimelineView.tsx @@ -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}