From 64614203e55a4555d9bb43151521da2282698ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Perpignane?= Date: Wed, 11 Oct 2023 21:42:40 +0200 Subject: [PATCH] feat/no more button on punctual insulin screen --- src/components/SectionComponent.tsx | 55 ------- src/core/Acetone.ts | 6 +- src/core/QuickInsulin.ts | 19 ++- src/screens/PunctualGlycemiaScreen.tsx | 137 +++++++++--------- .../__tests__/PunctualGlycemiaScreen.test.tsx | 28 ++-- 5 files changed, 98 insertions(+), 147 deletions(-) delete mode 100644 src/components/SectionComponent.tsx diff --git a/src/components/SectionComponent.tsx b/src/components/SectionComponent.tsx deleted file mode 100644 index cce4373..0000000 --- a/src/components/SectionComponent.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import {StyleSheet, Text, View, useColorScheme} from 'react-native' -import {Colors} from 'react-native/Libraries/NewAppScreen' -import React from 'react' -import type {PropsWithChildren} from 'react' - -type SectionProps = PropsWithChildren<{ - title: string -}> - -export function Section({children, title}: SectionProps): JSX.Element { - const isDarkMode = useColorScheme() === 'dark' - return ( - - - {title} - - - {children} - - - ) -} - -export const styles = StyleSheet.create({ - sectionContainer: { - marginTop: 32, - paddingHorizontal: 24, - }, - sectionTitle: { - fontSize: 24, - fontWeight: '600', - }, - sectionDescription: { - marginTop: 8, - fontSize: 18, - fontWeight: '400', - }, - highlight: { - fontWeight: '700', - }, -}) - -export default Section diff --git a/src/core/Acetone.ts b/src/core/Acetone.ts index 7cd1026..66c5a72 100644 --- a/src/core/Acetone.ts +++ b/src/core/Acetone.ts @@ -11,7 +11,11 @@ export class Acetone { public computeAdaptation(acetoneLevel: number): number { if (!this.acetoneAdaptationByLevel.has(acetoneLevel)) { - throw new Error('unknown acetone level: {acetoneLevel}') + let validLevels = [...this.acetoneAdaptationByLevel.keys()].join(', ') + + throw new Error( + `Invalid acetone level: ${acetoneLevel}. Valid levels are: ${validLevels}`, + ) } return this.acetoneAdaptationByLevel.get(acetoneLevel) diff --git a/src/core/QuickInsulin.ts b/src/core/QuickInsulin.ts index 9446d4b..87ac512 100644 --- a/src/core/QuickInsulin.ts +++ b/src/core/QuickInsulin.ts @@ -4,10 +4,16 @@ import conditions from './quick_insulin_conditions.json' export class PuntualAdaptationResult { private _glycemiaAdaptation: number private _acetoneAdaptation: number + private _checkAcetone: boolean - constructor(glycemiaAdapation: number, acetoneAdaptation: number) { + constructor( + glycemiaAdapation: number, + acetoneAdaptation: number, + checkAcetone: boolean, + ) { this._glycemiaAdaptation = glycemiaAdapation this._acetoneAdaptation = acetoneAdaptation + this._checkAcetone = checkAcetone } public get glycemiaAdaptation() { @@ -21,6 +27,10 @@ export class PuntualAdaptationResult { public get totalAdaptation() { return this.acetoneAdaptation + this.glycemiaAdaptation } + + public get checkAcetone() { + return this._checkAcetone + } } export class QuickInsulin { @@ -37,11 +47,11 @@ export class QuickInsulin { if (!glycemiaCondition) { throw new Error( - 'No adaptation found. Check quick insulin conditions config', + 'No adaptation found. Check quick insulin conditions configuration', ) } - if (glycemiaCondition.checkAcetone && acetoneLevel == null) { + if (glycemiaCondition.checkAcetone && acetoneLevel === undefined) { throw new AcetoneNeededError('Please provide acetone level') } @@ -55,6 +65,9 @@ export class QuickInsulin { return new PuntualAdaptationResult( glycemiaCondition.adaptation, acetoneAdaptation, + glycemiaCondition.checkAcetone === undefined + ? false + : glycemiaCondition.checkAcetone, ) } } diff --git a/src/screens/PunctualGlycemiaScreen.tsx b/src/screens/PunctualGlycemiaScreen.tsx index bb128d7..e2e64cb 100644 --- a/src/screens/PunctualGlycemiaScreen.tsx +++ b/src/screens/PunctualGlycemiaScreen.tsx @@ -15,7 +15,6 @@ import { QuickInsulin, } from '../core/QuickInsulin' import {DbNumericTextInput} from '../components/DbNumericTextInputComponent' -import {DbButton} from '../components/DbButtonComponent' import {screenStyles} from './styles' interface PunctualGlycemiaState { @@ -51,37 +50,88 @@ export class PunctualGlycemiaScreen extends React.Component< ` } - setGlycemiaLevel = (glycemiaLevel: number | undefined): void => { + private manageInvalidGlycemia = () => { + this.setVisibleAcetone(false) + this.setAcetoneLevel(undefined) + this.setErrorMessage('Invalid glycemia level') + this.setPunctualAdaptationResult(null) + } + + private setGlycemiaLevel = (glycemiaLevel: number | undefined): void => { + console.log('setting glycemia level') this.setState({ glycemiaLevel: glycemiaLevel, }) } - setAcetoneLevel = (acetoneLevel: number | undefined): void => { + private setAcetoneLevel = (acetoneLevel: number | undefined): void => { this.setState({ acetoneLevel: acetoneLevel, }) } - manageNumberInput = ( - strValue: string, - setValueFunction: (value: number | undefined) => void, - ): void => { - if (!strValue) { - setValueFunction(undefined) + private computeAdaptation = ( + glycemiaLevel: number, + acetoneLevel: number | undefined, + ) => { + let quickInsulin = new QuickInsulin() + try { + let lPunctualAdaptationResult = quickInsulin.computePunctualAdaptation( + glycemiaLevel, + acetoneLevel, + ) + this.setPunctualAdaptationResult(lPunctualAdaptationResult) + this.setVisibleAcetone(lPunctualAdaptationResult.checkAcetone) + this.setErrorMessage('') + } catch (e: any) { + if (e instanceof AcetoneNeededError) { + try { + Vibration.vibrate() + } catch (ve) {} + this.setVisibleAcetone(true) + this.setErrorMessage('Please provide acetone level') + } else { + this.setErrorMessage(e.toString()) + } + this.setPunctualAdaptationResult(null) + } + } + + private manageGlycemiaLevelInput = (newText: string) => { + let glycemiaLevel = this.manageNumberInput(newText) + + if (glycemiaLevel === undefined) { + this.manageInvalidGlycemia() return } + + this.setGlycemiaLevel(glycemiaLevel) + + this.computeAdaptation(glycemiaLevel, this.state.acetoneLevel) + } + + private manageAcetoneLevelInput = (newText: string) => { + let acetoneLevel = this.manageNumberInput(newText) + this.setAcetoneLevel(acetoneLevel) + if (this.state.glycemiaLevel) { + this.computeAdaptation(this.state.glycemiaLevel, acetoneLevel) + } + } + + private manageNumberInput = (strValue: string): number | undefined => { + if (!strValue) { + return undefined + } let numberValue: number = Number(strValue) if (isNaN(numberValue) || !isFinite(numberValue)) { - this.setErrorMessage('Invalid number') + return undefined } else { - setValueFunction(numberValue) - this.manageValidation() this.setErrorMessage('') + return numberValue } } - setPunctualAdaptationResult = ( + private setPunctualAdaptationResult = ( punctualAdaptationResult: PuntualAdaptationResult | null, ): void => { this.setState({ @@ -89,44 +139,16 @@ export class PunctualGlycemiaScreen extends React.Component< }) } - setVisibleAcetone = (visible: boolean) => { + private setVisibleAcetone = (visible: boolean) => { this.setState({visibleAcetone: visible}) } - setErrorMessage = (errorMessage: string) => { + private setErrorMessage = (errorMessage: string) => { this.setState({ errorMessage: errorMessage, }) } - manageValidation = (): void => { - if (this.state.glycemiaLevel === undefined) { - this.setPunctualAdaptationResult(null) - return - } - - let quickInsulin = new QuickInsulin() - try { - let lPunctualAdaptationResult = quickInsulin.computePunctualAdaptation( - this.state.glycemiaLevel, - this.state.acetoneLevel, - ) - this.setPunctualAdaptationResult(lPunctualAdaptationResult) - } catch (e) { - if (e instanceof AcetoneNeededError) { - try { - Vibration.vibrate() - } catch (ve) {} - - this.setVisibleAcetone(true) - } else { - this.setAcetoneLevel(undefined) - this.setVisibleAcetone(false) - this.setPunctualAdaptationResult(null) - } - } - } - render(): JSX.Element { const isDarkMode = Appearance.getColorScheme() === 'dark' @@ -147,16 +169,8 @@ export class PunctualGlycemiaScreen extends React.Component< Glycemia level: - this.manageNumberInput(newText, this.setGlycemiaLevel) - } + onChangeText={newText => this.manageGlycemiaLevelInput(newText)} testID="glycemiaInput" - defaultValue={ - this.state.glycemiaLevel == null - ? '' - : this.state.glycemiaLevel.toString() - } /> @@ -166,31 +180,16 @@ export class PunctualGlycemiaScreen extends React.Component< - this.manageNumberInput(newText, this.setAcetoneLevel) - } + onChangeText={newText => this.manageAcetoneLevelInput(newText)} testID="acetoneInput" - defaultValue={ - this.state.acetoneLevel == null - ? '' - : this.state.acetoneLevel.toString() - } /> )} - - - - {this.state.punctualAdaptationResult && ( - {this.state.punctualAdaptationResult?.totalAdaptation?.toString()} + {this.state.punctualAdaptationResult.totalAdaptation.toString()} )} diff --git a/src/screens/__tests__/PunctualGlycemiaScreen.test.tsx b/src/screens/__tests__/PunctualGlycemiaScreen.test.tsx index 2099c76..29a25a8 100644 --- a/src/screens/__tests__/PunctualGlycemiaScreen.test.tsx +++ b/src/screens/__tests__/PunctualGlycemiaScreen.test.tsx @@ -12,25 +12,23 @@ import {PunctualGlycemiaScreen} from '../PunctualGlycemiaScreen' it('renders correctly', () => { let SampleScreen = () => - let root = render() + render() - expect(root.getByTestId('glycemiaInput')).toBeDefined() - expect(() => root.getByTestId('acetoneInput')).toThrowError() - expect(() => root.getByTestId('resultDetails')).toThrowError() + expect(screen.getByTestId('glycemiaInput')).toBeDefined() + expect(() => screen.getByTestId('acetoneInput')).toThrowError() + expect(() => screen.getByTestId('resultDetails')).toThrowError() }) it('displays results when acetone not needed and entered glycemia is valid', () => { let SampleScreen = () => - let root = render() + render() - let glycemiaInput = root.getByTestId('glycemiaInput') - let validateButton = root.getByTestId('validateButton') + let glycemiaInput = screen.getByTestId('glycemiaInput') expect(glycemiaInput).toBeDefined() fireEvent.changeText(glycemiaInput, '1.2') - fireEvent(validateButton, 'onPress') let adaptationText = screen.getByTestId('adaptationText') expect(adaptationText.props.children).toBeTruthy() @@ -45,12 +43,10 @@ it('displays acetone input when needed', () => { render() let glycemiaInput = screen.getByTestId('glycemiaInput') - let validateButton = screen.getByTestId('validateButton') expect(glycemiaInput).toBeDefined() fireEvent.changeText(glycemiaInput, '2.6') - fireEvent(validateButton, 'onPress') let acetoneInput = screen.getByTestId('acetoneInput') expect(acetoneInput).toBeDefined() @@ -62,20 +58,16 @@ it('displays results when glycemia + acetone inputs are needed', () => { render() let glycemiaInput = screen.getByTestId('glycemiaInput') - let validateButton = screen.getByTestId('validateButton') expect(glycemiaInput).toBeDefined() fireEvent.changeText(glycemiaInput, '2.6') - fireEvent(validateButton, 'onPress') let acetoneInput = screen.getByTestId('acetoneInput') expect(acetoneInput).toBeDefined() fireEvent.changeText(acetoneInput, '1') - fireEvent(validateButton, 'onPress') - let adaptationText = screen.getByTestId('adaptationText') expect(adaptationText.props.children).toBeTruthy() @@ -89,16 +81,16 @@ it('displays error message when entered glycemia is not valid', () => { render() let glycemiaInput = screen.getByTestId('glycemiaInput') - let validateButton = screen.getByTestId('validateButton') expect(glycemiaInput).toBeDefined() fireEvent.changeText(glycemiaInput, 'abc') - fireEvent(validateButton, 'onPress') let errorMessage = screen.getByTestId('errorMessage') - expect(errorMessage.props.children).toEqual('Invalid number') + console.log(errorMessage.props.children) + + expect(errorMessage.props.children).toEqual('Invalid glycemia level') }) it('does not update anything when entered glycemia is empty', () => { @@ -107,12 +99,10 @@ it('does not update anything when entered glycemia is empty', () => { render() let glycemiaInput = screen.getByTestId('glycemiaInput') - let validateButton = screen.getByTestId('validateButton') expect(glycemiaInput).toBeDefined() fireEvent.changeText(glycemiaInput, '') - fireEvent(validateButton, 'onPress') expect(glycemiaInput.props.children).toBeUndefined() })