Selaa lähdekoodia

sheet view for meal presets ...wip

polscm32 aka Marvout 1 vuosi sitten
vanhempi
commit
a6cd13921f

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -297,6 +297,7 @@
 		B958F1B72BA0711600484851 /* MKRingProgressView in Frameworks */ = {isa = PBXBuildFile; productRef = B958F1B62BA0711600484851 /* MKRingProgressView */; };
 		B9CAAEFC2AE70836000F68BC /* branch.txt in Resources */ = {isa = PBXBuildFile; fileRef = B9CAAEFB2AE70836000F68BC /* branch.txt */; };
 		BA00D96F7B2FF169A06FB530 /* CGMStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C018D1680307A31C9ED7120 /* CGMStateModel.swift */; };
+		BD0B2EF32C5998E600B3298F /* MealPresetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD0B2EF22C5998E600B3298F /* MealPresetView.swift */; };
 		BD1661312B82ADAB00256551 /* CustomProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1661302B82ADAB00256551 /* CustomProgressView.swift */; };
 		BD2B464E0745FBE7B79913F4 /* NightscoutConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF768BD6264FF7D71D66767 /* NightscoutConfigProvider.swift */; };
 		BD2FF1A02AE29D43005D1C5D /* CheckboxToggleStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD2FF19F2AE29D43005D1C5D /* CheckboxToggleStyle.swift */; };
@@ -899,6 +900,7 @@
 		B9B5C0607505A38F256BF99A /* CGMDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CGMDataFlow.swift; sourceTree = "<group>"; };
 		B9CAAEFB2AE70836000F68BC /* branch.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = branch.txt; sourceTree = SOURCE_ROOT; };
 		BA49538D56989D8DA6FCF538 /* TargetsEditorDataFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TargetsEditorDataFlow.swift; sourceTree = "<group>"; };
+		BD0B2EF22C5998E600B3298F /* MealPresetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealPresetView.swift; sourceTree = "<group>"; };
 		BD1661302B82ADAB00256551 /* CustomProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomProgressView.swift; sourceTree = "<group>"; };
 		BD1CF8B72C1A4A8400CB930A /* ConfigOverride.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = ConfigOverride.xcconfig; sourceTree = "<group>"; };
 		BD2FF19F2AE29D43005D1C5D /* CheckboxToggleStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxToggleStyle.swift; sourceTree = "<group>"; };
@@ -2237,6 +2239,7 @@
 				BDFD16592AE40438007F0DDA /* BolusRootView.swift */,
 				58237D9D2BCF0A6B00A47A79 /* PopupView.swift */,
 				BDB899872C564509006F3298 /* ForeCastChart.swift */,
+				BD0B2EF22C5998E600B3298F /* MealPresetView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -3014,6 +3017,7 @@
 				DD57C4BD2C4C7103001A5B28 /* PumpEventStored+CoreDataProperties.swift in Sources */,
 				DD57C4BE2C4C7103001A5B28 /* TempBasalStored+CoreDataClass.swift in Sources */,
 				DD57C4BF2C4C7103001A5B28 /* TempBasalStored+CoreDataProperties.swift in Sources */,
+				BD0B2EF32C5998E600B3298F /* MealPresetView.swift in Sources */,
 				DD57C4C02C4C7103001A5B28 /* TempTargetsSlider+CoreDataClass.swift in Sources */,
 				DD57C4C12C4C7103001A5B28 /* TempTargetsSlider+CoreDataProperties.swift in Sources */,
 				DD57C4C22C4C7103001A5B28 /* Forecast+CoreDataClass.swift in Sources */,

