@hedia/recommendation-screen 2.1.14 → 2.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/coverage/clover.xml +588 -590
  2. package/coverage/coverage-final.json +27 -27
  3. package/coverage/lcov-report/index.html +7 -7
  4. package/coverage/lcov-report/src/RecommendationScreen.tsx.html +1039 -70
  5. package/coverage/lcov-report/src/__tests__/index.html +1 -1
  6. package/coverage/lcov-report/src/__tests__/utils.tsx.html +35 -14
  7. package/coverage/lcov-report/src/components/Header.tsx.html +14 -5
  8. package/coverage/lcov-report/src/components/InfoBars.tsx.html +97 -13
  9. package/coverage/lcov-report/src/components/InvisibleNumberInput.tsx.html +206 -14
  10. package/coverage/lcov-report/src/components/LimitationMessage.tsx.html +20 -2
  11. package/coverage/lcov-report/src/components/LineSeparator.tsx.html +13 -4
  12. package/coverage/lcov-report/src/components/RecentInsulin.tsx.html +30 -3
  13. package/coverage/lcov-report/src/components/RecommendationModal.tsx.html +200 -20
  14. package/coverage/lcov-report/src/components/RecommendedCarbs.tsx.html +218 -20
  15. package/coverage/lcov-report/src/components/RecommendedInsulin.tsx.html +195 -27
  16. package/coverage/lcov-report/src/components/Remeasure.tsx.html +125 -14
  17. package/coverage/lcov-report/src/components/TransferToLogbook.tsx.html +71 -8
  18. package/coverage/lcov-report/src/components/TwoOptionModal.tsx.html +34 -10
  19. package/coverage/lcov-report/src/components/activity/Activity.tsx.html +58 -7
  20. package/coverage/lcov-report/src/components/activity/ActivityIcon.tsx.html +42 -3
  21. package/coverage/lcov-report/src/components/activity/ActivityIntensity.tsx.html +30 -6
  22. package/coverage/lcov-report/src/components/activity/index.html +1 -1
  23. package/coverage/lcov-report/src/components/index.html +10 -10
  24. package/coverage/lcov-report/src/components/mood/Emotion.tsx.html +85 -10
  25. package/coverage/lcov-report/src/components/mood/MoodIcon.tsx.html +87 -12
  26. package/coverage/lcov-report/src/components/mood/index.html +1 -1
  27. package/coverage/lcov-report/src/index.html +1 -1
  28. package/coverage/lcov-report/src/locale/i18nUtils.ts.html +47 -8
  29. package/coverage/lcov-report/src/locale/index.html +1 -1
  30. package/coverage/lcov-report/src/utils/AttentionMessages.tsx.html +235 -7
  31. package/coverage/lcov-report/src/utils/Constants.ts.html +71 -2
  32. package/coverage/lcov-report/src/utils/RecommendationError.tsx.html +89 -2
  33. package/coverage/lcov-report/src/utils/RecommendationUtils.ts.html +337 -40
  34. package/coverage/lcov-report/src/utils/Translations.ts.html +27 -3
  35. package/coverage/lcov-report/src/utils/Utils.ts.html +295 -19
  36. package/coverage/lcov-report/src/utils/Validations.ts.html +763 -61
  37. package/coverage/lcov-report/src/utils/index.html +1 -1
  38. package/coverage/lcov.info +1243 -1249
  39. package/ignore-git.sh +1 -0
  40. package/ignore-publish.sh +1 -0
  41. package/package.json +5 -3
  42. package/src/RecommendationScreen.d.ts +323 -6
  43. package/src/RecommendationScreen.js +234 -1
  44. package/src/__tests__/RecommendationScreen.test.js +35 -1
  45. package/src/__tests__/utils.d.ts +5 -5
  46. package/src/__tests__/utils.js +1 -1
  47. package/src/components/Header.d.ts +4 -43
  48. package/src/components/Header.js +3 -1
  49. package/src/components/Icon.d.ts +9 -2
  50. package/src/components/Icon.js +6 -1
  51. package/src/components/InfoBars.d.ts +28 -0
  52. package/src/components/InfoBars.js +23 -0
  53. package/src/components/InvisibleNumberInput.d.ts +66 -3
  54. package/src/components/InvisibleNumberInput.js +53 -0
  55. package/src/components/LimitationMessage.d.ts +6 -0
  56. package/src/components/LimitationMessage.js +4 -0
  57. package/src/components/LineSeparator.d.ts +4 -2
  58. package/src/components/LineSeparator.js +2 -0
  59. package/src/components/RecentInsulin.d.ts +10 -2
  60. package/src/components/RecentInsulin.js +7 -0
  61. package/src/components/RecommendationModal.d.ts +61 -3
  62. package/src/components/RecommendationModal.js +45 -0
  63. package/src/components/RecommendedCarbs.d.ts +71 -4
  64. package/src/components/RecommendedCarbs.js +56 -0
  65. package/src/components/RecommendedInsulin.d.ts +66 -4
  66. package/src/components/RecommendedInsulin.js +51 -5
  67. package/src/components/Remeasure.d.ts +38 -2
  68. package/src/components/Remeasure.js +31 -0
  69. package/src/components/TransferToLogbook.d.ts +23 -3
  70. package/src/components/TransferToLogbook.js +18 -0
  71. package/src/components/TwoOptionModal.d.ts +12 -1
  72. package/src/components/TwoOptionModal.js +3 -3
  73. package/src/components/activity/Activity.d.ts +21 -5
  74. package/src/components/activity/Activity.js +14 -0
  75. package/src/components/activity/ActivityIcon.d.ts +15 -0
  76. package/src/components/activity/ActivityIcon.js +14 -1
  77. package/src/components/activity/ActivityIntensity.d.ts +11 -4
  78. package/src/components/activity/ActivityIntensity.js +7 -0
  79. package/src/components/mood/Emotion.d.ts +26 -1
  80. package/src/components/mood/Emotion.js +20 -0
  81. package/src/components/mood/MoodIcon.d.ts +28 -2
  82. package/src/components/mood/MoodIcon.js +20 -2
  83. package/src/locale/i18nUtils.d.ts +13 -0
  84. package/src/locale/i18nUtils.js +13 -0
  85. package/src/types/enum.d.ts +10 -0
  86. package/src/types/enum.js +9 -0
  87. package/src/types/types.d.ts +9 -7
  88. package/src/utils/AttentionMessages.d.ts +65 -0
  89. package/src/utils/AttentionMessages.js +65 -1
  90. package/src/utils/Constants.d.ts +23 -0
  91. package/src/utils/Constants.js +23 -0
  92. package/src/utils/RecommendationError.d.ts +29 -0
  93. package/src/utils/RecommendationError.js +29 -0
  94. package/src/utils/RecommendationUtils.d.ts +98 -6
  95. package/src/utils/RecommendationUtils.js +92 -0
  96. package/src/utils/Translations.d.ts +7 -0
  97. package/src/utils/Translations.js +7 -0
  98. package/src/utils/Utils.d.ts +92 -0
  99. package/src/utils/Utils.js +94 -2
  100. package/src/utils/Validations.d.ts +232 -9
  101. package/src/utils/Validations.js +225 -2
  102. package/typedoc.json +13 -0
