// // CategoryDetailView.swift // Nextcloud Cookbook iOS Client // // Created by Vincent Meilinger on 15.09.23. // import Foundation import SwiftUI import SwiftData struct RecipeListView: View { @Environment(\.modelContext) var modelContext @Query var recipes: [Recipe] @Binding var selectedRecipe: Recipe? @Binding var selectedCategory: String? init(selectedCategory: Binding, selectedRecipe: Binding) { var predicate: Predicate? = nil if let category = selectedCategory.wrappedValue, category != "*" { predicate = #Predicate { $0.category == category } } _recipes = Query(filter: predicate, sort: \.name) _selectedRecipe = selectedRecipe _selectedCategory = selectedCategory } var body: some View { List(selection: $selectedRecipe) { ForEach(recipes) { recipe in RecipeCardView(recipe: recipe) .shadow(radius: 2) .background( NavigationLink(value: recipe) { EmptyView() } .buttonStyle(.plain) .opacity(0) ) .frame(height: 85) .listRowInsets(EdgeInsets(top: 5, leading: 15, bottom: 5, trailing: 15)) .listRowSeparatorTint(.clear) } } .listStyle(.plain) .navigationTitle("Recipes") .toolbar { } } } /* struct RecipeListView: View { @EnvironmentObject var appState: AppState @EnvironmentObject var groceryList: GroceryList @State var categoryName: String @State var searchText: String = "" @Binding var showEditView: Bool @State var selectedRecipe: CookbookApiRecipeV1? = nil var body: some View { Group { let recipes = recipesFiltered() if !recipes.isEmpty { List(recipesFiltered(), id: \.recipe_id) { recipe in RecipeCardView(recipe: recipe) .shadow(radius: 2) .background( NavigationLink(value: recipe) { EmptyView() } .buttonStyle(.plain) .opacity(0) ) .frame(height: 85) .listRowInsets(EdgeInsets(top: 5, leading: 15, bottom: 5, trailing: 15)) .listRowSeparatorTint(.clear) } .listStyle(.plain) } else { VStack { Text("There are no recipes in this cookbook!") Button { Task { await appState.getCategories() await appState.getCategory(named: categoryName, fetchMode: .preferServer) } } label: { Text("Refresh") .bold() } .buttonStyle(.bordered) }.padding() } } .searchable(text: $searchText, prompt: "Search recipes/keywords") .navigationTitle(categoryName == "*" ? String(localized: "Other") : categoryName) .navigationDestination(for: CookbookApiRecipeV1.self) { recipe in RecipeView(viewModel: RecipeView.ViewModel(recipe: recipe)) .environmentObject(appState) .environmentObject(groceryList) } .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { print("Add new recipe") showEditView = true } label: { Image(systemName: "plus.circle.fill") } } } .task { await appState.getCategory( named: categoryName, fetchMode: UserSettings.shared.storeRecipes ? .preferLocal : .onlyServer ) } .refreshable { await appState.getCategory( named: categoryName, fetchMode: UserSettings.shared.storeRecipes ? .preferServer : .onlyServer ) } } func recipesFiltered() -> [CookbookApiRecipeV1] { guard let recipes = appState.recipes[categoryName] else { return [] } guard searchText != "" else { return recipes } return recipes.filter { recipe in recipe.name.lowercased().contains(searchText.lowercased()) || // check name for occurence of search term (recipe.keywords != nil && recipe.keywords!.lowercased().contains(searchText.lowercased())) // check keywords for search term } } } */ /* struct RecipeListView: View { @Bindable var cookbookState: CookbookState @State var selectedCategory: String @State var searchText: String = "" @Binding var showEditView: Bool var body: some View { Group { let recipes = recipesFiltered() if !recipes.isEmpty { List(recipesFiltered(), selection: $cookbookState.selectedAccountState.selectedRecipe) { recipe in RecipeCardView(state: cookbookState.selectedAccountState, recipe: recipe) .shadow(radius: 2) .background( NavigationLink { RecipeView(viewModel: RecipeView.ViewModel(recipeStub: recipe)) .environment(cookbookState) } label: { EmptyView() } .buttonStyle(.plain) .opacity(0) ) .frame(height: 85) .listRowInsets(EdgeInsets(top: 5, leading: 15, bottom: 5, trailing: 15)) .listRowSeparatorTint(.clear) } .listStyle(.plain) } else { VStack { Text("There are no recipes in this cookbook!") Button { Task { let _ = await cookbookState.selectedAccountState.getCategories() let _ = await cookbookState.selectedAccountState.getRecipeStubsForCategory(named: selectedCategory) } } label: { Text("Refresh") .bold() } .buttonStyle(.bordered) }.padding() } } .searchable(text: $searchText, prompt: "Search recipes/keywords") .navigationTitle(selectedCategory == "*" ? String(localized: "Other") : selectedCategory) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { print("Add new recipe") showEditView = true } label: { Image(systemName: "plus.circle.fill") } } } .task { let _ = await cookbookState.selectedAccountState.getRecipeStubsForCategory( named: selectedCategory ) } .refreshable { let _ = await cookbookState.selectedAccountState.getRecipeStubsForCategory( named: selectedCategory ) } } func recipesFiltered() -> [RecipeStub] { guard let recipes = cookbookState.selectedAccountState.recipeStubs[selectedCategory] else { return [] } guard searchText != "" else { return recipes } return recipes.filter { recipe in recipe.name.lowercased().contains(searchText.lowercased()) || // check name for occurence of search term (recipe.keywords != nil && recipe.keywords!.lowercased().contains(searchText.lowercased())) // check keywords for search term } } } */