diff --git a/Twigs/Category/CategoryDetailsView.swift b/Twigs/Category/CategoryDetailsView.swift index 9623ac4..98d8e03 100644 --- a/Twigs/Category/CategoryDetailsView.swift +++ b/Twigs/Category/CategoryDetailsView.swift @@ -15,7 +15,6 @@ struct CategoryDetailsView: View { @EnvironmentObject var apiService: TwigsApiService let budget: Budget @State var sum: Int? = 0 - @State var editingCategory: Bool = false var spent: Int { get { if case let .success(sum) = categoryDataStore.sum { @@ -49,12 +48,14 @@ struct CategoryDetailsView: View { await categoryDataStore.sum(categoryId: category.id) } .navigationBarItems(trailing: Button(action: { - self.editingCategory = true + Task { + await dataStore.edit(category) + } }) { Text("edit") }) - .sheet(isPresented: self.$editingCategory, onDismiss: { - self.editingCategory = false + .sheet(isPresented: self.$dataStore.editingCategory, onDismiss: { + self.dataStore.cancelEditCategory() }, content: { CategoryFormSheet(categoryForm: CategoryForm( category: category, diff --git a/Twigs/Category/CategoryListView.swift b/Twigs/Category/CategoryListView.swift index 8ec8911..fb12d52 100644 --- a/Twigs/Category/CategoryListView.swift +++ b/Twigs/Category/CategoryListView.swift @@ -13,29 +13,60 @@ import TwigsCore struct CategoryListView: View { @EnvironmentObject var dataStore: DataStore @State var requestId: String = "" + private var budgetId: String { + get { + if case let .success(budget) = dataStore.budget { + return budget.id + } else { + return "" + } + } + } @ViewBuilder var body: some View { - InlineLoadingView( - data: $dataStore.categories, - action: { await self.dataStore.getCategories(budgetId: budget.id, expense: nil, archived: nil, count: nil, page: nil) }, - errorTextLocalizedStringKey: "Failed to load categories" - ) { categories in - List { - Section { - ForEach(categories.filter { !$0.archived }) { category in - CategoryListItemView(CategoryDataStore(dataStore.apiService), budget: budget, category: category) - } - } - if categories.contains(where: { $0.archived }) { - Section("Archived") { - ForEach(categories.filter { $0.archived }) { category in + List { + InlineLoadingView( + data: $dataStore.categories, + action: { await self.dataStore.getCategories(budgetId: budget.id, expense: nil, archived: nil, count: nil, page: nil) }, + errorTextLocalizedStringKey: "Failed to load categories" + ) { categories in + if categories.isEmpty { + Text("no_categories") + } else { + Section { + ForEach(categories.filter { !$0.archived }) { category in CategoryListItemView(CategoryDataStore(dataStore.apiService), budget: budget, category: category) } } + if categories.contains(where: { $0.archived }) { + Section("Archived") { + ForEach(categories.filter { $0.archived }) { category in + CategoryListItemView(CategoryDataStore(dataStore.apiService), budget: budget, category: category) + } + } + } } } + }.refreshable { + await dataStore.getCategories() } + .navigationBarItems(trailing: Button(action: { + Task { + await dataStore.edit(TwigsCore.Category(budgetId: budgetId)) + } + }, label: { + Image(systemName: "plus").padding() + })) + .sheet(isPresented: self.$dataStore.editingCategory, onDismiss: { + self.dataStore.cancelEditCategory() + }, content: { + CategoryFormSheet(categoryForm: CategoryForm( + category: TwigsCore.Category(budgetId: budgetId), + dataStore: dataStore, + budgetId: budgetId + )) + }) } private let budget: Budget diff --git a/Twigs/DataStore.swift b/Twigs/DataStore.swift index d198031..b8b5eda 100644 --- a/Twigs/DataStore.swift +++ b/Twigs/DataStore.swift @@ -28,6 +28,7 @@ class DataStore : ObservableObject { @Published var overview: AsyncData = .empty @Published var showBudgetSelection: Bool = true @Published var editingBudget: Bool = false + @Published var editingCategory: Bool = false init( _ apiService: TwigsApiService @@ -176,7 +177,14 @@ class DataStore : ObservableObject { } @Published var selectedCategory: TwigsCore.Category? = nil - func getCategories(budgetId: String? = nil, expense: Bool? = nil, archived: Bool? = false, count: Int? = nil, page: Int? = nil) async { + func getCategories() async { + guard case let .success(budget) = self.budget else { + return + } + await self.getCategories(budgetId: budget.id) + } + + func getCategories(budgetId: String, expense: Bool? = nil, archived: Bool? = false, count: Int? = nil, page: Int? = nil) async { self.categories = .loading do { let categories = try await apiService.getCategories(budgetId: budgetId, expense: expense, archived: archived, count: count, page: page) @@ -196,6 +204,7 @@ class DataStore : ObservableObject { savedCategory = try await self.apiService.createCategory(category) } self.category = .success(savedCategory) + self.editingCategory = false if case let .success(categories) = self.categories { var updatedCategories = categories.filter(withoutId: category.id) updatedCategories.append(savedCategory) @@ -211,6 +220,7 @@ class DataStore : ObservableObject { do { try await self.apiService.deleteCategory(category.id) self.category = .empty + self.editingCategory = false if case let .success(categories) = self.categories { self.categories = .success(categories.filter(withoutId: category.id)) } @@ -220,10 +230,12 @@ class DataStore : ObservableObject { } func edit(_ category: TwigsCore.Category) async { + self.editingCategory = true self.category = .editing(category) } func cancelEditCategory() { + self.editingCategory = false if let category = self.selectedCategory { self.category = .success(category) } else {