후원 랭킹 기간 선택 추가

프로필 후원 랭킹 조회와 프로필 갱신 요청에 기간 값을 전달한다.
This commit is contained in:
2026-02-03 19:09:55 +09:00
parent 84803c171c
commit 21c87f95ef
11 changed files with 242 additions and 6 deletions

View File

@@ -48,6 +48,7 @@ interface ExplorerApi {
@Path("id") id: Long, @Path("id") id: Long,
@Query("page") page: Int, @Query("page") page: Int,
@Query("size") size: Int, @Query("size") size: Int,
@Query("period") period: String?,
@Header("Authorization") authHeader: String @Header("Authorization") authHeader: String
): Single<ApiResponse<GetDonationAllResponse>> ): Single<ApiResponse<GetDonationAllResponse>>

View File

@@ -80,12 +80,14 @@ class ExplorerRepository(
id: Long, id: Long,
page: Int, page: Int,
size: Int, size: Int,
donationRankingPeriod: String?,
token: String token: String
): Single<ApiResponse<GetDonationAllResponse>> { ): Single<ApiResponse<GetDonationAllResponse>> {
return api.getCreatorProfileDonationRanking( return api.getCreatorProfileDonationRanking(
id = id, id = id,
page = page - 1, page = page - 1,
size = size, size = size,
period = donationRankingPeriod,
authHeader = token authHeader = token
) )
} }

View File

@@ -0,0 +1,12 @@
package kr.co.vividnext.sodalive.explorer.profile.donation
import androidx.annotation.Keep
import com.google.gson.annotations.SerializedName
@Keep
enum class DonationRankingPeriod {
@SerializedName("WEEKLY")
WEEKLY,
@SerializedName("CUMULATIVE")
CUMULATIVE
}

View File

@@ -16,6 +16,8 @@ data class GetDonationAllResponse(
val isVisibleDonationRank: Boolean, val isVisibleDonationRank: Boolean,
@SerializedName("totalCount") @SerializedName("totalCount")
val totalCount: Int, val totalCount: Int,
@SerializedName("donationRankingPeriod")
val donationRankingPeriod: DonationRankingPeriod? = null,
@SerializedName("userDonationRanking") @SerializedName("userDonationRanking")
val userDonationRanking: List<UserDonationRankingResponse>, val userDonationRanking: List<UserDonationRankingResponse>,
) )

View File

