Refactor: Stabilize admin panel auto-refresh

This commit is contained in:
gpt-engineer-app[bot]
2025-10-06 19:31:15 +00:00
parent 71f497a001
commit d965d2c299

View File

@@ -80,6 +80,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
const [interactingWith, setInteractingWith] = useState<Set<string>>(new Set()); const [interactingWith, setInteractingWith] = useState<Set<string>>(new Set());
const [newItemsCount, setNewItemsCount] = useState(0); const [newItemsCount, setNewItemsCount] = useState(0);
const [isRefreshing, setIsRefreshing] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false);
const [profileCache, setProfileCache] = useState<Map<string, any>>(new Map());
const { toast } = useToast(); const { toast } = useToast();
const { isAdmin, isSuperuser } = useUserRole(); const { isAdmin, isSuperuser } = useUserRole();
const { user } = useAuth(); const { user } = useAuth();
@@ -109,8 +110,8 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
return; return;
} }
// Prevent duplicate requests // Prevent ANY refresh if one is in progress
if (isRefreshing && silent) { if (isRefreshing) {
console.log('⏭️ Skipping refresh - already in progress'); console.log('⏭️ Skipping refresh - already in progress');
return; return;
} }
@@ -377,7 +378,20 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
.select('user_id, username, display_name, avatar_url') .select('user_id, username, display_name, avatar_url')
.in('user_id', userIds); .in('user_id', userIds);
const profileMap = new Map(profiles?.map(p => [p.user_id, p]) || []); // Update profile cache with stable references
setProfileCache(prevCache => {
const newCache = new Map(prevCache);
profiles?.forEach(p => {
const existing = newCache.get(p.user_id);
// Only update if data actually changed
if (!existing || JSON.stringify(existing) !== JSON.stringify(p)) {
newCache.set(p.user_id, p);
}
});
return newCache;
});
const profileMap = profileCache;
// Combine and format items // Combine and format items
const formattedItems: ModerationItem[] = [ const formattedItems: ModerationItem[] = [
@@ -448,7 +462,7 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
addToTop: true, addToTop: true,
}); });
// If there are changes // Only update state if there are actual changes
if (mergeResult.hasChanges) { if (mergeResult.hasChanges) {
const actuallyNewItems = mergeResult.changes.added.length; const actuallyNewItems = mergeResult.changes.added.length;
@@ -458,30 +472,31 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
updated: mergeResult.changes.updated.length, updated: mergeResult.changes.updated.length,
removed: mergeResult.changes.removed.length, removed: mergeResult.changes.removed.length,
totalItems: mergeResult.items.length, totalItems: mergeResult.items.length,
protectedIds: Array.from(preserveInteraction ? interactingWith : new Set<string>()),
strategy: refreshStrategy,
preserveInteraction
}); });
// Filter out items user is interacting with // Only apply protection map if needed
const protectedIds = preserveInteraction ? interactingWith : new Set<string>(); let finalItems = mergeResult.items;
const mergedWithProtection = mergeResult.items.map(item => { if (preserveInteraction && interactingWith.size > 0) {
if (protectedIds.has(item.id)) { finalItems = mergeResult.items.map(item => {
// Find and preserve the current version of this item if (interactingWith.has(item.id)) {
const currentItem = items.find(i => i.id === item.id); const currentItem = items.find(i => i.id === item.id);
return currentItem || item; return currentItem || item;
} }
return item; return item;
}); });
}
setItems(mergedWithProtection); // Only call setItems if reference has actually changed
if (finalItems !== items) {
setItems(finalItems);
}
// Only set new items count if there are genuinely new items // Only set new items count if there are genuinely new items
if (actuallyNewItems > 0) { if (actuallyNewItems > 0) {
setNewItemsCount(actuallyNewItems); setNewItemsCount(actuallyNewItems);
} }
} else { } else {
// No changes detected - keep current state completely unchanged // No changes detected - skip all state updates
console.log('✅ No changes detected, keeping current state'); console.log('✅ No changes detected, keeping current state');
} }
} else { } else {