@@ -66,6 +66,8 @@ struct CarbEntryView: View, HorizontalSizeClassOverride {
66
66
. edgesIgnoringSafeArea ( . all)
67
67
68
68
ScrollView {
69
+ warningsCard
70
+
69
71
mainCard
70
72
. padding ( . top, 8 )
71
73
@@ -95,10 +97,10 @@ struct CarbEntryView: View, HorizontalSizeClassOverride {
95
97
96
98
private var mainCard : some View {
97
99
VStack ( spacing: 10 ) {
98
- var amountConsumedFocused : Binding < Bool > = Binding ( get: { expandedRow == . amountConsumed } , set: { expandedRow = $0 ? . amountConsumed : nil } )
99
- var timeFocused : Binding < Bool > = Binding ( get: { expandedRow == . time } , set: { expandedRow = $0 ? . time : nil } )
100
- var foodTypeFocused : Binding < Bool > = Binding ( get: { expandedRow == . foodType } , set: { expandedRow = $0 ? . foodType : nil } )
101
- var absorptionTimeFocused : Binding < Bool > = Binding ( get: { expandedRow == . absorptionTime } , set: { expandedRow = $0 ? . absorptionTime : nil } )
100
+ let amountConsumedFocused : Binding < Bool > = Binding ( get: { expandedRow == . amountConsumed } , set: { expandedRow = $0 ? . amountConsumed : nil } )
101
+ let timeFocused : Binding < Bool > = Binding ( get: { expandedRow == . time } , set: { expandedRow = $0 ? . time : nil } )
102
+ let foodTypeFocused : Binding < Bool > = Binding ( get: { expandedRow == . foodType } , set: { expandedRow = $0 ? . foodType : nil } )
103
+ let absorptionTimeFocused : Binding < Bool > = Binding ( get: { expandedRow == . absorptionTime } , set: { expandedRow = $0 ? . absorptionTime : nil } )
102
104
103
105
CarbQuantityRow ( quantity: $viewModel. carbsQuantity, isFocused: amountConsumedFocused, title: NSLocalizedString ( " Amount Consumed " , comment: " Label for carb quantity entry row on carb entry screen " ) , preferredCarbUnit: viewModel. preferredCarbUnit)
104
106
@@ -133,6 +135,49 @@ struct CarbEntryView: View, HorizontalSizeClassOverride {
133
135
private func clearExpandedRow( ) {
134
136
self . expandedRow = nil
135
137
}
138
+ }
139
+
140
+ // MARK: - Warnings & Alerts
141
+ extension CarbEntryView {
142
+ private var warningsCard : some View {
143
+ ForEach ( Array ( viewModel. warnings) . sorted ( by: { $0. priority < $1. priority } ) ) { warning in
144
+ warningView ( for: warning)
145
+ . padding ( . vertical, 8 )
146
+ . padding ( . horizontal)
147
+ . background ( CardBackground ( ) )
148
+ . padding ( . horizontal)
149
+ . padding ( . top, 8 )
150
+ }
151
+ }
152
+
153
+ private func warningView( for warning: CarbEntryViewModel . Warning ) -> some View {
154
+ HStack {
155
+ Image ( systemName: " exclamationmark.triangle.fill " )
156
+ . foregroundColor ( triangleColor ( for: warning) )
157
+
158
+ Text ( warningText ( for: warning) )
159
+ . font ( . caption)
160
+ }
161
+ . frame ( maxWidth: . infinity, alignment: . leading)
162
+ }
163
+
164
+ private func triangleColor( for warning: CarbEntryViewModel . Warning ) -> Color {
165
+ switch warning {
166
+ case . entryIsMissedMeal:
167
+ return . critical
168
+ case . overrideInProgress:
169
+ return . warning
170
+ }
171
+ }
172
+
173
+ private func warningText( for warning: CarbEntryViewModel . Warning ) -> String {
174
+ switch warning {
175
+ case . entryIsMissedMeal:
176
+ return NSLocalizedString ( " Loop has detected an missed meal and estimated its size. Edit the carb amount to match the amount of any carbs you may have eaten. " , comment: " Warning displayed when user is adding a meal from an missed meal notification " )
177
+ case . overrideInProgress:
178
+ return NSLocalizedString ( " An active override is modifying your carb ratio and insulin sensitivity. If you don't want this to affect your bolus calculation and projected glucose, consider turning off the override. " , comment: " Warning to ensure the carb entry is accurate during an override " )
179
+ }
180
+ }
136
181
137
182
private func alert( for alert: CarbEntryViewModel . Alert ) -> SwiftUI . Alert {
138
183
switch alert {
@@ -162,29 +207,8 @@ struct CarbEntryView: View, HorizontalSizeClassOverride {
162
207
}
163
208
}
164
209
210
+ // MARK: - Favorite Foods Card
165
211
extension CarbEntryView {
166
- private var dismissButton : some View {
167
- Button ( action: dismiss) {
168
- Text ( " Cancel " )
169
- }
170
- }
171
-
172
- private var continueButton : some View {
173
- Button ( action: viewModel. continueToBolus) {
174
- Text ( " Continue " )
175
- }
176
- . disabled ( viewModel. continueButtonDisabled)
177
- }
178
-
179
- private var continueActionButton : some View {
180
- Button ( action: viewModel. continueToBolus) {
181
- Text ( " Continue " )
182
- }
183
- . buttonStyle ( ActionButtonStyle ( ) )
184
- . padding ( )
185
- . disabled ( viewModel. continueButtonDisabled)
186
- }
187
-
188
212
private var favoriteFoodsCard : some View {
189
213
VStack ( alignment: . leading, spacing: 6 ) {
190
214
Text ( " FAVORITE FOODS " )
@@ -262,6 +286,32 @@ extension CarbEntryView {
262
286
}
263
287
}
264
288
289
+ // MARK: - Other UI Elements
290
+ extension CarbEntryView {
291
+ private var dismissButton : some View {
292
+ Button ( action: dismiss) {
293
+ Text ( " Cancel " )
294
+ }
295
+ }
296
+
297
+ private var continueButton : some View {
298
+ Button ( action: viewModel. continueToBolus) {
299
+ Text ( " Continue " )
300
+ }
301
+ . disabled ( viewModel. continueButtonDisabled)
302
+ }
303
+
304
+ private var continueActionButton : some View {
305
+ Button ( action: viewModel. continueToBolus) {
306
+ Text ( " Continue " )
307
+ }
308
+ . buttonStyle ( ActionButtonStyle ( ) )
309
+ . padding ( )
310
+ . disabled ( viewModel. continueButtonDisabled)
311
+ }
312
+
313
+ }
314
+
265
315
extension CarbEntryView {
266
316
enum Row {
267
317
case amountConsumed, time, foodType, absorptionTime, favoriteFoodSelection
0 commit comments