Fix admin dashboard auto-refresh

This commit is contained in:
gpt-engineer-app[bot]
2025-10-06 18:36:43 +00:00
parent b1112e6261
commit f5c59aa072
5 changed files with 176 additions and 10 deletions

View File

@@ -24,6 +24,7 @@ import { Progress } from '@/components/ui/progress';
import { QueueStatsDashboard } from './QueueStatsDashboard';
import { EscalationDialog } from './EscalationDialog';
import { ReassignDialog } from './ReassignDialog';
import { smartMergeArray } from '@/lib/smartStateUpdate';
interface ModerationItem {
id: string;
@@ -75,15 +76,24 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
const [escalationDialogOpen, setEscalationDialogOpen] = useState(false);
const [reassignDialogOpen, setReassignDialogOpen] = useState(false);
const [selectedItemForAction, setSelectedItemForAction] = useState<ModerationItem | null>(null);
const [interactingWith, setInteractingWith] = useState<Set<string>>(new Set());
const [newItemsCount, setNewItemsCount] = useState(0);
const { toast } = useToast();
const { isAdmin, isSuperuser } = useUserRole();
const { user } = useAuth();
const queue = useModerationQueue();
// Get admin settings for polling configuration
const { getAdminPanelRefreshMode, getAdminPanelPollInterval } = useAdminSettings();
const {
getAdminPanelRefreshMode,
getAdminPanelPollInterval,
getAutoRefreshStrategy,
getPreserveInteractionState
} = useAdminSettings();
const refreshMode = getAdminPanelRefreshMode();
const pollInterval = getAdminPanelPollInterval();
const refreshStrategy = getAutoRefreshStrategy();
const preserveInteraction = getPreserveInteractionState();
// Expose refresh method via ref
useImperativeHandle(ref, () => ({
@@ -346,7 +356,39 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
// Sort by creation date (newest first for better UX)
formattedItems.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
setItems(formattedItems);
// Use smart merging for silent refreshes if strategy is 'merge'
if (silent && refreshStrategy === 'merge') {
const mergeResult = smartMergeArray(items, formattedItems, {
compareFields: ['status', 'reviewed_at', 'reviewer_notes'],
preserveOrder: true,
addToTop: true,
});
// If there are changes and we should preserve interaction
if (mergeResult.hasChanges) {
// Filter out items user is interacting with
const protectedIds = preserveInteraction ? interactingWith : new Set<string>();
const mergedWithProtection = mergeResult.items.map(item => {
if (protectedIds.has(item.id)) {
// Find and preserve the current version of this item
const currentItem = items.find(i => i.id === item.id);
return currentItem || item;
}
return item;
});
setItems(mergedWithProtection);
// Update new items count
if (mergeResult.changes.added.length > 0) {
setNewItemsCount(prev => prev + mergeResult.changes.added.length);
}
}
} else {
// Full replacement for non-silent refreshes or 'replace' strategy
setItems(formattedItems);
setNewItemsCount(0);
}
} catch (error: any) {
console.error('Error fetching moderation items:', error);
console.error('Error details:', {
@@ -1985,6 +2027,24 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
</div>
)}
{/* New Items Notification */}
{newItemsCount > 0 && (
<div className="flex items-center justify-center">
<Button
variant="outline"
size="sm"
onClick={() => {
setNewItemsCount(0);
fetchItems(activeEntityFilter, activeStatusFilter, false);
}}
className="flex items-center gap-2 border-primary/50 bg-primary/5 hover:bg-primary/10"
>
<RefreshCw className="w-4 h-4" />
Show {newItemsCount} new {newItemsCount === 1 ? 'item' : 'items'}
</Button>
</div>
)}
{/* Queue Content */}
<QueueContent />