mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 22:11:24 -05:00
Implement persistent lock state
This commit is contained in:
@@ -162,6 +162,81 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Restore active lock from database on mount
|
||||
const restoreActiveLock = useCallback(async () => {
|
||||
if (!user?.id) return;
|
||||
|
||||
try {
|
||||
// Query for any active lock assigned to current user
|
||||
const { data, error } = await supabase
|
||||
.from('content_submissions')
|
||||
.select('id, locked_until')
|
||||
.eq('assigned_to', user.id)
|
||||
.gt('locked_until', new Date().toISOString())
|
||||
.in('status', ['pending', 'partially_approved'])
|
||||
.order('locked_until', { ascending: false })
|
||||
.limit(1)
|
||||
.maybeSingle();
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const expiresAt = new Date(data.locked_until || '');
|
||||
|
||||
// Only restore if lock hasn't expired (race condition check)
|
||||
if (data.locked_until && expiresAt > new Date()) {
|
||||
setCurrentLock({
|
||||
submissionId: data.id,
|
||||
expiresAt,
|
||||
});
|
||||
|
||||
// Start countdown timer for restored lock
|
||||
startLockTimer(expiresAt);
|
||||
|
||||
console.log('Lock state restored from database', {
|
||||
submissionId: data.id,
|
||||
expiresAt: expiresAt.toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
// Log but don't show user toast (they haven't taken any action yet)
|
||||
console.debug('Failed to restore lock state', {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
userId: user.id,
|
||||
});
|
||||
}
|
||||
}, [user, startLockTimer]);
|
||||
|
||||
// Initialize lock state from database on mount
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
|
||||
restoreActiveLock();
|
||||
}, [user, restoreActiveLock]);
|
||||
|
||||
// Sync lock state across tabs when user returns to the page
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
// User returned to tab - check if lock state is still valid
|
||||
if (!currentLock) {
|
||||
restoreActiveLock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, [user, currentLock, restoreActiveLock]);
|
||||
|
||||
// Claim a specific submission (CRM-style claim any)
|
||||
const extendLock = useCallback(async (submissionId: string): Promise<boolean> => {
|
||||
if (!user?.id) return false;
|
||||
@@ -323,6 +398,16 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if user already has an active lock on a different submission
|
||||
if (currentLock && currentLock.submissionId !== submissionId) {
|
||||
toast({
|
||||
title: 'Already Have Active Lock',
|
||||
description: 'Release your current lock before claiming another submission',
|
||||
variant: 'destructive',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
// Get submission details FIRST for better toast message
|
||||
|
||||
Reference in New Issue
Block a user