diff --git a/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingFragment.kt b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingFragment.kt index c7d4247d..4d451582 100644 --- a/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingFragment.kt +++ b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingFragment.kt @@ -4,15 +4,40 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController +import net.pengcook.android.data.datasource.making.FakeRecipeStepMakingDatasource +import net.pengcook.android.data.repository.making.step.FakeRecipeStepMakingRepository import net.pengcook.android.databinding.FragmentMakingStepBinding class StepMakingFragment : Fragment() { private var _binding: FragmentMakingStepBinding? = null private val binding: FragmentMakingStepBinding get() = _binding!! - private val viewModel: StepMakingViewModel by viewModels() + private val viewModel: StepMakingViewModel by viewModels { + /*StepMakingViewModelFactory( + recipeId = 1, + maximumStep = 15, + recipeStepMakingRepository = + DefaultRecipeStepMakingRepository( + recipeStepMakingDataSource = + DefaultRecipeStepMakingDataSource( + stepMakingService = RetrofitClient.service(StepMakingService::class.java), + ), + ), + )*/ + StepMakingViewModelFactory( + recipeId = 1, + maximumStep = 15, + recipeStepMakingRepository = + FakeRecipeStepMakingRepository( + recipeStepMakingDataSource = + FakeRecipeStepMakingDatasource(), + ), + ) + } override fun onCreateView( inflater: LayoutInflater, @@ -29,6 +54,7 @@ class StepMakingFragment : Fragment() { ) { super.onViewCreated(view, savedInstanceState) initBinding() + observeViewModel() } override fun onDestroyView() { @@ -39,5 +65,45 @@ class StepMakingFragment : Fragment() { private fun initBinding() { binding.lifecycleOwner = this binding.vm = viewModel + binding.eventHandler = viewModel + binding.appbarEventListener = viewModel + } + + private fun observeViewModel() { + viewModel.emptyIntroductionState.observe(viewLifecycleOwner) { event -> + event.getContentIfNotHandled()?.let { + Toast + .makeText( + requireContext(), + "Introduction Should be filled", + Toast.LENGTH_SHORT, + ).show() + } + } + + viewModel.uploadingImageState.observe(viewLifecycleOwner) { event -> + event.getContentIfNotHandled()?.let { + Toast + .makeText( + requireContext(), + "Cannot move to next step while uploading image", + Toast.LENGTH_SHORT, + ).show() + } + } + + viewModel.quitStepMakingState.observe(viewLifecycleOwner) { event -> + event.getContentIfNotHandled()?.let { + findNavController().popBackStack() + } + } + + viewModel.completeStepMakingState.observe(viewLifecycleOwner) { event -> + event.getContentIfNotHandled()?.let { + // Seems like legacy code + findNavController().popBackStack() + findNavController().popBackStack() + } + } } } diff --git a/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModel.kt b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModel.kt index 99c27298..32cce18e 100644 --- a/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModel.kt +++ b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModel.kt @@ -3,15 +3,136 @@ package net.pengcook.android.presentation.making.step import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import net.pengcook.android.presentation.making.step.listener.StepEventListener +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +import net.pengcook.android.data.repository.making.step.RecipeStepMakingRepository +import net.pengcook.android.presentation.core.listener.AppbarDoubleActionEventListener +import net.pengcook.android.presentation.core.model.RecipeStep +import net.pengcook.android.presentation.core.util.Event +import net.pengcook.android.presentation.making.step.listener.StepMakingEventHandler -class StepMakingViewModel : ViewModel(), StepEventListener { - private val _stepNumber = MutableLiveData() - val stepNumber: LiveData get() = _stepNumber +class StepMakingViewModel( + private val recipeId: Long, + private val maximumStep: Int = 15, + private val recipeStepMakingRepository: RecipeStepMakingRepository, +) : ViewModel(), + StepMakingEventHandler, + AppbarDoubleActionEventListener { + private val _maxStepPage = MutableLiveData(maximumStep) + val maxStepPage: LiveData + get() = _maxStepPage + + private val _stepNumber = MutableLiveData(1) + val stepNumber: LiveData get() = _stepNumber val introductionContent = MutableLiveData() - override fun onNavigateToNextStep() { - TODO("Not yet implemented") + private val _imageUrl = MutableLiveData() + val imageUrl: LiveData + get() = _imageUrl + + private val isIntroductionContentEmpty = MutableLiveData(true) + + private var _emptyIntroductionState = MutableLiveData>() + val emptyIntroductionState: LiveData> + get() = _emptyIntroductionState + + private var _isUploadingImage = MutableLiveData(false) + val isUploadingImage: LiveData + get() = _isUploadingImage + + private var _uploadingImageState = MutableLiveData>() + val uploadingImageState: LiveData> + get() = _uploadingImageState + + private var _completeStepMakingState = MutableLiveData>() + val completeStepMakingState: LiveData> + get() = _completeStepMakingState + + private var _quitStepMakingState = MutableLiveData>() + val quitStepMakingState: LiveData> + get() = _quitStepMakingState + + init { + initStepData(stepNumber.value!!) + } + + override fun validateNextPageableCondition() { + // Check if the introduction content is empty or Uploading image + isIntroductionContentEmpty.value = introductionContent.value.isNullOrBlank() + + if (isIntroductionContentEmpty.value == true) { + _emptyIntroductionState.value = Event(true) + } else if (isUploadingImage.value == true) { + _uploadingImageState.value = Event(true) + } else { + _stepNumber.value = _stepNumber.value?.plus(1) + initStepData(stepNumber.value!!) + isIntroductionContentEmpty.value = false + } + } + + override fun validatePreviousPageableCondition() { + _stepNumber.value = _stepNumber.value?.minus(1) + initStepData(stepNumber.value!!) + } + + override fun navigationAction() { + _quitStepMakingState.value = Event(true) + } + + override fun customAction() { + if (isIntroductionContentEmpty.value == true) { + _emptyIntroductionState.value = Event(true) + return + } + viewModelScope.launch { + uploadStepData(stepNumber.value!!) + } + _completeStepMakingState.value = Event(true) + } + + private fun initStepData(stepNumber: Int) { + viewModelScope.launch { + val data = fetchStepData(stepNumber) + + if (data == null) { + introductionContent.value = "" + _imageUrl.value = "" + } else { + introductionContent.value = data.description + _imageUrl.value = data.image + } + } + } + + private suspend fun fetchStepData(stepNumber: Int): RecipeStep? { + // Fetch step data from repository + val result = + recipeStepMakingRepository.fetchRecipeStep( + recipeId = recipeId, + sequence = stepNumber, + ) + + return result.getOrNull() + } + + private suspend fun uploadStepData(stepNumber: Int) { + // Upload step data to repository + recipeStepMakingRepository.uploadRecipeStep( + RecipeStep( + recipeId = recipeId, + sequence = stepNumber, + description = introductionContent.value ?: "", + image = imageUrl.value ?: "", + stepId = 1L, + ), + ) } } + +sealed interface StepMakingUiEvent { + data object EmptyIntroductionState : StepMakingUiEvent + + data object UploadIngImageState : StepMakingUiEvent +} diff --git a/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModelFactory.kt b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModelFactory.kt new file mode 100644 index 00000000..7869cda6 --- /dev/null +++ b/android/app/src/main/java/net/pengcook/android/presentation/making/step/StepMakingViewModelFactory.kt @@ -0,0 +1,22 @@ +package net.pengcook.android.presentation.making.step + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import net.pengcook.android.data.repository.making.step.RecipeStepMakingRepository + +class StepMakingViewModelFactory( + private val recipeId: Long, + private val maximumStep: Int = 15, + private val recipeStepMakingRepository: RecipeStepMakingRepository, +) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(StepMakingViewModel::class.java)) { + return StepMakingViewModel( + recipeId = recipeId, + maximumStep = maximumStep, + recipeStepMakingRepository = recipeStepMakingRepository, + ) as T + } + throw IllegalArgumentException() + } +} diff --git a/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepEventListener.kt b/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepEventListener.kt deleted file mode 100644 index cd2c89f0..00000000 --- a/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepEventListener.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.pengcook.android.presentation.making.step.listener - -interface StepEventListener { - fun onNavigateToNextStep() -} diff --git a/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepMakingEventHandler.kt b/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepMakingEventHandler.kt new file mode 100644 index 00000000..10f22f96 --- /dev/null +++ b/android/app/src/main/java/net/pengcook/android/presentation/making/step/listener/StepMakingEventHandler.kt @@ -0,0 +1,7 @@ +package net.pengcook.android.presentation.making.step.listener + +interface StepMakingEventHandler { + fun validateNextPageableCondition() + + fun validatePreviousPageableCondition() +}