diff --git a/frontend/src/components/calendar/EventDetailPanel.tsx b/frontend/src/components/calendar/EventDetailPanel.tsx index 0fe4b34..b656fbe 100644 --- a/frontend/src/components/calendar/EventDetailPanel.tsx +++ b/frontend/src/components/calendar/EventDetailPanel.tsx @@ -276,16 +276,15 @@ export default function EventDetailPanel({ refetchInterval: 5_000, }); - // Show/hide lock banner proactively in view mode + // Show/hide lock banner proactively in view mode (poll data always authoritative) useEffect(() => { - if (viewLockQuery.data && !isEditing && !isCreating) { - if (viewLockQuery.data.locked) { - setLockInfo(viewLockQuery.data); - } else { - setLockInfo(null); - } + if (!viewLockQuery.data) return; + if (viewLockQuery.data.locked) { + setLockInfo(viewLockQuery.data); + } else { + setLockInfo(null); } - }, [viewLockQuery.data, isEditing, isCreating]); + }, [viewLockQuery.data]); const isRecurring = !!(event?.is_recurring || event?.parent_event_id); @@ -581,8 +580,8 @@ export default function EventDetailPanel({ size="icon" className="h-7 w-7" onClick={handleEditStart} - disabled={isAcquiringLock} - title="Edit event" + disabled={isAcquiringLock || !!(lockInfo && lockInfo.locked)} + title={lockInfo && lockInfo.locked ? `Locked by ${lockInfo.locked_by_name || 'another user'}` : 'Edit event'} > {isAcquiringLock ? : } diff --git a/frontend/src/hooks/useEventLock.ts b/frontend/src/hooks/useEventLock.ts index 9c8d695..3495773 100644 --- a/frontend/src/hooks/useEventLock.ts +++ b/frontend/src/hooks/useEventLock.ts @@ -34,7 +34,7 @@ export function useEventLock(eventId: number | null) { if (!eventId) return null; const data = await acquireMutation.mutateAsync(eventId); return data; - }, [eventId]); + }, [eventId, acquireMutation]); const release = useCallback(async () => { const id = activeEventIdRef.current;