EventGantt: suppress click-on-bar that fires right after drag
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Without this, dragging a bar fired mouseup → onClick in the same tick,
opening the edit popover with stale (pre-mutation) year values. The
PATCH succeeded but the popover showed the old year_start until React
Query refetched. Adding a 250ms debounce after drag-end before
re-enabling click-to-edit.

Tests + build green.
This commit is contained in:
Viktor Barzin 2026-05-10 18:12:04 +00:00
parent 9fd8389c26
commit f9084d1a15

View file

@ -151,6 +151,11 @@ function Inner({
// Pixel-level offset applied during drag (without committing).
const [dragOffset, setDragOffset] = useState<{ id: number; dx: number; mode: DragMode } | null>(null);
const [popover, setPopover] = useState<PopoverState | null>(null);
// Timestamp of the most recent drag-end. We use it to suppress the
// synchronous `onClick` that fires on `mouseup` after a successful
// drag — that click would otherwise open the edit popover with stale
// (pre-drag) field values, since React Query hasn't re-fetched yet.
const lastDragEnd = useRef<number>(0);
useEffect(() => {
const onMove = (e: MouseEvent) => {
@ -169,6 +174,7 @@ function Inner({
drag.current = null;
setDragOffset(null);
if (Math.abs(dyears) < 1) return; // sub-year drag = ignore
lastDragEnd.current = performance.now();
let body: LifeEventPatchBody = {};
if (mode === 'move') {
const newStart = clamp(origYearStart + dyears, 0, horizonYears - 1);
@ -224,6 +230,9 @@ function Inner({
const onBarClick = (e: React.MouseEvent, ev: LifeEvent) => {
e.stopPropagation();
// Suppress the click that fires immediately after a drag — the
// popover would otherwise open with stale (pre-mutation) values.
if (performance.now() - lastDragEnd.current < 250) return;
const point = localPoint(e);
if (!point) return;
setPopover({ kind: 'edit', x: point.x, y: point.y, event: ev });