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