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 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(" ") 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..0af0badff87 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) ) } } @@ -689,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 dce1b9f0421..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,11 +187,18 @@ data class BMIReadingAdded( val bmiReading: BMIReading ) : PatientSummaryEvent() +data class BMISaved( + val bmiReading: BMIReading +) : PatientSummaryEvent() + 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/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/main/java/org/simple/clinic/summary/PatientSummaryModel.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt index b7f18195b3e..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 @@ -30,6 +31,8 @@ data class PatientSummaryModel( val hasShownDiagnosisWarningDialog: Boolean, val statinInfo: StatinInfo?, val hasShownTobaccoUseDialog: Boolean, + val showBMIContainer: Boolean, + val bmiReading: BMIReading? ) : Parcelable, PatientSummaryChildModel { companion object { @@ -50,6 +53,8 @@ data class PatientSummaryModel( hasShownDiagnosisWarningDialog = false, statinInfo = null, hasShownTobaccoUseDialog = false, + showBMIContainer = false, + bmiReading = null ) } } @@ -138,4 +143,13 @@ data class PatientSummaryModel( fun showTobaccoUseDialog(): PatientSummaryModel { return copy(hasShownTobaccoUseDialog = true) } + + 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/PatientSummaryScreen.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryScreen.kt index a2367962ac4..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 @@ -197,6 +201,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) } @@ -334,6 +340,17 @@ class PatientSummaryScreen : } } } + + bmiContainerComposeView.setContent { + SimpleTheme { + BMIContainer( + bmiReading = bmiReading, + onAddOrClick = { + additionalEvents.notify(AddBMIClicked) + } + ) + } + } } private fun handleScreenResult(requestKey: Parcelable, result: Succeeded) { @@ -829,6 +846,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/PatientSummaryUpdate.kt b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt index bce0f936a67..a68421f2c8b 100644 --- a/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt @@ -110,11 +110,18 @@ 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)) - is BMISaved -> dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient)) + is BMIReadingLoaded -> next(model.bmiReadingsLoaded(event.bmiReading)) + 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/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() + } + } } 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" /> + +