mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 23:51:13 -05:00
Implement complete roadmap
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useImperativeHandle, forwardRef, useMemo } from 'react';
|
||||
import { useState, useImperativeHandle, forwardRef, useMemo, useCallback } from 'react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { TooltipProvider } from '@/components/ui/tooltip';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
@@ -14,15 +14,18 @@ import { useModerationQueueManager } from '@/hooks/moderation';
|
||||
import { QueueItem } from './QueueItem';
|
||||
import { ModerationErrorBoundary } from '@/components/error/ModerationErrorBoundary';
|
||||
import { QueueSkeleton } from './QueueSkeleton';
|
||||
import { LockStatusDisplay } from './LockStatusDisplay';
|
||||
import { EnhancedLockStatusDisplay } from './EnhancedLockStatusDisplay';
|
||||
import { getLockStatus } from '@/lib/moderation/lockHelpers';
|
||||
import { QueueStats } from './QueueStats';
|
||||
import { QueueFilters } from './QueueFilters';
|
||||
import { ActiveFiltersDisplay } from './ActiveFiltersDisplay';
|
||||
import { AutoRefreshIndicator } from './AutoRefreshIndicator';
|
||||
import { NewItemsAlert } from './NewItemsAlert';
|
||||
import { EmptyQueueState } from './EmptyQueueState';
|
||||
import { EnhancedEmptyState } from './EnhancedEmptyState';
|
||||
import { QueuePagination } from './QueuePagination';
|
||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||
import { KeyboardShortcutsHelp } from './KeyboardShortcutsHelp';
|
||||
import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts';
|
||||
import { fetchSubmissionItems, type SubmissionItemWithDeps } from '@/lib/submissionItemsService';
|
||||
import type { ModerationQueueRef } from '@/types/moderation';
|
||||
import type { PhotoItem } from '@/types/photos';
|
||||
@@ -75,11 +78,68 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
|
||||
const [showItemEditDialog, setShowItemEditDialog] = useState(false);
|
||||
const [editingItem, setEditingItem] = useState<SubmissionItemWithDeps | null>(null);
|
||||
|
||||
// Confirmation dialog state
|
||||
const [confirmDialog, setConfirmDialog] = useState<{
|
||||
open: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
onConfirm: () => void;
|
||||
}>({
|
||||
open: false,
|
||||
title: '',
|
||||
description: '',
|
||||
onConfirm: () => {},
|
||||
});
|
||||
|
||||
// Keyboard shortcuts help dialog
|
||||
const [showShortcutsHelp, setShowShortcutsHelp] = useState(false);
|
||||
|
||||
// UI-specific handlers
|
||||
const handleNoteChange = (id: string, value: string) => {
|
||||
setNotes(prev => ({ ...prev, [id]: value }));
|
||||
};
|
||||
|
||||
// Wrapped delete with confirmation
|
||||
const handleDeleteSubmission = useCallback((item: any) => {
|
||||
setConfirmDialog({
|
||||
open: true,
|
||||
title: 'Delete Submission',
|
||||
description: 'Are you sure you want to permanently delete this submission? This action cannot be undone.',
|
||||
onConfirm: () => queueManager.deleteSubmission(item),
|
||||
});
|
||||
}, [queueManager]);
|
||||
|
||||
// Clear filters handler
|
||||
const handleClearFilters = useCallback(() => {
|
||||
queueManager.filters.clearFilters();
|
||||
}, [queueManager.filters]);
|
||||
|
||||
// Keyboard shortcuts
|
||||
const { shortcuts } = useKeyboardShortcuts({
|
||||
shortcuts: [
|
||||
{
|
||||
key: '?',
|
||||
handler: () => setShowShortcutsHelp(true),
|
||||
description: 'Show keyboard shortcuts',
|
||||
},
|
||||
{
|
||||
key: 'r',
|
||||
handler: () => queueManager.refresh(),
|
||||
description: 'Refresh queue',
|
||||
},
|
||||
{
|
||||
key: 'k',
|
||||
ctrlOrCmd: true,
|
||||
handler: () => {
|
||||
// Focus search/filter (if implemented)
|
||||
document.querySelector<HTMLInputElement>('[data-filter-search]')?.focus();
|
||||
},
|
||||
description: 'Focus filters',
|
||||
},
|
||||
],
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
const handleOpenPhotos = (photos: any[], index: number) => {
|
||||
setSelectedPhotos(photos);
|
||||
setSelectedPhotoIndex(index);
|
||||
@@ -135,14 +195,13 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
|
||||
<CardContent className="p-4">
|
||||
<div className="flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between">
|
||||
<QueueStats stats={queueManager.queue.queueStats} isMobile={isMobile} />
|
||||
<LockStatusDisplay
|
||||
<EnhancedLockStatusDisplay
|
||||
currentLock={queueManager.queue.currentLock}
|
||||
queueStats={queueManager.queue.queueStats}
|
||||
isLoading={queueManager.queue.isLoading}
|
||||
onExtendLock={queueManager.queue.extendLock}
|
||||
onReleaseLock={queueManager.queue.releaseLock}
|
||||
getTimeRemaining={queueManager.queue.getTimeRemaining}
|
||||
getLockProgress={queueManager.queue.getLockProgress}
|
||||
loading={queueManager.queue.isLoading}
|
||||
onExtendLock={() => queueManager.queue.extendLock(queueManager.queue.currentLock?.submissionId || '')}
|
||||
onReleaseLock={() => queueManager.queue.releaseLock(queueManager.queue.currentLock?.submissionId || '', false)}
|
||||
getCurrentTime={() => new Date()}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -192,9 +251,10 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
|
||||
{queueManager.loadingState === 'loading' || queueManager.loadingState === 'initial' ? (
|
||||
<QueueSkeleton count={queueManager.pagination.pageSize} />
|
||||
) : queueManager.items.length === 0 ? (
|
||||
<EmptyQueueState
|
||||
<EnhancedEmptyState
|
||||
entityFilter={queueManager.filters.entityFilter}
|
||||
statusFilter={queueManager.filters.statusFilter}
|
||||
onClearFilters={queueManager.filters.hasActiveFilters ? handleClearFilters : undefined}
|
||||
/>
|
||||
) : (
|
||||
<TooltipProvider>
|
||||
@@ -222,7 +282,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
|
||||
onOpenReviewManager={handleOpenReviewManager}
|
||||
onOpenItemEditor={handleOpenItemEditor}
|
||||
onClaimSubmission={queueManager.queue.claimSubmission}
|
||||
onDeleteSubmission={queueManager.deleteSubmission}
|
||||
onDeleteSubmission={handleDeleteSubmission}
|
||||
onInteractionFocus={(id) => queueManager.markInteracting(id, true)}
|
||||
onInteractionBlur={(id) => queueManager.markInteracting(id, false)}
|
||||
/>
|
||||
@@ -274,6 +334,24 @@ export const ModerationQueue = forwardRef<ModerationQueueRef, ModerationQueuePro
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Confirmation Dialog */}
|
||||
<ConfirmationDialog
|
||||
open={confirmDialog.open}
|
||||
onOpenChange={(open) => setConfirmDialog(prev => ({ ...prev, open }))}
|
||||
title={confirmDialog.title}
|
||||
description={confirmDialog.description}
|
||||
onConfirm={confirmDialog.onConfirm}
|
||||
variant="destructive"
|
||||
confirmLabel="Delete"
|
||||
/>
|
||||
|
||||
{/* Keyboard Shortcuts Help */}
|
||||
<KeyboardShortcutsHelp
|
||||
open={showShortcutsHelp}
|
||||
onOpenChange={setShowShortcutsHelp}
|
||||
shortcuts={shortcuts}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user