DeliveryLimitsStepView.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import SwiftUI
  2. struct DeliveryLimitsStepView: View {
  3. @Bindable var state: Onboarding.StateModel
  4. let substep: DeliveryLimitSubstep
  5. @State private var shouldDisplayPicker: Bool = false
  6. private let settingsProvider = PickerSettingsProvider.shared
  7. var body: some View {
  8. VStack(alignment: .leading, spacing: 16) {
  9. Text(substep.title)
  10. .padding(.horizontal)
  11. .font(.title3)
  12. .bold()
  13. Text(substep.hint)
  14. .font(.subheadline)
  15. .multilineTextAlignment(.leading)
  16. .padding(.horizontal)
  17. .foregroundStyle(Color.secondary)
  18. switch substep {
  19. case .maxIOB:
  20. deliveryLimitInputSection(
  21. label: substep.title,
  22. displayPicker: $shouldDisplayPicker,
  23. setting: settingsProvider.settings.maxIOB,
  24. decimalValue: $state.maxIOB
  25. )
  26. case .maxBolus:
  27. deliveryLimitInputSection(
  28. label: substep.title,
  29. displayPicker: $shouldDisplayPicker,
  30. setting: settingsProvider.settings.maxBolus,
  31. decimalValue: $state.maxBolus
  32. )
  33. case .maxBasal:
  34. deliveryLimitInputSection(
  35. label: substep.title,
  36. displayPicker: $shouldDisplayPicker,
  37. setting: settingsProvider.settings.maxBasal,
  38. decimalValue: $state.maxBasal
  39. )
  40. case .maxCOB:
  41. deliveryLimitInputSection(
  42. label: substep.title,
  43. displayPicker: $shouldDisplayPicker,
  44. setting: settingsProvider.settings.maxCOB,
  45. decimalValue: $state.maxCOB
  46. )
  47. case .minimumSafetyThreshold:
  48. deliveryLimitInputSection(
  49. label: substep.title,
  50. displayPicker: $shouldDisplayPicker,
  51. setting: settingsProvider.settings.threshold_setting,
  52. decimalValue: $state.minimumSafetyThreshold
  53. )
  54. }
  55. AnyView(substep.description(units: state.units))
  56. .font(.footnote)
  57. .foregroundStyle(.secondary)
  58. .padding(.horizontal)
  59. .multilineTextAlignment(.leading)
  60. }
  61. .onDisappear {
  62. shouldDisplayPicker = false
  63. }
  64. }
  65. @ViewBuilder private func deliveryLimitInputSection(
  66. label: String,
  67. displayPicker: Binding<Bool>,
  68. setting: PickerSetting,
  69. decimalValue: Binding<Decimal>
  70. ) -> some View {
  71. VStack {
  72. HStack {
  73. Text(label)
  74. Spacer()
  75. displayText(for: substep, decimalValue: decimalValue.wrappedValue)
  76. .foregroundColor(!displayPicker.wrappedValue ? .primary : .accentColor)
  77. .onTapGesture {
  78. displayPicker.wrappedValue.toggle()
  79. }
  80. }
  81. if displayPicker.wrappedValue {
  82. Picker(selection: decimalValue, label: Text(label)) {
  83. ForEach(settingsProvider.generatePickerValues(from: setting, units: state.units), id: \.self) { value in
  84. displayText(for: substep, decimalValue: value).tag(value)
  85. }
  86. }
  87. .pickerStyle(WheelPickerStyle())
  88. .frame(maxWidth: .infinity)
  89. }
  90. }
  91. .padding()
  92. .background(Color.chart.opacity(0.65))
  93. .cornerRadius(10)
  94. }
  95. private func displayText(for substep: DeliveryLimitSubstep, decimalValue: Decimal) -> Text {
  96. switch substep {
  97. case .maxBasal:
  98. return Text("\(decimalValue) \(String(localized: "U/hr", comment: "Insulin unit per hour abbreviation"))")
  99. case .maxBolus,
  100. .maxIOB:
  101. return Text("\(decimalValue) \(String(localized: "U", comment: "Insulin unit abbreviation"))")
  102. case .maxCOB:
  103. return Text("\(decimalValue) \(String(localized: "g", comment: "Gram abbreviation"))")
  104. case .minimumSafetyThreshold:
  105. let optionallyParsedValue = state.units == .mgdL ? decimalValue : decimalValue.asMmolL
  106. return Text("\(optionallyParsedValue) \(state.units.rawValue)")
  107. }
  108. }
  109. }