feat: Implement direct edit button for queue items

This commit is contained in:
gpt-engineer-app[bot]
2025-10-15 14:48:37 +00:00
parent 2071a4561b
commit 415aa45f4c
2 changed files with 52 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import { useUserRole } from '@/hooks/useUserRole';
import { useAuth } from '@/hooks/useAuth'; import { useAuth } from '@/hooks/useAuth';
import { PhotoModal } from './PhotoModal'; import { PhotoModal } from './PhotoModal';
import { SubmissionReviewManager } from './SubmissionReviewManager'; import { SubmissionReviewManager } from './SubmissionReviewManager';
import { ItemEditDialog } from './ItemEditDialog';
import { useIsMobile } from '@/hooks/use-mobile'; import { useIsMobile } from '@/hooks/use-mobile';
import { useAdminSettings } from '@/hooks/useAdminSettings'; import { useAdminSettings } from '@/hooks/useAdminSettings';
import { useModerationQueueManager } from '@/hooks/moderation'; import { useModerationQueueManager } from '@/hooks/moderation';
@@ -20,6 +21,7 @@ import { AutoRefreshIndicator } from './AutoRefreshIndicator';
import { NewItemsAlert } from './NewItemsAlert'; import { NewItemsAlert } from './NewItemsAlert';
import { EmptyQueueState } from './EmptyQueueState'; import { EmptyQueueState } from './EmptyQueueState';
import { QueuePagination } from './QueuePagination'; import { QueuePagination } from './QueuePagination';
import { fetchSubmissionItems, type SubmissionItemWithDeps } from '@/lib/submissionItemsService';
import type { ModerationQueueRef } from '@/types/moderation'; import type { ModerationQueueRef } from '@/types/moderation';
import type { PhotoItem } from '@/types/photos'; import type { PhotoItem } from '@/types/photos';
@@ -62,6 +64,8 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(0); const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(0);
const [reviewManagerOpen, setReviewManagerOpen] = useState(false); const [reviewManagerOpen, setReviewManagerOpen] = useState(false);
const [selectedSubmissionId, setSelectedSubmissionId] = useState<string | null>(null); const [selectedSubmissionId, setSelectedSubmissionId] = useState<string | null>(null);
const [showItemEditDialog, setShowItemEditDialog] = useState(false);
const [editingItem, setEditingItem] = useState<SubmissionItemWithDeps | null>(null);
// UI-specific handlers // UI-specific handlers
const handleNoteChange = (id: string, value: string) => { const handleNoteChange = (id: string, value: string) => {
@@ -79,6 +83,36 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
setReviewManagerOpen(true); setReviewManagerOpen(true);
}; };
const handleOpenItemEditor = async (submissionId: string) => {
try {
const items = await fetchSubmissionItems(submissionId);
// Find first pending item, fallback to first available
let itemToEdit = items.find(item => item.status === 'pending');
if (!itemToEdit && items.length > 0) {
itemToEdit = items[0];
}
if (itemToEdit) {
setEditingItem(itemToEdit);
setShowItemEditDialog(true);
} else {
toast({
title: 'No Items Found',
description: 'This submission has no items to edit',
variant: 'destructive',
});
}
} catch (error) {
console.error('Error fetching items for edit:', error);
toast({
title: 'Error',
description: 'Failed to load submission items',
variant: 'destructive',
});
}
};
// Expose imperative API // Expose imperative API
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
refresh: async () => { refresh: async () => {
@@ -179,6 +213,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
onRetryFailed={queueManager.retryFailedItems} onRetryFailed={queueManager.retryFailedItems}
onOpenPhotos={handleOpenPhotos} onOpenPhotos={handleOpenPhotos}
onOpenReviewManager={handleOpenReviewManager} onOpenReviewManager={handleOpenReviewManager}
onOpenItemEditor={handleOpenItemEditor}
onClaimSubmission={queueManager.queue.claimSubmission} onClaimSubmission={queueManager.queue.claimSubmission}
onDeleteSubmission={queueManager.deleteSubmission} onDeleteSubmission={queueManager.deleteSubmission}
onInteractionFocus={(id) => queueManager.markInteracting(id, true)} onInteractionFocus={(id) => queueManager.markInteracting(id, true)}
@@ -218,6 +253,19 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
onComplete={() => setReviewManagerOpen(false)} onComplete={() => setReviewManagerOpen(false)}
/> />
)} )}
{editingItem && (
<ItemEditDialog
item={editingItem}
open={showItemEditDialog}
onOpenChange={setShowItemEditDialog}
onComplete={async () => {
setShowItemEditDialog(false);
setEditingItem(null);
await queueManager.refresh();
}}
/>
)}
</div> </div>
); );
}); });

View File

@@ -39,6 +39,7 @@ interface QueueItemProps {
onRetryFailed: (item: ModerationItem) => void; onRetryFailed: (item: ModerationItem) => void;
onOpenPhotos: (photos: any[], index: number) => void; onOpenPhotos: (photos: any[], index: number) => void;
onOpenReviewManager: (submissionId: string) => void; onOpenReviewManager: (submissionId: string) => void;
onOpenItemEditor: (submissionId: string) => void;
onClaimSubmission: (submissionId: string) => void; onClaimSubmission: (submissionId: string) => void;
onDeleteSubmission: (item: ModerationItem) => void; onDeleteSubmission: (item: ModerationItem) => void;
onInteractionFocus: (id: string) => void; onInteractionFocus: (id: string) => void;
@@ -75,6 +76,7 @@ export const QueueItem = memo(({
onRetryFailed, onRetryFailed,
onOpenPhotos, onOpenPhotos,
onOpenReviewManager, onOpenReviewManager,
onOpenItemEditor,
onClaimSubmission, onClaimSubmission,
onDeleteSubmission, onDeleteSubmission,
onInteractionFocus, onInteractionFocus,
@@ -430,7 +432,7 @@ export const QueueItem = memo(({
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
onClick={() => onOpenReviewManager(item.id)} onClick={() => onOpenItemEditor(item.id)}
disabled={actionLoading === item.id} disabled={actionLoading === item.id}
variant="ghost" variant="ghost"
className={isMobile ? 'h-11' : ''} className={isMobile ? 'h-11' : ''}
@@ -441,7 +443,7 @@ export const QueueItem = memo(({
</Button> </Button>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent> <TooltipContent>
<p>Edit submission items directly as a moderator</p> <p>Quick edit first pending item</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
)} )}