Skip to content

Commit 6dfdc29

Browse files
siddh1004Siddharth Agarwal
andauthored
Show smoking status dialog when cvd risk is LOW-HIGH or MEDIUM-HIGH (#5229)
https://app.shortcut.com/simpledotorg/story/14643/show-smoking-dialog-if-risk-is-low-high-or-medium-high?team_id=1&iteration_ids=14465&iteration_ids=14489 --------- Co-authored-by: Siddharth Agarwal <sagarwal@rtsl.org>
1 parent e885709 commit 6dfdc29

File tree

8 files changed

+95
-33
lines changed

8 files changed

+95
-33
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
- Add statin translations for `bn-BD`, `si-LK`, `ta-LK`
5757
- Bump Sentry Android to v8.1.0
5858
- Bump Sentry Gradle plugin to v5.1.0
59+
- Show smoking status dialog for low and medium cvd risk.
5960

6061
### Fixes
6162

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.simple.clinic.cvdrisk
2+
3+
import androidx.compose.ui.graphics.Color
4+
import org.simple.clinic.R
5+
6+
enum class CVDRiskLevel(val displayStringResId: Int, val color: Color) {
7+
LOW_HIGH(R.string.statin_alert_low_high_risk_patient_x, Color(0xFFFF7A00)),
8+
MEDIUM_HIGH(R.string.statin_alert_medium_high_risk_patient_x, Color(0xFFFF7A00)),
9+
HIGH(R.string.statin_alert_high_risk_patient_x, Color(0xFFFF3355));
10+
11+
companion object {
12+
fun compute(cvdRiskRange: CVDRiskRange): CVDRiskLevel {
13+
return when {
14+
cvdRiskRange.min < 5 -> LOW_HIGH
15+
cvdRiskRange.min < 10 -> MEDIUM_HIGH
16+
else -> HIGH
17+
}
18+
}
19+
}
20+
}

app/src/main/java/org/simple/clinic/cvdrisk/CVDRiskRange.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ data class CVDRiskRange(
1212
val max: Int,
1313
) : Parcelable {
1414

15+
val level: CVDRiskLevel
16+
get() = CVDRiskLevel.compute(this)
17+
18+
val canPrescribeStatin: Boolean
19+
get() = max >= 10
20+
1521
class RoomTypeConverter {
1622

1723
@TypeConverter

app/src/main/java/org/simple/clinic/summary/PatientSummaryEffectHandler.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class PatientSummaryEffectHandler @AssistedInject constructor(
116116
return ObservableTransformer { effects ->
117117
effects
118118
.observeOn(schedulersProvider.io())
119-
.flatMap { effect ->
119+
.switchMap { effect ->
120120
val patient = effect.patient
121121
Observable.combineLatest(
122122
medicalHistoryRepository.historyForPatientOrDefault(
@@ -246,9 +246,8 @@ class PatientSummaryEffectHandler @AssistedInject constructor(
246246
)
247247
val bmiReading = patientAttributeRepository.getPatientAttributeImmediate(patientUuid)
248248
val cvdRisk = cvdRiskRepository.getCVDRiskImmediate(patientUuid)
249-
val canPrescribeStatin = cvdRisk?.riskScore?.let { it.max >= 10 } ?: false
250249
StatinInfoLoaded(StatinInfo(
251-
canPrescribeStatin = canPrescribeStatin,
250+
canPrescribeStatin = cvdRisk?.riskScore?.canPrescribeStatin ?: false,
252251
cvdRisk = cvdRisk?.riskScore,
253252
isSmoker = medicalHistory.isSmoking,
254253
bmiReading = bmiReading?.bmiReading,

app/src/main/java/org/simple/clinic/summary/PatientSummaryModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ data class PatientSummaryModel(
2929
val scheduledAppointment: ParcelableOptional<Appointment>?,
3030
val hasShownDiagnosisWarningDialog: Boolean,
3131
val statinInfo: StatinInfo?,
32+
val hasShownSmokingStatusDialog: Boolean,
3233
) : Parcelable, PatientSummaryChildModel {
3334

3435
companion object {
@@ -48,6 +49,7 @@ data class PatientSummaryModel(
4849
scheduledAppointment = null,
4950
hasShownDiagnosisWarningDialog = false,
5051
statinInfo = null,
52+
hasShownSmokingStatusDialog = false,
5153
)
5254
}
5355
}
@@ -132,4 +134,8 @@ data class PatientSummaryModel(
132134
fun updateStatinInfo(statinInfo: StatinInfo): PatientSummaryModel {
133135
return copy(statinInfo = statinInfo)
134136
}
137+
138+
fun showSmokingStatusDialog(): PatientSummaryModel {
139+
return copy(hasShownSmokingStatusDialog = true)
140+
}
135141
}

app/src/main/java/org/simple/clinic/summary/PatientSummaryUpdate.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.spotify.mobius.Next
44
import com.spotify.mobius.Next.next
55
import com.spotify.mobius.Next.noChange
66
import com.spotify.mobius.Update
7+
import org.simple.clinic.cvdrisk.CVDRiskLevel
78
import org.simple.clinic.cvdrisk.StatinInfo
89
import org.simple.clinic.drugs.DiagnosisWarningPrescriptions
910
import org.simple.clinic.drugs.PrescribedDrug
@@ -24,6 +25,7 @@ import org.simple.clinic.summary.OpenIntention.ViewExistingPatient
2425
import org.simple.clinic.summary.OpenIntention.ViewExistingPatientWithTeleconsultLog
2526
import org.simple.clinic.summary.OpenIntention.ViewNewPatient
2627
import java.util.UUID
28+
import org.simple.clinic.medicalhistory.Answer as MedicalHistoryAnswer
2729

2830
class PatientSummaryUpdate(
2931
private val isPatientReassignmentFeatureEnabled: Boolean,
@@ -145,7 +147,7 @@ class PatientSummaryUpdate(
145147
}
146148

147149
isEligibleForNonLabBasedCvdRisk && shouldCalculateCVDRisk -> {
148-
dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient))
150+
dispatch(CalculateNonLabBasedCVDRisk(model.patientSummaryProfile!!.patient))
149151
}
150152

151153
isEligibleForNonLabBasedCvdRisk -> {
@@ -179,7 +181,20 @@ class PatientSummaryUpdate(
179181
event: StatinInfoLoaded,
180182
model: PatientSummaryModel
181183
): Next<PatientSummaryModel, PatientSummaryEffect> {
182-
return next(model.updateStatinInfo(event.statinInfo))
184+
val canShowSmokingStatusDialog =
185+
event.statinInfo.canPrescribeStatin &&
186+
(event.statinInfo.cvdRisk?.level == CVDRiskLevel.LOW_HIGH ||
187+
event.statinInfo.cvdRisk?.level == CVDRiskLevel.MEDIUM_HIGH) &&
188+
event.statinInfo.isSmoker == MedicalHistoryAnswer.Unanswered &&
189+
!model.hasShownSmokingStatusDialog
190+
191+
return if (canShowSmokingStatusDialog) {
192+
next(model.updateStatinInfo(event.statinInfo)
193+
.showSmokingStatusDialog(),
194+
ShowSmokingStatusDialog)
195+
} else {
196+
next(model.updateStatinInfo(event.statinInfo))
197+
}
183198
}
184199

185200
private fun hypertensionNotNowClicked(continueToDiabetesDiagnosisWarning: Boolean): Next<PatientSummaryModel, PatientSummaryEffect> {

app/src/main/java/org/simple/clinic/summary/compose/StatinNudgeView.kt

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import org.simple.clinic.R
4040
import org.simple.clinic.common.ui.components.FilledButton
4141
import org.simple.clinic.common.ui.theme.SimpleInverseTheme
4242
import org.simple.clinic.common.ui.theme.SimpleTheme
43+
import org.simple.clinic.cvdrisk.CVDRiskLevel
4344
import org.simple.clinic.cvdrisk.CVDRiskRange
4445
import org.simple.clinic.cvdrisk.StatinInfo
4546
import org.simple.clinic.medicalhistory.Answer
@@ -119,15 +120,10 @@ fun RiskText(
119120
val riskText = when {
120121
hasCVD -> stringResource(R.string.statin_alert_very_high_risk_patient)
121122
cvdRiskRange == null -> stringResource(R.string.statin_alert_at_risk_patient)
122-
cvdRiskRange.min > 10 -> stringResource(R.string.statin_alert_high_risk_patient_x, riskPercentage)
123-
cvdRiskRange.min < 5 -> stringResource(R.string.statin_alert_low_high_risk_patient_x, riskPercentage)
124-
else -> stringResource(R.string.statin_alert_medium_high_risk_patient_x, riskPercentage)
123+
else -> stringResource(cvdRiskRange.level.displayStringResId, riskPercentage)
125124
}
126125

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

132128
val textMeasurer = rememberTextMeasurer()
133129
val textWidth = textMeasurer.measure(
@@ -164,11 +160,11 @@ fun RiskProgressBar(
164160
endOffset: Float
165161
) {
166162
val riskColors = listOf(
167-
Color(0xFF00B849), // Very Low
168-
Color(0xFFFFC800), // Low
169-
SimpleTheme.colors.material.error, // Medium
170-
Color(0xFFB81631), // High
171-
Color(0xFF731814) // Very High
163+
Color(0xFF00B849), // Low
164+
Color(0xFFFFC800), // MEDIUM
165+
SimpleTheme.colors.material.error, // HIGH
166+
Color(0xFFB81631), // VERY HIGH
167+
Color(0xFF731814) // CRITICAL
172168
)
173169

174170
val indicatorColor = Color(0xFF2F363D)
@@ -240,26 +236,28 @@ fun DescriptionText(
240236
statinInfo: StatinInfo
241237
) {
242238
val text = when {
243-
statinInfo.cvdRisk == null ||
244-
statinInfo.cvdRisk.min >= 10 -> stringResource(R.string.statin_alert_refer_to_doctor)
239+
statinInfo.cvdRisk == null || statinInfo.cvdRisk.level == CVDRiskLevel.HIGH ->
240+
stringResource(R.string.statin_alert_refer_to_doctor)
245241

246-
statinInfo.isSmoker == Answer.Unanswered &&
247-
statinInfo.bmiReading == null -> stringResource(R.string.statin_alert_add_smoking_and_bmi_info)
242+
statinInfo.isSmoker == Answer.Unanswered && statinInfo.bmiReading == null ->
243+
stringResource(R.string.statin_alert_add_smoking_and_bmi_info)
248244

249-
statinInfo.isSmoker == Answer.Unanswered &&
250-
statinInfo.bmiReading != null -> stringResource(R.string.statin_alert_add_smoking_info)
245+
statinInfo.isSmoker == Answer.Unanswered && statinInfo.bmiReading != null ->
246+
stringResource(R.string.statin_alert_add_smoking_info)
251247

252-
statinInfo.isSmoker != Answer.Unanswered &&
253-
statinInfo.bmiReading == null -> stringResource(R.string.statin_alert_add_bmi_info)
248+
statinInfo.isSmoker != Answer.Unanswered && statinInfo.bmiReading == null ->
249+
stringResource(R.string.statin_alert_add_bmi_info)
254250

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

258254
val textColor = when {
259-
statinInfo.cvdRisk == null ||
260-
statinInfo.cvdRisk.min >= 10 -> SimpleTheme.colors.material.error
255+
statinInfo.cvdRisk == null || statinInfo.cvdRisk.level == CVDRiskLevel.HIGH
256+
-> SimpleTheme.colors.material.error
257+
258+
statinInfo.isSmoker == Answer.Unanswered || statinInfo.bmiReading == null ->
259+
SimpleTheme.colors.onSurface67
261260

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

@@ -324,11 +322,11 @@ fun StainNudgeAddButtons(
324322

325323
fun getOffsets(cvdRiskRange: CVDRiskRange?, size: Size): Pair<Float, Float> {
326324
val riskRanges = listOf(
327-
0..4, // Very Low
328-
5..9, // Low
329-
10..19, // Medium
330-
20..29, // High
331-
30..33 // Very High
325+
0..4, // LOW
326+
5..9, // MEDIUM
327+
10..19, // HIGH
328+
20..29, // VERY HIGH
329+
30..33 // CRITICAL
332330
)
333331

334332
val startRatio: Float

app/src/test/java/org/simple/clinic/summary/PatientSummaryUpdateTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,23 @@ class PatientSummaryUpdateTest {
23582358
))
23592359
}
23602360

2361+
@Test
2362+
fun `when statin info is loaded and risk is low-high, then update the state and show smoking status dialog`() {
2363+
val statinInfo = StatinInfo(
2364+
canPrescribeStatin = true,
2365+
CVDRiskRange(7, 14),
2366+
)
2367+
updateSpec
2368+
.given(defaultModel)
2369+
.whenEvent(StatinInfoLoaded(
2370+
statinInfo = statinInfo
2371+
))
2372+
.then(assertThatNext(
2373+
hasModel(defaultModel.updateStatinInfo(statinInfo).showSmokingStatusDialog()),
2374+
hasEffects(ShowSmokingStatusDialog)
2375+
))
2376+
}
2377+
23612378
@Test
23622379
fun `when add smoking button is clicked, then show the smoking status dialog`() {
23632380
updateSpec

0 commit comments

Comments
 (0)