@hedia/recommendation-screen 1.2.1 → 1.3.0

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 (37) hide show
  1. package/.idea/workspace.xml +30 -30
  2. package/package.json +1 -1
  3. package/src/RecommendationScreen.d.ts +3 -0
  4. package/src/RecommendationScreen.jsx +50 -41
  5. package/src/RecommendationScreen.tsx +80 -56
  6. package/src/components/InvisibleNumberInput.d.ts +1 -0
  7. package/src/components/InvisibleNumberInput.jsx +1 -1
  8. package/src/components/InvisibleNumberInput.tsx +3 -0
  9. package/src/components/RecommendedCarbs.d.ts +0 -2
  10. package/src/components/RecommendedCarbs.jsx +8 -3
  11. package/src/components/RecommendedCarbs.tsx +10 -5
  12. package/src/components/RecommendedInsulin.d.ts +3 -3
  13. package/src/components/RecommendedInsulin.jsx +18 -6
  14. package/src/components/RecommendedInsulin.tsx +24 -10
  15. package/src/components/activity/ActivityIcon.jsx +1 -1
  16. package/src/components/activity/ActivityIcon.tsx +1 -1
  17. package/src/types/enum.d.ts +9 -10
  18. package/src/types/enum.js +9 -10
  19. package/src/types/enum.ts +0 -1
  20. package/src/types/types.ts +1 -0
  21. package/src/utils/AttentionMessages.d.ts +1 -1
  22. package/src/utils/AttentionMessages.jsx +1 -1
  23. package/src/utils/AttentionMessages.tsx +1 -1
  24. package/src/utils/Constants.d.ts +3 -0
  25. package/src/utils/Constants.js +4 -1
  26. package/src/utils/Constants.ts +5 -0
  27. package/src/utils/RecommendationError.d.ts +0 -1
  28. package/src/utils/RecommendationError.jsx +1 -3
  29. package/src/utils/RecommendationError.tsx +0 -7
  30. package/src/utils/RecommendationUtils.d.ts +2 -3
  31. package/src/utils/RecommendationUtils.js +3 -4
  32. package/src/utils/RecommendationUtils.ts +2 -4
  33. package/src/utils/Utils.d.ts +1 -0
  34. package/src/utils/Utils.js +4 -0
  35. package/src/utils/Utils.ts +4 -0
  36. package/src/utils/Validations.js +15 -11
  37. package/src/utils/Validations.ts +16 -11
@@ -28,9 +28,7 @@
28
28
  </select>
29
29
  </component>
30
30
  <component name="ChangeListManager">
31
- <list default="true" id="bceba75c-4c15-4bdc-9b41-023f63a30830" name="Default Changelist" comment="">
32
- <change beforePath="$PROJECT_DIR$/src/components/InvisibleNumberInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/InvisibleNumberInput.tsx" afterDir="false" />
33
- </list>
31
+ <list default="true" id="bceba75c-4c15-4bdc-9b41-023f63a30830" name="Default Changelist" comment="" />
34
32
  <option name="SHOW_DIALOG" value="false" />
35
33
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
36
34
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -169,7 +167,9 @@
169
167
  <workItem from="1599031274561" duration="12226000" />
170
168
  <workItem from="1599119614705" duration="6081000" />
171
169
  <workItem from="1599205746476" duration="8368000" />
172
- <workItem from="1599465060245" duration="4106000" />
170
+ <workItem from="1599465060245" duration="4905000" />
171
+ <workItem from="1599554723490" duration="10979000" />
172
+ <workItem from="1599637277136" duration="3405000" />
173
173
  </task>
174
174
  <servers />
175
175
  </component>
@@ -229,48 +229,48 @@
229
229
  <state x="0" y="123" width="1792" height="897" key="DiffContextDialog/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597747801467" />
230
230
  <state x="0" y="123" width="1792" height="897" key="DiffContextDialog/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1597836504040" />
231
231
  <state x="1792" y="-314" width="1920" height="865" key="DiffContextDialog/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1598603549140" />
232
- <state width="1276" height="270" key="GridCell.Tab.0.bottom" timestamp="1599230158300">
233
- <screen x="0" y="23" width="1792" height="1097" />
232
+ <state width="918" height="257" key="GridCell.Tab.0.bottom" timestamp="1599641656861">
233
+ <screen x="1792" y="-410" width="1920" height="1057" />
234
234
  </state>
235
235
  <state width="1750" height="261" key="GridCell.Tab.0.bottom/-1920.-66.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1596194051670" />
236
- <state width="1878" height="249" key="GridCell.Tab.0.bottom/0.23.1792.1097@0.23.1792.1097" timestamp="1596482378171" />
236
+ <state width="1678" height="366" key="GridCell.Tab.0.bottom/0.23.1792.1097@0.23.1792.1097" timestamp="1599585643328" />
237
237
  <state width="1750" height="383" key="GridCell.Tab.0.bottom/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597945008184" />
