GuardrailWarning.swift 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //
  2. // GuardrailWarning.swift
  3. // LoopKitUI
  4. //
  5. // Created by Michael Pangburn on 4/14/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. import LoopKit
  10. public struct GuardrailWarning: View {
  11. private enum CrossedThresholds {
  12. case one(SafetyClassification.Threshold)
  13. case oneOrMore([SafetyClassification.Threshold])
  14. }
  15. private var title: Text
  16. private var crossedThresholds: CrossedThresholds
  17. private var captionOverride: Text?
  18. public init(
  19. title: Text,
  20. threshold: SafetyClassification.Threshold,
  21. caption: Text? = nil
  22. ) {
  23. self.title = title
  24. self.crossedThresholds = .one(threshold)
  25. self.captionOverride = caption
  26. }
  27. public init(
  28. title: Text,
  29. thresholds: [SafetyClassification.Threshold],
  30. caption: Text? = nil
  31. ) {
  32. precondition(!thresholds.isEmpty)
  33. self.title = title
  34. self.crossedThresholds = .oneOrMore(thresholds)
  35. self.captionOverride = caption
  36. }
  37. public var body: some View {
  38. WarningView(title: title, caption: caption, severity: severity)
  39. }
  40. private var severity: WarningSeverity {
  41. switch crossedThresholds {
  42. case .one(let threshold):
  43. return threshold.severity
  44. case .oneOrMore(let thresholds):
  45. return thresholds.lazy.map({ $0.severity }).max()!
  46. }
  47. }
  48. private var caption: Text {
  49. if let caption = captionOverride {
  50. return caption
  51. }
  52. switch crossedThresholds {
  53. case .one(let threshold):
  54. // Chose to use premeal range override because it's not a schedule
  55. switch threshold {
  56. case .minimum, .belowRecommended:
  57. return Text(TherapySetting.preMealCorrectionRangeOverride.guardrailCaptionForLowValue)
  58. case .aboveRecommended, .maximum:
  59. return Text(TherapySetting.preMealCorrectionRangeOverride.guardrailCaptionForHighValue)
  60. }
  61. case .oneOrMore(let thresholds):
  62. // Chose to use correction range because it's a schedule
  63. if thresholds.count == 1 {
  64. switch thresholds.first! {
  65. case .minimum, .belowRecommended:
  66. return Text(TherapySetting.glucoseTargetRange.guardrailCaptionForLowValue)
  67. case .aboveRecommended, .maximum:
  68. return Text(TherapySetting.glucoseTargetRange.guardrailCaptionForHighValue)
  69. }
  70. } else {
  71. return Text(LocalizedString("Some of the values you have entered are outside of what is typically recommended for most people.", comment: "Caption for guardrail warning when more than one threshold is crossed"))
  72. }
  73. }
  74. }
  75. }
  76. fileprivate extension SafetyClassification.Threshold {
  77. var severity: WarningSeverity {
  78. switch self {
  79. case .belowRecommended, .aboveRecommended:
  80. return .default
  81. case .minimum, .maximum:
  82. return .critical
  83. }
  84. }
  85. }