diff --git a/core-ui/src/main/java/com/going/ui/base/BaseBottomSheet.kt b/core-ui/src/main/java/com/going/ui/base/BaseBottomSheet.kt index 28a039bf..cd376351 100644 --- a/core-ui/src/main/java/com/going/ui/base/BaseBottomSheet.kt +++ b/core-ui/src/main/java/com/going/ui/base/BaseBottomSheet.kt @@ -31,4 +31,4 @@ abstract class BaseBottomSheet( super.onDestroyView() _binding = null } -} \ No newline at end of file +} diff --git a/presentation/src/main/java/com/going/presentation/entertrip/createtrip/choosedate/BottomSheetDateContentFragment.kt b/presentation/src/main/java/com/going/presentation/entertrip/createtrip/choosedate/BottomSheetDateContentFragment.kt index 9d2edfb2..ce158779 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/createtrip/choosedate/BottomSheetDateContentFragment.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/createtrip/choosedate/BottomSheetDateContentFragment.kt @@ -1,8 +1,6 @@ package com.going.presentation.entertrip.createtrip.choosedate import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.view.View import com.going.presentation.R import com.going.presentation.databinding.FragmentBottomSheetDateContentBinding @@ -16,20 +14,47 @@ class BottomSheetDateContentFragment(val viewModel: CreateTripViewModel, val isS override fun onStart() { super.onStart() dialog?.window?.setBackgroundDrawableResource(R.color.transparent) + customStartDate() + customEndDate() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - destroyToast() + binding.lifecycleOwner = viewLifecycleOwner initFinishBtnClickListener() } + private fun customStartDate() { + val datePicker = binding.dpCreateTripDate + val calendar = Calendar.getInstance() - private fun destroyToast() { - dialog?.setOnDismissListener { - binding.tvErrorToast.visibility = View.GONE - } + val currentStartYear = calendar.get(Calendar.YEAR) + val currentStartMonth = calendar.get(Calendar.MONTH) + val currentStartDay = calendar.get(Calendar.DAY_OF_MONTH) + + calendar.set(2000, 0, 1) + datePicker.minDate = calendar.timeInMillis + + calendar.set(2100, 0, 1) + datePicker.maxDate = calendar.timeInMillis + + datePicker.updateDate(currentStartYear, currentStartMonth, currentStartDay) + } + + + private fun customEndDate() { + val datePicker = binding.dpCreateTripDate + val calendar = Calendar.getInstance() + + val currentEndYear = viewModel.startYear.value ?: 0 + val currentEndMonth = viewModel.startMonth.value ?: 0 + val currentEndDay = viewModel.startDay.value ?: 0 + + calendar.set(currentEndYear, currentEndMonth - 1, currentEndDay) + datePicker.minDate = calendar.timeInMillis + + calendar.set(2100, 0, 1) + datePicker.maxDate = calendar.timeInMillis } private fun sendDateInfo() { @@ -39,6 +64,7 @@ class BottomSheetDateContentFragment(val viewModel: CreateTripViewModel, val isS viewModel.startDay.value = binding.dpCreateTripDate.dayOfMonth viewModel.checkStartDateAvailable() } else { + customEndDate() viewModel.endYear.value = binding.dpCreateTripDate.year viewModel.endMonth.value = binding.dpCreateTripDate.month + 1 viewModel.endDay.value = binding.dpCreateTripDate.dayOfMonth @@ -67,21 +93,9 @@ class BottomSheetDateContentFragment(val viewModel: CreateTripViewModel, val isS viewModel.checkStartDateAvailable() viewModel.checkEndDateAvailable() dismiss() - } else { - viewModel.startYear.value = null - viewModel.endYear.value = null - viewModel.checkStartDateAvailable() - viewModel.checkEndDateAvailable() - - binding.viewBlank.visibility = View.VISIBLE - binding.tvErrorToast.visibility = View.VISIBLE - Handler(Looper.getMainLooper()).postDelayed({ - binding.tvErrorToast.visibility = View.GONE - }, 2000) } - } else { + } else dismiss() - } } } } diff --git a/presentation/src/main/java/com/going/presentation/entertrip/createtrip/finish/FinishTripActivity.kt b/presentation/src/main/java/com/going/presentation/entertrip/createtrip/finish/FinishTripActivity.kt index 4bd0a826..f7c09c1d 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/createtrip/finish/FinishTripActivity.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/createtrip/finish/FinishTripActivity.kt @@ -46,7 +46,7 @@ class FinishTripActivity : } private fun initCopyCodetvClickListener() { - binding.tvFinishTripTermsText.setOnSingleClickListener { + binding.clCopyCode.setOnSingleClickListener { val clipboardManager = this.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipData = ClipData.newPlainText("INVITE_CODE_LABEL", inviteCode) @@ -62,16 +62,16 @@ class FinishTripActivity : private fun startKakaoInvite(context: Context) { val test = HashMap() - test.put("KEY", inviteCode) - test.put("NAME", title) + test.put(KEY, inviteCode) + test.put(NAME, title) if (ShareClient.instance.isKakaoTalkSharingAvailable(context)) { ShareClient.instance.shareCustom( context, TEMPLATE_ID.toLong(), hashMapOf( - "KEY" to inviteCode, - "NAME" to title + KEY to inviteCode, + NAME to title ) ) { sharingResult, error -> if (error != null) { @@ -85,8 +85,8 @@ class FinishTripActivity : WebSharerClient.instance.makeCustomUrl( TEMPLATE_ID.toLong(), hashMapOf( - "KEY" to inviteCode, - "NAME" to title + KEY to inviteCode, + NAME to title ) ) try { @@ -140,6 +140,9 @@ class FinishTripActivity : companion object { const val TAG_SHARE = "recommendInvite" const val TEMPLATE_ID = 102829 + const val KEY = "KEY" + const val NAME = "NAME" + } } diff --git a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/finish/InviteFinishActivity.kt b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/finish/InviteFinishActivity.kt index 709571ed..cb5ed045 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/finish/InviteFinishActivity.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/finish/InviteFinishActivity.kt @@ -69,7 +69,7 @@ class InviteFinishActivity : companion object { const val DATE_FORMAT = "%s - %s" - const val D_DAY_FORMAT = "D - %d" + const val D_DAY_FORMAT = "D-%d" const val TRIP_FORMAT = "여행중" } } diff --git a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripActivity.kt b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripActivity.kt index ce27d694..9a29edfa 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripActivity.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripActivity.kt @@ -98,9 +98,9 @@ class EnterTripActivity : BaseActivity(R.layout.activi is UiState.Failure -> { when (state.msg) { - ERROR_NO_EXIST -> toast(getString(R.string.enter_trip_invite_code_exist_error)) + ERROR_NO_EXIST -> toast(getString(R.string.enter_trip_invite_code_exist_toast)) - ERROR_OVER_SIX -> toast(getString(R.string.enter_trip_invite_code_over_error)) + ERROR_OVER_SIX -> toast(getString(R.string.enter_trip_invite_code_over_toast)) else -> toast(getString(R.string.server_error)) } @@ -113,6 +113,7 @@ class EnterTripActivity : BaseActivity(R.layout.activi }.launchIn(lifecycleScope) } + private fun initNextBtnClickListener() { binding.btnEnterTripNext.setOnSingleClickListener { viewModel.checkInviteCodeFromServer() diff --git a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripViewModel.kt b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripViewModel.kt index 9d692b7a..7bef99a3 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripViewModel.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/invitecode/EnterTripViewModel.kt @@ -29,7 +29,7 @@ class EnterTripViewModel @Inject constructor( var codeLength = MutableLiveData(0) val isCodeAvailable = MutableLiveData(CodeState.Empty) - var isCheckEnterAvailable = MutableLiveData(false) + val isInviteCodeAvailable = MutableLiveData(false) fun checkCodeAvailable() { codeLength.value = getCodeLength(inviteCode.value) @@ -37,16 +37,24 @@ class EnterTripViewModel @Inject constructor( codeLength.value == 0 -> CodeState.Empty inviteCode.value.isNullOrBlank() -> CodeState.Blank !isCodeValid(inviteCode.value) -> CodeState.Invalid - else -> CodeState.Success.also { checkEnterAvailable() } + else -> CodeState.Success } + + val isLengthAvailable = codeLength.value in 1..MAX_INVITE_LEN + + isInviteCodeAvailable.value = + (isCodeAvailable.value == CodeState.Success) && isLengthAvailable + + checkEnterAvailable() } private fun getCodeLength(value: String?) = value?.length ?: 0 - private fun isCodeValid(code: String?) = code?.matches(ENG_NUM_REGEX.toRegex()) ?: false + private fun isCodeValid(code: String?) = + code?.matches(ENG_NUM_REGEX.toRegex()) == true && code.length == 6 fun checkEnterAvailable() { - isCheckEnterAvailable.value = isCodeAvailable.value == CodeState.Success + isInviteCodeAvailable.value = isCodeAvailable.value == CodeState.Success } fun checkInviteCodeFromServer() { @@ -73,5 +81,6 @@ class EnterTripViewModel @Inject constructor( const val MAX_INVITE_LEN = 6 const val ERROR_NO_EXIST = "e4043" const val ERROR_OVER_SIX = "e4006" + const val ERROR_ALREADY_EXIST = "e4092" } } diff --git a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceActivity.kt b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceActivity.kt index 0ccedcdb..6dc51459 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceActivity.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceActivity.kt @@ -12,9 +12,9 @@ import com.going.presentation.dashboard.DashBoardActivity import com.going.presentation.dashboard.DashBoardActivity.Companion.IS_FIRST_ENTERED import com.going.presentation.databinding.ActivityFinishPreferenceBinding import com.going.presentation.entertrip.invitetrip.invitecode.EnterTripActivity.Companion.TRIP_ID +import com.going.presentation.entertrip.invitetrip.invitecode.EnterTripViewModel.Companion.ERROR_ALREADY_EXIST import com.going.presentation.entertrip.preferencetag.PreferenceTagAdapter import com.going.presentation.entertrip.preferencetag.PreferenceTagDecoration -import com.going.presentation.util.initOnBackPressedListener import com.going.ui.base.BaseActivity import com.going.ui.extension.UiState import com.going.ui.extension.setOnSingleClickListener @@ -79,7 +79,11 @@ class FinishPreferenceActivity : is UiState.Success -> navigateToDashBoard(state.data.tripId) is UiState.Failure -> { - toast(getString(R.string.server_error)) + when (state.msg) { + ERROR_ALREADY_EXIST -> toast(getString(R.string.enter_trip_my_code_toast)) + + else -> toast(getString(R.string.server_error)) + } } is UiState.Loading -> return@onEach diff --git a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceViewModel.kt b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceViewModel.kt index 441c0d19..7b37359a 100644 --- a/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceViewModel.kt +++ b/presentation/src/main/java/com/going/presentation/entertrip/invitetrip/preference/FinishPreferenceViewModel.kt @@ -12,6 +12,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import org.json.JSONObject +import retrofit2.HttpException import javax.inject.Inject @HiltViewModel @@ -34,7 +36,8 @@ class FinishPreferenceViewModel @Inject constructor( _finishInviteState.value = UiState.Loading viewModelScope.launch { enterTripRepository.postStartInviteTrip( - tripId, StartInviteTripRequestModel( + tripId, + StartInviteTripRequestModel( styleA.value ?: 0, styleB.value ?: 0, styleC.value ?: 0, @@ -42,10 +45,15 @@ class FinishPreferenceViewModel @Inject constructor( styleE.value ?: 0, ), ).onSuccess { - _finishInviteState.value = UiState.Success(it) - }.onFailure { - _finishInviteState.value = UiState.Failure(it.message.orEmpty()) + _finishInviteState.value = UiState.Success(it) + }.onFailure { throwable -> + if (throwable is HttpException) { + val errorResponse = throwable.response()?.errorBody()?.string() + val jsonObject = JSONObject(errorResponse) + val errorCode = jsonObject.getString("code") + _finishInviteState.value = UiState.Failure(errorCode) } + } } } @@ -81,5 +89,4 @@ class FinishPreferenceViewModel @Inject constructor( rightPrefer = "여유롭게", ), ) - } diff --git a/presentation/src/main/java/com/going/presentation/tendency/result/UserTendencyResultList.kt b/presentation/src/main/java/com/going/presentation/tendency/result/UserTendencyResultList.kt index 3f09397a..f9fc7a86 100644 --- a/presentation/src/main/java/com/going/presentation/tendency/result/UserTendencyResultList.kt +++ b/presentation/src/main/java/com/going/presentation/tendency/result/UserTendencyResultList.kt @@ -11,7 +11,7 @@ val UserTendencyResultList = listOf( profileTitle = "배려심 넘치는, 든든잉", profileSubTitle = "꼼꼼하고 세심하게 여행을 준비해요", tags = listOf( - "친구와 함께", + "친구와함께", "꼼꼼함", "세심함", ), @@ -173,7 +173,7 @@ val UserTendencyResultList = listOf( tags = listOf( "낙천적", "낭만추구", - "남는건 사", + "남는건사진", ), profileBoxInfo = listOf( ProfileMock.BoxInfo( diff --git a/presentation/src/main/res/drawable/shape_rect_6_gray100_line.xml b/presentation/src/main/res/drawable/shape_rect_6_gray100_line.xml new file mode 100644 index 00000000..06f32878 --- /dev/null +++ b/presentation/src/main/res/drawable/shape_rect_6_gray100_line.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/presentation/src/main/res/layout/activity_create_trip.xml b/presentation/src/main/res/layout/activity_create_trip.xml index 840395bf..7c88d3f7 100644 --- a/presentation/src/main/res/layout/activity_create_trip.xml +++ b/presentation/src/main/res/layout/activity_create_trip.xml @@ -74,7 +74,7 @@ android:hint="@string/create_trip_et_name_hint" android:imeOptions="actionNext" android:inputType="text" - android:maxLines="1" + android:maxLines="3" android:text="@={viewModel.name}" android:textAppearance="@style/TextAppearance.Doorip.Detail1.Regular" app:layout_constraintEnd_toEndOf="parent" @@ -131,7 +131,7 @@ android:layout_weight="1" android:background="@drawable/shape_rect_4_gray200_line" android:hint="@string/create_trip_start_date" - android:maxLines="1" + android:maxLines="2" android:paddingHorizontal="12dp" android:paddingVertical="16dp" android:text="@{viewModel.isStartDateAvailable() == true ? @string/create_trip_date(viewModel.startYear, viewModel.startMonth, viewModel.startDay) : @string/create_trip_start_date}" /> @@ -152,7 +152,7 @@ android:layout_weight="1" android:background="@drawable/shape_rect_4_gray200_line" android:hint="@string/create_trip_end_date" - android:maxLines="1" + android:maxLines="2" android:paddingHorizontal="12dp" android:paddingVertical="16dp" android:text="@{viewModel.isEndDateAvailable() == true ? @string/create_trip_date(viewModel.endYear, viewModel.endMonth, viewModel.endDay) : @string/create_trip_end_date}" /> diff --git a/presentation/src/main/res/layout/activity_enter_trip.xml b/presentation/src/main/res/layout/activity_enter_trip.xml index 90c9251d..15c09849 100644 --- a/presentation/src/main/res/layout/activity_enter_trip.xml +++ b/presentation/src/main/res/layout/activity_enter_trip.xml @@ -18,7 +18,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white_000" - tools:context=".entertrip.createtrip.choosedate.CreateTripActivity"> + tools:context=".entertrip.invitetrip.invitecode.EnterTripActivity"> - - - + app:layout_constraintStart_toStartOf="parent"> - - + android:layout_width="match_parent" + android:layout_height="match_parent"> - + app:layout_constraintTop_toTopOf="parent" + tools:ignore="NotSibling"> - + - + - + - - - + - + - + - + - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + - diff --git a/presentation/src/main/res/layout/activity_invite_finish.xml b/presentation/src/main/res/layout/activity_invite_finish.xml index 9a66d7bd..612d51e2 100644 --- a/presentation/src/main/res/layout/activity_invite_finish.xml +++ b/presentation/src/main/res/layout/activity_invite_finish.xml @@ -94,24 +94,26 @@ diff --git a/presentation/src/main/res/layout/activity_profile.xml b/presentation/src/main/res/layout/activity_profile.xml index 5eb7b720..7d74b64a 100644 --- a/presentation/src/main/res/layout/activity_profile.xml +++ b/presentation/src/main/res/layout/activity_profile.xml @@ -481,8 +481,8 @@ diff --git a/presentation/src/main/res/layout/fragment_bottom_sheet_date_content.xml b/presentation/src/main/res/layout/fragment_bottom_sheet_date_content.xml index 6aafd780..0cb18226 100644 --- a/presentation/src/main/res/layout/fragment_bottom_sheet_date_content.xml +++ b/presentation/src/main/res/layout/fragment_bottom_sheet_date_content.xml @@ -1,6 +1,7 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> @@ -11,28 +12,6 @@ android:layout_height="wrap_content" android:background="@color/transparent_60"> - - - - + tools:ignore="MissingConstraints"> 여행을 할 때 우리는 어떤 모습일까? - 9개의 질문으로\n나를 대신 할 여행 캐릭터를 찾아보세요 + 9개의 질문으로\n나를 대신할 여행 캐릭터를 찾아보세요 테스트 시작하기 @@ -179,9 +179,9 @@ 친구에게 받은 초대코드 6자리를 입력해 주세요 잘못된 초대코드예요. 초대코드 확인하기 - 존재하지 않는 여행입니다 - 존재하지 않는 여행입니다. - 입장할 수 있는 최대 인원은 6명입니다. + 존재하지 않는 여행입니다 + 입장할 수 있는 최대 인원은 6명입니다 + 이미 존재하는 참가자입니다 초대받은 여행이 맞는지\n 확인해 주세요