feat: Extract moderation filter and sort logic

This commit is contained in:
gpt-engineer-app[bot]
2025-10-12 22:38:30 +00:00
parent d979fa6e8b
commit 99a4d002ba
6 changed files with 762 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
/**
* Moderation Queue Sorting Utilities
*
* Provides sorting functions and utilities for moderation queue items.
*/
import type { ModerationItem, SortField, SortDirection, SortConfig } from '@/types/moderation';
/**
* Sort moderation items based on configuration
*
* @param items - Array of moderation items to sort
* @param config - Sort configuration
* @returns Sorted array of items
*/
export function sortModerationItems(
items: ModerationItem[],
config: SortConfig
): ModerationItem[] {
const { field, direction } = config;
return [...items].sort((a, b) => {
let comparison = 0;
switch (field) {
case 'created_at':
comparison = new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
break;
case 'username':
const usernameA = a.user_profile?.username || a.user_profile?.display_name || '';
const usernameB = b.user_profile?.username || b.user_profile?.display_name || '';
comparison = usernameA.localeCompare(usernameB);
break;
case 'submission_type':
comparison = (a.submission_type || '').localeCompare(b.submission_type || '');
break;
case 'status':
comparison = a.status.localeCompare(b.status);
break;
case 'escalated':
const escalatedA = a.escalated ? 1 : 0;
const escalatedB = b.escalated ? 1 : 0;
comparison = escalatedB - escalatedA; // Escalated items first
break;
default:
comparison = 0;
}
return direction === 'asc' ? comparison : -comparison;
});
}
/**
* Get default sort configuration
*
* @returns Default sort config
*/
export function getDefaultSortConfig(): SortConfig {
return {
field: 'created_at',
direction: 'asc',
};
}
/**
* Load sort configuration from localStorage
*
* @param key - localStorage key
* @returns Saved sort config or default
*/
export function loadSortConfig(key: string = 'moderationQueue_sortConfig'): SortConfig {
try {
const saved = localStorage.getItem(key);
if (saved) {
return JSON.parse(saved);
}
} catch (error) {
console.error('Failed to load sort config:', error);
}
return getDefaultSortConfig();
}
/**
* Save sort configuration to localStorage
*
* @param config - Sort configuration to save
* @param key - localStorage key
*/
export function saveSortConfig(
config: SortConfig,
key: string = 'moderationQueue_sortConfig'
): void {
try {
localStorage.setItem(key, JSON.stringify(config));
} catch (error) {
console.error('Failed to save sort config:', error);
}
}
/**
* Toggle sort direction
*
* @param currentDirection - Current sort direction
* @returns Toggled direction
*/
export function toggleSortDirection(currentDirection: SortDirection): SortDirection {
return currentDirection === 'asc' ? 'desc' : 'asc';
}
/**
* Get human-readable label for sort field
*
* @param field - Sort field
* @returns Human-readable label
*/
export function getSortFieldLabel(field: SortField): string {
switch (field) {
case 'created_at':
return 'Date Created';
case 'username':
return 'Submitter';
case 'submission_type':
return 'Type';
case 'status':
return 'Status';
case 'escalated':
return 'Escalated';
default:
return field;
}
}
/**
* Check if sort config is default
*
* @param config - Sort configuration to check
* @returns True if config matches default
*/
export function isDefaultSortConfig(config: SortConfig): boolean {
const defaultConfig = getDefaultSortConfig();
return (
config.field === defaultConfig.field &&
config.direction === defaultConfig.direction
);
}