Skip to content

Commit

Permalink
Merge pull request #105 from POLZZAK/feat/my_notice_etc
Browse files Browse the repository at this point in the history
[FEAT] 계정관리, 이용약관
  • Loading branch information
kim0hoon authored Sep 7, 2023
2 parents 6646003 + b24b479 commit 3aaca54
Show file tree
Hide file tree
Showing 46 changed files with 1,447 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.polzzak_android.presentation.common.item

import com.polzzak_android.R
import com.polzzak_android.databinding.ItemFullLoadingBinding
import com.polzzak_android.presentation.common.util.BindableItem

class FullLoadingItem : BindableItem<ItemFullLoadingBinding>() {
override val layoutRes: Int = R.layout.item_full_loading

override fun areItemsTheSame(other: BindableItem<*>): Boolean = other is FullLoadingItem

override fun areContentsTheSame(other: BindableItem<*>): Boolean = other is FullLoadingItem

override fun bind(binding: ItemFullLoadingBinding, position: Int) {
//do nothing
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.polzzak_android.presentation.common.util

import android.content.Context
import android.util.DisplayMetrics
import java.time.Duration
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Period
import java.time.format.DateTimeFormatter

const val SERVER_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS"
Expand All @@ -31,4 +31,22 @@ fun LocalDateTime.getRemainingSeconds(): Int {
.between(LocalDateTime.now(), endTime)
.seconds
.toInt()
}
}

/**
* 날짜 규칙
* 3달 미만의 공지: O월.O일 (ex. 06.24)
* 3개월 이상 1년 미만의 공지: O개월 전 (ex. 3개월 전 ~ 11개월 전)
* 1년 이상이 지난 공지: 1년 단위로 카운팅(ex. 1년 전, 2년 전)
*/
fun LocalDate.toPublishedDateString(): String {
val nowDate = LocalDate.now()
val diff = Period.between(this, nowDate)
val getDateStr = { date: Int -> String.format("%02d", date) }
return when {
this.isAfter(nowDate.minusMonths(3)) -> "${getDateStr(this.monthValue)}.${getDateStr(this.dayOfMonth)}"
this.isBefore(nowDate.minusYears(1)) || this.isEqual(nowDate.minusYears(1)) -> "${diff.years}년 전"
else -> "${diff.months}개월 전"
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ class PermissionManager(private val activity: AppCompatActivity) {
permission
) != PackageManager.PERMISSION_GRANTED
}) return true

val dialogTitleSpannable = SpannableBuilder.build(activity) {
span(text = dialogTitle, textColor = R.color.gray_700, style = R.style.subtitle_18_600)
}
CommonDialogHelper.getInstance(
content = CommonDialogModel(
type = DialogStyleType.ALERT,
content = CommonDialogContent(title = dialogTitle),
content = CommonDialogContent(title = dialogTitleSpannable),
button = CommonButtonModel(
buttonCount = ButtonCount.TWO,
negativeButtonText = activity.getString(R.string.permission_manager_dialog_btn_negative_text),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import com.polzzak_android.presentation.common.model.ModelState
import com.polzzak_android.presentation.common.util.PermissionManager
import com.polzzak_android.presentation.common.util.getPermissionManagerOrNull
import com.polzzak_android.presentation.common.util.hideKeyboard
import com.polzzak_android.presentation.feature.term.TermDetailFragment
import com.polzzak_android.presentation.feature.term.model.TermType
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
import javax.inject.Inject
Expand Down Expand Up @@ -240,35 +242,19 @@ class SignUpFragment : BaseFragment<FragmentSignupBinding>() {
}
ivBtnServiceDetail.setOnClickListener {
val detailDataBundle = Bundle().apply {
putString(
SignUpTermDetailFragment.ARGUMENT_TITLE_KEY,
getString(R.string.signup_terms_of_service_detail_service_title)
)
//TODO 약관 url 추가
putString(
SignUpTermDetailFragment.ARGUMENT_URL_KEY,
"http://google.co.kr"
)
putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.SERVICE)
}
findNavController().navigate(
R.id.action_signUpFragment_to_signUpTermDetailFragment,
R.id.action_signUpFragment_to_termDetailFragment,
detailDataBundle
)
}
ivBtnPrivacyDetail.setOnClickListener {
val detailDataBundle = Bundle().apply {
putString(
SignUpTermDetailFragment.ARGUMENT_TITLE_KEY,
getString(R.string.signup_terms_of_service_detail_privacy_title)
)
//TODO 약관 url 추가
putString(
SignUpTermDetailFragment.ARGUMENT_URL_KEY,
"http://naver.com"
)
putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.PRIVACY)
}
findNavController().navigate(
R.id.action_signUpFragment_to_signUpTermDetailFragment,
R.id.action_signUpFragment_to_termDetailFragment,
detailDataBundle
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package com.polzzak_android.presentation.feature.myPage.accountmanagement

import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.polzzak_android.R
import com.polzzak_android.databinding.FragmentMyAccountDeleteBinding
import com.polzzak_android.presentation.common.model.ButtonCount
import com.polzzak_android.presentation.common.model.CommonButtonModel
import com.polzzak_android.presentation.common.model.ModelState
import com.polzzak_android.presentation.common.util.SpannableBuilder
import com.polzzak_android.presentation.component.dialog.CommonDialogContent
import com.polzzak_android.presentation.component.dialog.CommonDialogHelper
import com.polzzak_android.presentation.component.dialog.CommonDialogModel
import com.polzzak_android.presentation.component.dialog.DialogStyleType
import com.polzzak_android.presentation.component.dialog.OnButtonClickListener
import com.polzzak_android.presentation.component.toolbar.ToolbarData
import com.polzzak_android.presentation.component.toolbar.ToolbarHelper
import com.polzzak_android.presentation.feature.myPage.accountmanagement.MyAccountManagementFragment.Companion.ARGUMENT_NICKNAME_KEY
import com.polzzak_android.presentation.feature.myPage.accountmanagement.base.BaseMyAccountFragment
import timber.log.Timber

class MyAccountDeleteFragment : BaseMyAccountFragment<FragmentMyAccountDeleteBinding>() {
override val layoutResId: Int = R.layout.fragment_my_account_delete

private val myAccountDeleteViewModel by viewModels<MyAccountDeleteViewModel>()

private var currentDialog: DialogFragment? = null

override fun initView() {
super.initView()
initToolbar()
with(binding) {
val nickName = arguments?.getString(ARGUMENT_NICKNAME_KEY) ?: ""
tvTitle.text = getString(R.string.my_account_management_delete_title, nickName)
with(inMenuDeleteLink) {
tvContent.text =
getText(R.string.my_account_management_delete_menu_delete_link)
root.setOnClickListener {
myAccountDeleteViewModel.toggleDeleteLink()
}
}
with(inMenuDeletePoint) {
tvContent.text =
getText(R.string.my_account_management_delete_menu_delete_point)
root.setOnClickListener {
myAccountDeleteViewModel.toggleDeletePoint()
}
}
with(inMenuDeleteSocialAccountData) {
tvContent.text =
getText(R.string.my_account_management_delete_menu_delete_social_account_data)
root.setOnClickListener {
myAccountDeleteViewModel.toggleDeleteSocialAccountData()
}
}
with(inMenuDeleteStampAndCoupon) {
tvContent.text =
getText(R.string.my_account_management_delete_menu_delete_stamp_and_coupon)
root.setOnClickListener {
myAccountDeleteViewModel.toggleDeleteStampAndCoupon()
}
}
tvBtnDeleteAccount.setOnClickListener {
val context = context ?: return@setOnClickListener
val dialogTitleSpannable = SpannableBuilder.build(context) {
span(
text = getString(R.string.my_account_management_delete_dialog_title),
style = R.style.subtitle_18_600,
textColor = R.color.gray_700
)
}
val dialog = CommonDialogHelper.getInstance(
content = CommonDialogModel(
type = DialogStyleType.ALERT,
content = CommonDialogContent(title = dialogTitleSpannable),
button = CommonButtonModel(
buttonCount = ButtonCount.TWO,
positiveButtonText = getString(R.string.my_account_management_delete_dialog_btn_positive),
negativeButtonText = getString(R.string.my_account_management_delete_dialog_btn_negative)
)
),
onConfirmListener = {
object : OnButtonClickListener {
override fun setBusinessLogic() {
myAccountDeleteViewModel.deleteAccount()
}

override fun getReturnValue(value: Any) {
//do nothing
}
}
}
)
showDialog(dialogFragment = dialog)
}
}
}

private fun initToolbar() {
ToolbarHelper(
data = ToolbarData(
popStack = findNavController(),
titleText = getString(R.string.my_account_management)
),
toolbar = binding.inToolbar
).set()
}

override fun initObserver() {
super.initObserver()
myAccountDeleteViewModel.myAccountMenuLiveData.observe(viewLifecycleOwner) {
with(binding) {
inMenuDeleteLink.ivBtnCheck.isSelected = it.isCheckedDeleteLink
inMenuDeletePoint.ivBtnCheck.isSelected = it.isCheckedDeletePoint
inMenuDeleteSocialAccountData.ivBtnCheck.isSelected =
it.isCheckedDeleteSocialAccountData
inMenuDeleteStampAndCoupon.ivBtnCheck.isSelected = it.isCheckedDeleteStampAndCoupon
tvBtnDeleteAccount.isEnabled = it.isAllChecked()
}
}

myAccountDeleteViewModel.deleteAccountLiveData.observe(viewLifecycleOwner) {
val context = context ?: return@observe
when (it) {
is ModelState.Loading -> {
val dialogTitleSpannable = SpannableBuilder.build(context) {
span(
text = getString(R.string.my_account_management_delete_dialog_title),
style = R.style.subtitle_18_600,
textColor = R.color.gray_700
)
}
val loadingDialog = CommonDialogHelper.getInstance(
content = CommonDialogModel(
type = DialogStyleType.LOADING,
content = CommonDialogContent(title = dialogTitleSpannable),
button = CommonButtonModel(ButtonCount.ZERO)
)
)
showDialog(dialogFragment = loadingDialog)
}

is ModelState.Success -> {
dismissCurrentDialog()
Timber.d("회원탈퇴")
findRootNavigationOwner()?.backToTheLoginFragment()
}

is ModelState.Error -> {
//TODO error handling
}
}
}
}

private fun showDialog(dialogFragment: DialogFragment) {
currentDialog?.dismiss()
currentDialog = dialogFragment
dialogFragment.show(childFragmentManager, null)
}

private fun dismissCurrentDialog() {
currentDialog?.dismiss()
currentDialog = null
}

override fun onPause() {
super.onPause()
currentDialog?.dismiss()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.polzzak_android.presentation.feature.myPage.accountmanagement

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.polzzak_android.presentation.common.model.ModelState
import com.polzzak_android.presentation.feature.myPage.accountmanagement.model.MyAccountDeleteMenuModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MyAccountDeleteViewModel : ViewModel() {
private val _myAccountMenuLiveData = MutableLiveData<MyAccountDeleteMenuModel>()
val myAccountMenuLiveData: LiveData<MyAccountDeleteMenuModel> = _myAccountMenuLiveData

private val _deleteAccountLiveData = MutableLiveData<ModelState<Unit>>()
val deleteAccountLiveData: LiveData<ModelState<Unit>> = _deleteAccountLiveData
private var deleteAccountJob: Job? = null

fun toggleDeleteSocialAccountData() {
_myAccountMenuLiveData.value =
(myAccountMenuLiveData.value ?: MyAccountDeleteMenuModel()).run {
copy(isCheckedDeleteSocialAccountData = !isCheckedDeleteSocialAccountData)
}
}

fun toggleDeleteLink() {
_myAccountMenuLiveData.value =
(myAccountMenuLiveData.value ?: MyAccountDeleteMenuModel()).run {
copy(isCheckedDeleteLink = !isCheckedDeleteLink)
}
}

fun toggleDeletePoint() {
_myAccountMenuLiveData.value =
(myAccountMenuLiveData.value ?: MyAccountDeleteMenuModel()).run {
copy(isCheckedDeletePoint = !isCheckedDeletePoint)
}
}

fun toggleDeleteStampAndCoupon() {
_myAccountMenuLiveData.value =
(myAccountMenuLiveData.value ?: MyAccountDeleteMenuModel()).run {
copy(isCheckedDeleteStampAndCoupon = !isCheckedDeleteStampAndCoupon)
}
}

fun deleteAccount() {
if (deleteAccountJob?.isCompleted == false) return
deleteAccountJob = viewModelScope.launch {
//TODO 회원탈퇴 API 호출
_deleteAccountLiveData.value = ModelState.Loading()
delay(2000)
//onSuccess
_deleteAccountLiveData.value = ModelState.Success(Unit)
}

}
}
Loading

0 comments on commit 3aaca54

Please sign in to comment.