PumpView.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import SwiftUI
  2. struct PumpView: View {
  3. @Binding var reservoir: Decimal?
  4. @Binding var battery: Battery?
  5. @Binding var name: String
  6. @Binding var expiresAtDate: Date?
  7. @Binding var timerDate: Date
  8. @Binding var boluses: [PumpHistoryEvent]
  9. @State var state: Home.StateModel
  10. @State var totalBolus: Decimal = 0
  11. private var reservoirFormatter: NumberFormatter {
  12. let formatter = NumberFormatter()
  13. formatter.numberStyle = .decimal
  14. formatter.maximumFractionDigits = 0
  15. return formatter
  16. }
  17. private var batteryFormatter: NumberFormatter {
  18. let formatter = NumberFormatter()
  19. formatter.numberStyle = .percent
  20. return formatter
  21. }
  22. private var numberFormatter: NumberFormatter {
  23. let formatter = NumberFormatter()
  24. formatter.numberStyle = .decimal
  25. formatter.maximumFractionDigits = 2
  26. return formatter
  27. }
  28. var body: some View {
  29. HStack {
  30. Text("IOB").font(.callout).foregroundColor(.secondary)
  31. Text(
  32. (numberFormatter.string(from: (state.suggestion?.iob ?? 0) as NSNumber) ?? "0") +
  33. NSLocalizedString(" U", comment: "Insulin unit")
  34. )
  35. .font(.callout).fontWeight(.bold)
  36. Spacer()
  37. Text("COB").font(.callout).foregroundColor(.secondary)
  38. Text(
  39. (numberFormatter.string(from: (state.suggestion?.cob ?? 0) as NSNumber) ?? "0") +
  40. NSLocalizedString(" g", comment: "gram of carbs")
  41. )
  42. .font(.callout).fontWeight(.bold)
  43. Spacer()
  44. if let reservoir = reservoir {
  45. HStack {
  46. Image(systemName: "drop.fill")
  47. .resizable()
  48. .aspectRatio(contentMode: .fit)
  49. .frame(maxHeight: 15)
  50. .foregroundColor(reservoirColor)
  51. if reservoir == 0xDEAD_BEEF {
  52. Text("50+ " + NSLocalizedString("U", comment: "Insulin unit")).font(.callout)
  53. .fontWeight(.bold)
  54. } else {
  55. Text(
  56. reservoirFormatter
  57. .string(from: reservoir as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit")
  58. )
  59. .font(.callout).fontWeight(.bold)
  60. }
  61. }
  62. }
  63. Spacer()
  64. if let battery = battery, battery.display ?? false, expiresAtDate == nil {
  65. HStack {
  66. Image(systemName: "battery.100")
  67. .resizable()
  68. .aspectRatio(contentMode: .fit)
  69. .frame(maxHeight: 15)
  70. .foregroundColor(batteryColor)
  71. Text("\(Int(battery.percent ?? 100)) %").font(.callout)
  72. .fontWeight(.bold)
  73. Text(calculateTINS())
  74. .font(.callout).fontWeight(.bold)
  75. }
  76. }
  77. if let date = expiresAtDate {
  78. HStack {
  79. Image(systemName: "stopwatch.fill")
  80. .resizable()
  81. .aspectRatio(contentMode: .fit)
  82. .frame(maxHeight: 15)
  83. .foregroundColor(timerColor)
  84. Text(remainingTimeString(time: date.timeIntervalSince(timerDate))).font(.callout)
  85. .fontWeight(.bold)
  86. }
  87. }
  88. }
  89. }
  90. func calculateTINS() -> String {
  91. let date = Date()
  92. let calendar = Calendar.current
  93. let startTime = calendar.startOfDay(for: date)
  94. let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: date)
  95. let bolusesForCurrentDay = boluses.filter { $0.timestamp >= startTime && $0.type == .bolus }
  96. let totalBolus = bolusesForCurrentDay.map { $0.amount ?? 0 }.reduce(0, +)
  97. let roundedTotalBolus = Decimal(round(100 * Double(totalBolus)) / 100)
  98. return "\(roundedTotalBolus) U"
  99. }
  100. // func calculateTINS() -> String {
  101. // let date = Date()
  102. // let calendar = Calendar.current
  103. // let startTime = calendar.startOfDay(for: date)
  104. // let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: date)
  105. //
  106. // let bolusesForCurrentDay = boluses.filter { $0.timestamp >= startTime && $0.type == .bolus}
  107. // print("****************Boluses for current day: \(bolusesForCurrentDay)")
  108. //
  109. // let totalBolus = bolusesForCurrentDay.map { $0.value as? Decimal ?? 0 }.reduce(0, +)
  110. // print("****************Total Bolus: \(totalBolus)")
  111. //
  112. // return "\(totalBolus) U"
  113. // }
  114. // func calculateTINS() {
  115. // DispatchQueue.main.async { [weak self] in
  116. // guard let self = self else { return }
  117. //
  118. // // start of day
  119. // let startOfDay = Calendar.current.startOfDay(for: Date())
  120. //
  121. // // filtering for day
  122. //// let bolusesForCurrentDay = self.provider.pumpHistory()
  123. //// .filter { $0.type == .bolus && $0.timestamp >= startOfDay }
  124. //
  125. // // adding all together
  126. //// let totalBolus = bolusesForCurrentDay.map { $0.amount ?? 0 }.reduce(0, +)
  127. //
  128. // let totalBolus = boluses.map {}
  129. //
  130. // self.totalBolus = totalBolus
  131. // }
  132. // }
  133. //
  134. private func remainingTimeString(time: TimeInterval) -> String {
  135. guard time > 0 else {
  136. return NSLocalizedString("Replace pod", comment: "View/Header when pod expired")
  137. }
  138. var time = time
  139. let days = Int(time / 1.days.timeInterval)
  140. time -= days.days.timeInterval
  141. let hours = Int(time / 1.hours.timeInterval)
  142. time -= hours.hours.timeInterval
  143. let minutes = Int(time / 1.minutes.timeInterval)
  144. if days >= 1 {
  145. return "\(days)" + NSLocalizedString("d", comment: "abbreviation for days") + " \(hours)" +
  146. NSLocalizedString("h", comment: "abbreviation for hours")
  147. }
  148. if hours >= 1 {
  149. return "\(hours)" + NSLocalizedString("h", comment: "abbreviation for hours")
  150. }
  151. return "\(minutes)" + NSLocalizedString("m", comment: "abbreviation for minutes")
  152. }
  153. private var batteryColor: Color {
  154. guard let battery = battery, let percent = battery.percent else {
  155. return .gray
  156. }
  157. switch percent {
  158. case ...10:
  159. return .red
  160. case ...20:
  161. return .yellow
  162. default:
  163. return .green
  164. }
  165. }
  166. private var reservoirColor: Color {
  167. guard let reservoir = reservoir else {
  168. return .gray
  169. }
  170. switch reservoir {
  171. case ...10:
  172. return .red
  173. case ...30:
  174. return .yellow
  175. default:
  176. return .blue
  177. }
  178. }
  179. private var timerColor: Color {
  180. guard let expisesAt = expiresAtDate else {
  181. return .gray
  182. }
  183. let time = expisesAt.timeIntervalSince(timerDate)
  184. switch time {
  185. case ...8.hours.timeInterval:
  186. return .red
  187. case ...1.days.timeInterval:
  188. return .yellow
  189. default:
  190. return .green
  191. }
  192. }
  193. }
  194. struct Hairline: View {
  195. let color: Color
  196. var body: some View {
  197. Rectangle()
  198. .fill(color)
  199. .frame(width: UIScreen.main.bounds.width / 1.3, height: 1)
  200. .opacity(0.5)
  201. }
  202. }