238
- <state width="1678" height="367" key="GridCell.Tab.0.bottom/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599152764316" />
238
+ <state width="1678" height="366" key="GridCell.Tab.0.bottom/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599567565615" />
239
239
  <state width="1276" height="270" key="GridCell.Tab.0.bottom/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1599230158300" />
240
- <state width="1878" height="259" key="GridCell.Tab.0.bottom/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599060151002" />
241
- <state width="1276" height="270" key="GridCell.Tab.0.center" timestamp="1599230158300">
242
- <screen x="0" y="23" width="1792" height="1097" />
240
+ <state width="918" height="257" key="GridCell.Tab.0.bottom/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599641656861" />
241
+ <state width="918" height="257" key="GridCell.Tab.0.center" timestamp="1599641656860">
242
+ <screen x="1792" y="-410" width="1920" height="1057" />
243
243
  </state>
244
244
  <state width="1750" height="261" key="GridCell.Tab.0.center/-1920.-66.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1596194051669" />
245
- <state width="1878" height="249" key="GridCell.Tab.0.center/0.23.1792.1097@0.23.1792.1097" timestamp="1596482378170" />
245
+ <state width="1678" height="366" key="GridCell.Tab.0.center/0.23.1792.1097@0.23.1792.1097" timestamp="1599585643327" />
246
246
  <state width="1750" height="383" key="GridCell.Tab.0.center/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597945008183" />
247
- <state width="1678" height="367" key="GridCell.Tab.0.center/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599152764316" />
247
+ <state width="1678" height="366" key="GridCell.Tab.0.center/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599567565614" />
248
248
  <state width="1276" height="270" key="GridCell.Tab.0.center/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1599230158300" />
249
- <state width="1878" height="259" key="GridCell.Tab.0.center/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599060151001" />
250
- <state width="1276" height="270" key="GridCell.Tab.0.left" timestamp="1599230158299">
251
- <screen x="0" y="23" width="1792" height="1097" />
249
+ <state width="918" height="257" key="GridCell.Tab.0.center/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599641656860" />
250
+ <state width="918" height="257" key="GridCell.Tab.0.left" timestamp="1599641656860">
251
+ <screen x="1792" y="-410" width="1920" height="1057" />
252
252
  </state>
253
253
  <state width="1750" height="261" key="GridCell.Tab.0.left/-1920.-66.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1596194051668" />
254
- <state width="1878" height="249" key="GridCell.Tab.0.left/0.23.1792.1097@0.23.1792.1097" timestamp="1596482378170" />
254
+ <state width="1678" height="366" key="GridCell.Tab.0.left/0.23.1792.1097@0.23.1792.1097" timestamp="1599585643327" />
255
255
  <state width="1750" height="383" key="GridCell.Tab.0.left/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597945008182" />
256
- <state width="1678" height="367" key="GridCell.Tab.0.left/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599152764315" />
256
+ <state width="1678" height="366" key="GridCell.Tab.0.left/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599567565614" />
257
257
  <state width="1276" height="270" key="GridCell.Tab.0.left/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1599230158299" />
258
- <state width="1878" height="259" key="GridCell.Tab.0.left/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599060150995" />
259
- <state width="1276" height="270" key="GridCell.Tab.0.right" timestamp="1599230158300">
260
- <screen x="0" y="23" width="1792" height="1097" />
258
+ <state width="918" height="257" key="GridCell.Tab.0.left/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599641656860" />
259
+ <state width="918" height="257" key="GridCell.Tab.0.right" timestamp="1599641656861">
260
+ <screen x="1792" y="-410" width="1920" height="1057" />
261
261
  </state>
262
262
  <state width="1750" height="261" key="GridCell.Tab.0.right/-1920.-66.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1596194051669" />
263
- <state width="1878" height="249" key="GridCell.Tab.0.right/0.23.1792.1097@0.23.1792.1097" timestamp="1596482378171" />
263
+ <state width="1678" height="366" key="GridCell.Tab.0.right/0.23.1792.1097@0.23.1792.1097" timestamp="1599585643328" />
264
264
  <state width="1750" height="383" key="GridCell.Tab.0.right/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597945008183" />
265
- <state width="1678" height="367" key="GridCell.Tab.0.right/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599152764316" />
265
+ <state width="1678" height="366" key="GridCell.Tab.0.right/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599567565614" />
266
266
  <state width="1276" height="270" key="GridCell.Tab.0.right/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1599230158300" />
267
- <state width="1878" height="259" key="GridCell.Tab.0.right/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599060151002" />
268
- <state x="2773" y="167" key="IDE.errors.dialog" timestamp="1598973647546">
269
- <screen x="1792" y="-195" width="3440" height="1417" />
267
+ <state width="918" height="257" key="GridCell.Tab.0.right/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599641656861" />
268
+ <state x="2340" y="-140" key="IDE.errors.dialog" timestamp="1599637300780">
269
+ <screen x="1792" y="-410" width="1920" height="1057" />
270
270
  </state>
271
271
  <state x="511" y="303" key="IDE.errors.dialog/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597308623997" />
272
272
  <state x="2773" y="167" key="IDE.errors.dialog/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1598973647546" />
