diff --git a/frontend/src/components/calendar/EventDetailPanel.tsx b/frontend/src/components/calendar/EventDetailPanel.tsx
index b656fbe..8362a1f 100644
--- a/frontend/src/components/calendar/EventDetailPanel.tsx
+++ b/frontend/src/components/calendar/EventDetailPanel.tsx
@@ -264,6 +264,7 @@ export default function EventDetailPanel({
const [locationSearch, setLocationSearch] = useState('');
// Poll lock status in view mode for shared events (Stream A: real-time lock awareness)
+ // lockInfo is only set from the 423 error path; poll data (viewLockQuery.data) is used directly.
const viewLockQuery = useQuery({
queryKey: ['event-lock', event?.id],
queryFn: async () => {
@@ -274,18 +275,22 @@ export default function EventDetailPanel({
},
enabled: !!isSharedEvent && !!event && typeof event.id === 'number' && !isEditing && !isCreating,
refetchInterval: 5_000,
+ refetchIntervalInBackground: true,
+ refetchOnMount: 'always',
});
- // Show/hide lock banner proactively in view mode (poll data always authoritative)
+ // Clear 423-error lockInfo when poll confirms lock is gone
useEffect(() => {
- if (!viewLockQuery.data) return;
- if (viewLockQuery.data.locked) {
- setLockInfo(viewLockQuery.data);
- } else {
+ if (viewLockQuery.data && !viewLockQuery.data.locked) {
setLockInfo(null);
}
}, [viewLockQuery.data]);
+ // Derived: authoritative lock state — poll data wins, 423 error lockInfo as fallback
+ const activeLockInfo: EventLockInfo | null =
+ (viewLockQuery.data?.locked ? viewLockQuery.data : null) ??
+ (lockInfo?.locked ? lockInfo : null);
+
const isRecurring = !!(event?.is_recurring || event?.parent_event_id);
// Permission helpers
@@ -580,8 +585,8 @@ export default function EventDetailPanel({
size="icon"
className="h-7 w-7"
onClick={handleEditStart}
- disabled={isAcquiringLock || !!(lockInfo && lockInfo.locked)}
- title={lockInfo && lockInfo.locked ? `Locked by ${lockInfo.locked_by_name || 'another user'}` : 'Edit event'}
+ disabled={isAcquiringLock || !!activeLockInfo}
+ title={activeLockInfo ? `Locked by ${activeLockInfo.locked_by_name || 'another user'}` : 'Edit event'}
>
{isAcquiringLock ?