From 9f7ef79c9831ddd4640592b5d81fc8cab9203cd1 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Tue, 3 Jan 2023 21:26:42 -0700 Subject: [PATCH] Fix budget/category/user disappearing on transaction details --- Twigs.xcodeproj/project.pbxproj | 4 - Twigs/DataStore.swift | 18 +++- Twigs/Transaction/TransactionDetails.swift | 66 --------------- .../Transaction/TransactionDetailsView.swift | 83 ++++++++----------- Twigs/Transaction/TransactionListView.swift | 2 +- 5 files changed, 53 insertions(+), 120 deletions(-) delete mode 100644 Twigs/Transaction/TransactionDetails.swift diff --git a/Twigs.xcodeproj/project.pbxproj b/Twigs.xcodeproj/project.pbxproj index 5aff051..5f0a7d2 100644 --- a/Twigs.xcodeproj/project.pbxproj +++ b/Twigs.xcodeproj/project.pbxproj @@ -45,7 +45,6 @@ 8043704728CBF16600F229F9 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8043704628CBF16600F229F9 /* GoogleService-Info.plist */; }; 8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */; }; 8044BA3927828E9D009A78D4 /* CategoryDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */; }; - 8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */; }; 8044BA3D2784CC0D009A78D4 /* TransactionForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3C2784CC0D009A78D4 /* TransactionForm.swift */; }; 8044BA3F27853054009A78D4 /* CategoryForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3E27853054009A78D4 /* CategoryForm.swift */; }; 806C7850272B700B00FA1375 /* TwigsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 806C784F272B700B00FA1375 /* TwigsApp.swift */; }; @@ -144,7 +143,6 @@ 8043704628CBF16600F229F9 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDetailsView.swift; sourceTree = ""; }; 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDataStore.swift; sourceTree = ""; }; - 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionDetails.swift; sourceTree = ""; }; 8044BA3C2784CC0D009A78D4 /* TransactionForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionForm.swift; sourceTree = ""; }; 8044BA3E27853054009A78D4 /* CategoryForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryForm.swift; sourceTree = ""; }; 806C784F272B700B00FA1375 /* TwigsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwigsApp.swift; sourceTree = ""; }; @@ -346,7 +344,6 @@ 28FE6B03234449DC00D5543E /* TransactionListView.swift */, 28FE6B0523444A9800D5543E /* TransactionDetailsView.swift */, 2821265F23555FD300072D52 /* TransactionFormSheet.swift */, - 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */, 8044BA3C2784CC0D009A78D4 /* TransactionForm.swift */, ); path = Transaction; @@ -621,7 +618,6 @@ 2857EAED233DA30B0026BC83 /* LoadingView.swift in Sources */, 282126A3235ABC1800072D52 /* TwigsInMemoryCacheService.swift in Sources */, 800DFC2C277FF47A00EDCE9B /* AsyncData.swift in Sources */, - 8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */, 28B9E50E2346BCB2007C3909 /* RegistrationView.swift in Sources */, 284102322342E12F00EAFA29 /* CategoryListView.swift in Sources */, 8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */, diff --git a/Twigs/DataStore.swift b/Twigs/DataStore.swift index 92d38af..ffdb84d 100644 --- a/Twigs/DataStore.swift +++ b/Twigs/DataStore.swift @@ -103,6 +103,14 @@ class DataStore : ObservableObject { showBudgetSelection = true } } + + func getBudget(_ id: String) -> TwigsCore.Budget? { + if case let .success(budgets) = self.budgets { + return budgets.first(where: { $0.id == id }) + } + + return nil + } func newBudget() { self.budget = .editing(Budget(id: "", name: "", description: "", currencyCode: "")) @@ -252,6 +260,14 @@ class DataStore : ObservableObject { self.categories = .error(error) } } + + func getCategory(_ id: String) -> TwigsCore.Category? { + if case let .success(categories) = self.categories { + return categories.first(where: { $0.id == id }) + } + + return nil + } func save(_ category: TwigsCore.Category) async { self.category = .loading @@ -731,7 +747,7 @@ class DataStore : ObservableObject { self.user = .success(user) } catch { self.errorReporter.reportError(error: error) - self.currentUser = .error(error) + self.user = .error(error) } } } diff --git a/Twigs/Transaction/TransactionDetails.swift b/Twigs/Transaction/TransactionDetails.swift deleted file mode 100644 index af27ac2..0000000 --- a/Twigs/Transaction/TransactionDetails.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// TransactionDetail.swift -// Twigs -// -// Created by William Brawner on 1/4/22. -// Copyright © 2022 William Brawner. All rights reserved. -// - -import Foundation -import TwigsCore - -@MainActor -class TransactionDetails: ObservableObject { - @Published var category: AsyncData = .empty - @Published var budget: AsyncData = .empty - @Published var user: AsyncData = .empty - let apiService: TwigsApiService - - init(_ apiService: TwigsApiService) { - self.apiService = apiService - } - - func loadDetails(_ transaction: TwigsCore.Transaction) async { - Task { - await loadBudget(transaction.budgetId) - } - Task { - if let categoryId = transaction.categoryId { - await loadCategory(categoryId) - } - } - Task { - await loadUser(transaction.createdBy) - } - } - - private func loadBudget(_ id: String) async { - self.budget = .loading - do { - let budget = try await apiService.getBudget(id) - self.budget = .success(budget) - } catch { - self.budget = .error(error) - } - } - - private func loadCategory(_ id: String) async { - self.category = .loading - do { - let category = try await apiService.getCategory(id) - self.category = .success(category) - } catch { - self.category = .error(error) - } - } - - private func loadUser(_ id: String) async { - self.user = .loading - do { - let user = try await apiService.getUser(id) - self.user = .success(user) - } catch { - self.user = .error(error) - } - } -} diff --git a/Twigs/Transaction/TransactionDetailsView.swift b/Twigs/Transaction/TransactionDetailsView.swift index dab9f77..5710a0c 100644 --- a/Twigs/Transaction/TransactionDetailsView.swift +++ b/Twigs/Transaction/TransactionDetailsView.swift @@ -13,7 +13,6 @@ import ArgumentParser struct TransactionDetailsView: View { @EnvironmentObject var apiService: TwigsApiService @EnvironmentObject var dataStore: DataStore - @ObservedObject var transactionDetails: TransactionDetails var editing: Bool { if case .editing(_) = dataStore.transaction { return true @@ -24,9 +23,6 @@ struct TransactionDetailsView: View { return false } - init(_ transactionDetails: TransactionDetails) { - self.transactionDetails = transactionDetails - } private var currentUserId: String? { get { if case let .success(currentUser) = self.dataStore.currentUser { @@ -55,14 +51,13 @@ struct TransactionDetailsView: View { if let description = transaction.description { LabeledField(label: "notes", value: description, loading: .constant(false), showDivider: true) } - CategoryLineItem() - BudgetLineItem() - UserLineItem() - }.padding() - .environmentObject(transactionDetails) - .task { - await transactionDetails.loadDetails(transaction) + if let categoryId = transaction.categoryId { + CategoryLineItem(id: categoryId) } + BudgetLineItem(id: transaction.budgetId) + UserLineItem(id: transaction.createdBy) + } + .padding() } .navigationBarItems(trailing: Button( action: { self.dataStore.editTransaction(transaction) } @@ -92,32 +87,31 @@ struct LabeledField: View { @ViewBuilder var body: some View { - if let val = value, !val.isEmpty { - VStack { - HStack { - Text(self.label) - .foregroundColor(.secondary) - Spacer() - if loading { - EmbeddedLoadingView() - } else { - Text(verbatim: val) - .multilineTextAlignment(.trailing) - } - } - if showDivider { - Divider() + VStack { + HStack { + Text(self.label) + .foregroundColor(.secondary) + Spacer() + if loading { + EmbeddedLoadingView() + } else { + Text(verbatim: self.value ?? "") + .multilineTextAlignment(.trailing) } } + if showDivider { + Divider() + } } } } struct CategoryLineItem: View { - @EnvironmentObject var transactionDetails: TransactionDetails + let id: String + @EnvironmentObject var dataStore: DataStore var value: String { // TODO: Show errors - if case let .success(category) = transactionDetails.category { + if let category = dataStore.getCategory(id) { return category.title } else { return "" @@ -126,19 +120,16 @@ struct CategoryLineItem: View { @ViewBuilder var body: some View { - if case .empty = transactionDetails.category { - EmptyView() - } else { - LabeledField(label: "category", value: value, loading: .constant(self.value == ""), showDivider: true) - } + LabeledField(label: "category", value: value, loading: .constant(self.value == ""), showDivider: true) } } struct BudgetLineItem: View { - @EnvironmentObject var transactionDetails: TransactionDetails + let id: String + @EnvironmentObject var dataStore: DataStore var value: String { // TODO: Show errors - if case let .success(budget) = transactionDetails.budget { + if let budget = dataStore.getBudget(id) { return budget.name } else { return "" @@ -147,19 +138,16 @@ struct BudgetLineItem: View { @ViewBuilder var body: some View { - if case .empty = transactionDetails.budget { - EmptyView() - } else { - LabeledField(label: "budget", value: value, loading: .constant(self.value == ""), showDivider: true) - } + LabeledField(label: "budget", value: value, loading: .constant(self.value == ""), showDivider: true) } } struct UserLineItem: View { - @EnvironmentObject var transactionDetails: TransactionDetails + let id: String + @EnvironmentObject var dataStore: DataStore var value: String { // TODO: Show errors - if case let .success(user) = transactionDetails.user { + if case let .success(user) = dataStore.user, user.id == id { return user.username } else { return "" @@ -168,18 +156,17 @@ struct UserLineItem: View { @ViewBuilder var body: some View { - if case .empty = transactionDetails.user { - EmptyView() - } else { - LabeledField(label: "created_by", value: value, loading: .constant(self.value == ""), showDivider: false) - } + LabeledField(label: "created_by", value: value, loading: .constant(self.value == ""), showDivider: false) + .task { + await dataStore.getUser(id) + } } } #if DEBUG struct TransactionDetailsView_Previews: PreviewProvider { static var previews: some View { - TransactionDetailsView(TransactionDetails(TwigsInMemoryCacheService())) + TransactionDetailsView() } } #endif diff --git a/Twigs/Transaction/TransactionListView.swift b/Twigs/Transaction/TransactionListView.swift index 7c6cad5..046388b 100644 --- a/Twigs/Transaction/TransactionListView.swift +++ b/Twigs/Transaction/TransactionListView.swift @@ -138,7 +138,7 @@ struct TransactionListItemView: View { tag: self.transaction, selection: self.$dataStore.selectedTransaction, destination: { - TransactionDetailsView(TransactionDetails(dataStore.apiService)) + TransactionDetailsView() .navigationBarTitle("details", displayMode: .inline) }, label: {