// // ContentModeViewModel.swift // Feels (iOS) // // Created by Trey Tartt on 1/20/22. // import SwiftUI import CoreData class ContentModeViewModel: ObservableObject { @Published var grouped = [Int: [Int: [MoodEntry]]]() @Published public private(set) var savedOnboardingData = UserDefaultsStore.getOnboarding() @Published var numberOfItems = 0 var hasNoData: Bool { grouped.isEmpty } private var numberOfEntries: Int { var num = 0 grouped.keys.forEach({ let year = grouped[$0] let monthKeys = year?.keys monthKeys?.forEach({ num += year![$0]!.count }) }) return num // grouped.keys.map{ // grouped[$0]!.values.reduce(0) { sum, array in // sum + array.count // } // }.reduce(0, +) } init() { PersistenceController.shared.switchContainerListeners.append { self.getGroupedData() } updateData() } private func getGroupedData() { grouped = PersistenceController.shared.splitIntoYearMonth() numberOfItems = numberOfEntries } public func shouldShowVotingHeader() -> Bool { if isMissingCurrentVote() { return true } return savedOnboardingData.ableToVoteBasedOnCurentTime() ? true : false } public func updateOnboardingData(onboardingData: OnboardingData) { self.savedOnboardingData = UserDefaultsStore.saveOnboarding(onboardingData: onboardingData) LocalNotification.scheduleReminder(atTime: onboardingData.date, withTitle: onboardingData.title) } private func isMissingCurrentVote() -> Bool { let latestVoteUnLocked = UserDefaultsStore.getOnboarding().ableToVoteBasedOnCurentTime() let inputDay = UserDefaultsStore.getOnboarding().inputDay var startDate: Date? switch (latestVoteUnLocked, inputDay) { case (true, .Previous): startDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())! case (true, .Today): startDate = Date() case (false, .Previous): startDate = Calendar.current.date(byAdding: .day, value: -2, to: Date())! case (false, .Today): startDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())! } startDate = Calendar.current.startOfDay(for: startDate!) let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate!)! let fetchRequest = NSFetchRequest(entityName: "MoodEntry") let fromPredicate = NSPredicate(format: "%@ <= %K", startDate! as NSDate, #keyPath(MoodEntry.forDate)) let toPredicate = NSPredicate(format: "%K < %@", #keyPath(MoodEntry.forDate), endDate as NSDate) let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate]) fetchRequest.predicate = datePredicate let entries = try! PersistenceController.shared.viewContext.count(for: fetchRequest) return entries == 0 } public func updateData() { getGroupedData() } public func add(mood: Mood, forDate date: Date, entryType: EntryType) { PersistenceController.shared.add(mood: mood, forDate: date, entryType: entryType) getGroupedData() } public func update(entry: MoodEntry, toMood mood: Mood) { let forDate = entry.forDate! if let entry = PersistenceController.shared.getEntry(byDate: entry.forDate!) { PersistenceController.shared.viewContext.delete(entry) } do { try PersistenceController.shared.viewContext.save() getGroupedData() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } PersistenceController.shared.add(mood: mood, forDate: forDate, entryType: .listView) do { try PersistenceController.shared.viewContext.save() getGroupedData() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } public func delete(offsets: IndexSet, inMonth month: Int, inYear year: Int) { if let monthEntries = grouped[year], let entries = monthEntries[month] { var mutableEntries = entries.sorted(by: { $0.forDate! > $1.forDate! }) var entriesToDelete = [MoodEntry]() for idx in offsets { let obj = mutableEntries.remove(at: idx) entriesToDelete.append(obj) } entriesToDelete.forEach({ entry in let entryDate = entry.forDate! PersistenceController.shared.viewContext.delete(entry) self.add(mood: .missing, forDate: entryDate, entryType: .listView) }) } do { try PersistenceController.shared.viewContext.save() getGroupedData() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } }