| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- 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);
- }
- }
|