273
- <state x="2340" y="-140" key="IDE.errors.dialog/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1596547237176" />
273
+ <state x="2340" y="-140" key="IDE.errors.dialog/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599637300780" />
274
274
  <state x="0" y="23" width="1792" height="1097" key="MergeDialog" timestamp="1597409959598">
275
275
  <screen x="0" y="23" width="1792" height="1097" />
276
276
  </state>
@@ -307,14 +307,14 @@
307
307
  <screen x="1792" y="-410" width="1920" height="1057" />
308
308
  </state>
309
309
  <state x="2477" y="-143" key="refactoring.ChangeSignatureDialog/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599040674381" />
310
- <state x="2178" y="-174" width="718" height="652" key="search.everywhere.popup" timestamp="1599489043631">
310
+ <state x="2178" y="-174" width="718" height="652" key="search.everywhere.popup" timestamp="1599645055979">
311
311
  <screen x="1792" y="-410" width="1920" height="1057" />
312
312
  </state>
313
313
  <state x="360" y="268" width="670" height="676" key="search.everywhere.popup/-1920.-66.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1596101738778" />
314
314
  <state x="360" y="268" width="670" height="676" key="search.everywhere.popup/0.23.1792.1097@0.23.1792.1097" timestamp="1596191050648" />
315
315
  <state x="360" y="268" width="671" height="677" key="search.everywhere.popup/1792.-195.3440.1417/0.23.1792.1097@0.23.1792.1097" timestamp="1597748285464" />
316
- <state x="2484" y="121" width="1287" height="875" key="search.everywhere.popup/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599137557476" />
316
+ <state x="2484" y="121" width="1287" height="875" key="search.everywhere.popup/1792.-195.3440.1417/0.23.1792.1097@1792.-195.3440.1417" timestamp="1599560052196" />
317
317
  <state x="360" y="268" width="671" height="677" key="search.everywhere.popup/1792.-410.1920.1057/0.23.1792.1097@0.23.1792.1097" timestamp="1599216348282" />
318
- <state x="2178" y="-174" width="718" height="652" key="search.everywhere.popup/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599489043631" />
318
+ <state x="2178" y="-174" width="718" height="652" key="search.everywhere.popup/1792.-410.1920.1057/0.23.1792.1097@1792.-410.1920.1057" timestamp="1599645055979" />
319
319
  </component>
