Skip to content

Commit

Permalink
Show smoking status dialog when cvd risk is LOW-HIGH or `MEDIUM-HIG…
Browse files Browse the repository at this point in the history
  • Loading branch information
siddh1004 and Siddharth Agarwal authored Feb 3, 2025
1 parent e885709 commit 6dfdc29
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
- Add statin translations for `bn-BD`, `si-LK`, `ta-LK`
- Bump Sentry Android to v8.1.0
- Bump Sentry Gradle plugin to v5.1.0
- Show smoking status dialog for low and medium cvd risk.

### Fixes

Expand Down
20 changes: 20 additions & 0 deletions app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskLevel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.simple.clinic.cvdrisk

import androidx.compose.ui.graphics.Color
import org.simple.clinic.R

enum class CVDRiskLevel(val displayStringResId: Int, val color: Color) {
LOW_HIGH(R.string.statin_alert_low_high_risk_patient_x, Color(0xFFFF7A00)),
MEDIUM_HIGH(R.string.statin_alert_medium_high_risk_patient_x, Color(0xFFFF7A00)),
HIGH(R.string.statin_alert_high_risk_patient_x, Color(0xFFFF3355));

companion object {
fun compute(cvdRiskRange: CVDRiskRange): CVDRiskLevel {
return when {
cvdRiskRange.min < 5 -> LOW_HIGH
cvdRiskRange.min < 10 -> MEDIUM_HIGH
else -> HIGH
}
}
}
}
6 changes: 6 additions & 0 deletions app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ data class CVDRiskRange(
val max: Int,
) : Parcelable {

val level: CVDRiskLevel
get() = CVDRiskLevel.compute(this)

val canPrescribeStatin: Boolean
get() = max >= 10

class RoomTypeConverter {

@TypeConverter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor(
return ObservableTransformer { effects ->
effects
.observeOn(schedulersProvider.io())
.flatMap { effect ->
.switchMap { effect ->
val patient = effect.patient
Observable.combineLatest(
medicalHistoryRepository.historyForPatientOrDefault(
Expand Down Expand Up @@ -246,9 +246,8 @@ class PatientSummaryEffectHandler @AssistedInject constructor(
)
val bmiReading = patientAttributeRepository.getPatientAttributeImmediate(patientUuid)
val cvdRisk = cvdRiskRepository.getCVDRiskImmediate(patientUuid)
val canPrescribeStatin = cvdRisk?.riskScore?.let { it.max >= 10 } ?: false
StatinInfoLoaded(StatinInfo(
canPrescribeStatin = canPrescribeStatin,
canPrescribeStatin = cvdRisk?.riskScore?.canPrescribeStatin ?: false,
cvdRisk = cvdRisk?.riskScore,
isSmoker = medicalHistory.isSmoking,
bmiReading = bmiReading?.bmiReading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ data class PatientSummaryModel(
val scheduledAppointment: ParcelableOptional<Appointment>?,
val hasShownDiagnosisWarningDialog: Boolean,
val statinInfo: StatinInfo?,
val hasShownSmokingStatusDialog: Boolean,
) : Parcelable, PatientSummaryChildModel {

companion object {
Expand All @@ -48,6 +49,7 @@ data class PatientSummaryModel(
scheduledAppointment = null,
hasShownDiagnosisWarningDialog = false,
statinInfo = null,
hasShownSmokingStatusDialog = false,
)
}
}
Expand Down Expand Up @@ -132,4 +134,8 @@ data class PatientSummaryModel(
fun updateStatinInfo(statinInfo: StatinInfo): PatientSummaryModel {
return copy(statinInfo = statinInfo)
}

fun showSmokingStatusDialog(): PatientSummaryModel {
return copy(hasShownSmokingStatusDialog = true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.spotify.mobius.Next
import com.spotify.mobius.Next.next
import com.spotify.mobius.Next.noChange
import com.spotify.mobius.Update
import org.simple.clinic.cvdrisk.CVDRiskLevel
import org.simple.clinic.cvdrisk.StatinInfo
import org.simple.clinic.drugs.DiagnosisWarningPrescriptions
import org.simple.clinic.drugs.PrescribedDrug
Expand All @@ -24,6 +25,7 @@ import org.simple.clinic.summary.OpenIntention.ViewExistingPatient
import org.simple.clinic.summary.OpenIntention.ViewExistingPatientWithTeleconsultLog
import org.simple.clinic.summary.OpenIntention.ViewNewPatient
import java.util.UUID
import org.simple.clinic.medicalhistory.Answer as MedicalHistoryAnswer

class PatientSummaryUpdate(
private val isPatientReassignmentFeatureEnabled: Boolean,
Expand Down Expand Up @@ -145,7 +147,7 @@ class PatientSummaryUpdate(
}

isEligibleForNonLabBasedCvdRisk && shouldCalculateCVDRisk -> {
dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient))
dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient))
}

isEligibleForNonLabBasedCvdRisk -> {
Expand Down Expand Up @@ -179,7 +181,20 @@ class PatientSummaryUpdate(
event: StatinInfoLoaded,
model: PatientSummaryModel
): Next<PatientSummaryModel, PatientSummaryEffect> {
return next(model.updateStatinInfo(event.statinInfo))
val canShowSmokingStatusDialog =
event.statinInfo.canPrescribeStatin &&
(event.statinInfo.cvdRisk?.level == CVDRiskLevel.LOW_HIGH ||
event.statinInfo.cvdRisk?.level == CVDRiskLevel.MEDIUM_HIGH) &&
event.statinInfo.isSmoker == MedicalHistoryAnswer.Unanswered &&
!model.hasShownSmokingStatusDialog

return if (canShowSmokingStatusDialog) {
next(model.updateStatinInfo(event.statinInfo)
.showSmokingStatusDialog(),
ShowSmokingStatusDialog)
} else {
next(model.updateStatinInfo(event.statinInfo))
}
}

private fun hypertensionNotNowClicked(continueToDiabetesDiagnosisWarning: Boolean): Next<PatientSummaryModel, PatientSummaryEffect> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.simple.clinic.R
import org.simple.clinic.common.ui.components.FilledButton
import org.simple.clinic.common.ui.theme.SimpleInverseTheme
import org.simple.clinic.common.ui.theme.SimpleTheme
import org.simple.clinic.cvdrisk.CVDRiskLevel
import org.simple.clinic.cvdrisk.CVDRiskRange
import org.simple.clinic.cvdrisk.StatinInfo
import org.simple.clinic.medicalhistory.Answer
Expand Down Expand Up @@ -119,15 +120,10 @@ fun RiskText(
val riskText = when {
hasCVD -> stringResource(R.string.statin_alert_very_high_risk_patient)
cvdRiskRange == null -> stringResource(R.string.statin_alert_at_risk_patient)
cvdRiskRange.min > 10 -> stringResource(R.string.statin_alert_high_risk_patient_x, riskPercentage)
cvdRiskRange.min < 5 -> stringResource(R.string.statin_alert_low_high_risk_patient_x, riskPercentage)
else -> stringResource(R.string.statin_alert_medium_high_risk_patient_x, riskPercentage)
else -> stringResource(cvdRiskRange.level.displayStringResId, riskPercentage)
}

val riskColor = when {
cvdRiskRange == null || cvdRiskRange.min > 10 -> SimpleTheme.colors.material.error
else -> Color(0xFFFF7A00)
}
val riskColor = cvdRiskRange?.level?.color ?: SimpleTheme.colors.material.error

val textMeasurer = rememberTextMeasurer()
val textWidth = textMeasurer.measure(
Expand Down Expand Up @@ -164,11 +160,11 @@ fun RiskProgressBar(
endOffset: Float
) {
val riskColors = listOf(
Color(0xFF00B849), // Very Low
Color(0xFFFFC800), // Low
SimpleTheme.colors.material.error, // Medium
Color(0xFFB81631), // High
Color(0xFF731814) // Very High
Color(0xFF00B849), // Low
Color(0xFFFFC800), // MEDIUM
SimpleTheme.colors.material.error, // HIGH
Color(0xFFB81631), // VERY HIGH
Color(0xFF731814) // CRITICAL
)

val indicatorColor = Color(0xFF2F363D)
Expand Down Expand Up @@ -240,26 +236,28 @@ fun DescriptionText(
statinInfo: StatinInfo
) {
val text = when {
statinInfo.cvdRisk == null ||
statinInfo.cvdRisk.min >= 10 -> stringResource(R.string.statin_alert_refer_to_doctor)
statinInfo.cvdRisk == null || statinInfo.cvdRisk.level == CVDRiskLevel.HIGH ->
stringResource(R.string.statin_alert_refer_to_doctor)

statinInfo.isSmoker == Answer.Unanswered &&
statinInfo.bmiReading == null -> stringResource(R.string.statin_alert_add_smoking_and_bmi_info)
statinInfo.isSmoker == Answer.Unanswered && statinInfo.bmiReading == null ->
stringResource(R.string.statin_alert_add_smoking_and_bmi_info)

statinInfo.isSmoker == Answer.Unanswered &&
statinInfo.bmiReading != null -> stringResource(R.string.statin_alert_add_smoking_info)
statinInfo.isSmoker == Answer.Unanswered && statinInfo.bmiReading != null ->
stringResource(R.string.statin_alert_add_smoking_info)

statinInfo.isSmoker != Answer.Unanswered &&
statinInfo.bmiReading == null -> stringResource(R.string.statin_alert_add_bmi_info)
statinInfo.isSmoker != Answer.Unanswered && statinInfo.bmiReading == null ->
stringResource(R.string.statin_alert_add_bmi_info)

else -> stringResource(R.string.statin_alert_refer_to_doctor)
}.toAnnotatedString()

val textColor = when {
statinInfo.cvdRisk == null ||
statinInfo.cvdRisk.min >= 10 -> SimpleTheme.colors.material.error
statinInfo.cvdRisk == null || statinInfo.cvdRisk.level == CVDRiskLevel.HIGH
-> SimpleTheme.colors.material.error

statinInfo.isSmoker == Answer.Unanswered || statinInfo.bmiReading == null ->
SimpleTheme.colors.onSurface67

statinInfo.isSmoker == Answer.Unanswered || statinInfo.bmiReading == null -> SimpleTheme.colors.onSurface67
else -> SimpleTheme.colors.material.error
}

Expand Down Expand Up @@ -324,11 +322,11 @@ fun StainNudgeAddButtons(

fun getOffsets(cvdRiskRange: CVDRiskRange?, size: Size): Pair<Float, Float> {
val riskRanges = listOf(
0..4, // Very Low
5..9, // Low
10..19, // Medium
20..29, // High
30..33 // Very High
0..4, // LOW
5..9, // MEDIUM
10..19, // HIGH
20..29, // VERY HIGH
30..33 // CRITICAL
)

val startRatio: Float
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2358,6 +2358,23 @@ class PatientSummaryUpdateTest {
))
}

@Test
fun `when statin info is loaded and risk is low-high, then update the state and show smoking status dialog`() {
val statinInfo = StatinInfo(
canPrescribeStatin = true,
CVDRiskRange(7, 14),
)
updateSpec
.given(defaultModel)
.whenEvent(StatinInfoLoaded(
statinInfo = statinInfo
))
.then(assertThatNext(
hasModel(defaultModel.updateStatinInfo(statinInfo).showSmokingStatusDialog()),
hasEffects(ShowSmokingStatusDialog)
))
}

@Test
fun `when add smoking button is clicked, then show the smoking status dialog`() {
updateSpec
Expand Down

0 comments on commit 6dfdc29

Please sign in to comment.