diff --git a/SearchEmptyState/ContentView.swift b/SearchEmptyState/ContentView.swift index 1d437e5..d5b6a4b 100644 --- a/SearchEmptyState/ContentView.swift +++ b/SearchEmptyState/ContentView.swift @@ -8,42 +8,72 @@ import SwiftUI struct ContentView: View { - @State private var wizards = ["Alvo Dumbledore", "Harry Potter", "Hermione Granger", "Severus Snape", "Minerva McGonagall"] + @State private var wizards: [String] = [] @State private var searchTerm = "" - + private var staticWizards = ["Alvo Dumbledore", "Harry Potter", "Hermione Granger", "Severus Snape", "Minerva McGonagall"] var filteredWizards: [String] { guard !searchTerm.isEmpty else {return wizards} - return wizards.filter { $0.localizedCaseInsensitiveContains(searchTerm) } } - var body: some View { NavigationStack { VStack { - List(filteredWizards, id: \.self) { - wizard in Text(wizard) - } - .searchable(text: $searchTerm, prompt: "Search a Wizard") - .overlay { - if filteredWizards.isEmpty { - ContentUnavailableView(label: { - VStack { - Image("wand").resizable().frame(width: 120, height: 120).padding(.bottom, -20) - Text("No Wizards").bold() + if !wizards.isEmpty { + List(filteredWizards, id: \.self) { + wizard in Text(wizard) + } + .searchable(text: $searchTerm, prompt: "Search a Wizard") + .overlay { + if filteredWizards.isEmpty { + ContentUnavailableView(label: { + VStack { + Image("wand").resizable().frame(width: 120, height: 120).padding(.bottom, -20) + Text("No Wizards").bold() + } + }, description: { + Text("No wizards were found with the name \(searchTerm). Perhaps you're looking for a muggle?").accessibilityIdentifier("ResultError") } - }, description: { - Text("No wizards was found with: \(searchTerm), maybe you're looking for a muggle?").accessibilityIdentifier("ResultError") + ) } - ) } + } else { + Text("loading...") } } .navigationTitle("Hogwarts Wizards") + }.task { + do { + wizards = try await fetchWizards() + } catch { + wizards = staticWizards + } } } + + struct Wizards: Codable { + let name: String + let hogwartsStudent: Bool + let hogwartsStaff: Bool + } + + func fetchWizards() async throws -> [String] { + let url = URL(string: "https://hp-api.onrender.com/api/characters")! + let (data, _) = try await URLSession.shared.data(from: url) + do { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + let result = try decoder.decode([Wizards].self, from: data) + return result.filter { $0.hogwartsStaff || $0.hogwartsStudent } .map { $0.name } + } catch { + throw error + } + } + } + #Preview { ContentView() } + diff --git a/SearchEmptyStateUITests/SearchEmptyStateUITestsSearchTests.swift b/SearchEmptyStateUITests/SearchEmptyStateUITestsSearchTests.swift index f8223e2..c2e85f2 100644 --- a/SearchEmptyStateUITests/SearchEmptyStateUITestsSearchTests.swift +++ b/SearchEmptyStateUITests/SearchEmptyStateUITestsSearchTests.swift @@ -19,7 +19,7 @@ final class SearchEmptyStateUITestsSearchTests: XCTestCase { func testErrorMessage() throws { let searchTerm = "Petunia Dursley" - let expectedResultErrorMessage = "No wizards was found with: \(searchTerm), maybe you're looking for a muggle?" + let expectedResultErrorMessage = "No wizards were found with the name \(searchTerm). Perhaps you're looking for a muggle?" let search = app.searchFields["Search a Wizard"] search.tap()