Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.groundplatform.android.ui.common.BackPressListener
import org.groundplatform.android.ui.components.ConfirmationDialog
import org.groundplatform.android.ui.home.HomeScreenFragmentDirections
import org.groundplatform.android.util.renderComposableDialog
import org.groundplatform.domain.model.locationofinterest.LoiReport
import org.groundplatform.domain.model.task.Task

/** Fragment allowing the user to collect data to complete a task. */
Expand Down Expand Up @@ -68,14 +69,19 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
guideline = binding.progressBarGuideline
getAbstractActivity().setSupportActionBar(binding.dataCollectionToolbar)

binding.dataCollectionToolbar.setNavigationOnClickListener { showExitWarningDialog() }
binding.dataCollectionToolbar.setNavigationOnClickListener {
if (viewModel.uiState.value is DataCollectionUiState.TaskSubmitted) {
navigateBack()
} else {
showExitWarningDialog()
}
}

return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.lifecycleOwner = viewLifecycleOwner

viewPager.isUserInputEnabled = false
viewPager.offscreenPageLimit = 1
Expand Down Expand Up @@ -110,8 +116,8 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
when (uiState) {
// Ensure adapter has the task list; then jump to the current position.
is DataCollectionUiState.Ready -> {
binding.jobName = uiState.job.name
binding.loiName = uiState.loiName
binding.dataCollectionToolbar.title = uiState.job.name
binding.dataCollectionToolbar.subtitle = uiState.loiName
loadTasks(uiState.tasks, uiState.position)
}

Expand All @@ -120,7 +126,9 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
}

is DataCollectionUiState.TaskSubmitted -> {
onTaskSubmitted()
binding.dataCollectionToolbar.title = getString(R.string.data_collection_complete)
binding.dataCollectionToolbar.subtitle = null
onTaskSubmitted(uiState.loiReport)
}

is DataCollectionUiState.Loading,
Expand Down Expand Up @@ -156,14 +164,12 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
updateProgressBar(taskPosition, true)
}

private fun onTaskSubmitted() {
// Hide close button
binding.dataCollectionToolbar.navigationIcon = null
private fun onTaskSubmitted(loiReport: LoiReport?) {
viewPager.adapter = null

// Display a confirmation dialog and move to home screen after that.
renderComposableDialog {
DataSubmissionConfirmationScreen {
DataSubmissionConfirmationScreen(loiReport) {
findNavController().navigate(HomeScreenFragmentDirections.showHomeScreen())
}
}
Expand All @@ -189,7 +195,7 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
}

override fun onBack(): Boolean {
if (viewModel.uiState.value == DataCollectionUiState.TaskSubmitted) {
if (viewModel.uiState.value is DataCollectionUiState.TaskSubmitted) {
// Pressing back button after submitting task should navigate back to home screen.
navigateBack()
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.groundplatform.android.ui.datacollection

import org.groundplatform.domain.model.job.Job
import org.groundplatform.domain.model.locationofinterest.LoiReport
import org.groundplatform.domain.model.task.Task

/**
Expand Down Expand Up @@ -85,7 +86,7 @@ sealed interface DataCollectionUiState {
* affordance or navigate away (e.g., back to the home screen) and must not attempt to read or
* save further draft data for this session.
*/
data object TaskSubmitted : DataCollectionUiState
data class TaskSubmitted(val loiReport: LoiReport?) : DataCollectionUiState
}

/** Stable, UI-mappable error codes for data collection bootstrapping and flow. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import org.groundplatform.domain.model.submission.TaskData
import org.groundplatform.domain.model.submission.ValueDelta
import org.groundplatform.domain.model.submission.isNotNullOrEmpty
import org.groundplatform.domain.model.task.Task
import org.groundplatform.domain.usecases.GetLoiReportUseCase
import timber.log.Timber

/** View model for the Data Collection fragment. */
Expand All @@ -72,6 +73,7 @@ internal constructor(
private val popups: Provider<EphemeralPopups>,
private val viewModelFactory: ViewModelFactory,
private val dataCollectionInitializer: DataCollectionInitializer,
private val getLoiReportUseCase: GetLoiReportUseCase,
) : AbstractViewModel() {

/** The current vertical position of the task view footer. */
Expand All @@ -86,7 +88,6 @@ internal constructor(

private val jobId: String = requireNotNull(savedStateHandle[TASK_JOB_ID_KEY])
private val loiId: String? = savedStateHandle[TASK_LOI_ID_KEY]
private val loiName: String? = savedStateHandle[TASK_LOI_NAME_KEY]

private val taskDataHandler = TaskDataHandler()
private lateinit var taskSequenceHandler: TaskSequenceHandler
Expand All @@ -99,7 +100,13 @@ internal constructor(

init {
viewModelScope.launch {
val initResult = dataCollectionInitializer.initialize(savedStateHandle, jobId, loiId, loiName)
val initResult =
dataCollectionInitializer.initialize(
savedStateHandle,
jobId,
loiId,
getTypedLoiNameOrEmpty(),
)

if (initResult is DataCollectionUiState.Ready) {
taskSequenceHandler = TaskSequenceHandler(initResult.tasks, taskDataHandler)
Expand Down Expand Up @@ -167,8 +174,16 @@ internal constructor(
moveToNextTask()
} else {
clearDraft()
saveChanges(st, getDeltas())
_uiState.value = DataCollectionUiState.TaskSubmitted
externalScope.launch(ioDispatcher) {
val submittedLoiId = saveChanges(st, getDeltas())
val loiReport =
getLoiReportUseCase.invoke(
loiName = getTypedLoiNameOrEmpty(),
loiId = submittedLoiId,
surveyId = st.surveyId,
)
_uiState.value = DataCollectionUiState.TaskSubmitted(loiReport)
}
}
}
}
Expand Down Expand Up @@ -240,18 +255,19 @@ internal constructor(
moveToTask(withReady { taskSequenceHandler.getNextTask(it.currentTaskId) })
}

private fun saveChanges(state: DataCollectionUiState.Ready, deltas: List<ValueDelta>) {
externalScope.launch(ioDispatcher) {
val collectionId = offlineUuidGenerator.generateUuid()
submitDataUseCase.invoke(
loiId,
state.job,
state.surveyId,
deltas,
savedStateHandle[TASK_LOI_NAME_KEY],
collectionId,
)
}
private suspend fun saveChanges(
state: DataCollectionUiState.Ready,
deltas: List<ValueDelta>,
): String {
val collectionId = offlineUuidGenerator.generateUuid()
return submitDataUseCase.invoke(
selectedLoiId = loiId,
job = state.job,
surveyId = state.surveyId,
deltas = deltas,
loiName = savedStateHandle[TASK_LOI_NAME_KEY],
collectionId = collectionId,
)
}

private fun suppressDrafts() {
Expand Down Expand Up @@ -282,7 +298,7 @@ internal constructor(
val state = uiState.value

if (
state == DataCollectionUiState.TaskSubmitted ||
state is DataCollectionUiState.TaskSubmitted ||
deltas.isEmpty() ||
state !is DataCollectionUiState.Ready
) {
Expand Down
Loading
Loading