From 116d4b3ecfd4db89bb6d2c7559455d88e80c8d9a Mon Sep 17 00:00:00 2001 From: klaus Date: Tue, 20 May 2025 00:29:00 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20UI=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 5 +- .../java/kr/co/vividnext/sodalive/di/AppDI.kt | 6 + .../sodalive/mypage/MyPageFragment.kt | 10 ++ .../mypage/point/GetPointStatusResponse.kt | 7 + .../mypage/point/PointStatusActivity.kt | 118 +++++++++++++++++ .../sodalive/mypage/point/PointStatusApi.kt | 28 ++++ .../mypage/point/PointStatusRepository.kt | 17 +++ .../mypage/point/PointStatusViewModel.kt | 123 ++++++++++++++++++ .../reward/GetPointRewardStatusResponse.kt | 11 ++ .../point/reward/PointRewardStatusAdapter.kt | 36 +++++ .../point/reward/PointRewardStatusFragment.kt | 79 +++++++++++ .../point/use/GetPointUseStatusResponse.kt | 11 ++ .../mypage/point/use/PointUseStatusAdapter.kt | 36 +++++ .../point/use/PointUseStatusFragment.kt | 79 +++++++++++ .../main/res/layout/activity_point_status.xml | 63 +++++++++ app/src/main/res/layout/fragment_my.xml | 7 + .../main/res/layout/item_point_use_status.xml | 50 +++++++ 17 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/GetPointStatusResponse.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusActivity.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusApi.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusRepository.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusViewModel.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/GetPointRewardStatusResponse.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusAdapter.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusFragment.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/GetPointUseStatusResponse.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusAdapter.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusFragment.kt create mode 100644 app/src/main/res/layout/activity_point_status.xml create mode 100644 app/src/main/res/layout/item_point_use_status.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index daad0b6c..ff31ef7f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -104,6 +104,7 @@ + @@ -203,11 +204,13 @@ android:exported="true"> + - diff --git a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt index 65f728b4..42c6f294 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt @@ -126,6 +126,9 @@ import kr.co.vividnext.sodalive.mypage.can.payment.CanPaymentTempViewModel import kr.co.vividnext.sodalive.mypage.can.payment.CanPaymentViewModel import kr.co.vividnext.sodalive.mypage.can.payment.CanTempApi import kr.co.vividnext.sodalive.mypage.can.status.CanStatusViewModel +import kr.co.vividnext.sodalive.mypage.point.PointStatusApi +import kr.co.vividnext.sodalive.mypage.point.PointStatusRepository +import kr.co.vividnext.sodalive.mypage.point.PointStatusViewModel import kr.co.vividnext.sodalive.mypage.profile.ProfileUpdateViewModel import kr.co.vividnext.sodalive.mypage.profile.nickname.NicknameUpdateViewModel import kr.co.vividnext.sodalive.mypage.profile.tag.MemberTagApi @@ -236,6 +239,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { single { ApiBuilder().build(get(), AuditionApi::class.java) } single { ApiBuilder().build(get(), AdTrackingApi::class.java) } single { ApiBuilder().build(get(), SearchApi::class.java) } + single { ApiBuilder().build(get(), PointStatusApi::class.java) } } private val viewModelModule = module { @@ -331,6 +335,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { viewModel { CompletedSeriesViewModel(get()) } viewModel { AlarmContentAllViewModel(get()) } viewModel { SearchViewModel(get()) } + viewModel { PointStatusViewModel(get()) } } private val repositoryModule = module { @@ -373,6 +378,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { factory { AdTrackingRepository(get()) } factory { SearchRepository(get()) } factory { UserEventRepository(get()) } + factory { PointStatusRepository(get()) } } private val moduleList = listOf( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt index de9c52db..47fc5876 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt @@ -32,6 +32,7 @@ import kr.co.vividnext.sodalive.mypage.block.BlockMemberActivity import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity import kr.co.vividnext.sodalive.mypage.can.coupon.CanCouponActivity import kr.co.vividnext.sodalive.mypage.can.status.CanStatusActivity +import kr.co.vividnext.sodalive.mypage.point.PointStatusActivity import kr.co.vividnext.sodalive.mypage.profile.ProfileUpdateActivity import kr.co.vividnext.sodalive.mypage.service_center.ServiceCenterActivity import kr.co.vividnext.sodalive.settings.SettingsActivity @@ -127,6 +128,15 @@ class MyPageFragment : BaseFragment(FragmentMyBinding::inflat ) } + binding.llTotalPoint.setOnClickListener { + startActivity( + Intent( + requireActivity(), + PointStatusActivity::class.java + ) + ) + } + binding.tvChargeCan.setOnClickListener { startActivity( Intent( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/GetPointStatusResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/GetPointStatusResponse.kt new file mode 100644 index 00000000..a44fc443 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/GetPointStatusResponse.kt @@ -0,0 +1,7 @@ +package kr.co.vividnext.sodalive.mypage.point + +import androidx.annotation.Keep +import com.google.gson.annotations.SerializedName + +@Keep +data class GetPointStatusResponse(@SerializedName("point") val point: Int) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusActivity.kt new file mode 100644 index 00000000..3097f2c6 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusActivity.kt @@ -0,0 +1,118 @@ +package kr.co.vividnext.sodalive.mypage.point + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import android.widget.Toast +import androidx.activity.OnBackPressedCallback +import com.google.android.material.tabs.TabLayout +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.base.BaseActivity +import kr.co.vividnext.sodalive.common.LoadingDialog +import kr.co.vividnext.sodalive.databinding.ActivityPointStatusBinding +import kr.co.vividnext.sodalive.extensions.moneyFormat +import kr.co.vividnext.sodalive.main.MainActivity +import kr.co.vividnext.sodalive.mypage.point.reward.PointRewardStatusFragment +import kr.co.vividnext.sodalive.mypage.point.use.PointUseStatusFragment +import org.koin.android.ext.android.inject + +class PointStatusActivity : BaseActivity( + ActivityPointStatusBinding::inflate +) { + private val viewModel: PointStatusViewModel by inject() + private val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + onClickBackButton() + } + } + + private lateinit var loadingDialog: LoadingDialog + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(this, onBackPressedCallback) + + bindData() + viewModel.getPointStatus() + } + + override fun setupView() { + binding.toolbar.tvBack.text = "포인트 내역" + binding.toolbar.tvBack.setOnClickListener { onClickBackButton() } + + loadingDialog = LoadingDialog(this, layoutInflater) + + val tabs = binding.tabs + tabs.addTab(tabs.newTab().setText("받은내역").setTag("reward_status")) + tabs.addTab(tabs.newTab().setText("사용내역").setTag("use_status")) + + changeFragment("reward_status") + + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + val tag = tab.tag as String + changeFragment(tag) + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + }) + } + + private fun changeFragment(tag: String) { + val fragmentManager = supportFragmentManager + val fragmentTransaction = fragmentManager.beginTransaction() + + val currentFragment = fragmentManager.primaryNavigationFragment + if (currentFragment != null) { + fragmentTransaction.hide(currentFragment) + } + + var fragment = fragmentManager.findFragmentByTag(tag) + if (fragment == null) { + fragment = if (tag == "reward_status") { + PointRewardStatusFragment(viewModel) + } else { + PointUseStatusFragment(viewModel) + } + + fragmentTransaction.add(R.id.container, fragment, tag) + } else { + fragmentTransaction.show(fragment) + } + + fragmentTransaction.setPrimaryNavigationFragment(fragment) + fragmentTransaction.setReorderingAllowed(true) + fragmentTransaction.commitNow() + } + + @SuppressLint("SetTextI18n") + private fun bindData() { + viewModel.totalPointLiveData.observe(this) { + binding.tvTotalPoint.text = it.moneyFormat() + } + + viewModel.toastLiveData.observe(this) { + it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() } + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth) + } else { + loadingDialog.dismiss() + } + } + } + + private fun onClickBackButton() { + val intent = Intent(applicationContext, MainActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) + startActivity(intent) + finish() + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusApi.kt new file mode 100644 index 00000000..fccdf750 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusApi.kt @@ -0,0 +1,28 @@ +package kr.co.vividnext.sodalive.mypage.point + +import io.reactivex.rxjava3.core.Single +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.mypage.point.reward.GetPointRewardStatusResponse +import kr.co.vividnext.sodalive.mypage.point.use.GetPointUseStatusResponse +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.Query + +interface PointStatusApi { + @GET("/point/status") + fun getPointStatus( + @Header("Authorization") authHeader: String + ): Single> + + @GET("/point/status/reward") + fun getPointRewardStatus( + @Query("timezone") timezone: String, + @Header("Authorization") authHeader: String + ): Single>> + + @GET("/point/status/use") + fun getPointUseStatus( + @Query("timezone") timezone: String, + @Header("Authorization") authHeader: String + ): Single>> +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusRepository.kt new file mode 100644 index 00000000..cf0c468e --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusRepository.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.mypage.point + +import java.util.TimeZone + +class PointStatusRepository(private val api: PointStatusApi) { + fun getPointStatus(token: String) = api.getPointStatus(authHeader = token) + + fun getPointRewardStatus(token: String) = api.getPointRewardStatus( + timezone = TimeZone.getDefault().id, + authHeader = token + ) + + fun getPointUseStatus(token: String) = api.getPointUseStatus( + timezone = TimeZone.getDefault().id, + authHeader = token + ) +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusViewModel.kt new file mode 100644 index 00000000..adb5e85e --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/PointStatusViewModel.kt @@ -0,0 +1,123 @@ +package kr.co.vividnext.sodalive.mypage.point + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.orhanobut.logger.Logger +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers +import kr.co.vividnext.sodalive.base.BaseViewModel +import kr.co.vividnext.sodalive.common.SharedPreferenceManager +import kr.co.vividnext.sodalive.mypage.point.reward.GetPointRewardStatusResponse +import kr.co.vividnext.sodalive.mypage.point.use.GetPointUseStatusResponse + +class PointStatusViewModel(private val repository: PointStatusRepository) : BaseViewModel() { + private val _totalPointLiveData = MutableLiveData() + val totalPointLiveData: LiveData + get() = _totalPointLiveData + + private val _pointUseStatusLiveData = MutableLiveData>() + val pointUseStatusLiveData: LiveData> + get() = _pointUseStatusLiveData + + private val _pointRewardStatusLiveData = MutableLiveData>() + val pointRewardStatusLiveData: LiveData> + get() = _pointRewardStatusLiveData + + private val _toastLiveData = MutableLiveData() + val toastLiveData: LiveData + get() = _toastLiveData + + private var _isLoading = MutableLiveData(false) + val isLoading: LiveData + get() = _isLoading + + fun getPointStatus() { + _isLoading.value = true + compositeDisposable.add( + repository.getPointStatus("Bearer ${SharedPreferenceManager.token}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null) { + _totalPointLiveData.value = it.data.point + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + + fun getPointRewardStatus() { + _isLoading.value = true + compositeDisposable.add( + repository.getPointRewardStatus(("Bearer ${SharedPreferenceManager.token}")) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null) { + _pointRewardStatusLiveData.value = it.data + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + + fun getPointUseStatus() { + _isLoading.value = true + compositeDisposable.add( + repository.getPointUseStatus(("Bearer ${SharedPreferenceManager.token}")) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null) { + _pointUseStatusLiveData.value = it.data + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/GetPointRewardStatusResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/GetPointRewardStatusResponse.kt new file mode 100644 index 00000000..ee3cba06 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/GetPointRewardStatusResponse.kt @@ -0,0 +1,11 @@ +package kr.co.vividnext.sodalive.mypage.point.reward + +import androidx.annotation.Keep +import com.google.gson.annotations.SerializedName + +@Keep +data class GetPointRewardStatusResponse( + @SerializedName("rewardPoint") val rewardPoint: String, + @SerializedName("date") val date: String, + @SerializedName("method") val method: String +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusAdapter.kt new file mode 100644 index 00000000..8678d34c --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusAdapter.kt @@ -0,0 +1,36 @@ +package kr.co.vividnext.sodalive.mypage.point.reward + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.databinding.ItemCanChargeStatusBinding + +class PointRewardStatusAdapter : RecyclerView.Adapter() { + val items = mutableListOf() + + inner class ViewHolder( + private val binding: ItemCanChargeStatusBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: GetPointRewardStatusResponse) { + binding.tvTitle.text = item.rewardPoint + binding.tvDate.text = item.date + binding.tvChargeMethod.text = item.method + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemCanChargeStatusBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position]) + } + + override fun getItemCount() = items.count() +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusFragment.kt new file mode 100644 index 00000000..83f2bac0 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/reward/PointRewardStatusFragment.kt @@ -0,0 +1,79 @@ +package kr.co.vividnext.sodalive.mypage.point.reward + +import android.annotation.SuppressLint +import android.graphics.Rect +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.base.BaseFragment +import kr.co.vividnext.sodalive.databinding.FragmentCanStatusBinding +import kr.co.vividnext.sodalive.extensions.dpToPx +import kr.co.vividnext.sodalive.mypage.point.PointStatusViewModel + +class PointRewardStatusFragment( + private val viewModel: PointStatusViewModel +) : BaseFragment( + FragmentCanStatusBinding::inflate +) { + + private lateinit var adapter: PointRewardStatusAdapter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupView() + bindData() + viewModel.getPointRewardStatus() + } + + @SuppressLint("NotifyDataSetChanged") + private fun setupView() { + val recyclerView = binding.rvCanStatus + adapter = PointRewardStatusAdapter() + + recyclerView.layoutManager = LinearLayoutManager( + requireContext(), + LinearLayoutManager.VERTICAL, + false + ) + + recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + + when (parent.getChildAdapterPosition(view)) { + 0 -> { + outRect.top = 13.3f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + + adapter.itemCount - 1 -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 13.3f.dpToPx().toInt() + } + + else -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + } + } + }) + + recyclerView.adapter = adapter + } + + @SuppressLint("NotifyDataSetChanged") + private fun bindData() { + viewModel.pointRewardStatusLiveData.observe(viewLifecycleOwner) { + adapter.items.addAll(it) + adapter.notifyDataSetChanged() + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/GetPointUseStatusResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/GetPointUseStatusResponse.kt new file mode 100644 index 00000000..7f14adcf --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/GetPointUseStatusResponse.kt @@ -0,0 +1,11 @@ +package kr.co.vividnext.sodalive.mypage.point.use + +import androidx.annotation.Keep +import com.google.gson.annotations.SerializedName + +@Keep +data class GetPointUseStatusResponse( + @SerializedName("title") val title: String, + @SerializedName("date") val date: String, + @SerializedName("point") val point: Int +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusAdapter.kt new file mode 100644 index 00000000..e8c59954 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusAdapter.kt @@ -0,0 +1,36 @@ +package kr.co.vividnext.sodalive.mypage.point.use + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.databinding.ItemPointUseStatusBinding + +class PointUseStatusAdapter : RecyclerView.Adapter() { + val items = mutableListOf() + + inner class ViewHolder( + private val binding: ItemPointUseStatusBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: GetPointUseStatusResponse) { + binding.tvTitle.text = item.title + binding.tvDate.text = item.date + binding.tvPoint.text = "${item.point}" + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemPointUseStatusBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position]) + } + + override fun getItemCount() = items.count() +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusFragment.kt new file mode 100644 index 00000000..ae508356 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/point/use/PointUseStatusFragment.kt @@ -0,0 +1,79 @@ +package kr.co.vividnext.sodalive.mypage.point.use + +import android.annotation.SuppressLint +import android.graphics.Rect +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.base.BaseFragment +import kr.co.vividnext.sodalive.databinding.FragmentCanStatusBinding +import kr.co.vividnext.sodalive.extensions.dpToPx +import kr.co.vividnext.sodalive.mypage.point.PointStatusViewModel + +class PointUseStatusFragment( + private val viewModel: PointStatusViewModel +) : BaseFragment( + FragmentCanStatusBinding::inflate +) { + + private lateinit var adapter: PointUseStatusAdapter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupView() + bindData() + viewModel.getPointUseStatus() + } + + @SuppressLint("NotifyDataSetChanged") + private fun setupView() { + val recyclerView = binding.rvCanStatus + adapter = PointUseStatusAdapter() + + recyclerView.layoutManager = LinearLayoutManager( + requireContext(), + LinearLayoutManager.VERTICAL, + false + ) + + recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + + when (parent.getChildAdapterPosition(view)) { + 0 -> { + outRect.top = 13.3f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + + adapter.itemCount - 1 -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 13.3f.dpToPx().toInt() + } + + else -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + } + } + }) + + recyclerView.adapter = adapter + } + + @SuppressLint("NotifyDataSetChanged") + private fun bindData() { + viewModel.pointUseStatusLiveData.observe(viewLifecycleOwner) { + adapter.items.addAll(it) + adapter.notifyDataSetChanged() + } + } +} diff --git a/app/src/main/res/layout/activity_point_status.xml b/app/src/main/res/layout/activity_point_status.xml new file mode 100644 index 00000000..1b23ed8e --- /dev/null +++ b/app/src/main/res/layout/activity_point_status.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_my.xml b/app/src/main/res/layout/fragment_my.xml index 74562287..748e9d70 100644 --- a/app/src/main/res/layout/fragment_my.xml +++ b/app/src/main/res/layout/fragment_my.xml @@ -319,6 +319,13 @@ android:contentDescription="@null" android:gravity="center" android:src="@drawable/ic_point" /> + + diff --git a/app/src/main/res/layout/item_point_use_status.xml b/app/src/main/res/layout/item_point_use_status.xml new file mode 100644 index 00000000..ca29dd87 --- /dev/null +++ b/app/src/main/res/layout/item_point_use_status.xml @@ -0,0 +1,50 @@ + + + + + + + + + +