Fix category list showing all transactions
This commit is contained in:
parent
9fdd8bf517
commit
c4555fe804
5 changed files with 74 additions and 72 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -88,3 +88,4 @@ fastlane/test_output
|
||||||
# https://github.com/johnno1962/injectionforxcode
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
iOSInjectionProject/
|
iOSInjectionProject/
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
801D08CE275F189E00931465 /* RecurringTransactionsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08CD275F189E00931465 /* RecurringTransactionsRepository.swift */; };
|
801D08CE275F189E00931465 /* RecurringTransactionsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08CD275F189E00931465 /* RecurringTransactionsRepository.swift */; };
|
||||||
801D08D2275FB7DE00931465 /* RecurringTransactionDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */; };
|
801D08D2275FB7DE00931465 /* RecurringTransactionDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */; };
|
||||||
802161D0277647920075761A /* AsyncObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 802161CF277647920075761A /* AsyncObservableObject.swift */; };
|
802161D0277647920075761A /* AsyncObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 802161CF277647920075761A /* AsyncObservableObject.swift */; };
|
||||||
8021EFAD280A0FCA00043F18 /* TwigsCore in Frameworks */ = {isa = PBXBuildFile; productRef = 8021EFAC280A0FCA00043F18 /* TwigsCore */; };
|
|
||||||
8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */; };
|
8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */; };
|
||||||
8044BA3927828E9D009A78D4 /* CategoryDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */; };
|
8044BA3927828E9D009A78D4 /* CategoryDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */; };
|
||||||
8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */; };
|
8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */; };
|
||||||
|
@ -59,6 +58,7 @@
|
||||||
80AC75CD284E8E100099E846 /* EditPasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AC75CC284E8E100099E846 /* EditPasswordView.swift */; };
|
80AC75CD284E8E100099E846 /* EditPasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AC75CC284E8E100099E846 /* EditPasswordView.swift */; };
|
||||||
80AC75CF284E8E1B0099E846 /* EditEmailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AC75CE284E8E1B0099E846 /* EditEmailView.swift */; };
|
80AC75CF284E8E1B0099E846 /* EditEmailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AC75CE284E8E1B0099E846 /* EditEmailView.swift */; };
|
||||||
80AF7A982835ED3B009565C6 /* RecurringTransactionFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AF7A972835ED3B009565C6 /* RecurringTransactionFormView.swift */; };
|
80AF7A982835ED3B009565C6 /* RecurringTransactionFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AF7A972835ED3B009565C6 /* RecurringTransactionFormView.swift */; };
|
||||||
|
80D06DD1288C817800B50467 /* TwigsCore in Frameworks */ = {isa = PBXBuildFile; productRef = 80D06DD0288C817800B50467 /* TwigsCore */; };
|
||||||
80D1FC14277C1EF9007F17FB /* InlineLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D1FC13277C1EF9007F17FB /* InlineLoadingView.swift */; };
|
80D1FC14277C1EF9007F17FB /* InlineLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D1FC13277C1EF9007F17FB /* InlineLoadingView.swift */; };
|
||||||
80D2CE1A2833448500EDD6C2 /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D2CE192833448500EDD6C2 /* DataStore.swift */; };
|
80D2CE1A2833448500EDD6C2 /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80D2CE192833448500EDD6C2 /* DataStore.swift */; };
|
||||||
80FC1BBE28411DD800682F21 /* YearlyFrequencyPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80FC1BBD28411DD800682F21 /* YearlyFrequencyPicker.swift */; };
|
80FC1BBE28411DD800682F21 /* YearlyFrequencyPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80FC1BBD28411DD800682F21 /* YearlyFrequencyPicker.swift */; };
|
||||||
|
@ -166,7 +166,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
8021EFAD280A0FCA00043F18 /* TwigsCore in Frameworks */,
|
80D06DD1288C817800B50467 /* TwigsCore in Frameworks */,
|
||||||
8076A8522809FE99006B9DC9 /* Collections in Frameworks */,
|
8076A8522809FE99006B9DC9 /* Collections in Frameworks */,
|
||||||
8076A84F2809FE8E006B9DC9 /* ArgumentParser in Frameworks */,
|
8076A84F2809FE8E006B9DC9 /* ArgumentParser in Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -413,7 +413,7 @@
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
8076A84E2809FE8E006B9DC9 /* ArgumentParser */,
|
8076A84E2809FE8E006B9DC9 /* ArgumentParser */,
|
||||||
8076A8512809FE99006B9DC9 /* Collections */,
|
8076A8512809FE99006B9DC9 /* Collections */,
|
||||||
8021EFAC280A0FCA00043F18 /* TwigsCore */,
|
80D06DD0288C817800B50467 /* TwigsCore */,
|
||||||
);
|
);
|
||||||
productName = Budget;
|
productName = Budget;
|
||||||
productReference = 28AC94EA233C373900BFB70A /* Twigs.app */;
|
productReference = 28AC94EA233C373900BFB70A /* Twigs.app */;
|
||||||
|
@ -800,7 +800,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 16;
|
CURRENT_PROJECT_VERSION = 18;
|
||||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
||||||
|
@ -829,7 +829,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 16;
|
CURRENT_PROJECT_VERSION = 18;
|
||||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
||||||
|
@ -1057,10 +1057,6 @@
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
8021EFAC280A0FCA00043F18 /* TwigsCore */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = TwigsCore;
|
|
||||||
};
|
|
||||||
8076A84E2809FE8E006B9DC9 /* ArgumentParser */ = {
|
8076A84E2809FE8E006B9DC9 /* ArgumentParser */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
||||||
|
@ -1076,6 +1072,10 @@
|
||||||
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
||||||
productName = ArgumentParser;
|
productName = ArgumentParser;
|
||||||
};
|
};
|
||||||
|
80D06DD0288C817800B50467 /* TwigsCore */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = TwigsCore;
|
||||||
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 28AC94E2233C373900BFB70A /* Project object */;
|
rootObject = 28AC94E2233C373900BFB70A /* Project object */;
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct CategoryDetailsView: View {
|
||||||
return LocalizedStringKey("amount_earned")
|
return LocalizedStringKey("amount_earned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let category = dataStore.selectedCategory {
|
if let category = dataStore.selectedCategory {
|
||||||
TransactionListView() {
|
TransactionListView() {
|
||||||
|
@ -65,7 +65,7 @@ struct CategoryDetailsView: View {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init (_ budget: Budget) {
|
init (_ budget: Budget) {
|
||||||
self.budget = budget
|
self.budget = budget
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var budgetId: String? {
|
var budgetId: String? {
|
||||||
get {
|
get {
|
||||||
if case let .success(budget) = self.budget {
|
if case let .success(budget) = self.budget {
|
||||||
|
@ -54,7 +54,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var categoryId: String? {
|
var categoryId: String? {
|
||||||
get {
|
get {
|
||||||
if case let .success(category) = self.category {
|
if case let .success(category) = self.category {
|
||||||
|
@ -74,7 +74,7 @@ class DataStore : ObservableObject {
|
||||||
self.token = UserDefaults.standard.string(forKey: KEY_TOKEN)
|
self.token = UserDefaults.standard.string(forKey: KEY_TOKEN)
|
||||||
self.userId = UserDefaults.standard.string(forKey: KEY_USER_ID)
|
self.userId = UserDefaults.standard.string(forKey: KEY_USER_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBudgets(count: Int? = nil, page: Int? = nil) async {
|
func getBudgets(count: Int? = nil, page: Int? = nil) async {
|
||||||
// TODO: Find some way to extract this to a generic function
|
// TODO: Find some way to extract this to a generic function
|
||||||
self.budgets = .loading
|
self.budgets = .loading
|
||||||
|
@ -99,11 +99,11 @@ class DataStore : ObservableObject {
|
||||||
showBudgetSelection = true
|
showBudgetSelection = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBudget() {
|
func newBudget() {
|
||||||
self.budget = .editing(Budget(id: "", name: "", description: "", currencyCode: ""))
|
self.budget = .editing(Budget(id: "", name: "", description: "", currencyCode: ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
func save(_ budget: Budget) async {
|
func save(_ budget: Budget) async {
|
||||||
self.budget = .saving(budget)
|
self.budget = .saving(budget)
|
||||||
do {
|
do {
|
||||||
|
@ -123,7 +123,7 @@ class DataStore : ObservableObject {
|
||||||
self.budget = .error(error, budget)
|
self.budget = .error(error, budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteBudget() async {
|
func deleteBudget() async {
|
||||||
guard case let .editing(budget) = self.budget, budget.id != "" else {
|
guard case let .editing(budget) = self.budget, budget.id != "" else {
|
||||||
return
|
return
|
||||||
|
@ -139,7 +139,7 @@ class DataStore : ObservableObject {
|
||||||
self.budget = .error(error, budget)
|
self.budget = .error(error, budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelEditBudget() async {
|
func cancelEditBudget() async {
|
||||||
guard case let .success(budgets) = self.budgets else {
|
guard case let .success(budgets) = self.budgets else {
|
||||||
return
|
return
|
||||||
|
@ -153,7 +153,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
await self.selectBudget(budget)
|
await self.selectBudget(budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadOverview(showLoader: Bool = true) async {
|
func loadOverview(showLoader: Bool = true) async {
|
||||||
guard case let .success(budget) = self.budget else {
|
guard case let .success(budget) = self.budget else {
|
||||||
return
|
return
|
||||||
|
@ -178,7 +178,7 @@ class DataStore : ObservableObject {
|
||||||
} else {
|
} else {
|
||||||
budgetOverview.expectedIncome += category.amount
|
budgetOverview.expectedIncome += category.amount
|
||||||
}
|
}
|
||||||
|
|
||||||
if category.expense {
|
if category.expense {
|
||||||
budgetOverview.actualExpenses += abs(response.balance)
|
budgetOverview.actualExpenses += abs(response.balance)
|
||||||
} else {
|
} else {
|
||||||
|
@ -191,7 +191,7 @@ class DataStore : ObservableObject {
|
||||||
self.overview = .error(error)
|
self.overview = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectBudget(_ budget: Budget?) async {
|
func selectBudget(_ budget: Budget?) async {
|
||||||
if let budget = budget {
|
if let budget = budget {
|
||||||
self.budget = .success(budget)
|
self.budget = .success(budget)
|
||||||
|
@ -206,7 +206,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransactions = .empty
|
self.recurringTransactions = .empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func editBudget() {
|
func editBudget() {
|
||||||
guard case let .success(budget) = self.budget else {
|
guard case let .success(budget) = self.budget else {
|
||||||
return
|
return
|
||||||
|
@ -225,14 +225,14 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var selectedCategory: TwigsCore.Category? = nil
|
@Published var selectedCategory: TwigsCore.Category? = nil
|
||||||
|
|
||||||
func getCategories(showLoader: Bool = true) async {
|
func getCategories(showLoader: Bool = true) async {
|
||||||
guard case let .success(budget) = self.budget else {
|
guard case let .success(budget) = self.budget else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await self.getCategories(budgetId: budget.id, showLoader: showLoader)
|
await self.getCategories(budgetId: budget.id, showLoader: showLoader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCategories(budgetId: String, expense: Bool? = nil, archived: Bool? = false, count: Int? = nil, page: Int? = nil, showLoader: Bool = true) async {
|
func getCategories(budgetId: String, expense: Bool? = nil, archived: Bool? = false, count: Int? = nil, page: Int? = nil, showLoader: Bool = true) async {
|
||||||
if showLoader {
|
if showLoader {
|
||||||
self.categories = .loading
|
self.categories = .loading
|
||||||
|
@ -244,7 +244,7 @@ class DataStore : ObservableObject {
|
||||||
self.categories = .error(error)
|
self.categories = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func save(_ category: TwigsCore.Category) async {
|
func save(_ category: TwigsCore.Category) async {
|
||||||
self.category = .loading
|
self.category = .loading
|
||||||
do {
|
do {
|
||||||
|
@ -265,7 +265,7 @@ class DataStore : ObservableObject {
|
||||||
self.category = .error(error, category)
|
self.category = .error(error, category)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func delete(_ category: TwigsCore.Category) async {
|
func delete(_ category: TwigsCore.Category) async {
|
||||||
self.category = .loading
|
self.category = .loading
|
||||||
do {
|
do {
|
||||||
|
@ -279,12 +279,12 @@ class DataStore : ObservableObject {
|
||||||
self.category = .error(error, category)
|
self.category = .error(error, category)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func edit(_ category: TwigsCore.Category) async {
|
func edit(_ category: TwigsCore.Category) async {
|
||||||
self.editingCategory = true
|
self.editingCategory = true
|
||||||
self.category = .editing(category)
|
self.category = .editing(category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelEditCategory() {
|
func cancelEditCategory() {
|
||||||
self.editingCategory = false
|
self.editingCategory = false
|
||||||
if let category = self.selectedCategory {
|
if let category = self.selectedCategory {
|
||||||
|
@ -313,7 +313,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var selectedRecurringTransaction: RecurringTransaction? = nil
|
@Published var selectedRecurringTransaction: RecurringTransaction? = nil
|
||||||
|
|
||||||
func getRecurringTransactions(showLoader: Bool = true) async {
|
func getRecurringTransactions(showLoader: Bool = true) async {
|
||||||
guard case let .success(budget) = self.budget else {
|
guard case let .success(budget) = self.budget else {
|
||||||
return
|
return
|
||||||
|
@ -328,7 +328,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransactions = .error(error)
|
self.recurringTransactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRecurringTransaction() {
|
func newRecurringTransaction() {
|
||||||
guard case let .success(user) = self.currentUser else {
|
guard case let .success(user) = self.currentUser else {
|
||||||
return
|
return
|
||||||
|
@ -338,11 +338,11 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
self.recurringTransaction = .editing(RecurringTransaction(createdBy: user.id, budgetId: budget.id))
|
self.recurringTransaction = .editing(RecurringTransaction(createdBy: user.id, budgetId: budget.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func edit(_ transaction: RecurringTransaction) async {
|
func edit(_ transaction: RecurringTransaction) async {
|
||||||
self.recurringTransaction = .editing(transaction)
|
self.recurringTransaction = .editing(transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelEditRecurringTransaction() {
|
func cancelEditRecurringTransaction() {
|
||||||
guard case let .editing(rt) = self.recurringTransaction else {
|
guard case let .editing(rt) = self.recurringTransaction else {
|
||||||
return
|
return
|
||||||
|
@ -353,7 +353,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransaction = .empty
|
self.recurringTransaction = .empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveRecurringTransaction(_ transaction: RecurringTransaction) async {
|
func saveRecurringTransaction(_ transaction: RecurringTransaction) async {
|
||||||
self.recurringTransaction = .loading
|
self.recurringTransaction = .loading
|
||||||
do {
|
do {
|
||||||
|
@ -377,7 +377,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransactions = .error(error)
|
self.recurringTransactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteRecurringTransaction(_ transaction: RecurringTransaction) async {
|
func deleteRecurringTransaction(_ transaction: RecurringTransaction) async {
|
||||||
self.recurringTransaction = .loading
|
self.recurringTransaction = .loading
|
||||||
do {
|
do {
|
||||||
|
@ -390,7 +390,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransaction = .error(error, transaction)
|
self.recurringTransaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearSelectedRecurringTransaction() {
|
func clearSelectedRecurringTransaction() {
|
||||||
self.recurringTransaction = .empty
|
self.recurringTransaction = .empty
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var selectedTransaction: Transaction? = nil
|
@Published var selectedTransaction: Transaction? = nil
|
||||||
|
|
||||||
func getTransactions(showLoader: Bool = true) async {
|
func getTransactions(showLoader: Bool = true) async {
|
||||||
guard let budgetId = self.budgetId else {
|
guard let budgetId = self.budgetId else {
|
||||||
self.transactions = .error(NetworkError.unknown)
|
self.transactions = .error(NetworkError.unknown)
|
||||||
|
@ -434,7 +434,7 @@ class DataStore : ObservableObject {
|
||||||
self.transactions = .error(error)
|
self.transactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveTransaction(_ transaction: Transaction) async {
|
func saveTransaction(_ transaction: Transaction) async {
|
||||||
self.transaction = .saving(transaction)
|
self.transaction = .saving(transaction)
|
||||||
do {
|
do {
|
||||||
|
@ -454,7 +454,7 @@ class DataStore : ObservableObject {
|
||||||
self.transaction = .error(error, transaction)
|
self.transaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTransaction(_ transaction: Transaction) async {
|
func deleteTransaction(_ transaction: Transaction) async {
|
||||||
self.transaction = .loading
|
self.transaction = .loading
|
||||||
do {
|
do {
|
||||||
|
@ -465,7 +465,7 @@ class DataStore : ObservableObject {
|
||||||
self.transaction = .error(error, transaction)
|
self.transaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTransaction() {
|
func newTransaction() {
|
||||||
var budgetId = ""
|
var budgetId = ""
|
||||||
if case let .success(budget) = self.budget {
|
if case let .success(budget) = self.budget {
|
||||||
|
@ -481,7 +481,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
self.transaction = .editing(TwigsCore.Transaction(categoryId: categoryId, createdBy: createdBy, budgetId: budgetId))
|
self.transaction = .editing(TwigsCore.Transaction(categoryId: categoryId, createdBy: createdBy, budgetId: budgetId))
|
||||||
}
|
}
|
||||||
|
|
||||||
func editTransaction(_ transaction: Transaction) {
|
func editTransaction(_ transaction: Transaction) {
|
||||||
self.transaction = .editing(transaction)
|
self.transaction = .editing(transaction)
|
||||||
}
|
}
|
||||||
|
@ -493,11 +493,11 @@ class DataStore : ObservableObject {
|
||||||
self.transaction = .empty
|
self.transaction = .empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearSelectedTransaction() {
|
func clearSelectedTransaction() {
|
||||||
self.transaction = .empty
|
self.transaction = .empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var currentUser: AsyncData<User> = .empty {
|
@Published var currentUser: AsyncData<User> = .empty {
|
||||||
didSet {
|
didSet {
|
||||||
switch currentUser {
|
switch currentUser {
|
||||||
|
@ -510,7 +510,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let KEY_BASE_URL = "BASE_URL"
|
private let KEY_BASE_URL = "BASE_URL"
|
||||||
private let KEY_TOKEN = "TOKEN"
|
private let KEY_TOKEN = "TOKEN"
|
||||||
private let KEY_USER_ID = "USER_ID"
|
private let KEY_USER_ID = "USER_ID"
|
||||||
|
@ -533,11 +533,11 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Published var showLogin: Bool = true
|
@Published var showLogin: Bool = true
|
||||||
|
|
||||||
func clearUserError() {
|
func clearUserError() {
|
||||||
self.currentUser = .empty
|
self.currentUser = .empty
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(username: String, password: String) async {
|
func login(username: String, password: String) async {
|
||||||
if baseUrl.isEmpty {
|
if baseUrl.isEmpty {
|
||||||
self.currentUser = .error(NetworkError.invalidUrl)
|
self.currentUser = .error(NetworkError.invalidUrl)
|
||||||
|
@ -559,7 +559,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .error(error)
|
self.currentUser = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(username: String, email: String, password: String, confirmPassword: String) async {
|
func register(username: String, email: String, password: String, confirmPassword: String) async {
|
||||||
if baseUrl.isEmpty {
|
if baseUrl.isEmpty {
|
||||||
self.currentUser = .error(NetworkError.invalidUrl)
|
self.currentUser = .error(NetworkError.invalidUrl)
|
||||||
|
@ -595,7 +595,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
await self.login(username: username, password: password)
|
await self.login(username: username, password: password)
|
||||||
}
|
}
|
||||||
|
|
||||||
func logout() {
|
func logout() {
|
||||||
self.budgets = .empty
|
self.budgets = .empty
|
||||||
self.budget = .empty
|
self.budget = .empty
|
||||||
|
@ -615,7 +615,7 @@ class DataStore : ObservableObject {
|
||||||
UserDefaults.standard.removeObject(forKey: KEY_TOKEN)
|
UserDefaults.standard.removeObject(forKey: KEY_TOKEN)
|
||||||
UserDefaults.standard.removeObject(forKey: KEY_USER_ID)
|
UserDefaults.standard.removeObject(forKey: KEY_USER_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadProfile() async {
|
func loadProfile() async {
|
||||||
guard let userId = self.userId, !userId.isEmpty else {
|
guard let userId = self.userId, !userId.isEmpty else {
|
||||||
return
|
return
|
||||||
|
@ -628,7 +628,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .error(error)
|
self.currentUser = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUsername(_ username: String) async -> UsernameError? {
|
func updateUsername(_ username: String) async -> UsernameError? {
|
||||||
guard case let .success(current) = self.currentUser else {
|
guard case let .success(current) = self.currentUser else {
|
||||||
return .unknown
|
return .unknown
|
||||||
|
@ -643,7 +643,7 @@ class DataStore : ObservableObject {
|
||||||
return .unavailable
|
return .unavailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateEmail(_ email: String) async -> EmailError? {
|
func updateEmail(_ email: String) async -> EmailError? {
|
||||||
guard case let .success(current) = self.currentUser else {
|
guard case let .success(current) = self.currentUser else {
|
||||||
return .unknown
|
return .unknown
|
||||||
|
@ -661,7 +661,7 @@ class DataStore : ObservableObject {
|
||||||
return .unavailable
|
return .unavailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePassword(_ password: String, confirmPassword: String) async -> PasswordError? {
|
func updatePassword(_ password: String, confirmPassword: String) async -> PasswordError? {
|
||||||
guard case let .success(current) = self.currentUser else {
|
guard case let .success(current) = self.currentUser else {
|
||||||
return .unknown
|
return .unknown
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private func TransactionList(_ transactions: OrderedDictionary<String, [TwigsCore.Transaction]>) -> some View {
|
private func TransactionList(_ transactions: OrderedDictionary<String, [TwigsCore.Transaction]>) -> some View {
|
||||||
if transactions.isEmpty {
|
if transactions.isEmpty {
|
||||||
|
@ -37,10 +37,21 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
}
|
}
|
||||||
ForEach(transactions.keys, id: \.self) { (key: String) in
|
ForEach(transactions.keys, id: \.self) { (key: String) in
|
||||||
Group {
|
Group {
|
||||||
let filtered = search.isEmpty ? transactions[key]! : transactions[key]!.filter { $0.title.lowercased().contains(search.lowercased())
|
let filtered = transactions[key]!
|
||||||
|| $0.description?.lowercased().contains(search.lowercased()) ?? false
|
.filter {
|
||||||
|| $0.amount.toCurrencyString().contains(search)
|
if let categoryId = dataStore.selectedCategory?.id {
|
||||||
}
|
if $0.categoryId != categoryId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !search.isEmpty {
|
||||||
|
return $0.title.lowercased().contains(search.lowercased())
|
||||||
|
|| $0.description?.lowercased().contains(search.lowercased()) ?? false
|
||||||
|
|| $0.amount.toCurrencyString().contains(search)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
if !filtered.isEmpty {
|
if !filtered.isEmpty {
|
||||||
Section(header: Text(key)) {
|
Section(header: Text(key)) {
|
||||||
ForEach(filtered) { transaction in
|
ForEach(filtered) { transaction in
|
||||||
|
@ -52,7 +63,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var currentUserId: String? {
|
private var currentUserId: String? {
|
||||||
get {
|
get {
|
||||||
if case let .success(currentUser) = dataStore.currentUser {
|
if case let .success(currentUser) = dataStore.currentUser {
|
||||||
|
@ -62,7 +73,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var budgetId: String? {
|
private var budgetId: String? {
|
||||||
get {
|
get {
|
||||||
if case let .success(budget) = dataStore.budget {
|
if case let .success(budget) = dataStore.budget {
|
||||||
|
@ -72,16 +83,6 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var categoryId: String? {
|
|
||||||
get {
|
|
||||||
if case let .success(category) = dataStore.category {
|
|
||||||
return category.id
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -104,7 +105,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
dataStore: dataStore,
|
dataStore: dataStore,
|
||||||
createdBy: currentUserId ?? "",
|
createdBy: currentUserId ?? "",
|
||||||
budgetId: budgetId ?? "",
|
budgetId: budgetId ?? "",
|
||||||
categoryId: categoryId,
|
categoryId: dataStore.categoryId,
|
||||||
transaction: nil
|
transaction: nil
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -120,7 +121,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(header: (() -> Content)? = nil) {
|
init(header: (() -> Content)? = nil) {
|
||||||
self.header = header
|
self.header = header
|
||||||
}
|
}
|
||||||
|
@ -129,7 +130,7 @@ struct TransactionListView<Content>: View where Content: View {
|
||||||
struct TransactionListItemView: View {
|
struct TransactionListItemView: View {
|
||||||
@EnvironmentObject var dataStore: DataStore
|
@EnvironmentObject var dataStore: DataStore
|
||||||
var transaction: TwigsCore.Transaction
|
var transaction: TwigsCore.Transaction
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationLink(
|
NavigationLink(
|
||||||
tag: self.transaction,
|
tag: self.transaction,
|
||||||
|
@ -163,7 +164,7 @@ struct TransactionListItemView: View {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
init (_ transaction: TwigsCore.Transaction) {
|
init (_ transaction: TwigsCore.Transaction) {
|
||||||
self.transaction = transaction
|
self.transaction = transaction
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue