@hedia/recommendation-screen 1.0.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 (118) hide show
  1. package/.prettierignore +2 -0
  2. package/Changelog.md +5 -0
  3. package/README.md +3 -0
  4. package/android/app/BUCK +55 -0
  5. package/android/app/build.gradle +226 -0
  6. package/android/app/build_defs.bzl +19 -0
  7. package/android/app/debug.keystore +0 -0
  8. package/android/app/proguard-rules.pro +10 -0
  9. package/android/app/src/debug/AndroidManifest.xml +8 -0
  10. package/android/app/src/debug/java/com/hediarecommendationscreen/ReactNativeFlipper.java +72 -0
  11. package/android/app/src/main/AndroidManifest.xml +27 -0
  12. package/android/app/src/main/java/com/hediarecommendationscreen/MainActivity.java +15 -0
  13. package/android/app/src/main/java/com/hediarecommendationscreen/MainApplication.java +80 -0
  14. package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  15. package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  16. package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  17. package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  18. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  19. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  20. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  21. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  22. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  23. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  24. package/android/app/src/main/res/values/strings.xml +3 -0
  25. package/android/app/src/main/res/values/styles.xml +9 -0
  26. package/android/build.gradle +38 -0
  27. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  28. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  29. package/android/gradle.properties +28 -0
  30. package/android/gradlew +188 -0
  31. package/android/gradlew.bat +100 -0
  32. package/android/settings.gradle +3 -0
  33. package/index-git.sh +5 -0
  34. package/index.d.ts +5 -0
  35. package/index.js +16 -0
  36. package/index.ts +19 -0
  37. package/ios/HediaRecommendationScreen/AppDelegate.h +8 -0
  38. package/ios/HediaRecommendationScreen/AppDelegate.m +58 -0
  39. package/ios/HediaRecommendationScreen/Base.lproj/LaunchScreen.xib +42 -0
  40. package/ios/HediaRecommendationScreen/Images.xcassets/AppIcon.appiconset/Contents.json +38 -0
  41. package/ios/HediaRecommendationScreen/Images.xcassets/Contents.json +6 -0
  42. package/ios/HediaRecommendationScreen/Info.plist +57 -0
  43. package/ios/HediaRecommendationScreen/main.m +9 -0
  44. package/ios/HediaRecommendationScreen-tvOS/Info.plist +53 -0
  45. package/ios/HediaRecommendationScreen-tvOSTests/Info.plist +24 -0
  46. package/ios/HediaRecommendationScreen.xcodeproj/project.pbxproj +807 -0
  47. package/ios/HediaRecommendationScreen.xcodeproj/xcshareddata/xcschemes/HediaRecommendationScreen-tvOS.xcscheme +88 -0
  48. package/ios/HediaRecommendationScreen.xcodeproj/xcshareddata/xcschemes/HediaRecommendationScreen.xcscheme +88 -0
  49. package/ios/HediaRecommendationScreenTests/HediaRecommendationScreenTests.m +65 -0
  50. package/ios/HediaRecommendationScreenTests/Info.plist +24 -0
  51. package/ios/Podfile +104 -0
  52. package/package.json +75 -0
  53. package/src/RecommendationScreen.d.ts +42 -0
  54. package/src/RecommendationScreen.js +142 -0
  55. package/src/RecommendationScreen.tsx +210 -0
  56. package/src/assets/happy.png +0 -0
  57. package/src/assets/happy_active.png +0 -0
  58. package/src/assets/neutral.png +0 -0
  59. package/src/assets/neutral_active.png +0 -0
  60. package/src/assets/sad.png +0 -0
  61. package/src/assets/sad_active.png +0 -0
  62. package/src/assets/semi_happy.png +0 -0
  63. package/src/assets/semi_happy_active.png +0 -0
  64. package/src/assets/semi_sad.png +0 -0
  65. package/src/assets/semi_sad_active.png +0 -0
  66. package/src/components/Emotion.d.ts +14 -0
  67. package/src/components/Emotion.js +55 -0
  68. package/src/components/Emotion.tsx +71 -0
  69. package/src/components/Header.d.ts +52 -0
  70. package/src/components/Header.js +83 -0
  71. package/src/components/Header.tsx +94 -0
  72. package/src/components/Icon.js +41 -0
  73. package/src/components/InfoBars.d.ts +67 -0
  74. package/src/components/InfoBars.js +89 -0
  75. package/src/components/InfoBars.tsx +93 -0
  76. package/src/components/InvisibleNumberInput.d.ts +24 -0
  77. package/src/components/InvisibleNumberInput.js +64 -0
  78. package/src/components/InvisibleNumberInput.tsx +88 -0
  79. package/src/components/MoodIcon.d.ts +14 -0
  80. package/src/components/MoodIcon.js +53 -0
  81. package/src/components/MoodIcon.tsx +58 -0
  82. package/src/components/RecentInsulin.d.ts +9 -0
  83. package/src/components/RecentInsulin.js +91 -0
  84. package/src/components/RecentInsulin.tsx +97 -0
  85. package/src/components/RecommendedCarbs.d.ts +30 -0
  86. package/src/components/RecommendedCarbs.js +193 -0
  87. package/src/components/RecommendedCarbs.tsx +242 -0
  88. package/src/components/RecommendedInsulin.d.ts +22 -0
  89. package/src/components/RecommendedInsulin.js +110 -0
  90. package/src/components/RecommendedInsulin.tsx +147 -0
  91. package/src/components/Remeasure.d.ts +13 -0
  92. package/src/components/Remeasure.js +89 -0
  93. package/src/components/Remeasure.tsx +105 -0
  94. package/src/components/TransferToLogbook.d.ts +14 -0
  95. package/src/components/TransferToLogbook.js +81 -0
  96. package/src/components/TransferToLogbook.tsx +97 -0
  97. package/src/locale/da/messages.js +1 -0
  98. package/src/locale/da/messages.po +119 -0
  99. package/src/locale/en/messages.js +1 -0
  100. package/src/locale/en/messages.po +119 -0
  101. package/src/locale/i18nUtils.d.ts +5 -0
  102. package/src/locale/i18nUtils.js +22 -0
  103. package/src/locale/i18nUtils.ts +21 -0
  104. package/src/types/enum.d.ts +26 -0
  105. package/src/types/enum.js +34 -0
  106. package/src/types/enum.ts +30 -0
  107. package/src/types/types.d.ts +21 -0
  108. package/src/types/types.js +2 -0
  109. package/src/types/types.ts +23 -0
  110. package/src/utils/Constants.d.ts +3 -0
  111. package/src/utils/Constants.js +6 -0
  112. package/src/utils/Constants.ts +3 -0
  113. package/src/utils/RecommendationError.d.ts +9 -0
  114. package/src/utils/RecommendationError.js +17 -0
  115. package/src/utils/RecommendationError.ts +30 -0
  116. package/src/utils/Utils.d.ts +5 -0
  117. package/src/utils/Utils.js +24 -0
  118. package/src/utils/Utils.ts +26 -0
