// // EmployeeService.swift // EmployeeDirectory // // Created by Matt Bruce on 1/20/25. // import Foundation public enum EmployeeSortField: String { case fullName case team case employeeType } public enum EmployeeSortOrder: String { case ascending = "asc" case descending = "desc" } /// These are the testing URL Endpoints for different states internal enum EmployeeServiceMode: String, CaseIterable { case production case malformed case empty public var service: EmployeeServiceProtocol { switch self { case .production: return MockEmployeeService.shared //return EmployeeService.shared case .malformed: return EmployeeMalformedService.shared case .empty: return EmployeeEmptyService.shared } } /// Enpoint in which to grabe employees from. public var endpoint: String { switch self { case .production: return "https://s3.amazonaws.com/sq-mobile-interview/employees.json" case .malformed: return "https://s3.amazonaws.com/sq-mobile-interview/employees_malformed.json" case .empty: return "https://s3.amazonaws.com/sq-mobile-interview/employees_empty.json" } } } /// Service Layer for Employees public class EmployeeService: EmployeeServiceProtocol { // MARK: - Properties public static let shared = EmployeeService() // Default shared instance // MARK: - Initializer public init() {} // MARK: - Public Methods /// This will get a list of all employees /// - Parameter serviceMode: Mode in which to hit. /// - Returns: An Employees struct public func getEmployees() async throws -> Employees { return try await NetworkService.shared.fetchData(from: EmployeeServiceMode.production.endpoint, as: Employees.self) } /// Fetch employees with pagination support /// - Parameters: /// - page: The page number to fetch. /// - perPage: The number of employees per page. /// - Returns: A paginated Employees object. public func getEmployees(page: Int, perPage: Int, sortField: EmployeeSortField = .fullName, sortOrder: EmployeeSortOrder = .ascending) async throws -> Employees { guard var urlComponents = URLComponents(string: EmployeeServiceMode.production.endpoint) else { throw NetworkServiceError.invalidURL } urlComponents.queryItems = [ URLQueryItem(name: "page", value: "\(page)"), URLQueryItem(name: "perPage", value: "\(perPage)"), URLQueryItem(name: "sortField", value: "\(sortField.rawValue)"), URLQueryItem(name: "sortOrder", value: "\(sortOrder.rawValue)") ] guard let url = urlComponents.url else { throw NetworkServiceError.invalidURL } let request = RequestBuilder(url: url, method: .get).build() return try await NetworkService.shared.fetchData(with: request, as: Employees.self) } } /// Service Layer for Employees public class EmployeeMalformedService: EmployeeServiceProtocol { // MARK: - Properties public static let shared = EmployeeMalformedService() // Default shared instance // MARK: - Initializer public init() {} // MARK: - Public Methods /// This will get a list of all employees /// - Parameter serviceMode: Mode in which to hit. /// - Returns: An Employees struct public func getEmployees() async throws -> Employees { return try await NetworkService.shared.fetchData(from: EmployeeServiceMode.malformed.endpoint, as: Employees.self) } public func getEmployees(page: Int, perPage: Int, sortField: EmployeeSortField, sortOrder: EmployeeSortOrder) async throws -> Employees { return try await NetworkService.shared.fetchData(from: EmployeeServiceMode.malformed.endpoint, as: Employees.self) } } /// Service Layer for Employees public class EmployeeEmptyService: EmployeeServiceProtocol { // MARK: - Properties public static let shared = EmployeeEmptyService() // Default shared instance // MARK: - Initializer public init() {} // MARK: - Public Methods /// This will get a list of all employees /// - Parameter serviceMode: Mode in which to hit. /// - Returns: An Employees struct public func getEmployees() async throws -> Employees { return try await NetworkService.shared.fetchData(from: EmployeeServiceMode.empty.endpoint, as: Employees.self) } public func getEmployees(page: Int, perPage: Int, sortField: EmployeeSortField, sortOrder: EmployeeSortOrder) async throws -> Employees { return try await NetworkService.shared.fetchData(from: EmployeeServiceMode.empty.endpoint, as: Employees.self) } }