import Foundation @MainActor final class AddBooksViewModel: ObservableObject { enum Mode: String, CaseIterable { case title case scan case filter var title: String { switch self { case .title: return String(localized: "add.searchByTitle") case .scan: return String(localized: "add.scanBarcode") case .filter: return String(localized: "add.filter") } } } @Published var mode: Mode = .title @Published var titleQuery = "" @Published var filterTitle = "" @Published var filterYear = "" @Published var results: [BookRemote] = [] @Published var isLoading = false @Published var errorMessage: String? private var debounceTask: Task? private let booksService: BooksServiceProtocol init(booksService: BooksServiceProtocol) { self.booksService = booksService } func titleChanged() { debounceTask?.cancel() let query = titleQuery.trimmingCharacters(in: .whitespacesAndNewlines) guard query.count >= 2 else { results = [] return } debounceTask = Task { try? await Task.sleep(for: .milliseconds(400)) await searchByTitle(query) } } func searchByTitle(_ query: String? = nil) async { let value = query ?? titleQuery guard !value.isEmpty else { return } isLoading = true defer { isLoading = false } do { results = try await booksService.searchByTitle(value, locales: "tr,en") errorMessage = nil } catch { errorMessage = error.localizedDescription } } func searchByISBN(_ isbn: String) async { guard !isbn.isEmpty else { return } isLoading = true defer { isLoading = false } do { results = try await booksService.searchByISBN(isbn, locales: "tr,en") errorMessage = nil } catch { errorMessage = error.localizedDescription } } func applyFilter() async { guard !filterTitle.isEmpty, !filterYear.isEmpty else { return } isLoading = true defer { isLoading = false } do { results = try await booksService.filter(title: filterTitle, year: filterYear, locales: "tr,en") errorMessage = nil } catch { errorMessage = error.localizedDescription } } }