@@ -7,6 +7,7 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.tabs.TabLayout
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseActivity import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.Constants import kr.co.vividnext.sodalive.common.Constants
@@ -27,15 +28,19 @@ class UserProfileDonationAllViewActivity : BaseActivity<ActivityUserProfileLiveA
private lateinit var adapter: UserProfileDonationAllAdapter private lateinit var adapter: UserProfileDonationAllAdapter
private var userId: Long = 0 private var userId: Long = 0
private var isCreator: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
userId = intent.getLongExtra(Constants.EXTRA_USER_ID, 0) userId = intent.getLongExtra(Constants.EXTRA_USER_ID, 0)
isCreator = SharedPreferenceManager.userId == userId
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (userId > 0) { if (userId > 0) {
bindData() bindData()
if (!isCreator) {
viewModel.getCreatorProfileDonationRanking(userId) viewModel.getCreatorProfileDonationRanking(userId)
}
} else { } else {
Toast.makeText( Toast.makeText(
applicationContext, applicationContext,
@@ -120,15 +125,26 @@ class UserProfileDonationAllViewActivity : BaseActivity<ActivityUserProfileLiveA
binding.swipeRefreshLayout.isRefreshing = false binding.swipeRefreshLayout.isRefreshing = false
} }
if (SharedPreferenceManager.userId == userId) { if (isCreator) {
binding.llTotal.visibility = View.VISIBLE binding.llTotal.visibility = View.VISIBLE
binding.llVisibleDonationRanking.visibility = View.VISIBLE binding.llVisibleDonationRanking.visibility = View.VISIBLE
binding.llDonationRankingPeriod.visibility = View.VISIBLE
binding.tabDonationRankingPeriod.visibility = View.VISIBLE
binding.ivVisibleDonationRank.setOnClickListener { binding.ivVisibleDonationRank.setOnClickListener {
viewModel.onClickToggleVisibleDonationRank() viewModel.onClickToggleVisibleDonationRank()
} }
binding.llPeriodWeekly.setOnClickListener {
viewModel.updateDonationRankingPeriod(DonationRankingPeriod.WEEKLY)
}
binding.llPeriodCumulative.setOnClickListener {
viewModel.updateDonationRankingPeriod(DonationRankingPeriod.CUMULATIVE)
}
setupDonationRankingTabs()
} else { } else {
binding.llTotal.visibility = View.GONE binding.llTotal.visibility = View.GONE
binding.llVisibleDonationRanking.visibility = View.GONE binding.llVisibleDonationRanking.visibility = View.GONE
binding.llDonationRankingPeriod.visibility = View.GONE
binding.tabDonationRankingPeriod.visibility = View.GONE
} }
} }
@@ -156,6 +172,10 @@ class UserProfileDonationAllViewActivity : BaseActivity<ActivityUserProfileLiveA
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
} }
viewModel.selectedDonationRankingPeriod.observe(this) {
updateDonationRankingPeriodSelection(it)
}
viewModel.isVisibleDonationRank.observe(this) { viewModel.isVisibleDonationRank.observe(this) {
binding.ivVisibleDonationRank.setImageResource( binding.ivVisibleDonationRank.setImageResource(
if (it) { if (it) {
@@ -166,4 +186,57 @@ class UserProfileDonationAllViewActivity : BaseActivity<ActivityUserProfileLiveA
) )
} }
} }
private fun setupDonationRankingTabs() {
binding.tabDonationRankingPeriod.apply {
addTab(
newTab()
.setText(R.string.screen_user_profile_donation_period_weekly)
.setTag(DonationRankingPeriod.WEEKLY)
)
addTab(
newTab()
.setText(R.string.screen_user_profile_donation_period_cumulative)
.setTag(DonationRankingPeriod.CUMULATIVE)
)
addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
@SuppressLint("NotifyDataSetChanged")
override fun onTabSelected(tab: TabLayout.Tab) {
val period = tab.tag as DonationRankingPeriod
adapter.items.clear()
adapter.notifyDataSetChanged()
viewModel.refresh(userId, period)
}
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
@SuppressLint("NotifyDataSetChanged")
override fun onTabReselected(tab: TabLayout.Tab) {
val period = tab.tag as DonationRankingPeriod
adapter.items.clear()
adapter.notifyDataSetChanged()
viewModel.refresh(userId, period)
}
})
}
binding.tabDonationRankingPeriod.getTabAt(0)?.select()
}
private fun updateDonationRankingPeriodSelection(period: DonationRankingPeriod) {
binding.ivPeriodWeekly.setImageResource(
if (period == DonationRankingPeriod.WEEKLY) {
R.drawable.btn_square_select_checked
} else {
R.drawable.btn_square_select_normal
}
)
binding.ivPeriodCumulative.setImageResource(
if (period == DonationRankingPeriod.CUMULATIVE) {
R.drawable.btn_square_select_checked
} else {
R.drawable.btn_square_select_normal
}
)
}
} }

View File

