| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import Charts
- import Foundation
- import SwiftUI
- // MARK: - Current Glucose View
- struct GlucoseChartView: View {
- let glucoseValues: [(date: Date, glucose: Double, color: Color)]
- let minYAxisValue: Decimal
- let maxYAxisValue: Decimal
- @State private var timeWindow: TimeWindow = .threeHours
- enum TimeWindow: Int {
- case threeHours = 3
- case sixHours = 6
- case twelveHours = 12
- case twentyFourHours = 24
- var next: TimeWindow {
- switch self {
- case .threeHours: return .sixHours
- case .sixHours: return .twelveHours
- case .twelveHours: return .twentyFourHours
- case .twentyFourHours: return .threeHours
- }
- }
- }
- // TODO: should we only change the x axis here like we do in the main chart instead of filtering the values?
- private var filteredValues: [(date: Date, glucose: Double, color: Color)] {
- let cutoffDate = Date().addingTimeInterval(-Double(timeWindow.rawValue) * 3600)
- return glucoseValues.filter { $0.date > cutoffDate }
- }
- var glucosePointSize: CGFloat {
- switch timeWindow {
- case .threeHours: return 18
- case .sixHours: return 14
- case .twelveHours: return 10
- case .twentyFourHours: return 6
- }
- }
- var body: some View {
- VStack(spacing: 8) {
- if filteredValues.isEmpty {
- Text("No glucose readings.").font(.headline)
- Text("Check phone and CGM connectivity.").font(.caption)
- } else {
- Chart {
- ForEach(filteredValues, id: \.date) { reading in
- PointMark(
- x: .value("Time", reading.date),
- y: .value("Glucose", reading.glucose)
- )
- .foregroundStyle(reading.color)
- .symbolSize(glucosePointSize)
- }
- }
- .chartXAxis(.hidden)
- .chartYAxisLabel("\(timeWindow.rawValue) h", alignment: .topLeading)
- .chartYAxis {
- AxisMarks(position: .trailing) { value in
- AxisGridLine(stroke: .init(lineWidth: 0.65, dash: [2, 3]))
- .foregroundStyle(Color.white.opacity(0.25))
- AxisValueLabel {
- if let glucose = value.as(Double.self) {
- Text("\(Int(glucose))")
- }
- }
- }
- }
- .chartYScale(
- domain: minYAxisValue ... maxYAxisValue
- )
- .chartPlotStyle { plotContent in
- plotContent
- .background(
- RoundedRectangle(cornerRadius: 12)
- .fill(Color.clear)
- )
- .clipShape(RoundedRectangle(cornerRadius: 12))
- }
- .padding(.bottom)
- }
- }
- .scenePadding()
- .onTapGesture {
- withAnimation {
- timeWindow = timeWindow.next
- }
- }
- }
- }
|