@@ -0,0 +1,97 @@
1
+ import { t } from "@lingui/macro";
2
+ import React from "react";
3
+ import { Dimensions, StyleSheet, Text, TouchableOpacity, View } from "react-native";
4
+ import { i18n } from "../locale/i18nUtils";
5
+ import { infoStyles } from "./InfoBars";
6
+
7
+ interface IProps {
8
+ onRecentInsulinYes(): void;
9
+ onRecentInsulinNo(): void;
10
+ }
11
+
12
+ export default class RecentInsulin extends React.Component<IProps> {
13
+ public render = () => {
14
+ return (
15
+ <View style={recentInsulinStyles.container}>
16
+ <View style={recentInsulinStyles.titleContainer}>
17
+ <Text style={recentInsulinStyles.recommended}>{i18n._(t`Recommended amount of insulin`)}</Text>
18
+ </View>
19
+ <View style={recentInsulinStyles.takenInsulinContainer}>
20
+ <Text style={recentInsulinStyles.takenInsulin}>
21
+ {i18n._(t`Have you taken insulin within the last 4 hours?`)}
22
+ </Text>
23
+ </View>
24
+ <View style={recentInsulinStyles.buttonContainer}>
25
+ <View style={recentInsulinStyles.filler} />
26
+ <TouchableOpacity
27
+ onPress={this.props.onRecentInsulinYes}
28
+ style={[recentInsulinStyles.yesNoContainer, { marginRight: `2%` }]}
29
+ >
30
+ <Text style={recentInsulinStyles.yesNoText}>{i18n._(t`Yes`)}</Text>
31
+ </TouchableOpacity>
32
+ <TouchableOpacity
33
+ onPress={this.props.onRecentInsulinNo}
34
+ style={[recentInsulinStyles.yesNoContainer, { marginLeft: `2%` }]}
35
+ >
36
+ <Text style={recentInsulinStyles.yesNoText}>{i18n._(t`No`)}</Text>
37
+ </TouchableOpacity>
38
+ <View style={recentInsulinStyles.filler} />
39
+ </View>
40
+ </View>
41
+ );
42
+ };
43
+ }
44
+
45
+ const recentInsulinStyles = StyleSheet.create({
46
+ container: {
47
+ ...infoStyles.margin,
48
+ backgroundColor: `rgba(118, 82, 255, 0.5)`,
49
+ borderRadius: 5,
50
+ },
51
+ titleContainer: {
52
+ flex: 1,
53
+ justifyContent: `center`,
54
+ alignItems: `center`,
55
+ marginTop: `4%`,
56
+ marginBottom: `4%`,
57
+ },
58
+ recommended: {
59
+ ...infoStyles.label,
60
+ },
61
+ takenInsulinContainer: {
62
+ flex: 1,
63
+ justifyContent: `center`,
64
+ alignItems: `center`,
65
+ marginTop: `2%`,
66
+ },
67
+ takenInsulin: {
68
+ ...infoStyles.label,
69
+ fontSize: Dimensions.get(`screen`).width / 27,
70
+ },
71
+ buttonContainer: {
72
+ flex: 1,
73
+ flexDirection: `row`,
74
+ justifyContent: `space-evenly`,
75
+ marginTop: `4%`,
76
+ marginBottom: `5%`,
77
+ },
78
+ yesNoContainer: {
79
+ flex: 1,
80
+ borderColor: `white`,
81
+ borderRadius: 100,
82
+ borderWidth: 2,
83
+ paddingHorizontal: `2%`,
84
+ paddingVertical: `1%`,
85
+ },
86
+ yesNoText: {
87
+ textAlign: `center`,
88
+ paddingTop: `1%`,
89
+ paddingBottom: `1%`,
90
+ color: `white`,
91
+ fontSize: Dimensions.get(`screen`).width / 25,
92
+ fontWeight: `bold`,
93
+ },
94
+ filler: {
95
+ flex: 1,
96
+ },
97
+ });
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { RecommendationError } from "../utils/RecommendationError";
3
+ interface ICalculationRow {
4
+ label: string;
5
+ info: string;
6
+ value: string;
7
+ units: string;
8
+ }
9
+ interface IProps {
10
+ recommendedCarbs?: string;
11
+ enteredCarbs: string;
12
+ removeRecommendedCarbs(): void;
13
+ changedRecommendedCarbs(value: number): void;
14
+ onError(error: RecommendationError): void;
15
+ }
16
+ interface IState {
17
+ remeasureTime: number;
18
+ partialInput: string;
19
+ }
20
+ export default class RecommendedCarbs extends React.Component<IProps, IState> {
21
+ state: IState;
22
+ callbackInput: () => void;
23
+ showTextInput: () => void;
24
+ handlePartialInput: (partialInput: string) => void;
25
+ handleChangedCarbs: (carbs: number) => void;
26
+ renderRecommendedCarbs: () => JSX.Element;
27
+ renderRow: (row: ICalculationRow) => JSX.Element;
28
+ render(): JSX.Element;
29
+ }
30
+ export {};
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const macro_1 = require("@lingui/macro");
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const i18nUtils_1 = require("../locale/i18nUtils");
10
+ const Constants_1 = require("../utils/Constants");
11
+ const RecommendationError_1 = require("../utils/RecommendationError");
12
+ const Icon_1 = __importDefault(require("./Icon"));
13
+ const InfoBars_1 = require("./InfoBars");
14
+ const InvisibleNumberInput_1 = __importDefault(require("./InvisibleNumberInput"));
15
+ class RecommendedCarbs extends react_1.default.Component {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.state = {
19
+ remeasureTime: 1.5,
20
+ partialInput: null,
21
+ };
22
+ this.showTextInput = () => {
23
+ this.callbackInput?.();
24
+ };
25
+ this.handlePartialInput = (partialInput) => {
26
+ this.setState({
27
+ partialInput,
28
+ });
29
+ };
30
+ this.handleChangedCarbs = (carbs) => {
31
+ if (carbs >= 0) {
32
+ if (carbs > 300) {
33
+ return this.props.onError(RecommendationError_1.CarbohydrateLimitError);
34
+ }
35
+ this.props.changedRecommendedCarbs(carbs);
36
+ }
37
+ };
38
+ this.renderRecommendedCarbs = () => {
39
+ return (<react_1.default.Fragment>
40
+ <react_native_1.View style={calculationStyles.borderContainer}>
41
+ <react_native_1.View style={calculationStyles.recommendedContainer}>
42
+ <react_native_1.TouchableOpacity accessibilityLabel="removeRecommendedCarbs" style={calculationStyles.removeRecommended} onPress={this.props.removeRecommendedCarbs}>
43
+ <Icon_1.default iconIdentifier={`Ionicons/ios-close-circle-outline`} style={calculationStyles.removeRecommendedIcon}/>
44
+ </react_native_1.TouchableOpacity>
45
+ <react_native_1.Text style={calculationStyles.recommendedLabel}>{i18nUtils_1.i18n._(macro_1.t `Recommended`)}</react_native_1.Text>
46
+ </react_native_1.View>
47
+ <react_native_1.View style={calculationStyles.additionalContainer}>
48
+ <react_native_1.Text style={calculationStyles.additional}>{i18nUtils_1.i18n._(macro_1.t `Additional`)}</react_native_1.Text>
49
+ </react_native_1.View>
50
+ <react_native_1.View style={{ flex: calculationStyles.valueUnitContainer[`flex`] }}>
51
+ <react_native_1.TouchableOpacity accessibilityLabel="editRecommendedCarbsButton" onPress={this.showTextInput} style={[calculationStyles.valueUnitContainer, calculationStyles.recommendedBorder]}>
52
+ <react_native_1.View style={calculationStyles.valueContainer}>
53
+ <react_native_1.Text style={[calculationStyles.value, { color: Constants_1.BORDER_COLOUR_TEAL }]}>
54
+ +{this.state.partialInput ?? this.props.recommendedCarbs}
55
+ </react_native_1.Text>
56
+ </react_native_1.View>
57
+ <react_native_1.View style={[calculationStyles.unitContainer]}>
58
+ <react_native_1.View style={calculationStyles.editIconContainer}>
59
+ <Icon_1.default style={calculationStyles.editIcon} iconIdentifier={`Feather/edit`}/>
60
+ </react_native_1.View>
61
+ <react_native_1.Text style={[calculationStyles.units, { color: Constants_1.BORDER_COLOUR_TEAL }]}>
62
+ {i18nUtils_1.i18n._(macro_1.t `g carbs`)}
63
+ </react_native_1.Text>
64
+ </react_native_1.View>
65
+ </react_native_1.TouchableOpacity>
66
+ </react_native_1.View>
67
+ </react_native_1.View>
68
+ {this.renderRow({
69
+ label: ``,
70
+ info: i18nUtils_1.i18n._(macro_1.t `Total`),
71
+ value: `0`,
72
+ units: i18nUtils_1.i18n._(macro_1.t `g carbs`),
73
+ })}
74
+ <InvisibleNumberInput_1.default negativeAllowed={false} cleanPartialInput={true} decimalPlaces={0} visible={(callback) => (this.callbackInput = callback)} partialInput={this.handlePartialInput} onEnd={(val) => {
75
+ this.handleChangedCarbs(val);
76
+ }} startValue={this.props.recommendedCarbs}/>
77
+ </react_1.default.Fragment>);
78
+ };
79
+ this.renderRow = (row) => {
80
+ return (<react_native_1.View style={calculationStyles.borderContainer}>
81
+ <react_native_1.View style={calculationStyles.foodContainer}>
82
+ <react_native_1.Text style={calculationStyles.foodLabel}>{row.label}</react_native_1.Text>
83
+ </react_native_1.View>
84
+ <react_native_1.View style={calculationStyles.enteredContainer}>
85
+ <react_native_1.Text style={calculationStyles.entered}>{row.info}</react_native_1.Text>
86
+ </react_native_1.View>
87
+ <react_native_1.View style={calculationStyles.valueUnitContainer}>
88
+ <react_native_1.View style={calculationStyles.valueContainer}>
89
+ <react_native_1.Text style={calculationStyles.value}>{row.value}</react_native_1.Text>
90
+ </react_native_1.View>
91
+ <react_native_1.View style={calculationStyles.unitContainer}>
92
+ <react_native_1.Text style={calculationStyles.units}>{row.units}</react_native_1.Text>
93
+ </react_native_1.View>
94
+ </react_native_1.View>
95
+ </react_native_1.View>);
96
+ };
97
+ }
98
+ render() {
99
+ const carbs = Number(this.props.recommendedCarbs);
100
+ return (<react_1.default.Fragment>
101
+ {this.renderRow({
102
+ label: i18nUtils_1.i18n._(macro_1.t `Food`),
103
+ info: i18nUtils_1.i18n._(macro_1.t `Entered`),
104
+ value: this.props.enteredCarbs,
105
+ units: i18nUtils_1.i18n._(macro_1.t `g carbs`),
106
+ })}
107
+ {!isNaN(carbs) && carbs > 0 ? this.renderRecommendedCarbs() : null}
108
+ </react_1.default.Fragment>);
109
+ }
110
+ }
111
+ exports.default = RecommendedCarbs;
112
+ const calculationStyles = react_native_1.StyleSheet.create({
113
+ borderContainer: {
114
+ ...InfoBars_1.infoStyles.borderContainer,
115
+ alignItems: `center`,
116
+ },
117
+ foodContainer: {
118
+ flex: 4,
119
+ },
120
+ foodLabel: {
121
+ color: `white`,
122
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 22,
123
+ fontWeight: `bold`,
124
+ },
125
+ enteredContainer: {
126
+ flex: 3,
127
+ alignItems: `flex-end`,
128
+ },
129
+ entered: {
130
+ color: `white`,
131
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 23,
132
+ },
133
+ valueUnitContainer: {
134
+ ...InfoBars_1.infoStyles.valueUnitContainer,
135
+ },
136
+ valueContainer: {
137
+ ...InfoBars_1.infoStyles.valueContainer,
138
+ },
139
+ value: {
140
+ ...InfoBars_1.infoStyles.value,
141
+ },
142
+ unitContainer: {
143
+ ...InfoBars_1.infoStyles.unitContainer,
144
+ },
145
+ units: {
146
+ ...InfoBars_1.infoStyles.units,
147
+ },
148
+ editIconContainer: {
149
+ justifyContent: `flex-end`,
150
+ flexDirection: `row`,
151
+ paddingRight: `5%`,
152
+ },
153
+ editIcon: {
154
+ color: Constants_1.BORDER_COLOUR_TEAL,
155
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 30,
156
+ },
157
+ recommendedContainer: {
158
+ flex: 4,
159
+ flexDirection: `row`,
160
+ },
161
+ recommendedLabel: {
162
+ color: Constants_1.BORDER_COLOUR_TEAL,
163
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 27,
164
+ fontWeight: `bold`,
165
+ },
166
+ removeRecommended: {
167
+ justifyContent: `center`,
168
+ padding: `1%`,
169
+ marginRight: `2%`,
170
+ marginTop: `1%`,
171
+ },
172
+ removeRecommendedIcon: {
173
+ color: Constants_1.BORDER_COLOUR_TEAL,
174
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 26,
175
+ },
176
+ additionalContainer: {
177
+ flex: 3,
178
+ alignItems: `flex-end`,
179
+ },
180
+ additional: {
181
+ color: Constants_1.BORDER_COLOUR_TEAL,
182
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 27,
183
+ },
184
+ recommendedBorder: {
185
+ borderWidth: 2,
186
+ borderColor: Constants_1.BORDER_COLOUR_TEAL,
187
+ borderRadius: 5,
188
+ paddingBottom: `2%`,
189
+ marginLeft: `10%`,
190
+ paddingRight: `3%`,
191
+ marginRight: `7%`,
192
+ },
193
+ });
@@ -0,0 +1,242 @@
1
+ import { t } from "@lingui/macro";
2
+ import React from "react";
3
+ import { Dimensions, StyleSheet, Text, TouchableOpacity, View } from "react-native";
4
+ import { i18n } from "../locale/i18nUtils";
5
+ import { BORDER_COLOUR_TEAL } from "../utils/Constants";
6
+ import { CarbohydrateLimitError, RecommendationError } from "../utils/RecommendationError";
7
+ import Icon from "./Icon";
8
+ import { infoStyles } from "./InfoBars";
9
+ import InvisibleNumberInput from "./InvisibleNumberInput";
10
+
11
+ interface ICalculationRow {
12
+ label: string;
13
+ info: string;
14
+ value: string;
15
+ units: string;
16
+ }
17
+
18
+ interface IProps {
19
+ // Values
20
+ recommendedCarbs?: string;
21
+ enteredCarbs: string;
22
+
23
+ // Callbacks
24
+ removeRecommendedCarbs(): void;
25
+ changedRecommendedCarbs(value: number): void;
26
+ onError(error: RecommendationError): void;
27
+ }
28
+
29
+ interface IState {
30
+ remeasureTime: number;
31
+ partialInput: string;
32
+ }
33
+
34
+ export default class RecommendedCarbs extends React.Component<IProps, IState> {
35
+ public state: IState = {
36
+ remeasureTime: 1.5,
37
+ partialInput: null,
38
+ };
39
+
40
+ public callbackInput: () => void;
41
+
42
+ public showTextInput = () => {
43
+ this.callbackInput?.();
44
+ };
45
+
46
+ public handlePartialInput = (partialInput: string) => {
47
+ this.setState({
48
+ partialInput,
49
+ });
50
+ };
51
+
52
+ public handleChangedCarbs = (carbs: number) => {
53
+ if (carbs >= 0) {
54
+ if (carbs > 300) {
55
+ return this.props.onError(CarbohydrateLimitError);
56
+ }
57
+ this.props.changedRecommendedCarbs(carbs);
58
+ }
59
+ };
60
+
61
+ public renderRecommendedCarbs = () => {
62
+ return (
63
+ <React.Fragment>
64
+ <View style={calculationStyles.borderContainer}>
65
+ <View style={calculationStyles.recommendedContainer}>
66
+ <TouchableOpacity
67
+ accessibilityLabel="removeRecommendedCarbs"
68
+ style={calculationStyles.removeRecommended}
69
+ onPress={this.props.removeRecommendedCarbs}
70
+ >
71
+ <Icon
72
+ iconIdentifier={`Ionicons/ios-close-circle-outline`}
73
+ style={calculationStyles.removeRecommendedIcon}
74
+ />
75
+ </TouchableOpacity>
76
+ <Text style={calculationStyles.recommendedLabel}>{i18n._(t`Recommended`)}</Text>
77
+ </View>
78
+ <View style={calculationStyles.additionalContainer}>
79
+ <Text style={calculationStyles.additional}>{i18n._(t`Additional`)}</Text>
80
+ </View>
81
+ <View style={{ flex: calculationStyles.valueUnitContainer[`flex`] }}>
82
+ <TouchableOpacity
83
+ accessibilityLabel="editRecommendedCarbsButton"
84
+ onPress={this.showTextInput}
85
+ style={[calculationStyles.valueUnitContainer, calculationStyles.recommendedBorder]}
86
+ >
87
+ <View style={calculationStyles.valueContainer}>
88
+ <Text style={[calculationStyles.value, { color: BORDER_COLOUR_TEAL }]}>
89
+ +{this.state.partialInput ?? this.props.recommendedCarbs}
90
+ </Text>
91
+ </View>
92
+ <View style={[calculationStyles.unitContainer]}>
93
+ <View style={calculationStyles.editIconContainer}>
94
+ <Icon style={calculationStyles.editIcon} iconIdentifier={`Feather/edit`} />
95
+ </View>
96
+ <Text style={[calculationStyles.units, { color: BORDER_COLOUR_TEAL }]}>
97
+ {i18n._(t`g carbs`)}
98
+ </Text>
99
+ </View>
100
+ </TouchableOpacity>
101
+ </View>
102
+ </View>
103
+ {this.renderRow({
104
+ label: ``,
105
+ info: i18n._(t`Total`),
106
+ value: `0`,
107
+ units: i18n._(t`g carbs`),
108
+ })}
109
+ <InvisibleNumberInput
110
+ negativeAllowed={false}
111
+ cleanPartialInput={true}
112
+ decimalPlaces={0}
113
+ visible={(callback) => (this.callbackInput = callback)}
114
+ partialInput={this.handlePartialInput}
115
+ onEnd={(val) => {
116
+ this.handleChangedCarbs(val);
117
+ }}
118
+ startValue={this.props.recommendedCarbs}
119
+ />
120
+ </React.Fragment>
121
+ );
122
+ };
123
+
124
+ public renderRow = (row: ICalculationRow) => {
125
+ return (
126
+ <View style={calculationStyles.borderContainer}>
127
+ <View style={calculationStyles.foodContainer}>
128
+ <Text style={calculationStyles.foodLabel}>{row.label}</Text>
129
+ </View>
130
+ <View style={calculationStyles.enteredContainer}>
131
+ <Text style={calculationStyles.entered}>{row.info}</Text>
132
+ </View>
133
+ <View style={calculationStyles.valueUnitContainer}>
134
+ <View style={calculationStyles.valueContainer}>
135
+ <Text style={calculationStyles.value}>{row.value}</Text>
136
+ </View>
137
+ <View style={calculationStyles.unitContainer}>
138
+ <Text style={calculationStyles.units}>{row.units}</Text>
139
+ </View>
140
+ </View>
141
+ </View>
142
+ );
143
+ };
144
+
145
+ public render() {
146
+ const carbs = Number(this.props.recommendedCarbs);
147
+ return (
148
+ <React.Fragment>
149
+ {this.renderRow({
150
+ label: i18n._(t`Food`),
151
+ info: i18n._(t`Entered`),
152
+ value: this.props.enteredCarbs,
153
+ units: i18n._(t`g carbs`),
154
+ })}
155
+ {!isNaN(carbs) && carbs > 0 ? this.renderRecommendedCarbs() : null}
156
+ </React.Fragment>
157
+ );
158
+ }
159
+ }
160
+
161
+ const calculationStyles = StyleSheet.create({
162
+ borderContainer: {
163
+ ...infoStyles.borderContainer,
164
+ alignItems: `center`,
165
+ },
166
+ foodContainer: {
167
+ flex: 4,
168
+ },
169
+ foodLabel: {
170
+ color: `white`,
171
+ fontSize: Dimensions.get(`screen`).width / 22,
172
+ fontWeight: `bold`,
173
+ },
174
+ enteredContainer: {
175
+ flex: 3,
176
+ alignItems: `flex-end`,
177
+ },
178
+ entered: {
179
+ color: `white`,
180
+ fontSize: Dimensions.get(`screen`).width / 23,
181
+ },
182
+ valueUnitContainer: {
183
+ ...infoStyles.valueUnitContainer,
184
+ },
185
+ valueContainer: {
186
+ ...infoStyles.valueContainer,
187
+ },
188
+ value: {
189
+ ...infoStyles.value,
190
+ },
191
+ unitContainer: {
192
+ ...infoStyles.unitContainer,
193
+ },
194
+ units: {
195
+ ...infoStyles.units,
196
+ },
197
+ editIconContainer: {
198
+ justifyContent: `flex-end`,
199
+ flexDirection: `row`,
200
+ paddingRight: `5%`,
201
+ },
202
+ editIcon: {
203
+ color: BORDER_COLOUR_TEAL,
204
+ fontSize: Dimensions.get(`screen`).width / 30,
205
+ },
206
+ recommendedContainer: {
207
+ flex: 4,
208
+ flexDirection: `row`,
209
+ },
210
+ recommendedLabel: {
211
+ color: BORDER_COLOUR_TEAL,
212
+ fontSize: Dimensions.get(`screen`).width / 27,
213
+ fontWeight: `bold`,
214
+ },
215
+ removeRecommended: {
216
+ justifyContent: `center`,
217
+ padding: `1%`,
218
+ marginRight: `2%`,
219
+ marginTop: `1%`,
220
+ },
221
+ removeRecommendedIcon: {
222
+ color: BORDER_COLOUR_TEAL,
223
+ fontSize: Dimensions.get(`screen`).width / 26,
224
+ },
225
+ additionalContainer: {
226
+ flex: 3,
227
+ alignItems: `flex-end`,
228
+ },
229
+ additional: {
230
+ color: BORDER_COLOUR_TEAL,
231
+ fontSize: Dimensions.get(`screen`).width / 27,
232
+ },
233
+ recommendedBorder: {
234
+ borderWidth: 2,
235
+ borderColor: BORDER_COLOUR_TEAL,
236
+ borderRadius: 5,
237
+ paddingBottom: `2%`,
238
+ marginLeft: `10%`,
239
+ paddingRight: `3%`,
240
+ marginRight: `7%`,
241
+ },
242
+ });
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import { InjectionMethod } from "../types/enum";
3
+ import { RecommendationError } from "../utils/RecommendationError";
4
+ interface IProps {
5
+ insulinRecommendation?: number;
6
+ activityReduction?: number;
7
+ injectionMethod: InjectionMethod;
8
+ updateRecommendedInsulin(value: number): void;
9
+ onError(error: RecommendationError): void;
10
+ }
11
+ interface IState {
12
+ insulin: string;
13
+ }
14
+ export default class RecommendedInsulin extends React.Component<IProps, IState> {
15
+ callbackInput: () => void;
16
+ constructor(props: IProps);
17
+ handleOnPress: () => void;
18
+ updatePartially: (insulin: string) => string;
19
+ handleUpdatedInsulin: (value: number) => void;
20
+ render: () => JSX.Element;
21
+ }
22
+ export {};
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const macro_1 = require("@lingui/macro");
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const react_native_linear_gradient_1 = __importDefault(require("react-native-linear-gradient"));
10
+ const i18nUtils_1 = require("../locale/i18nUtils");
11
+ const RecommendationError_1 = require("../utils/RecommendationError");
12
+ const Utils_1 = require("../utils/Utils");
13
+ const Icon_1 = __importDefault(require("./Icon"));
14
+ const InfoBars_1 = require("./InfoBars");
15
+ const InvisibleNumberInput_1 = __importDefault(require("./InvisibleNumberInput"));
16
+ class RecommendedInsulin extends react_1.default.Component {
17
+ constructor(props) {
18
+ super(props);
19
+ this.handleOnPress = () => {
20
+ this.callbackInput?.();
21
+ };
22
+ this.updatePartially = (insulin) => {
23
+ const replacedZero = insulin.length > 1 && insulin.startsWith(`0`) && !insulin.startsWith(`0.`) ? insulin.substring(1) : insulin;
24
+ this.setState({
25
+ insulin: replacedZero,
26
+ });
27
+ return replacedZero;
28
+ };
29
+ this.handleUpdatedInsulin = (value) => {
30
+ const rounded = Utils_1.Utils.roundValue(value, this.props.injectionMethod);
31
+ // https://hedia.atlassian.net/browse/HDA-795
32
+ const limited = (1 - this.props.activityReduction) * 50;
33
+ if (rounded > limited) {
34
+ this.updatePartially(`${limited}`);
35
+ return this.props.onError(RecommendationError_1.InsulinLimitError);
36
+ }
37
+ this.updatePartially(`${rounded}`);
38
+ this.props.updateRecommendedInsulin(rounded);
39
+ };
40
+ this.render = () => {
41
+ return (<react_1.default.Fragment>
42
+ <react_native_1.TouchableOpacity accessibilityLabel="editRecommendedInsulin" onPress={this.handleOnPress}>
43
+ <react_native_linear_gradient_1.default style={recommendedInsulinStyles.container} colors={[`#a200ff`, `#578aff`]} start={{ x: 0, y: 0 }} end={{ x: 1, y: 0 }}>
44
+ <react_native_1.View style={recommendedInsulinStyles.recommendedTextContainer}>
45
+ <react_native_1.Text style={recommendedInsulinStyles.recommendedText}>
46
+ {i18nUtils_1.i18n._(macro_1.t `Recommended amount of insulin`)}
47
+ </react_native_1.Text>
48
+ </react_native_1.View>
49
+ <react_native_1.View style={recommendedInsulinStyles.recommendedContainer}>
50
+ <react_native_1.View style={recommendedInsulinStyles.valueContainer}>
51
+ <react_native_1.Text style={recommendedInsulinStyles.value}>{this.state.insulin}</react_native_1.Text>
52
+ <react_native_1.Text style={recommendedInsulinStyles.units}>{i18nUtils_1.i18n._(macro_1.t `Units`)}</react_native_1.Text>
53
+ </react_native_1.View>
54
+ <Icon_1.default style={recommendedInsulinStyles.editIcon} iconIdentifier={`Feather/edit`}/>
55
+ </react_native_1.View>
56
+ </react_native_linear_gradient_1.default>
57
+ </react_native_1.TouchableOpacity>
58
+ <InvisibleNumberInput_1.default decimalPlaces={3} negativeAllowed={false} cleanPartialInput={false} partialInput={this.updatePartially} onEnd={this.handleUpdatedInsulin} visible={(visible) => (this.callbackInput = visible)} startValue={`${this.state.insulin}`}/>
59
+ </react_1.default.Fragment>);
60
+ };
61
+ this.state = {
62
+ insulin: `${props.insulinRecommendation ?? 0}`,
63
+ };
64
+ }
65
+ }
66
+ exports.default = RecommendedInsulin;
67
+ const recommendedInsulinStyles = react_native_1.StyleSheet.create({
68
+ container: {
69
+ marginHorizontal: InfoBars_1.infoStyles.margin.margin,
70
+ borderRadius: 5,
71
+ },
72
+ recommendedTextContainer: {
73
+ flex: 1,
74
+ alignItems: `center`,
75
+ marginTop: `3%`,
76
+ },
77
+ recommendedText: {
78
+ color: `white`,
79
+ fontWeight: `bold`,
80
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 24,
81
+ },
82
+ recommendedContainer: {
83
+ flex: 1,
84
+ flexDirection: `row`,
85
+ marginLeft: `10%`,
86
+ },
87
+ valueContainer: {
88
+ flex: 1,
89
+ flexDirection: `row`,
90
+ justifyContent: `center`,
91
+ },
92
+ value: {
93
+ color: `white`,
94
+ fontWeight: `bold`,
95
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 5,
96
+ },
97
+ units: {
98
+ color: `white`,
99
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 28,
100
+ textAlignVertical: `bottom`,
101
+ paddingBottom: `6%`,
102
+ },
103
+ editIcon: {
104
+ color: `white`,
105
+ fontSize: react_native_1.Dimensions.get(`screen`).width / 28,
106
+ textAlignVertical: `center`,
107
+ paddingBottom: `10%`,
108
+ marginRight: `5%`,
109
+ },
110
+ });