// // FilterViewModel.swift // Reflect // // Created by Trey Tartt on 1/17/22. // import Foundation @MainActor class YearViewModel: ObservableObject { @Published public var entryStartDate: Date = Date() @Published public var entryEndDate: Date = Date() @Published var selectedDays = [Int]() // year, month, items @Published public private(set) var data = [Int: [Int: [DayChartView]]]() @Published public private(set) var numberOfRatings: Int = 0 /// Entries organized by year for efficient access @Published public private(set) var entriesByYear = [Int: [MoodEntryModel]]() public private(set) var uncategorizedData = [MoodEntryModel]() { didSet { self.numberOfRatings = uncategorizedData.count } } private var dataListenerToken: DataController.DataListenerToken? init() { dataListenerToken = DataController.shared.addNewDataListener { [weak self] in self?.refreshData() } updateData() } deinit { if let token = dataListenerToken { Task { @MainActor in DataController.shared.removeDataListener(token: token) } } } /// Re-fetch data using the current date range. Called by the data listener /// when mood entries change in other tabs. public func refreshData() { updateData() filterEntries(startDate: entryStartDate, endDate: entryEndDate) } private func updateData() { let filteredEntries = DataController.shared.getData(startDate: Date(timeIntervalSince1970: 0), endDate: Date(), includedDays: selectedDays) if let firstDate = filteredEntries.sorted(by: { $0.forDate < $1.forDate }).first?.forDate { self.entryStartDate = firstDate } self.entryEndDate = Date() } private let chartViewBuilder = DayChartViewChartBuilder() public func filterEntries(startDate: Date, endDate: Date) { let filteredEntries = DataController.shared.getData(startDate: startDate, endDate: endDate, includedDays: selectedDays) data.removeAll() entriesByYear.removeAll() let filledOutData = chartViewBuilder.buildGridData(withData: filteredEntries) data = filledOutData uncategorizedData = filteredEntries // Organize entries by year for efficient access in YearCard let calendar = Calendar.current for entry in filteredEntries { let year = calendar.component(.year, from: entry.forDate) entriesByYear[year, default: []].append(entry) } } }