Browse Source

Use DynamicFetchView to pull budget entries

Andrea Franceschini 4 years ago
parent
commit
83b965dbdf
3 changed files with 121 additions and 120 deletions
  1. 4 0
      ydnab.xcodeproj/project.pbxproj
  2. 96 120
      ydnab/Views/BudgetView.swift
  3. 21 0
      ydnab/Views/DynamicFetchView.swift

+ 4 - 0
ydnab.xcodeproj/project.pbxproj

@@ -18,6 +18,7 @@
 		A36E59E3251A79F0003DA5B3 /* Budget.swift in Sources */ = {isa = PBXBuildFile; fileRef = A36E59E2251A79F0003DA5B3 /* Budget.swift */; };
 		A37B9449251B1B3C00B3B45F /* BudgetsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A37B9448251B1B3C00B3B45F /* BudgetsListView.swift */; };
 		A37B944D251B2FA100B3B45F /* BudgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A37B944C251B2FA100B3B45F /* BudgetView.swift */; };
+		A3A70742252CBFB3000BD249 /* DynamicFetchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A70741252CBFB3000BD249 /* DynamicFetchView.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
@@ -35,6 +36,7 @@
 		A36E59E5251AB1BD003DA5B3 /* ydnab.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ydnab.entitlements; sourceTree = "<group>"; };
 		A37B9448251B1B3C00B3B45F /* BudgetsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetsListView.swift; sourceTree = "<group>"; };
 		A37B944C251B2FA100B3B45F /* BudgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BudgetView.swift; sourceTree = "<group>"; };
+		A3A70741252CBFB3000BD249 /* DynamicFetchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicFetchView.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -56,6 +58,7 @@
 				A37B944C251B2FA100B3B45F /* BudgetView.swift */,
 				A332A0602528CA300096684D /* BudgetViewSummary.swift */,
 				A332A05D2528C9F30096684D /* YearAndMonthPicker.swift */,
+				A3A70741252CBFB3000BD249 /* DynamicFetchView.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -180,6 +183,7 @@
 				A36CCED8251807AF00C00647 /* ydnab.xcdatamodeld in Sources */,
 				A36CCED5251807AF00C00647 /* Persistence.swift in Sources */,
 				A36E59E3251A79F0003DA5B3 /* Budget.swift in Sources */,
+				A3A70742252CBFB3000BD249 /* DynamicFetchView.swift in Sources */,
 				A37B9449251B1B3C00B3B45F /* BudgetsListView.swift in Sources */,
 				A332A05A2528C73A0096684D /* BudgetCells.swift in Sources */,
 				A37B944D251B2FA100B3B45F /* BudgetView.swift in Sources */,

+ 96 - 120
ydnab/Views/BudgetView.swift

@@ -7,6 +7,7 @@
 
 import SwiftUI
 import Combine
+import CoreData
 
 /// Shows the budget values for the selected budget, month, and year.
 struct BudgetView: View {
@@ -25,11 +26,6 @@ struct BudgetView: View {
 
     @Environment(\.managedObjectContext) var managedObjectContext
 
-//    private var budgetEntriesRequest: FetchRequest<BudgetCategoryEntry>
-//    private var budgetEntries: FetchedResults<BudgetCategoryEntry> { budgetEntriesRequest.wrappedValue }
-
-    @FetchRequest<BudgetCategoryEntry> private var budgetEntries: FetchedResults<BudgetCategoryEntry>
-
     init(budget: BudgetInfo, currentBudgetId: Binding<UUID?>) {
         _budget = .init(initialValue: budget)
         _currentBudgetId = currentBudgetId
@@ -39,20 +35,6 @@ struct BudgetView: View {
         _month = .init(initialValue: cal.component(.month, from: now))
         _monthName = .init(initialValue: cal.monthSymbols[self._month.wrappedValue])
         _year = .init(initialValue: cal.component(.year, from: now))
-
-        _budgetEntries = FetchRequest<BudgetCategoryEntry>(entity: BudgetCategoryEntry.entity(),
-                                                           sortDescriptors: [],
-                                                           predicate: NSPredicate(format: "(budgetId == %@) AND (month == %d) AND (year == %d)",
-                                                                                  budget.id as CVarArg, _month.wrappedValue, _year.wrappedValue))
-
-//        budgetEntriesRequest = FetchRequest<BudgetCategoryEntry>(entity: BudgetCategoryEntry.entity(),
-//                                                                 sortDescriptors: [],
-//                                                                 predicate: NSCompoundPredicate(andPredicateWithSubpredicates: [
-//                                                                    NSPredicate(format: "budgetId == %@", budget.id as CVarArg),
-//                                                                    NSPredicate(format: "month == %i", month),
-//                                                                    NSPredicate(format: "year == %i", year)
-//                                                                 ])
-//        )
     }
 
     func formatAmount(_ amount: NSNumber) -> String? {
@@ -62,122 +44,116 @@ struct BudgetView: View {
         return f.string(from: amount)
     }
 
-    private func findBudgetCategoryEntry(withId: UUID) -> BudgetCategoryEntry? {
-        return budgetEntries.first(where: { $0.budgetCategoryId == withId })
-    }
+//    private func findBudgetCategoryEntry(withId: UUID) -> BudgetCategoryEntry? {
+//        return budgetEntries.first(where: { $0.budgetCategoryId == withId })
+//    }
 
     private func zeroBudgetEntries() -> Void {
-        for section in budget.sections {
-            for category in section.categories {
-                if let entry = findBudgetCategoryEntry(withId: category.id) {
-                    entry.amount = 0
-                } else {
-                    let newEntry = BudgetCategoryEntry(context: managedObjectContext)
-                    newEntry.budgetId = budget.id
-                    newEntry.budgetCategoryId = category.id
-                    newEntry.month = Int64(month)
-                    newEntry.year = Int64(year)
-                    newEntry.amount = 0
-                }
-
-                do {
-                    try managedObjectContext.save()
-                } catch {
-                    print(error)
-                }
-            }
-        }
+//        for section in budget.sections {
+//            for category in section.categories {
+//                if let entry = findBudgetCategoryEntry(withId: category.id) {
+//                    entry.amount = 0
+//                } else {
+//                    let newEntry = BudgetCategoryEntry(context: managedObjectContext)
+//                    newEntry.budgetId = budget.id
+//                    newEntry.budgetCategoryId = category.id
+//                    newEntry.month = Int64(month)
+//                    newEntry.year = Int64(year)
+//                    newEntry.amount = 0
+//                }
+//
+//                do {
+//                    try managedObjectContext.save()
+//                } catch {
+//                    print(error)
+//                }
+//            }
+//        }
     }
 
+    @State private var refreshView: Bool = false
+
     var body: some View {
-        VStack {
-            HStack {
-                Button(action: { withAnimation() { showMonthPicker.toggle() } } ) {
-                    Text("\(monthName) \(String(year))")
-                    Image(systemName: showMonthPicker ? "chevron.up" : "chevron.down")
+        DynamicFetchView(predicate: NSPredicate(format: "budgetId == %@ AND month == %ld AND year == %ld", budget.id as CVarArg, month, year),
+                         sortDescriptors: []) { (budgetEntries: FetchedResults<BudgetCategoryEntry>) in
+
+            VStack {
+                HStack {
+                    Button(action: { withAnimation() { showMonthPicker.toggle() } } ) {
+                        Text("\(monthName) \(String(year))")
+                        Image(systemName: showMonthPicker ? "chevron.up" : "chevron.down")
+                    }
+                    Spacer()
+                    Button(action: { showQuickBudget.toggle() }) { // TODO: Implement this
+                        Image(systemName: "bolt.fill")
+                    }
+                    Button(action: { showNotImplemented.toggle() }) { // TODO: Implement this
+                        Image(systemName: "gearshape.fill")
+                    }.padding(.leading, 11)
                 }
-                Spacer()
-                Button(action: { showQuickBudget.toggle() }) { // TODO: Implement this
-                    Image(systemName: "bolt.fill")
+                .padding(11)
+
+                if showMonthPicker {
+                    YearAndMonthPicker(month: $month,
+                                       monthName: $monthName,
+                                       year: $year,
+                                       locale: Locale(identifier: budget.localeIdentifier)
+                    )
                 }
-                Button(action: { showNotImplemented.toggle() }) { // TODO: Implement this
-                    Image(systemName: "gearshape.fill")
-                }.padding(.leading, 11)
-            }
-            .padding(11)
-
-            if showMonthPicker {
-                YearAndMonthPicker(month: $month,
-                                   monthName: $monthName,
-                                   year: $year,
-                                   locale: Locale(identifier: budget.localeIdentifier)
-                )
-            }
-            
-            BudgetViewSummary(budget: $budget, month: $month, monthName: $monthName, 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(budgetEntries.first(where: { $0.budgetCategoryId == category.id })?.amount ?? 0) ?? "--",
-                                                       color: 0 < 0 ? Color("negativeAmount") : Color("positiveAmount")
-                                    )
-                                    .onLongPressGesture {
-                                        editingCategoryEntry = findBudgetCategoryEntry(withId: category.id)
-                                        showEditCategoryEntry.toggle()
+
+                BudgetViewSummary(budget: $budget, month: $month, monthName: $monthName, 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: String(format: "= %@ =", budgetEntries.first(where: { $0.budgetCategoryId == category.id })?.amount ?? -69 ),
+                                                           color: 0 < 0 ? Color("negativeAmount") : Color("positiveAmount")
+                                        )
                                     }
                                 }
                             }
-                            .onMove { (indexSet, s) in
-                                print(indexSet, s)
-                            }
                         }
                     }
                 }
-                .onMove { (indexSet, s) in
-                    print(indexSet, s)
+                .listStyle(PlainListStyle())
+//                .onChange(of: month) { m in
+//                    let entries = budgetEntries
+//                    print(entries.map { $0.amount })
+//                }
+                .navigationBarTitle(budget.name, displayMode: .inline)
+                .toolbar {
+                    EditButton()
+                }
+                .onAppear() {
+                    currentBudgetId = budget.id
+                    lastLoadedBudgetId = budget.id.uuidString
+                }
+                .actionSheet(isPresented: $showQuickBudget) {
+                    ActionSheet(
+                        title: Text("Quick budget"),
+                        message: Text("How would you like to set up your budget for \(monthName) \(String(year))?"),
+                        buttons: [
+                            .cancel { print(self.showQuickBudget) },
+                            .default(Text("All categories to zero"), action: zeroBudgetEntries),
+                            .default(Text("Values used the previous month"), action: { print(self) })
+                        ]
+                    )
+                }
+                .popover(isPresented: $showEditCategoryEntry) {
+    //                BudgetCategoryEntryEditor(amount: $editingCategoryEntry.wrappedValue?.amount)
                 }
-            }
-            .listStyle(PlainListStyle())
-            .navigationBarTitle(budget.name, displayMode: .inline)
-            .toolbar {
-                EditButton()
-            }
-            .onAppear() {
-                currentBudgetId = budget.id
-                lastLoadedBudgetId = budget.id.uuidString
-            }
-            .onChange(of: month) { e in
-
-            }
-            .onReceive(budgetEntries.publisher) { o in
-                print(o.month)
-            }
-            .actionSheet(isPresented: $showQuickBudget) {
-                ActionSheet(
-                    title: Text("Quick budget"),
-                    message: Text("How would you like to set up your budget for \(monthName) \(String(year))?"),
-                    buttons: [
-                        .cancel { print(self.showQuickBudget) },
-                        .default(Text("All categories to zero"), action: zeroBudgetEntries),
-                        .default(Text("Values used the previous month"), action: { print(self) })
-                    ]
-                )
-            }
-            .popover(isPresented: $showEditCategoryEntry) {
-//                BudgetCategoryEntryEditor(amount: $editingCategoryEntry.wrappedValue?.amount)
-            }
 
-            .alert(isPresented: $showNotImplemented) {
-                Alert(title: Text("Not Implemented!"))
+                .alert(isPresented: $showNotImplemented) {
+                    Alert(title: Text("Not Implemented!"))
+                }
             }
         }
     }

+ 21 - 0
ydnab/Views/DynamicFetchView.swift

@@ -0,0 +1,21 @@
+import CoreData
+import SwiftUI
+
+struct DynamicFetchView<T: NSManagedObject, Content: View>: View {
+    let fetchRequest: FetchRequest<T>
+    let content: (FetchedResults<T>) -> Content
+
+    var body: some View {
+        self.content(fetchRequest.wrappedValue)
+    }
+
+    init(predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor], @ViewBuilder content: @escaping (FetchedResults<T>) -> Content) {
+        fetchRequest = FetchRequest<T>(entity: T.entity(), sortDescriptors: sortDescriptors, predicate: predicate)
+        self.content = content
+    }
+
+    init(fetchRequest: NSFetchRequest<T>, @ViewBuilder content: @escaping (FetchedResults<T>) -> Content) {
+        self.fetchRequest = FetchRequest<T>(fetchRequest: fetchRequest)
+        self.content = content
+    }
+}