Home > Software design >  Filter a list with two parameters depending if toggle is active
Filter a list with two parameters depending if toggle is active

Time:01-31

I want to filter the list "employees" with two parameters "gender" and "department". But only if the corresponding toggle is activated. I tried to use an "all" case in both enum's but obviously with case "all" there is no member inside the list. What would be the best solution, if one toggle is deactivate to return all cases for the corresponding enum?

import SwiftUI


enum Gender: String, CaseIterable, Identifiable {
    var id: Self { self }
    
    case male = "male"
    case female = "female"
    case other = "other"
    
    case all = "all"
}

enum Department: String, CaseIterable, Identifiable {
    var id: Self { self }

    case engineering = "Engineer"
    case software = "Software"
    case sales = "Sales"
    case hr = "Human Ressources"
    case export = "Export"
    
    case all = "All"
    
}

struct Employe: Identifiable {
    
    let sex: Gender
    let department: Department
    let name: String
    
    var id: String { name }
}


struct ContentView: View {
    
    @State private var filterGender: Gender = .all
    @State private var filterDepartment: Department = .all
    
    @State private var activeGenderFilter: Bool = false
    @State private var activeDepartmentFilter: Bool = false
    
    let employees: [Employe] = [
        .init(sex: .female, department: .engineering, name: "Sarah"),
        .init(sex: .female, department: .engineering, name: "Anna"),
        .init(sex: .male, department: .export, name: "Tom"),
        .init(sex: .male, department: .sales, name: "Stephen"),
        .init(sex: .other, department: .software, name: "Alexis"),
        .init(sex: .female, department: .hr, name: "Julia"),
        .init(sex: .female, department: .sales, name: "Alina"),
        .init(sex: .male, department: .software, name: "Marie"),
        .init(sex: .other, department: .sales, name: "Sam"),
        .init(sex: .male, department: .export, name: "Ed")
    ]
    
    var body: some View {
        NavigationStack {
            
            toggleBar
            
            VStack {
                
                filterBar
                
                List {
                    ForEach((activeGenderFilter || activeDepartmentFilter) ? employees.filter { matchFilter(employe: $0, gender: filterGender, departmend: filterDepartment) }  : employees) { employe in
                        HStack {
                            Text(employe.name)
                            Text("(\(employe.sex.rawValue))")
                            Spacer()
                            Text(employe.department.rawValue)
                            
                        }
                    }
                }
            }
            .navigationTitle("Employees")
        }
    }
    
    func matchFilter(employe: Employe, gender: Gender, departmend: Department) -> Bool {
        return employe.sex == gender && employe.department == departmend
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

extension ContentView {
    private var toggleBar: some View  {
        VStack {
            
            Toggle("Gender", isOn: $activeGenderFilter.animation(.easeInOut))
            Toggle("Department", isOn: $activeDepartmentFilter.animation(.easeInOut))
        }
        .padding()
    }
    
    private var filterBar: some View {
        
        HStack {
            if activeGenderFilter {
                Picker("Gender", selection: $filterGender) {
                    ForEach(Gender.allCases) { gender in
                        Text(gender.rawValue)
                    }
                }
                .pickerStyle(.menu)
                .padding()
            }
            
            Spacer()

            
            if activeDepartmentFilter {
                Picker("Department", selection: $filterDepartment) {
                    ForEach(Department.allCases) { department in
                        Text(department.rawValue)
                    }
                }
                .padding()
                .pickerStyle(.menu)
            }
        }
    }
}

CodePudding user response:

You need to include the toggle properties and the .all cases in your matching logic

func matchFilter(employe: Employe, gender: Gender, departmend: Department) -> Bool {
    return (activeGenderFilter == false || gender == .all || employe.sex == gender) &&
        (activeDepartmentFilter == false || departmend == .all || employe.department == departmend)
}
  • Related