AddTempTargetForm.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import Foundation
  2. import SwiftUI
  3. struct AddTempTargetForm: View {
  4. @StateObject var state: OverrideConfig.StateModel
  5. @Environment(\.presentationMode) var presentationMode
  6. @Environment(\.colorScheme) var colorScheme
  7. @Environment(\.dismiss) var dismiss
  8. @State private var showAlert = false
  9. @State private var showPresetAlert = false
  10. @State private var alertString = ""
  11. var color: LinearGradient {
  12. colorScheme == .dark ? LinearGradient(
  13. gradient: Gradient(colors: [
  14. Color.bgDarkBlue,
  15. Color.bgDarkerDarkBlue
  16. ]),
  17. startPoint: .top,
  18. endPoint: .bottom
  19. )
  20. :
  21. LinearGradient(
  22. gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
  23. startPoint: .top,
  24. endPoint: .bottom
  25. )
  26. }
  27. private var formatter: NumberFormatter {
  28. let formatter = NumberFormatter()
  29. formatter.numberStyle = .decimal
  30. formatter.maximumFractionDigits = 0
  31. return formatter
  32. }
  33. private var glucoseFormatter: NumberFormatter {
  34. let formatter = NumberFormatter()
  35. formatter.numberStyle = .decimal
  36. formatter.maximumFractionDigits = 0
  37. if state.units == .mmolL {
  38. formatter.maximumFractionDigits = 1
  39. }
  40. formatter.roundingMode = .halfUp
  41. return formatter
  42. }
  43. var body: some View {
  44. NavigationView {
  45. Form {
  46. addTempTarget()
  47. }.scrollContentBackground(.hidden).background(color)
  48. .navigationTitle("Add Temp Target")
  49. .navigationBarItems(trailing: Button("Cancel") {
  50. presentationMode.wrappedValue.dismiss()
  51. })
  52. .alert(
  53. "Start Temp Target",
  54. isPresented: $showAlert,
  55. actions: {
  56. Button("Cancel", role: .cancel) { state.isTempTargetEnabled = false }
  57. Button("Start Temp Target", role: .destructive) {
  58. Task {
  59. await setupAlertString()
  60. state.isTempTargetEnabled.toggle()
  61. await state.saveCustomTempTarget()
  62. await state.resetTempTargetState()
  63. dismiss()
  64. }
  65. }
  66. },
  67. message: {
  68. Text(alertString)
  69. }
  70. )
  71. }
  72. }
  73. @ViewBuilder private func addTempTarget() -> some View {
  74. Section {
  75. VStack {
  76. TextField("Name", text: $state.tempTargetName)
  77. }
  78. } header: {
  79. Text("Name")
  80. }.listRowBackground(Color.chart)
  81. Section {
  82. HStack {
  83. Text("Target")
  84. Spacer()
  85. TextFieldWithToolBar(text: $state.tempTargetTarget, placeholder: "0", numberFormatter: glucoseFormatter)
  86. Text(state.units.rawValue).foregroundColor(.secondary)
  87. }
  88. HStack {
  89. Text("Duration")
  90. Spacer()
  91. TextFieldWithToolBar(text: $state.tempTargetDuration, placeholder: "0", numberFormatter: formatter)
  92. Text("minutes").foregroundColor(.secondary)
  93. }
  94. DatePicker("Date", selection: $state.date)
  95. HStack {
  96. Button {
  97. showAlert.toggle()
  98. }
  99. label: { Text("Enact") }
  100. .disabled(state.tempTargetDuration == 0)
  101. .buttonStyle(BorderlessButtonStyle())
  102. .font(.callout)
  103. .controlSize(.mini)
  104. Button {
  105. Task {
  106. await state.saveTempTargetPreset()
  107. dismiss()
  108. }
  109. }
  110. label: { Text("Save as preset") }
  111. .disabled(state.tempTargetDuration == 0)
  112. .tint(.orange)
  113. .frame(maxWidth: .infinity, alignment: .trailing)
  114. .buttonStyle(BorderlessButtonStyle())
  115. .controlSize(.mini)
  116. }
  117. } header: {
  118. Text("Add Custom Temp Target")
  119. }.listRowBackground(Color.chart)
  120. }
  121. private func setupAlertString() async {
  122. alertString =
  123. (
  124. state.tempTargetDuration > 0 ?
  125. (
  126. state
  127. .tempTargetDuration
  128. .formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) +
  129. " min."
  130. ) :
  131. NSLocalizedString(" infinite duration.", comment: "")
  132. ) +
  133. (
  134. state.tempTargetTarget == 0 ? "" :
  135. (" Target: " + state.tempTargetTarget.formatted() + " " + state.units.rawValue + ".")
  136. )
  137. +
  138. "\n\n"
  139. +
  140. NSLocalizedString(
  141. "Starting this Temp Target will change your profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Temp Target” will start your new Temp Target or edit your current active Temp Target.",
  142. comment: ""
  143. )
  144. }
  145. }