Files
Reflect/Shared/Protocols/ChartDataBuildable.swift

107 lines
4.2 KiB
Swift

//
// ChartDataBuildable.swift
// Feels
//
// Created by Trey Tartt on 1/17/22.
//
import SwiftUI
typealias Year = Int
typealias Month = Int
protocol ChartDataBuildable {
associatedtype ChartType: ChartViewItemBuildable
// [Year: [Month: [View]]
func buildGridData(withData data: [MoodEntry]) -> [Year: [Month: [ChartType]]]
}
extension ChartDataBuildable {
public func buildGridData(withData data: [MoodEntry]) -> [Year: [Month: [ChartType]]] {
var returnData = [Int: [Int: [ChartType]]]()
if let earliestEntry = data.first,
let lastEntry = data.last {
let calendar = Calendar.current
let components = calendar.dateComponents([.year], from: earliestEntry.forDate!)
let earliestYear = components.year!
let latestComponents = calendar.dateComponents([.year], from: lastEntry.forDate!)
let latestYear = latestComponents.year!
for year in earliestYear...latestYear {
var allMonths = [Int: [ChartType]]()
// add back in if months header has leading (-1, ""),
// and add back gridItem
// var dayViews = [DayChartView]()
// for day in 0...32 {
// let view = DayChartView(color: Mood.missing.color,
// weekDay: 2,
// viewType: .text(String(day+1)))
// dayViews.append(view)
// }
// allMonths[0] = dayViews
for month in (1...12) {
var components = DateComponents()
components.month = month
components.year = year
let startDateOfMonth = Calendar.current.date(from: components)!
let items = data.filter({ entry in
let components = calendar.dateComponents([.month, .year], from: startDateOfMonth)
let entryComponents = calendar.dateComponents([.month, .year], from: entry.forDate!)
return (components.month == entryComponents.month && components.year == entryComponents.year)
})
allMonths[month] = createViewFor(monthEntries: items, forMonth: startDateOfMonth)
}
returnData[year] = allMonths
}
}
return returnData
}
private func createViewFor(monthEntries: [MoodEntry], forMonth month: Date) -> [ChartType] {
var filledOutArray = [ChartType]()
let calendar = Calendar.current
let range = calendar.range(of: .day, in: .month, for: month)!
let numDays = range.count
for day in 1...numDays {
if let item = monthEntries.filter({ entry in
let components = calendar.dateComponents([.day], from: entry.forDate!)
let date = components.day
return day == date
}).first {
let view = ChartType(color: item.mood.color,
weekDay: Int(item.weekDay),
viewType: .square)
filledOutArray.append(view)
} else {
let thisDate = Calendar.current.date(bySetting: .day, value: day, of: month)!
let view = ChartType(color: Mood.missing.color,
weekDay: Calendar.current.component(.weekday, from: thisDate),
viewType: .square)
filledOutArray.append(view)
}
}
for _ in filledOutArray.count...32 {
let view = ChartType(color: Mood.missing.color,
weekDay: 2,
viewType: .cicle)
filledOutArray.append(view)
}
return filledOutArray
}
}
struct DayChartViewChartBuilder: ChartDataBuildable {
typealias ChartType = DayChartView
}