GlucoseChartView.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import Charts
  2. import Foundation
  3. import SwiftUI
  4. // MARK: - Current Glucose View
  5. struct GlucoseChartView: View {
  6. let glucoseValues: [(date: Date, glucose: Double)]
  7. @State private var timeWindow: TimeWindow = .threeHours
  8. enum TimeWindow: Int {
  9. case threeHours = 3
  10. case sixHours = 6
  11. case twelveHours = 12
  12. case twentyFourHours = 24
  13. var next: TimeWindow {
  14. switch self {
  15. case .threeHours: return .sixHours
  16. case .sixHours: return .twelveHours
  17. case .twelveHours: return .twentyFourHours
  18. case .twentyFourHours: return .threeHours
  19. }
  20. }
  21. }
  22. // TODO: should we only change the x axis here like we do in the main chart instead of filtering the values?
  23. private var filteredValues: [(date: Date, glucose: Double)] {
  24. let cutoffDate = Date().addingTimeInterval(-Double(timeWindow.rawValue) * 3600)
  25. return glucoseValues.filter { $0.date > cutoffDate }
  26. }
  27. // TODO: replace hard coded values with actual settings and add dynamic color
  28. private func glucoseColor(_ value: Double) -> Color {
  29. if value > 180 {
  30. return .orange
  31. } else if value < 70 {
  32. return .red
  33. } else {
  34. return .green
  35. }
  36. }
  37. var body: some View {
  38. VStack(spacing: 8) {
  39. HStack {
  40. Text("Glucose History")
  41. .font(.system(.headline, design: .rounded))
  42. Spacer()
  43. Text("\(timeWindow.rawValue)h")
  44. .font(.system(.caption2, design: .rounded))
  45. .foregroundStyle(.secondary)
  46. }
  47. .padding(.horizontal)
  48. Chart {
  49. ForEach(filteredValues, id: \.date) { reading in
  50. PointMark(
  51. x: .value("Time", reading.date),
  52. y: .value("Glucose", reading.glucose)
  53. )
  54. .foregroundStyle(glucoseColor(reading.glucose))
  55. .symbolSize(30)
  56. }
  57. }
  58. .chartXAxis {
  59. AxisMarks(values: .automatic(desiredCount: 4)) { _ in
  60. AxisValueLabel(format: .dateTime.hour())
  61. .font(.footnote)
  62. }
  63. }
  64. .chartYAxis {
  65. AxisMarks(position: .leading) { value in
  66. AxisValueLabel {
  67. if let glucose = value.as(Double.self) {
  68. Text("\(Int(glucose))").font(.footnote)
  69. }
  70. }
  71. }
  72. }
  73. .padding()
  74. }
  75. .onTapGesture {
  76. withAnimation {
  77. timeWindow = timeWindow.next
  78. }
  79. }
  80. }
  81. }