mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 13:31:12 -05:00
Reverted to commit be92deec43
This commit is contained in:
@@ -128,8 +128,6 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
const fetchItemsRef = useRef<((silent?: boolean) => Promise<void>) | null>(null);
|
||||
|
||||
const FETCH_COOLDOWN_MS = 1000;
|
||||
const EFFECT_DEBOUNCE_MS = 50; // Short debounce to let all effects settle
|
||||
const effectFetchTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Store settings in refs to avoid re-creating fetchItems
|
||||
const settingsRef = useRef(settings);
|
||||
@@ -223,26 +221,9 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
status
|
||||
)
|
||||
`,
|
||||
);
|
||||
|
||||
// Validate sort field is an actual column in content_submissions
|
||||
const validSortFields = ['created_at', 'submission_type', 'status', 'escalated', 'submitted_at'];
|
||||
let sortField = sort.config.field;
|
||||
|
||||
if (!validSortFields.includes(sortField)) {
|
||||
console.warn('[Query] Invalid sort field:', sortField, '- falling back to created_at');
|
||||
sortField = 'created_at';
|
||||
}
|
||||
|
||||
console.log('[Query] Sorting by:', {
|
||||
field: sortField,
|
||||
direction: sort.config.direction,
|
||||
ascending: sort.config.direction === 'asc'
|
||||
});
|
||||
|
||||
// Apply sorting by user's chosen field only
|
||||
submissionsQuery = submissionsQuery
|
||||
.order(sortField, { ascending: sort.config.direction === 'asc' });
|
||||
)
|
||||
.order("escalated", { ascending: false })
|
||||
.order("created_at", { ascending: true });
|
||||
|
||||
// Apply tab-based status filtering
|
||||
const tab = filters.activeTab;
|
||||
@@ -250,20 +231,6 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
const entityFilter = filters.debouncedEntityFilter;
|
||||
|
||||
if (tab === "mainQueue") {
|
||||
// Main queue: non-escalated pending items
|
||||
submissionsQuery = submissionsQuery.eq("escalated", false);
|
||||
|
||||
if (statusFilter === "all") {
|
||||
submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||
} else if (statusFilter === "pending") {
|
||||
submissionsQuery = submissionsQuery.in("status", ["pending", "partially_approved"]);
|
||||
} else {
|
||||
submissionsQuery = submissionsQuery.eq("status", statusFilter);
|
||||
}
|
||||
} else if (tab === "escalated") {
|
||||
// Escalated queue: only escalated items
|
||||
submissionsQuery = submissionsQuery.eq("escalated", true);
|
||||
|
||||
if (statusFilter === "all") {
|
||||
submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||
} else if (statusFilter === "pending") {
|
||||
@@ -272,7 +239,6 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
submissionsQuery = submissionsQuery.eq("status", statusFilter);
|
||||
}
|
||||
} else {
|
||||
// Archive: completed items (non-escalated and escalated)
|
||||
if (statusFilter === "all") {
|
||||
submissionsQuery = submissionsQuery.in("status", ["approved", "rejected"]);
|
||||
} else {
|
||||
@@ -295,56 +261,12 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
);
|
||||
}
|
||||
|
||||
// Get total count - rebuild query with same filters
|
||||
let countQuery = supabase
|
||||
// Get total count
|
||||
const { count } = await supabase
|
||||
.from("content_submissions")
|
||||
.select("*", { count: "exact", head: true });
|
||||
.select("*", { count: "exact", head: true })
|
||||
.match(submissionsQuery as any);
|
||||
|
||||
// Apply the exact same filters as the main query
|
||||
if (tab === "mainQueue") {
|
||||
countQuery = countQuery.eq("escalated", false);
|
||||
|
||||
if (statusFilter === "all") {
|
||||
countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||
} else if (statusFilter === "pending") {
|
||||
countQuery = countQuery.in("status", ["pending", "partially_approved"]);
|
||||
} else {
|
||||
countQuery = countQuery.eq("status", statusFilter);
|
||||
}
|
||||
} else if (tab === "escalated") {
|
||||
countQuery = countQuery.eq("escalated", true);
|
||||
|
||||
if (statusFilter === "all") {
|
||||
countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||
} else if (statusFilter === "pending") {
|
||||
countQuery = countQuery.in("status", ["pending", "partially_approved"]);
|
||||
} else {
|
||||
countQuery = countQuery.eq("status", statusFilter);
|
||||
}
|
||||
} else {
|
||||
if (statusFilter === "all") {
|
||||
countQuery = countQuery.in("status", ["approved", "rejected"]);
|
||||
} else {
|
||||
countQuery = countQuery.eq("status", statusFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply entity type filter
|
||||
if (entityFilter === "photos") {
|
||||
countQuery = countQuery.eq("submission_type", "photo");
|
||||
} else if (entityFilter === "submissions") {
|
||||
countQuery = countQuery.neq("submission_type", "photo");
|
||||
}
|
||||
|
||||
// Apply access control
|
||||
if (!isAdmin && !isSuperuser) {
|
||||
const now = new Date().toISOString();
|
||||
countQuery = countQuery.or(
|
||||
`assigned_to.is.null,locked_until.lt.${now},assigned_to.eq.${user.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { count } = await countQuery;
|
||||
pagination.setTotalCount(count || 0);
|
||||
|
||||
// Apply pagination
|
||||
@@ -530,7 +452,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
setLoadingState("ready");
|
||||
}
|
||||
},
|
||||
[user, isAdmin, isSuperuser, filters, pagination, sort, profileCache, entityCache, toast],
|
||||
[user, isAdmin, isSuperuser, filters, pagination, profileCache, entityCache, toast],
|
||||
);
|
||||
|
||||
// Store fetchItems in ref to avoid re-creating visibility listener
|
||||
@@ -858,53 +780,20 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [user?.id]);
|
||||
|
||||
// Debounced fetch for effects - prevents race conditions
|
||||
const debouncedEffectFetch = useCallback(() => {
|
||||
if (effectFetchTimerRef.current) {
|
||||
clearTimeout(effectFetchTimerRef.current);
|
||||
}
|
||||
|
||||
effectFetchTimerRef.current = setTimeout(() => {
|
||||
console.log('[Debounced Fetch] Executing after effects settled');
|
||||
fetchItemsRef.current?.(true);
|
||||
}, EFFECT_DEBOUNCE_MS);
|
||||
}, []);
|
||||
|
||||
// Filter and tab changes trigger refetch
|
||||
// Filter changes trigger refetch
|
||||
useEffect(() => {
|
||||
if (!user || !initialFetchCompleteRef.current || isMountingRef.current) return;
|
||||
|
||||
console.log('[Filter/Tab Change] Queuing debounced fetch');
|
||||
pagination.reset();
|
||||
debouncedEffectFetch();
|
||||
}, [filters.activeTab, filters.debouncedEntityFilter, filters.debouncedStatusFilter, user, debouncedEffectFetch, pagination]);
|
||||
|
||||
// Sort changes trigger refetch
|
||||
useEffect(() => {
|
||||
if (!user || !initialFetchCompleteRef.current || isMountingRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Sort Change] Queuing debounced fetch');
|
||||
pagination.reset();
|
||||
debouncedEffectFetch();
|
||||
}, [sort.field, sort.direction, user, pagination, debouncedEffectFetch]);
|
||||
fetchItems(true);
|
||||
}, [filters.debouncedEntityFilter, filters.debouncedStatusFilter]);
|
||||
|
||||
// Pagination changes trigger refetch
|
||||
useEffect(() => {
|
||||
if (!user || !initialFetchCompleteRef.current || pagination.currentPage === 1) return;
|
||||
|
||||
debouncedEffectFetch();
|
||||
}, [pagination.currentPage, pagination.pageSize, debouncedEffectFetch]);
|
||||
|
||||
// Cleanup effect timer on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (effectFetchTimerRef.current) {
|
||||
clearTimeout(effectFetchTimerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
fetchItemsRef.current?.(true);
|
||||
}, [pagination.currentPage, pagination.pageSize]);
|
||||
|
||||
// Polling effect (when realtime disabled)
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user