aboutsummaryrefslogtreecommitdiff
path: root/src/core/utils/search.rs
blob: 81607cd5bc593aadd8722ecc69cb5438d192328f (plain)
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
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);
    }
}