CalibrationsRootView.swift 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import SwiftUI
  2. import Swinject
  3. extension Calibrations {
  4. struct RootView: BaseView {
  5. let resolver: Resolver
  6. @State var state = StateModel()
  7. @Environment(\.colorScheme) var colorScheme
  8. @Environment(AppState.self) var appState
  9. private var formatter: NumberFormatter {
  10. let formatter = NumberFormatter()
  11. formatter.numberStyle = .decimal
  12. formatter.maximumFractionDigits = 2
  13. return formatter
  14. }
  15. private var manualGlucoseFormatter: NumberFormatter {
  16. let formatter = NumberFormatter()
  17. formatter.numberStyle = .decimal
  18. if state.units == .mgdL {
  19. formatter.maximumIntegerDigits = 3
  20. formatter.maximumFractionDigits = 0
  21. } else {
  22. formatter.maximumIntegerDigits = 2
  23. formatter.minimumFractionDigits = 0
  24. formatter.maximumFractionDigits = 1
  25. }
  26. formatter.roundingMode = .halfUp
  27. return formatter
  28. }
  29. private var dateFormatter: DateFormatter {
  30. let formatter = DateFormatter()
  31. formatter.timeStyle = .short
  32. formatter.dateStyle = .short
  33. return formatter
  34. }
  35. var body: some View {
  36. GeometryReader { geo in
  37. Form {
  38. Section(header: Text("Add calibration")) {
  39. HStack {
  40. Text("Meter glucose")
  41. Spacer()
  42. TextFieldWithToolBar(
  43. text: $state.newCalibration,
  44. placeholder: "0",
  45. numberFormatter: manualGlucoseFormatter,
  46. unitsText: state.units.rawValue
  47. )
  48. }
  49. Button {
  50. Task {
  51. await state.addCalibration()
  52. }
  53. }
  54. label: { Text("Add") }
  55. .disabled(state.newCalibration <= 0)
  56. }.listRowBackground(Color.chart)
  57. Section(header: Text("Info")) {
  58. HStack {
  59. Text("Slope")
  60. Spacer()
  61. Text(formatter.string(from: state.slope as NSNumber)!)
  62. }
  63. HStack {
  64. Text("Intercept")
  65. Spacer()
  66. Text(formatter.string(from: state.intercept as NSNumber)!)
  67. }
  68. }.listRowBackground(Color.chart)
  69. Section(header: Text("Remove")) {
  70. Button {
  71. state.removeLast()
  72. }
  73. label: { Text("Remove Last") }
  74. .disabled(state.calibrations.isEmpty)
  75. Button {
  76. state.removeAll()
  77. }
  78. label: { Text("Remove All") }
  79. .disabled(state.calibrations.isEmpty)
  80. List {
  81. ForEach(state.items) { item in
  82. HStack {
  83. Text(dateFormatter.string(from: item.calibration.date))
  84. Spacer()
  85. VStack(alignment: .leading) {
  86. Text("raw: \(item.calibration.x)")
  87. .font(.caption2)
  88. .foregroundColor(.secondary)
  89. Text("value: \(item.calibration.y)")
  90. .font(.caption2)
  91. .foregroundColor(.secondary)
  92. }
  93. }
  94. }.onDelete(perform: delete)
  95. }
  96. }.listRowBackground(Color.chart)
  97. if state.calibrations.isNotEmpty {
  98. Section(header: Text("Chart")) {
  99. CalibrationsChart(state: state)
  100. .frame(minHeight: geo.size.width)
  101. }.listRowBackground(Color.chart)
  102. }
  103. }
  104. }
  105. .scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
  106. .dynamicTypeSize(...DynamicTypeSize.xxLarge)
  107. .onAppear(perform: configureView)
  108. .navigationTitle("Calibrations")
  109. .navigationBarItems(trailing: EditButton().disabled(state.calibrations.isEmpty))
  110. .navigationBarTitleDisplayMode(.automatic)
  111. }
  112. private func delete(at offsets: IndexSet) {
  113. state.removeAtIndex(offsets[offsets.startIndex])
  114. }
  115. }
  116. }