320
320
  </project>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hedia/recommendation-screen",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Hedia Recommendation Screen for Bolus and Carbohydrates",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -42,8 +42,11 @@ interface IState {
42
42
  export default class RecommendationScreen extends React.Component<IRecommendationProps, IState> {
43
43
  private readonly timer;
44
44
  private readonly suggestedCarbs;
45
+ private readonly hasError;
45
46
  private scrollView;
46
47
  constructor(props: IRecommendationProps);
48
+ componentWillUnmount(): void;
49
+ recalculateInsulin: (calculatorParams: Calculator.IRecommendationParams) => void;
47
50
  onExit: () => void;
48
51
  updateRemeasureTime: (remeasureTime: number) => void;
49
52
  handleNoRecentInsulin: () => void;
@@ -51,13 +51,20 @@ react_native_1.YellowBox.ignoreWarnings([`Setting a timer`]);
51
51
  class RecommendationScreen extends react_1.default.Component {
52
52
  constructor(props) {
53
53
  super(props);
54
+ this.hasError = false;
55
+ this.recalculateInsulin = (calculatorParams) => {
56
+ const { bolus } = Calculator.calculateRecommendation(RecommendationUtils_1.assignTargetBGL(calculatorParams));
57
+ this.setState({
58
+ insulinRecommendation: Utils_1.Utils.roundValue(bolus, this.props.injectionMethod),
59
+ enteredInsulin: undefined,
60
+ });
61
+ };
54
62
  this.onExit = () => {
55
63
  if (this.state.isRecommendationDisplayed) {
56
64
  this.setState({ exitModal: true }, () => this.props.showBolusBar(!this.state.exitModal));
57
65
  }
58
66
  else {
59
67
  this.props.exitCallback();
60
- clearTimeout(this.timer);
61
68
  }
62
69
  };
63
70
  this.updateRemeasureTime = (remeasureTime) => {
@@ -71,10 +78,11 @@ class RecommendationScreen extends react_1.default.Component {
71
78
  });
72
79
  };
73
80
  this.updateCarbRecommendation = (enteredCarbs) => {
74
- this.setState({ enteredCarbs });
81
+ const providedCarbs = this.props.calculatorParams.carbohydrates;
82
+ this.setState({ enteredCarbs }, () => this.recalculateInsulin({ ...this.props.calculatorParams, carbohydrates: providedCarbs + enteredCarbs }));
75
83
  };
76
84
  this.removeCarbRecommendation = () => {
77
- this.setState({ enteredCarbs: null, carbRecommendation: null });
85
+ this.setState({ enteredCarbs: null, carbRecommendation: null }, () => this.recalculateInsulin({ ...this.props.calculatorParams }));
78
86
  };
79
87
  this.declineCarbRecommendation = () => {
80
88
  this.hideAttentionModal();
@@ -93,7 +101,6 @@ class RecommendationScreen extends react_1.default.Component {
93
101
  };
94
102
  this.closeCalculation = () => {
95
103
  this.hideExitModal();
96
- clearTimeout(this.timer);
97
104
  this.props.closeCalculationCallback();
98
105
  };
99
106
  this.handleMoodSelected = (selectedMood) => {
@@ -106,14 +113,9 @@ class RecommendationScreen extends react_1.default.Component {
106
113
  if (this.state.exitModal) {
107
114
  this.hideExitModal();
108
115
  }
109
- this.props.transferToLogbook({
110
- suggested: this.suggestedCarbs,
111
- entered: this.state.enteredCarbs,
112
- }, {
113
- suggested: this.state.insulinRecommendation,
114
- entered: this.state.enteredInsulin,
115
- }, this.state.remeasureTime);
116
- clearTimeout(this.timer);
116
+ const carbs = { suggested: this.suggestedCarbs, entered: this.state.enteredCarbs };
117
+ const insulin = { suggested: this.state.insulinRecommendation, entered: this.state.enteredInsulin };
118
+ this.props.transferToLogbook(carbs, insulin, this.state.remeasureTime);
117
119
  };
118
120
  this.getBGLevelAttentionMessage = () => {
119
121
  const { calculatorParams, latestLogbookFrom6Hours } = this.props;
@@ -132,42 +134,49 @@ class RecommendationScreen extends react_1.default.Component {
132
134
  return RecommendationUtils_1.getLimitationMessage(wasLimited, activityReduction);
133
135
  };
134
136
  try {
135
- Validations_1.validateParams(props);
137
+ Validations_1.validateParams(this.props);
138
+ i18nUtils_1.changeLanguage(props.language);
139
+ const { recentBoluses } = this.props?.calculatorParams;
140
+ const { bolus, carbRecommendation, activityReduction, wasLimited, activeInsulin, } = Calculator.calculateRecommendation(RecommendationUtils_1.assignTargetBGL(this.props.calculatorParams));
141
+ this.suggestedCarbs = carbRecommendation;
142
+ this.state = {
143
+ remeasureTime: this.getBGLevelRemeasurementReminder(),
144
+ isRecommendationDisplayed: recentBoluses?.length !== 0,
145
+ insulinRecommendation: Utils_1.Utils.roundValue(bolus, props.injectionMethod),
146
+ wasLimited,
147
+ activityReduction,
148
+ bolus,
149
+ carbRecommendation,
150
+ activeInsulin,
151
+ selectedMood: null,
152
+ recommendationModal: wasLimited || !!Math.round(carbRecommendation) || !!this.getBGLevelAttentionMessage(),
153
+ exitModal: false,
154
+ };
155
+ this.timer = setTimeout(() => {
156
+ props.onError(RecommendationError_1.TimeoutLimitError());
157
+ }, enum_1.Milliseconds.Minute * 15);
136
158
  }
137
159
  catch (error) {
138
- props.onError(error);
160
+ this.hasError = true;
161
+ this.props.onError(error);
139
162
  }
140
- i18nUtils_1.changeLanguage(props.language);
141
- const { recentBoluses } = props?.calculatorParams;
142
- const { bolus, carbRecommendation, activityReduction, wasLimited } = Calculator.calculateRecommendation(RecommendationUtils_1.getParams(this.props));
143
- this.suggestedCarbs = carbRecommendation;
144
- const activeInsulin = Calculator.calculateActiveInsulin(recentBoluses ?? []);
145
- this.state = {
146
- remeasureTime: this.getBGLevelRemeasurementReminder(),
147
- isRecommendationDisplayed: recentBoluses?.length !== 0,
148
- insulinRecommendation: Utils_1.Utils.roundValue(bolus, props.injectionMethod),
149
- wasLimited,
150
- activityReduction,
151
- bolus,
152
- carbRecommendation,
153
- activeInsulin,
154
- selectedMood: null,
155
- recommendationModal: wasLimited || !!Math.round(carbRecommendation) || !!this.getBGLevelAttentionMessage(),
156
- exitModal: false,
157
- };
158
- this.timer = setTimeout(() => {
159
- props.onError(RecommendationError_1.TimeoutLimitError());
160
- }, enum_1.Milliseconds.Minute * 15);
163
+ }
164
+ componentWillUnmount() {
165
+ clearTimeout(this.timer);
161
166
  }
162
167
  render() {
163
- const { activeInsulin, recommendationModal, carbRecommendation, enteredCarbs } = this.state;
164
- const { calculatorParams } = this.props;
168
+ if (this.hasError) {
169
+ return <react_native_1.View style={containerStyles.container}/>;
170
+ }
171
+ const { activeInsulin, recommendationModal, carbRecommendation, enteredCarbs, enteredInsulin, insulinRecommendation, activityReduction, isRecommendationDisplayed, } = this.state;
172
+ const { calculatorParams, units } = this.props;
165
173
  const { currentBGL, carbohydrates } = calculatorParams;
174
+ const displayedBGL = units === enum_1.BGUnit.MMOL_L ? currentBGL : Utils_1.Utils.convertToMGDL(currentBGL);
166
175
  return (<react_2.I18nProvider language={this.props.language} i18n={i18nUtils_1.i18n}>
167
176
  <react_native_1.ScrollView style={containerStyles.container} ref={(view) => (this.scrollView = view)}>
168
177
  <Header_1.default exitCallback={this.onExit}/>
169
178
  <InfoBars_1.default style={{ flex: 5 }} label={i18nUtils_1.i18n._(macro_1.t `Active Insulin`)} value={activeInsulin ? `${activeInsulin.toFixed(1)}` : null} units={i18nUtils_1.i18n._(macro_1.t `units`)} showZeroAsDash={false}/>
170
- <InfoBars_1.default label={i18nUtils_1.i18n._(macro_1.t `Blood Glucose Level`)} value={currentBGL ? `${currentBGL}` : null} units={this.props.units} showZeroAsDash={true}/>
179
+ <InfoBars_1.default label={i18nUtils_1.i18n._(macro_1.t `Blood Glucose Level`)} value={currentBGL ? `${displayedBGL}` : null} units={this.props.units} showZeroAsDash={true}/>
171
180
  <react_native_1.View style={containerStyles.calcContainer}>
172
181
  <react_native_1.View style={containerStyles.calcMargin}>
173
182
  <react_native_1.View style={[
@@ -176,15 +185,15 @@ class RecommendationScreen extends react_1.default.Component {
176
185
  borderColor: carbRecommendation ? Constants_1.BORDER_COLOUR_TEAL : Constants_1.BORDER_COLOUR_GREY,
177
186
  },
178
187
  ]}>
179
- <RecommendedCarbs_1.default enteredCarbs={`${carbohydrates}`} changedRecommendedCarbs={this.updateCarbRecommendation} recommendedCarbs={`${enteredCarbs ?? Math.round(carbRecommendation)}`} removeRecommendedCarbs={this.removeCarbRecommendation} onError={this.props.onError}/>
188
+ <RecommendedCarbs_1.default enteredCarbs={`${carbohydrates}`} changedRecommendedCarbs={this.updateCarbRecommendation} recommendedCarbs={`${enteredCarbs ?? Math.round(carbRecommendation)}`} removeRecommendedCarbs={this.removeCarbRecommendation}/>
180
189
  <Remeasure_1.default onSliderChange={this.updateRemeasureTime} remeasureTime={this.state.remeasureTime}/>
181
190
  </react_native_1.View>
182
191
  </react_native_1.View>
183
192
  </react_native_1.View>
184
193
  {this.props.calculatorParams.activity && this.props.activityType !== null ? (<Activity_1.default activity={this.props.calculatorParams.activity} activityType={this.props.activityType} activityReduction={this.state.activityReduction}/>) : null}
185
- {!this.state.isRecommendationDisplayed ? (<RecentInsulin_1.default onRecentInsulinYes={this.props.onRecentInsulinYes} onRecentInsulinNo={this.handleNoRecentInsulin}/>) : (<RecommendedInsulin_1.default injectionMethod={this.props.injectionMethod} insulinRecommendation={this.state.enteredInsulin ?? this.state.insulinRecommendation} activityReduction={this.state.activityReduction} updateRecommendedInsulin={this.updateInsulinRecommendation} onError={this.props.onError}/>)}
194
+ {!this.state.isRecommendationDisplayed ? (<RecentInsulin_1.default onRecentInsulinYes={this.props.onRecentInsulinYes} onRecentInsulinNo={this.handleNoRecentInsulin}/>) : (<RecommendedInsulin_1.default injectionMethod={this.props.injectionMethod} insulinRecommendation={insulinRecommendation} enteredInsulin={enteredInsulin} activityReduction={activityReduction} updateRecommendedInsulin={this.updateInsulinRecommendation}/>)}
186
195
  <Emotion_1.default moodSelected={this.handleMoodSelected} currentMood={this.state.selectedMood}/>
187
- <TransferToLogbook_1.default visible={this.state.isRecommendationDisplayed} transfer={this.handleTransfer}/>
196
+ <TransferToLogbook_1.default visible={isRecommendationDisplayed} transfer={this.handleTransfer}/>
188
197
  <RecommendationModal_1.default isVisible={recommendationModal} suggestedCarbohydrates={carbRecommendation} attentionMessage={this.getBGLevelAttentionMessage()} limitationMessage={this.getLimitationAttentionMessage()} onClickOkButton={this.hideAttentionModal} onAcceptCarbohydrates={this.acceptCarbRecommendation} onDeclineCarbohydrates={this.declineCarbRecommendation}/>
189
198
  </react_native_1.ScrollView>
190
199
  {this.state.exitModal ? (<ExitModal_1.default onSave={this.handleTransfer} onCloseCalculation={this.closeCalculation} onClose={this.hideExitModal}/>) : null}
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { ScrollView, StyleSheet, View, YellowBox } from "react-native";
3
+
3
4
  import { ActivityEnum, BGUnit, InjectionMethod, Languages, Milliseconds, MoodEnum } from "./types/enum";
4
5
  import { BACKGROUND_COLOUR_PURPLE, BORDER_COLOUR_GREY, BORDER_COLOUR_TEAL } from "./utils/Constants";
5
6
 
@@ -24,10 +25,10 @@ import { changeLanguage, i18n } from "./locale/i18nUtils";
24
25
  import { IActivity, logbookEntry } from "./types/types";
25
26
  import { AttentionMessage } from "./utils/AttentionMessages";
26
27
  import {
28
+ assignTargetBGL,
27
29
  getAttentionMessage,
28
30
  getBGLevel,
29
31
  getLimitationMessage,
30
- getParams,
31
32
  getReminder,
32
33
  } from "./utils/RecommendationUtils";
33
34
  import { Utils } from "./utils/Utils";
@@ -81,52 +82,68 @@ interface IState {
81
82
  export default class RecommendationScreen extends React.Component<IRecommendationProps, IState> {
82
83
  private readonly timer: ReturnType<typeof setTimeout>;
83
84
  private readonly suggestedCarbs: number;
85
+ private readonly hasError: boolean = false;
84
86
  private scrollView: ScrollView;
85
87
 
86
88
  constructor(props: IRecommendationProps) {
87
89
  super(props);
88
90
  try {
89
- validateParams(props);
91
+ validateParams(this.props);
92
+
93
+ changeLanguage(props.language);
94
+
95
+ const { recentBoluses } = this.props?.calculatorParams;
96
+ const {
97
+ bolus,
98
+ carbRecommendation,
99
+ activityReduction,
100
+ wasLimited,
101
+ activeInsulin,
102
+ } = Calculator.calculateRecommendation(assignTargetBGL(this.props.calculatorParams));
103
+
104
+ this.suggestedCarbs = carbRecommendation;
105
+
106
+ this.state = {
107
+ remeasureTime: this.getBGLevelRemeasurementReminder(),
108
+ isRecommendationDisplayed: recentBoluses?.length !== 0,
109
+ insulinRecommendation: Utils.roundValue(bolus, props.injectionMethod),
110
+ wasLimited,
111
+ activityReduction,
112
+ bolus,
113
+ carbRecommendation,
114
+ activeInsulin,
115
+ selectedMood: null,
116
+ recommendationModal:
117
+ wasLimited || !!Math.round(carbRecommendation) || !!this.getBGLevelAttentionMessage(),
118
+ exitModal: false,
119
+ };
120
+
121
+ this.timer = setTimeout((): void => {
122
+ props.onError(TimeoutLimitError());
123
+ }, Milliseconds.Minute * 15);
90
124
  } catch (error) {
91
- props.onError(error);
125
+ this.hasError = true;
126
+ this.props.onError(error);
92
127
  }
128
+ }
93
129
 
94
- changeLanguage(props.language);
95
-
96
- const { recentBoluses } = props?.calculatorParams;
97
- const { bolus, carbRecommendation, activityReduction, wasLimited } = Calculator.calculateRecommendation(
98
- getParams(this.props),
99
- );
100
-
101
- this.suggestedCarbs = carbRecommendation;
102
-
103
- const activeInsulin = Calculator.calculateActiveInsulin(recentBoluses ?? []);
104
-
105
- this.state = {
106
- remeasureTime: this.getBGLevelRemeasurementReminder(),
107
- isRecommendationDisplayed: recentBoluses?.length !== 0,
108
- insulinRecommendation: Utils.roundValue(bolus, props.injectionMethod),
109
- wasLimited,
110
- activityReduction,
111
- bolus,
112
- carbRecommendation,
113
- activeInsulin,
114
- selectedMood: null,
115
- recommendationModal: wasLimited || !!Math.round(carbRecommendation) || !!this.getBGLevelAttentionMessage(),
116
- exitModal: false,
117
- };
118
-
119
- this.timer = setTimeout((): void => {
120
- props.onError(TimeoutLimitError());
121
- }, Milliseconds.Minute * 15);
130
+ public componentWillUnmount(): void {
131
+ clearTimeout(this.timer);
122
132
  }
123
133
 
134
+ public recalculateInsulin = (calculatorParams: Calculator.IRecommendationParams): void => {
135
+ const { bolus } = Calculator.calculateRecommendation(assignTargetBGL(calculatorParams));
136
+ this.setState({
137
+ insulinRecommendation: Utils.roundValue(bolus, this.props.injectionMethod),
138
+ enteredInsulin: undefined,
139
+ });
140
+ };
141
+
124
142
  public onExit = (): void => {
125
143
  if (this.state.isRecommendationDisplayed) {
126
144
  this.setState({ exitModal: true }, (): void => this.props.showBolusBar(!this.state.exitModal));
127
145
  } else {
128
146
  this.props.exitCallback();
129
- clearTimeout(this.timer);
130
147
  }
131
148
  };
132
149
 
@@ -143,11 +160,16 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
143
160
  };
144
161
 
145
162
  public updateCarbRecommendation = (enteredCarbs: number): void => {
146
- this.setState({ enteredCarbs });
163
+ const providedCarbs = this.props.calculatorParams.carbohydrates;
164
+ this.setState({ enteredCarbs }, (): void =>
165
+ this.recalculateInsulin({ ...this.props.calculatorParams, carbohydrates: providedCarbs + enteredCarbs }),
166
+ );
147
167
  };
148
168
 
149
169
  public removeCarbRecommendation = (): void => {
150
- this.setState({ enteredCarbs: null, carbRecommendation: null });
170
+ this.setState({ enteredCarbs: null, carbRecommendation: null }, (): void =>
171
+ this.recalculateInsulin({ ...this.props.calculatorParams }),
172
+ );
151
173
  };
152
174
 
153
175
  public declineCarbRecommendation = (): void => {
@@ -168,7 +190,6 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
168
190
  };
169
191
  public closeCalculation = (): void => {
170
192
  this.hideExitModal();
171
- clearTimeout(this.timer);
172
193
  this.props.closeCalculationCallback();
173
194
  };
174
195
 
@@ -184,19 +205,9 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
184
205
  if (this.state.exitModal) {
185
206
  this.hideExitModal();
186
207
  }
187
- this.props.transferToLogbook(
188
- {
189
- suggested: this.suggestedCarbs,
190
- entered: this.state.enteredCarbs,
191
- },
192
- {
193
- suggested: this.state.insulinRecommendation,
194
- entered: this.state.enteredInsulin,
195
- },
196
- this.state.remeasureTime,
197
- );
198
-
199
- clearTimeout(this.timer);
208
+ const carbs: IResult = { suggested: this.suggestedCarbs, entered: this.state.enteredCarbs };
209
+ const insulin: IResult = { suggested: this.state.insulinRecommendation, entered: this.state.enteredInsulin };
210
+ this.props.transferToLogbook(carbs, insulin, this.state.remeasureTime);
200
211
  };
201
212
 
202
213
  public getBGLevelAttentionMessage = (): AttentionMessage => {
@@ -218,9 +229,23 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
218
229
  };
219
230
 
220
231
  public render(): JSX.Element {
221
- const { activeInsulin, recommendationModal, carbRecommendation, enteredCarbs } = this.state;
222
- const { calculatorParams } = this.props;
232
+ if (this.hasError) {
233
+ return <View style={containerStyles.container} />;
234
+ }
235
+
236
+ const {
237
+ activeInsulin,
238
+ recommendationModal,
239
+ carbRecommendation,
240
+ enteredCarbs,
241
+ enteredInsulin,
242
+ insulinRecommendation,
243
+ activityReduction,
244
+ isRecommendationDisplayed,
245
+ } = this.state;
246
+ const { calculatorParams, units } = this.props;
223
247
  const { currentBGL, carbohydrates } = calculatorParams;
248
+ const displayedBGL = units === BGUnit.MMOL_L ? currentBGL : Utils.convertToMGDL(currentBGL);
224
249
 
225
250
  return (
226
251
  <I18nProvider language={this.props.language} i18n={i18n}>
@@ -235,7 +260,7 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
235
260
  />
236
261
  <InfoBars
237
262
  label={i18n._(t`Blood Glucose Level`)}
238
- value={currentBGL ? `${currentBGL}` : null}
263
+ value={currentBGL ? `${displayedBGL}` : null}
239
264
  units={this.props.units}
240
265
  showZeroAsDash={true}
241
266
  />
@@ -254,7 +279,6 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
254
279
  changedRecommendedCarbs={this.updateCarbRecommendation}
255
280
  recommendedCarbs={`${enteredCarbs ?? Math.round(carbRecommendation)}`}
256
281
  removeRecommendedCarbs={this.removeCarbRecommendation}
257
- onError={this.props.onError}
258
282
  />
259
283
  <Remeasure
260
284
  onSliderChange={this.updateRemeasureTime}
@@ -278,14 +302,14 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
278
302
  ) : (
279
303
  <RecommendedInsulin
280
304
  injectionMethod={this.props.injectionMethod}
281
- insulinRecommendation={this.state.enteredInsulin ?? this.state.insulinRecommendation}
282
- activityReduction={this.state.activityReduction}
305
+ insulinRecommendation={insulinRecommendation}
306
+ enteredInsulin={enteredInsulin}
307
+ activityReduction={activityReduction}
283
308
  updateRecommendedInsulin={this.updateInsulinRecommendation}
284
- onError={this.props.onError}
285
309
  />
286
310
  )}
287
311
  <Emotion moodSelected={this.handleMoodSelected} currentMood={this.state.selectedMood} />
288
- <TransferToLogbook visible={this.state.isRecommendationDisplayed} transfer={this.handleTransfer} />
312
+ <TransferToLogbook visible={isRecommendationDisplayed} transfer={this.handleTransfer} />
289
313
  <RecommendationModal
290
314
  isVisible={recommendationModal}
291
315
  suggestedCarbohydrates={carbRecommendation}
@@ -5,6 +5,7 @@ interface IProps {
5
5
  decimalPlaces: number;
6
6
  cleanPartialInput: boolean;
7
7
  negativeAllowed: boolean;
8
+ maxLength?: number;
8
9
  visible(toggle: () => void): void;
9
10
  onEnd?(value: number): void;
10
11
  partialInput?(value: string): void;
@@ -51,7 +51,7 @@ class InvisibleNumberInput extends react_1.default.Component {
51
51
  });
52
52
  }
53
53
  render() {
54
- return (<react_native_1.TextInput accessibilityLabel="InvisibleNumberInput" value={`${this.state.value}`} ref={(textInput) => (this.textInput = textInput)} style={inputStyles.textInput} keyboardType="numeric" onChangeText={this.handleOnChangeText} onEndEditing={this.onEndEdit}/>);
54
+ return (<react_native_1.TextInput accessibilityLabel="InvisibleNumberInput" value={`${this.state.value}`} ref={(textInput) => (this.textInput = textInput)} style={inputStyles.textInput} keyboardType="numeric" onChangeText={this.handleOnChangeText} onEndEditing={this.onEndEdit} maxLength={this.props.maxLength} selectTextOnFocus/>);
55
55
  }
56
56
  }
57
57
  exports.default = InvisibleNumberInput;
@@ -6,6 +6,7 @@ interface IProps {
6
6
  decimalPlaces: number;
7
7
  cleanPartialInput: boolean;
8
8
  negativeAllowed: boolean;
9
+ maxLength?: number;
9
10
  visible(toggle: () => void): void;
10
11
  onEnd?(value: number): void;
11
12
  partialInput?(value: string): void;
@@ -74,6 +75,8 @@ export default class InvisibleNumberInput extends React.Component<IProps, IState
74
75
  keyboardType="numeric"
75
76
  onChangeText={this.handleOnChangeText}
76
77
  onEndEditing={this.onEndEdit}
78
+ maxLength={this.props.maxLength}
79
+ selectTextOnFocus
77
80
  />
78
81
  );
79
82
  }
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import { RecommendationError } from "../utils/RecommendationError";
3
2
  interface ICalculationRow {
4
3
  label: string;
5
4
  info: string;
@@ -11,7 +10,6 @@ interface IProps {
11
10
  enteredCarbs: string;
12
11
  removeRecommendedCarbs(): void;
13
12
  changedRecommendedCarbs(value: number): void;
14
- onError(error: RecommendationError): void;
15
13
  }
16
14
  interface IState {
17
15
  partialInput: string;
@@ -29,14 +29,19 @@ class RecommendedCarbs extends react_1.default.Component {
29
29
  this.handleChangedCarbs = (carbs) => {
30
30
  if (carbs >= 0) {
31
31
  if (carbs > 300) {
32
- return this.props.onError(RecommendationError_1.CarbohydrateLimitError());
32
+ this.setState({ partialInput: this.props.recommendedCarbs });
33
+ return react_native_1.Alert.alert(i18nUtils_1.i18n._(`Attention`), RecommendationError_1.CarbohydrateLimitError().message, [
34
+ {
35
+ text: i18nUtils_1.i18n._(`OK`),
36
+ },
37
+ ]);
33
38
  }
34
39
  this.props.changedRecommendedCarbs(carbs);
35
40
  }
36
41
  };
37
42
  this.renderRecommendedCarbs = () => {
38
43
  const shownCarbs = this.state.partialInput ?? Math.round(Number(this.props.recommendedCarbs));
39
- const totalCarbs = Math.round(parseFloat(this.props.enteredCarbs) + parseFloat(this.props.recommendedCarbs));
44
+ const totalCarbs = Math.round(parseFloat(this.props.enteredCarbs) + Number(shownCarbs));
40
45
  return (<react_1.default.Fragment>
41
46
  <react_native_1.View style={calculationStyles.borderContainer}>
42
47
  <react_native_1.View style={calculationStyles.recommendedContainer}>
@@ -72,7 +77,7 @@ class RecommendedCarbs extends react_1.default.Component {
72
77
  value: totalCarbs.toString(),
73
78
  units: i18nUtils_1.i18n._(macro_1.t `g carbs`),
74
79
  })}
75
- <InvisibleNumberInput_1.default negativeAllowed={false} cleanPartialInput={true} decimalPlaces={0} visible={(callback) => (this.callbackInput = callback)} partialInput={this.handlePartialInput} onEnd={this.handleChangedCarbs} startValue={this.props.recommendedCarbs}/>
80
+ <InvisibleNumberInput_1.default negativeAllowed={false} cleanPartialInput={true} decimalPlaces={0} visible={(callback) => (this.callbackInput = callback)} partialInput={this.handlePartialInput} onEnd={this.handleChangedCarbs} startValue={this.props.recommendedCarbs} maxLength={3}/>
76
81
  </react_1.default.Fragment>);
77
82
  };
78
83
  this.renderRow = (row) => {