CalibrationsRootView.swift 4.2 KB

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