@hedia/recommendation-screen 1.2.0 → 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.
- package/.idea/workspace.xml +60 -98
- package/package.json +1 -1
- package/src/RecommendationScreen.d.ts +3 -0
- package/src/RecommendationScreen.jsx +51 -42
- package/src/RecommendationScreen.tsx +82 -57
- package/src/components/InfoBars.d.ts +2 -0
- package/src/components/InfoBars.jsx +4 -4
- package/src/components/InfoBars.tsx +6 -6
- package/src/components/InvisibleNumberInput.d.ts +1 -0
- package/src/components/InvisibleNumberInput.jsx +1 -1
- package/src/components/InvisibleNumberInput.tsx +3 -0
- package/src/components/RecommendedCarbs.d.ts +0 -2
- package/src/components/RecommendedCarbs.jsx +8 -3
- package/src/components/RecommendedCarbs.tsx +10 -5
- package/src/components/RecommendedInsulin.d.ts +3 -3
- package/src/components/RecommendedInsulin.jsx +18 -6
- package/src/components/RecommendedInsulin.tsx +24 -10
- package/src/components/activity/ActivityIcon.jsx +1 -1
- package/src/components/activity/ActivityIcon.tsx +1 -1
- package/src/types/enum.d.ts +9 -10
- package/src/types/enum.js +9 -10
- package/src/types/enum.ts +0 -1
- package/src/types/types.ts +1 -0
- package/src/utils/AttentionMessages.d.ts +1 -1
- package/src/utils/AttentionMessages.jsx +1 -1
- package/src/utils/AttentionMessages.tsx +1 -1
- package/src/utils/Constants.d.ts +3 -0
- package/src/utils/Constants.js +4 -1
- package/src/utils/Constants.ts +5 -0
- package/src/utils/RecommendationError.d.ts +0 -1
- package/src/utils/RecommendationError.jsx +1 -3
- package/src/utils/RecommendationError.tsx +0 -7
- package/src/utils/RecommendationUtils.d.ts +2 -3
- package/src/utils/RecommendationUtils.js +3 -4
- package/src/utils/RecommendationUtils.ts +2 -4
- package/src/utils/Utils.d.ts +1 -0
- package/src/utils/Utils.js +4 -0
- package/src/utils/Utils.ts +4 -0
- package/src/utils/Validations.js +15 -11
- package/src/utils/Validations.ts +16 -11
|
@@ -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";
|
|
@@ -79,54 +80,70 @@ interface IState {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
export default class RecommendationScreen extends React.Component<IRecommendationProps, IState> {
|
|
82
|
-
private readonly timer:
|
|
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
|
-
|
|
125
|
+
this.hasError = true;
|
|
126
|
+
this.props.onError(error);
|
|
92
127
|
}
|
|
128
|
+
}
|
|
93
129
|
|
|
94
|
-
|
|
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.
|
|
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.
|
|
188
|
-
|
|
189
|
-
|
|
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,15 +229,30 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
|
|
|
218
229
|
};
|
|
219
230
|
|
|
220
231
|
public render(): JSX.Element {
|
|
221
|
-
|
|
222
|
-
|
|
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}>
|
|
227
252
|
<ScrollView style={containerStyles.container} ref={(view): ScrollView => (this.scrollView = view)}>
|
|
228
253
|
<Header exitCallback={this.onExit} />
|
|
229
254
|
<InfoBars
|
|
255
|
+
style={{ flex: 5 }}
|
|
230
256
|
label={i18n._(t`Active Insulin`)}
|
|
231
257
|
value={activeInsulin ? `${activeInsulin.toFixed(1)}` : null}
|
|
232
258
|
units={i18n._(t`units`)}
|
|
@@ -234,7 +260,7 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
|
|
|
234
260
|
/>
|
|
235
261
|
<InfoBars
|
|
236
262
|
label={i18n._(t`Blood Glucose Level`)}
|
|
237
|
-
value={currentBGL ? `${
|
|
263
|
+
value={currentBGL ? `${displayedBGL}` : null}
|
|
238
264
|
units={this.props.units}
|
|
239
265
|
showZeroAsDash={true}
|
|
240
266
|
/>
|
|
@@ -253,7 +279,6 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
|
|
|
253
279
|
changedRecommendedCarbs={this.updateCarbRecommendation}
|
|
254
280
|
recommendedCarbs={`${enteredCarbs ?? Math.round(carbRecommendation)}`}
|
|
255
281
|
removeRecommendedCarbs={this.removeCarbRecommendation}
|
|
256
|
-
onError={this.props.onError}
|
|
257
282
|
/>
|
|
258
283
|
<Remeasure
|
|
259
284
|
onSliderChange={this.updateRemeasureTime}
|
|
@@ -277,14 +302,14 @@ export default class RecommendationScreen extends React.Component<IRecommendatio
|
|
|
277
302
|
) : (
|
|
278
303
|
<RecommendedInsulin
|
|
279
304
|
injectionMethod={this.props.injectionMethod}
|
|
280
|
-
insulinRecommendation={
|
|
281
|
-
|
|
305
|
+
insulinRecommendation={insulinRecommendation}
|
|
306
|
+
enteredInsulin={enteredInsulin}
|
|
307
|
+
activityReduction={activityReduction}
|
|
282
308
|
updateRecommendedInsulin={this.updateInsulinRecommendation}
|
|
283
|
-
onError={this.props.onError}
|
|
284
309
|
/>
|
|
285
310
|
)}
|
|
286
311
|
<Emotion moodSelected={this.handleMoodSelected} currentMood={this.state.selectedMood} />
|
|
287
|
-
<TransferToLogbook visible={
|
|
312
|
+
<TransferToLogbook visible={isRecommendationDisplayed} transfer={this.handleTransfer} />
|
|
288
313
|
<RecommendationModal
|
|
289
314
|
isVisible={recommendationModal}
|
|
290
315
|
suggestedCarbohydrates={carbRecommendation}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
2
3
|
export interface IProps {
|
|
3
4
|
label: string;
|
|
4
5
|
value?: string;
|
|
5
6
|
units: string;
|
|
6
7
|
showZeroAsDash: boolean;
|
|
8
|
+
style?: StyleProp<ViewStyle>;
|
|
7
9
|
}
|
|
8
10
|
export default class InfoBars extends React.Component<IProps> {
|
|
9
11
|
render(): JSX.Element;
|
|
@@ -18,8 +18,8 @@ class InfoBars extends react_1.default.Component {
|
|
|
18
18
|
<react_native_1.View style={exports.infoStyles.labelContainer}>
|
|
19
19
|
<react_native_1.Text style={exports.infoStyles.label}>{this.props.label}</react_native_1.Text>
|
|
20
20
|
</react_native_1.View>
|
|
21
|
-
<react_native_1.View style={exports.infoStyles.valueUnitContainer}>
|
|
22
|
-
<react_native_1.View style={exports.infoStyles.valueContainer}>
|
|
21
|
+
<react_native_1.View style={[{ ...exports.infoStyles.valueUnitContainer }, this.props.style]}>
|
|
22
|
+
<react_native_1.View style={[{ ...exports.infoStyles.valueContainer }, this.props.style]}>
|
|
23
23
|
<react_native_1.Text style={exports.infoStyles.value}>{displayedValue}</react_native_1.Text>
|
|
24
24
|
</react_native_1.View>
|
|
25
25
|
<react_native_1.View style={exports.infoStyles.unitContainer}>
|
|
@@ -67,7 +67,7 @@ exports.infoStyles = react_native_1.StyleSheet.create({
|
|
|
67
67
|
flexDirection: `row`,
|
|
68
68
|
},
|
|
69
69
|
valueContainer: {
|
|
70
|
-
flex:
|
|
70
|
+
flex: 4,
|
|
71
71
|
justifyContent: `flex-end`,
|
|
72
72
|
},
|
|
73
73
|
value: {
|
|
@@ -77,7 +77,7 @@ exports.infoStyles = react_native_1.StyleSheet.create({
|
|
|
77
77
|
textAlign: `right`,
|
|
78
78
|
},
|
|
79
79
|
unitContainer: {
|
|
80
|
-
flex:
|
|
80
|
+
flex: 4,
|
|
81
81
|
justifyContent: `flex-end`,
|
|
82
82
|
paddingBottom: `3%`,
|
|
83
83
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Dimensions, StyleSheet, Text, View } from "react-native";
|
|
2
|
+
import { Dimensions, StyleProp, StyleSheet, Text, View, ViewStyle } from "react-native";
|
|
3
3
|
import { BORDER_COLOUR_GREY } from "../utils/Constants";
|
|
4
4
|
import { headerStyles } from "./Header";
|
|
5
5
|
|
|
@@ -8,12 +8,12 @@ export interface IProps {
|
|
|
8
8
|
value?: string;
|
|
9
9
|
units: string;
|
|
10
10
|
showZeroAsDash: boolean;
|
|
11
|
+
style?: StyleProp<ViewStyle>;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export default class InfoBars extends React.Component<IProps> {
|
|
14
15
|
public render(): JSX.Element {
|
|
15
16
|
const displayedValue = this.props.value ?? (this.props.showZeroAsDash ? `-.-` : `0`);
|
|
16
|
-
|
|
17
17
|
return (
|
|
18
18
|
<View style={infoStyles.container}>
|
|
19
19
|
<View style={infoStyles.margin}>
|
|
@@ -22,8 +22,8 @@ export default class InfoBars extends React.Component<IProps> {
|
|
|
22
22
|
<View style={infoStyles.labelContainer}>
|
|
23
23
|
<Text style={infoStyles.label}>{this.props.label}</Text>
|
|
24
24
|
</View>
|
|
25
|
-
<View style={infoStyles.valueUnitContainer}>
|
|
26
|
-
<View style={infoStyles.valueContainer}>
|
|
25
|
+
<View style={[{ ...infoStyles.valueUnitContainer }, this.props.style]}>
|
|
26
|
+
<View style={[{ ...infoStyles.valueContainer }, this.props.style]}>
|
|
27
27
|
<Text style={infoStyles.value}>{displayedValue}</Text>
|
|
28
28
|
</View>
|
|
29
29
|
<View style={infoStyles.unitContainer}>
|
|
@@ -72,7 +72,7 @@ export const infoStyles = StyleSheet.create({
|
|
|
72
72
|
flexDirection: `row`,
|
|
73
73
|
},
|
|
74
74
|
valueContainer: {
|
|
75
|
-
flex:
|
|
75
|
+
flex: 4,
|
|
76
76
|
justifyContent: `flex-end`,
|
|
77
77
|
},
|
|
78
78
|
value: {
|
|
@@ -82,7 +82,7 @@ export const infoStyles = StyleSheet.create({
|
|
|
82
82
|
textAlign: `right`,
|
|
83
83
|
},
|
|
84
84
|
unitContainer: {
|
|
85
|
-
flex:
|
|
85
|
+
flex: 4,
|
|
86
86
|
justifyContent: `flex-end`,
|
|
87
87
|
paddingBottom: `3%`,
|
|
88
88
|
},
|
|
@@ -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
|
-
|
|
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) +
|
|
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) => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t } from "@lingui/macro";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { Dimensions, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
3
|
+
import { Alert, Dimensions, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
4
4
|
import { i18n } from "../locale/i18nUtils";
|
|
5
5
|
import { BORDER_COLOUR_TEAL } from "../utils/Constants";
|
|
6
|
-
import { CarbohydrateLimitError
|
|
6
|
+
import { CarbohydrateLimitError } from "../utils/RecommendationError";
|
|
7
7
|
import Icon from "./Icon";
|
|
8
8
|
import { infoStyles } from "./InfoBars";
|
|
9
9
|
import InvisibleNumberInput from "./InvisibleNumberInput";
|
|
@@ -23,7 +23,6 @@ interface IProps {
|
|
|
23
23
|
// Callbacks
|
|
24
24
|
removeRecommendedCarbs(): void;
|
|
25
25
|
changedRecommendedCarbs(value: number): void;
|
|
26
|
-
onError(error: RecommendationError): void;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
interface IState {
|
|
@@ -50,7 +49,12 @@ export default class RecommendedCarbs extends React.Component<IProps, IState> {
|
|
|
50
49
|
public handleChangedCarbs = (carbs: number): void => {
|
|
51
50
|
if (carbs >= 0) {
|
|
52
51
|
if (carbs > 300) {
|
|
53
|
-
|
|
52
|
+
this.setState({ partialInput: this.props.recommendedCarbs });
|
|
53
|
+
return Alert.alert(i18n._(`Attention`), CarbohydrateLimitError().message, [
|
|
54
|
+
{
|
|
55
|
+
text: i18n._(`OK`),
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
54
58
|
}
|
|
55
59
|
this.props.changedRecommendedCarbs(carbs);
|
|
56
60
|
}
|
|
@@ -58,7 +62,7 @@ export default class RecommendedCarbs extends React.Component<IProps, IState> {
|
|
|
58
62
|
|
|
59
63
|
public renderRecommendedCarbs = (): JSX.Element => {
|
|
60
64
|
const shownCarbs = this.state.partialInput ?? Math.round(Number(this.props.recommendedCarbs));
|
|
61
|
-
const totalCarbs = Math.round(parseFloat(this.props.enteredCarbs) +
|
|
65
|
+
const totalCarbs = Math.round(parseFloat(this.props.enteredCarbs) + Number(shownCarbs));
|
|
62
66
|
return (
|
|
63
67
|
<React.Fragment>
|
|
64
68
|
<View style={calculationStyles.borderContainer}>
|
|
@@ -114,6 +118,7 @@ export default class RecommendedCarbs extends React.Component<IProps, IState> {
|
|
|
114
118
|
partialInput={this.handlePartialInput}
|
|
115
119
|
onEnd={this.handleChangedCarbs}
|
|
116
120
|
startValue={this.props.recommendedCarbs}
|
|
121
|
+
maxLength={3}
|
|
117
122
|
/>
|
|
118
123
|
</React.Fragment>
|
|
119
124
|
);
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { InjectionMethod } from "../types/enum";
|
|
3
|
-
import { RecommendationError } from "../utils/RecommendationError";
|
|
4
3
|
interface IProps {
|
|
5
4
|
insulinRecommendation?: number;
|
|
5
|
+
enteredInsulin?: number;
|
|
6
6
|
activityReduction?: number;
|
|
7
7
|
injectionMethod: InjectionMethod;
|
|
8
8
|
updateRecommendedInsulin(value: number): void;
|
|
9
|
-
onError(error: RecommendationError): void;
|
|
10
9
|
}
|
|
11
10
|
interface IState {
|
|
12
|
-
|
|
11
|
+
partialInput: string;
|
|
13
12
|
}
|
|
14
13
|
export default class RecommendedInsulin extends React.Component<IProps, IState> {
|
|
15
14
|
callbackInput: () => void;
|
|
16
15
|
constructor(props: IProps);
|
|
16
|
+
componentDidUpdate(prevProps: IProps): void;
|
|
17
17
|
handleOnPress: () => void;
|
|
18
18
|
updatePartially: (insulin: string) => string;
|
|
19
19
|
handleUpdatedInsulin: (value: number) => void;
|
|
@@ -9,7 +9,7 @@ const react_1 = __importDefault(require("react"));
|
|
|
9
9
|
const react_native_1 = require("react-native");
|
|
10
10
|
const react_native_linear_gradient_1 = __importDefault(require("react-native-linear-gradient"));
|
|
11
11
|
const i18nUtils_1 = require("../locale/i18nUtils");
|
|
12
|
-
const
|
|
12
|
+
const AttentionMessages_1 = require("../utils/AttentionMessages");
|
|
13
13
|
const Utils_1 = require("../utils/Utils");
|
|
14
14
|
const Icon_1 = __importDefault(require("./Icon"));
|
|
15
15
|
const InfoBars_1 = require("./InfoBars");
|
|
@@ -23,7 +23,7 @@ class RecommendedInsulin extends react_1.default.Component {
|
|
|
23
23
|
this.updatePartially = (insulin) => {
|
|
24
24
|
const replacedZero = insulin.length > 1 && insulin.startsWith(`0`) && !insulin.startsWith(`0.`) ? insulin.substring(1) : insulin;
|
|
25
25
|
this.setState({
|
|
26
|
-
|
|
26
|
+
partialInput: replacedZero,
|
|
27
27
|
});
|
|
28
28
|
return replacedZero;
|
|
29
29
|
};
|
|
@@ -33,13 +33,18 @@ class RecommendedInsulin extends react_1.default.Component {
|
|
|
33
33
|
const limited = (1 - this.props.activityReduction) * recommendation_calculator_1.SAFETY_INSULIN_LIMIT;
|
|
34
34
|
if (rounded > limited) {
|
|
35
35
|
this.updatePartially(`${limited}`);
|
|
36
|
-
return
|
|
36
|
+
return react_native_1.Alert.alert(i18nUtils_1.i18n._(`Attention`), AttentionMessages_1.Messages.InsulinInputWasLimited(this.props.activityReduction), [
|
|
37
|
+
{
|
|
38
|
+
text: i18nUtils_1.i18n._(`OK`),
|
|
39
|
+
},
|
|
40
|
+
]);
|
|
37
41
|
}
|
|
38
42
|
this.updatePartially(`${rounded}`);
|
|
39
43
|
this.props.updateRecommendedInsulin(rounded);
|
|
40
44
|
};
|
|
41
45
|
this.render = () => {
|
|
42
46
|
const paddingBottom = react_native_1.Platform.OS === `ios` ? `3%` : `1%`;
|
|
47
|
+
const shownInsulin = this.state.partialInput ?? this.props.insulinRecommendation ?? `0`;
|
|
43
48
|
return (<react_1.default.Fragment>
|
|
44
49
|
<react_native_1.TouchableOpacity accessibilityLabel="editRecommendedInsulin" onPress={this.handleOnPress}>
|
|
45
50
|
<react_native_linear_gradient_1.default style={recommendedInsulinStyles.container} colors={[`#a200ff`, `#578aff`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}>
|
|
@@ -50,20 +55,26 @@ class RecommendedInsulin extends react_1.default.Component {
|
|
|
50
55
|
</react_native_1.View>
|
|
51
56
|
<react_native_1.View style={[recommendedInsulinStyles.recommendedContainer, { paddingBottom }]}>
|
|
52
57
|
<react_native_1.View style={recommendedInsulinStyles.valueContainer}>
|
|
53
|
-
<react_native_1.Text style={recommendedInsulinStyles.value}>{
|
|
58
|
+
<react_native_1.Text style={recommendedInsulinStyles.value}>{shownInsulin}</react_native_1.Text>
|
|
54
59
|
<react_native_1.Text style={recommendedInsulinStyles.units}>{i18nUtils_1.i18n._(macro_1.t `Units`)}</react_native_1.Text>
|
|
55
60
|
</react_native_1.View>
|
|
56
61
|
<Icon_1.default style={recommendedInsulinStyles.editIcon} iconIdentifier={`Feather/edit`}/>
|
|
57
62
|
</react_native_1.View>
|
|
58
63
|
</react_native_linear_gradient_1.default>
|
|
59
64
|
</react_native_1.TouchableOpacity>
|
|
60
|
-
<InvisibleNumberInput_1.default decimalPlaces={3} negativeAllowed={false} cleanPartialInput={false} partialInput={this.updatePartially} onEnd={this.handleUpdatedInsulin} visible={(visible) => (this.callbackInput = visible)} startValue={`${
|
|
65
|
+
<InvisibleNumberInput_1.default decimalPlaces={3} negativeAllowed={false} cleanPartialInput={false} partialInput={this.updatePartially} onEnd={this.handleUpdatedInsulin} visible={(visible) => (this.callbackInput = visible)} startValue={`${shownInsulin}`}/>
|
|
61
66
|
</react_1.default.Fragment>);
|
|
62
67
|
};
|
|
63
68
|
this.state = {
|
|
64
|
-
|
|
69
|
+
partialInput: null,
|
|
65
70
|
};
|
|
66
71
|
}
|
|
72
|
+
componentDidUpdate(prevProps) {
|
|
73
|
+
const { enteredInsulin } = this.props;
|
|
74
|
+
if (prevProps.enteredInsulin !== enteredInsulin) {
|
|
75
|
+
this.setState({ partialInput: enteredInsulin?.toString() });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
67
78
|
}
|
|
68
79
|
exports.default = RecommendedInsulin;
|
|
69
80
|
const recommendedInsulinStyles = react_native_1.StyleSheet.create({
|
|
@@ -90,6 +101,7 @@ const recommendedInsulinStyles = react_native_1.StyleSheet.create({
|
|
|
90
101
|
flex: 1,
|
|
91
102
|
flexDirection: `row`,
|
|
92
103
|
justifyContent: `center`,
|
|
104
|
+
minHeight: react_native_1.Dimensions.get(`screen`).width / 4,
|
|
93
105
|
},
|
|
94
106
|
value: {
|
|
95
107
|
color: `white`,
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { SAFETY_INSULIN_LIMIT } from "@hedia/recommendation-calculator";
|
|
2
2
|
import { t } from "@lingui/macro";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { Dimensions, Platform, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
4
|
+
import { Alert, Dimensions, Platform, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
5
5
|
import LinearGradient from "react-native-linear-gradient";
|
|
6
6
|
import { i18n } from "../locale/i18nUtils";
|
|
7
7
|
import { InjectionMethod } from "../types/enum";
|
|
8
|
-
import {
|
|
8
|
+
import { Messages } from "../utils/AttentionMessages";
|
|
9
9
|
import { Utils } from "../utils/Utils";
|
|
10
10
|
import Icon from "./Icon";
|
|
11
11
|
import { infoStyles } from "./InfoBars";
|
|
12
12
|
import InvisibleNumberInput from "./InvisibleNumberInput";
|
|
13
13
|
|
|
14
14
|
interface IProps {
|
|
15
|
+
// Values
|
|
15
16
|
insulinRecommendation?: number;
|
|
17
|
+
enteredInsulin?: number;
|
|
16
18
|
activityReduction?: number;
|
|
17
|
-
|
|
18
19
|
injectionMethod: InjectionMethod;
|
|
19
20
|
|
|
21
|
+
// Callbacks
|
|
20
22
|
updateRecommendedInsulin(value: number): void;
|
|
21
|
-
onError(error: RecommendationError): void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
interface IState {
|
|
25
|
-
|
|
26
|
+
partialInput: string;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export default class RecommendedInsulin extends React.Component<IProps, IState> {
|
|
@@ -32,10 +33,17 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
32
33
|
super(props);
|
|
33
34
|
|
|
34
35
|
this.state = {
|
|
35
|
-
|
|
36
|
+
partialInput: null,
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
public componentDidUpdate(prevProps: IProps): void {
|
|
41
|
+
const { enteredInsulin } = this.props;
|
|
42
|
+
if (prevProps.enteredInsulin !== enteredInsulin) {
|
|
43
|
+
this.setState({ partialInput: enteredInsulin?.toString() });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
39
47
|
public handleOnPress = (): void => {
|
|
40
48
|
this.callbackInput?.();
|
|
41
49
|
};
|
|
@@ -44,7 +52,7 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
44
52
|
const replacedZero =
|
|
45
53
|
insulin.length > 1 && insulin.startsWith(`0`) && !insulin.startsWith(`0.`) ? insulin.substring(1) : insulin;
|
|
46
54
|
this.setState({
|
|
47
|
-
|
|
55
|
+
partialInput: replacedZero,
|
|
48
56
|
});
|
|
49
57
|
return replacedZero;
|
|
50
58
|
};
|
|
@@ -57,7 +65,11 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
57
65
|
|
|
58
66
|
if (rounded > limited) {
|
|
59
67
|
this.updatePartially(`${limited}`);
|
|
60
|
-
return
|
|
68
|
+
return Alert.alert(i18n._(`Attention`), Messages.InsulinInputWasLimited(this.props.activityReduction), [
|
|
69
|
+
{
|
|
70
|
+
text: i18n._(`OK`),
|
|
71
|
+
},
|
|
72
|
+
]);
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
this.updatePartially(`${rounded}`);
|
|
@@ -66,6 +78,7 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
66
78
|
|
|
67
79
|
public render = (): JSX.Element => {
|
|
68
80
|
const paddingBottom = Platform.OS === `ios` ? `3%` : `1%`;
|
|
81
|
+
const shownInsulin = this.state.partialInput ?? this.props.insulinRecommendation ?? `0`;
|
|
69
82
|
return (
|
|
70
83
|
<React.Fragment>
|
|
71
84
|
<TouchableOpacity accessibilityLabel="editRecommendedInsulin" onPress={this.handleOnPress}>
|
|
@@ -82,7 +95,7 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
82
95
|
</View>
|
|
83
96
|
<View style={[recommendedInsulinStyles.recommendedContainer, { paddingBottom }]}>
|
|
84
97
|
<View style={recommendedInsulinStyles.valueContainer}>
|
|
85
|
-
<Text style={recommendedInsulinStyles.value}>{
|
|
98
|
+
<Text style={recommendedInsulinStyles.value}>{shownInsulin}</Text>
|
|
86
99
|
<Text style={recommendedInsulinStyles.units}>{i18n._(t`Units`)}</Text>
|
|
87
100
|
</View>
|
|
88
101
|
<Icon style={recommendedInsulinStyles.editIcon} iconIdentifier={`Feather/edit`} />
|
|
@@ -96,7 +109,7 @@ export default class RecommendedInsulin extends React.Component<IProps, IState>
|
|
|
96
109
|
partialInput={this.updatePartially}
|
|
97
110
|
onEnd={this.handleUpdatedInsulin}
|
|
98
111
|
visible={(visible): (() => void) => (this.callbackInput = visible)}
|
|
99
|
-
startValue={`${
|
|
112
|
+
startValue={`${shownInsulin}`}
|
|
100
113
|
/>
|
|
101
114
|
</React.Fragment>
|
|
102
115
|
);
|
|
@@ -127,6 +140,7 @@ const recommendedInsulinStyles = StyleSheet.create({
|
|
|
127
140
|
flex: 1,
|
|
128
141
|
flexDirection: `row`,
|
|
129
142
|
justifyContent: `center`,
|
|
143
|
+
minHeight: Dimensions.get(`screen`).width / 4,
|
|
130
144
|
},
|
|
131
145
|
value: {
|
|
132
146
|
color: `white`,
|