Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -67,7 +68,7 @@ fun BMIContainer(

val bmiText = buildAnnotatedString {
if (isBmiRecorded) {
append(bmiReading.calculateBMI().toString())
append(bmiReading.calculateBMI()?.roundToInt().toString())

append(" ")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ data class UpdateTobaccoUse(
val isUsingSmokelessTobacco: MedicalHistoryAnswer
) : PatientSummaryEffect()

data object LoadBMIFeature : PatientSummaryEffect()

sealed class PatientSummaryViewEffect : PatientSummaryEffect()

data class HandleEditClick(
Expand All @@ -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()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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<LoadBMIFeature, PatientSummaryEvent> {
return ObservableTransformer { effects ->
effects
.observeOn(schedulersProvider.io())
.map {
BMIFeatureLoaded(
isEnabled = feature.isEnabled(Feature.ShowBMIContainer)
)
}
}
Expand Down Expand Up @@ -689,7 +702,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor(
loggedInUserUuid = currentUser.get().uuid,
uuid = uuidGenerator.v4(),
)
BMISaved
BMISaved(createNewBMIEntry.reading)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class PatientSummaryInit : Init<PatientSummaryModel, PatientSummaryEffect> {
override fun init(model: PatientSummaryModel): First<PatientSummaryModel, PatientSummaryEffect> {
val effects = mutableSetOf(
LoadPatientSummaryProfile(model.patientUuid),
CheckIfCDSSPilotIsEnabled
CheckIfCDSSPilotIsEnabled,
LoadBMIFeature,
LoadBMiReading(model.patientUuid),
)

if (!model.hasUserLoggedInStatus || !model.hasLoadedCurrentFacility) {
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -50,6 +53,8 @@ data class PatientSummaryModel(
hasShownDiagnosisWarningDialog = false,
statinInfo = null,
hasShownTobaccoUseDialog = false,
showBMIContainer = false,
bmiReading = null
)
}
}
Expand Down Expand Up @@ -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)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -142,6 +143,9 @@ class PatientSummaryScreen :
private val facilityNameAndDateTextView
get() = binding.facilityNameAndDateTextView

private val bmiContainerComposeView
get() = binding.bmiContainerComposeView

private val labelRegistered
get() = binding.labelRegistered

Expand Down Expand Up @@ -197,6 +201,8 @@ class PatientSummaryScreen :
private var showClinicalDecisionAlert by mutableStateOf(false)
private var animateClinicalDecisionSupportAlert by mutableStateOf(false)

private var bmiReading by mutableStateOf<BMIReading?>(null)

override fun defaultModel(): PatientSummaryModel {
return PatientSummaryModel.from(screenKey.intention, screenKey.patientUuid)
}
Expand Down Expand Up @@ -334,6 +340,17 @@ class PatientSummaryScreen :
}
}
}

bmiContainerComposeView.setContent {
SimpleTheme {
BMIContainer(
bmiReading = bmiReading,
onAddOrClick = {
additionalEvents.notify(AddBMIClicked)
}
)
}
}
}

private fun handleScreenResult(requestKey: Parcelable, result: Succeeded) {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -21,4 +22,6 @@ interface PatientSummaryScreenUi {
fun hideClinicalDecisionSupportAlert()
fun hideClinicalDecisionSupportAlertWithoutAnimation()
fun updateStatinAlert(statinInfo: StatinInfo)
fun showBMIContainer(bmiReading: BMIReading?)
fun hideBMIContainer()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PatientSummaryViewRenderer(
setupUiForAssignedFacility(model)
renderPatientDiedStatus(model)
renderPatientSummaryToolbar(model.patientSummaryProfile)
renderBMIContainer(model)
}

if (model.hasLoadedCurrentFacility) {
Expand Down Expand Up @@ -158,4 +159,12 @@ class PatientSummaryViewRenderer(
ui.hideClinicalDecisionSupportAlertWithoutAnimation()
}
}

private fun renderBMIContainer(model: PatientSummaryModel) {
if (model.showBMIContainer) {
ui.showBMIContainer(model.bmiReading)
} else {
ui.hideBMIContainer()
}
}
}
8 changes: 8 additions & 0 deletions app/src/main/res/layout/screen_patient_summary.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<androidx.compose.ui.platform.ComposeView
android:id="@+id/bmiContainerComposeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_8"
android:layout_marginEnd="@dimen/spacing_8"
android:visibility="gone" />

<TextView
android:id="@+id/labelRegistered"
android:layout_width="match_parent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -90,6 +91,7 @@ class PatientSummaryEffectHandlerTest {
remoteConfigService = NoOpRemoteConfigService(DefaultValueConfigReader()),
overrides = mapOf(
Feature.Screening to true,
Feature.ShowBMIContainer to true
)
)

Expand Down Expand Up @@ -1118,7 +1120,6 @@ class PatientSummaryEffectHandlerTest {
// when
testCase.dispatch(LoadBMiReading(patientUuid = patientUuid))

// then
//then
testCase.assertOutgoingEvents(BMIReadingLoaded(null))
}
Expand All @@ -1130,8 +1131,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(true))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ class PatientSummaryInitTest {
CheckForInvalidPhone(patientUuid),
LoadMedicalOfficers,
LoadPatientRegistrationData(patientUuid),
CheckIfCDSSPilotIsEnabled
CheckIfCDSSPilotIsEnabled,
LoadBMIFeature,
LoadBMiReading(patientUuid)
)
)
)
Expand Down Expand Up @@ -63,7 +65,9 @@ class PatientSummaryInitTest {
hasModel(model),
hasEffects(
LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect,
CheckIfCDSSPilotIsEnabled
CheckIfCDSSPilotIsEnabled,
LoadBMIFeature,
LoadBMiReading(patientUuid)
)
)
)
Expand Down Expand Up @@ -95,7 +99,9 @@ class PatientSummaryInitTest {
assertThatFirst(
hasModel(model),
hasEffects(
LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect
LoadPatientSummaryProfile(patientUuid) as PatientSummaryEffect,
LoadBMIFeature,
LoadBMiReading(patientUuid)
)
)
)
Expand Down
Loading
Loading