Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ add taking time form for step making #358

Merged
merged 6 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -55,7 +55,7 @@ class DefaultRecipeStepMakingRepository
private fun RecipeStepMaking.toRecipeStepEntity(): RecipeStepEntity =
RecipeStepEntity(
recipeDescriptionId = recipeId,
cookingTime = "00:00:00",
cookingTime = cookingTime,
stepNumber = sequence,
description = description.ifEmpty { null },
imageUri = imageUri.ifEmpty { null },
Expand All @@ -70,5 +70,6 @@ class DefaultRecipeStepMakingRepository
description = description ?: "",
imageUri = imageUri ?: "",
image = imageTitle ?: "",
cookingTime = cookingTime ?: "00:00:00",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null 처리 굿입니다!

)
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fun RecipeStepEntity.toRecipeStepMaking(): RecipeStepMaking =
image = imageTitle ?: "",
imageUri = imageUri ?: "",
stepId = id,
cookingTime = cookingTime ?: "::",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null 이면 "::"이렇게 표시하는게 의도된거죠..? 00:00:00 이런 방식이 아닌거죠..?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null일 경우는 사실상 이뤄질 일이 없긴 한데, 없으면 그냥 빈 값으로 edittext에 들어가도록 하려고 했습니다.
근데 일단 뷰모델에서도 시간이 비어있으면 00:00:00으로 처리하는 만큼 통일성이 있으면 좋기야 할 것 같습니다.

)

fun IngredientEntity.toIngredient(): Ingredient =
Expand All @@ -90,7 +91,7 @@ fun Ingredient.toIngredientRequest(): IngredientRequest =

