import SwiftUI import Swinject extension CREditor { struct RootView: BaseView { let resolver: Resolver @StateObject var state = StateModel() @State private var editMode = EditMode.inactive @Environment(\.colorScheme) var colorScheme var color: LinearGradient { colorScheme == .dark ? LinearGradient( gradient: Gradient(colors: [ Color.bgDarkBlue, Color.bgDarkerDarkBlue ]), startPoint: .top, endPoint: .bottom ) : LinearGradient( gradient: Gradient(colors: [Color.gray.opacity(0.1)]), startPoint: .top, endPoint: .bottom ) } private var dateFormatter: DateFormatter { let formatter = DateFormatter() formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.timeStyle = .short return formatter } private var rateFormatter: NumberFormatter { let formatter = NumberFormatter() formatter.numberStyle = .decimal return formatter } var body: some View { Form { if let autotune = state.autotune, !state.settingsManager.settings.onlyAutotuneBasals { Section(header: Text("Autotune")) { HStack { Text("Calculated Ratio") Spacer() Text(rateFormatter.string(from: autotune.carbRatio as NSNumber) ?? "0") Text("g/U").foregroundColor(.secondary) } } } Section(header: Text("Schedule")) { list addButton } Section { Button { let impactHeavy = UIImpactFeedbackGenerator(style: .heavy) impactHeavy.impactOccurred() state.save() } label: { Text("Save") } .disabled(state.items.isEmpty) } } .scrollContentBackground(.hidden).background(color) .onAppear(perform: configureView) .navigationTitle("Carb Ratios") .navigationBarTitleDisplayMode(.automatic) .navigationBarItems( trailing: EditButton() ) .environment(\.editMode, $editMode) .onAppear { state.validate() } } private func pickers(for index: Int) -> some View { GeometryReader { geometry in VStack { HStack { Text("Ratio").frame(width: geometry.size.width / 2) Text("Time").frame(width: geometry.size.width / 2) } HStack(spacing: 0) { Picker(selection: $state.items[index].rateIndex, label: EmptyView()) { ForEach(0 ..< state.rateValues.count, id: \.self) { i in Text( ( self.rateFormatter .string(from: state.rateValues[i] as NSNumber) ?? "" ) + " g/U" ).tag(i) } } .frame(maxWidth: geometry.size.width / 2) .clipped() Picker(selection: $state.items[index].timeIndex, label: EmptyView()) { ForEach(0 ..< state.timeValues.count, id: \.self) { i in Text( self.dateFormatter .string(from: Date( timeIntervalSince1970: state .timeValues[i] )) ).tag(i) } } .frame(maxWidth: geometry.size.width / 2) .clipped() } } } } private var list: some View { List { ForEach(state.items.indexed(), id: \.1.id) { index, item in NavigationLink(destination: pickers(for: index)) { HStack { Text("Ratio").foregroundColor(.secondary) Text( "\(rateFormatter.string(from: state.rateValues[item.rateIndex] as NSNumber) ?? "0") g/U" ) Spacer() Text("starts at").foregroundColor(.secondary) Text( "\(dateFormatter.string(from: Date(timeIntervalSince1970: state.timeValues[item.timeIndex])))" ) } } .moveDisabled(true) } .onDelete(perform: onDelete) } } private var addButton: some View { guard state.canAdd else { return AnyView(EmptyView()) } switch editMode { case .inactive: return AnyView(Button(action: onAdd) { Text("Add") }) default: return AnyView(EmptyView()) } } func onAdd() { state.add() } private func onDelete(offsets: IndexSet) { state.items.remove(atOffsets: offsets) state.validate() } } }