CurrentGlucoseView.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import SwiftUI
  2. struct CurrentGlucoseView: View {
  3. @Binding var recentGlucose: BloodGlucose?
  4. @Binding var delta: Int?
  5. @Binding var units: GlucoseUnits
  6. private var glucoseFormatter: NumberFormatter {
  7. let formatter = NumberFormatter()
  8. formatter.numberStyle = .decimal
  9. formatter.maximumFractionDigits = 0
  10. if units == .mmolL {
  11. formatter.minimumFractionDigits = 1
  12. formatter.maximumFractionDigits = 1
  13. }
  14. formatter.roundingMode = .halfUp
  15. return formatter
  16. }
  17. private var deltaFormatter: NumberFormatter {
  18. let formatter = NumberFormatter()
  19. formatter.numberStyle = .decimal
  20. formatter.maximumFractionDigits = 1
  21. formatter.positivePrefix = "+"
  22. return formatter
  23. }
  24. private var dateFormatter: DateFormatter {
  25. let formatter = DateFormatter()
  26. formatter.timeStyle = .short
  27. return formatter
  28. }
  29. var body: some View {
  30. VStack(alignment: .center, spacing: 6) {
  31. HStack(spacing: 8) {
  32. Text(
  33. recentGlucose?.glucose
  34. .map {
  35. glucoseFormatter
  36. .string(from: Double(units == .mmolL ? $0.asMmolL : Decimal($0)) as NSNumber)! }
  37. ?? "--"
  38. )
  39. .font(.system(size: 24, weight: .bold))
  40. .fixedSize()
  41. .foregroundColor(colorOfGlucose)
  42. image.padding(.bottom, 2)
  43. }.padding(.leading, 4)
  44. HStack(alignment: .lastTextBaseline, spacing: 2) {
  45. Text(
  46. "\(minutesAgo)m "
  47. ).font(.caption2).foregroundColor(colorOfMinutesAgo(minutesAgo))
  48. Text(
  49. delta
  50. .map { deltaFormatter.string(from: Double(units == .mmolL ? $0.asMmolL : Decimal($0)) as NSNumber)!
  51. } ??
  52. "--"
  53. ).font(.system(size: 12, weight: .bold)) }
  54. }
  55. }
  56. var colorOfGlucose: Color {
  57. guard let recentBG = recentGlucose?.glucose
  58. else { return .loopYellow }
  59. // recentBG = Int(recentBG.asMmolL) // convert to mmol/l for calculation
  60. switch recentBG {
  61. case 73 ... 144:
  62. return .loopGreen
  63. case 63 ... 72,
  64. 145 ... 180:
  65. return .loopYellow
  66. case 54 ... 62,
  67. 181 ... 207:
  68. return .loopOrange
  69. default:
  70. return .loopRed
  71. }
  72. }
  73. var minutesAgo: Int {
  74. let lastGlucoseDateString = recentGlucose.map { dateFormatter.string(from: $0.dateString) } ?? "--"
  75. let LastGlucoseDate = Date(lastGlucoseDateString) ?? Date()
  76. let now = Date()
  77. let diffs = Calendar.current.dateComponents([.hour, .minute], from: LastGlucoseDate, to: now)
  78. let minutesDiff = diffs.minute!
  79. return minutesDiff
  80. }
  81. func colorOfMinutesAgo(_ minutes: Int) -> Color {
  82. switch minutes {
  83. case 0 ... 5:
  84. return .loopGreen
  85. case 6 ... 9:
  86. return .loopYellow
  87. default:
  88. return .loopRed
  89. }
  90. }
  91. var image: Image {
  92. guard let direction = recentGlucose?.direction else {
  93. return Image(systemName: "arrow.left.and.right")
  94. }
  95. switch direction {
  96. case .doubleUp,
  97. .singleUp,
  98. .tripleUp:
  99. return Image(systemName: "arrow.up")
  100. case .fortyFiveUp:
  101. return Image(systemName: "arrow.up.right")
  102. case .flat:
  103. return Image(systemName: "arrow.forward")
  104. case .fortyFiveDown:
  105. return Image(systemName: "arrow.down.forward")
  106. case .doubleDown,
  107. .singleDown,
  108. .tripleDown:
  109. return Image(systemName: "arrow.down")
  110. case .none,
  111. .notComputable,
  112. .rateOutOfRange:
  113. return Image(systemName: "arrow.left.and.right")
  114. }
  115. }
  116. }