diff --git a/CHANGELOG.md b/CHANGELOG.md index 795786e0317..746396b0fcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Bump Sentry Android to v5.9.0 - Bump AndroidX ViewModel to v2.9.3 - Update Compose BOM to v2025.08.01 +- Migrate new medical history screen to Jetpack Compose ### Changes diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffect.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffect.kt index 011c702b8df..37858da59a7 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffect.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffect.kt @@ -26,3 +26,5 @@ data object ShowHypertensionDiagnosisRequiredError : NewMedicalHistoryViewEffect data object ShowChangeDiagnosisErrorDialog : NewMedicalHistoryViewEffect() data object ShowOngoingDiabetesTreatmentErrorDialog : NewMedicalHistoryViewEffect() + +data object GoBack : NewMedicalHistoryViewEffect() diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEvent.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEvent.kt index 36d659522c8..88c6b492738 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEvent.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEvent.kt @@ -32,3 +32,7 @@ data class SyncTriggered(val registeredPatientUuid: UUID) : NewMedicalHistoryEve data object ChangeDiagnosisNotNowClicked : NewMedicalHistoryEvent() { override val analyticsName = "New Medical History:Change Diagnosis:Not Now Clicked" } + +data object BackClicked : NewMedicalHistoryEvent() { + override val analyticsName: String = "New Medical History:Back Clicked" +} diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt index c95abe59eb3..6a32b3d8b56 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreen.kt @@ -6,66 +6,35 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.stringResource +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.jakewharton.rxbinding3.view.clicks -import com.spotify.mobius.functions.Consumer -import io.reactivex.Observable -import io.reactivex.rxkotlin.cast -import io.reactivex.subjects.PublishSubject -import io.reactivex.subjects.Subject import kotlinx.parcelize.Parcelize import org.simple.clinic.R -import org.simple.clinic.ReportAnalyticsEvents import org.simple.clinic.appconfig.Country -import org.simple.clinic.common.ui.theme.SimpleTheme -import org.simple.clinic.databinding.ScreenNewMedicalHistoryBinding import org.simple.clinic.di.injector -import org.simple.clinic.feature.Feature import org.simple.clinic.feature.Features -import org.simple.clinic.medicalhistory.Answer -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithDiabetes -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithHypertension -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnDiabetesTreatment -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnHypertensionTreatment -import org.simple.clinic.medicalhistory.OngoingMedicalHistoryEntry import org.simple.clinic.medicalhistory.SelectDiagnosisErrorDialog import org.simple.clinic.medicalhistory.SelectOngoingDiabetesTreatmentErrorDialog import org.simple.clinic.medicalhistory.SelectOngoingHypertensionTreatmentErrorDialog -import org.simple.clinic.medicalhistory.ui.HistoryContainer -import org.simple.clinic.medicalhistory.ui.MedicalHistoryDiagnosisWithTreatment -import org.simple.clinic.medicalhistory.ui.TobaccoQuestion +import org.simple.clinic.medicalhistory.ui.NewMedicalHistoryUi +import org.simple.clinic.mobius.DisposableViewEffect +import org.simple.clinic.navigation.v2.HandlesBack import org.simple.clinic.navigation.v2.Router import org.simple.clinic.navigation.v2.ScreenKey -import org.simple.clinic.navigation.v2.fragments.BaseScreen import org.simple.clinic.summary.OpenIntention import org.simple.clinic.summary.PatientSummaryScreenKey import org.simple.clinic.util.UtcClock -import org.simple.clinic.util.applyInsetsBottomPadding -import org.simple.clinic.util.applyStatusBarPadding -import org.simple.clinic.widgets.ProgressMaterialButton.ButtonState.Enabled -import org.simple.clinic.widgets.ProgressMaterialButton.ButtonState.InProgress +import org.simple.clinic.util.unsafeLazy import java.time.Instant import java.util.UUID import javax.inject.Inject -class NewMedicalHistoryScreen : BaseScreen< - NewMedicalHistoryScreen.Key, - ScreenNewMedicalHistoryBinding, - NewMedicalHistoryModel, - NewMedicalHistoryEvent, - NewMedicalHistoryEffect, - NewMedicalHistoryViewEffect>(), NewMedicalHistoryUi, NewMedicalHistoryUiActions { +class NewMedicalHistoryScreen : Fragment(), NewMedicalHistoryUiActions, HandlesBack { @Inject lateinit var router: Router @@ -85,210 +54,52 @@ class NewMedicalHistoryScreen : BaseScreen< @Inject lateinit var features: Features - private val appbar - get() = binding.appbar - - private val toolbar - get() = binding.toolbar - - private val nextButtonFrame - get() = binding.nextButtonFrame - - private val nextButton - get() = binding.nextButton - - private var showSmokerQuestion by mutableStateOf(false) - private var showSmokelessTobaccoQuestion by mutableStateOf(false) - private var showDiabetesQuestion by mutableStateOf(false) - private var showHypertensionTreatmentQuestion by mutableStateOf(false) - private var showDiabetesTreatmentQuestion by mutableStateOf(false) - private var showDiabetesDiagnosis by mutableStateOf(false) - private var ongoingMedicalHistoryEntry by mutableStateOf(null) - - private val composeView - get() = binding.composeView + @Inject + lateinit var newMedicalHistoryEffectHandler: NewMedicalHistoryEffectHandler.Factory - private val hotEvents: Subject = PublishSubject.create() + private val viewEffectHandler by unsafeLazy { NewMedicalHistoryViewEffectHandler(this) } - override fun defaultModel() = NewMedicalHistoryModel.default( - country = country, - showIsSmokingQuestion = features.isEnabled(Feature.NonLabBasedStatinNudge) || - features.isEnabled(Feature.LabBasedStatinNudge), - showSmokelessTobaccoQuestion = country.isoCountryCode != Country.ETHIOPIA + private val viewModel by viewModels( + factoryProducer = { + NewMedicalHistoryViewModel.factory( + country = country, + features = features, + effectHandlerFactory = effectHandlerFactory) + } ) - override fun bindView( - layoutInflater: LayoutInflater, - container: ViewGroup? - ) = ScreenNewMedicalHistoryBinding.inflate(layoutInflater, container, false) - - override fun createUpdate() = NewMedicalHistoryUpdate() - - override fun events() = Observable - .merge( - hotEvents, - saveClicks() - ) - .compose(ReportAnalyticsEvents()) - .cast() - - override fun createEffectHandler( - viewEffectsConsumer: Consumer - ) = effectHandlerFactory - .create( - viewEffectsConsumer = viewEffectsConsumer - ) - .build() - - override fun createInit() = NewMedicalHistoryInit() - - override fun uiRenderer() = NewMedicalHistoryUiRenderer(this) - - override fun viewEffectHandler() = NewMedicalHistoryViewEffectHandler(this) - override fun onAttach(context: Context) { super.onAttach(context) context.injector().inject(this) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - appbar.applyStatusBarPadding() - nextButtonFrame.applyInsetsBottomPadding() - toolbar.setNavigationOnClickListener { - router.pop() - } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - composeView.apply { - setViewCompositionStrategy( - ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed - ) setContent { - SimpleTheme { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(dimensionResource(R.dimen.spacing_8)), - verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.spacing_8)) - ) { - MedicalHistoryDiagnosisWithTreatment( - diagnosisLabel = stringResource(R.string.medicalhistory_diagnosis_hypertension_required), - diagnosisQuestion = DiagnosedWithHypertension, - diagnosisAnswer = ongoingMedicalHistoryEntry?.diagnosedWithHypertension, - treatmentQuestion = IsOnHypertensionTreatment(country.isoCountryCode), - treatmentAnswer = ongoingMedicalHistoryEntry?.isOnHypertensionTreatment, - showTreatmentQuestion = showHypertensionTreatmentQuestion - ) { question, answer -> - hotEvents.onNext(NewMedicalHistoryAnswerToggled(question, answer)) - } - if (showDiabetesDiagnosis) { - MedicalHistoryDiagnosisWithTreatment( - diagnosisLabel = stringResource(R.string.medicalhistory_diagnosis_diabetes_required), - diagnosisQuestion = DiagnosedWithDiabetes, - diagnosisAnswer = ongoingMedicalHistoryEntry?.hasDiabetes, - treatmentQuestion = IsOnDiabetesTreatment, - treatmentAnswer = ongoingMedicalHistoryEntry?.isOnDiabetesTreatment, - showTreatmentQuestion = showDiabetesTreatmentQuestion - ) { question, answer -> - hotEvents.onNext(NewMedicalHistoryAnswerToggled(question, answer)) - } - } - HistoryContainer( - heartAttackAnswer = ongoingMedicalHistoryEntry?.hasHadHeartAttack, - strokeAnswer = ongoingMedicalHistoryEntry?.hasHadStroke, - kidneyAnswer = ongoingMedicalHistoryEntry?.hasHadKidneyDisease, - diabetesAnswer = ongoingMedicalHistoryEntry?.hasDiabetes, - showDiabetesQuestion = showDiabetesQuestion, - ) { question, answer -> - hotEvents.onNext(NewMedicalHistoryAnswerToggled(question, answer)) - } - if (showSmokerQuestion) { - TobaccoQuestion( - isSmokingAnswer = ongoingMedicalHistoryEntry?.isSmoking, - isUsingSmokelessTobaccoAnswer = ongoingMedicalHistoryEntry?.isUsingSmokelessTobacco, - showSmokelessTobaccoQuestion = showSmokelessTobaccoQuestion, - ) { question, answer -> - hotEvents.onNext(NewMedicalHistoryAnswerToggled(question, answer)) + viewModel.viewEffects.DisposableViewEffect(viewEffectHandler::handle) + + val model by viewModel.models.observeAsState() + model?.let { + NewMedicalHistoryUi( + model = it, + navigationIconClick = { onBackPressed() }, + onNextClick = { + viewModel.dispatch(SaveMedicalHistoryClicked()) } - } + ) { question, answer -> + viewModel.dispatch(NewMedicalHistoryAnswerToggled(question, answer)) } } } } } - private fun saveClicks() = nextButton - .clicks() - .map { SaveMedicalHistoryClicked() } - override fun openPatientSummaryScreen(patientUuid: UUID) { router.push(PatientSummaryScreenKey(patientUuid, OpenIntention.ViewNewPatient, Instant.now(utcClock))) } - override fun setPatientName(patientName: String) { - toolbar.title = patientName - } - - override fun populateOngoingMedicalHistoryEntry(ongoingMedicalHistoryEntry: OngoingMedicalHistoryEntry) { - this.ongoingMedicalHistoryEntry = ongoingMedicalHistoryEntry - } - - override fun showDiabetesDiagnosisView() { - showDiabetesDiagnosis = true - } - - override fun hideDiabetesDiagnosisView() { - showDiabetesDiagnosis = false - } - - override fun hideDiabetesHistorySection() { - showDiabetesQuestion = false - } - - override fun showDiabetesHistorySection() { - showDiabetesQuestion = true - } - - override fun showNextButtonProgress() { - nextButton.setButtonState(InProgress) - } - - override fun hideNextButtonProgress() { - nextButton.setButtonState(Enabled) - } - - override fun showHypertensionTreatmentQuestion(answer: Answer) { - showHypertensionTreatmentQuestion = true - } - - override fun hideHypertensionTreatmentQuestion() { - showHypertensionTreatmentQuestion = false - } - - override fun showDiabetesTreatmentQuestion(answer: Answer) { - showDiabetesTreatmentQuestion = true - } - - override fun hideDiabetesTreatmentQuestion() { - showDiabetesTreatmentQuestion = false - } - - override fun showCurrentSmokerQuestion() { - showSmokerQuestion = true - } - - override fun hideCurrentSmokerQuestion() { - showSmokerQuestion = false - } - - override fun showSmokelessTobaccoQuestion() { - showSmokelessTobaccoQuestion = true - } - - override fun hideSmokelessTobaccoQuestion() { - showSmokelessTobaccoQuestion = false - } - override fun showOngoingHypertensionTreatmentErrorDialog() { SelectOngoingHypertensionTreatmentErrorDialog.show(fragmentManager = activity.supportFragmentManager) } @@ -297,6 +108,10 @@ class NewMedicalHistoryScreen : BaseScreen< SelectOngoingDiabetesTreatmentErrorDialog.show(fragmentManager = activity.supportFragmentManager) } + override fun goBack() { + router.pop() + } + override fun showDiagnosisRequiredErrorDialog() { SelectDiagnosisErrorDialog.show(activity.supportFragmentManager) } @@ -315,11 +130,16 @@ class NewMedicalHistoryScreen : BaseScreen< .setMessage(getString(R.string.change_diagnosis_message)) .setPositiveButton(getString(R.string.change_diagnosis_positive), null) .setNegativeButton(getString(R.string.change_diagnosis_negative)) { _, _ -> - hotEvents.onNext(ChangeDiagnosisNotNowClicked) + viewModel.dispatch(ChangeDiagnosisNotNowClicked) } .show() } + override fun onBackPressed(): Boolean { + viewModel.dispatch(BackClicked) + return true + } + interface Injector { fun inject(target: NewMedicalHistoryScreen) } diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUi.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUi.kt deleted file mode 100644 index b1e1e9ca559..00000000000 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUi.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.simple.clinic.medicalhistory.newentry - -import org.simple.clinic.medicalhistory.Answer -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion -import org.simple.clinic.medicalhistory.OngoingMedicalHistoryEntry - -interface NewMedicalHistoryUi { - fun setPatientName(patientName: String) - fun populateOngoingMedicalHistoryEntry(ongoingMedicalHistoryEntry: OngoingMedicalHistoryEntry) - fun showDiabetesDiagnosisView() - fun hideDiabetesDiagnosisView() - fun showDiabetesHistorySection() - fun hideDiabetesHistorySection() - fun showNextButtonProgress() - fun hideNextButtonProgress() - fun showHypertensionTreatmentQuestion(answer: Answer) - fun hideHypertensionTreatmentQuestion() - fun showDiabetesTreatmentQuestion(answer: Answer) - fun hideDiabetesTreatmentQuestion() - fun showCurrentSmokerQuestion() - fun hideCurrentSmokerQuestion() - fun showSmokelessTobaccoQuestion() - fun hideSmokelessTobaccoQuestion() -} diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiActions.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiActions.kt index 705a86e7f0a..192e04f2e87 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiActions.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiActions.kt @@ -9,4 +9,6 @@ interface NewMedicalHistoryUiActions { fun showHypertensionDiagnosisRequiredErrorDialog() fun showChangeDiagnosisErrorDialog() fun showOngoingDiabetesTreatmentErrorDialog() + + fun goBack() } diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRenderer.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRenderer.kt deleted file mode 100644 index bf4b78d68e0..00000000000 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRenderer.kt +++ /dev/null @@ -1,89 +0,0 @@ -package org.simple.clinic.medicalhistory.newentry - -import org.simple.clinic.mobius.ViewRenderer - -class NewMedicalHistoryUiRenderer( - private val ui: NewMedicalHistoryUi -) : ViewRenderer { - - override fun render(model: NewMedicalHistoryModel) { - if (model.hasLoadedPatientEntry) { - renderPatientName(model) - } - - renderMedicalHistoryQuestions(model) - - if (model.hasLoadedCurrentFacility && model.facilityDiabetesManagementEnabled) { - renderDiabetesManagementEnabled(model) - } else { - renderDiabetesManagementDisabled() - } - - renderSmokingQuestion(model) - renderSmokelessTobaccoQuestion(model) - - renderNextButton(model) - } - - private fun renderPatientName(model: NewMedicalHistoryModel) { - ui.setPatientName(model.ongoingPatientEntry!!.personalDetails!!.fullName) - } - - private fun renderMedicalHistoryQuestions(model: NewMedicalHistoryModel) { - with(model.ongoingMedicalHistoryEntry) { - renderHypertensionTreatmentQuestion(model) - } - ui.populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - } - - private fun renderHypertensionTreatmentQuestion(model: NewMedicalHistoryModel) { - if (model.showOngoingHypertensionTreatment) { - ui.showHypertensionTreatmentQuestion(model.ongoingMedicalHistoryEntry.isOnHypertensionTreatment) - } else { - ui.hideHypertensionTreatmentQuestion() - } - } - - private fun renderDiabetesManagementEnabled(model: NewMedicalHistoryModel) { - ui.showDiabetesDiagnosisView() - ui.hideDiabetesHistorySection() - renderDiabetesTreatmentQuestion(model) - } - - private fun renderDiabetesTreatmentQuestion(model: NewMedicalHistoryModel) { - if (model.showOngoingDiabetesTreatment) { - ui.showDiabetesTreatmentQuestion(model.ongoingMedicalHistoryEntry.isOnDiabetesTreatment) - } else { - ui.hideDiabetesTreatmentQuestion() - } - } - - private fun renderDiabetesManagementDisabled() { - ui.hideDiabetesDiagnosisView() - ui.showDiabetesHistorySection() - } - - private fun renderSmokingQuestion(model: NewMedicalHistoryModel) { - if (model.showIsSmokingQuestion) { - ui.showCurrentSmokerQuestion() - } else { - ui.hideCurrentSmokerQuestion() - } - } - - private fun renderSmokelessTobaccoQuestion(model: NewMedicalHistoryModel) { - if (model.showSmokelessTobaccoQuestion) { - ui.showSmokelessTobaccoQuestion() - } else { - ui.hideSmokelessTobaccoQuestion() - } - } - - private fun renderNextButton(model: NewMedicalHistoryModel) { - if (model.registeringPatient) { - ui.showNextButtonProgress() - } else { - ui.hideNextButtonProgress() - } - } -} diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdate.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdate.kt index 3de80152c9d..626b780dfb3 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdate.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdate.kt @@ -21,6 +21,7 @@ class NewMedicalHistoryUpdate : Update currentFacilityLoaded(event, model) is SyncTriggered -> dispatch(OpenPatientSummaryScreen(event.registeredPatientUuid)) is ChangeDiagnosisNotNowClicked -> registerPatient(model) + is BackClicked -> dispatch(GoBack) } } diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewEffectHandler.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewEffectHandler.kt index c3f21b34c4c..6e4434cfdf5 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewEffectHandler.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewEffectHandler.kt @@ -15,6 +15,7 @@ class NewMedicalHistoryViewEffectHandler( ShowHypertensionDiagnosisRequiredError -> uiActions.showHypertensionDiagnosisRequiredErrorDialog() ShowChangeDiagnosisErrorDialog -> uiActions.showChangeDiagnosisErrorDialog() ShowOngoingDiabetesTreatmentErrorDialog -> uiActions.showOngoingDiabetesTreatmentErrorDialog() + GoBack -> uiActions.goBack() }.exhaustive() } } diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewModel.kt b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewModel.kt new file mode 100644 index 00000000000..e6a0c508b52 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryViewModel.kt @@ -0,0 +1,52 @@ +package org.simple.clinic.medicalhistory.newentry + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.spotify.mobius.rx2.RxMobius +import org.simple.clinic.appconfig.Country +import org.simple.clinic.feature.Feature +import org.simple.clinic.feature.Features +import org.simple.clinic.mobius.MobiusViewModel + +class NewMedicalHistoryViewModel( + country: Country, + features: Features, + savedStateHandle: SavedStateHandle, + effectHandlerFactory: NewMedicalHistoryEffectHandler.Factory +) : MobiusViewModel( + modelKey = NewMedicalHistoryModel::class.java.name, + savedStateHandle = savedStateHandle, + defaultModel = NewMedicalHistoryModel.default( + country = country, + showIsSmokingQuestion = features.isEnabled(Feature.NonLabBasedStatinNudge) || + features.isEnabled(Feature.LabBasedStatinNudge), + showSmokelessTobaccoQuestion = country.isoCountryCode != Country.ETHIOPIA + ), + init = NewMedicalHistoryInit(), + loopFactoryProvider = { viewEffectsConsumer -> + RxMobius.loop( + NewMedicalHistoryUpdate(), + effectHandlerFactory.create(viewEffectsConsumer).build() + ) + } +) { + + companion object { + fun factory( + country: Country, + features: Features, + effectHandlerFactory: NewMedicalHistoryEffectHandler.Factory + ) = viewModelFactory { + initializer { + NewMedicalHistoryViewModel( + country = country, + features = features, + savedStateHandle = createSavedStateHandle(), + effectHandlerFactory = effectHandlerFactory + ) + } + } + } +} diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/ui/NewMedicalHistoryUi.kt b/app/src/main/java/org/simple/clinic/medicalhistory/ui/NewMedicalHistoryUi.kt new file mode 100644 index 00000000000..10f1141b261 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/medicalhistory/ui/NewMedicalHistoryUi.kt @@ -0,0 +1,157 @@ +package org.simple.clinic.medicalhistory.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import org.simple.clinic.R +import org.simple.clinic.appconfig.Country +import org.simple.clinic.common.ui.components.FilledButtonWithFrame +import org.simple.clinic.common.ui.components.TopAppBar +import org.simple.clinic.common.ui.theme.SimpleTheme +import org.simple.clinic.medicalhistory.Answer +import org.simple.clinic.medicalhistory.MedicalHistoryQuestion +import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithDiabetes +import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithHypertension +import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnDiabetesTreatment +import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnHypertensionTreatment +import org.simple.clinic.medicalhistory.OngoingMedicalHistoryEntry +import org.simple.clinic.medicalhistory.newentry.NewMedicalHistoryModel + +@Composable +fun NewMedicalHistoryUi( + model: NewMedicalHistoryModel, + navigationIconClick: () -> Unit, + onNextClick: () -> Unit, + onSelectionChange: (MedicalHistoryQuestion, Answer) -> Unit, +) { + SimpleTheme { + Scaffold( + modifier = Modifier.fillMaxWidth(), + topBar = { + TopAppBar( + navigationIcon = { + IconButton(onClick = navigationIconClick) { + Icon(imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) + } + }, + title = { + Text( + text = model.ongoingPatientEntry?.personalDetails?.fullName ?: "", + ) + }, + ) + }, + bottomBar = { + FilledButtonWithFrame( + testTag = "NEXT_BUTTON", + onClick = onNextClick, + ) { + if (!model.registeringPatient) { + Text( + text = stringResource(R.string.newmedicalhistory_next).uppercase() + ) + } else { + CircularProgressIndicator( + modifier = Modifier.size(dimensionResource(R.dimen.spacing_24)), + color = MaterialTheme.colors.onPrimary + ) + } + + } + }, + ) { paddingValues -> + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(scrollState) + .padding(paddingValues) + .padding(dimensionResource(R.dimen.spacing_8)), + verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.spacing_8)) + ) { + val showDiabetesDiagnosis = model.hasLoadedCurrentFacility && model.facilityDiabetesManagementEnabled + MedicalHistoryDiagnosisWithTreatment( + diagnosisLabel = stringResource(R.string.medicalhistory_diagnosis_hypertension_required), + diagnosisQuestion = DiagnosedWithHypertension, + diagnosisAnswer = model.ongoingMedicalHistoryEntry.diagnosedWithHypertension, + treatmentQuestion = IsOnHypertensionTreatment(model.country.isoCountryCode), + treatmentAnswer = model.ongoingMedicalHistoryEntry.isOnHypertensionTreatment, + showTreatmentQuestion = model.showOngoingHypertensionTreatment, + onSelectionChange = onSelectionChange + ) + if (showDiabetesDiagnosis) { + MedicalHistoryDiagnosisWithTreatment( + diagnosisLabel = stringResource(R.string.medicalhistory_diagnosis_diabetes_required), + diagnosisQuestion = DiagnosedWithDiabetes, + diagnosisAnswer = model.ongoingMedicalHistoryEntry.hasDiabetes, + treatmentQuestion = IsOnDiabetesTreatment, + treatmentAnswer = model.ongoingMedicalHistoryEntry.isOnDiabetesTreatment, + showTreatmentQuestion = model.showOngoingDiabetesTreatment, + onSelectionChange = onSelectionChange + ) + } + HistoryContainer( + heartAttackAnswer = model.ongoingMedicalHistoryEntry.hasHadHeartAttack, + strokeAnswer = model.ongoingMedicalHistoryEntry.hasHadStroke, + kidneyAnswer = model.ongoingMedicalHistoryEntry.hasHadKidneyDisease, + diabetesAnswer = model.ongoingMedicalHistoryEntry.hasDiabetes, + showDiabetesQuestion = !showDiabetesDiagnosis, + onAnswerChange = onSelectionChange + ) + if (model.showIsSmokingQuestion) { + TobaccoContainer( + isSmokingAnswer = model.ongoingMedicalHistoryEntry.isSmoking, + isUsingSmokelessTobaccoAnswer = model.ongoingMedicalHistoryEntry.isUsingSmokelessTobacco, + showSmokelessTobaccoQuestion = model.showSmokelessTobaccoQuestion, + onAnswerChange = onSelectionChange + ) + } + } + } + } +} + +private val previewMedicalHistoryModel = NewMedicalHistoryModel( + country = Country( + isoCountryCode = "IN", + displayName = "India", + isdCode = "91", + deployments = listOf() + ), + ongoingPatientEntry = null, + ongoingMedicalHistoryEntry = OngoingMedicalHistoryEntry(), + currentFacility = null, + nextButtonState = null, + hasShownChangeDiagnosisError = true, + showIsSmokingQuestion = true, + showSmokelessTobaccoQuestion = true +) + +@Preview +@Composable +private fun NewMedicalHistoryUiPreview() { + NewMedicalHistoryUi( + model = previewMedicalHistoryModel, + navigationIconClick = {}, + onNextClick = {} + ) { question, answer -> + //do nothing + } +} diff --git a/app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoQuestion.kt b/app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoContainer.kt similarity index 98% rename from app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoQuestion.kt rename to app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoContainer.kt index 57676f5724e..0962790846c 100644 --- a/app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoQuestion.kt +++ b/app/src/main/java/org/simple/clinic/medicalhistory/ui/TobaccoContainer.kt @@ -18,7 +18,7 @@ import org.simple.clinic.medicalhistory.Answer import org.simple.clinic.medicalhistory.MedicalHistoryQuestion @Composable -fun TobaccoQuestion( +fun TobaccoContainer( isSmokingAnswer: Answer?, isUsingSmokelessTobaccoAnswer: Answer?, showSmokelessTobaccoQuestion: Boolean, @@ -105,7 +105,7 @@ fun TobaccoUseContainer( @Preview @Composable fun TobaccoQuestionPreview() { - TobaccoQuestion( + TobaccoContainer( isSmokingAnswer = Answer.Yes, isUsingSmokelessTobaccoAnswer = Answer.Unanswered, showSmokelessTobaccoQuestion = false @@ -117,7 +117,7 @@ fun TobaccoQuestionPreview() { @Preview @Composable fun TobaccoWithSmokelessQuestionPreview() { - TobaccoQuestion( + TobaccoContainer( isSmokingAnswer = Answer.Yes, isUsingSmokelessTobaccoAnswer = Answer.Yes, showSmokelessTobaccoQuestion = true diff --git a/app/src/main/java/org/simple/clinic/summary/medicalhistory/ui/MedicalHistorySummary.kt b/app/src/main/java/org/simple/clinic/summary/medicalhistory/ui/MedicalHistorySummary.kt index 68889cb50ab..a993b015f13 100644 --- a/app/src/main/java/org/simple/clinic/summary/medicalhistory/ui/MedicalHistorySummary.kt +++ b/app/src/main/java/org/simple/clinic/summary/medicalhistory/ui/MedicalHistorySummary.kt @@ -20,7 +20,7 @@ import org.simple.clinic.medicalhistory.Answer import org.simple.clinic.medicalhistory.MedicalHistoryQuestion import org.simple.clinic.medicalhistory.ui.HistoryContainer import org.simple.clinic.medicalhistory.ui.MedicalHistoryQuestionItem -import org.simple.clinic.medicalhistory.ui.TobaccoQuestion +import org.simple.clinic.medicalhistory.ui.TobaccoContainer @Composable fun MedicalHistorySummary( @@ -62,7 +62,7 @@ fun MedicalHistorySummary( ) if (showSmokerQuestion) { - TobaccoQuestion( + TobaccoContainer( isSmokingAnswer = isSmokingAnswer, isUsingSmokelessTobaccoAnswer = isUsingSmokelessTobaccoAnswer, showSmokelessTobaccoQuestion = showSmokelessTobaccoQuestion, diff --git a/app/src/main/res/layout/screen_new_medical_history.xml b/app/src/main/res/layout/screen_new_medical_history.xml deleted file mode 100644 index bc7dba3721f..00000000000 --- a/app/src/main/res/layout/screen_new_medical_history.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffectHandlerTest.kt index a67644e1c7e..8b41c44c9e6 100644 --- a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffectHandlerTest.kt +++ b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryEffectHandlerTest.kt @@ -1,12 +1,12 @@ package org.simple.clinic.medicalhistory.newentry -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoMoreInteractions -import org.mockito.kotlin.verifyNoInteractions import dagger.Lazy import org.junit.After import org.junit.Test +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoInteractions +import org.mockito.kotlin.verifyNoMoreInteractions import org.simple.clinic.TestData import org.simple.clinic.mobius.EffectHandlerTestCase import org.simple.clinic.sync.DataSync @@ -128,4 +128,16 @@ class NewMedicalHistoryEffectHandlerTest { testCase.assertNoOutgoingEvents() } + + @Test + fun `when back is clicked, then go back to previous screen`() { + // when + testCase.dispatch(GoBack) + + // then + verify(uiActions).goBack() + verifyNoMoreInteractions(uiActions) + + testCase.assertNoOutgoingEvents() + } } diff --git a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreenLogicTest.kt b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreenLogicTest.kt index 18aab4b1ccd..56f2e5a55c8 100644 --- a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreenLogicTest.kt +++ b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryScreenLogicTest.kt @@ -10,8 +10,6 @@ import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.inOrder import org.mockito.kotlin.mock -import org.mockito.kotlin.times -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.simple.clinic.TestData import org.simple.clinic.appconfig.Country @@ -29,9 +27,7 @@ import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsSmoking import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsUsingSmokelessTobacco import org.simple.clinic.medicalhistory.MedicalHistoryRepository import org.simple.clinic.medicalhistory.OngoingMedicalHistoryEntry -import org.simple.clinic.patient.Gender import org.simple.clinic.patient.OngoingNewPatientEntry -import org.simple.clinic.patient.OngoingNewPatientEntry.PersonalDetails import org.simple.clinic.patient.PatientProfile import org.simple.clinic.patient.PatientRepository import org.simple.clinic.util.RxErrorsRule @@ -49,9 +45,7 @@ class NewMedicalHistoryScreenLogicTest { @get:Rule val rxErrorsRule = RxErrorsRule() - private val screen: NewMedicalHistoryUi = mock() private val uiActions: NewMedicalHistoryUiActions = mock() - private val viewRenderer = NewMedicalHistoryUiRenderer(screen) private val medicalHistoryRepository: MedicalHistoryRepository = mock() private val patientRepository: PatientRepository = mock() @@ -70,24 +64,6 @@ class NewMedicalHistoryScreenLogicTest { testFixture.dispose() } - @Test - fun `when screen is started then the patient's name should be shown on the toolbar`() { - val patientName = "Ashok Kumar" - val patientEntry = OngoingNewPatientEntry(personalDetails = PersonalDetails( - fullName = patientName, - dateOfBirth = null, - age = "20", - gender = Gender.Transgender)) - whenever(patientRepository.ongoingEntry()).thenReturn(patientEntry) - - startMobiusLoop(ongoingPatientEntry = patientEntry) - - // This gets set twice: - // 1. When we read the patient entry - // 2. When we load the current facility and update the model - verify(screen, times(2)).setPatientName(patientName) - } - @Test fun `when save is clicked with selected answers then patient with the answers should be saved and summary screen should be opened`() { // given @@ -335,7 +311,7 @@ class NewMedicalHistoryScreenLogicTest { init = NewMedicalHistoryInit(), update = NewMedicalHistoryUpdate(), effectHandler = effectHandler, - modelUpdateListener = viewRenderer::render + modelUpdateListener = { /* no-op */ } ) testFixture.start() diff --git a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRendererTest.kt b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRendererTest.kt deleted file mode 100644 index fca91d984d0..00000000000 --- a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUiRendererTest.kt +++ /dev/null @@ -1,356 +0,0 @@ -package org.simple.clinic.medicalhistory.newentry - -import org.junit.Test -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoMoreInteractions -import org.simple.clinic.TestData -import org.simple.clinic.appconfig.Country -import org.simple.clinic.facility.FacilityConfig -import org.simple.clinic.medicalhistory.Answer.No -import org.simple.clinic.medicalhistory.Answer.Unanswered -import org.simple.clinic.medicalhistory.Answer.Yes -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithDiabetes -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithHypertension -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.HasHadAHeartAttack -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.HasHadAKidneyDisease -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.HasHadAStroke -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsSmoking -import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsUsingSmokelessTobacco -import java.util.UUID - -class NewMedicalHistoryUiRendererTest { - - private val facilityWithDiabetesManagementEnabled = TestData - .facility( - uuid = UUID.fromString("fb08c52e-24ac-4fa8-8573-13edd2f06232"), - facilityConfig = FacilityConfig( - diabetesManagementEnabled = true, - teleconsultationEnabled = false, - monthlyScreeningReportsEnabled = false, - monthlySuppliesReportsEnabled = false - ) - ) - - private val facilityWithDiabetesManagementDisabled = TestData - .facility( - uuid = UUID.fromString("66a52e56-b773-4692-b19c-a58636c6d85a"), - facilityConfig = FacilityConfig( - diabetesManagementEnabled = false, - teleconsultationEnabled = false, - monthlyScreeningReportsEnabled = false, - monthlySuppliesReportsEnabled = false - ) - ) - - private val country = TestData.country(isoCountryCode = Country.INDIA) - private val defaultModel = NewMedicalHistoryModel.default( - country = country, - showIsSmokingQuestion = false, - showSmokelessTobaccoQuestion = false - ) - - private val ui = mock() - private val uiRenderer = NewMedicalHistoryUiRenderer(ui) - - @Test - fun `the medical history answers must be rendered`() { - // given - val model = defaultModel - .answerChanged(DiagnosedWithHypertension, Unanswered) - .answerChanged(HasHadAHeartAttack, Yes) - .answerChanged(HasHadAStroke, No) - .answerChanged(HasHadAKidneyDisease, Unanswered) - - // when - uiRenderer.render(model) - - // then - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - verify(ui).hideNextButtonProgress() - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verify(ui).hideCurrentSmokerQuestion() - verify(ui).hideSmokelessTobaccoQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `if the facility supports diabetes management, show the diagnosis view and hide the diabetes history question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithHypertension, Yes) - .answerChanged(DiagnosedWithDiabetes, No) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).showHypertensionTreatmentQuestion(Unanswered) - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `if the facility does not support diabetes management, hide the diabetes diagnosis view and show the diabetes history question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementDisabled) - .answerChanged(DiagnosedWithDiabetes, Yes) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when patient is being saved, then show next button progress`() { - // given - val model = defaultModel - .registeringPatient() - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).showNextButtonProgress() - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when patient has hypertension and country is india, then show hypertension treatment question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithHypertension, Yes) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).showHypertensionTreatmentQuestion(Unanswered) - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when patient has hypertension and country is not from india, then don't show hypertension treatment question`() { - // given - val bangladesh = TestData.country(isoCountryCode = Country.BANGLADESH) - val model = NewMedicalHistoryModel.default( - country = bangladesh, - showIsSmokingQuestion = false, - showSmokelessTobaccoQuestion = false - ) - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithHypertension, Yes) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when patient does not have hypertension, then hide hypertension treatment question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when diabetes management is enabled and patient has diabetes and is from india, then show diabetes treatment question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithDiabetes, Yes) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).showDiabetesTreatmentQuestion(Unanswered) - verifyNoMoreInteractions(ui) - } - - @Test - fun `when diabetes management is enabled and patient has diabetes and is not from india, then don't show diabetes treatment question`() { - // given - val bangladesh = TestData.country(isoCountryCode = Country.BANGLADESH) - val model = NewMedicalHistoryModel.default( - country = bangladesh, - showIsSmokingQuestion = false, - showSmokelessTobaccoQuestion = false - ) - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithDiabetes, Yes) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when diabetes management is enabled and patient does not have diabetes, then don't show diabetes treatment question`() { - // given - val model = defaultModel - .currentFacilityLoaded(facilityWithDiabetesManagementEnabled) - .answerChanged(DiagnosedWithDiabetes, No) - - // when - uiRenderer.render(model) - - // then - verifyImplicitRenders(model) - verify(ui).showDiabetesDiagnosisView() - verify(ui).hideDiabetesHistorySection() - verify(ui).hideNextButtonProgress() - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).hideDiabetesTreatmentQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when show smoker question is enabled, then show current smoker question`() { - // given - val model = NewMedicalHistoryModel.default( - country = country, - showIsSmokingQuestion = true, - showSmokelessTobaccoQuestion = false - ) - .answerChanged(DiagnosedWithHypertension, Unanswered) - .answerChanged(HasHadAHeartAttack, Yes) - .answerChanged(HasHadAStroke, No) - .answerChanged(HasHadAKidneyDisease, Unanswered) - .answerChanged(IsSmoking, No) - .answerChanged(IsUsingSmokelessTobacco, No) - - // when - uiRenderer.render(model) - - // then - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - verify(ui).hideNextButtonProgress() - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verify(ui).showCurrentSmokerQuestion() - verify(ui).hideSmokelessTobaccoQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when show smoker question is disabled, then hide current smoker question`() { - // given - val model = NewMedicalHistoryModel.default( - country = country, - showIsSmokingQuestion = false, - showSmokelessTobaccoQuestion = false, - ) - .answerChanged(DiagnosedWithHypertension, Unanswered) - .answerChanged(HasHadAHeartAttack, Yes) - .answerChanged(HasHadAStroke, No) - .answerChanged(HasHadAKidneyDisease, Unanswered) - - // when - uiRenderer.render(model) - - // then - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - verify(ui).hideNextButtonProgress() - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verify(ui).hideCurrentSmokerQuestion() - verify(ui).hideSmokelessTobaccoQuestion() - verifyNoMoreInteractions(ui) - } - - @Test - fun `when show smokeless tobacco question is enabled, then show smokeless tobacco question`() { - // given - val model = NewMedicalHistoryModel.default( - country = country, - showIsSmokingQuestion = true, - showSmokelessTobaccoQuestion = true - ) - .answerChanged(DiagnosedWithHypertension, Unanswered) - .answerChanged(HasHadAHeartAttack, Yes) - .answerChanged(HasHadAStroke, No) - .answerChanged(HasHadAKidneyDisease, Unanswered) - .answerChanged(IsSmoking, No) - .answerChanged(IsUsingSmokelessTobacco, No) - - // when - uiRenderer.render(model) - - // then - verify(ui).hideHypertensionTreatmentQuestion() - verify(ui).populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - verify(ui).hideNextButtonProgress() - verify(ui).hideDiabetesDiagnosisView() - verify(ui).showDiabetesHistorySection() - verify(ui).showCurrentSmokerQuestion() - verify(ui).showSmokelessTobaccoQuestion() - verifyNoMoreInteractions(ui) - } - - private fun verifyImplicitRenders(model: NewMedicalHistoryModel) { - verify(ui).populateOngoingMedicalHistoryEntry(model.ongoingMedicalHistoryEntry) - verify(ui).hideCurrentSmokerQuestion() - verify(ui).hideSmokelessTobaccoQuestion() - } -} diff --git a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdateTest.kt b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdateTest.kt index 275434c0f98..fb1c63d87e3 100644 --- a/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdateTest.kt +++ b/app/src/test/java/org/simple/clinic/medicalhistory/newentry/NewMedicalHistoryUpdateTest.kt @@ -345,4 +345,15 @@ class NewMedicalHistoryUpdateTest { hasEffects(RegisterPatient(model.ongoingMedicalHistoryEntry)) )) } + + @Test + fun `when back is clicked, then go back`() { + updateSpec + .given(defaultModel) + .whenEvent(BackClicked) + .then(assertThatNext( + hasNoModel(), + hasEffects(GoBack) + )) + } }