fun RecipeStepMaking.toRecipeStepRequest(): RecipeStepRequest =
RecipeStepRequest(
cookingTime = "00:00:00",
cookingTime = cookingTime,
description = description,
image = image,
sequence = sequence,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ data class RecipeStepMaking(
val image: String,
val sequence: Int,
val imageUri: String,
)
val cookingTime: String,
) {
init {
require(cookingTime.matches(Regex("\\d{2}:\\d{2}:\\d{2}"))) {
"cookingTime must be in the format of HH:MM:SS"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ class RecipeMakingFragment : Fragment() {
val etHour = binding.itemTimeRequired.etTimeAmountPicker.etHour
val etMinute = binding.itemTimeRequired.etTimeAmountPicker.etMinute
val etSecond = binding.itemTimeRequired.etTimeAmountPicker.etSecond
etHour.filters = arrayOf(MinMaxInputFilter(0, 23))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

시간에 맞는 필터사용 굿 👍

arrayOf(MinMaxInputFilter(0, 59)).also { filters ->
etHour.filters = filters
etMinute.filters = filters
etSecond.filters = filters
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ class RecipeMakingViewModel
val ingredients = ingredientContent.value?.trim()
val title = titleContent.value?.trim()
val hour = hourContent.value
val minute = minuteContent.value
val second = secondContent.value
val minute = minuteContent.value
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minute이 second 아래로 옮겨진거 같은데, 이유가 있을까요?
직관적으로 생각하면 hour-min-sec 순서로 놔두는게 좋을것 같아요!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵넵 좋습니다!


if (category.isNullOrEmpty() ||
introduction.isNullOrEmpty() ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import net.pengcook.android.databinding.FragmentMakingStepBinding
import net.pengcook.android.presentation.core.util.AnalyticsLogging
import net.pengcook.android.presentation.core.util.FileUtils
import net.pengcook.android.presentation.core.util.ImageUtils
import net.pengcook.android.presentation.core.util.MinMaxInputFilter
import java.io.File
import javax.inject.Inject

Expand Down Expand Up @@ -111,6 +112,7 @@ class StepMakingFragment : Fragment() {
) {
super.onViewCreated(view, savedInstanceState)
initBinding()
initTimeFormatInput()
AnalyticsLogging.viewLogEvent("RecipeMaking")
observeViewModel()
}
Expand All @@ -127,6 +129,15 @@ class StepMakingFragment : Fragment() {
binding.appbarEventListener = viewModel
}

private fun initTimeFormatInput() {
val etMinute = binding.etTimeAmount.etTimeAmountPicker.etMinute
val etSecond = binding.etTimeAmount.etTimeAmountPicker.etSecond
arrayOf(MinMaxInputFilter(0, 59)).also { filters ->
etMinute.filters = filters
etSecond.filters = filters
}
}

private fun observeViewModel() {
viewModel.uiEvent.observe(viewLifecycleOwner) { event ->
val newEvent = event.getContentIfNotHandled() ?: return@observe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class StepMakingViewModel
) : ViewModel(),
StepMakingEventHandler,
AppbarDoubleActionEventListener {
private val stepTraversalStatus = MutableList(maximumStep) { false }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 내용은 정확히 로직이 이해가 되지 않네요... 오프라인으로 설명 한번 들으러 가겠습니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설명 잘 들었습니다! approve 하겠습니다!


private val _stepNumber = MutableLiveData<Int>(1)
val stepNumber: LiveData<Int> get() = _stepNumber

Expand Down Expand Up @@ -56,8 +58,17 @@ class StepMakingViewModel
val uiEvent: LiveData<Event<RecipeStepMakingEvent>>
get() = _uiEvent

private var completionPressed = false

private val _errorVisibility: MutableLiveData<Boolean> = MutableLiveData(false)
val errorVisibility: LiveData<Boolean>
get() = _errorVisibility

private val stepCompletion: MutableMap<Int, Boolean> = mutableMapOf(1 to false)

val minuteContent = MutableLiveData<String>()
val secondContent = MutableLiveData<String>()

init {
val stepNumber = stepNumber.value
if (stepNumber != null) {
Expand All @@ -72,6 +83,7 @@ class StepMakingViewModel
override fun moveToNextPage() {
val imageUploaded = imageUploaded.value
val introduction = introductionContent.value

if (imageUploaded != true) {
_uiEvent.value = Event(RecipeStepMakingEvent.ImageNotUploaded)
return
Expand Down Expand Up @@ -115,6 +127,9 @@ class StepMakingViewModel

override fun customAction() {
viewModelScope.launch {
completionPressed = true
_errorVisibility.value = true

if (imageSelected.value != true) {
_uiEvent.value = Event(RecipeStepMakingEvent.FormNotCompleted)
return@launch
Expand Down Expand Up @@ -184,6 +199,8 @@ class StepMakingViewModel
private fun initStepData(stepNumber: Int) {
viewModelScope.launch {
_isLoading.value = true
_errorVisibility.value = completionPressed && stepTraversalStatus[stepNumber - 1]
stepTraversalStatus[stepNumber - 1] = true
_imageUri.value = null
fetchRecipeStep(stepNumber)
_isLoading.value = false
Expand Down Expand Up @@ -214,6 +231,8 @@ class StepMakingViewModel
_imageUploaded.value = false
introductionContent.value = ""
thumbnailTitle = null
minuteContent.value = ""
secondContent.value = ""
}

private suspend fun postRecipe(recipeCreation: RecipeCreation) {
Expand Down Expand Up @@ -249,7 +268,11 @@ class StepMakingViewModel
sequence = stepNumber,
).onSuccess { recipeStep ->
if (recipeStep == null) return@onSuccess
val minute = recipeStep.cookingTime.split(SEPARATOR_TIME).getOrNull(1) ?: ""
val second = recipeStep.cookingTime.split(SEPARATOR_TIME).getOrNull(2) ?: ""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하디의 코드였다면, 어김없이 매직넘버로 슬라이딩 태클 걸었을지도...?ㅋㅋㅋ

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

introductionContent.value = recipeStep.description
minuteContent.value = if (minute.toIntOrNull() == 0) "" else minute
secondContent.value = if (second.toIntOrNull() == 0) "" else second
if (recipeStep.imageUri.isNotEmpty()) {
_imageUri.value = Uri.parse(recipeStep.imageUri)
}
Expand All @@ -269,6 +292,11 @@ class StepMakingViewModel
stepNumber: Int,
stepAction: StepAction,
) {
val minute = minuteContent.value
val second = secondContent.value
println("minute : $minute")
println("second : $second")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요거 지워주시면 감사하겠습니다!


val recipeStep =
RecipeStepMaking(
recipeId = recipeId,
Expand All @@ -277,6 +305,12 @@ class StepMakingViewModel
image = thumbnailTitle ?: "",
stepId = 1L,
imageUri = imageUri.value?.toString() ?: "",
cookingTime =
FORMAT_TIME_REQUIRED.format(
0,
minute?.toIntOrNull() ?: 0,
second?.toIntOrNull() ?: 0,
),
)

recipeStepMakingRepository.saveRecipeStep(recipeId = recipeId, recipeStep = recipeStep)
Expand All @@ -290,6 +324,9 @@ class StepMakingViewModel
}

companion object {
private const val FORMAT_TIME_REQUIRED = "%02d:%02d:%02d"
private const val SEPARATOR_TIME = ":"

fun provideFactory(
assistedFactory: StepMakingViewModelFactory,
recipeId: Long,
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/res/layout/fragment_detail_recipe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
android:id="@+id/iv_thumbnail_recipe"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
android:scaleType="centerCrop"
app:imageUrl="@{recipe.thumbnail}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
Expand Down
20 changes: 17 additions & 3 deletions android/app/src/main/res/layout/fragment_making_step.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,22 @@

</androidx.constraintlayout.widget.ConstraintLayout>

<include
android:id="@+id/et_time_amount"
layout="@layout/item_minute_second_picker_with_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/cl_btn_add_image"
app:title="@{@string/making_form_time_required}"
app:minute="@={vm.minuteContent}"
app:second="@={vm.secondContent}"
app:visibleCondition="@{vm.errorVisibility}"/>

<include
android:id="@+id/et_guide_step_recipe"
layout="@layout/item_form_multi_text"
layout="@layout/item_form_multi_text_with_warning"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
Expand All @@ -95,8 +108,9 @@
app:hintContent="@{@string/step_making_hint}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_btn_add_image"
app:title="@{String.valueOf(vm.stepNumber)}" />
app:layout_constraintTop_toBottomOf="@id/et_time_amount"
app:title="@{String.valueOf(vm.stepNumber)}"
app:errorVisibility="@{vm.errorVisibility}"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/res/layout/fragment_sign_up.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="12dp"
app:buttonClickListener="@{viewModel}"
app:buttonText="@{(viewModel.imageUploaded == false &amp;&amp; viewModel.imageSelected == true) ? @string/making_uploading_image : @string/making_step}"
app:buttonText="@{(viewModel.imageUploaded == false &amp;&amp; viewModel.imageSelected == true) ? @string/making_uploading_image : @string/signup_button_next}"
app:enabled="@{true}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/sv_sign_up" />
Expand Down
1 change: 0 additions & 1 deletion android/app/src/main/res/layout/item_form_multi_text.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="title"
type="String" />

<variable
name="hintContent"
type="String" />

<variable
name="content"
type="String" />

<variable
name="errorVisibility"
type="Boolean" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<include
android:id="@+id/et_content"
layout="@layout/item_form_multi_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:content="@={content}"
app:hintContent="@{hintContent}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:title="@{title}" />

<TextView
android:id="@+id/tv_alert_message"
style="@style/WarningMessageUnfilledForm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_content"
bind:visibility="@{errorVisibility &amp;&amp; (content == null || content.isEmpty())}" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
78 changes: 78 additions & 0 deletions android/app/src/main/res/layout/item_minute_second_picker.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="title"
type="String" />

<variable
name="minute"
type="String" />

<variable
name="second"
type="String" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/tv_form_hour_title"
style="@style/Body.Regular.B2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{title}"
app:layout_constraintTop_toTopOf="parent"
tools:text="Title" />

<EditText
android:id="@+id/et_minute"
style="@style/Body.Regular.B2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:background="@drawable/bg_radius_outlined"
android:gravity="center"
android:hint="Minute"
android:importantForAutofill="no"
android:inputType="numberDecimal"
android:maxLength="2"
android:maxLines="1"
android:padding="16dp"
android:text="@={minute}"
app:layout_constraintEnd_toStartOf="@id/et_second"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_form_hour_title"
tools:hint="Minute" />

<EditText
android:id="@+id/et_second"
style="@style/Body.Regular.B2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:background="@drawable/bg_radius_outlined"
android:gravity="center"
android:hint="Second"
android:importantForAutofill="no"
android:inputType="numberDecimal"
android:maxLength="2"
android:maxLines="1"
android:padding="16dp"
android:text="@={second}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/et_minute"
app:layout_constraintTop_toTopOf="@id/et_minute"
tools:hint="Second" />


</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Loading
Loading