@@ -34,19 +34,29 @@ class UserProfileDonationAllViewModel(
val isVisibleDonationRank: LiveData<Boolean> val isVisibleDonationRank: LiveData<Boolean>
get() = _isVisibleDonationRank get() = _isVisibleDonationRank
private val _selectedDonationRankingPeriod = MutableLiveData<DonationRankingPeriod>()
val selectedDonationRankingPeriod: LiveData<DonationRankingPeriod>
get() = _selectedDonationRankingPeriod
private var isLast = false private var isLast = false
private var page = 1 private var page = 1
private val size = 10 private val size = 10
private var currentRankingPeriod: DonationRankingPeriod? = null
fun getCreatorProfileDonationRanking(userId: Long) { fun getCreatorProfileDonationRanking(userId: Long, period: DonationRankingPeriod? = null) {
if (!_isLoading.value!! && !isLast) { if (!_isLoading.value!! && !isLast) {
if (period != null) {
currentRankingPeriod = period
}
_isLoading.value = true _isLoading.value = true
val requestPeriod = period ?: currentRankingPeriod
compositeDisposable.add( compositeDisposable.add(
repository.getCreatorProfileDonationRanking( repository.getCreatorProfileDonationRanking(
id = userId, id = userId,
page = page, page = page,
size = size, size = size,
donationRankingPeriod = requestPeriod?.name,
token = "Bearer ${SharedPreferenceManager.token}" token = "Bearer ${SharedPreferenceManager.token}"
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@@ -54,6 +64,12 @@ class UserProfileDonationAllViewModel(
.subscribe( .subscribe(
{ {
if (it.success && it.data != null) { if (it.success && it.data != null) {
it.data.donationRankingPeriod?.let { donationRankingPeriod ->
_selectedDonationRankingPeriod.postValue(donationRankingPeriod)
if (currentRankingPeriod == null) {
currentRankingPeriod = donationRankingPeriod
}
}
if (it.data.userDonationRanking.isNotEmpty()) { if (it.data.userDonationRanking.isNotEmpty()) {
page += 1 page += 1
_donationLiveData.postValue(it.data!!) _donationLiveData.postValue(it.data!!)
@@ -87,10 +103,10 @@ class UserProfileDonationAllViewModel(
} }
} }
fun refresh(userId: Long) { fun refresh(userId: Long, period: DonationRankingPeriod? = null) {
page = 1 page = 1
isLast = false isLast = false
getCreatorProfileDonationRanking(userId) getCreatorProfileDonationRanking(userId, period)
} }
fun onClickToggleVisibleDonationRank() { fun onClickToggleVisibleDonationRank() {
@@ -135,4 +151,45 @@ class UserProfileDonationAllViewModel(
) )
) )
} }
fun updateDonationRankingPeriod(period: DonationRankingPeriod) {
_isLoading.value = true
compositeDisposable.add(
memberRepository.updateProfile(
request = ProfileUpdateRequest(
email = SharedPreferenceManager.email,
donationRankingPeriod = period
),
token = "Bearer ${SharedPreferenceManager.token}"
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
if (it.success) {
_selectedDonationRankingPeriod.postValue(period)
} else {
if (it.message != null) {
_toastLiveData.postValue(it.message)
} else {
_toastLiveData.postValue(
SodaLiveApplicationHolder.get()
.getString(R.string.common_error_unknown)
)
}
}
_isLoading.value = false
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue(
SodaLiveApplicationHolder.get()
.getString(R.string.common_error_unknown)
)
}
)
)
}
} }

View File

@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.mypage.profile
import androidx.annotation.Keep import androidx.annotation.Keep
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kr.co.vividnext.sodalive.explorer.profile.donation.DonationRankingPeriod
import kr.co.vividnext.sodalive.user.Gender import kr.co.vividnext.sodalive.user.Gender
@Keep @Keep
@@ -19,5 +20,6 @@ data class ProfileUpdateRequest(
@SerializedName("websiteUrl") val websiteUrl: String? = null, @SerializedName("websiteUrl") val websiteUrl: String? = null,
@SerializedName("blogUrl") val blogUrl: String? = null, @SerializedName("blogUrl") val blogUrl: String? = null,
@SerializedName("isVisibleDonationRank") val isVisibleDonationRank: Boolean? = null, @SerializedName("isVisibleDonationRank") val isVisibleDonationRank: Boolean? = null,
@SerializedName("donationRankingPeriod") val donationRankingPeriod: DonationRankingPeriod? = null,
@SerializedName("container") val container: String = "aos" @SerializedName("container") val container: String = "aos"
) )

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/black" android:background="@color/black"
@@ -54,11 +55,76 @@
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/ll_donation_ranking_period"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="13.3dp"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:id="@+id/ll_period_weekly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv_period_weekly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/btn_square_select_checked"
tools:src="@drawable/btn_square_select_checked" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6.7dp"
android:fontFamily="@font/medium"
android:text="@string/screen_user_profile_donation_period_weekly"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_period_cumulative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv_period_cumulative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/btn_square_select_normal"
tools:src="@drawable/btn_square_select_normal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6.7dp"
android:fontFamily="@font/medium"
android:text="@string/screen_user_profile_donation_period_cumulative"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_total" android:id="@+id/ll_total"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="13.3dp" android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="13.3dp"
android:background="@drawable/bg_round_corner_8_13181b" android:background="@drawable/bg_round_corner_8_13181b"
android:orientation="vertical" android:orientation="vertical"
android:padding="16.7dp" android:padding="16.7dp"
@@ -167,9 +233,24 @@
</LinearLayout> </LinearLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_donation_ranking_period"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="13.3dp"
android:background="@color/black"
android:visibility="gone"
app:tabIndicatorColor="@color/color_3bb9f1"
app:tabIndicatorFullWidth="true"
app:tabIndicatorHeight="4dp"
app:tabSelectedTextColor="@color/color_3bb9f1"
app:tabTextAppearance="@style/tabText"
app:tabTextColor="@color/color_b0bec5" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="13.3dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingHorizontal="13.3dp"> android:paddingHorizontal="13.3dp">

View File

@@ -810,6 +810,8 @@
<string name="screen_user_profile_donation_total_label">All</string> <string name="screen_user_profile_donation_total_label">All</string>
<string name="screen_user_profile_donation_total_unit">items</string> <string name="screen_user_profile_donation_total_unit">items</string>
<string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string> <string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string>
<string name="screen_user_profile_donation_period_weekly">Weekly</string>
<string name="screen_user_profile_donation_period_cumulative">Cumulative</string>
<string name="screen_user_profile_community_title">Community</string> <string name="screen_user_profile_community_title">Community</string>
<string name="screen_user_profile_community_create">Create post</string> <string name="screen_user_profile_community_create">Create post</string>
<string name="screen_user_profile_community_empty_desc">After posting, your post will appear here\nand be visible in the community.</string> <string name="screen_user_profile_community_empty_desc">After posting, your post will appear here\nand be visible in the community.</string>

View File

@@ -810,6 +810,8 @@
<string name="screen_user_profile_donation_total_label"></string> <string name="screen_user_profile_donation_total_label"></string>
<string name="screen_user_profile_donation_total_unit"></string> <string name="screen_user_profile_donation_total_unit"></string>
<string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string> <string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string>
<string name="screen_user_profile_donation_period_weekly">週間</string>
<string name="screen_user_profile_donation_period_cumulative">累計</string>
<string name="screen_user_profile_community_title">コミュニティ</string> <string name="screen_user_profile_community_title">コミュニティ</string>
<string name="screen_user_profile_community_create">投稿作成</string> <string name="screen_user_profile_community_create">投稿作成</string>
<string name="screen_user_profile_community_empty_desc">投稿するとここに表示され、\nコミュニティに公開されます。</string> <string name="screen_user_profile_community_empty_desc">投稿するとここに表示され、\nコミュニティに公開されます。</string>

View File

@@ -809,6 +809,8 @@
<string name="screen_user_profile_donation_total_label">전체</string> <string name="screen_user_profile_donation_total_label">전체</string>
<string name="screen_user_profile_donation_total_unit"></string> <string name="screen_user_profile_donation_total_unit"></string>
<string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string> <string name="screen_user_profile_donation_total_can_format">%1$s %2$s</string>
<string name="screen_user_profile_donation_period_weekly">주간</string>
<string name="screen_user_profile_donation_period_cumulative">누적</string>
<string name="screen_user_profile_community_title">커뮤니티</string> <string name="screen_user_profile_community_title">커뮤니티</string>
<string name="screen_user_profile_community_create">게시물 등록</string> <string name="screen_user_profile_community_create">게시물 등록</string>
<string name="screen_user_profile_community_empty_desc">게시 후에 게시물이 여기에 표시되고\n커뮤니티에 공개됩니다.</string> <string name="screen_user_profile_community_empty_desc">게시 후에 게시물이 여기에 표시되고\n커뮤니티에 공개됩니다.</string>