@@ -8,7 +8,7 @@ import RecommendedCarbs from "./components/RecommendedCarbs";
8
8
  import RecommendedInsulin from "./components/RecommendedInsulin";
9
9
  import Remeasure from "./components/Remeasure";
10
10
  import * as Calculator from "@hedia/recommendation-calculator";
11
- import { Milliseconds } from "@hedia/types";
11
+ import { Milliseconds, } from "@hedia/types";
12
12
  import { I18nProvider } from "@lingui/react";
13
13
  import Emotion from "./components/mood/Emotion";
14
14
  import TransferToLogbook from "./components/TransferToLogbook";
@@ -27,10 +27,50 @@ const { InfoBarTestIds, RecommendationScreenTestIds } = Testing.Id;
27
27
  // Ignoring long timer warnings
28
28
  // https://github.com/facebook/react-native/issues/12981#issuecomment-652745831
29
29
  YellowBox.ignoreWarnings([`Setting a timer`]);
30
+ /**
31
+ * The RecommendationScreen is the React component that passes relevant inputs to the recommendation calculation module and presents
32
+ * the resulting recommendation along with related messages or warnings to the user.
33
+ * The RecommendationScreen component accepts properties with the user’s settings/preferences and other inputs needed for calculating a recommendation.
34
+ * @noInheritDoc
35
+ */
30
36
  export default class RecommendationScreen extends React.Component {
37
+ /**
38
+ * Steps:
39
+ * 1. Call the super() method with the props.
40
+ * 2. Execute the following steps and if an exception is thrown, catch it, set the hasError member variable to true and call the onError callback prop with the caught exception as argument:
41
+ * - Call the validateParams() method with the props as argument
42
+ * - Set the recommendationDate member to the current date and time
43
+ * - Set the language by using the language prop as argument for calling changeLanguage()
44
+ * - Unpack recentBoluses from the calculatorParams prop.
45
+ * - Use the calculatorParams prop as argument for calling calculateRecommendation() and unpack all of the resulting values.
46
+ * - Copy the carbRecommendation to the suggestedCarbs member variable.
47
+ * - Set the following state variables:
48
+ * - Set remeasureTime to the return value from calling the getBGLevelRemeasurementReminder() method.
49
+ * - Set isRecommendationDisplayed to be false if the length of recentBoluses is 0 or false otherwise.
50
+ * - Set insulinRecommendation to be the bolus insulin recommendation rounded using roundValue().
51
+ * - Set wasLimited to the wasLimited return value from calling calculateRecommendation() above.
52
+ * - Set activityReduction to the reduction returned from the calculation result.
53
+ * - Set carbRecommendation to the recommendation returned from the calculation result.
54
+ * - Set activeInsulin to the estimation returned from the calculation result.
55
+ * - Set enteredCarbs, enteredInsulin, selectedMood to null.
56
+ * - Set recommendationModal to be true if wasLimited is true or if carbRecommendation after being rounded is truthy or if the return value from calling the getBGLevelAttentionMessage() method is truthy.
57
+ * - Set showExitModal, showLimitationMessage, showTimeoutModal to be false.
58
+ * 3. Start a 15 minute timer assigned to the timer member variable using the setTimeout() function. When the timer expires, call the showTimeoutModal() method.
59
+ * @param props The data required to initialise the Recommendation Screen
60
+ */
31
61
  constructor(props) {
32
62
  super(props);
63
+ /**
64
+ * A guard against displaying wrong or dangerous information to the user.
65
+ * If an error has occurred, this variable will be set to true and an empty placeholder will be rendered instead of the normal recommendation screen.
66
+ */
33
67
  this.hasError = false;
68
+ /**
69
+ * Steps:
70
+ * 1. Evaluate a boolean called isOlderThan15Minutes to indicate whether the recommendationDate member variable represents a time more than 15 minutes ago.
71
+ * 2. If nextAppState is ‘active’ and isOlderThan15Minutes is true then call the showTimeoutModal() method.
72
+ * @param nextAppState The new state of the app.
73
+ */
34
74
  this.handleAppStateChange = (nextAppState) => {
35
75
  const time = this.recommendationDate.getTime();
36
76
  const isOlderThan15Minutes = global.Date.now() - time > Milliseconds.Minute * 15;
@@ -38,9 +78,26 @@ export default class RecommendationScreen extends React.Component {
38
78
  this.showTimeoutModal();
39
79
  }
40
80
  };
81
+ /**
82
+ * Steps:
83
+ * 1. Set the showTimeoutModal state variable to be true. Use a callback function to call the showBolusBar prop callback function with false as argument when the state has been updated.
84
+ * */
41
85
  this.showTimeoutModal = () => {
42
86
  this.setState({ showTimeoutModal: true }, () => this.props.showBolusBar(!this.state.showTimeoutModal));
43
87
  };
88
+ /**
89
+ * Make a new insulin calculation and set the result to be displayed to the user.
90
+ *
91
+ * Steps:
92
+ * 1. Use calculatorParams as an argument for calling calculateRecommendation(). Unpack bolus, wasLimited, and activityReduction from the result.
93
+ * 2. Set the following state variables:
94
+ * - Set insulinRecommendation to the bolus rounded using the roundValue() function.
95
+ * - Set enteredInsulin to be undefined.
96
+ * - Set wasLimited to be the value returned from the insulin calculator.
97
+ * - Set activityReduction to be the value returned from the insulin calculator.
98
+ * - Set showLimitationMessage to be the wasLimited value returned from the insulin calculator.
99
+ * @param calculatorParams The input values for the bolus calculator itself.
100
+ */
44
101
  this.recalculateInsulin = (calculatorParams) => {
45
102
  const { bolus, wasLimited, activityReduction } = Calculator.calculateRecommendation(calculatorParams);
46
103
  this.setState({
@@ -51,6 +108,15 @@ export default class RecommendationScreen extends React.Component {
51
108
  showLimitationMessage: wasLimited,
52
109
  });
53
110
  };
111
+ /**
112
+ * Handle presses on the exit button in the header bar.
113
+ *
114
+ * Steps:
115
+ * 1. If the insulin recommendation is being displayed (the isRecommendationDisplayed state variable is true):
116
+ * - Set the showExitModal state variable to true. When the state has been updated, call the showBolusBar prop callback function with the inverse value of the showExitModal state variable as argument.
117
+ * 2. Else:
118
+ * - Call the exitCallback prop callback function.
119
+ */
54
120
  this.onExit = () => {
55
121
  if (this.state.isRecommendationDisplayed) {
56
122
  this.setState({ showExitModal: true }, () => this.props.showBolusBar(!this.state.showExitModal));
@@ -59,21 +125,66 @@ export default class RecommendationScreen extends React.Component {
59
125
  this.props.exitCallback();
60
126
  }
61
127
  };
128
+ /**
129
+ * Hide the modal that shows attention messages.
130
+ *
131
+ * Steps:
132
+ * 1. Set the recommendationModal state variable to false.
133
+ */
62
134
  this.hideAttentionModal = () => {
63
135
  this.setState({ recommendationModal: false });
64
136
  };
137
+ /**
138
+ * Hide the modal that shows attention messages.
139
+ *
140
+ * Steps:
141
+ * 1. Set the showLimitationMessage state variable to false.
142
+ */
65
143
  this.hideLimitationMessage = () => {
66
144
  this.setState({ showLimitationMessage: false });
67
145
  };
146
+ /**
147
+ * Hide the exit modal. To be used when the user closes the modal directly or in some way exits the recommendation screen.
148
+ *
149
+ * Steps:
150
+ * 1. Set the showExitModal state variable to false.
151
+ * When the state has been updated, call the showBolusBar prop callback function with the inverse value of the showExitModal state variable as argument.
152
+ */
68
153
  this.hideExitModal = () => {
69
154
  this.setState({ showExitModal: false }, () => this.props.showBolusBar(!this.state.showExitModal));
70
155
  };
156
+ /**
157
+ * Hide the modal that warns the user that their recommendation is old.
158
+ *
159
+ * Steps:
160
+ * 1. Set the showTimeoutModal state variable to false.
161
+ * When the state has been updated, call the showBolusBar prop callback function with the inverse value of the showTimeoutModal state variable as argument.
162
+ */
71
163
  this.hideTimeoutModal = () => {
72
164
  this.setState({ showTimeoutModal: false }, () => this.props.showBolusBar(!this.state.showTimeoutModal));
73
165
  };
166
+ /**
167
+ * Used as a callback function for the Remeasure component to update the state when the remeasure time slider’s value changes.
168
+ *
169
+ * Steps:
170
+ * 1. Set the remeasureTime state variable to the value of the remeasureTime argument.
171
+ * @param remeasureTime The number of hours for which to wait before reminding the user to measure their BGL again. 0 indicates that the user should not be reminded.
172
+ */
74
173
  this.updateRemeasureTime = (remeasureTime) => {
75
174
  this.setState({ remeasureTime });
76
175
  };
176
+ /**
177
+ * Handle what happens if the user taps “No” to the question about injecting insulin within the last 4 hours.
178
+ * The card that prompts the user to answer if they have injected insulin within the last 4 hours shall be hidden and
179
+ * the screen shall automatically be scrolled to the bottom so the user can see the now visible “Transfer to logbook” button.
180
+ *
181
+ * Steps:
182
+ * 1. Set the isRecommendationDisplayed state variable to be true.
183
+ * 2. As a callback to the setState() method, define a new anonymous function that calls setTimeout() with a duration of 0 milliseconds.
184
+ * When the time expires, call the scrollToEnd() method of the scrollView member, with the animated argument set to true.
185
+ * This ensures that the scroll event happens after all other events that get queued to happen at the same time,
186
+ * so all relevant elements are visible on the screen and the scroll happens reliably.
187
+ */
77
188
  this.handleNoRecentInsulin = () => {
78
189
  this.setState({ isRecommendationDisplayed: true }, () => {
79
190
  setTimeout(() => {
@@ -81,38 +192,113 @@ export default class RecommendationScreen extends React.Component {
81
192
  }, 0);
82
193
  });
83
194
  };
195
+ /**
196
+ * Handle what happens when the user changes the content of the additional carbohydrates input field.
197
+ *
198
+ * Steps:
199
+ * 1. Set the enteredCarbs state variable to the value of the enteredCarbs argument.
200
+ * 2. As a callback to the setState() method, define a new anonymous function that calls the recalculateInsulin() function using
201
+ * a copy of the calculatorParams prop where the carbohydrates property has been overwritten to be
202
+ * the sum of the carbohydrates property of the calculatorParams prop and the enteredCarbs argument.
203
+ * @param enteredCarbs The amount of carbohydrates in grams that has been entered in the additional carbohydrates input field.
204
+ */
84
205
  this.updateCarbRecommendation = (enteredCarbs) => {
85
206
  const providedCarbs = this.props.calculatorParams.carbohydrates;
86
207
  this.setState({ enteredCarbs }, () => {
87
208
  this.recalculateInsulin({ ...this.props.calculatorParams, carbohydrates: providedCarbs + enteredCarbs });
88
209
  });
89
210
  };
211
+ /**
212
+ * Handle what happens when the cross button by the additional carbohydrates button is tapped.
213
+ *
214
+ * Steps:
215
+ * 1. Set both the enteredCarbs and the carbRecommendation state variables to null.
216
+ * 2. As a callback to the setState() method, define a new anonymous function that calls the recalculateInsulin() function using a copy of the calculatorParams prop.
217
+ */
90
218
  this.removeCarbRecommendation = () => {
91
219
  this.setState({ enteredCarbs: null, carbRecommendation: null }, () => this.recalculateInsulin({ ...this.props.calculatorParams }));
92
220
  };
221
+ /**
222
+ * Handle what happens when the user is recommended to eat additional carbohydrates but taps the decline button.
223
+ *
224
+ * Steps:
225
+ * 1. Call the hideAttentionModal() method.
226
+ * 2. Call the removeCarbRecommendation() method.
227
+ * 3. Call the carbRecommendationAnswer() prop callback function with false as argument.
228
+ */
93
229
  this.declineCarbRecommendation = () => {
94
230
  this.hideAttentionModal();
95
231
  this.removeCarbRecommendation();
96
232
  this.props.carbRecommendationAnswer(false);
97
233
  };
234
+ /**
235
+ * Handle what happens when the user is recommended to eat additional carbohydrates and they tap the accept button.
236
+ *
237
+ * Steps:
238
+ * 1. Call the hideAttentionModal() method.
239
+ * 2. Call the carbRecommendationAnswer() prop callback function with true as argument.
240
+ */
98
241
  this.acceptCarbRecommendation = () => {
99
242
  this.hideAttentionModal();
100
243
  this.props.carbRecommendationAnswer(true);
101
244
  };
245
+ /**
246
+ * Handles what happens when the user hits the “close calculation”-button on the exit modal.
247
+ *
248
+ * Steps:
249
+ * 1. If the showExitModal state variable is true then call the hideExitModal() method. Otherwise, call the hideTimeoutModal() method
250
+ * 2. Call the closeCalculationCallback prop callback function.
251
+ */
102
252
  this.closeCalculation = () => {
103
253
  this.state.showExitModal ? this.hideExitModal() : this.hideTimeoutModal();
104
254
  this.props.closeCalculationCallback();
105
255
  };
256
+ /**
257
+ * Close the current recommendation and start a new bolus calculation.
258
+ *
259
+ * Steps:
260
+ * 1. Call the hideTimeoutModal() method.
261
+ * 2. Call the restartCalculation prop callback function.
262
+ */
106
263
  this.restartCalculation = () => {
107
264
  this.hideTimeoutModal();
108
265
  this.props.restartCalculation();
109
266
  };
267
+ /**
268
+ * Used as a callback function for the Emotion component to update the state when a mood icon is tapped.
269
+ *
270
+ * Steps:
271
+ * 1. Set the selectedMood state variable to the value of the selectedMood argument.
272
+ * @param selectedMood he mood that should be selected going forward or null if no mood should be selected.
273
+ */
110
274
  this.handleMoodSelected = (selectedMood) => {
111
275
  this.setState({ selectedMood });
112
276
  };
277
+ /**
278
+ * Handle what happens when the user changes the content of the insulin input field.
279
+ *
280
+ * Steps:
281
+ * 1. Set the enteredInsulin state variable to the value of the enteredInsulin argument.
282
+ * @param enteredInsulin The amount of insulin (in units) that has been entered in the insulin input field.
283
+ */
113
284
  this.updateInsulinRecommendation = (enteredInsulin) => {
114
285
  this.setState({ enteredInsulin });
115
286
  };
287
+ /**
288
+ * Handle what happens when the “Transfer to Logbook” button is pressed.
289
+ * Namely, the entered data should be saved in a logbook entry and the recommendation screen should be closed.
290
+ *
291
+ * Steps:
292
+ * 1. Unpack the enteredCarbs, enteredInsulin, insulinRecommendation, remeasureTime, and showExitModal state variables
293
+ * 2. Create an IResult object called carbs consisting of suggestedCarbs and enteredCarbs.
294
+ * 3. Create an IResult object called Insulin consisting of insulinRecommendation and enteredInsulin.
295
+ * 4. If showExitModal is true then call the hideExitModal() method. otherwise call the hideTimeoutModal() method.
296
+ * 5. Call the transferToLogbook prop callback function with the following arguments:
297
+ * - Set the carbs argument to the carbs IResult object.
298
+ * - Set the insulin argument to the insulin IResult object.
299
+ * - Set the reminder argument to the remeasureTime state variable.
300
+ * - Set the recommendationDate argument to the recommendationDate member variable.
301
+ */
116
302
  this.handleTransfer = () => {
117
303
  const { enteredCarbs, enteredInsulin, insulinRecommendation, remeasureTime, showExitModal, selectedMood, } = this.state;
118
304
  const carbs = { suggested: this.suggestedCarbs, entered: enteredCarbs };
@@ -120,18 +306,48 @@ export default class RecommendationScreen extends React.Component {
120
306
  showExitModal ? this.hideExitModal() : this.hideTimeoutModal();
121
307
  this.props.transferToLogbook(carbs, insulin, remeasureTime, this.recommendationDate, selectedMood);
122
308
  };
309
+ /**
310
+ * Get the attention message that should be displayed for the user to draw their attention to noteworthy circumstances regarding their current blood glucose level.
311
+ *
312
+ * Steps:
313
+ * 1. Unpack calculatorParams and latestLogbookFrom6Hours from the props.
314
+ * 2. Unpack currentBGL and activity from calculatorparams.
315
+ * 3. Get bgLevel, the categorisation of the blood glucose level, by calling the getBGLevel() function with the currentBGL and latestLogbookFrom6Hours as arguments.
316
+ * 4. Return the attention message that is returned when calling getAttentionMessage() using bgLevel and activity as arguments.
317
+ * @returns A string describing what the user needs to be aware of regarding their current blood glucose level.
318
+ * If there is nothing noteworthy, null will be returned instead.
319
+ */
123
320
  this.getBGLevelAttentionMessage = () => {
124
321
  const { calculatorParams, latestLogbookFrom6Hours } = this.props;
125
322
  const { currentBGL, activity } = calculatorParams;
126
323
  const bgLevel = getBGLevel(currentBGL, latestLogbookFrom6Hours);
127
324
  return getAttentionMessage(bgLevel, activity);
128
325
  };
326
+ /**
327
+ * Get the initial value for the remeasurement reminder time slider depending on the user’s entered information.
328
+ *
329
+ * Steps:
330
+ * 1. Unpack calculatorParams, userReminder, and latestLogbookFrom6Hours from the props.
331
+ * 2. Unpack currentBGL, activity, and carbohydrates from calculatorParams.
332
+ * 3. Get bgLevel, the categorisation of the blood glucose level, by calling the getBGLevel() function with the currentBGL and latestLogbookFrom6Hours as arguments.
333
+ * 4. Return the attention message that is returned when calling getReminder() using bgLevel, carbohydrates, userReminder, and activity as arguments.
334
+ * @returns The time interval in hours that should be used as the initial value for the remeasurement reminder time slider.
335
+ */
129
336
  this.getBGLevelRemeasurementReminder = () => {
130
337
  const { calculatorParams, userReminder, latestLogbookFrom6Hours } = this.props;
131
338
  const { currentBGL, activity, carbohydrates } = calculatorParams;
132
339
  const bgLevel = getBGLevel(currentBGL, latestLogbookFrom6Hours);
133
340
  return getReminder(bgLevel, carbohydrates, userReminder, activity);
134
341
  };
342
+ /**
343
+ * Get the attention message that should be displayed to the user to let them know that the insulin recommendation that
344
+ * is being displayed to them was limited by the maximum insulin threshold.
345
+ *
346
+ * Steps:
347
+ * 1. Unpack the wasLimited and activityReduction state variables.
348
+ * 2. Return the result from calling getLimitationMessage() with wasLimited and activityReduction as arguments.
349
+ * @returns A message to inform the user how the insulin recommendation was limited. If there is no limitation attention message, null will be returned instead.
350
+ */
135
351
  this.getLimitationAttentionMessage = () => {
136
352
  const { wasLimited, activityReduction } = this.state;
137
353
  return getLimitationMessage(wasLimited, activityReduction);
@@ -166,15 +382,32 @@ export default class RecommendationScreen extends React.Component {
166
382
  props.onError(error);
167
383
  }
168
384
  }
385
+ /**
386
+ * Called immediately after a component is mounted. Setting state here will trigger re-rendering.
387
+ *
388
+ * Steps:
389
+ * 1. Create a listener to call the handleAppStateChange() method when the app state changes.
390
+ */
169
391
  componentDidMount() {
170
392
  AppState.addEventListener(`change`, this.handleAppStateChange);
171
393
  }
394
+ /**
395
+ * Called immediately before a component is destroyed.
396
+ * Perform any necessary cleanup in this method, such as cancelled network requests, or cleaning up any DOM elements created in componentDidMount.
397
+ *
398
+ * Clear the 15 minute timer that was set in the constructor during initialisation so it doesn’t keep running and gets triggered after the recommendation screen was closed.
399
+ *
400
+ * Steps:
401
+ * 1. Call clearTimeout on the timer member variable.
402
+ * 2. Remove the listener for app state changes that was set by the componentDidMount() method.
403
+ */
172
404
  componentWillUnmount() {
173
405
  if (this.timer !== undefined) {
174
406
  clearTimeout(this.timer);
175
407
  }
176
408
  AppState.removeEventListener(`change`, this.handleAppStateChange);
177
409
  }
410
+ /** Render a JSX element for displaying the insulin recommendation screen. */
178
411
  render() {
179
412
  if (this.hasError) {
180
413
  return <View style={containerStyles.container}/>;
@@ -294,7 +294,7 @@ describe(`RecommendationScreen`, () => {
294
294
  recentBoluses | shown
295
295
  ${[]} | ${true}
296
296
  ${[{ insulinDose: 4, secondsPassed: 5500 }]} | ${false}
297
- `(`Only show recent insulin if recent boluses is empty`, ({ recentBoluses, shown }) => {
297
+ `(`Only show recent insulin if recent boluses is empty`, ({ recentBoluses, shown, }) => {
298
298
  const props = getRecommendationProps({
299
299
  calculatorParams: {
300
300
  ...getRecommendationProps().calculatorParams,
@@ -566,6 +566,40 @@ describe(`RecommendationScreen`, () => {
566
566
  expect(shownKetoneUnit).toBe(``);
567
567
  expect(shownKetoneValue).toBe(`-`);
568
568
  });
569
+ test.each `
570
+ currentBKLMmoll | bloodKetoneUnit | expectedDisplayedValue
571
+ ${3.12345600000095} | ${BloodKetonesUnit.MMOL_L} | ${`3.1`}
572
+ ${7.65345600000095} | ${BloodKetonesUnit.MMOL_L} | ${`7.7`}
573
+ ${0.92000000000001} | ${BloodKetonesUnit.MG_DL} | ${`10`}
574
+ ${1.00000000000001} | ${BloodKetonesUnit.MG_DL} | ${`10`}
575
+ `(`InfoBars displays blood ketone: $currentBKLMmoll with the right decimal`, ({ currentBKLMmoll, bloodKetoneUnit, expectedDisplayedValue }) => {
576
+ const { BloodKetone: BKValueTestID } = InfoBarTestIds.Value;
577
+ const props = {
578
+ ...getRecommendationProps(),
579
+ currentBKL: currentBKLMmoll,
580
+ bloodKetoneUnit,
581
+ };
582
+ const wrapper = render(<RecommendationScreen {...props}/>);
583
+ const shownKetoneValue = queryTextFromComponent(wrapper, BKValueTestID);
584
+ expect(shownKetoneValue).toBe(expectedDisplayedValue);
585
+ });
586
+ test.each `
587
+ currentBGLMmoll | bloodGlucoseUnit | expectedDisplayedValue
588
+ ${32.65345600000095} | ${BloodGlucoseUnit.MMOL_L} | ${`32.7`}
589
+ ${3.493456000000095} | ${BloodGlucoseUnit.MMOL_L} | ${`3.5`}
590
+ ${5.530000000000001} | ${BloodGlucoseUnit.MG_DL} | ${`100`}
591
+ ${5.550000000000001} | ${BloodGlucoseUnit.MG_DL} | ${`100`}
592
+ `(`InfoBars displays blood glucose: $currentBGLMmoll with the right decimal`, ({ currentBGLMmoll, bloodGlucoseUnit, expectedDisplayedValue }) => {
593
+ const { BloodGlucose: BGValueTestID } = InfoBarTestIds.Value;
594
+ const calculatorParams = {
595
+ ...generateDefaultCalculatorParams(),
596
+ currentBGL: currentBGLMmoll,
597
+ };
598
+ const props = { ...getRecommendationProps(), calculatorParams, bloodGlucoseUnit };
599
+ const wrapper = render(<RecommendationScreen {...props}/>);
600
+ const shownGlucoseValue = queryTextFromComponent(wrapper, BGValueTestID);
601
+ expect(shownGlucoseValue).toBe(expectedDisplayedValue);
602
+ });
569
603
  test(`Can display with null activityDisplayProps`, () => {
570
604
  const props = getRecommendationProps({
571
605
  calculatorParams: getRecommendationProps().calculatorParams,
@@ -1,14 +1,14 @@
1
1
  /// <reference types="react" />
2
+ import { BolusCalculator, Logbook } from "@hedia/types";
2
3
  import { RenderAPI } from "react-native-testing-library";
3
4
  import { ReactTestInstance } from "react-test-renderer";
4
5
  import { IRecommendationProps } from "../RecommendationScreen";
5
6
  import { Testing } from "../types/enum";
6
- import { IActivityParams, IRecommendationParams, logbookEntry } from "../types/types";
7
7
  export declare function getRecommendationProps(partials?: Partial<IRecommendationProps>): IRecommendationProps;
8
- export declare function generateDefaultCalculatorParams(): IRecommendationParams;
9
- export declare function generateActivityProps(): IActivityParams;
10
- export declare function generateDefaultActivitySettings(): IActivityParams["activitySettings"];
11
- export declare function generateDefaultLogbook(): logbookEntry;
8
+ export declare function generateDefaultCalculatorParams(): BolusCalculator.Types.IRecommendationParams;
9
+ export declare function generateActivityProps(): BolusCalculator.Types.IActivityParams;
10
+ export declare function generateDefaultActivitySettings(): BolusCalculator.Types.IActivityParams["activitySettings"];
11
+ export declare function generateDefaultLogbook(): Logbook.Types.ILogbookEntry;
12
12
  export declare function expectTextExists(component: RenderAPI, text: string | RegExp): void;
13
13
  export declare function queryTextFromComponent(wrapper: RenderAPI, testID: Testing.Types.TestIdEnum): string;
14
14
  export declare function expectTextNotExists(component: RenderAPI, text: string | RegExp): void;
@@ -1,4 +1,4 @@
1
- import { Activity, BloodGlucoseUnit, BloodKetonesUnit, Languages, UserSettings } from "@hedia/types";
1
+ import { Activity, BloodGlucoseUnit, BloodKetonesUnit, Languages, UserSettings, } from "@hedia/types";
2
2
  import { I18nProvider } from "@lingui/react";
3
3
  import React from "react";
4
4
  import { i18n } from "../locale/i18nUtils";
@@ -1,49 +1,10 @@
1
1
  import React from "react";
2
- interface IProps {
2
+ export interface IProps {
3
+ /** A callback that doesn’t take any arguments and doesn’t return a value to be called when the cancel-button is pressed. */
3
4
  exitCallback(): void;
4
5
  }
6
+ /** Component to display a header text along with a cancel-button that triggers a callback function. */
5
7
  export default class Header extends React.Component<IProps> {
8
+ /** JSX element to display the cancel button and header. When the cancel button in the header is tabbed, the exitCallback prop callback function should be called. */
6
9
  render(): JSX.Element;
7
10
  }
8
- export declare const headerStyles: {
9
- backgroundColour: {
10
- backgroundColor: string;
11
- };
12
- margin: {
13
- margin: string;
14
- marginBottom: string;
15
- flexDirection: "row";
16
- flex: number;
17
- };
18
- headerContainer: {
19
- flexDirection: "row";
20
- flex: number;
21
- };
22
- exitButtonContainer: {
23
- alignItems: "center";
24
- flex: number;
25
- };
26
- exitButton: {
27
- flex: number;
28
- };
29
- iconStyle: {
30
- fontSize: number;
31
- color: string;
32
- };
33
- headerTextContainer: {
34
- flex: number;
35
- justifyContent: "center";
36
- alignItems: "center";
37
- marginTop: string;
38
- };
39
- headerText: {
40
- fontSize: number;
41
- fontWeight: "bold";
42
- textAlign: "center";
43
- color: string;
44
- };
45
- headerFiller: {
46
- flex: number;
47
- };
48
- };
49
- export {};
@@ -5,7 +5,9 @@ import { i18n } from "../locale/i18nUtils";
5
5
  import { Testing } from "../types/enum";
6
6
  import { BACKGROUND_COLOUR_PURPLE, BORDER_COLOUR_GREY } from "../utils/Constants";
7
7
  import Icon from "./Icon";
8
+ /** Component to display a header text along with a cancel-button that triggers a callback function. */
8
9
  export default class Header extends React.Component {
10
+ /** JSX element to display the cancel button and header. When the cancel button in the header is tabbed, the exitCallback prop callback function should be called. */
9
11
  render() {
10
12
  return (<React.Fragment>
11
13
  <SafeAreaView style={headerStyles.backgroundColour}/>
@@ -30,7 +32,7 @@ export default class Header extends React.Component {
30
32
  </React.Fragment>);
31
33
  }
32
34
  }
33
- export const headerStyles = StyleSheet.create({
35
+ const headerStyles = StyleSheet.create({
34
36
  backgroundColour: {
35
37
  backgroundColor: BACKGROUND_COLOUR_PURPLE,
36
38
  },
@@ -1,13 +1,20 @@
1
1
  import React from "react";
2
2
  import { StyleSheet } from "react-native";
3
- interface IProps {
3
+ /** Mapping from react-native-vector-icons identifier to corresponding icon resource. */
4
+ export declare const IconSets: Record<string, any>;
5
+ export interface IProps {
6
+ /** The name of the react-native-vector-icons identifier */
4
7
  iconIdentifier: string;
8
+ /** Style of the icon */
5
9
  iconStyle: StyleSheet.NamedStyles<any>;
6
10
  }
11
+ /** Component used to display a react-native-vector-icons */
7
12
  export default class Icon extends React.Component<IProps> {
8
13
  static defaultProps: any;
9
14
  _root: any;
10
15
  setNativeProps(nativeProps: any): void;
16
+ /**
17
+ * @returns JSX Element containing the desired react-native-vector-icons
18
+ */
11
19
  render(): JSX.Element;
12
20
  }
13
- export {};
@@ -1,7 +1,8 @@
1
1
  // @ts-nocheck
2
2
  /* tslint:disable */
3
3
  import React from "react";
4
- const IconSets = {
4
+ /** Mapping from react-native-vector-icons identifier to corresponding icon resource. */
5
+ export const IconSets = {
5
6
  AntDesign: require(`react-native-vector-icons/AntDesign`),
6
7
  Feather: require(`react-native-vector-icons/Feather`),
7
8
  EvilIcons: require(`react-native-vector-icons/EvilIcons`),
@@ -9,10 +10,14 @@ const IconSets = {
9
10
  FontAwesome: require(`react-native-vector-icons/FontAwesome`),
10
11
  Entypo: require(`react-native-vector-icons/Entypo`),
11
12
  };
13
+ /** Component used to display a react-native-vector-icons */
12
14
  export default class Icon extends React.Component {
13
15
  setNativeProps(nativeProps) {
14
16
  this._root.setNativeProps(nativeProps);
15
17
  }
18
+ /**
19
+ * @returns JSX Element containing the desired react-native-vector-icons
20
+ */
16
21
  render() {
17
22
  const iconParts = this.props.iconIdentifier.split(`/`);
18
23
  let iconPackageName = iconParts[0];
@@ -2,20 +2,48 @@ import { BloodGlucoseUnit, BloodKetonesUnit } from "@hedia/types";
2
2
  import React from "react";
3
3
  import { Testing } from "../types/enum";
4
4
  export interface IProps {
5
+ /** The display label that describes the value to the user. */
5
6
  label: string;
7
+ /** The value to display. */
6
8
  value: string | null;
9
+ /** Unit label to print after the value. */
7
10
  unit: string | BloodGlucoseUnit | BloodKetonesUnit | null;
11
+ /** If true then a dash character (“-”) will be printed in place of the value if the value is null. */
8
12
  showNullAsDash: boolean;
13
+ /** optional object that contains as properties a valueID and a unitID */
9
14
  testID?: {
10
15
  valueID: Testing.Id.InfoBarTestIds.Value;
11
16
  unitID: Testing.Id.InfoBarTestIds.Unit;
12
17
  };
13
18
  }
19
+ /** A standard panel to display some data that the user entered. */
14
20
  export default class InfoBars extends React.Component<IProps> {
21
+ /**
22
+ * Determine the value to be displayed in the infobar.
23
+ *
24
+ * Steps:
25
+ * 1. Unpack showNullAsDash, unit, and value from props.
26
+ * 2. Set noDecimal to be true if unit is BloodGlucoseUnit.MG_DL or if unit is BloodKetonesUnit.MG_DL.
27
+ * 3. Set nullPlaceholder to be ‘-' if noDecimal is true and to '-.-’ otherwise.
28
+ * 4. Return value if it is not null or undefined. Otherwise, if showNullAsDash is true then return nullPlaceholder, otherwise return the string '0'.
29
+ * @returns The string to display as the value in the infobar.
30
+ */
15
31
  displayValue: () => string;
32
+ /**
33
+ * Determine the unit string to be displayed in the infobar.
34
+ *
35
+ * Steps:
36
+ * 1. Unpack unit from props.
37
+ * 2. Return unit if unit is “units” or the result of calling formatUnit() with unit as argument otherwise.
38
+ * @returns The string to display as the unit in the infobar
39
+ */
16
40
  displayUnit: () => string | null;
41
+ /**
42
+ * @returns JSX element to display a card with the entered value.
43
+ */
17
44
  render(): JSX.Element;
18
45
  }
46
+ /** @internal */
19
47
  export declare const infoStyles: {
20
48
  container: {
21
49
  flex: number;