diff options
| author | UMTS at Teleco <crt@teleco.ch> | 2025-12-13 02:51:15 +0100 |
|---|---|---|
| committer | UMTS at Teleco <crt@teleco.ch> | 2025-12-13 02:51:15 +0100 |
| commit | 8323fdd73272a2882781aba3c499ba0be3dff2a6 (patch) | |
| tree | ffbf86473933e69cfaeef30d5c6ea7e5b494856c /src/core/utils | |
Diffstat (limited to 'src/core/utils')
| -rw-r--r-- | src/core/utils/mod.rs | 4 | ||||
| -rw-r--r-- | src/core/utils/search.rs | 135 |
2 files changed, 139 insertions, 0 deletions
diff --git a/src/core/utils/mod.rs b/src/core/utils/mod.rs new file mode 100644 index 0000000..02800e7 --- /dev/null +++ b/src/core/utils/mod.rs @@ -0,0 +1,4 @@ +/// Utility functions for search and filtering +pub mod search; + +// search module available but not currently used at top level diff --git a/src/core/utils/search.rs b/src/core/utils/search.rs new file mode 100644 index 0000000..81607cd --- /dev/null +++ b/src/core/utils/search.rs @@ -0,0 +1,135 @@ +use serde_json::Value; + +/// Search and filtering utilities for entity data +#[allow(dead_code)] +pub struct SearchFilter; + +#[allow(dead_code)] +impl SearchFilter { + /// Filter a collection of JSON values based on a search query across specified fields + pub fn filter_data(data: &[Value], search_query: &str, search_fields: &[&str]) -> Vec<Value> { + if search_query.is_empty() { + return data.to_vec(); + } + + let search_lower = search_query.to_lowercase(); + data.iter() + .filter(|item| { + search_fields.iter().any(|field| { + item.get(field) + .and_then(|v| v.as_str()) + .map(|s| s.to_lowercase().contains(&search_lower)) + .unwrap_or(false) + }) + }) + .cloned() + .collect() + } + + /// Filter any generic collection with a custom predicate + pub fn filter_generic<T>(data: &[T], predicate: impl Fn(&T) -> bool) -> Vec<T> + where + T: Clone, + { + data.iter() + .filter(|item| predicate(item)) + .cloned() + .collect() + } + + /// Search assets specifically (common fields: name, asset_tag, manufacturer, model) + pub fn filter_assets(assets: &[Value], search_query: &str) -> Vec<Value> { + Self::filter_data( + assets, + search_query, + &[ + "name", + "asset_tag", + "manufacturer", + "model", + "serial_number", + ], + ) + } + + /// Search borrowers (common fields: first_name, last_name, email, username) + pub fn filter_borrowers(borrowers: &[Value], search_query: &str) -> Vec<Value> { + Self::filter_data( + borrowers, + search_query, + &["first_name", "last_name", "email", "username"], + ) + } + + /// Search categories (common fields: category_name, category_code) + pub fn filter_categories(categories: &[Value], search_query: &str) -> Vec<Value> { + Self::filter_data( + categories, + search_query, + &["category_name", "category_code"], + ) + } + + /// Search zones (common fields: zone_name, zone_code) + pub fn filter_zones(zones: &[Value], search_query: &str) -> Vec<Value> { + Self::filter_data(zones, search_query, &["zone_name", "zone_code"]) + } + + /// Search suppliers (common fields: name) + pub fn filter_suppliers(suppliers: &[Value], search_query: &str) -> Vec<Value> { + Self::filter_data(suppliers, search_query, &["name"]) + } +} + +/// Sorting utilities +#[allow(dead_code)] +pub struct SortUtils; + +#[allow(dead_code)] +impl SortUtils { + /// Sort JSON values by a specific field + pub fn sort_json_by_field(data: &mut [Value], field: &str, ascending: bool) { + data.sort_by(|a, b| { + let val_a = a.get(field); + let val_b = b.get(field); + + let cmp = match (val_a, val_b) { + (Some(a), Some(b)) => { + // Try to compare as strings first + match (a.as_str(), b.as_str()) { + (Some(s_a), Some(s_b)) => s_a.cmp(s_b), + _ => { + // Try to compare as numbers + match (a.as_i64(), b.as_i64()) { + (Some(n_a), Some(n_b)) => n_a.cmp(&n_b), + _ => { + // Try to compare as floats + match (a.as_f64(), b.as_f64()) { + (Some(f_a), Some(f_b)) => f_a + .partial_cmp(&f_b) + .unwrap_or(std::cmp::Ordering::Equal), + _ => std::cmp::Ordering::Equal, + } + } + } + } + } + } + (Some(_), None) => std::cmp::Ordering::Less, + (None, Some(_)) => std::cmp::Ordering::Greater, + (None, None) => std::cmp::Ordering::Equal, + }; + + if ascending { + cmp + } else { + cmp.reverse() + } + }); + } + + /// Generic sort function for any collection + pub fn sort_generic<T>(data: &mut [T], compare_fn: impl Fn(&T, &T) -> std::cmp::Ordering) { + data.sort_by(compare_fn); + } +} |
