feat(creator): 후원 탭 UI 모델 매핑을 추가한다
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.donation.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.common.UtcRelativeTimeTextFormatter
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.data.CreatorChannelDonationResponse
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.data.MemberDonationRankingResponse
|
||||||
|
|
||||||
|
fun List<MemberDonationRankingResponse>.toDonationRankingUiModels(): List<CreatorChannelDonationRankingUiModel> =
|
||||||
|
mapIndexed { index, response -> response.toDonationRankingUiModel(rank = index + 1) }
|
||||||
|
|
||||||
|
fun List<CreatorChannelDonationResponse>.toDonationUiModels(
|
||||||
|
context: Context,
|
||||||
|
relativeTimeTextFormatter: UtcRelativeTimeTextFormatter
|
||||||
|
): List<CreatorChannelDonationUiModel> = map { it.toDonationUiModel(context, relativeTimeTextFormatter) }
|
||||||
|
|
||||||
|
private fun MemberDonationRankingResponse.toDonationRankingUiModel(rank: Int) = CreatorChannelDonationRankingUiModel(
|
||||||
|
rank = rank,
|
||||||
|
userId = userId,
|
||||||
|
nickname = nickname,
|
||||||
|
profileImageUrl = profileImage,
|
||||||
|
donationCan = donationCan
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun CreatorChannelDonationResponse.toDonationUiModel(
|
||||||
|
context: Context,
|
||||||
|
relativeTimeTextFormatter: UtcRelativeTimeTextFormatter
|
||||||
|
) = CreatorChannelDonationUiModel(
|
||||||
|
nickname = nickname,
|
||||||
|
profileImageUrl = profileImageUrl,
|
||||||
|
can = can,
|
||||||
|
message = message.takeUnless { it.isBlank() } ?: context.getString(R.string.creator_channel_donation_fallback_message, can),
|
||||||
|
createdAtText = relativeTimeTextFormatter.format(createdAtUtc),
|
||||||
|
headerColorResId = calculateDonationHeaderColorRes(can)
|
||||||
|
)
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
internal fun calculateDonationHeaderColorRes(can: Int): Int = when {
|
||||||
|
can >= 500 -> R.color.red_400
|
||||||
|
can >= 101 -> R.color.creator_channel_donation_cyan
|
||||||
|
can >= 51 -> R.color.green_400
|
||||||
|
else -> R.color.gray_200
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.donation.model
|
||||||
|
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
|
|
||||||
|
data class CreatorChannelDonationRankingUiModel(
|
||||||
|
val rank: Int,
|
||||||
|
val userId: Long,
|
||||||
|
val nickname: String,
|
||||||
|
val profileImageUrl: String,
|
||||||
|
val donationCan: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CreatorChannelDonationUiModel(
|
||||||
|
val nickname: String,
|
||||||
|
val profileImageUrl: String,
|
||||||
|
val can: Int,
|
||||||
|
val message: String,
|
||||||
|
val createdAtText: String,
|
||||||
|
@param:ColorRes val headerColorResId: Int
|
||||||
|
)
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.donation
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.common.AndroidUtcRelativeTimeTextFormatter
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.data.CreatorChannelDonationResponse
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.data.MemberDonationRankingResponse
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.model.toDonationRankingUiModels
|
||||||
|
import kr.co.vividnext.sodalive.v2.creator.channel.donation.model.toDonationUiModels
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [28], application = Application::class)
|
||||||
|
class CreatorChannelDonationMapperTest {
|
||||||
|
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private val relativeTimeTextFormatter = AndroidUtcRelativeTimeTextFormatter(context)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ranking rank는 응답 순서 기준 1부터 시작하고 profileImage를 profileImageUrl로 매핑한다`() {
|
||||||
|
val rankings = listOf(
|
||||||
|
ranking(userId = 10L, profileImage = "first.png"),
|
||||||
|
ranking(userId = 20L, profileImage = "second.png")
|
||||||
|
).toDonationRankingUiModels()
|
||||||
|
|
||||||
|
assertEquals(listOf(1, 2), rankings.map { it.rank })
|
||||||
|
assertEquals(listOf(10L, 20L), rankings.map { it.userId })
|
||||||
|
assertEquals(listOf("first.png", "second.png"), rankings.map { it.profileImageUrl })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `후원 message가 blank이면 can을 포함한 fallback 문구를 사용한다`() {
|
||||||
|
val item = listOf(donation(can = 50, message = " "))
|
||||||
|
.toDonationUiModels(context, relativeTimeTextFormatter)
|
||||||
|
.single()
|
||||||
|
|
||||||
|
assertEquals(context.getString(R.string.creator_channel_donation_fallback_message, 50), item.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `후원 createdAtUtc는 상대 시간으로 매핑하고 can 기준 header color를 계산한다`() {
|
||||||
|
val item = listOf(donation(can = 500, createdAtUtc = System.currentTimeMillis().toString()))
|
||||||
|
.toDonationUiModels(context, relativeTimeTextFormatter)
|
||||||
|
.single()
|
||||||
|
|
||||||
|
assertEquals(context.getString(R.string.character_comment_time_just_now), item.createdAtText)
|
||||||
|
assertEquals(R.color.red_400, item.headerColorResId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ranking(
|
||||||
|
userId: Long,
|
||||||
|
nickname: String = "member",
|
||||||
|
profileImage: String = "profile.png",
|
||||||
|
donationCan: Int = 100
|
||||||
|
) = MemberDonationRankingResponse(
|
||||||
|
userId = userId,
|
||||||
|
nickname = nickname,
|
||||||
|
profileImage = profileImage,
|
||||||
|
donationCan = donationCan
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun donation(
|
||||||
|
nickname: String = "member",
|
||||||
|
profileImageUrl: String = "profile.png",
|
||||||
|
can: Int = 50,
|
||||||
|
message: String = "응원합니다",
|
||||||
|
createdAtUtc: String = "2026-06-21T00:00:00Z"
|
||||||
|
) = CreatorChannelDonationResponse(
|
||||||
|
nickname = nickname,
|
||||||
|
profileImageUrl = profileImageUrl,
|
||||||
|
can = can,
|
||||||
|
message = message,
|
||||||
|
createdAtUtc = createdAtUtc
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user