AutotuneConfigRootView.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import SwiftUI
  2. import Swinject
  3. extension AutotuneConfig {
  4. struct RootView: BaseView {
  5. let resolver: Resolver
  6. @StateObject var state = StateModel()
  7. @State var replaceAlert = false
  8. @Environment(\.colorScheme) var colorScheme
  9. var color: LinearGradient {
  10. colorScheme == .dark ? LinearGradient(
  11. gradient: Gradient(colors: [
  12. Color.bgDarkBlue,
  13. Color.bgDarkerDarkBlue
  14. ]),
  15. startPoint: .top,
  16. endPoint: .bottom
  17. )
  18. :
  19. LinearGradient(
  20. gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
  21. startPoint: .top,
  22. endPoint: .bottom
  23. )
  24. }
  25. private var isfFormatter: NumberFormatter {
  26. let formatter = NumberFormatter()
  27. formatter.numberStyle = .decimal
  28. formatter.maximumFractionDigits = 2
  29. return formatter
  30. }
  31. private var rateFormatter: NumberFormatter {
  32. let formatter = NumberFormatter()
  33. formatter.numberStyle = .decimal
  34. formatter.maximumFractionDigits = 2
  35. return formatter
  36. }
  37. private var dateFormatter: DateFormatter {
  38. let formatter = DateFormatter()
  39. formatter.dateStyle = .medium
  40. formatter.timeStyle = .short
  41. return formatter
  42. }
  43. var body: some View {
  44. Form {
  45. Section {
  46. Toggle("Use Autotune", isOn: $state.useAutotune)
  47. if state.useAutotune {
  48. Toggle("Only Autotune Basal Insulin", isOn: $state.onlyAutotuneBasals)
  49. }
  50. }
  51. Section {
  52. HStack {
  53. Text("Last run")
  54. Spacer()
  55. Text(dateFormatter.string(from: state.publishedDate))
  56. }
  57. Button { state.run() }
  58. label: { Text("Run now") }
  59. }
  60. if let autotune = state.autotune {
  61. if !state.onlyAutotuneBasals {
  62. Section {
  63. HStack {
  64. Text("Carb ratio")
  65. Spacer()
  66. Text(isfFormatter.string(from: autotune.carbRatio as NSNumber) ?? "0")
  67. Text("g/U").foregroundColor(.secondary)
  68. }
  69. HStack {
  70. Text("Sensitivity")
  71. Spacer()
  72. if state.units == .mmolL {
  73. Text(isfFormatter.string(from: autotune.sensitivity.asMmolL as NSNumber) ?? "0")
  74. } else {
  75. Text(isfFormatter.string(from: autotune.sensitivity as NSNumber) ?? "0")
  76. }
  77. Text(state.units.rawValue + "/U").foregroundColor(.secondary)
  78. }
  79. }
  80. }
  81. Section(header: Text("Basal profile")) {
  82. ForEach(0 ..< autotune.basalProfile.count, id: \.self) { index in
  83. HStack {
  84. Text(autotune.basalProfile[index].start).foregroundColor(.secondary)
  85. Spacer()
  86. Text(rateFormatter.string(from: autotune.basalProfile[index].rate as NSNumber) ?? "0")
  87. Text("U/hr").foregroundColor(.secondary)
  88. }
  89. }
  90. HStack {
  91. Text("Total")
  92. .bold()
  93. .foregroundColor(.primary)
  94. Spacer()
  95. Text(rateFormatter.string(from: autotune.basalProfile.reduce(0) { $0 + $1.rate } as NSNumber) ?? "0")
  96. .foregroundColor(.primary) +
  97. Text(" U/day")
  98. .foregroundColor(.secondary)
  99. }
  100. }
  101. Section {
  102. Button {
  103. Task {
  104. await state.delete()
  105. }
  106. }
  107. label: { Text("Delete autotune data") }
  108. .foregroundColor(.red)
  109. }
  110. /* Section {
  111. Button {
  112. replaceAlert = true
  113. }
  114. label: { Text("Save as your Normal Basal Rates") }
  115. } header: {
  116. Text("Replace Normal Basal")
  117. } */
  118. }
  119. }
  120. .scrollContentBackground(.hidden).background(color)
  121. .onAppear(perform: configureView)
  122. .navigationTitle("Autotune")
  123. .navigationBarTitleDisplayMode(.automatic)
  124. .alert(Text("Are you sure?"), isPresented: $replaceAlert) {
  125. Button("Yes", action: {
  126. state.replace()
  127. replaceAlert.toggle()
  128. })
  129. Button("No", action: { replaceAlert.toggle() })
  130. }
  131. }
  132. }
  133. }