@hedia/recommendation-screen 1.0.7 → 1.1.1
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/App.jsx +36 -15
- package/android/app/src/main/res/values/color.xml +3 -0
- package/android/app/src/main/res/values/styles.xml +3 -0
- package/index.d.ts +3 -3
- package/index.js +23 -7
- package/index.ts +3 -16
- package/ios/HediaRecommendationScreen/Info.plist +80 -57
- package/ios/HediaRecommendationScreen.xcodeproj/project.pbxproj +1085 -807
- package/ios/HediaRecommendationScreen.xcworkspace/contents.xcworkspacedata +10 -0
- package/ios/HediaRecommendationScreen.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/Podfile +106 -104
- package/ios/Podfile.lock +474 -0
- package/jest.mock.js +1 -0
- package/package.json +9 -2
- package/src/RecommendationScreen.d.ts +19 -5
- package/src/RecommendationScreen.jsx +69 -33
- package/src/RecommendationScreen.tsx +130 -60
- package/src/assets/activity/Cyclist.png +0 -0
- package/src/assets/activity/Other.png +0 -0
- package/src/assets/activity/Runner.png +0 -0
- package/src/assets/activity/Swimmer.png +0 -0
- package/src/assets/activity/Walk.png +0 -0
- package/src/components/Header.d.ts +1 -5
- package/src/components/Header.jsx +4 -9
- package/src/components/Header.tsx +7 -14
- package/src/components/HediaRecommendationModal.d.ts +26 -0
- package/src/components/HediaRecommendationModal.jsx +207 -0
- package/src/components/HediaRecommendationModal.tsx +231 -0
- package/src/components/InfoBars.jsx +1 -1
- package/src/components/InfoBars.tsx +3 -3
- package/src/components/InvisibleNumberInput.tsx +7 -7
- package/src/components/RecentInsulin.jsx +5 -4
- package/src/components/RecentInsulin.tsx +6 -5
- package/src/components/RecommendedCarbs.jsx +17 -17
- package/src/components/RecommendedCarbs.tsx +24 -24
- package/src/components/RecommendedInsulin.jsx +12 -9
- package/src/components/RecommendedInsulin.tsx +18 -15
- package/src/components/Remeasure.jsx +7 -5
- package/src/components/Remeasure.tsx +15 -13
- package/src/components/TransferToLogbook.jsx +4 -3
- package/src/components/TransferToLogbook.tsx +6 -4
- package/src/components/activity/Activity.d.ts +11 -0
- package/src/components/activity/Activity.jsx +68 -0
- package/src/components/activity/Activity.tsx +74 -0
- package/src/components/activity/ActivityIcon.d.ts +7 -0
- package/src/components/activity/ActivityIcon.jsx +50 -0
- package/src/components/activity/ActivityIcon.tsx +52 -0
- package/src/components/activity/ActivityIntensity.d.ts +5 -0
- package/src/components/activity/ActivityIntensity.jsx +67 -0
- package/src/components/activity/ActivityIntensity.tsx +66 -0
- package/src/components/mood/Emotion.d.ts +12 -0
- package/src/components/{Emotion.jsx → mood/Emotion.jsx} +12 -16
- package/src/components/mood/Emotion.tsx +64 -0
- package/src/components/{MoodIcon.d.ts → mood/MoodIcon.d.ts} +1 -1
- package/src/components/{MoodIcon.jsx → mood/MoodIcon.jsx} +15 -15
- package/src/components/{MoodIcon.tsx → mood/MoodIcon.tsx} +17 -17
- package/src/locale/da/messages.js +1 -1
- package/src/locale/da/messages.po +191 -49
- package/src/locale/en/messages.js +1 -1
- package/src/locale/en/messages.po +193 -51
- package/src/types/enum.d.ts +48 -6
- package/src/types/enum.js +53 -7
- package/src/types/enum.ts +48 -3
- package/src/types/types.d.ts +18 -1
- package/src/types/types.ts +21 -1
- package/src/utils/AttentionMessages.d.ts +21 -0
- package/src/utils/AttentionMessages.js +62 -0
- package/src/utils/AttentionMessages.ts +59 -0
- package/src/utils/Constants.d.ts +16 -1
- package/src/utils/Constants.js +16 -2
- package/src/utils/Constants.ts +20 -1
- package/src/utils/RecommendationError.d.ts +18 -6
- package/src/utils/RecommendationError.js +23 -7
- package/src/utils/RecommendationError.ts +114 -28
- package/src/utils/RecommendationUtils.d.ts +12 -0
- package/src/utils/RecommendationUtils.js +118 -0
- package/src/utils/RecommendationUtils.ts +128 -0
- package/src/utils/Utils.d.ts +3 -1
- package/src/utils/Utils.js +6 -0
- package/src/utils/Utils.ts +13 -5
- package/src/utils/Validations.d.ts +22 -0
- package/src/utils/Validations.js +175 -0
- package/src/utils/Validations.ts +210 -0
- package/src/components/Emotion.d.ts +0 -14
- package/src/components/Emotion.tsx +0 -70
- /package/src/assets/{happy.png → mood/happy.png} +0 -0
- /package/src/assets/{happy_active.png → mood/happy_active.png} +0 -0
- /package/src/assets/{neutral.png → mood/neutral.png} +0 -0
- /package/src/assets/{neutral_active.png → mood/neutral_active.png} +0 -0
- /package/src/assets/{sad.png → mood/sad.png} +0 -0
- /package/src/assets/{sad_active.png → mood/sad_active.png} +0 -0
- /package/src/assets/{semi_happy.png → mood/semi_happy.png} +0 -0
- /package/src/assets/{semi_happy_active.png → mood/semi_happy_active.png} +0 -0
- /package/src/assets/{semi_sad.png → mood/semi_sad.png} +0 -0
- /package/src/assets/{semi_sad_active.png → mood/semi_sad_active.png} +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { IRecommendationParams } from "@hedia/recommendation-calculator";
|
|
2
|
+
import moment from "moment";
|
|
3
|
+
import { IRecommendationProps } from "../RecommendationScreen";
|
|
4
|
+
import { BgLevel, RecommendationReminders } from "../types/enum";
|
|
5
|
+
import { IActivity, logbookEntry } from "../types/types";
|
|
6
|
+
import { addPostponeActivityMessage, AttentionMessage, Messages } from "./AttentionMessages";
|
|
7
|
+
import { SEVERE_HYPERGLYCEMIA_START_MMOL } from "./Constants";
|
|
8
|
+
import { CurrentBGLError } from "./RecommendationError";
|
|
9
|
+
|
|
10
|
+
export function getBGLevel(currentBGL: number, latestLogbookFrom6Hours: logbookEntry): BgLevel {
|
|
11
|
+
if (currentBGL === null) {
|
|
12
|
+
return BgLevel.BGLevelNotProvided;
|
|
13
|
+
}
|
|
14
|
+
if (currentBGL >= 1.1 && currentBGL <= 2) {
|
|
15
|
+
return BgLevel.SevereHypoglycemia;
|
|
16
|
+
}
|
|
17
|
+
if (currentBGL > 2 && currentBGL <= 3.5) {
|
|
18
|
+
return BgLevel.Hypoglycemia;
|
|
19
|
+
}
|
|
20
|
+
if (currentBGL > 3.5 && currentBGL <= 4) {
|
|
21
|
+
return BgLevel.MildHypoglycemia;
|
|
22
|
+
}
|
|
23
|
+
if (currentBGL > 4 && currentBGL < 5) {
|
|
24
|
+
return BgLevel.NormoglycemiaUnder5MMOL;
|
|
25
|
+
}
|
|
26
|
+
if (currentBGL >= 5 && currentBGL <= 7) {
|
|
27
|
+
return BgLevel.Normoglycemia;
|
|
28
|
+
}
|
|
29
|
+
if (currentBGL > 7 && currentBGL < 15) {
|
|
30
|
+
return BgLevel.MildHyperglycemia;
|
|
31
|
+
}
|
|
32
|
+
if (currentBGL > 15 && currentBGL <= 33.3 && isSevereHyperglycemia(latestLogbookFrom6Hours)) {
|
|
33
|
+
return BgLevel.SevereHyperglycemia;
|
|
34
|
+
}
|
|
35
|
+
if (currentBGL >= 15 && currentBGL <= 33.3) {
|
|
36
|
+
return BgLevel.Hyperglycemia;
|
|
37
|
+
}
|
|
38
|
+
return BgLevel.UnsupportedBGLevel;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getReminder(
|
|
42
|
+
bgLevel: BgLevel,
|
|
43
|
+
carbohydrates: number,
|
|
44
|
+
userReminder: number,
|
|
45
|
+
activity: IRecommendationParams["activity"],
|
|
46
|
+
): number {
|
|
47
|
+
const reminder = userReminder === undefined ? RecommendationReminders.HediaReminderDefault : userReminder;
|
|
48
|
+
switch (bgLevel) {
|
|
49
|
+
case BgLevel.BGLevelNotProvided:
|
|
50
|
+
return RecommendationReminders.ReminderOff;
|
|
51
|
+
|
|
52
|
+
case BgLevel.SevereHypoglycemia:
|
|
53
|
+
case BgLevel.Hypoglycemia:
|
|
54
|
+
case BgLevel.MildHypoglycemia:
|
|
55
|
+
return RecommendationReminders.Reminder15Minutes;
|
|
56
|
+
|
|
57
|
+
case BgLevel.NormoglycemiaUnder5MMOL:
|
|
58
|
+
case BgLevel.Normoglycemia:
|
|
59
|
+
case BgLevel.MildHyperglycemia:
|
|
60
|
+
return carbohydrates || activity ? reminder : RecommendationReminders.ReminderOff;
|
|
61
|
+
|
|
62
|
+
case BgLevel.Hyperglycemia:
|
|
63
|
+
case BgLevel.SevereHyperglycemia:
|
|
64
|
+
return isActivityWithin15Minutes(activity)
|
|
65
|
+
? RecommendationReminders.Reminder15Minutes
|
|
66
|
+
: RecommendationReminders.Reminder60Minutes;
|
|
67
|
+
|
|
68
|
+
default:
|
|
69
|
+
throw CurrentBGLError();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function getAttentionMessage(bgLevel: BgLevel, activity: IRecommendationParams["activity"]): AttentionMessage {
|
|
74
|
+
switch (bgLevel) {
|
|
75
|
+
case BgLevel.BGLevelNotProvided:
|
|
76
|
+
case BgLevel.Normoglycemia:
|
|
77
|
+
case BgLevel.MildHyperglycemia:
|
|
78
|
+
return undefined;
|
|
79
|
+
|
|
80
|
+
case BgLevel.NormoglycemiaUnder5MMOL:
|
|
81
|
+
return isActivityWithin15Minutes(activity) ? AttentionMessage.NormoglycemiaActivityUnder5MMOL() : undefined;
|
|
82
|
+
|
|
83
|
+
case BgLevel.SevereHypoglycemia:
|
|
84
|
+
case BgLevel.Hypoglycemia:
|
|
85
|
+
case BgLevel.MildHypoglycemia:
|
|
86
|
+
return isActivityWithin15Minutes(activity)
|
|
87
|
+
? addPostponeActivityMessage(AttentionMessage[BgLevel[bgLevel]]())
|
|
88
|
+
: AttentionMessage[BgLevel[bgLevel]]();
|
|
89
|
+
|
|
90
|
+
case BgLevel.Hyperglycemia:
|
|
91
|
+
return isActivityWithin15Minutes(activity) ? AttentionMessage.HyperglycemiaActivity() : undefined;
|
|
92
|
+
|
|
93
|
+
case BgLevel.SevereHyperglycemia:
|
|
94
|
+
return isActivityWithin15Minutes(activity)
|
|
95
|
+
? AttentionMessage.SevereHyperglycemiaActivity()
|
|
96
|
+
: AttentionMessage.SevereHyperglycemia();
|
|
97
|
+
default:
|
|
98
|
+
throw CurrentBGLError();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isSevereHyperglycemia(latestLogbookFrom6Hours: logbookEntry): boolean {
|
|
103
|
+
return latestLogbookFrom6Hours?.blood_glucose_millimolar > SEVERE_HYPERGLYCEMIA_START_MMOL;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function isActivityWithin15Minutes(activity: IRecommendationParams["activity"]): boolean {
|
|
107
|
+
const minutes = activity?.activityDuration;
|
|
108
|
+
return moment
|
|
109
|
+
.utc(activity?.activityDate)
|
|
110
|
+
.isBetween(moment.utc().subtract(minutes, `minutes`), moment.utc().add(15, `minutes`));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function getLimitationMessage(wasLimited: boolean, activityReduction: number): Messages {
|
|
114
|
+
const message = activityReduction
|
|
115
|
+
? Messages.RecommendationWasLimitedActivity(activityReduction)
|
|
116
|
+
: Messages.RecommendationWasLimited();
|
|
117
|
+
return wasLimited ? message : undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getParams(props: IRecommendationProps): IRecommendationParams & IActivity {
|
|
121
|
+
const { calculatorParams } = props;
|
|
122
|
+
const activityTarget = calculatorParams.activity?.activitySettings?.target;
|
|
123
|
+
const paramsWithAssignedCurrentBGL = {
|
|
124
|
+
...calculatorParams,
|
|
125
|
+
currentBGL: activityTarget ?? calculatorParams.targetBGL,
|
|
126
|
+
};
|
|
127
|
+
return calculatorParams.currentBGL === null ? paramsWithAssignedCurrentBGL : calculatorParams;
|
|
128
|
+
}
|
package/src/utils/Utils.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { InjectionMethod } from "../types/enum";
|
|
2
|
+
import { IInterval } from "../types/types";
|
|
2
3
|
export declare class Utils {
|
|
3
|
-
static getRounding(method: InjectionMethod):
|
|
4
|
+
static getRounding(method: InjectionMethod): number;
|
|
4
5
|
static roundValue(value: number, injectMethod: InjectionMethod): number;
|
|
6
|
+
static isInClosedInterval(value: number, interval: IInterval): boolean;
|
|
5
7
|
}
|
package/src/utils/Utils.js
CHANGED
|
@@ -20,5 +20,11 @@ class Utils {
|
|
|
20
20
|
const rounded = Math.round(value * rounding) / rounding;
|
|
21
21
|
return rounded;
|
|
22
22
|
}
|
|
23
|
+
static isInClosedInterval(value, interval) {
|
|
24
|
+
if (value === null) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return value >= interval.min && value <= interval.max;
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
exports.Utils = Utils;
|
package/src/utils/Utils.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { InjectionMethod } from "../types/enum";
|
|
2
|
+
import { IInterval } from "../types/types";
|
|
2
3
|
|
|
3
4
|
export class Utils {
|
|
4
|
-
public static getRounding(method: InjectionMethod) {
|
|
5
|
+
public static getRounding(method: InjectionMethod): number {
|
|
5
6
|
switch (method) {
|
|
6
7
|
case InjectionMethod.PenWhole:
|
|
7
8
|
return 1;
|
|
@@ -17,10 +18,17 @@ export class Utils {
|
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
public static roundValue(value: number, injectMethod: InjectionMethod) {
|
|
21
|
-
const rounding = Utils.getRounding(injectMethod);
|
|
22
|
-
|
|
23
|
-
const rounded = Math.round(value * rounding) / rounding;
|
|
21
|
+
public static roundValue(value: number, injectMethod: InjectionMethod): number {
|
|
22
|
+
const rounding: number = Utils.getRounding(injectMethod);
|
|
23
|
+
const rounded: number = Math.round(value * rounding) / rounding;
|
|
24
24
|
return rounded;
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
public static isInClosedInterval(value: number, interval: IInterval): boolean {
|
|
28
|
+
if (value === null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return value >= interval.min && value <= interval.max;
|
|
33
|
+
}
|
|
26
34
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IRecommendationParams } from "@hedia/recommendation-calculator";
|
|
2
|
+
import { IRecentBolus } from "@hedia/recommendation-calculator/src/RecommendationCalculator";
|
|
3
|
+
import { IRecommendationProps } from "../RecommendationScreen";
|
|
4
|
+
import { BGUnit, InjectionMethod, Languages } from "../types/enum";
|
|
5
|
+
export declare function validateParams(props: IRecommendationProps): void;
|
|
6
|
+
export declare function checkLanguage(language: Languages): void;
|
|
7
|
+
export declare function checkInjectionMethod(injectionMethod: InjectionMethod): void;
|
|
8
|
+
export declare function checkUnit(unit: BGUnit): void;
|
|
9
|
+
export declare function checkUserReminder(userReminder: number): void;
|
|
10
|
+
export declare function checkActivity(activity: IRecommendationParams["activity"]): void;
|
|
11
|
+
export declare function checkRecentBolusesInsulinDosis(recentBoluses: Array<IRecentBolus>): void;
|
|
12
|
+
export declare function checkRecentBolusesSecondsPassed(recentBoluses: Array<IRecentBolus>): void;
|
|
13
|
+
export declare function checkActivityDuration(activityDuration: IRecommendationParams["activity"]["activityDuration"]): void;
|
|
14
|
+
export declare function checkActivityIntensity(activityIntensity: IRecommendationParams["activity"]["activityIntensity"]): void;
|
|
15
|
+
export declare function checkActivityDate(activity: IRecommendationParams["activity"]): void;
|
|
16
|
+
export declare function checkActivitySettings(activitySettings: IRecommendationParams["activity"]["activitySettings"]): void;
|
|
17
|
+
export declare function checkActivityTargetBGL(activitySettings: IRecommendationParams["activity"]["activitySettings"]["target"]): void;
|
|
18
|
+
export declare function checkCurrentBGL(currentBGL: number): void;
|
|
19
|
+
export declare function checkTargetBGL(targetBGL: number): void;
|
|
20
|
+
export declare function checkInsulinSensitivity(insulinSensitivity: number): void;
|
|
21
|
+
export declare function checkInsulinToCarbRatio(insulinToCarbRatio: number): void;
|
|
22
|
+
export declare function checkCarbohydrates(carbohydrates: number): void;
|
|
@@ -0,0 +1,175 @@
|
|
|
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
|
+
exports.checkCarbohydrates = exports.checkInsulinToCarbRatio = exports.checkInsulinSensitivity = exports.checkTargetBGL = exports.checkCurrentBGL = exports.checkActivityTargetBGL = exports.checkActivitySettings = exports.checkActivityDate = exports.checkActivityIntensity = exports.checkActivityDuration = exports.checkRecentBolusesSecondsPassed = exports.checkRecentBolusesInsulinDosis = exports.checkActivity = exports.checkUserReminder = exports.checkUnit = exports.checkInjectionMethod = exports.checkLanguage = exports.validateParams = void 0;
|
|
7
|
+
const RecommendationCalculator_1 = require("@hedia/recommendation-calculator/src/RecommendationCalculator");
|
|
8
|
+
const moment_1 = __importDefault(require("moment"));
|
|
9
|
+
const enum_1 = require("../types/enum");
|
|
10
|
+
const Constants_1 = require("./Constants");
|
|
11
|
+
const RecommendationError_1 = require("./RecommendationError");
|
|
12
|
+
const Utils_1 = require("./Utils");
|
|
13
|
+
function validateParams(props) {
|
|
14
|
+
checkCalculatorParams(props.calculatorParams);
|
|
15
|
+
checkUnit(props.units);
|
|
16
|
+
checkInjectionMethod(props.injectionMethod);
|
|
17
|
+
checkUserReminder(props.userReminder);
|
|
18
|
+
checkLanguage(props.language);
|
|
19
|
+
}
|
|
20
|
+
exports.validateParams = validateParams;
|
|
21
|
+
function checkLanguage(language) {
|
|
22
|
+
switch (language) {
|
|
23
|
+
case enum_1.Languages.da:
|
|
24
|
+
case enum_1.Languages.en:
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
throw RecommendationError_1.LanguageError();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.checkLanguage = checkLanguage;
|
|
31
|
+
function checkInjectionMethod(injectionMethod) {
|
|
32
|
+
switch (injectionMethod) {
|
|
33
|
+
case enum_1.InjectionMethod.PenHalf:
|
|
34
|
+
case enum_1.InjectionMethod.PenWhole:
|
|
35
|
+
case enum_1.InjectionMethod.Pump:
|
|
36
|
+
break;
|
|
37
|
+
default:
|
|
38
|
+
throw RecommendationError_1.InjectionMethodError();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.checkInjectionMethod = checkInjectionMethod;
|
|
42
|
+
function checkUnit(unit) {
|
|
43
|
+
switch (unit) {
|
|
44
|
+
case enum_1.BGUnit.MG_DL:
|
|
45
|
+
case enum_1.BGUnit.MMOL_L:
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
throw RecommendationError_1.UnitError();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.checkUnit = checkUnit;
|
|
52
|
+
function checkUserReminder(userReminder) {
|
|
53
|
+
if (!Utils_1.Utils.isInClosedInterval(userReminder, Constants_1.REMINDER_HOURS_LIMITS)) {
|
|
54
|
+
throw RecommendationError_1.UserReminderError();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.checkUserReminder = checkUserReminder;
|
|
58
|
+
function checkCalculatorParams(calculatorParams) {
|
|
59
|
+
checkActivity(calculatorParams.activity);
|
|
60
|
+
checkCarbohydrates(calculatorParams.carbohydrates);
|
|
61
|
+
checkCurrentBGL(calculatorParams.currentBGL);
|
|
62
|
+
checkTargetBGL(calculatorParams.targetBGL);
|
|
63
|
+
checkInsulinToCarbRatio(calculatorParams.carbohydrateRatio);
|
|
64
|
+
checkInsulinSensitivity(calculatorParams.insulinSensitivity);
|
|
65
|
+
checkRecentBolusesInsulinDosis(calculatorParams.recentBoluses);
|
|
66
|
+
checkRecentBolusesSecondsPassed(calculatorParams.recentBoluses);
|
|
67
|
+
}
|
|
68
|
+
function checkActivity(activity) {
|
|
69
|
+
if (activity) {
|
|
70
|
+
checkActivityDate(activity);
|
|
71
|
+
checkActivityDuration(activity.activityDuration);
|
|
72
|
+
checkActivityIntensity(activity.activityIntensity);
|
|
73
|
+
checkActivitySettings(activity.activitySettings);
|
|
74
|
+
checkActivityTargetBGL(activity.activitySettings.target);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.checkActivity = checkActivity;
|
|
78
|
+
function checkRecentBolusesInsulinDosis(recentBoluses) {
|
|
79
|
+
recentBoluses.forEach((bolus) => {
|
|
80
|
+
if (!Utils_1.Utils.isInClosedInterval(bolus.insulinDosis, Constants_1.INSULIN_DOSIS_LIMITS)) {
|
|
81
|
+
throw RecommendationError_1.BolusInsulinDosisError();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
exports.checkRecentBolusesInsulinDosis = checkRecentBolusesInsulinDosis;
|
|
86
|
+
function checkRecentBolusesSecondsPassed(recentBoluses) {
|
|
87
|
+
recentBoluses.forEach((bolus) => {
|
|
88
|
+
if (!Utils_1.Utils.isInClosedInterval(bolus.secondsPassed, Constants_1.BOLUS_SECONDS_PASSED_LIMITS)) {
|
|
89
|
+
throw RecommendationError_1.BolusInsulinSecondsPassedError();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
exports.checkRecentBolusesSecondsPassed = checkRecentBolusesSecondsPassed;
|
|
94
|
+
function checkActivityDuration(activityDuration) {
|
|
95
|
+
if (!Utils_1.Utils.isInClosedInterval(activityDuration, Constants_1.ACTIVITY_DURATION_MINUTES_LIMITS)) {
|
|
96
|
+
throw RecommendationError_1.ActivityDurationError();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.checkActivityDuration = checkActivityDuration;
|
|
100
|
+
function checkActivityIntensity(activityIntensity) {
|
|
101
|
+
switch (activityIntensity) {
|
|
102
|
+
case RecommendationCalculator_1.ActivityIntensity.Hard:
|
|
103
|
+
case RecommendationCalculator_1.ActivityIntensity.Moderate:
|
|
104
|
+
case RecommendationCalculator_1.ActivityIntensity.Light:
|
|
105
|
+
case RecommendationCalculator_1.ActivityIntensity.Post:
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
throw RecommendationError_1.ActivityIntensityError();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.checkActivityIntensity = checkActivityIntensity;
|
|
112
|
+
function checkActivityDate(activity) {
|
|
113
|
+
const maximumDate = moment_1.default
|
|
114
|
+
.utc(activity.activityDate)
|
|
115
|
+
.add(activity.activityDuration + Constants_1.ONE_HOUR_MINUTES * 4, `minutes`);
|
|
116
|
+
if (!moment_1.default.utc().isBefore(maximumDate)) {
|
|
117
|
+
throw RecommendationError_1.ActivityDateError();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.checkActivityDate = checkActivityDate;
|
|
121
|
+
function checkActivitySettings(activitySettings) {
|
|
122
|
+
for (const intensity of Object.keys(activitySettings)) {
|
|
123
|
+
for (const interval of Object.keys(activitySettings[intensity])) {
|
|
124
|
+
const value = activitySettings[intensity][interval];
|
|
125
|
+
const isInInterval = Utils_1.Utils.isInClosedInterval(value, Constants_1.ACTIVITY_SETTINGS_INTERVAL_LIMITS);
|
|
126
|
+
if (intensity === RecommendationCalculator_1.ActivityIntensity.Hard.toLowerCase() && interval === enum_1.ActivityInterval.fromFortysix) {
|
|
127
|
+
if (!isInInterval && value !== null) {
|
|
128
|
+
throw RecommendationError_1.ActivitySettingsError();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (!isInInterval) {
|
|
132
|
+
throw RecommendationError_1.ActivitySettingsError();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.checkActivitySettings = checkActivitySettings;
|
|
138
|
+
function checkActivityTargetBGL(activitySettings) {
|
|
139
|
+
if (!Utils_1.Utils.isInClosedInterval(activitySettings, Constants_1.ACTIVITY_TARGET_BGL_MMOL_LIMITS)) {
|
|
140
|
+
throw RecommendationError_1.ActivityTargetBGLError();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.checkActivityTargetBGL = checkActivityTargetBGL;
|
|
144
|
+
function checkCurrentBGL(currentBGL) {
|
|
145
|
+
if (currentBGL !== null) {
|
|
146
|
+
if (!Utils_1.Utils.isInClosedInterval(currentBGL, Constants_1.CURRENT_BGL_MMOL_LIMITS)) {
|
|
147
|
+
throw RecommendationError_1.CurrentBGLError();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.checkCurrentBGL = checkCurrentBGL;
|
|
152
|
+
function checkTargetBGL(targetBGL) {
|
|
153
|
+
if (!Utils_1.Utils.isInClosedInterval(targetBGL, Constants_1.TARGET_BGL_MMOL_LIMITS)) {
|
|
154
|
+
throw RecommendationError_1.TargetBGLError();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.checkTargetBGL = checkTargetBGL;
|
|
158
|
+
function checkInsulinSensitivity(insulinSensitivity) {
|
|
159
|
+
if (!Utils_1.Utils.isInClosedInterval(insulinSensitivity, Constants_1.INSULIN_SENSITIVITY_MMOL_LIMITS)) {
|
|
160
|
+
throw RecommendationError_1.InsulinSensitivityError();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.checkInsulinSensitivity = checkInsulinSensitivity;
|
|
164
|
+
function checkInsulinToCarbRatio(insulinToCarbRatio) {
|
|
165
|
+
if (!Utils_1.Utils.isInClosedInterval(insulinToCarbRatio, Constants_1.INSULIN_TO_CARBS_RATIO_LIMITS)) {
|
|
166
|
+
throw RecommendationError_1.InsulinToCarbsRatioError();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.checkInsulinToCarbRatio = checkInsulinToCarbRatio;
|
|
170
|
+
function checkCarbohydrates(carbohydrates) {
|
|
171
|
+
if (!Utils_1.Utils.isInClosedInterval(carbohydrates, Constants_1.CARBOHYDRATES_LIMTS)) {
|
|
172
|
+
throw RecommendationError_1.CarbohydrateLimitError();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
exports.checkCarbohydrates = checkCarbohydrates;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { IRecommendationParams } from "@hedia/recommendation-calculator";
|
|
2
|
+
import {
|
|
3
|
+
ActivityIntensity,
|
|
4
|
+
IActivityInterval,
|
|
5
|
+
IActivitySettings,
|
|
6
|
+
IRecentBolus,
|
|
7
|
+
} from "@hedia/recommendation-calculator/src/RecommendationCalculator";
|
|
8
|
+
import moment from "moment";
|
|
9
|
+
import { IRecommendationProps } from "../RecommendationScreen";
|
|
10
|
+
import { ActivityInterval, BGUnit, InjectionMethod, Languages } from "../types/enum";
|
|
11
|
+
import {
|
|
12
|
+
ACTIVITY_DURATION_MINUTES_LIMITS,
|
|
13
|
+
ACTIVITY_SETTINGS_INTERVAL_LIMITS,
|
|
14
|
+
ACTIVITY_TARGET_BGL_MMOL_LIMITS,
|
|
15
|
+
BOLUS_SECONDS_PASSED_LIMITS,
|
|
16
|
+
CARBOHYDRATES_LIMTS,
|
|
17
|
+
CURRENT_BGL_MMOL_LIMITS,
|
|
18
|
+
INSULIN_DOSIS_LIMITS,
|
|
19
|
+
INSULIN_SENSITIVITY_MMOL_LIMITS,
|
|
20
|
+
INSULIN_TO_CARBS_RATIO_LIMITS,
|
|
21
|
+
ONE_HOUR_MINUTES,
|
|
22
|
+
REMINDER_HOURS_LIMITS,
|
|
23
|
+
TARGET_BGL_MMOL_LIMITS,
|
|
24
|
+
} from "./Constants";
|
|
25
|
+
import {
|
|
26
|
+
ActivityDateError,
|
|
27
|
+
ActivityDurationError,
|
|
28
|
+
ActivityIntensityError,
|
|
29
|
+
ActivitySettingsError,
|
|
30
|
+
ActivityTargetBGLError,
|
|
31
|
+
BolusInsulinDosisError,
|
|
32
|
+
BolusInsulinSecondsPassedError,
|
|
33
|
+
CarbohydrateLimitError,
|
|
34
|
+
CurrentBGLError,
|
|
35
|
+
InjectionMethodError,
|
|
36
|
+
InsulinSensitivityError,
|
|
37
|
+
InsulinToCarbsRatioError,
|
|
38
|
+
LanguageError,
|
|
39
|
+
TargetBGLError,
|
|
40
|
+
UnitError,
|
|
41
|
+
UserReminderError,
|
|
42
|
+
} from "./RecommendationError";
|
|
43
|
+
import { Utils } from "./Utils";
|
|
44
|
+
|
|
45
|
+
export function validateParams(props: IRecommendationProps): void {
|
|
46
|
+
checkCalculatorParams(props.calculatorParams);
|
|
47
|
+
checkUnit(props.units);
|
|
48
|
+
checkInjectionMethod(props.injectionMethod);
|
|
49
|
+
checkUserReminder(props.userReminder);
|
|
50
|
+
checkLanguage(props.language);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function checkLanguage(language: Languages): void {
|
|
54
|
+
switch (language) {
|
|
55
|
+
case Languages.da:
|
|
56
|
+
case Languages.en:
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
throw LanguageError();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function checkInjectionMethod(injectionMethod: InjectionMethod): void {
|
|
64
|
+
switch (injectionMethod) {
|
|
65
|
+
case InjectionMethod.PenHalf:
|
|
66
|
+
case InjectionMethod.PenWhole:
|
|
67
|
+
case InjectionMethod.Pump:
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
throw InjectionMethodError();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function checkUnit(unit: BGUnit): void {
|
|
75
|
+
switch (unit) {
|
|
76
|
+
case BGUnit.MG_DL:
|
|
77
|
+
case BGUnit.MMOL_L:
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
throw UnitError();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function checkUserReminder(userReminder: number): void {
|
|
85
|
+
if (!Utils.isInClosedInterval(userReminder, REMINDER_HOURS_LIMITS)) {
|
|
86
|
+
throw UserReminderError();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function checkCalculatorParams(calculatorParams: IRecommendationProps["calculatorParams"]): void {
|
|
91
|
+
checkActivity(calculatorParams.activity);
|
|
92
|
+
checkCarbohydrates(calculatorParams.carbohydrates);
|
|
93
|
+
checkCurrentBGL(calculatorParams.currentBGL);
|
|
94
|
+
checkTargetBGL(calculatorParams.targetBGL);
|
|
95
|
+
checkInsulinToCarbRatio(calculatorParams.carbohydrateRatio);
|
|
96
|
+
checkInsulinSensitivity(calculatorParams.insulinSensitivity);
|
|
97
|
+
checkRecentBolusesInsulinDosis(calculatorParams.recentBoluses);
|
|
98
|
+
checkRecentBolusesSecondsPassed(calculatorParams.recentBoluses);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function checkActivity(activity: IRecommendationParams["activity"]): void {
|
|
102
|
+
if (activity) {
|
|
103
|
+
checkActivityDate(activity);
|
|
104
|
+
checkActivityDuration(activity.activityDuration);
|
|
105
|
+
checkActivityIntensity(activity.activityIntensity);
|
|
106
|
+
checkActivitySettings(activity.activitySettings);
|
|
107
|
+
checkActivityTargetBGL(activity.activitySettings.target);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function checkRecentBolusesInsulinDosis(recentBoluses: Array<IRecentBolus>): void {
|
|
112
|
+
recentBoluses.forEach((bolus: IRecentBolus): void => {
|
|
113
|
+
if (!Utils.isInClosedInterval(bolus.insulinDosis, INSULIN_DOSIS_LIMITS)) {
|
|
114
|
+
throw BolusInsulinDosisError();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function checkRecentBolusesSecondsPassed(recentBoluses: Array<IRecentBolus>): void {
|
|
120
|
+
recentBoluses.forEach((bolus: IRecentBolus): void => {
|
|
121
|
+
if (!Utils.isInClosedInterval(bolus.secondsPassed, BOLUS_SECONDS_PASSED_LIMITS)) {
|
|
122
|
+
throw BolusInsulinSecondsPassedError();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function checkActivityDuration(activityDuration: IRecommendationParams["activity"]["activityDuration"]): void {
|
|
128
|
+
if (!Utils.isInClosedInterval(activityDuration, ACTIVITY_DURATION_MINUTES_LIMITS)) {
|
|
129
|
+
throw ActivityDurationError();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function checkActivityIntensity(
|
|
134
|
+
activityIntensity: IRecommendationParams["activity"]["activityIntensity"],
|
|
135
|
+
): void {
|
|
136
|
+
switch (activityIntensity) {
|
|
137
|
+
case ActivityIntensity.Hard:
|
|
138
|
+
case ActivityIntensity.Moderate:
|
|
139
|
+
case ActivityIntensity.Light:
|
|
140
|
+
case ActivityIntensity.Post:
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
throw ActivityIntensityError();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function checkActivityDate(activity: IRecommendationParams["activity"]): void {
|
|
147
|
+
const maximumDate = moment
|
|
148
|
+
.utc(activity.activityDate)
|
|
149
|
+
.add(activity.activityDuration + ONE_HOUR_MINUTES * 4, `minutes`);
|
|
150
|
+
if (!moment.utc().isBefore(maximumDate)) {
|
|
151
|
+
throw ActivityDateError();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type intensityType = Omit<IActivitySettings, "target">;
|
|
156
|
+
export function checkActivitySettings(activitySettings: IRecommendationParams["activity"]["activitySettings"]): void {
|
|
157
|
+
for (const intensity of Object.keys(activitySettings) as Array<keyof intensityType>) {
|
|
158
|
+
for (const interval of Object.keys(activitySettings[intensity]) as Array<keyof IActivityInterval>) {
|
|
159
|
+
const value: number = activitySettings[intensity][interval];
|
|
160
|
+
const isInInterval: boolean = Utils.isInClosedInterval(value, ACTIVITY_SETTINGS_INTERVAL_LIMITS);
|
|
161
|
+
if (intensity === ActivityIntensity.Hard.toLowerCase() && interval === ActivityInterval.fromFortysix) {
|
|
162
|
+
if (!isInInterval && value !== null) {
|
|
163
|
+
throw ActivitySettingsError();
|
|
164
|
+
}
|
|
165
|
+
} else if (!isInInterval) {
|
|
166
|
+
throw ActivitySettingsError();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function checkActivityTargetBGL(
|
|
173
|
+
activitySettings: IRecommendationParams["activity"]["activitySettings"]["target"],
|
|
174
|
+
): void {
|
|
175
|
+
if (!Utils.isInClosedInterval(activitySettings, ACTIVITY_TARGET_BGL_MMOL_LIMITS)) {
|
|
176
|
+
throw ActivityTargetBGLError();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function checkCurrentBGL(currentBGL: number): void {
|
|
181
|
+
if (currentBGL !== null) {
|
|
182
|
+
if (!Utils.isInClosedInterval(currentBGL, CURRENT_BGL_MMOL_LIMITS)) {
|
|
183
|
+
throw CurrentBGLError();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function checkTargetBGL(targetBGL: number): void {
|
|
189
|
+
if (!Utils.isInClosedInterval(targetBGL, TARGET_BGL_MMOL_LIMITS)) {
|
|
190
|
+
throw TargetBGLError();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function checkInsulinSensitivity(insulinSensitivity: number): void {
|
|
195
|
+
if (!Utils.isInClosedInterval(insulinSensitivity, INSULIN_SENSITIVITY_MMOL_LIMITS)) {
|
|
196
|
+
throw InsulinSensitivityError();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function checkInsulinToCarbRatio(insulinToCarbRatio: number): void {
|
|
201
|
+
if (!Utils.isInClosedInterval(insulinToCarbRatio, INSULIN_TO_CARBS_RATIO_LIMITS)) {
|
|
202
|
+
throw InsulinToCarbsRatioError();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function checkCarbohydrates(carbohydrates: number): void {
|
|
207
|
+
if (!Utils.isInClosedInterval(carbohydrates, CARBOHYDRATES_LIMTS)) {
|
|
208
|
+
throw CarbohydrateLimitError();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { MoodEnum } from "../types/enum";
|
|
3
|
-
interface IProps {
|
|
4
|
-
moodSelected(mood: MoodEnum | 0): void;
|
|
5
|
-
}
|
|
6
|
-
interface IState {
|
|
7
|
-
selected: MoodEnum | 0;
|
|
8
|
-
}
|
|
9
|
-
export default class Emotion extends React.Component<IProps, IState> {
|
|
10
|
-
state: IState;
|
|
11
|
-
handleIconPress: (selected: number, toggle: boolean) => void;
|
|
12
|
-
render(): JSX.Element;
|
|
13
|
-
}
|
|
14
|
-
export {};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Dimensions, Image, StyleSheet, Text, View } from "react-native";
|
|
3
|
-
import { i18n } from "../locale/i18nUtils";
|
|
4
|
-
import { MoodEnum } from "../types/enum";
|
|
5
|
-
import MoodIcon from "./MoodIcon";
|
|
6
|
-
|
|
7
|
-
interface IProps {
|
|
8
|
-
moodSelected(mood: MoodEnum | 0): void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type value = keyof typeof MoodEnum;
|
|
12
|
-
|
|
13
|
-
interface IState {
|
|
14
|
-
selected: MoodEnum | 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default class Emotion extends React.Component<IProps, IState> {
|
|
18
|
-
public state: IState = {
|
|
19
|
-
selected: 0,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
public handleIconPress = (selected: number, toggle: boolean) => {
|
|
23
|
-
const select = toggle ? selected : 0;
|
|
24
|
-
this.setState({
|
|
25
|
-
selected: select,
|
|
26
|
-
});
|
|
27
|
-
this.props.moodSelected(select);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
public render() {
|
|
31
|
-
const values = Object.values(MoodEnum).filter((val) => isNaN(Number(val))) as Array<value>;
|
|
32
|
-
|
|
33
|
-
const mapped = values.map((key) => {
|
|
34
|
-
const moodValue = MoodEnum[key];
|
|
35
|
-
return (
|
|
36
|
-
<MoodIcon
|
|
37
|
-
onPress={(toggle) => this.handleIconPress(moodValue, toggle)}
|
|
38
|
-
active={moodValue === this.state.selected}
|
|
39
|
-
mood={moodValue}
|
|
40
|
-
key={moodValue}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<View style={emotionStyles.container}>
|
|
47
|
-
<View style={emotionStyles.feelingContainer}>
|
|
48
|
-
<Text style={emotionStyles.feelingText}>{i18n._("How are you feeling?")}</Text>
|
|
49
|
-
</View>
|
|
50
|
-
<View style={emotionStyles.moodIconContainer}>{mapped}</View>
|
|
51
|
-
</View>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const emotionStyles = StyleSheet.create({
|
|
57
|
-
container: {
|
|
58
|
-
flex: 1,
|
|
59
|
-
},
|
|
60
|
-
feelingContainer: {
|
|
61
|
-
marginVertical: `3%`,
|
|
62
|
-
},
|
|
63
|
-
feelingText: {
|
|
64
|
-
textAlign: `center`,
|
|
65
|
-
color: `white`,
|
|
66
|
-
fontWeight: `bold`,
|
|
67
|
-
fontSize: Dimensions.get(`screen`).width / 26,
|
|
68
|
-
},
|
|
69
|
-
moodIconContainer: { flex: 1, flexDirection: `row`, justifyContent: `center` },
|
|
70
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|