Update budget details view and fix some loading issues

This commit is contained in:
William Brawner 2021-11-30 20:03:46 -07:00
parent 5fd73bf0bc
commit c5647a0553
6 changed files with 77 additions and 59 deletions

View file

@ -10,45 +10,66 @@ import SwiftUI
struct BudgetDetailsView: View {
@EnvironmentObject var budgetDataStore: BudgetsDataStore
@State var requestedOverview = ""
let budget: Budget
@ViewBuilder
var body: some View {
ScrollView {
VStack {
switch budgetDataStore.overview {
case .failure(.loading):
ActivityIndicator(isAnimating: .constant(true), style: .large)
case .success(let overview):
Text("current_balance")
Text(verbatim: overview.balance.toCurrencyString())
.foregroundColor(overview.balance < 0 ? .red : .green)
Text("expected_income")
Text(verbatim: overview.expectedIncome.toCurrencyString())
Text("actual_income")
Text(verbatim: overview.actualIncome.toCurrencyString())
.foregroundColor(.green)
Text("expected_expenses")
Text(verbatim: overview.expectedExpenses.toCurrencyString())
Text("actual_expenses")
Text(verbatim: overview.actualExpenses.toCurrencyString())
.foregroundColor(.red)
default:
Text("An error has ocurred")
switch budgetDataStore.overview {
case .failure(.loading):
ActivityIndicator(isAnimating: .constant(true), style: .large)
case .success(let overview):
List {
Section(overview.budget.name) {
VStack(alignment: .leading) {
if let description = overview.budget.description {
Text(description)
}
HStack {
Text("current_balance")
Text(verbatim: overview.balance.toCurrencyString())
.foregroundColor(overview.balance < 0 ? .red : .green)
}
}
}
}.onAppear {
if requestedOverview != budget.id {
requestedOverview = budget.id
budgetDataStore.loadOverview(budget)
Section("income") {
VStack(alignment: .leading) {
HStack {
Text("expected")
Text(verbatim: overview.expectedIncome.toCurrencyString())
}
ProgressView(value: Float(overview.expectedIncome), maxValue: Float(max(overview.expectedIncome, overview.actualIncome)), progressTintColor: .gray, progressBarHeight: 10.0, progressBarCornerRadius: 4.0)
HStack {
Text("actual")
Text(verbatim: overview.actualIncome.toCurrencyString())
.foregroundColor(.green)
}
ProgressView(value: Float(overview.actualIncome), maxValue: Float(max(overview.expectedIncome, overview.actualIncome)), progressTintColor: .green, progressBarHeight: 10.0, progressBarCornerRadius: 4.0)
}
}
}
Section("expenses") {
VStack(alignment: .leading) {
HStack {
Text("expected")
Text(verbatim: overview.expectedExpenses.toCurrencyString())
}
ProgressView(value: Float(overview.expectedExpenses), maxValue: Float(max(overview.expectedExpenses, overview.actualExpenses)), progressTintColor: .gray, progressBarHeight: 10.0, progressBarCornerRadius: 4.0)
HStack {
Text("actual")
Text(verbatim: overview.actualExpenses.toCurrencyString())
.foregroundColor(.red)
}
ProgressView(value: Float(overview.actualExpenses), maxValue: Float(max(overview.expectedExpenses, overview.actualExpenses)), progressTintColor: .red, progressBarHeight: 10.0, progressBarCornerRadius: 4.0)
}
}
}.listStyle(.insetGrouped)
.navigationBarItems(leading: HStack {
Button("budgets", action: {
self.budgetDataStore.showBudgetSelection = true
}).padding()
})
default:
Text("An error has ocurred")
}
.navigationBarItems(trailing: HStack {
Button("budgets", action: {
self.budgetDataStore.deselectBudget()
}).padding()
})
}
}

View file

@ -34,8 +34,6 @@ struct BudgetListsView: View {
self.budgetDataStore.getBudgets()
})
}
}.onAppear {
self.budgetDataStore.getBudgets()
}
}
}

View file

@ -19,17 +19,13 @@ class BudgetsDataStore: ObservableObject {
didSet {
if case let .success(budget) = self.budget {
UserDefaults.standard.set(budget.id, forKey: LAST_BUDGET)
self.showBudgetSelection = false
loadOverview(budget)
}
}
}
@Published var overview: Result<BudgetOverview, NetworkError> = .failure(.loading)
var showBudgetSelection: Bool {
get {
return self.budget == nil
}
set { }
}
@Published var showBudgetSelection: Bool = true
init(budgetRepository: BudgetRepository, categoryRepository: CategoryRepository, transactionRepository: TransactionRepository) {
self.budgetRepository = budgetRepository
@ -62,7 +58,9 @@ class BudgetsDataStore: ObservableObject {
}
}, receiveValue: { (budgets) in
self.budgets = .success(budgets.sorted(by: { $0.name < $1.name }))
if self.budget != nil {
if case .success(_) = self.budget {
// Don't do anything here
} else {
if let id = UserDefaults.standard.string(forKey: LAST_BUDGET) {
if let budget = budgets.first(where: { $0.id == id }) {
self.budget = .success(budget)
@ -70,7 +68,11 @@ class BudgetsDataStore: ObservableObject {
self.budget = nil
}
} else {
self.budget = nil
if let budget = budgets.first {
self.budget = .success(budget)
} else {
self.budget = nil
}
}
}
})
@ -174,14 +176,8 @@ class BudgetsDataStore: ObservableObject {
}
func selectBudget(_ budget: Budget) {
self.objectWillChange.send()
self.budget = .success(budget)
}
func deselectBudget() {
self.objectWillChange.send()
self.budget = nil
}
}
private let LAST_BUDGET = "LAST_BUDGET"

View file

@ -71,7 +71,7 @@ struct TabbedBudgetView: View {
.keyboardShortcut("4")
}
} else {
Text("Loading…")
ActivityIndicator(isAnimating: .constant(true), style: .large)
}
}
@ -83,12 +83,15 @@ struct TabbedBudgetView: View {
content: {
LoginView()
.environmentObject(authenticationDataStore)
.onDisappear {
self.budgetDataStore.getBudgets()
}
}).sheet(isPresented: $budgetDataStore.showBudgetSelection,
content: {
BudgetListsView()
.environmentObject(budgetDataStore)
})
.interactiveDismissDisabled(!hasSelectedBudget)
.interactiveDismissDisabled(true)
}
}

View file

@ -62,10 +62,10 @@
"budget" = "Budget";
"budgets" = "Budgets";
"current_balance" = "Current Balance:";
"expected_income" = "Expected Income:";
"actual_income" = "Actual Income:";
"expected_expenses" = "Expected Expenses:";
"actual_expenses" = "Actual Expenses:";
"expected" = "Expected:";
"actual" = "Actual:";
"income" = "Income:";
"expenses" = "Expenses:";
// MARK: Profile
"profile" = "Profile";

View file

@ -62,10 +62,10 @@
"budget" = "Presupuesto";
"budgets" = "Presupuestos";
"current_balance" = "Saldo Actual:";
"expected_income" = "Ingresos Estimados:";
"actual_income" = "Ingresos Actuales:";
"expected_expenses" = "Gastos Estimados:";
"actual_expenses" = "Gastos Actuales:";
"income" = "Ingresos:";
"expenses" = "Gastos:";
"expected" = "Planeados:";
"actual" = "Actuales:";
// MARK: Profile