| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- //
- // CarbRatioScheduleEditor.swift
- // LoopKitUI
- //
- // Created by Michael Pangburn on 4/20/20.
- // Copyright © 2020 LoopKit Authors. All rights reserved.
- //
- import SwiftUI
- import HealthKit
- import LoopKit
- fileprivate extension HKUnit {
- static let storedCarbRatioScheduleUnit = HKUnit.gram()
- static let realCarbRatioScheduleUnit = HKUnit.gramsPerUnit
- }
- public struct CarbRatioScheduleEditor: View {
- private var schedule: DailyQuantitySchedule<Double>?
- private var mode: SettingsPresentationMode
- private var save: (CarbRatioSchedule) -> Void
- @Environment(\.appName) private var appName
- public init(
- schedule: CarbRatioSchedule?,
- onSave save: @escaping (CarbRatioSchedule) -> Void,
- mode: SettingsPresentationMode = .settings
- ) {
- // CarbRatioSchedule stores only the gram unit.
- // For consistency across display & computation, convert to "real" g/U units.
- self.schedule = schedule.map { schedule in
- DailyQuantitySchedule(
- unit: .realCarbRatioScheduleUnit,
- dailyItems: schedule.items
- )!
- }
- self.mode = mode
- self.save = save
- }
-
- public init(
- mode: SettingsPresentationMode,
- therapySettingsViewModel: TherapySettingsViewModel,
- didSave: (() -> Void)? = nil
- ) {
- self.init(
- schedule: therapySettingsViewModel.therapySettings.carbRatioSchedule,
- onSave: { [weak therapySettingsViewModel] in
- therapySettingsViewModel?.saveCarbRatioSchedule(carbRatioSchedule: $0)
- didSave?()
- },
- mode: mode
- )
- }
- public var body: some View {
- QuantityScheduleEditor(
- title: Text(TherapySetting.carbRatio.title),
- description: description,
- schedule: schedule,
- unit: .realCarbRatioScheduleUnit,
- guardrail: .carbRatio,
- selectableValueStride: HKQuantity(unit: .realCarbRatioScheduleUnit, doubleValue: 0.1),
- quantitySelectionMode: .fractional,
- defaultFirstScheduleItemValue: Guardrail.carbRatio.startingSuggestion ?? Guardrail.carbRatio.recommendedBounds.upperBound,
- confirmationAlertContent: confirmationAlertContent,
- guardrailWarning: CarbRatioGuardrailWarning.init(crossedThresholds:),
- onSave: {
- // Convert back to the expected gram-unit-only schedule.
- self.save(DailyQuantitySchedule(unit: .storedCarbRatioScheduleUnit, dailyItems: $0.items)!)
- },
- mode: mode,
- settingType: .carbRatio
- )
- }
- private var description: Text {
- Text(TherapySetting.carbRatio.descriptiveText(appName: appName))
- }
- private var confirmationAlertContent: AlertContent {
- AlertContent(
- title: Text(LocalizedString("Save Carb Ratios?", comment: "Alert title for confirming carb ratios outside the recommended range")),
- message: Text(TherapySetting.carbRatio.guardrailSaveWarningCaption)
- )
- }
- }
- private struct CarbRatioGuardrailWarning: View {
- var crossedThresholds: [SafetyClassification.Threshold]
- var body: some View {
- assert(!crossedThresholds.isEmpty)
- return GuardrailWarning(
- therapySetting: .carbRatio,
- title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
- thresholds: crossedThresholds
- )
- }
- private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
- switch threshold {
- case .minimum, .belowRecommended:
- return Text(LocalizedString("Low Carb Ratio", comment: "Title text for the low carb ratio warning"))
- case .aboveRecommended, .maximum:
- return Text(LocalizedString("High Carb Ratio", comment: "Title text for the high carb ratio warning"))
- }
- }
- private var multipleWarningTitle: Text {
- Text(LocalizedString("Carb Ratios", comment: "Title text for multi-value carb ratio warning"))
- }
- }
|