CurrentGlucoseView.swift 3.9 KB

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