Files
thrilltrack-explorer/src-old/lib/moderation/lockMonitor.ts

111 lines
3.1 KiB
TypeScript

/**
* Moderation Lock Monitor
*
* Monitors lock expiry and provides automatic renewal prompts for moderators.
* Prevents loss of work due to expired locks.
*/
import { useEffect } from 'react';
import type { ModerationState } from '../moderationStateMachine';
import type { ModerationAction } from '../moderationStateMachine';
import { hasActiveLock, needsLockRenewal } from '../moderationStateMachine';
import { toast } from '@/hooks/use-toast';
import { supabase } from '@/lib/supabaseClient';
import { handleNonCriticalError } from '../errorHandler';
/**
* Hook to monitor lock status and warn about expiry
*
* @param state - Current moderation state
* @param dispatch - State machine dispatch function
* @param itemId - ID of the locked item (optional, for manual extension)
* @returns Extension function to manually extend lock
*/
export function useLockMonitor(
state: ModerationState,
dispatch: React.Dispatch<ModerationAction>,
itemId?: string
): { extendLock: () => Promise<void> } {
useEffect(() => {
if (!hasActiveLock(state)) {
return;
}
const checkInterval = setInterval(() => {
if (needsLockRenewal(state)) {
// Dispatch lock expiry warning
dispatch({ type: 'LOCK_EXPIRED' });
// Show toast with extension option
toast({
title: 'Lock Expiring Soon',
description: 'Your lock on this submission will expire in less than 2 minutes. Click below to extend.',
duration: Infinity,
});
// Also call extension function automatically after showing toast
if (itemId) {
setTimeout(() => {
handleExtendLock(itemId, dispatch);
}, 100);
}
}
}, 30000); // Check every 30 seconds
return () => clearInterval(checkInterval);
}, [state, dispatch, itemId]);
const extendLock = async () => {
if (itemId) {
await handleExtendLock(itemId, dispatch);
}
};
return { extendLock };
}
/**
* Extend the lock on a submission
*
* @param submissionId - Submission ID
* @param dispatch - State machine dispatch function
*/
export async function handleExtendLock(
submissionId: string,
dispatch: React.Dispatch<ModerationAction>
) {
try {
// Call Supabase to extend lock (assumes 15 minute extension)
const { error } = await supabase
.from('content_submissions')
.update({
locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
})
.eq('id', submissionId);
if (error) throw error;
// Update state machine with new lock time
dispatch({
type: 'LOCK_ACQUIRED',
payload: { lockExpires: new Date(Date.now() + 15 * 60 * 1000).toISOString() },
});
toast({
title: 'Lock Extended',
description: 'You have 15 more minutes to complete your review.',
});
} catch (error: unknown) {
handleNonCriticalError(error, {
action: 'Extend Lock',
metadata: { submissionId }
});
toast({
title: 'Extension Failed',
description: 'Could not extend lock. Please save your work and re-claim the item.',
variant: 'destructive',
});
}
}