+ 30 - 188
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -18,16 +18,17 @@ extension Bolus {
 
         @StateObject var state = StateModel()
 
-        @State private var showAlert = false
+//        @State private var showAlert = false
+        @State private var showPresetSheet = false
         @State private var autofocus: Bool = true
         @State private var calculatorDetent = PresentationDetent.medium
         @State private var pushed: Bool = false
-        @State private var isPromptPresented: Bool = false
-        @State private var dish: String = ""
-        @State private var saved: Bool = false
+//        @State private var isPromptPresented: Bool = false
+//        @State private var dish: String = ""
+//        @State private var saved: Bool = false
         @State private var debounce: DispatchWorkItem?
 
-        @Environment(\.managedObjectContext) var moc
+//        @Environment(\.managedObjectContext) var moc
 
         private enum Config {
             static let dividerHeight: CGFloat = 2
@@ -36,10 +37,10 @@ extension Bolus {
 
         @Environment(\.colorScheme) var colorScheme
 
-        @FetchRequest(
-            entity: MealPresetStored.entity(),
-            sortDescriptors: [NSSortDescriptor(key: "dish", ascending: true)]
-        ) var carbPresets: FetchedResults<MealPresetStored>
+//        @FetchRequest(
+//            entity: MealPresetStored.entity(),
+//            sortDescriptors: [NSSortDescriptor(key: "dish", ascending: true)]
+//        ) var carbPresets: FetchedResults<MealPresetStored>
 
         private var formatter: NumberFormatter {
             let formatter = NumberFormatter()
@@ -87,9 +88,9 @@ extension Bolus {
                 )
         }
 
-        private var empty: Bool {
-            state.useFPUconversion ? (state.carbs <= 0 && state.fat <= 0 && state.protein <= 0) : (state.carbs <= 0)
-        }
+//        private var empty: Bool {
+//            state.useFPUconversion ? (state.carbs <= 0 && state.fat <= 0 && state.protein <= 0) : (state.carbs <= 0)
+//        }
 
         /// Handles macro input (carb, fat, protein) in a debounced fashion.
         func handleDebouncedInput() {
@@ -105,159 +106,6 @@ extension Bolus {
             }
         }
 
-        private var presetPopover: some View {
-            Form {
-                Section {
-                    TextField("Name Of Dish", text: $dish)
-                    Button {
-                        saved = true
-                        if dish != "", saved {
-                            let preset = MealPresetStored(context: moc)
-                            preset.dish = dish
-                            preset.fat = state.fat as NSDecimalNumber
-                            preset.protein = state.protein as NSDecimalNumber
-                            preset.carbs = state.carbs as NSDecimalNumber
-                            if self.moc.hasChanges {
-                                try? moc.save()
-                            }
-                            state.addNewPresetToWaitersNotepad(dish)
-                            saved = false
-                            isPromptPresented = false
-                        }
-                    }
-                    label: { Text("Save") }
-                    Button {
-                        dish = ""
-                        saved = false
-                        isPromptPresented = false }
-                    label: { Text("Cancel") }
-                } header: { Text("Enter Meal Preset Name") }
-            }
-        }
-
-        private var minusButton: some View {
-            Button {
-                if state.carbs != 0,
-                   (state.carbs - (((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal) as Decimal) >= 0
-                {
-                    state.carbs -= (((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal)
-                } else { state.carbs = 0 }
-
-                if state.fat != 0,
-                   (state.fat - (((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal) as Decimal) >= 0
-                {
-                    state.fat -= (((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal)
-                } else { state.fat = 0 }
-
-                if state.protein != 0,
-                   (state.protein - (((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal) as Decimal) >= 0
-                {
-                    state.protein -= (((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal)
-                } else { state.protein = 0 }
-
-                state.removePresetFromNewMeal()
-                if state.carbs == 0, state.fat == 0, state.protein == 0 { state.summation = [] }
-            }
-            label: { Image(systemName: "minus.circle.fill")
-                .font(.system(size: 20))
-            }
-            .disabled(
-                state
-                    .selection == nil ||
-                    (
-                        !state.summation
-                            .contains(state.selection?.dish ?? "") && (state.selection?.dish ?? "") != ""
-                    )
-            )
-            .buttonStyle(.borderless)
-            .tint(.blue)
-        }
-
-        private var plusButton: some View {
-            Button {
-                state.carbs += ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
-                state.fat += ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
-                state.protein += ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
-
-                state.addPresetToNewMeal()
-            }
-            label: { Image(systemName: "plus.circle.fill")
-                .font(.system(size: 20))
-            }
-            .disabled(state.selection == nil)
-            .buttonStyle(.borderless)
-            .tint(.blue)
-        }
-
-        private var mealPresets: some View {
-            Section {
-                HStack {
-                    if state.selection != nil {
-                        minusButton
-                    }
-                    Picker("Preset", selection: $state.selection) {
-                        Text("Saved Food").tag(nil as MealPresetStored?)
-                        ForEach(carbPresets, id: \.self) { (preset: MealPresetStored) in
-                            Text(preset.dish ?? "").tag(preset as MealPresetStored?)
-                        }
-                    }
-                    .labelsHidden()
-                    .frame(maxWidth: .infinity, alignment: .center)
-                    ._onBindingChange($state.selection) { _ in
-                        state.carbs += ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
-                        state.fat += ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
-                        state.protein += ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
-                        state.addToSummation()
-                    }
-                    if state.selection != nil {
-                        plusButton
-                    }
-                }
-
-                HStack {
-                    Button("Delete Preset") {
-                        showAlert.toggle()
-                    }
-                    .disabled(state.selection == nil)
-                    .tint(.orange)
-                    .buttonStyle(.borderless)
-                    .alert(
-                        "Delete preset '\(state.selection?.dish ?? "")'?",
-                        isPresented: $showAlert,
-                        actions: {
-                            Button("No", role: .cancel) {}
-                            Button("Yes", role: .destructive) {
-                                state.deletePreset()
-
-                                state.carbs += ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
-                                state.fat += ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
-                                state.protein += ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
-
-                                state.addPresetToNewMeal()
-                            }
-                        }
-                    )
-
-                    Spacer()
-
-                    Button {
-                        isPromptPresented = true
-                    }
-                    label: { Text("Save as Preset") }
-                        .buttonStyle(.borderless)
-                        .disabled(
-                            empty ||
-                                (
-                                    (((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal) == state
-                                        .carbs && (((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal) == state
-                                        .fat && (((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal) == state
-                                        .protein
-                                )
-                        )
-                }
-            }
-        }
-
         @ViewBuilder private func proteinAndFat() -> some View {
             HStack {
                 Text("Fat").foregroundColor(.orange)
@@ -308,20 +156,6 @@ extension Bolus {
                                 proteinAndFat()
                             }
 
-                            // Summary when combining presets
-                            if state.waitersNotepad() != "" {
-                                HStack {
-                                    Text("Total")
-                                    let test = state.waitersNotepad().components(separatedBy: ", ").removeDublicates()
-                                    HStack(spacing: 0) {
-                                        ForEach(test, id: \.self) {
-                                            Text($0).foregroundStyle(Color.blue).font(.footnote)
-                                            Text($0 == test[test.count - 1] ? "" : ", ")
-                                        }
-                                    }.frame(maxWidth: .infinity, alignment: .trailing)
-                                }
-                            }
-
                             // Time
                             HStack {
                                 Text("Time").foregroundStyle(Color.secondary)
@@ -346,17 +180,13 @@ extension Bolus {
                                     label: { Image(systemName: "plus.circle") }.tint(.blue).buttonStyle(.borderless)
                                 }
                             }
-
-                            .popover(isPresented: $isPromptPresented) {
-                                presetPopover
-                            }
                         }.listRowBackground(Color.chart)
 
-                        if state.displayPresets {
-                            Section {
-                                mealPresets
-                            }.listRowBackground(Color.chart)
-                        }
+//                        if state.displayPresets {
+//                            Section {
+//                                mealPresets
+//                            }.listRowBackground(Color.chart)
+//                        }
 
                         Section {
                             HStack {
@@ -469,6 +299,13 @@ extension Bolus {
                         Text("Close")
                     }
                 }
+                ToolbarItem(placement: .topBarTrailing) {
+                    Button(action: {
+                        showPresetSheet = true
+                    }, label: {
+                        Image(systemName: "plus")
+                    })
+                }
             })
             .onAppear {
                 configureView {
@@ -485,6 +322,11 @@ extension Bolus {
                         selection: $calculatorDetent
                     )
             }
+            .sheet(isPresented: $showPresetSheet, onDismiss: {
+                showPresetSheet = false
+            }) {
+                MealPresetView(state: state)
+            }
         }
 
         var progressText: ProgressText {

+ 404 - 0
FreeAPS/Sources/Modules/Bolus/View/MealPresetView.swift

@@ -0,0 +1,404 @@
+import CoreData
+import Foundation
+import SwiftUI
+
+struct MealPresetView: View {
+    @StateObject var state: Bolus.StateModel
+    @Environment(\.colorScheme) var colorScheme
+    @Environment(\.dismiss) var dismiss
+    @Environment(\.managedObjectContext) var moc
+
+    @State private var showAlert = false
+    @State private var dish: String = ""
+    @State private var saved: Bool = false
+
+    @State private var addNewPreset: Bool = false
+
+    @State private var presetCarbs: Decimal = 0
+    @State private var presetFat: Decimal = 0
+    @State private var presetProtein: Decimal = 0
+
+    @State private var carbs: Decimal = 0
+    @State private var fat: Decimal = 0
+    @State private var protein: Decimal = 0
+
+    @FetchRequest(
+        entity: MealPresetStored.entity(),
+        sortDescriptors: [NSSortDescriptor(key: "dish", ascending: true)]
+    ) var carbPresets: FetchedResults<MealPresetStored>
+
+    private var mealFormatter: NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 1
+        return formatter
+    }
+
+    private 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
+            )
+    }
+
+    var body: some View {
+        NavigationStack {
+            Form {
+                if addNewPreset {
+                    showNewPresetForm()
+                } else {
+                    addNewPresetButton
+                }
+
+                mealPresets
+                dishInfos()
+                addPresetToTreatmentsButton
+            }
+            .scrollContentBackground(.hidden).background(color)
+            .navigationTitle("Meal Presets")
+            .navigationBarTitleDisplayMode(.inline)
+            .toolbar(content: {
+                ToolbarItem(placement: .topBarLeading) {
+                    Button {
+                        dismiss()
+                    } label: {
+                        Text("Close")
+                    }
+                }
+            })
+            .onDisappear {
+                resetValues()
+            }
+        }
+    }
+
+    private var addNewPresetButton: some View {
+        Button(action: {
+            addNewPreset = true
+        }, label: {
+            HStack {
+                Spacer()
+                Text("Add new meal Preset")
+                Spacer()
+            }
+        })
+    }
+
+    @ViewBuilder private func showNewPresetForm() -> some View {
+        Section {
+            TextField("Name Of Dish", text: $dish)
+        } header: {
+            Text("New Preset")
+        } footer: {
+            Text("Add a name for your Preset")
+        }
+
+        Section {
+            carbsTextField()
+
+            if state.useFPUconversion {
+                proteinAndFat()
+            }
+        } footer: {
+            Text("Add the macros for your new Preset")
+        }
+
+        savePresetButton
+    }
+
+    @ViewBuilder private func carbsTextField() -> some View {
+        HStack {
+            Text("Carbs").fontWeight(.semibold)
+            Spacer()
+            TextFieldWithToolBar(
+                text: $presetCarbs,
+                placeholder: "0",
+                keyboardType: .numberPad,
+                numberFormatter: mealFormatter
+            )
+            Text("g").foregroundColor(.secondary)
+        }
+    }
+
+    @ViewBuilder private func proteinAndFat() -> some View {
+        HStack {
+            Text("Fat").foregroundColor(.orange)
+            Spacer()
+            TextFieldWithToolBar(text: $presetFat, placeholder: "0", keyboardType: .numberPad, numberFormatter: mealFormatter)
+            Text("g").foregroundColor(.secondary)
+        }
+        HStack {
+            Text("Protein").foregroundColor(.red)
+            Spacer()
+            TextFieldWithToolBar(
+                text: $presetProtein,
+                placeholder: "0",
+                keyboardType: .numberPad,
+                numberFormatter: mealFormatter
+            )
+            Text("g").foregroundColor(.secondary)
+        }
+    }
+
+    private var mealPresets: some View {
+        Section {
+            HStack {
+                if state.selection != nil {
+                    minusButton
+                }
+                Picker("Preset", selection: $state.selection) {
+                    Text("Saved Food").tag(nil as MealPresetStored?)
+                    ForEach(carbPresets, id: \.self) { (preset: MealPresetStored) in
+                        Text(preset.dish ?? "").tag(preset as MealPresetStored?)
+                    }
+                }
+                .labelsHidden()
+                .frame(maxWidth: .infinity, alignment: .center)
+                ._onBindingChange($state.selection) { _ in
+                    carbs += ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
+                    fat += ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
+                    protein += ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
+                    state.addToSummation()
+                }
+                if state.selection != nil {
+                    plusButton
+                }
+            }
+
+            HStack {
+                Spacer()
+
+                Button("Delete Preset") {
+                    showAlert.toggle()
+                }
+                .disabled(state.selection == nil)
+                .tint(.orange)
+                .buttonStyle(.borderless)
+                .alert(
+                    "Delete preset '\(state.selection?.dish ?? "")'?",
+                    isPresented: $showAlert,
+                    actions: {
+                        Button("No", role: .cancel) {}
+                        Button("Yes", role: .destructive) {
+                            if let selection = state.selection {
+                                let previousSelection = state.selection
+                                let count = state.summation.filter { $0 == selection.dish }.count
+                                state.summation.removeAll { $0 == selection.dish }
+                                carbs -= (((selection.carbs ?? 0) as NSDecimalNumber) as Decimal) * Decimal(count)
+                                fat -= (((selection.fat ?? 0) as NSDecimalNumber) as Decimal) * Decimal(count)
+                                protein -= (((selection.protein ?? 0) as NSDecimalNumber) as Decimal) * Decimal(count)
+                                state.deletePreset()
+                                state.selection = previousSelection
+                            }
+                        }
+                    }
+                )
+
+                Spacer()
+            }
+
+        } footer: {
+            Text("Here you can choose from an existing Preset to add it to your treatments")
+        }
+    }
+
+    private var savePresetButton: some View {
+        Button {
+            saved = true
+            if dish != "", saved {
+                let preset = MealPresetStored(context: moc)
+                preset.dish = dish
+                preset.fat = presetFat as NSDecimalNumber
+                preset.protein = presetProtein as NSDecimalNumber
+                preset.carbs = presetCarbs as NSDecimalNumber
+                if self.moc.hasChanges {
+                    try? moc.save()
+                }
+//                state.addNewPresetToWaitersNotepad(dish)
+                resetValues()
+                saved = false
+                addNewPreset = false
+            }
+        }
+        label: {
+            Text("Save")
+                .font(.headline)
+                .foregroundStyle(Color.white)
+                .frame(maxWidth: .infinity, alignment: .center)
+        }
+        .disabled(notEnoughPresetInfosGiven)
+        .listRowBackground(notEnoughPresetInfosGiven ? Color(.systemGray3) : Color(.systemBlue))
+        .shadow(radius: 3)
+        .clipShape(RoundedRectangle(cornerRadius: 8))
+    }
+
+    private var addPresetToTreatmentsButton: some View {
+        Button {
+            state.carbs += carbs
+            state.fat += fat
+            state.protein += protein
+
+            dismiss()
+        }
+        label: {
+            Text("Add to treatments")
+                .font(.headline)
+                .foregroundStyle(Color.white)
+                .frame(maxWidth: .infinity, alignment: .center)
+        }
+        .disabled(noPresetChosen)
+        .listRowBackground(noPresetChosen ? Color(.systemGray3) : Color(.systemBlue))
+        .shadow(radius: 3)
+        .clipShape(RoundedRectangle(cornerRadius: 8))
+    }
+
+    private var noPresetChosen: Bool {
+        state.selection == nil || carbs == 0 || fat == 0 || protein == 0
+    }
+
+    private var notEnoughPresetInfosGiven: Bool {
+        state
+            .useFPUconversion ? (presetCarbs <= 0 && presetFat <= 0 && presetProtein <= 0 || dish == "") :
+            (presetCarbs <= 0 || dish == "")
+    }
+
+    @ViewBuilder private func dishInfos() -> some View {
+        if !state.summation.isEmpty {
+            let presetSummary = generatePresetSummary()
+
+            Section(header: Text("Summary")) {
+                presetSummary
+                    .lineLimit(nil) // In case the text is too long, allow it to wrap to the next line
+
+                HStack {
+                    HStack {
+                        Text("Carbs: ")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                        Text("\(carbs as NSNumber, formatter: mealFormatter)")
+                        Text(" g")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                    }
+
+                    Spacer()
+
+                    HStack {
+                        Text("Fat: ")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                        Text("\(fat as NSNumber, formatter: mealFormatter)")
+                        Text(" g")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                    }
+
+                    Spacer()
+
+                    HStack {
+                        Text("Protein: ")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                        Text("\(protein as NSNumber, formatter: mealFormatter)")
+                        Text(" g")
+                            .font(.subheadline)
+                            .foregroundStyle(.secondary)
+                    }
+                }
+            }
+        }
+    }
+
+    private func generatePresetSummary() -> some View {
+        var counts = [String: Int]()
+
+        for preset in state.summation {
+            counts[preset, default: 0] += 1
+        }
+
+        return VStack(alignment: .leading) {
+            ForEach(counts.sorted(by: { $0.key < $1.key }), id: \.key) { key, value in
+                if value > 0 {
+                    HStack {
+                        Text("\(value)")
+                            .foregroundColor(.blue)
+                        Text(key)
+                    }
+                }
+            }
+        }
+    }
+
+    private func resetValues() {
+        dish = ""
+        presetCarbs = 0
+        presetFat = 0
+        presetProtein = 0
+//        saved = false
+//        addNewPreset = false
+        state.selection = nil
+        state.summation.removeAll()
+    }
+
+    private var minusButton: some View {
+        Button {
+            if carbs != 0 {
+                carbs -= (((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal)
+            } else { carbs = 0 }
+
+            if fat != 0,
+               (fat - (((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal) as Decimal) >= 0
+            {
+                fat -= (((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal)
+            } else { fat = 0 }
+
+            if protein != 0,
+               (protein - (((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal) as Decimal) >= 0
+            {
+                protein -= (((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal)
+            } else { protein = 0 }
+
+            state.removePresetFromNewMeal()
+            if carbs == 0, fat == 0, protein == 0 { state.summation = [] }
+        }
+        label: { Image(systemName: "minus.circle.fill")
+            .font(.system(size: 20))
+        }
+        .disabled(
+            state
+                .selection == nil ||
+                (
+                    !state.summation
+                        .contains(state.selection?.dish ?? "") && (state.selection?.dish ?? "") != ""
+                )
+        )
+        .buttonStyle(.borderless)
+        .tint(.blue)
+    }
+
+    private var plusButton: some View {
+        Button {
+            carbs += ((state.selection?.carbs ?? 0) as NSDecimalNumber) as Decimal
+            fat += ((state.selection?.fat ?? 0) as NSDecimalNumber) as Decimal
+            protein += ((state.selection?.protein ?? 0) as NSDecimalNumber) as Decimal
+
+            state.addPresetToNewMeal()
+        }
+        label: { Image(systemName: "plus.circle.fill")
+            .font(.system(size: 20))
+        }
+        .disabled(state.selection == nil)
+        .buttonStyle(.borderless)
+        .tint(.blue)
+    }
+}