From f8270dbabd654306a9e4a7778d92bfcfd40b3806 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:07:07 +0530 Subject: [PATCH 01/11] Add effect to load bmi feature --- .../clinic/summary/PatientSummaryEffect.kt | 6 ++++-- .../summary/PatientSummaryEffectHandler.kt | 19 ++++++++++++++++--- .../PatientSummaryEffectHandlerTest.kt | 14 +++++++++++--- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt index 82213ec45e2..ceb9f67fdb5 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffect.kt @@ -93,6 +93,8 @@ data class UpdateTobaccoUse( val isUsingSmokelessTobacco: MedicalHistoryAnswer ) : PatientSummaryEffect() +data object LoadBMIFeature : PatientSummaryEffect() + sealed class PatientSummaryViewEffect : PatientSummaryEffect() data class HandleEditClick( @@ -119,9 +121,9 @@ data class ShowScheduleAppointmentSheet( val currentFacility: Facility ) : PatientSummaryViewEffect() -data object ShowDiagnosisRequiredError: PatientSummaryViewEffect() +data object ShowDiagnosisRequiredError : PatientSummaryViewEffect() -data object ShowDiagnosisOrReferralRequiredError: PatientSummaryViewEffect() +data object ShowDiagnosisOrReferralRequiredError : PatientSummaryViewEffect() data object ShowHypertensionDiagnosisRequiredError : PatientSummaryViewEffect() diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt index 49b69e7d988..7723c5d686b 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt @@ -104,6 +104,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor( .addConsumer(PatientSummaryViewEffect::class.java, viewEffectsConsumer::accept) .addTransformer(LoadPatientRegistrationData::class.java, checkPatientRegistrationData()) .addTransformer(CheckIfCDSSPilotIsEnabled::class.java, checkIfCDSSPilotIsEnabled()) + .addTransformer(LoadBMIFeature::class.java, loadBMIFeature()) .addTransformer(LoadLatestScheduledAppointment::class.java, loadLatestScheduledAppointment()) .addConsumer(UpdatePatientReassignmentStatus::class.java, { updatePatientReassignmentState(it.patientUuid, it.status) }, schedulersProvider.io()) .addTransformer(CheckPatientReassignmentStatus::class.java, checkPatientReassignmentStatus()) @@ -390,9 +391,21 @@ class PatientSummaryEffectHandler @AssistedInject constructor( .map { val currentFacilityId = currentFacility.get().uuid CDSSPilotStatusChecked(isPilotEnabledForFacility = - country.isoCountryCode == Country.ETHIOPIA || - country.isoCountryCode == Country.SRI_LANKA || - cdssPilotFacilities.get().contains(currentFacilityId) + country.isoCountryCode == Country.ETHIOPIA || + country.isoCountryCode == Country.SRI_LANKA || + cdssPilotFacilities.get().contains(currentFacilityId) + ) + } + } + } + + private fun loadBMIFeature(): ObservableTransformer { + return ObservableTransformer { effects -> + effects + .observeOn(schedulersProvider.io()) + .map { + BMIFeatureLoaded( + isEnabled = feature.isEnabled(Feature.ShowBMIContainer) ) } } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt index 209986b7370..9bd49cdc826 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt @@ -4,6 +4,7 @@ import io.reactivex.Completable import io.reactivex.Observable import org.junit.After import org.junit.Test +import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.verify @@ -1118,7 +1119,6 @@ class PatientSummaryEffectHandlerTest { // when testCase.dispatch(LoadBMiReading(patientUuid = patientUuid)) - // then //then testCase.assertOutgoingEvents(BMIReadingLoaded(null)) } @@ -1130,8 +1130,16 @@ class PatientSummaryEffectHandlerTest { testCase.dispatch(CreateNewBMIEntry(patientUuid, bmiReading)) - // then //then - testCase.assertOutgoingEvents(BMISaved) + testCase.assertOutgoingEvents(BMISaved(bmiReading)) + } + + @Test + fun `when load bmi feature effect is received, then bmi feature should be loaded`() { + // when + testCase.dispatch(LoadBMIFeature) + + //then + testCase.assertOutgoingEvents(BMIFeatureLoaded(any())) } } From 4e707d8e2a8fdd1eb03d770a19fabf7ac9d9f37b Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:11:34 +0530 Subject: [PATCH 02/11] Update model when bmi feature is loaded --- .../simple/clinic/summary/PatientSummaryEvent.kt | 7 +++++-- .../simple/clinic/summary/PatientSummaryModel.kt | 6 ++++++ .../simple/clinic/summary/PatientSummaryUpdate.kt | 1 + .../clinic/summary/PatientSummaryUpdateTest.kt | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt index dce1b9f0421..6968178207c 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt @@ -189,9 +189,12 @@ data class BMIReadingAdded( data object AddBMIClicked : PatientSummaryEvent() -data object AddCholesterolClicked: PatientSummaryEvent() +data object AddCholesterolClicked : PatientSummaryEvent() data object CholesterolAdded : PatientSummaryEvent() -data object BMISaved : PatientSummaryEvent() + +data class BMIFeatureLoaded( + val isEnabled: Boolean +) : PatientSummaryEvent() diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt index b7f18195b3e..6817c14a3c2 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt @@ -30,6 +30,7 @@ data class PatientSummaryModel( val hasShownDiagnosisWarningDialog: Boolean, val statinInfo: StatinInfo?, val hasShownTobaccoUseDialog: Boolean, + val showBMIContainer: Boolean, ) : Parcelable, PatientSummaryChildModel { companion object { @@ -50,6 +51,7 @@ data class PatientSummaryModel( hasShownDiagnosisWarningDialog = false, statinInfo = null, hasShownTobaccoUseDialog = false, + showBMIContainer = false, ) } } @@ -138,4 +140,8 @@ data class PatientSummaryModel( fun showTobaccoUseDialog(): PatientSummaryModel { return copy(hasShownTobaccoUseDialog = true) } + + fun bmiVisibilityUpdated(isEnabled: Boolean): PatientSummaryModel { + return copy(showBMIContainer = isEnabled) + } } diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index bce0f936a67..8ed0c60ca6c 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -115,6 +115,7 @@ class PatientSummaryUpdate( CholesterolAdded -> dispatch(CalculateLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) is BMIReadingLoaded -> dispatch(OpenBMIEntrySheet(event.bmiReading)) is BMISaved -> dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) + is BMIFeatureLoaded -> next(model.bmiVisibilityUpdated(event.isEnabled)) } } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index b8a7bd059c0..b45f45800c8 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2691,6 +2691,20 @@ class PatientSummaryUpdateTest { )) } + @Test + fun `when BMI feature is loaded, then update the model`() { + val model = defaultModel + .patientSummaryProfileLoaded(patientSummaryProfile) + + updateSpec + .given(model) + .whenEvent(BMIFeatureLoaded(true)) + .then(assertThatNext( + hasModel(model.bmiVisibilityUpdated(true)), + hasNoEffects() + )) + } + @Test fun `when add bmi button is clicked, then load bmi reading`() { val model = defaultModel From 053421979ebb35aee19a437708e6299a8662b904 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:15:10 +0530 Subject: [PATCH 03/11] When BMI is saved then update the model and calculate cvd risk --- .../clinic/summary/PatientSummaryEffectHandler.kt | 2 +- .../org/simple/clinic/summary/PatientSummaryEvent.kt | 4 ++++ .../org/simple/clinic/summary/PatientSummaryModel.kt | 8 ++++++++ .../org/simple/clinic/summary/PatientSummaryUpdate.kt | 7 +++++++ .../simple/clinic/summary/PatientSummaryUpdateTest.kt | 11 ++++++++--- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt index 7723c5d686b..0af0badff87 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt @@ -702,7 +702,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor( loggedInUserUuid = currentUser.get().uuid, uuid = uuidGenerator.v4(), ) - BMISaved + BMISaved(createNewBMIEntry.reading) } } } diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt index 6968178207c..8b1d291984b 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryEvent.kt @@ -187,6 +187,10 @@ data class BMIReadingAdded( val bmiReading: BMIReading ) : PatientSummaryEvent() +data class BMISaved( + val bmiReading: BMIReading +) : PatientSummaryEvent() + data object AddBMIClicked : PatientSummaryEvent() data object AddCholesterolClicked : PatientSummaryEvent() diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt index 6817c14a3c2..84ab41de3a7 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt @@ -6,6 +6,7 @@ import org.simple.clinic.cvdrisk.StatinInfo import org.simple.clinic.facility.Facility import org.simple.clinic.overdue.Appointment import org.simple.clinic.patient.PatientStatus +import org.simple.clinic.patientattribute.BMIReading import org.simple.clinic.summary.teleconsultation.sync.MedicalOfficer import org.simple.clinic.user.User import org.simple.clinic.util.ParcelableOptional @@ -31,6 +32,7 @@ data class PatientSummaryModel( val statinInfo: StatinInfo?, val hasShownTobaccoUseDialog: Boolean, val showBMIContainer: Boolean, + val bmiReading: BMIReading? ) : Parcelable, PatientSummaryChildModel { companion object { @@ -52,6 +54,7 @@ data class PatientSummaryModel( statinInfo = null, hasShownTobaccoUseDialog = false, showBMIContainer = false, + bmiReading = null ) } } @@ -144,4 +147,9 @@ data class PatientSummaryModel( fun bmiVisibilityUpdated(isEnabled: Boolean): PatientSummaryModel { return copy(showBMIContainer = isEnabled) } + + fun bmiReadingsLoaded(bmiReading: BMIReading?): PatientSummaryModel { + return copy(bmiReading = bmiReading) + } + } diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index 8ed0c60ca6c..cebc96c59e9 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -115,6 +115,13 @@ class PatientSummaryUpdate( CholesterolAdded -> dispatch(CalculateLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) is BMIReadingLoaded -> dispatch(OpenBMIEntrySheet(event.bmiReading)) is BMISaved -> dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) + is BMISaved -> { + next( + model.copy(bmiReading = event.bmiReading), + setOf(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) + ) + } + is BMIFeatureLoaded -> next(model.bmiVisibilityUpdated(event.isEnabled)) } } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index b45f45800c8..9f76cf8578c 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2757,16 +2757,21 @@ class PatientSummaryUpdateTest { } @Test - fun `when BMI reading is saved, then calculate non lab based cvd risk`() { + fun `when BMI reading is saved, then calculate non lab based cvd risk and update the model`() { val model = defaultModel .patientSummaryProfileLoaded(patientSummaryProfile) + val bmiReading = BMIReading( + height = 165f, + weight = 60f + ) + updateSpec .given(model) - .whenEvent(BMISaved) + .whenEvent(BMISaved(bmiReading)) .then(assertThatNext( hasEffects(CalculateNonLabBasedCVDRisk(patientSummaryProfile.patient)), - hasNoModel() + hasModel(model.bmiReadingsLoaded(bmiReading)) )) } From f41af373321b4d7d9cb8f056567952afb2ea93e7 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:15:34 +0530 Subject: [PATCH 04/11] Load bmi feature and readings when screen is created --- .../org/simple/clinic/summary/PatientSummaryInit.kt | 4 +++- .../simple/clinic/summary/PatientSummaryInitTest.kt | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryInit.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryInit.kt index 6541823c7e6..98048286c58 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryInit.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryInit.kt @@ -9,7 +9,9 @@ class PatientSummaryInit : Init { override fun init(model: PatientSummaryModel): First { val effects = mutableSetOf( LoadPatientSummaryProfile(model.patientUuid), - CheckIfCDSSPilotIsEnabled + CheckIfCDSSPilotIsEnabled, + LoadBMIFeature, + LoadBMiReading(model.patientUuid), ) if (!model.hasUserLoggedInStatus || !model.hasLoadedCurrentFacility) { diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryInitTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryInitTest.kt index 1efa43e148b..546b17a2f1f 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryInitTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryInitTest.kt @@ -30,7 +30,9 @@ class PatientSummaryInitTest { CheckForInvalidPhone(patientUuid), LoadMedicalOfficers, LoadPatientRegistrationData(patientUuid), - CheckIfCDSSPilotIsEnabled + CheckIfCDSSPilotIsEnabled, + LoadBMIFeature, + LoadBMiReading(patientUuid) ) ) ) @@ -63,7 +65,9 @@ class PatientSummaryInitTest { hasModel(model), hasEffects( LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect, - CheckIfCDSSPilotIsEnabled + CheckIfCDSSPilotIsEnabled, + LoadBMIFeature, + LoadBMiReading(patientUuid) ) ) ) @@ -95,7 +99,9 @@ class PatientSummaryInitTest { assertThatFirst( hasModel(model), hasEffects( - LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect + LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect, + LoadBMIFeature, + LoadBMiReading(patientUuid) ) ) ) From 928d65fb24ffd8ed9aefb8d16dfc4805bebd386d Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:16:33 +0530 Subject: [PATCH 05/11] Update the ui when model is rendered --- .../org/simple/clinic/summary/PatientSummaryScreen.kt | 11 +++++++++++ .../simple/clinic/summary/PatientSummaryScreenUi.kt | 3 +++ .../clinic/summary/PatientSummaryViewRenderer.kt | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt index a2367962ac4..53950a89d36 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt @@ -197,6 +197,8 @@ class PatientSummaryScreen : private var showClinicalDecisionAlert by mutableStateOf(false) private var animateClinicalDecisionSupportAlert by mutableStateOf(false) + private var bmiReading by mutableStateOf(null) + override fun defaultModel(): PatientSummaryModel { return PatientSummaryModel.from(screenKey.intention, screenKey.patientUuid) } @@ -829,6 +831,15 @@ class PatientSummaryScreen : this.statinInfo = statinInfo } + override fun showBMIContainer(bmiReading: BMIReading?) { + bmiContainerComposeView.visibility = VISIBLE + this.bmiReading = bmiReading + } + + override fun hideBMIContainer() { + bmiContainerComposeView.visibility = GONE + } + override fun showReassignPatientWarningSheet( patientUuid: UUID, currentFacility: Facility, diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreenUi.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreenUi.kt index 0b7f02eaaf3..5c5236e8fd4 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreenUi.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreenUi.kt @@ -1,6 +1,7 @@ package org.simple.clinic.summary import org.simple.clinic.cvdrisk.StatinInfo +import org.simple.clinic.patientattribute.BMIReading interface PatientSummaryScreenUi { fun renderPatientSummaryToolbar(patientSummaryProfile: PatientSummaryProfile) @@ -21,4 +22,6 @@ interface PatientSummaryScreenUi { fun hideClinicalDecisionSupportAlert() fun hideClinicalDecisionSupportAlertWithoutAnimation() fun updateStatinAlert(statinInfo: StatinInfo) + fun showBMIContainer(bmiReading: BMIReading?) + fun hideBMIContainer() } diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryViewRenderer.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryViewRenderer.kt index f5378bf7669..7a355e25336 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryViewRenderer.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryViewRenderer.kt @@ -26,6 +26,7 @@ class PatientSummaryViewRenderer( setupUiForAssignedFacility(model) renderPatientDiedStatus(model) renderPatientSummaryToolbar(model.patientSummaryProfile) + renderBMIContainer(model) } if (model.hasLoadedCurrentFacility) { @@ -158,4 +159,12 @@ class PatientSummaryViewRenderer( ui.hideClinicalDecisionSupportAlertWithoutAnimation() } } + + private fun renderBMIContainer(model: PatientSummaryModel) { + if (model.showBMIContainer) { + ui.showBMIContainer(model.bmiReading) + } else { + ui.hideBMIContainer() + } + } } From bf794372f21b56c39960fe61647d815ad4dcdc06 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:16:50 +0530 Subject: [PATCH 06/11] Add bmi container ui to patient summary screen --- .../simple/clinic/summary/PatientSummaryScreen.kt | 15 +++++++++++++++ .../main/res/layout/screen_patient_summary.xml | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt index 53950a89d36..75b816d357e 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt @@ -49,6 +49,7 @@ import org.simple.clinic.feature.Feature import org.simple.clinic.feature.Features import org.simple.clinic.home.HomeScreenKey import org.simple.clinic.medicalhistory.Answer +import org.simple.clinic.medicalhistory.ui.BMIContainer import org.simple.clinic.mobius.DeferredEventSource import org.simple.clinic.mobius.ViewRenderer import org.simple.clinic.navigation.v2.HandlesBack @@ -142,6 +143,9 @@ class PatientSummaryScreen : private val facilityNameAndDateTextView get() = binding.facilityNameAndDateTextView + private val bmiContainerComposeView + get() = binding.bmiContainerComposeView + private val labelRegistered get() = binding.labelRegistered @@ -336,6 +340,17 @@ class PatientSummaryScreen : } } } + + bmiContainerComposeView.setContent { + SimpleTheme { + BMIContainer( + bmiReading = bmiReading, + onAddOrClick = { + additionalEvents.notify(AddBMIClicked) + } + ) + } + } } private fun handleScreenResult(requestKey: Parcelable, result: Succeeded) { diff --git a/app/src/main/res/layout/screen_patient_summary.xml b/app/src/main/res/layout/screen_patient_summary.xml index 3b1c2eb8f81..f92b78ed903 100644 --- a/app/src/main/res/layout/screen_patient_summary.xml +++ b/app/src/main/res/layout/screen_patient_summary.xml @@ -96,6 +96,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + Date: Wed, 10 Jun 2026 16:18:22 +0530 Subject: [PATCH 07/11] Update AddBMIClicked effect to open bmi entry sheet --- .../main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt | 2 +- .../java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index cebc96c59e9..e3bc04dcc97 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -110,7 +110,7 @@ class PatientSummaryUpdate( is AddTobaccoUseClicked -> dispatch(ShowTobaccoStatusDialog) is TobaccoUseAnswered -> dispatch(UpdateTobaccoUse(model.patientUuid, event.isSmoker, event.isUsingSmokelessTobacco)) is BMIReadingAdded -> dispatch(CreateNewBMIEntry(model.patientUuid, event.bmiReading)) - is AddBMIClicked -> dispatch(LoadBMiReading(model.patientUuid)) + is AddBMIClicked -> dispatch(OpenBMIEntrySheet(model.bmiReading)) is AddCholesterolClicked -> dispatch(OpenCholesterolEntrySheet(model.patientUuid)) CholesterolAdded -> dispatch(CalculateLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) is BMIReadingLoaded -> dispatch(OpenBMIEntrySheet(event.bmiReading)) diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index 9f76cf8578c..3d6c25bdd44 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2714,7 +2714,7 @@ class PatientSummaryUpdateTest { .given(model) .whenEvent(AddBMIClicked) .then(assertThatNext( - hasEffects(LoadBMiReading(model.patientUuid)), + hasEffects(OpenBMIEntrySheet(model.bmiReading)), hasNoModel() )) } From f864fed1cdab7c3a14ffbbde65f87174a8c4c313 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:19:57 +0530 Subject: [PATCH 08/11] Update `BMIReadingLoaded` effect to update the model and dispatch no effect --- .../org/simple/clinic/summary/PatientSummaryUpdate.kt | 3 +-- .../org/simple/clinic/summary/PatientSummaryUpdateTest.kt | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index e3bc04dcc97..a68421f2c8b 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -113,8 +113,7 @@ class PatientSummaryUpdate( is AddBMIClicked -> dispatch(OpenBMIEntrySheet(model.bmiReading)) is AddCholesterolClicked -> dispatch(OpenCholesterolEntrySheet(model.patientUuid)) CholesterolAdded -> dispatch(CalculateLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) - is BMIReadingLoaded -> dispatch(OpenBMIEntrySheet(event.bmiReading)) - is BMISaved -> dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) + is BMIReadingLoaded -> next(model.bmiReadingsLoaded(event.bmiReading)) is BMISaved -> { next( model.copy(bmiReading = event.bmiReading), diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index 3d6c25bdd44..8a804e000f7 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2706,7 +2706,7 @@ class PatientSummaryUpdateTest { } @Test - fun `when add bmi button is clicked, then load bmi reading`() { + fun `when add bmi button is clicked, open bmi entry sheet`() { val model = defaultModel .patientSummaryProfileLoaded(patientSummaryProfile) @@ -2720,7 +2720,7 @@ class PatientSummaryUpdateTest { } @Test - fun `when bmi reading is loaded, then open bmi entry sheet`() { + fun `when bmi reading is loaded, then update the model`() { val model = defaultModel .patientSummaryProfileLoaded(patientSummaryProfile) @@ -2733,8 +2733,8 @@ class PatientSummaryUpdateTest { .given(model) .whenEvent(BMIReadingLoaded(bmiReading)) .then(assertThatNext( - hasEffects(OpenBMIEntrySheet(bmiReading)), - hasNoModel() + hasNoEffects(), + hasModel(model.bmiReadingsLoaded(bmiReading)) )) } From d8f804d9fa95f9bb188572d66f8e684c9ee161dc Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:28:03 +0530 Subject: [PATCH 09/11] Fix test cases --- .../summary/PatientSummaryEffectHandlerTest.kt | 3 ++- .../clinic/summary/PatientSummaryUpdateTest.kt | 6 +++--- .../summary/PatientSummaryViewRendererTest.kt | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt index 9bd49cdc826..e350f1e2bbb 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryEffectHandlerTest.kt @@ -91,6 +91,7 @@ class PatientSummaryEffectHandlerTest { remoteConfigService = NoOpRemoteConfigService(DefaultValueConfigReader()), overrides = mapOf( Feature.Screening to true, + Feature.ShowBMIContainer to true ) ) @@ -1140,6 +1141,6 @@ class PatientSummaryEffectHandlerTest { testCase.dispatch(LoadBMIFeature) //then - testCase.assertOutgoingEvents(BMIFeatureLoaded(any())) + testCase.assertOutgoingEvents(BMIFeatureLoaded(true)) } } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt index 8a804e000f7..6e7437bceb0 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt @@ -2776,7 +2776,7 @@ class PatientSummaryUpdateTest { } @Test - fun `when BMI reading is loaded, then open bmi entry sheet`() { + fun `when BMI reading is loaded, then update the model`() { val model = defaultModel .patientSummaryProfileLoaded(patientSummaryProfile) @@ -2788,8 +2788,8 @@ class PatientSummaryUpdateTest { .given(model) .whenEvent(BMIReadingLoaded(bmiReading)) .then(assertThatNext( - hasEffects(OpenBMIEntrySheet(bmiReading)), - hasNoModel() + hasNoEffects(), + hasModel(model.bmiReadingsLoaded(bmiReading)) )) } diff --git a/app/src/test/java/org/simple/clinic/summary/PatientSummaryViewRendererTest.kt b/app/src/test/java/org/simple/clinic/summary/PatientSummaryViewRendererTest.kt index 1ddc33a894e..17eb20a5bd0 100644 --- a/app/src/test/java/org/simple/clinic/summary/PatientSummaryViewRendererTest.kt +++ b/app/src/test/java/org/simple/clinic/summary/PatientSummaryViewRendererTest.kt @@ -12,6 +12,7 @@ import org.simple.clinic.patient.businessid.Identifier import org.simple.clinic.summary.OpenIntention.ViewExistingPatient import org.simple.clinic.user.User import org.simple.clinic.TestData +import org.simple.clinic.patientattribute.BMIReading import org.simple.clinic.util.TestUserClock import java.time.Instant import java.time.LocalDate @@ -136,6 +137,7 @@ class PatientSummaryViewRendererTest { verify(ui).hidePatientDiedStatus() verify(ui).hideNextAppointmentCard() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -234,6 +236,7 @@ class PatientSummaryViewRendererTest { verify(ui).hidePatientDiedStatus() verify(ui).hideNextAppointmentCard() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -274,6 +277,7 @@ class PatientSummaryViewRendererTest { verify(ui).hidePatientDiedStatus() verify(ui).hideNextAppointmentCard() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -336,6 +340,7 @@ class PatientSummaryViewRendererTest { verify(ui).hidePatientDiedStatus() verify(ui).hideNextAppointmentCard() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -374,6 +379,7 @@ class PatientSummaryViewRendererTest { verify(ui).showPatientDiedStatus() verify(ui).hideNextAppointmentCard() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -438,11 +444,15 @@ class PatientSummaryViewRendererTest { facility = facility ) + val bmiReading = BMIReading(height = 177f, weight = 68f) + val updatedModel = defaultModel .patientRegistrationDataLoaded(hasPatientRegistrationData = true) .currentFacilityLoaded(facility = facility) .patientSummaryProfileLoaded(patientSummaryProfile = patientSummaryProfile) .clinicalDecisionSupportInfoLoaded(isNewestBpEntryHigh = true, hasPrescribedDrugsChangedToday = false) + .bmiVisibilityUpdated(true) + .bmiReadingsLoaded(bmiReading) val uiRenderer = PatientSummaryViewRenderer( ui = ui, @@ -463,6 +473,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideTeleconsultButton() verify(ui).showClinicalDecisionSupportAlert() verify(ui).showNextAppointmentCard() + verify(ui).showBMIContainer(bmiReading) verifyNoMoreInteractions(ui) } @@ -517,6 +528,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideTeleconsultButton() verify(ui).hideClinicalDecisionSupportAlert() verify(ui).showNextAppointmentCard() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -571,6 +583,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideTeleconsultButton() verify(ui).hideClinicalDecisionSupportAlert() verify(ui).showNextAppointmentCard() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -640,6 +653,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideDiabetesView() verify(ui).hideTeleconsultButton() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -700,6 +714,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideTeleconsultButton() verify(ui).showClinicalDecisionSupportAlert() verify(ui).showNextAppointmentCard() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -760,6 +775,7 @@ class PatientSummaryViewRendererTest { verify(ui).hideTeleconsultButton() verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() verify(ui).showNextAppointmentCard() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } @@ -842,6 +858,7 @@ class PatientSummaryViewRendererTest { verify(ui).updateStatinAlert(StatinInfo(canShowStatinNudge = true)) verify(ui).hideClinicalDecisionSupportAlertWithoutAnimation() verify(ui).showNextAppointmentCard() + verify(ui).hideBMIContainer() verifyNoMoreInteractions(ui) } } From 8e906bccbf739cdfc3356f4166b19695cf26d0ab Mon Sep 17 00:00:00 2001 From: sagarwal Date: Wed, 10 Jun 2026 16:54:55 +0530 Subject: [PATCH 10/11] Round off the bmi --- .../java/org/simple/clinic/medicalhistory/ui/BMIContainer.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/ui/BMIContainer.kt b/app/src/main/java/org/simple/clinic/medicalhistory/ui/BMIContainer.kt index 46ddfb728b5..b7406cb97e1 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/ui/BMIContainer.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/ui/BMIContainer.kt @@ -22,6 +22,7 @@ import org.simple.clinic.common.ui.components.ButtonSize import org.simple.clinic.common.ui.components.TextButton import org.simple.clinic.common.ui.theme.SimpleTheme import org.simple.clinic.patientattribute.BMIReading +import kotlin.math.roundToInt @Composable fun BMIContainer( @@ -67,7 +68,7 @@ fun BMIContainer( val bmiText = buildAnnotatedString { if (isBmiRecorded) { - append(bmiReading.calculateBMI().toString()) + append(bmiReading.calculateBMI()?.roundToInt().toString()) append(" ") From d53242af5188878a80892e15aca3dd085f2eb0c7 Mon Sep 17 00:00:00 2001 From: sagarwal Date: Thu, 11 Jun 2026 13:42:35 +0530 Subject: [PATCH 11/11] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7d0a5c0eda..e0dbe68be8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Update Titration nudge threshold for diabetic patients in SriLanka from `140/90` to `130/80` - Add BMI container to patient registration screen +- Add BMI container to patient summary screen ## 2026.05.11