83 lines
2.7 KiB
Swift
83 lines
2.7 KiB
Swift
//
|
|
// EmployeesViewModel.swift
|
|
// EmployeeDirectory
|
|
//
|
|
// Created by Matt Bruce on 1/20/25.
|
|
//
|
|
|
|
import Foundation
|
|
import Combine
|
|
|
|
/// ViewModel that will be bound to an Employees model and used
|
|
/// specifically with the EmployeesViewController.
|
|
@MainActor
|
|
public class EmployeesViewModel: ObservableObject {
|
|
private var employeeService: EmployeeServiceProtocol = EmployeeService()
|
|
|
|
private var allEmployees: [Employee] = [] // Holds unfiltered employees
|
|
@Published public private(set) var employees: [Employee] = []
|
|
@Published public private(set) var errorMessage: String? = nil
|
|
@Published public private(set) var isLoading: Bool = false
|
|
@Published public var searchText: String = "" // User input from search bar
|
|
private var cancellables = Set<AnyCancellable>()
|
|
public init() {
|
|
setupSearch()
|
|
}
|
|
|
|
/// Sets up Combine to filter employees as the search text changes
|
|
private func setupSearch() {
|
|
$searchText
|
|
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main) // Add delay to avoid frequent filtering
|
|
.removeDuplicates()
|
|
.sink { [weak self] query in
|
|
self?.filterEmployees(by: query)
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
public func fetchEmployees() {
|
|
// resetting values out the values before fetching new data
|
|
errorMessage = nil
|
|
isLoading = true
|
|
|
|
Task {
|
|
do {
|
|
// Fetch employees using the async method
|
|
let wrapper = try await employeeService.getEmployees()
|
|
|
|
// Update published properties
|
|
allEmployees = wrapper.employees
|
|
filterEmployees(by: searchText)
|
|
isLoading = false
|
|
|
|
} catch {
|
|
// Handle errors
|
|
employees = []
|
|
isLoading = false
|
|
errorMessage = "An unexpected error occurred, please try to refresh"
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public func changeService(to employeeService: EmployeeServiceProtocol) {
|
|
self.employeeService = employeeService
|
|
fetchEmployees()
|
|
}
|
|
|
|
/// Filters employees based on search query
|
|
private func filterEmployees(by query: String) {
|
|
if query.isEmpty {
|
|
employees = allEmployees // Reset to all employees if no search text
|
|
} else {
|
|
employees = allEmployees.filter { employee in
|
|
employee.fullName.lowercased().contains(query.lowercased()) ||
|
|
employee.team.lowercased().contains(query.lowercased()) ||
|
|
employee.emailAddress.lowercased().contains(query.lowercased())
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|