From 37f9a1e05d67a7a942017ff8bb4451c6195d9023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=EC=9A=B0?= <85734140+jinuemong@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:20:35 +0900 Subject: [PATCH] =?UTF-8?q?[AN]=20=EB=AA=A8=EC=9E=84=20UI=20=ED=94=BC?= =?UTF-8?q?=EB=93=9C=EB=B0=B1=20=EA=B0=9C=EC=84=A0=20(#634)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bottom/ClubRecruitmentBottomSheet.kt | 2 +- .../ui/club/detail/ClubDetailActionHandler.kt | 2 + .../ui/club/detail/ClubDetailActivity.kt | 12 + .../club/detail/ClubDetailBindingAdapters.kt | 8 + .../ui/club/detail/ClubDetailEvent.kt | 4 + .../ui/club/detail/ClubDetailViewModel.kt | 26 + .../ui/club/list/ClubListBindingAdapters.kt | 6 +- .../ui/club/modify/ClubModifyActivity.kt | 2 +- .../club/modify/ClubModifyBindingAdapters.kt | 9 +- .../main/res/layout/activity_club_detail.xml | 454 ++++++++++-------- .../res/layout/fragment_club_add_filter.xml | 2 +- android/app/src/main/res/layout/item_club.xml | 1 + android/app/src/main/res/values/strings.xml | 12 +- .../ui/club/detail/ClubDetailViewModelTest.kt | 8 + 14 files changed, 334 insertions(+), 214 deletions(-) rename android/app/src/main/java/com/happy/friendogly/presentation/ui/club/{modify => common}/bottom/ClubRecruitmentBottomSheet.kt (95%) diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/bottom/ClubRecruitmentBottomSheet.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/common/bottom/ClubRecruitmentBottomSheet.kt similarity index 95% rename from android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/bottom/ClubRecruitmentBottomSheet.kt rename to android/app/src/main/java/com/happy/friendogly/presentation/ui/club/common/bottom/ClubRecruitmentBottomSheet.kt index 679a17943..a9ab1e815 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/bottom/ClubRecruitmentBottomSheet.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/common/bottom/ClubRecruitmentBottomSheet.kt @@ -1,4 +1,4 @@ -package com.happy.friendogly.presentation.ui.club.modify.bottom +package com.happy.friendogly.presentation.ui.club.common.bottom import android.os.Bundle import android.view.LayoutInflater diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActionHandler.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActionHandler.kt index 5beaeb30c..3da4d6a3d 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActionHandler.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActionHandler.kt @@ -6,4 +6,6 @@ interface ClubDetailActionHandler { fun closeDetail() fun openMenu() + + fun openSelectState() } diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActivity.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActivity.kt index d8189d808..dedae0463 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActivity.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailActivity.kt @@ -15,6 +15,7 @@ import com.happy.friendogly.presentation.dialog.PetAddAlertDialog import com.happy.friendogly.presentation.ui.chatlist.chat.ChatActivity import com.happy.friendogly.presentation.ui.club.common.ClubChangeStateIntent import com.happy.friendogly.presentation.ui.club.common.MessageHandler +import com.happy.friendogly.presentation.ui.club.common.bottom.ClubRecruitmentBottomSheet import com.happy.friendogly.presentation.ui.club.common.handleError import com.happy.friendogly.presentation.ui.club.common.model.clubfilter.ClubFilter import com.happy.friendogly.presentation.ui.club.detail.adapter.DetailProfileAdapter @@ -136,6 +137,9 @@ class ClubDetailActivity : } ClubDetailEvent.Navigation.NavigateToRegisterPet -> openRegisterPetDialog() + + ClubDetailEvent.Navigation.NavigateSelectState -> openSelectState() + ClubDetailEvent.SaveReLoadState -> putLoadState() } } @@ -178,6 +182,14 @@ class ClubDetailActivity : ) } + private fun openSelectState() { + val bottomSheet = + ClubRecruitmentBottomSheet { state -> + viewModel.submitClubStateModify(state) + } + bottomSheet.show(supportFragmentManager, "TAG") + } + private fun openDogSelector(filters: List) { val bottomSheet = PetSelectBottomSheet(filters = filters) { dogs -> diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailBindingAdapters.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailBindingAdapters.kt index cafcb6bf7..737178d4d 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailBindingAdapters.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailBindingAdapters.kt @@ -1,5 +1,6 @@ package com.happy.friendogly.presentation.ui.club.detail +import android.view.View import android.widget.TextView import androidx.core.content.ContextCompat import androidx.databinding.BindingAdapter @@ -47,7 +48,14 @@ fun TextView.bindDetailViewTypeStyle(clubDetailViewType: ClubDetailViewType?) { ClubDetailViewType.RECRUITMENT, ClubDetailViewType.MINE, -> R.style.Theme_AppCompat_TextView_SemiBold_White_Size14 + ClubDetailViewType.END_RECRUITMENT -> R.style.Theme_AppCompat_TextView_SemiBold_Gray07_Size14 } this.setTextAppearance(textStyle) } + +@BindingAdapter("detailViewClubModifyVisible") +fun View.bindDetailViewClubModifyVisible(clubDetailViewType: ClubDetailViewType?) { + clubDetailViewType ?: return + this.visibility = if (clubDetailViewType == ClubDetailViewType.MINE) View.VISIBLE else View.GONE +} diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailEvent.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailEvent.kt index d9d0e6897..4e2755163 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailEvent.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailEvent.kt @@ -8,11 +8,15 @@ sealed interface ClubDetailEvent { data class OpenDetailMenu(val clubDetailViewType: ClubDetailViewType) : ClubDetailEvent + data object SaveReLoadState : ClubDetailEvent + sealed interface Navigation : ClubDetailEvent { data class NavigateToChat(val chatRoomId: Long) : Navigation data object NavigateToHome : Navigation data object NavigateToRegisterPet : Navigation + + data object NavigateSelectState : Navigation } } diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModel.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModel.kt index 0400ccbc7..8ee608550 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModel.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModel.kt @@ -4,7 +4,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.happy.friendogly.domain.fold +import com.happy.friendogly.domain.model.ClubState import com.happy.friendogly.domain.usecase.GetClubUseCase +import com.happy.friendogly.domain.usecase.PatchClubUseCase import com.happy.friendogly.domain.usecase.PostClubMemberUseCase import com.happy.friendogly.firebase.analytics.AnalyticsHelper import com.happy.friendogly.presentation.base.BaseViewModel @@ -26,6 +28,7 @@ class ClubDetailViewModel private val analyticsHelper: AnalyticsHelper, private val getClubUseCase: GetClubUseCase, private val postClubMemberUseCase: PostClubMemberUseCase, + private val patchClubUseCase: PatchClubUseCase, ) : BaseViewModel(), ClubDetailActionHandler { val clubErrorHandler = ClubErrorHandler() @@ -75,6 +78,10 @@ class ClubDetailViewModel _clubDetailEvent.emit(ClubDetailEvent.OpenDetailMenu(detailViewType)) } + override fun openSelectState() { + _clubDetailEvent.emit(ClubDetailEvent.Navigation.NavigateSelectState) + } + fun joinClub(dogs: List) = viewModelScope.launch { analyticsHelper.logParticipateClick() @@ -96,6 +103,25 @@ class ClubDetailViewModel ) } + fun submitClubStateModify(newState: ClubState) = + viewModelScope.launch { + val club = club.value ?: return@launch + patchClubUseCase( + clubId = club.clubId, + title = club.title, + content = club.content, + state = newState, + ).fold( + onSuccess = { + _club.value = club.copy(clubState = newState) + _clubDetailEvent.emit(ClubDetailEvent.SaveReLoadState) + }, + onError = { error -> + clubErrorHandler.handle(error) + }, + ) + } + private fun requireRegisterUserPet() { _clubDetailEvent.emit(ClubDetailEvent.Navigation.NavigateToRegisterPet) } diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/list/ClubListBindingAdapters.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/list/ClubListBindingAdapters.kt index 9429d96c4..060df748c 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/list/ClubListBindingAdapters.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/list/ClubListBindingAdapters.kt @@ -38,7 +38,8 @@ fun TextView.bindMyLocation(userAddress: UserAddress?) { } @BindingAdapter("clubStateTextStyle") -fun TextView.bindClubStateTextStyle(clubState: ClubState) { +fun TextView.bindClubStateTextStyle(clubState: ClubState?) { + clubState ?: return val textStyle = when (clubState) { ClubState.OPEN -> context.getColor(R.color.coral500) @@ -48,7 +49,8 @@ fun TextView.bindClubStateTextStyle(clubState: ClubState) { } @BindingAdapter("clubStateText") -fun TextView.bindClubStateText(clubState: ClubState) { +fun TextView.bindClubStateText(clubState: ClubState?) { + clubState ?: return this.text = when (clubState) { ClubState.OPEN -> context.getString(R.string.club_state_open) diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyActivity.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyActivity.kt index 51ee2c12c..aad894867 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyActivity.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyActivity.kt @@ -9,8 +9,8 @@ import com.happy.friendogly.databinding.ActivityClubModifyBinding import com.happy.friendogly.presentation.base.BaseActivity import com.happy.friendogly.presentation.base.observeEvent import com.happy.friendogly.presentation.ui.club.common.MessageHandler +import com.happy.friendogly.presentation.ui.club.common.bottom.ClubRecruitmentBottomSheet import com.happy.friendogly.presentation.ui.club.common.handleError -import com.happy.friendogly.presentation.ui.club.modify.bottom.ClubRecruitmentBottomSheet import com.happy.friendogly.presentation.utils.customOnFocusChangeListener import com.happy.friendogly.presentation.utils.hideKeyboard import com.happy.friendogly.presentation.utils.intentSerializable diff --git a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyBindingAdapters.kt b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyBindingAdapters.kt index 0f154aa05..8df7ada9c 100644 --- a/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyBindingAdapters.kt +++ b/android/app/src/main/java/com/happy/friendogly/presentation/ui/club/modify/ClubModifyBindingAdapters.kt @@ -9,7 +9,8 @@ import com.happy.friendogly.R import com.happy.friendogly.domain.model.ClubState @BindingAdapter("selectModifyStateBackground") -fun View.bindSelectModifyStateBackground(clubState: ClubState) { +fun View.bindSelectModifyStateBackground(clubState: ClubState?) { + clubState ?: return val backgroundTint = if (clubState == ClubState.FULL) { ContextCompat.getColorStateList( @@ -26,7 +27,8 @@ fun View.bindSelectModifyStateBackground(clubState: ClubState) { } @BindingAdapter("selectModifyStateTypeStyle") -fun TextView.bindSelectModifyStateTypeStyle(clubState: ClubState) { +fun TextView.bindSelectModifyStateTypeStyle(clubState: ClubState?) { + clubState ?: return val textStyle = if (clubState == ClubState.FULL) { R.style.Theme_AppCompat_TextView_SemiBold_Gray07_Size14 @@ -37,7 +39,8 @@ fun TextView.bindSelectModifyStateTypeStyle(clubState: ClubState) { } @BindingAdapter("selectModifyStateImageTint") -fun ImageView.bindSelectModifyStateImageTint(clubState: ClubState) { +fun ImageView.bindSelectModifyStateImageTint(clubState: ClubState?) { + clubState ?: return val backgroundTint = if (clubState == ClubState.FULL) { ContextCompat.getColorStateList( diff --git a/android/app/src/main/res/layout/activity_club_detail.xml b/android/app/src/main/res/layout/activity_club_detail.xml index ccf6e36a8..e2e8c834d 100644 --- a/android/app/src/main/res/layout/activity_club_detail.xml +++ b/android/app/src/main/res/layout/activity_club_detail.xml @@ -11,253 +11,309 @@ type="com.happy.friendogly.presentation.ui.club.detail.ClubDetailViewModel" /> - - + android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + + + + + + + + - - - + android:layout_marginBottom="5dp" + android:orientation="horizontal" + app:layout_constraintBottom_toBottomOf="@id/view_club_detail_user_top_bar" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/iv_club_detail_user_image" + app:layout_constraintTop_toBottomOf="@id/tv_club_detail_user_name"> - + + - - - - - + + - - - + - + + + + + + + + + + + + + android:layout_margin="10dp" + android:orientation="horizontal" + app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" + app:layout_constraintTop_toBottomOf="@id/view_club_state_modify" + tools:listitem="@layout/item_filter" /> - + android:layout_margin="10dp" + android:paddingTop="10dp" + android:text="@{vm.club.title}" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/rcv_club_detail_filter_list" + tools:text="모임 이름이에요~모임 이름이에요~모임 이름이에요~모임 이름이에요~" /> - + android:layout_margin="10dp" + android:paddingTop="10dp" + android:text="@{vm.club.content}" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_club_detail_subject" + tools:text="모임 내용입니다.모임 내용입니다.모임 내용입니다.모임 내용입니다.모임 내용입니다.모임 내용입니다.모임 내용입니다.모임 내용입니다." /> - + - + - + - - - + + + + + android:layout_margin="10dp" + android:paddingTop="10dp" + android:text="@string/club_dog_list_subject" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/rcv_club_detail_user_list" /> - + android:layout_marginTop="10dp" + android:layout_marginEnd="10dp" + android:layout_marginBottom="90dp" + android:orientation="horizontal" + app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_club_list_dog_list_subject" + tools:listitem="@layout/item_detail_profile" /> + + - - + - + android:layout_gravity="start" + android:background="@drawable/ripple_circle_white" + android:padding="16dp" + android:src="@drawable/ic_arrow_left" + app:tint="@color/black" /> - - - + + + + + + - - + + diff --git a/android/app/src/main/res/layout/fragment_club_add_filter.xml b/android/app/src/main/res/layout/fragment_club_add_filter.xml index 1b0fbcc03..f1dfc8247 100644 --- a/android/app/src/main/res/layout/fragment_club_add_filter.xml +++ b/android/app/src/main/res/layout/fragment_club_add_filter.xml @@ -24,7 +24,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" - android:text="@string/club_add_information_main_title" /> + android:text="@string/club_add_filter_main_title" /> 모임을 소개해주세요. 기준으로 모임이 생성돼요. 모임 생성을 위해서 주소를 등록해주세요! - 댕댕이 사이즈 선택 - 댕댕이 성별 선택 + 강아지 사이즈 선택 + 강아지 성별 선택 모임 제목 참여 가능 인원 모임 소개 - 내 댕댕이 - 댕댕이 추가 등록하기 모임명 모임을 소개해주세요. - 모집할 댕댕이를 설정해주세요. + 모집할 강아지를 설정해주세요. 사이즈와 성별을 선택할 수 있어요! 누구나 가능해요! 모임 정보를 입력해주세요 @@ -212,9 +210,9 @@ 모집 여부 모임 수정에 실패하였습니다.. - + 모임에 참여할 강아지를 선택해주세요. - 조건에 맞는 댕댕이만 선택할 수 있어요! + 조건에 맞는 강아지만 선택할 수 있어요! %s는 모임에 참여할 수 없어요.. 강아지를 등록해야 모임에 참여할 수 있어요! %s는 모임에 데려갈 수 없어요.. diff --git a/android/app/src/test/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModelTest.kt b/android/app/src/test/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModelTest.kt index 2a9dc58bd..eeb929840 100644 --- a/android/app/src/test/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModelTest.kt +++ b/android/app/src/test/java/com/happy/friendogly/presentation/ui/club/detail/ClubDetailViewModelTest.kt @@ -4,6 +4,7 @@ import com.happy.friendogly.domain.DomainResult import com.happy.friendogly.domain.error.DataError import com.happy.friendogly.domain.model.ClubState import com.happy.friendogly.domain.usecase.GetClubUseCase +import com.happy.friendogly.domain.usecase.PatchClubUseCase import com.happy.friendogly.domain.usecase.PostClubMemberUseCase import com.happy.friendogly.firebase.analytics.AnalyticsHelper import com.happy.friendogly.presentation.ui.club.common.ClubErrorEvent @@ -41,6 +42,9 @@ class ClubDetailViewModelTest { @MockK private lateinit var postClubMemberUseCase: PostClubMemberUseCase + @MockK + private lateinit var patchClubUseCase: PatchClubUseCase + @BeforeEach fun setup() { analyticsHelper = mockk(relaxed = true) @@ -65,6 +69,7 @@ class ClubDetailViewModelTest { analyticsHelper = analyticsHelper, getClubUseCase = getClubUseCase, postClubMemberUseCase = postClubMemberUseCase, + patchClubUseCase = patchClubUseCase, ) // when @@ -88,6 +93,7 @@ class ClubDetailViewModelTest { analyticsHelper = analyticsHelper, getClubUseCase = getClubUseCase, postClubMemberUseCase = postClubMemberUseCase, + patchClubUseCase = patchClubUseCase, ) // when @@ -126,6 +132,7 @@ class ClubDetailViewModelTest { analyticsHelper = analyticsHelper, getClubUseCase = getClubUseCase, postClubMemberUseCase = postClubMemberUseCase, + patchClubUseCase = patchClubUseCase, ) // when @@ -163,6 +170,7 @@ class ClubDetailViewModelTest { analyticsHelper = analyticsHelper, getClubUseCase = getClubUseCase, postClubMemberUseCase = postClubMemberUseCase, + patchClubUseCase = patchClubUseCase, ) // when