diff --git a/app/src/main/java/com/polzzak_android/presentation/common/item/FullLoadingItem.kt b/app/src/main/java/com/polzzak_android/presentation/common/item/FullLoadingItem.kt new file mode 100644 index 00000000..5f54b704 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/common/item/FullLoadingItem.kt @@ -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() { + 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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/common/util/Extensions.kt b/app/src/main/java/com/polzzak_android/presentation/common/util/Extensions.kt index 25542d31..ad0683a7 100644 --- a/app/src/main/java/com/polzzak_android/presentation/common/util/Extensions.kt +++ b/app/src/main/java/com/polzzak_android/presentation/common/util/Extensions.kt @@ -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" @@ -31,4 +31,22 @@ fun LocalDateTime.getRemainingSeconds(): Int { .between(LocalDateTime.now(), endTime) .seconds .toInt() -} \ No newline at end of file +} + +/** + * 날짜 규칙 + * 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}개월 전" + } +} + diff --git a/app/src/main/java/com/polzzak_android/presentation/common/util/PermissionManager.kt b/app/src/main/java/com/polzzak_android/presentation/common/util/PermissionManager.kt index 0626c9da..5a2436c1 100644 --- a/app/src/main/java/com/polzzak_android/presentation/common/util/PermissionManager.kt +++ b/app/src/main/java/com/polzzak_android/presentation/common/util/PermissionManager.kt @@ -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), diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpFragment.kt index 36231b1c..275ec7ca 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpFragment.kt @@ -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 @@ -240,35 +242,19 @@ class SignUpFragment : BaseFragment() { } 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 ) } diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteFragment.kt new file mode 100644 index 00000000..6debafac --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteFragment.kt @@ -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() { + override val layoutResId: Int = R.layout.fragment_my_account_delete + + private val myAccountDeleteViewModel by viewModels() + + 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() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteViewModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteViewModel.kt new file mode 100644 index 00000000..1854c51d --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountDeleteViewModel.kt @@ -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() + val myAccountMenuLiveData: LiveData = _myAccountMenuLiveData + + private val _deleteAccountLiveData = MutableLiveData>() + val deleteAccountLiveData: LiveData> = _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) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountManagementFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountManagementFragment.kt new file mode 100644 index 00000000..4608efb3 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/MyAccountManagementFragment.kt @@ -0,0 +1,87 @@ +package com.polzzak_android.presentation.feature.myPage.accountmanagement + +import android.os.Bundle +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.polzzak_android.R +import com.polzzak_android.databinding.FragmentMyAccountManagementBinding +import com.polzzak_android.presentation.common.model.ButtonCount +import com.polzzak_android.presentation.common.model.CommonButtonModel +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.base.BaseMyAccountFragment +import com.polzzak_android.presentation.feature.root.MainViewModel + +class MyAccountManagementFragment : BaseMyAccountFragment() { + override val layoutResId: Int = R.layout.fragment_my_account_management + + private val mainViewModel by activityViewModels() + + override fun initView() { + super.initView() + initToolbar() + binding.tvBtnLogout.setOnClickListener { + val context = context ?: return@setOnClickListener + val dialogTitleSpannable = SpannableBuilder.build(context) { + span( + getString(R.string.my_account_management_logout_dialog_title), + style = R.style.subtitle_18_600, + textColor = R.color.gray_700 + ) + } + CommonDialogHelper.getInstance( + content = CommonDialogModel( + type = DialogStyleType.ALERT, + content = CommonDialogContent(title = dialogTitleSpannable), + button = CommonButtonModel( + buttonCount = ButtonCount.TWO, + positiveButtonText = getString(R.string.my_account_management_logout_dialog_btn_positive) + ) + ), + onConfirmListener = { + object : OnButtonClickListener { + override fun setBusinessLogic() { + findRootNavigationOwner()?.let { + mainViewModel.logout() + it.backToTheLoginFragment() + } + } + + override fun getReturnValue(value: Any) { + //do nothing + } + } + } + ).show(childFragmentManager, null) + } + binding.tvBtnDeleteAccount.setOnClickListener { + val nickName = arguments?.getString(ARGUMENT_NICKNAME_KEY) ?: "" + val bundle = Bundle().apply { + putString(ARGUMENT_NICKNAME_KEY, nickName) + } + findNavController().navigate( + R.id.action_myAccountManagementFragment_to_myAccountDeleteFragment, + bundle + ) + } + } + + private fun initToolbar() { + ToolbarHelper( + data = ToolbarData( + popStack = findNavController(), + titleText = getString(R.string.my_account_management) + ), toolbar = binding.inToolbar + ).set() + } + + companion object { + const val ARGUMENT_NICKNAME_KEY = "argument_nickname_key" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/base/BaseMyAccountFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/base/BaseMyAccountFragment.kt new file mode 100644 index 00000000..079f3854 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/base/BaseMyAccountFragment.kt @@ -0,0 +1,16 @@ +package com.polzzak_android.presentation.feature.myPage.accountmanagement.base + +import androidx.databinding.ViewDataBinding +import com.polzzak_android.presentation.common.base.BaseFragment +import com.polzzak_android.presentation.feature.root.host.RootNavigationOwner + +abstract class BaseMyAccountFragment : BaseFragment() { + protected fun findRootNavigationOwner(): RootNavigationOwner? { + var parentFragment = parentFragment + while (parentFragment != null) { + if (parentFragment is RootNavigationOwner) return parentFragment + parentFragment = parentFragment.parentFragment + } + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/model/MyAccountDeleteMenuModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/model/MyAccountDeleteMenuModel.kt new file mode 100644 index 00000000..5db35e69 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/accountmanagement/model/MyAccountDeleteMenuModel.kt @@ -0,0 +1,11 @@ +package com.polzzak_android.presentation.feature.myPage.accountmanagement.model + +data class MyAccountDeleteMenuModel( + val isCheckedDeleteSocialAccountData: Boolean = false, + val isCheckedDeleteLink: Boolean = false, + val isCheckedDeletePoint: Boolean = false, + val isCheckedDeleteStampAndCoupon: Boolean = false +) { + fun isAllChecked() = + isCheckedDeleteLink && isCheckedDeletePoint && isCheckedDeleteSocialAccountData && isCheckedDeleteStampAndCoupon +} diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/kid/KidMyPageFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/kid/KidMyPageFragment.kt index ea7ea6cf..5a040346 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/kid/KidMyPageFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/kid/KidMyPageFragment.kt @@ -1,11 +1,16 @@ package com.polzzak_android.presentation.feature.myPage.kid +import android.os.Bundle +import androidx.navigation.fragment.findNavController import com.polzzak_android.R import com.polzzak_android.presentation.common.base.BaseFragment import com.polzzak_android.databinding.FragmentKidMyPageBinding import com.polzzak_android.presentation.component.toolbar.ToolbarData import com.polzzak_android.presentation.component.toolbar.ToolbarHelper import com.polzzak_android.presentation.component.toolbar.ToolbarIconInteraction +import com.polzzak_android.presentation.feature.myPage.accountmanagement.MyAccountManagementFragment.Companion.ARGUMENT_NICKNAME_KEY +import com.polzzak_android.presentation.feature.term.TermDetailFragment +import com.polzzak_android.presentation.feature.term.model.TermType class KidMyPageFragment : BaseFragment(), ToolbarIconInteraction { override val layoutResId: Int = R.layout.fragment_kid_my_page @@ -73,19 +78,32 @@ class KidMyPageFragment : BaseFragment(), ToolbarIconI } fun onClickNotice() { - // todo: 공지사항 클릭 + findNavController().navigate(R.id.action_kidMyPageFragment_to_myNoticeFragment) } fun onClickManageAccount() { - // todo: 계정관리 클릭 + //TODO 닉네임 추가 + val bundle = Bundle().apply { + putString(ARGUMENT_NICKNAME_KEY, "nickname") + } + findNavController().navigate( + R.id.action_kidMyPageFragment_to_myAccountManagementFragment, + bundle + ) } fun onClickUsingTerms() { - // todo: 이용약관 클릭 + val bundle = Bundle().apply { + putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.SERVICE) + } + findNavController().navigate(R.id.action_kidMyPageFragment_to_termDetailFragment, bundle) } fun onClickPrivacyPolicy() { - // todo: 개인정보처리방침 클릭 + val bundle = Bundle().apply { + putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.PRIVACY) + } + findNavController().navigate(R.id.action_kidMyPageFragment_to_termDetailFragment, bundle) } override fun onToolbarIconClicked() { diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeClickListener.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeClickListener.kt new file mode 100644 index 00000000..3a1abe52 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeClickListener.kt @@ -0,0 +1,7 @@ +package com.polzzak_android.presentation.feature.myPage.notice + +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticeModel + +interface MyNoticeClickListener { + fun onClickNotice(model: MyNoticeModel) +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeDetailFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeDetailFragment.kt new file mode 100644 index 00000000..98c8da2e --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeDetailFragment.kt @@ -0,0 +1,45 @@ +package com.polzzak_android.presentation.feature.myPage.notice + +import androidx.navigation.fragment.findNavController +import com.polzzak_android.R +import com.polzzak_android.databinding.FragmentMyNoticeDetailBinding +import com.polzzak_android.presentation.common.base.BaseFragment +import com.polzzak_android.presentation.common.util.getParcelableOrNull +import com.polzzak_android.presentation.component.toolbar.ToolbarData +import com.polzzak_android.presentation.component.toolbar.ToolbarHelper +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticeModel +import java.time.format.DateTimeFormatter + +class MyNoticeDetailFragment : BaseFragment() { + override val layoutResId: Int = R.layout.fragment_my_notice_detail + + override fun initView() { + super.initView() + initToolbar() + initContent() + } + + private fun initToolbar() { + ToolbarHelper( + data = ToolbarData( + popStack = findNavController(), + titleText = getString(R.string.common_notice) + ), + toolbar = binding.inToolbar + ).set() + } + + private fun initContent() { + val noticeModel = + arguments?.getParcelableOrNull(ARGUMENT_NOTICE_KEY, MyNoticeModel::class.java) ?: return + with(binding) { + tvTitle.text = noticeModel.title + tvDate.text = noticeModel.date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm")) + tvContent.text = noticeModel.content + } + } + + companion object { + const val ARGUMENT_NOTICE_KEY = "argument_notice_key" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeFragment.kt new file mode 100644 index 00000000..326d93a2 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeFragment.kt @@ -0,0 +1,100 @@ +package com.polzzak_android.presentation.feature.myPage.notice + +import android.os.Bundle +import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.polzzak_android.R +import com.polzzak_android.databinding.FragmentMyNoticeBinding +import com.polzzak_android.presentation.common.base.BaseFragment +import com.polzzak_android.presentation.common.item.FullLoadingItem +import com.polzzak_android.presentation.common.item.LoadMoreLoadingSpinnerItem +import com.polzzak_android.presentation.common.model.ModelState +import com.polzzak_android.presentation.common.util.BindableItem +import com.polzzak_android.presentation.common.util.BindableItemAdapter +import com.polzzak_android.presentation.common.util.toPx +import com.polzzak_android.presentation.component.toolbar.ToolbarData +import com.polzzak_android.presentation.component.toolbar.ToolbarHelper +import com.polzzak_android.presentation.feature.myPage.notice.item.MyNoticeEmptyItem +import com.polzzak_android.presentation.feature.myPage.notice.item.MyNoticeItem +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticeModel +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticesModel + +//TODO 바텀네비 invisible +class MyNoticeFragment : BaseFragment(), MyNoticeClickListener { + override val layoutResId: Int = R.layout.fragment_my_notice + + private val noticeViewModel by viewModels() + + override fun initView() { + super.initView() + initToolbar() + initRecyclerView() + } + + private fun initToolbar() { + with(binding) { + ToolbarHelper( + data = ToolbarData( + popStack = findNavController(), + titleText = getString(R.string.common_notice) + ), + toolbar = inToolbar + ).set() + } + } + + private fun initRecyclerView() { + val context = binding.root.context ?: return + with(binding.rvNotices) { + layoutManager = LinearLayoutManager(context) + adapter = BindableItemAdapter() + val marginPx = NOTICE_ITEM_MARGIN_DP.toPx(context) + addItemDecoration(MyNoticeItemDecoration(marginPx = marginPx)) + addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + if (!recyclerView.canScrollVertically(1) && noticeViewModel.noticesLiveData.value is ModelState.Success) noticeViewModel.requestMoreNotices() + } + }) + } + } + + override fun initObserver() { + super.initObserver() + noticeViewModel.noticesLiveData.observe(viewLifecycleOwner) { + val adapter = (binding.rvNotices.adapter as? BindableItemAdapter) ?: return@observe + val noticeItem = createNoticeItem(it.data ?: MyNoticesModel()) + val items = mutableListOf>() + when (it) { + is ModelState.Loading -> { + if (it.data?.notices.isNullOrEmpty()) items.add(FullLoadingItem()) + else items.addAll(noticeItem + LoadMoreLoadingSpinnerItem()) + } + + is ModelState.Success -> items.addAll(noticeItem) + is ModelState.Error -> { + //TODO error handling + } + } + adapter.updateItem(item = items) + } + } + + private fun createNoticeItem(model: MyNoticesModel) = model.notices.map { + MyNoticeItem(model = it, clickListener = this) + }.ifEmpty { listOf(MyNoticeEmptyItem()) } + + override fun onClickNotice(model: MyNoticeModel) { + val bundle = Bundle().apply { + putParcelable(MyNoticeDetailFragment.ARGUMENT_NOTICE_KEY, model) + } + findNavController().navigate(R.id.action_myNoticeFragment_to_myNoticeDetailFragment, bundle) + } + + companion object { + private const val NOTICE_ITEM_MARGIN_DP = 8 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeItemDecoration.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeItemDecoration.kt new file mode 100644 index 00000000..226c974e --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeItemDecoration.kt @@ -0,0 +1,25 @@ +package com.polzzak_android.presentation.feature.myPage.notice + +import android.graphics.Rect +import android.view.View +import androidx.annotation.Px +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.ItemDecoration +import com.polzzak_android.presentation.common.util.BindableItemAdapter +import com.polzzak_android.presentation.feature.myPage.notice.item.MyNoticeItem + +class MyNoticeItemDecoration(@Px private val marginPx: Int) : ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + val position = parent.getChildAdapterPosition(view) + val adapter = (parent.adapter as? BindableItemAdapter) ?: return + if (adapter.currentList.getOrNull(position) !is MyNoticeItem) return + outRect.top = marginPx + outRect.bottom = if (position == adapter.currentList.lastIndex) marginPx else 0 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeViewModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeViewModel.kt new file mode 100644 index 00000000..38de5fef --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/MyNoticeViewModel.kt @@ -0,0 +1,78 @@ +package com.polzzak_android.presentation.feature.myPage.notice + +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.common.util.toLocalDateTime +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticeModel +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticesModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import java.time.LocalDateTime + +//TODO api 연동 +class MyNoticeViewModel : ViewModel() { + private val _noticesLiveData = MutableLiveData>() + val noticesLiveData: LiveData> = _noticesLiveData + + private var requestNoticesJob: Job? = null + + init { + initNotices() + } + + private fun initNotices() { + requestNoticesJob?.cancel() + requestNoticesJob = viewModelScope.launch { + _noticesLiveData.value = ModelState.Loading(MyNoticesModel()) + requestNotices() + } + } + + fun requestMoreNotices() { + if (noticesLiveData.value?.data?.hasNextPage == false) return + if (requestNoticesJob?.isCompleted == false) return + requestNoticesJob = viewModelScope.launch { + _noticesLiveData.value = + ModelState.Loading(_noticesLiveData.value?.data ?: MyNoticesModel()) + requestNotices() + } + } + + private suspend fun requestNotices() { + val prevData = noticesLiveData.value?.data ?: MyNoticesModel() + delay(2000) + //TODO api 연동 + //on Success + val nextData = getMockNotices(nextId = prevData.nextId, pageSize = PAGE_SIZE) + val updatedData = nextData.copy(notices = prevData.notices + nextData.notices) + _noticesLiveData.value = ModelState.Success(updatedData) + } + + companion object { + private const val PAGE_SIZE = 10 + } +} + +private fun getMockNotices(nextId: Int?, pageSize: Int): MyNoticesModel { + val startIdx = nextId ?: 0 + val nextIdx = minOf(mockNotices.size, startIdx + pageSize) + val nId = mockNotices.getOrNull(nextIdx)?.id + return MyNoticesModel( + notices = mockNotices.subList(startIdx, nextIdx), + nextId = nId, + hasNextPage = (nId != null) + ) +} + +private val mockNotices = List(27) { + MyNoticeModel( + id = it, + title = "title$it".repeat((it % 12) + 1), + date = "2023-06-04T20:08:23.745393551".toLocalDateTime() ?: (LocalDateTime.now()), + content = "content\n\n\ncontent1\n\ncontent\ncontent".repeat(7) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeEmptyItem.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeEmptyItem.kt new file mode 100644 index 00000000..fd5e3f6e --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeEmptyItem.kt @@ -0,0 +1,17 @@ +package com.polzzak_android.presentation.feature.myPage.notice.item + +import com.polzzak_android.R +import com.polzzak_android.databinding.ItemMyNoticieEmptyBinding +import com.polzzak_android.presentation.common.util.BindableItem + +class MyNoticeEmptyItem : BindableItem() { + override val layoutRes: Int = R.layout.item_my_noticie_empty + override fun areItemsTheSame(other: BindableItem<*>): Boolean = other is MyNoticeEmptyItem + + override fun areContentsTheSame(other: BindableItem<*>): Boolean = other is MyNoticeEmptyItem + + override fun bind(binding: ItemMyNoticieEmptyBinding, position: Int) { + //do nothing + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeItem.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeItem.kt new file mode 100644 index 00000000..de6528ad --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/item/MyNoticeItem.kt @@ -0,0 +1,31 @@ +package com.polzzak_android.presentation.feature.myPage.notice.item + +import com.polzzak_android.R +import com.polzzak_android.databinding.ItemMyNoticeBinding +import com.polzzak_android.presentation.common.util.BindableItem +import com.polzzak_android.presentation.common.util.toPublishedDateString +import com.polzzak_android.presentation.feature.myPage.notice.MyNoticeClickListener +import com.polzzak_android.presentation.feature.myPage.notice.model.MyNoticeModel + +class MyNoticeItem( + private val model: MyNoticeModel, + private val clickListener: MyNoticeClickListener +) : BindableItem() { + override val layoutRes: Int = R.layout.item_my_notice + override fun areItemsTheSame(other: BindableItem<*>): Boolean = + other is MyNoticeItem && this.model.id == other.model.id + + override fun areContentsTheSame(other: BindableItem<*>): Boolean = + other is MyNoticeItem && this.model == other.model + + override fun bind(binding: ItemMyNoticeBinding, position: Int) { + with(binding) { + root.setOnClickListener { + clickListener.onClickNotice(model = model) + } + tvTitle.text = model.title + tvDate.text = model.date.toLocalDate().toPublishedDateString() + tvContent.text = model.content.replace(Regex("(\\r\\n|\\r|\\n)+"), " ") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticeModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticeModel.kt new file mode 100644 index 00000000..0f630ccc --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticeModel.kt @@ -0,0 +1,13 @@ +package com.polzzak_android.presentation.feature.myPage.notice.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import java.time.LocalDateTime + +@Parcelize +data class MyNoticeModel( + val id: Int, + val title: String, + val date: LocalDateTime, + val content: String +) : Parcelable diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticesModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticesModel.kt new file mode 100644 index 00000000..e3e176fc --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/notice/model/MyNoticesModel.kt @@ -0,0 +1,7 @@ +package com.polzzak_android.presentation.feature.myPage.notice.model + +data class MyNoticesModel( + val notices: List = emptyList(), + val nextId: Int? = null, + val hasNextPage: Boolean = true +) \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/protector/ProtectorMyPageFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/protector/ProtectorMyPageFragment.kt index a5ecdd4d..74e77984 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/myPage/protector/ProtectorMyPageFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/myPage/protector/ProtectorMyPageFragment.kt @@ -1,5 +1,6 @@ package com.polzzak_android.presentation.feature.myPage.protector +import android.os.Bundle import androidx.navigation.fragment.findNavController import com.polzzak_android.R import com.polzzak_android.databinding.FragmentProtectorMyPageBinding @@ -7,6 +8,9 @@ import com.polzzak_android.presentation.common.base.BaseFragment import com.polzzak_android.presentation.component.toolbar.ToolbarData import com.polzzak_android.presentation.component.toolbar.ToolbarHelper import com.polzzak_android.presentation.component.toolbar.ToolbarIconInteraction +import com.polzzak_android.presentation.feature.myPage.accountmanagement.MyAccountManagementFragment +import com.polzzak_android.presentation.feature.term.TermDetailFragment +import com.polzzak_android.presentation.feature.term.model.TermType class ProtectorMyPageFragment : BaseFragment(), ToolbarIconInteraction { @@ -33,7 +37,7 @@ class ProtectorMyPageFragment : BaseFragment(), setUpPointView() } - private fun setUpPointView(){ + private fun setUpPointView() { with(binding.pointRanking) { text = "폴짝 랭킹" icon.setImageResource(R.drawable.ic_point_rank) @@ -75,19 +79,39 @@ class ProtectorMyPageFragment : BaseFragment(), } fun onClickNotice() { - // todo: 공지사항 클릭 + findNavController().navigate(R.id.action_protectorMyPageFragment_to_myNoticeFragment) + } fun onClickManageAccount() { - // todo: 계정관리 클릭 + //TODO 닉네임 추가 + val bundle = Bundle().apply { + putString(MyAccountManagementFragment.ARGUMENT_NICKNAME_KEY, "nickname") + } + findNavController().navigate( + R.id.action_protectorMyPageFragment_to_myAccountManagementFragment, + bundle + ) } fun onClickUsingTerms() { - // todo: 이용약관 클릭 + val bundle = Bundle().apply { + putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.SERVICE) + } + findNavController().navigate( + R.id.action_protectorMyPageFragment_to_termDetailFragment, + bundle + ) } fun onClickPrivacyPolicy() { - // todo: 개인정보처리방침 클릭 + val bundle = Bundle().apply { + putParcelable(TermDetailFragment.ARGUMENT_TYPE_KEY, TermType.PRIVACY) + } + findNavController().navigate( + R.id.action_protectorMyPageFragment_to_termDetailFragment, + bundle + ) } override fun onToolbarIconClicked() { diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/root/MainViewModel.kt b/app/src/main/java/com/polzzak_android/presentation/feature/root/MainViewModel.kt index bc4221c8..65a936cb 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/root/MainViewModel.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/root/MainViewModel.kt @@ -4,4 +4,8 @@ import androidx.lifecycle.ViewModel class MainViewModel : ViewModel() { var accessToken: String? = null + + fun logout() { + accessToken = null + } } \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/root/host/KidHostFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/KidHostFragment.kt index 213705ef..e7a6d425 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/root/host/KidHostFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/KidHostFragment.kt @@ -4,6 +4,7 @@ import androidx.activity.OnBackPressedCallback import androidx.navigation.NavController import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.fragment.findNavController import androidx.navigation.ui.NavigationUI import com.polzzak_android.R import com.polzzak_android.presentation.common.base.BaseFragment @@ -11,7 +12,7 @@ import com.polzzak_android.databinding.FragmentKidHostBinding import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class KidHostFragment : BaseFragment() { +class KidHostFragment : BaseFragment(), RootNavigationOwner { override val layoutResId = R.layout.fragment_kid_host private lateinit var navController: NavController @@ -39,10 +40,15 @@ class KidHostFragment : BaseFragment() { destination.parent?.findStartDestination()?.id -> { backPressedCallback.isEnabled = false } + else -> { backPressedCallback.isEnabled = true } } } } + + override fun backToTheLoginFragment() { + findNavController().popBackStack(R.id.loginFragment, false) + } } \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/root/host/ProtectorHostFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/ProtectorHostFragment.kt index 37e8d812..d01beb5a 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/root/host/ProtectorHostFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/ProtectorHostFragment.kt @@ -3,12 +3,14 @@ package com.polzzak_android.presentation.feature.root.host import androidx.activity.OnBackPressedCallback import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.fragment.findNavController import androidx.navigation.ui.setupWithNavController import com.polzzak_android.R import com.polzzak_android.databinding.FragmentProtectorHostBinding import com.polzzak_android.presentation.common.base.BaseFragment -class ProtectorHostFragment() : BaseFragment() { +class ProtectorHostFragment() : BaseFragment(), + RootNavigationOwner { override val layoutResId = R.layout.fragment_protector_host private lateinit var protectorNavController: NavController @@ -34,4 +36,7 @@ class ProtectorHostFragment() : BaseFragment() { } } + override fun backToTheLoginFragment() { + findNavController().popBackStack(R.id.loginFragment, false) + } } \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/root/host/RootNavigationOwner.kt b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/RootNavigationOwner.kt new file mode 100644 index 00000000..03a853e4 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/root/host/RootNavigationOwner.kt @@ -0,0 +1,5 @@ +package com.polzzak_android.presentation.feature.root.host + +interface RootNavigationOwner { + fun backToTheLoginFragment() +} \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpTermDetailFragment.kt b/app/src/main/java/com/polzzak_android/presentation/feature/term/TermDetailFragment.kt similarity index 61% rename from app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpTermDetailFragment.kt rename to app/src/main/java/com/polzzak_android/presentation/feature/term/TermDetailFragment.kt index 567cda6b..07635855 100644 --- a/app/src/main/java/com/polzzak_android/presentation/feature/auth/signup/SignUpTermDetailFragment.kt +++ b/app/src/main/java/com/polzzak_android/presentation/feature/term/TermDetailFragment.kt @@ -1,15 +1,21 @@ -package com.polzzak_android.presentation.feature.auth.signup +package com.polzzak_android.presentation.feature.term import android.webkit.WebViewClient import androidx.navigation.fragment.findNavController import com.polzzak_android.R -import com.polzzak_android.databinding.FragmentSignupTermDetailBinding +import com.polzzak_android.databinding.FragmentTermDetailBinding import com.polzzak_android.presentation.common.base.BaseFragment +import com.polzzak_android.presentation.common.util.getParcelableOrNull import com.polzzak_android.presentation.component.toolbar.ToolbarData import com.polzzak_android.presentation.component.toolbar.ToolbarHelper +import com.polzzak_android.presentation.feature.term.model.TermType -class SignUpTermDetailFragment : BaseFragment() { - override val layoutResId: Int = R.layout.fragment_signup_term_detail +class TermDetailFragment : BaseFragment() { + override val layoutResId: Int = R.layout.fragment_term_detail + + private val type by lazy { + arguments?.getParcelableOrNull(ARGUMENT_TYPE_KEY, TermType::class.java) + } override fun initView() { super.initView() @@ -19,7 +25,7 @@ class SignUpTermDetailFragment : BaseFragment() private fun initToolbar() { with(binding.inToolbar) { - val title = arguments?.getString(ARGUMENT_TITLE_KEY) ?: "" + val title = type?.let { getString(it.titleStrRes) } ?: "" val toolbarData = ToolbarData(popStack = findNavController(), titleText = title) ToolbarHelper(data = toolbarData, toolbar = this).run { @@ -31,7 +37,7 @@ class SignUpTermDetailFragment : BaseFragment() private fun initWebView() { with(binding.wbContent) { - val url = arguments?.getString(ARGUMENT_URL_KEY) ?: "" + val url = type?.url ?: "" webViewClient = WebViewClient() settings.loadWithOverviewMode = true settings.useWideViewPort = true @@ -40,7 +46,6 @@ class SignUpTermDetailFragment : BaseFragment() } companion object { - const val ARGUMENT_TITLE_KEY = "argument_title_key" - const val ARGUMENT_URL_KEY = "argument_url_key" + const val ARGUMENT_TYPE_KEY = "argument_type_key" } } \ No newline at end of file diff --git a/app/src/main/java/com/polzzak_android/presentation/feature/term/model/TermType.kt b/app/src/main/java/com/polzzak_android/presentation/feature/term/model/TermType.kt new file mode 100644 index 00000000..901a6fa3 --- /dev/null +++ b/app/src/main/java/com/polzzak_android/presentation/feature/term/model/TermType.kt @@ -0,0 +1,13 @@ +package com.polzzak_android.presentation.feature.term.model + +import android.os.Parcelable +import androidx.annotation.StringRes +import com.polzzak_android.R +import kotlinx.parcelize.Parcelize + +//TODO 웹뷰 주소 +@Parcelize +enum class TermType(@StringRes val titleStrRes: Int, val url: String) : Parcelable { + SERVICE(R.string.terms_of_service_detail_service_title, "http://google.co.kr"), + PRIVACY(R.string.terms_of_service_detail_privacy_title, "http://naver.com"), +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_signup_terms_of_service_checked.xml b/app/src/main/res/drawable/ic_checked.xml similarity index 100% rename from app/src/main/res/drawable/ic_signup_terms_of_service_checked.xml rename to app/src/main/res/drawable/ic_checked.xml diff --git a/app/src/main/res/drawable/ic_signup_terms_of_service_unchecked.xml b/app/src/main/res/drawable/ic_unchecked.xml similarity index 100% rename from app/src/main/res/drawable/ic_signup_terms_of_service_unchecked.xml rename to app/src/main/res/drawable/ic_unchecked.xml diff --git a/app/src/main/res/drawable/selector_menu_checked.xml b/app/src/main/res/drawable/selector_menu_checked.xml new file mode 100644 index 00000000..a8e3d659 --- /dev/null +++ b/app/src/main/res/drawable/selector_menu_checked.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_rectangle_r8_enabled_primary_gray_300.xml b/app/src/main/res/drawable/selector_rectangle_r8_enabled_primary_gray_300.xml new file mode 100644 index 00000000..ac4a47fa --- /dev/null +++ b/app/src/main/res/drawable/selector_rectangle_r8_enabled_primary_gray_300.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_signup_terms_of_service_check.xml b/app/src/main/res/drawable/selector_signup_terms_of_service_check.xml deleted file mode 100644 index 7e81f529..00000000 --- a/app/src/main/res/drawable/selector_signup_terms_of_service_check.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_account_delete.xml b/app/src/main/res/layout/fragment_my_account_delete.xml new file mode 100644 index 00000000..30434b5f --- /dev/null +++ b/app/src/main/res/layout/fragment_my_account_delete.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_account_management.xml b/app/src/main/res/layout/fragment_my_account_management.xml new file mode 100644 index 00000000..8453fd1a --- /dev/null +++ b/app/src/main/res/layout/fragment_my_account_management.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_notice.xml b/app/src/main/res/layout/fragment_my_notice.xml new file mode 100644 index 00000000..4c5bab7c --- /dev/null +++ b/app/src/main/res/layout/fragment_my_notice.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_notice_detail.xml b/app/src/main/res/layout/fragment_my_notice_detail.xml new file mode 100644 index 00000000..8a0088a3 --- /dev/null +++ b/app/src/main/res/layout/fragment_my_notice_detail.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_signup_term_detail.xml b/app/src/main/res/layout/fragment_term_detail.xml similarity index 100% rename from app/src/main/res/layout/fragment_signup_term_detail.xml rename to app/src/main/res/layout/fragment_term_detail.xml diff --git a/app/src/main/res/layout/item_full_loading.xml b/app/src/main/res/layout/item_full_loading.xml new file mode 100644 index 00000000..88b46c62 --- /dev/null +++ b/app/src/main/res/layout/item_full_loading.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_my_account_management_delete_menu.xml b/app/src/main/res/layout/item_my_account_management_delete_menu.xml new file mode 100644 index 00000000..9ef73f11 --- /dev/null +++ b/app/src/main/res/layout/item_my_account_management_delete_menu.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_my_notice.xml b/app/src/main/res/layout/item_my_notice.xml new file mode 100644 index 00000000..3da8a873 --- /dev/null +++ b/app/src/main/res/layout/item_my_notice.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_my_noticie_empty.xml b/app/src/main/res/layout/item_my_noticie_empty.xml new file mode 100644 index 00000000..383fa36e --- /dev/null +++ b/app/src/main/res/layout/item_my_noticie_empty.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_signup_terms_of_service.xml b/app/src/main/res/layout/layout_signup_terms_of_service.xml index aa6c0487..3d497c00 100644 --- a/app/src/main/res/layout/layout_signup_terms_of_service.xml +++ b/app/src/main/res/layout/layout_signup_terms_of_service.xml @@ -41,13 +41,13 @@ android:drawablePadding="8dp" android:text="@string/signup_terms_of_service_agree_all" android:textColor="@color/selector_signup_terms_of_service_checklist" - app:drawableStartCompat="@drawable/selector_signup_terms_of_service_check" + app:drawableStartCompat="@drawable/selector_menu_checked" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:drawableStart="@drawable/selector_signup_terms_of_service_check" /> + tools:drawableStart="@drawable/selector_menu_checked" /> + tools:drawableStart="@drawable/selector_menu_checked" /> + tools:drawableStart="@drawable/selector_menu_checked" /> - + android:defaultValue="-1" + app:argType="integer" /> - - - + android:label="KidMyPageFragment"> + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/protector_nav_graph.xml b/app/src/main/res/navigation/protector_nav_graph.xml index 26788038..e963068d 100644 --- a/app/src/main/res/navigation/protector_nav_graph.xml +++ b/app/src/main/res/navigation/protector_nav_graph.xml @@ -76,12 +76,64 @@ android:name="com.polzzak_android.presentation.feature.myPage.protector.ProtectorMyPageFragment" android:label="ProtectorMyPageFragment" tools:layout="@layout/fragment_protector_my_page"> + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/root_nav_graph.xml b/app/src/main/res/navigation/root_nav_graph.xml index 45838340..7851e912 100644 --- a/app/src/main/res/navigation/root_nav_graph.xml +++ b/app/src/main/res/navigation/root_nav_graph.xml @@ -5,8 +5,6 @@ android:id="@+id/root_nav_graph" app:startDestination="@id/splashFragment"> - - - - - + android:id="@+id/action_signUpFragment_to_termDetailFragment" + app:destination="@id/termDetailFragment" /> + android:id="@+id/termDetailFragment" + android:name="com.polzzak_android.presentation.feature.term.TermDetailFragment" + android:label="termDetailFragment" + tools:layout="@layout/fragment_term_detail" /> 수락 거절 알림 + 공지사항 참 잘 했어요 도장 쾅! @@ -58,8 +59,6 @@ 모두 동의 서비스 이용약관에 동의합니다. 개인정보처리방침에 동의합니다. - 이용약관 - 개인정보처리방침 폴짝!\n회원이 되신 것을 환영해요 @@ -167,4 +166,26 @@ 취소 앱 설정에서 ‘저장소’ 권한을 허용해 주세요 앱 설정에서 알림 권한을 허용해주세요 + + + 업데이트된 소식이 없어요 + 계정관리 + 로그아웃 + 회원탈퇴 + 정말로 로그아웃 하시겠어요? + 로그아웃 할래요 + %s 회원님\n폴짝을 떠나시나요? + 다음 안내사항을 확인하고 동의해주세요 + 가입한 소셜 계정 정보가 삭제돼요. + 연동 목록이 모두 삭제돼요. + 도장판과 쿠폰들이 모두 사라져요. + 열심히 모은 포인트가 모두 사라져요. + 탈퇴하기 + 정말로 탈퇴하시겠어요? + 아니요 + 네,탈퇴할래요 + + + 이용약관 + 개인정보처리방침 \ No newline at end of file