CarbRatioScheduleEditor.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // CarbRatioScheduleEditor.swift
  3. // LoopKitUI
  4. //
  5. // Created by Michael Pangburn on 4/20/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. import HealthKit
  10. import LoopKit
  11. fileprivate extension HKUnit {
  12. static let storedCarbRatioScheduleUnit = HKUnit.gram()
  13. static let realCarbRatioScheduleUnit = HKUnit.gramsPerUnit
  14. }
  15. public struct CarbRatioScheduleEditor: View {
  16. private var schedule: DailyQuantitySchedule<Double>?
  17. private var mode: SettingsPresentationMode
  18. private var save: (CarbRatioSchedule) -> Void
  19. @Environment(\.appName) private var appName
  20. public init(
  21. schedule: CarbRatioSchedule?,
  22. onSave save: @escaping (CarbRatioSchedule) -> Void,
  23. mode: SettingsPresentationMode = .settings
  24. ) {
  25. // CarbRatioSchedule stores only the gram unit.
  26. // For consistency across display & computation, convert to "real" g/U units.
  27. self.schedule = schedule.map { schedule in
  28. DailyQuantitySchedule(
  29. unit: .realCarbRatioScheduleUnit,
  30. dailyItems: schedule.items
  31. )!
  32. }
  33. self.mode = mode
  34. self.save = save
  35. }
  36. public init(
  37. mode: SettingsPresentationMode,
  38. therapySettingsViewModel: TherapySettingsViewModel,
  39. didSave: (() -> Void)? = nil
  40. ) {
  41. self.init(
  42. schedule: therapySettingsViewModel.therapySettings.carbRatioSchedule,
  43. onSave: { [weak therapySettingsViewModel] in
  44. therapySettingsViewModel?.saveCarbRatioSchedule(carbRatioSchedule: $0)
  45. didSave?()
  46. },
  47. mode: mode
  48. )
  49. }
  50. public var body: some View {
  51. QuantityScheduleEditor(
  52. title: Text(TherapySetting.carbRatio.title),
  53. description: description,
  54. schedule: schedule,
  55. unit: .realCarbRatioScheduleUnit,
  56. guardrail: .carbRatio,
  57. quantitySelectionMode: .fractional,
  58. defaultFirstScheduleItemValue: Guardrail.carbRatio.startingSuggestion ?? Guardrail.carbRatio.recommendedBounds.upperBound,
  59. confirmationAlertContent: confirmationAlertContent,
  60. guardrailWarning: CarbRatioGuardrailWarning.init(crossedThresholds:),
  61. onSave: {
  62. // Convert back to the expected gram-unit-only schedule.
  63. self.save(DailyQuantitySchedule(unit: .storedCarbRatioScheduleUnit, dailyItems: $0.items)!)
  64. },
  65. mode: mode,
  66. settingType: .carbRatio
  67. )
  68. }
  69. private var description: Text {
  70. Text(TherapySetting.carbRatio.descriptiveText(appName: appName))
  71. }
  72. private var confirmationAlertContent: AlertContent {
  73. AlertContent(
  74. title: Text(LocalizedString("Save Carb Ratios?", comment: "Alert title for confirming carb ratios outside the recommended range")),
  75. message: Text(TherapySetting.carbRatio.guardrailSaveWarningCaption)
  76. )
  77. }
  78. }
  79. private struct CarbRatioGuardrailWarning: View {
  80. var crossedThresholds: [SafetyClassification.Threshold]
  81. var body: some View {
  82. assert(!crossedThresholds.isEmpty)
  83. return GuardrailWarning(
  84. therapySetting: .carbRatio,
  85. title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
  86. thresholds: crossedThresholds
  87. )
  88. }
  89. private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
  90. switch threshold {
  91. case .minimum, .belowRecommended:
  92. return Text(LocalizedString("Low Carb Ratio", comment: "Title text for the low carb ratio warning"))
  93. case .aboveRecommended, .maximum:
  94. return Text(LocalizedString("High Carb Ratio", comment: "Title text for the high carb ratio warning"))
  95. }
  96. }
  97. private var multipleWarningTitle: Text {
  98. Text(LocalizedString("Carb Ratios", comment: "Title text for multi-value carb ratio warning"))
  99. }
  100. }