Implement claim and freeze system for moderation queue

Refactors the moderation queue to implement a "claim and freeze" model, preventing automatic updates during background polling and enforcing claim/lock isolation. Adds a `claimSubmission` function to `useModerationQueue` and modifies `ModerationQueue.tsx` to filter submissions based on claim status and update handling.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: e14c2292-b0e5-43fe-b301-a4ad668949e9
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
pac7
2025-10-08 14:48:15 +00:00
parent fb10642fed
commit 0050032681
2 changed files with 143 additions and 19 deletions

View File

@@ -305,6 +305,60 @@ export const useModerationQueue = () => {
}
}, [user, toast, fetchStats]);
// Claim a specific submission (CRM-style claim any)
const claimSubmission = useCallback(async (submissionId: string): Promise<boolean> => {
if (!user?.id) {
toast({
title: 'Authentication Required',
description: 'You must be logged in to claim submissions',
variant: 'destructive',
});
return false;
}
setIsLoading(true);
try {
const expiresAt = new Date(Date.now() + 15 * 60 * 1000);
const { error } = await supabase
.from('content_submissions')
.update({
assigned_to: user.id,
assigned_at: new Date().toISOString(),
locked_until: expiresAt.toISOString(),
})
.eq('id', submissionId)
.or(`assigned_to.is.null,locked_until.lt.${new Date().toISOString()}`); // Only if unclaimed or lock expired
if (error) throw error;
setCurrentLock({
submissionId,
expiresAt,
});
startLockTimer(expiresAt);
fetchStats();
toast({
title: 'Submission Claimed',
description: 'You now have 15 minutes to review this submission',
});
return true;
} catch (error: any) {
console.error('Error claiming submission:', error);
toast({
title: 'Error',
description: error.message || 'Failed to claim submission',
variant: 'destructive',
});
return false;
} finally {
setIsLoading(false);
}
}, [user, toast, startLockTimer, fetchStats]);
// Reassign submission
const reassignSubmission = useCallback(async (submissionId: string, newModeratorId: string): Promise<boolean> => {
if (!user?.id) return false;
@@ -355,6 +409,7 @@ export const useModerationQueue = () => {
queueStats,
isLoading,
claimNext,
claimSubmission,
extendLock,
releaseLock,
getTimeRemaining,