import SwiftUI struct AddBooksView: View { @EnvironmentObject private var router: AppRouter @ObservedObject var viewModel: AddBooksViewModel var body: some View { VStack(spacing: 12) { Picker("Mode", selection: $viewModel.mode) { ForEach(AddBooksViewModel.Mode.allCases, id: \.self) { mode in Text(mode.title).tag(mode) } } .pickerStyle(.segmented) Group { switch viewModel.mode { case .title: titleSearch case .scan: scanSearch case .filter: filterSearch } } if let error = viewModel.errorMessage { NetworkErrorView(message: error) { Task { await viewModel.searchByTitle() } } } List(viewModel.results, id: \.id) { book in Button { router.path.append(.detail(book)) } label: { HStack(spacing: 12) { AsyncImage(url: book.coverImageUrl) { phase in if let image = phase.image { image.resizable().scaledToFill() } else { RoundedRectangle(cornerRadius: 8).fill(.gray.opacity(0.2)) } } .frame(width: 48, height: 72) .clipShape(RoundedRectangle(cornerRadius: 8)) VStack(alignment: .leading, spacing: 4) { Text(book.title) .font(.headline) .lineLimit(2) Text(book.authors.joined(separator: ", ")) .font(.subheadline) .foregroundStyle(.secondary) .lineLimit(1) if let year = book.publishedYear { Text("\(year)") .font(.caption) .foregroundStyle(.secondary) } } } } } .listStyle(.plain) .overlay { if viewModel.results.isEmpty, !viewModel.isLoading { Text(String(localized: "common.empty")) .font(.subheadline) .foregroundStyle(.secondary) } } } .padding(.horizontal, 16) .navigationTitle(String(localized: "add.title")) .navigationBarTitleDisplayMode(.inline) .overlay { if viewModel.isLoading { ProgressView() .controlSize(.large) } } } private var titleSearch: some View { TextField(String(localized: "add.searchPlaceholder"), text: $viewModel.titleQuery) .textFieldStyle(.roundedBorder) .onChange(of: viewModel.titleQuery) { _, _ in viewModel.titleChanged() } } private var scanSearch: some View { BarcodeScannerView { isbn in Task { await viewModel.searchByISBN(isbn) } } .frame(height: 260) .clipShape(RoundedRectangle(cornerRadius: 16)) } private var filterSearch: some View { VStack(spacing: 8) { TextField("Title", text: $viewModel.filterTitle) .textFieldStyle(.roundedBorder) TextField("YYYY", text: $viewModel.filterYear) .textFieldStyle(.roundedBorder) .keyboardType(.numberPad) Button("Apply") { Task { await viewModel.applyFilter() } } .buttonStyle(.borderedProminent) .frame(maxWidth: .infinity, alignment: .trailing) } } }