@@ -6,66 +6,35 @@ import android.view.LayoutInflater
66import android.view.View
77import android.view.ViewGroup
88import androidx.appcompat.app.AppCompatActivity
9- import androidx.compose.foundation.layout.Arrangement
10- import androidx.compose.foundation.layout.Column
11- import androidx.compose.foundation.layout.fillMaxWidth
12- import androidx.compose.foundation.layout.padding
139import androidx.compose.runtime.getValue
14- import androidx.compose.runtime.mutableStateOf
15- import androidx.compose.runtime.setValue
16- import androidx.compose.ui.Modifier
10+ import androidx.compose.runtime.livedata.observeAsState
11+ import androidx.compose.ui.platform.ComposeView
1712import androidx.compose.ui.platform.ViewCompositionStrategy
18- import androidx.compose.ui.res.dimensionResource
19- import androidx.compose.ui.res.stringResource
13+ import androidx.fragment.app.Fragment
14+ import androidx.fragment.app.viewModels
2015import com.google.android.material.dialog.MaterialAlertDialogBuilder
21- import com.jakewharton.rxbinding3.view.clicks
22- import com.spotify.mobius.functions.Consumer
23- import io.reactivex.Observable
24- import io.reactivex.rxkotlin.cast
25- import io.reactivex.subjects.PublishSubject
26- import io.reactivex.subjects.Subject
2716import kotlinx.parcelize.Parcelize
2817import org.simple.clinic.R
29- import org.simple.clinic.ReportAnalyticsEvents
3018import org.simple.clinic.appconfig.Country
31- import org.simple.clinic.common.ui.theme.SimpleTheme
32- import org.simple.clinic.databinding.ScreenNewMedicalHistoryBinding
3319import org.simple.clinic.di.injector
34- import org.simple.clinic.feature.Feature
3520import org.simple.clinic.feature.Features
36- import org.simple.clinic.medicalhistory.Answer
37- import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithDiabetes
38- import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.DiagnosedWithHypertension
39- import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnDiabetesTreatment
40- import org.simple.clinic.medicalhistory.MedicalHistoryQuestion.IsOnHypertensionTreatment
41- import org.simple.clinic.medicalhistory.OngoingMedicalHistoryEntry
4221import org.simple.clinic.medicalhistory.SelectDiagnosisErrorDialog
4322import org.simple.clinic.medicalhistory.SelectOngoingDiabetesTreatmentErrorDialog
4423import org.simple.clinic.medicalhistory.SelectOngoingHypertensionTreatmentErrorDialog
45- import org.simple.clinic.medicalhistory.ui.HistoryContainer
46- import org.simple.clinic.medicalhistory.ui.MedicalHistoryDiagnosisWithTreatment
47- import org.simple.clinic.medicalhistory.ui.TobaccoQuestion
24+ import org.simple.clinic.medicalhistory.ui.NewMedicalHistoryUi
25+ import org.simple.clinic.mobius.DisposableViewEffect
26+ import org.simple.clinic.navigation.v2.HandlesBack
4827import org.simple.clinic.navigation.v2.Router
4928import org.simple.clinic.navigation.v2.ScreenKey
50- import org.simple.clinic.navigation.v2.fragments.BaseScreen
5129import org.simple.clinic.summary.OpenIntention
5230import org.simple.clinic.summary.PatientSummaryScreenKey
5331import org.simple.clinic.util.UtcClock
54- import org.simple.clinic.util.applyInsetsBottomPadding
55- import org.simple.clinic.util.applyStatusBarPadding
56- import org.simple.clinic.widgets.ProgressMaterialButton.ButtonState.Enabled
57- import org.simple.clinic.widgets.ProgressMaterialButton.ButtonState.InProgress
32+ import org.simple.clinic.util.unsafeLazy
5833import java.time.Instant
5934import java.util.UUID
6035import javax.inject.Inject
6136
62- class NewMedicalHistoryScreen : BaseScreen <
63- NewMedicalHistoryScreen .Key ,
64- ScreenNewMedicalHistoryBinding ,
65- NewMedicalHistoryModel ,
66- NewMedicalHistoryEvent ,
67- NewMedicalHistoryEffect ,
68- NewMedicalHistoryViewEffect > (), NewMedicalHistoryUi , NewMedicalHistoryUiActions {
37+ class NewMedicalHistoryScreen : Fragment (), NewMedicalHistoryUiActions, HandlesBack {
6938
7039 @Inject
7140 lateinit var router: Router
@@ -85,210 +54,52 @@ class NewMedicalHistoryScreen : BaseScreen<
8554 @Inject
8655 lateinit var features: Features
8756
88- private val appbar
89- get() = binding.appbar
90-
91- private val toolbar
92- get() = binding.toolbar
93-
94- private val nextButtonFrame
95- get() = binding.nextButtonFrame
96-
97- private val nextButton
98- get() = binding.nextButton
99-
100- private var showSmokerQuestion by mutableStateOf(false )
101- private var showSmokelessTobaccoQuestion by mutableStateOf(false )
102- private var showDiabetesQuestion by mutableStateOf(false )
103- private var showHypertensionTreatmentQuestion by mutableStateOf(false )
104- private var showDiabetesTreatmentQuestion by mutableStateOf(false )
105- private var showDiabetesDiagnosis by mutableStateOf(false )
106- private var ongoingMedicalHistoryEntry by mutableStateOf<OngoingMedicalHistoryEntry ?>(null )
107-
108- private val composeView
109- get() = binding.composeView
57+ @Inject
58+ lateinit var newMedicalHistoryEffectHandler: NewMedicalHistoryEffectHandler .Factory
11059
111- private val hotEvents : Subject < NewMedicalHistoryEvent > = PublishSubject .create()
60+ private val viewEffectHandler by unsafeLazy { NewMedicalHistoryViewEffectHandler ( this ) }
11261
113- override fun defaultModel () = NewMedicalHistoryModel .default(
114- country = country,
115- showIsSmokingQuestion = features.isEnabled(Feature .NonLabBasedStatinNudge ) ||
116- features.isEnabled(Feature .LabBasedStatinNudge ),
117- showSmokelessTobaccoQuestion = country.isoCountryCode != Country .ETHIOPIA
62+ private val viewModel by viewModels<NewMedicalHistoryViewModel >(
63+ factoryProducer = {
64+ NewMedicalHistoryViewModel .factory(
65+ country = country,
66+ features = features,
67+ effectHandlerFactory = effectHandlerFactory)
68+ }
11869 )
11970
120- override fun bindView (
121- layoutInflater : LayoutInflater ,
122- container : ViewGroup ?
123- ) = ScreenNewMedicalHistoryBinding .inflate(layoutInflater, container, false )
124-
125- override fun createUpdate () = NewMedicalHistoryUpdate ()
126-
127- override fun events () = Observable
128- .merge(
129- hotEvents,
130- saveClicks()
131- )
132- .compose(ReportAnalyticsEvents ())
133- .cast<NewMedicalHistoryEvent >()
134-
135- override fun createEffectHandler (
136- viewEffectsConsumer : Consumer <NewMedicalHistoryViewEffect >
137- ) = effectHandlerFactory
138- .create(
139- viewEffectsConsumer = viewEffectsConsumer
140- )
141- .build()
142-
143- override fun createInit () = NewMedicalHistoryInit ()
144-
145- override fun uiRenderer () = NewMedicalHistoryUiRenderer (this )
146-
147- override fun viewEffectHandler () = NewMedicalHistoryViewEffectHandler (this )
148-
14971 override fun onAttach (context : Context ) {
15072 super .onAttach(context)
15173 context.injector<Injector >().inject(this )
15274 }
15375
154- override fun onViewCreated (view : View , savedInstanceState : Bundle ? ) {
155- super .onViewCreated(view, savedInstanceState)
156- appbar.applyStatusBarPadding()
157- nextButtonFrame.applyInsetsBottomPadding()
158- toolbar.setNavigationOnClickListener {
159- router.pop()
160- }
76+ override fun onCreateView (inflater : LayoutInflater , container : ViewGroup ? , savedInstanceState : Bundle ? ): View ? {
77+ return ComposeView (requireContext()).apply {
78+ setViewCompositionStrategy(ViewCompositionStrategy .DisposeOnViewTreeLifecycleDestroyed )
16179
162- composeView.apply {
163- setViewCompositionStrategy(
164- ViewCompositionStrategy .DisposeOnViewTreeLifecycleDestroyed
165- )
16680 setContent {
167- SimpleTheme {
168- Column (
169- modifier = Modifier
170- .fillMaxWidth()
171- .padding(dimensionResource(R .dimen.spacing_8)),
172- verticalArrangement = Arrangement .spacedBy(dimensionResource(R .dimen.spacing_8))
173- ) {
174- MedicalHistoryDiagnosisWithTreatment (
175- diagnosisLabel = stringResource(R .string.medicalhistory_diagnosis_hypertension_required),
176- diagnosisQuestion = DiagnosedWithHypertension ,
177- diagnosisAnswer = ongoingMedicalHistoryEntry?.diagnosedWithHypertension,
178- treatmentQuestion = IsOnHypertensionTreatment (country.isoCountryCode),
179- treatmentAnswer = ongoingMedicalHistoryEntry?.isOnHypertensionTreatment,
180- showTreatmentQuestion = showHypertensionTreatmentQuestion
181- ) { question, answer ->
182- hotEvents.onNext(NewMedicalHistoryAnswerToggled (question, answer))
183- }
184- if (showDiabetesDiagnosis) {
185- MedicalHistoryDiagnosisWithTreatment (
186- diagnosisLabel = stringResource(R .string.medicalhistory_diagnosis_diabetes_required),
187- diagnosisQuestion = DiagnosedWithDiabetes ,
188- diagnosisAnswer = ongoingMedicalHistoryEntry?.hasDiabetes,
189- treatmentQuestion = IsOnDiabetesTreatment ,
190- treatmentAnswer = ongoingMedicalHistoryEntry?.isOnDiabetesTreatment,
191- showTreatmentQuestion = showDiabetesTreatmentQuestion
192- ) { question, answer ->
193- hotEvents.onNext(NewMedicalHistoryAnswerToggled (question, answer))
194- }
195- }
196- HistoryContainer (
197- heartAttackAnswer = ongoingMedicalHistoryEntry?.hasHadHeartAttack,
198- strokeAnswer = ongoingMedicalHistoryEntry?.hasHadStroke,
199- kidneyAnswer = ongoingMedicalHistoryEntry?.hasHadKidneyDisease,
200- diabetesAnswer = ongoingMedicalHistoryEntry?.hasDiabetes,
201- showDiabetesQuestion = showDiabetesQuestion,
202- ) { question, answer ->
203- hotEvents.onNext(NewMedicalHistoryAnswerToggled (question, answer))
204- }
205- if (showSmokerQuestion) {
206- TobaccoQuestion (
207- isSmokingAnswer = ongoingMedicalHistoryEntry?.isSmoking,
208- isUsingSmokelessTobaccoAnswer = ongoingMedicalHistoryEntry?.isUsingSmokelessTobacco,
209- showSmokelessTobaccoQuestion = showSmokelessTobaccoQuestion,
210- ) { question, answer ->
211- hotEvents.onNext(NewMedicalHistoryAnswerToggled (question, answer))
81+ viewModel.viewEffects.DisposableViewEffect (viewEffectHandler::handle)
82+
83+ val model by viewModel.models.observeAsState()
84+ model?.let {
85+ NewMedicalHistoryUi (
86+ model = it,
87+ navigationIconClick = { onBackPressed() },
88+ onNextClick = {
89+ viewModel.dispatch(SaveMedicalHistoryClicked ())
21290 }
213- }
91+ ) { question, answer ->
92+ viewModel.dispatch(NewMedicalHistoryAnswerToggled (question, answer))
21493 }
21594 }
21695 }
21796 }
21897 }
21998
220- private fun saveClicks () = nextButton
221- .clicks()
222- .map { SaveMedicalHistoryClicked () }
223-
22499 override fun openPatientSummaryScreen (patientUuid : UUID ) {
225100 router.push(PatientSummaryScreenKey (patientUuid, OpenIntention .ViewNewPatient , Instant .now(utcClock)))
226101 }
227102
228- override fun setPatientName (patientName : String ) {
229- toolbar.title = patientName
230- }
231-
232- override fun populateOngoingMedicalHistoryEntry (ongoingMedicalHistoryEntry : OngoingMedicalHistoryEntry ) {
233- this .ongoingMedicalHistoryEntry = ongoingMedicalHistoryEntry
234- }
235-
236- override fun showDiabetesDiagnosisView () {
237- showDiabetesDiagnosis = true
238- }
239-
240- override fun hideDiabetesDiagnosisView () {
241- showDiabetesDiagnosis = false
242- }
243-
244- override fun hideDiabetesHistorySection () {
245- showDiabetesQuestion = false
246- }
247-
248- override fun showDiabetesHistorySection () {
249- showDiabetesQuestion = true
250- }
251-
252- override fun showNextButtonProgress () {
253- nextButton.setButtonState(InProgress )
254- }
255-
256- override fun hideNextButtonProgress () {
257- nextButton.setButtonState(Enabled )
258- }
259-
260- override fun showHypertensionTreatmentQuestion (answer : Answer ) {
261- showHypertensionTreatmentQuestion = true
262- }
263-
264- override fun hideHypertensionTreatmentQuestion () {
265- showHypertensionTreatmentQuestion = false
266- }
267-
268- override fun showDiabetesTreatmentQuestion (answer : Answer ) {
269- showDiabetesTreatmentQuestion = true
270- }
271-
272- override fun hideDiabetesTreatmentQuestion () {
273- showDiabetesTreatmentQuestion = false
274- }
275-
276- override fun showCurrentSmokerQuestion () {
277- showSmokerQuestion = true
278- }
279-
280- override fun hideCurrentSmokerQuestion () {
281- showSmokerQuestion = false
282- }
283-
284- override fun showSmokelessTobaccoQuestion () {
285- showSmokelessTobaccoQuestion = true
286- }
287-
288- override fun hideSmokelessTobaccoQuestion () {
289- showSmokelessTobaccoQuestion = false
290- }
291-
292103 override fun showOngoingHypertensionTreatmentErrorDialog () {
293104 SelectOngoingHypertensionTreatmentErrorDialog .show(fragmentManager = activity.supportFragmentManager)
294105 }
@@ -297,6 +108,10 @@ class NewMedicalHistoryScreen : BaseScreen<
297108 SelectOngoingDiabetesTreatmentErrorDialog .show(fragmentManager = activity.supportFragmentManager)
298109 }
299110
111+ override fun goBack () {
112+ router.pop()
113+ }
114+
300115 override fun showDiagnosisRequiredErrorDialog () {
301116 SelectDiagnosisErrorDialog .show(activity.supportFragmentManager)
302117 }
@@ -315,11 +130,16 @@ class NewMedicalHistoryScreen : BaseScreen<
315130 .setMessage(getString(R .string.change_diagnosis_message))
316131 .setPositiveButton(getString(R .string.change_diagnosis_positive), null )
317132 .setNegativeButton(getString(R .string.change_diagnosis_negative)) { _, _ ->
318- hotEvents.onNext (ChangeDiagnosisNotNowClicked )
133+ viewModel.dispatch (ChangeDiagnosisNotNowClicked )
319134 }
320135 .show()
321136 }
322137
138+ override fun onBackPressed (): Boolean {
139+ viewModel.dispatch(BackClicked )
140+ return true
141+ }
142+
323143 interface Injector {
324144 fun inject (target : NewMedicalHistoryScreen )
325145 }
0 commit comments