diff --git a/EmployeeDirectory-Observed/ContentView.swift b/EmployeeDirectory-Observed/ContentView.swift index 3755d11..12bf3eb 100644 --- a/EmployeeDirectory-Observed/ContentView.swift +++ b/EmployeeDirectory-Observed/ContentView.swift @@ -29,37 +29,29 @@ public struct EmployeeDirectoryList: View { @State public var path = NavigationPath() @State private var selectedEmployees = Set() @State private var editMode: EditMode = .inactive + @State private var searchText = "" init(viewModel: EmployeesViewModel? = nil) { _viewModel = .init(wrappedValue: viewModel ?? .init(service: EmployeeService())) } + var filteredEmployees: [Employee] { + if searchText.isEmpty { + return viewModel.employees + } else { + return viewModel.employees.filter { employee in + employee.firstName.lowercased().contains(searchText.lowercased()) || + employee.lastName.lowercased().contains(searchText.lowercased()) + } + } + } + public var body: some View { NavigationStack(path: $path) { List(selection: $selectedEmployees) { - ForEach(viewModel.employees, id: \.id) { employee in + ForEach(filteredEmployees, id: \.id) { employee in let employeeViewModel = EmployeeViewModel(employee: employee) - HStack(spacing: 10) { - ProfileImageView(urlString: employeeViewModel.smallPhoto, size: 51) - VStack(alignment: .leading, spacing: 5) { - Text(employeeViewModel.fullName) - .font(.headline) - if let bio = employeeViewModel.biography { - Text(bio) - .font(.footnote) - .foregroundColor(.gray) - .lineLimit(2) - } - Label("Email: \(employeeViewModel.emailAddress)", systemImage: "envelope.fill") - .foregroundColor(.gray) - .font(.caption) - if let phoneNumber = employeeViewModel.phoneNumber { - Label("Call: \(phoneNumber)", systemImage: "phone.fill") - .foregroundColor(.gray) - .font(.caption) - } - } - } + EmployeeListItem(employeeViewModel: employeeViewModel) .onTapGesture { if editMode != .active { path.append(employee) @@ -92,6 +84,7 @@ public struct EmployeeDirectoryList: View { await viewModel.refresh() } } + .searchable(text: $searchText, prompt: "Search employees by name") .navigationTitle("Employee Directory") .navigationDestination(for: Employee.self) { employee in EmployeeDetailView(viewModel: .init(employee: employee)) @@ -136,6 +129,40 @@ public struct EmployeeDirectoryList: View { } } +public struct EmployeeListItem: View { + public let employeeViewModel: EmployeeViewModel + + public var body: some View { + HStack(spacing: 10) { + ProfileImageView(urlString: employeeViewModel.smallPhoto, size: 51) + VStack(alignment: .leading, spacing: 5) { + Text(employeeViewModel.fullName) + .font(.headline) + if let bio = employeeViewModel.biography { + Text(bio) + .font(.footnote) + .foregroundColor(.gray) + .lineLimit(2) + } + Label("Email: \(employeeViewModel.emailAddress)", systemImage: "envelope.fill") + .foregroundColor(.gray) + .font(.caption) + if let phoneNumber = employeeViewModel.phoneNumber { + Label("Call: \(phoneNumber)", systemImage: "phone.fill") + .foregroundColor(.gray) + .font(.caption) + } + } + Spacer() + } + .contentShape(Rectangle()) + } +} + +#Preview("EmployeeListItem") { + EmployeeListItem(employeeViewModel: .init(employee: MockEmployeeService.sample)) +} + public struct EmployeeDetailView: View { public let viewModel: EmployeeViewModel