|
@@ -0,0 +1,216 @@
|
|
|
+//
|
|
|
+// BudgetView.swift
|
|
|
+// ydnab
|
|
|
+//
|
|
|
+// Created by Andrea Franceschini on 23/09/2020.
|
|
|
+//
|
|
|
+
|
|
|
+import SwiftUI
|
|
|
+
|
|
|
+struct BudgetCategoryCell: View {
|
|
|
+ @State var category: BudgetCategory
|
|
|
+ @State var amountText: String
|
|
|
+ @State var color: Color
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ HStack {
|
|
|
+ Text(category.name)
|
|
|
+ Spacer()
|
|
|
+ Text(amountText)
|
|
|
+ .bold()
|
|
|
+ .foregroundColor(color)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct BudgetSectionCell: View {
|
|
|
+ @State var section: BudgetSection
|
|
|
+ @State var amountText: String
|
|
|
+ @State var color: Color
|
|
|
+
|
|
|
+ @Environment(\.editMode) var editMode
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ HStack {
|
|
|
+ Text(section.name)
|
|
|
+ .textCase(.none)
|
|
|
+ Spacer()
|
|
|
+ if editMode?.wrappedValue == .inactive {
|
|
|
+ Text(amountText)
|
|
|
+ .foregroundColor(color)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .padding(.vertical, 11)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct YearAndMonthPicker: View {
|
|
|
+ @Binding var month: Int
|
|
|
+ @Binding var year: Int
|
|
|
+ @State var locale: Locale
|
|
|
+
|
|
|
+ private var monthNames: [String] {
|
|
|
+ var c = Calendar(identifier: .gregorian)
|
|
|
+ c.locale = locale
|
|
|
+ return c.monthSymbols
|
|
|
+ }
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ VStack {
|
|
|
+ HStack {
|
|
|
+ Button(action: { print(self) }) {
|
|
|
+ Image(systemName: "chevron.backward.square")
|
|
|
+ .imageScale(.large)
|
|
|
+ }
|
|
|
+ Spacer()
|
|
|
+ Text("\(year)").bold()
|
|
|
+ Spacer()
|
|
|
+ Button(action: {}) {
|
|
|
+ Image(systemName: "chevron.forward.square")
|
|
|
+ .imageScale(.large)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// GridStack(rows: 4, columns: 3) { row, col in
|
|
|
+// Button(monthNames[row+col], action: { month = row+col+1 })
|
|
|
+// }
|
|
|
+
|
|
|
+// ScrollView(.horizontal) {
|
|
|
+ LazyHGrid(rows: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], alignment: .top, spacing: nil, pinnedViews: []) {
|
|
|
+ ForEach(0..<monthNames.count) { i in
|
|
|
+ Button(monthNames[i], action: { month = i+1 }).padding(40)
|
|
|
+ }
|
|
|
+// }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .padding(.bottom, 11)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct BudgetViewSummary: View {
|
|
|
+ @Binding var budget: BudgetInfo
|
|
|
+ @Binding var month: Int
|
|
|
+ @Binding var year: Int
|
|
|
+
|
|
|
+ @State private var showMonthPicker: Bool = true
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ VStack {
|
|
|
+ HStack {
|
|
|
+ Button("\(month)", action: { withAnimation() { showMonthPicker.toggle() } } )
|
|
|
+ Spacer()
|
|
|
+ }
|
|
|
+ .padding(.vertical, 11)
|
|
|
+
|
|
|
+ if showMonthPicker {
|
|
|
+ YearAndMonthPicker(month: $month, year: $year, locale: Locale(identifier: budget.localeIdentifier))
|
|
|
+ }
|
|
|
+
|
|
|
+ HStack {
|
|
|
+ Text("To budget") // Or "overbudgeted"
|
|
|
+ Spacer()
|
|
|
+ Text("$ 0.00")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .padding(.vertical, 11)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct BudgetView: View {
|
|
|
+ @State var budget: BudgetInfo
|
|
|
+ @Binding var currentBudgetId: UUID?
|
|
|
+ @State private var month: Int = 0
|
|
|
+ @State private var year: Int = 0
|
|
|
+
|
|
|
+ @AppStorage("lastLoadedBudgetId") private var lastLoadedBudgetId = ""
|
|
|
+
|
|
|
+ func formatAmount(_ amount: NSNumber) -> String? {
|
|
|
+ let f = NumberFormatter()
|
|
|
+ f.locale = Locale(identifier: budget.localeIdentifier)
|
|
|
+ f.numberStyle = .currency
|
|
|
+ return f.string(from: amount)
|
|
|
+ }
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ VStack {
|
|
|
+ BudgetViewSummary(budget: $budget, month: $month, year: $year)
|
|
|
+ .padding([.leading, .trailing], 16)
|
|
|
+
|
|
|
+ List {
|
|
|
+ ForEach(budget.sections) { section in
|
|
|
+ if !section.hidden {
|
|
|
+ Section(header: BudgetSectionCell(section: section,
|
|
|
+ amountText: formatAmount(0) ?? "--",
|
|
|
+ color: 0 < 0 ? Color("negativeAmount") : Color("positiveAmount"))
|
|
|
+ ) {
|
|
|
+ ForEach(section.categories) { category in
|
|
|
+ if !category.hidden {
|
|
|
+ BudgetCategoryCell(category: category,
|
|
|
+ amountText: formatAmount(0) ?? "--",
|
|
|
+ color: 0 < 0 ? Color("negativeAmount") : Color("positiveAmount")
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .onMove { (indexSet, s) in
|
|
|
+ print(indexSet, s)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .onMove { (indexSet, s) in
|
|
|
+ print(indexSet, s)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .listStyle(PlainListStyle())
|
|
|
+ .navigationBarTitle(budget.name, displayMode: .inline)
|
|
|
+ .toolbar {
|
|
|
+ EditButton()
|
|
|
+ }
|
|
|
+ .onAppear() {
|
|
|
+ print("BudgetView Appears")
|
|
|
+ currentBudgetId = budget.id
|
|
|
+ lastLoadedBudgetId = budget.id.uuidString
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct BudgetView_Previews: PreviewProvider {
|
|
|
+ static let budget: [BudgetSection] = [
|
|
|
+ BudgetSection(name: "Everyday Expenses", categories: [
|
|
|
+ BudgetCategory(name: "Groceries"),
|
|
|
+ BudgetCategory(name: "Eating out"),
|
|
|
+ BudgetCategory(name: "Medical"),
|
|
|
+ BudgetCategory(name: "Clothing"),
|
|
|
+ BudgetCategory(name: "Household goods")
|
|
|
+ ]),
|
|
|
+ BudgetSection(name: "Travel", categories: [
|
|
|
+ BudgetCategory(name: "Transport"),
|
|
|
+ BudgetCategory(name: "Fuel"),
|
|
|
+ BudgetCategory(name: "Accommodation")
|
|
|
+ ]),
|
|
|
+ BudgetSection(name: "Rainy Days", categories: [
|
|
|
+ BudgetCategory(name: "Emergencies"),
|
|
|
+ BudgetCategory(name: "Car insurance")
|
|
|
+ ]),
|
|
|
+ BudgetSection(name: "Monthly Expenses", categories: [
|
|
|
+ BudgetCategory(name: "Rent"),
|
|
|
+ BudgetCategory(name: "Mobile")
|
|
|
+ ]),
|
|
|
+ BudgetSection(name: "Savings Goals", categories: [
|
|
|
+ BudgetCategory(name: "Savings"),
|
|
|
+ BudgetCategory(name: "Holidays")
|
|
|
+ ])
|
|
|
+ ]
|
|
|
+ @State static var currentBudgetId: UUID?
|
|
|
+
|
|
|
+ static var previews: some View {
|
|
|
+ NavigationView {
|
|
|
+ BudgetView(budget: BudgetInfo(name: "Default Budget", sections: budget),
|
|
|
+ currentBudgetId: $currentBudgetId)
|
|
|
+ }
|
|
|
+ .preferredColorScheme(.light)
|
|
|
+ //.environment(\.layoutDirection, .rightToLeft)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|