Spaces:
Sleeping
Sleeping
File size: 4,658 Bytes
d97b8f9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /**
* Search utility functions for enhanced filtering and searching
*/
/**
* Performs a fuzzy search on a string, checking if all search terms are present
* @param searchTerm The search term to look for
* @param targetString The string to search in
* @returns true if all search terms are found in the target string
*/
export function fuzzySearch(searchTerm: string, targetString: string): boolean {
if (!searchTerm.trim()) return true;
const searchWords = searchTerm.toLowerCase().split(/\s+/).filter(word => word.length > 0);
const target = targetString.toLowerCase();
return searchWords.every(word => target.includes(word));
}
/**
* Performs a multi-field search across multiple string fields
* @param searchTerm The search term to look for
* @param fields Array of strings to search in
* @returns true if the search term is found in any of the fields
*/
export function multiFieldSearch(searchTerm: string, fields: (string | number)[]): boolean {
if (!searchTerm.trim()) return true;
const searchLower = searchTerm.toLowerCase();
return fields.some(field => {
const fieldStr = String(field).toLowerCase();
return fieldStr.includes(searchLower);
});
}
/**
* Highlights search terms in a string by wrapping them with HTML tags
* @param text The text to highlight
* @param searchTerm The term to highlight
* @param className CSS class to apply to highlighted text
* @returns HTML string with highlighted terms
*/
export function highlightSearchTerm(
text: string,
searchTerm: string,
className: string = 'bg-yellow-200'
): string {
if (!searchTerm.trim()) return text;
const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return text.replace(regex, `<span class="${className}">$1</span>`);
}
/**
* Debounce function to limit the rate of function calls
* @param func The function to debounce
* @param delay The delay in milliseconds
* @returns Debounced function
*/
export function debounce<T extends (...args: any[]) => any>(
func: T,
delay: number
): (...args: Parameters<T>) => void {
let timeoutId: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func(...args), delay);
};
}
/**
* Creates a search filter function for arrays of objects
* @param searchTerm The search term
* @param searchFields Array of field names to search in
* @returns Filter function that can be used with Array.filter()
*/
export function createSearchFilter<T extends Record<string, any>>(
searchTerm: string,
searchFields: (keyof T)[]
) {
return (item: T): boolean => {
if (!searchTerm.trim()) return true;
const fieldsToSearch = searchFields.map(field => item[field]);
return multiFieldSearch(searchTerm, fieldsToSearch);
};
}
/**
* Sorts an array of objects by a specific field
* @param array The array to sort
* @param field The field to sort by
* @param direction The sort direction
* @returns Sorted array
*/
export function sortByField<T extends Record<string, any>>(
array: T[],
field: keyof T,
direction: 'asc' | 'desc' = 'asc'
): T[] {
return [...array].sort((a, b) => {
const aValue = a[field];
const bValue = b[field];
if (typeof aValue === 'string' && typeof bValue === 'string') {
const comparison = aValue.localeCompare(bValue);
return direction === 'asc' ? comparison : -comparison;
}
if (typeof aValue === 'number' && typeof bValue === 'number') {
const comparison = aValue - bValue;
return direction === 'asc' ? comparison : -comparison;
}
if (aValue instanceof Date && bValue instanceof Date) {
const comparison = aValue.getTime() - bValue.getTime();
return direction === 'asc' ? comparison : -comparison;
}
// Fallback to string comparison
const comparison = String(aValue).localeCompare(String(bValue));
return direction === 'asc' ? comparison : -comparison;
});
}
/**
* Filters an array based on multiple filter criteria
* @param array The array to filter
* @param filters Object containing filter criteria
* @returns Filtered array
*/
export function applyFilters<T extends Record<string, any>>(
array: T[],
filters: Record<string, any>
): T[] {
return array.filter(item => {
return Object.entries(filters).every(([key, value]) => {
if (value === 'all' || value === '' || value == null) return true;
return item[key] === value;
});
});
} |