From e1e8fa2ddc4a7e7b8ced19e3144e91102b707d52 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:58:21 +0000 Subject: [PATCH] Fix auto-refresh and queue claiming --- src/components/moderation/ModerationQueue.tsx | 61 ++++++++++++++----- ...3_5aea811b-4e27-4338-8872-5f6a5a79de0c.sql | 47 ++++++++++++++ 2 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 supabase/migrations/20251006185633_5aea811b-4e27-4338-8872-5f6a5a79de0c.sql diff --git a/src/components/moderation/ModerationQueue.tsx b/src/components/moderation/ModerationQueue.tsx index 07fe48ca..6140aa46 100644 --- a/src/components/moderation/ModerationQueue.tsx +++ b/src/components/moderation/ModerationQueue.tsx @@ -7,11 +7,12 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Textarea } from '@/components/ui/textarea'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { supabase } from '@/integrations/supabase/client'; import { useToast } from '@/hooks/use-toast'; import { useUserRole } from '@/hooks/useUserRole'; import { useAuth } from '@/hooks/useAuth'; -import { format } from 'date-fns'; +import { format, formatDistance } from 'date-fns'; import { PhotoModal } from './PhotoModal'; import { SubmissionReviewManager } from './SubmissionReviewManager'; import { useIsMobile } from '@/hooks/use-mobile'; @@ -366,6 +367,17 @@ export const ModerationQueue = forwardRef((props, ref) => { // If there are changes and we should preserve interaction if (mergeResult.hasChanges) { + // Debug logging for smart merge + console.log('🔄 Smart merge detected changes:', { + added: mergeResult.changes.added.length, + updated: mergeResult.changes.updated.length, + removed: mergeResult.changes.removed.length, + newItemsCount: mergeResult.changes.added.length, + protectedIds: Array.from(preserveInteraction ? interactingWith : new Set()), + strategy: refreshStrategy, + preserveInteraction + }); + // Filter out items user is interacting with const protectedIds = preserveInteraction ? interactingWith : new Set(); const mergedWithProtection = mergeResult.items.map(item => { @@ -2027,21 +2039,40 @@ export const ModerationQueue = forwardRef((props, ref) => { )} - {/* New Items Notification */} + {/* Auto-refresh Status Indicator */} + {refreshMode === 'auto' && ( +
+
+
+ Auto-refresh active +
+ • + Checking every {Math.round(pollInterval / 1000)}s +
+ )} + + {/* New Items Notification - Enhanced */} {newItemsCount > 0 && ( -
- +
+ + + New Items Available + + {newItemsCount} new {newItemsCount === 1 ? 'submission' : 'submissions'} pending review + + +
)} diff --git a/supabase/migrations/20251006185633_5aea811b-4e27-4338-8872-5f6a5a79de0c.sql b/supabase/migrations/20251006185633_5aea811b-4e27-4338-8872-5f6a5a79de0c.sql new file mode 100644 index 00000000..3b6f01e2 --- /dev/null +++ b/supabase/migrations/20251006185633_5aea811b-4e27-4338-8872-5f6a5a79de0c.sql @@ -0,0 +1,47 @@ +-- Fix ambiguous column reference in claim_next_submission +CREATE OR REPLACE FUNCTION public.claim_next_submission( + moderator_id UUID, + lock_duration INTERVAL DEFAULT '15 minutes' +) +RETURNS TABLE ( + submission_id UUID, + submission_type TEXT, + priority INTEGER, + waiting_time INTERVAL +) +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = public +AS $$ +BEGIN + -- Update priority for all pending submissions first + UPDATE content_submissions + SET priority = calculate_submission_priority(id) + WHERE status IN ('pending', 'partially_approved') + AND (assigned_to IS NULL OR locked_until < NOW()); + + -- Claim next item with row-level lock + RETURN QUERY + UPDATE content_submissions + SET + assigned_to = moderator_id, + assigned_at = NOW(), + locked_until = NOW() + lock_duration, + first_reviewed_at = COALESCE(first_reviewed_at, NOW()) + WHERE id = ( + SELECT cs.id FROM content_submissions cs + WHERE cs.status IN ('pending', 'partially_approved') + AND (cs.assigned_to IS NULL OR cs.locked_until < NOW()) + ORDER BY + cs.priority DESC, + cs.submitted_at ASC + LIMIT 1 + FOR UPDATE SKIP LOCKED + ) + RETURNING + content_submissions.id, + content_submissions.submission_type, + content_submissions.priority, + NOW() - content_submissions.submitted_at; +END; +$$; \ No newline at end of file