From ba694e0e288f1e54446ee2bd8db14b579db27536 Mon Sep 17 00:00:00 2001 From: Jonathan Rodrigues Date: Sun, 5 May 2024 23:02:24 -0300 Subject: [PATCH] Pie chart improvement --- .../designsystem/components/PieChartLayout.kt | 58 +++++++++++-------- .../com/stonks/feature/home/di/HomeModule.kt | 9 ++- .../home/domain/mapper/HomeModelToUiMapper.kt | 28 ++------- .../domain/mapper/WalletModelToChartMapper.kt | 56 ++++++++++++++++++ .../feature/home/ui/model/HomeUiModel.kt | 2 +- .../stonks/feature/home/ui/view/HomeScreen.kt | 20 ++++--- 6 files changed, 115 insertions(+), 58 deletions(-) create mode 100644 feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/WalletModelToChartMapper.kt diff --git a/design-system/src/main/kotlin/br/com/stonks/designsystem/components/PieChartLayout.kt b/design-system/src/main/kotlin/br/com/stonks/designsystem/components/PieChartLayout.kt index 1be110f..40c32a2 100644 --- a/design-system/src/main/kotlin/br/com/stonks/designsystem/components/PieChartLayout.kt +++ b/design-system/src/main/kotlin/br/com/stonks/designsystem/components/PieChartLayout.kt @@ -32,15 +32,19 @@ import br.com.stonks.common.formatters.formatPercent import br.com.stonks.designsystem.tokens.ColorToken import br.com.stonks.designsystem.tokens.FractionToken import br.com.stonks.designsystem.tokens.SpacingToken +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList data class PieChartDataProgress( val progress: Float, val progressColor: Color, + val trackColor: Color = Color.Transparent, ) data class PieChartData( val title: String, val value: Double, + val progress: Float, val dataProgress: List, ) @@ -78,13 +82,14 @@ private fun PieChartContent( private fun PieChartProgress( progress: Float, progressColor: Color, + trackColor: Color, ) { CircularProgressIndicator( progress = { progress }, modifier = Modifier.fillMaxSize(), strokeWidth = 20.dp, color = progressColor, - trackColor = Color.Transparent, + trackColor = trackColor, strokeCap = StrokeCap.Round, ) } @@ -128,10 +133,10 @@ private fun PieChartSubtitle( @Composable @OptIn(ExperimentalFoundationApi::class) fun PieChartLayout( - data: PieChartData, + data: ImmutableList, modifier: Modifier = Modifier, ) { - val pagerState = rememberPagerState(pageCount = { data.dataProgress.size }) + val pagerState = rememberPagerState(pageCount = { data.size }) Column( modifier = modifier.wrapContentSize(), @@ -140,7 +145,7 @@ fun PieChartLayout( modifier = Modifier .wrapContentSize(), state = pagerState, - ) { _ -> + ) { pageIndex -> Column( modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, @@ -151,16 +156,18 @@ fun PieChartLayout( .aspectRatio(FractionToken.level10), contentAlignment = Alignment.Center, ) { - data.dataProgress.forEach { + val entry = data[pageIndex] + entry.dataProgress.forEach { PieChartProgress( progress = it.progress, progressColor = it.progressColor, + trackColor = it.trackColor, ) } PieChartContent( - title = data.value.formatCurrency(), - subtitle = data.title, - progress = 1f, + title = entry.value.formatCurrency(), + subtitle = entry.title, + progress = entry.progress, ) } } @@ -176,23 +183,26 @@ fun PieChartLayout( @Composable private fun PieChartLayoutPreview() { PieChartLayout( - data = PieChartData( - title = "Todos os produtos", - value = 160000.0, - dataProgress = listOf( - PieChartDataProgress( - progress = 1f, - progressColor = ColorToken.HighlightGreen, - ), - PieChartDataProgress( - progress = 0.7f, - progressColor = ColorToken.HighlightBlue, - ), - PieChartDataProgress( - progress = 0.3f, - progressColor = ColorToken.HighlightPurple, + data = listOf( + PieChartData( + title = "Todos os produtos", + value = 160000.0, + progress = 1f, + dataProgress = listOf( + PieChartDataProgress( + progress = 1f, + progressColor = ColorToken.HighlightGreen, + ), + PieChartDataProgress( + progress = 0.7f, + progressColor = ColorToken.HighlightBlue, + ), + PieChartDataProgress( + progress = 0.3f, + progressColor = ColorToken.HighlightPurple, + ), ), ), - ), + ).toImmutableList(), ) } diff --git a/feature/home/src/main/kotlin/br/com/stonks/feature/home/di/HomeModule.kt b/feature/home/src/main/kotlin/br/com/stonks/feature/home/di/HomeModule.kt index 339f2fa..94e071f 100644 --- a/feature/home/src/main/kotlin/br/com/stonks/feature/home/di/HomeModule.kt +++ b/feature/home/src/main/kotlin/br/com/stonks/feature/home/di/HomeModule.kt @@ -3,6 +3,7 @@ package br.com.stonks.feature.home.di import br.com.stonks.common.states.ViewModelState import br.com.stonks.feature.home.domain.mapper.DailyTransactionResponseToModelMapper import br.com.stonks.feature.home.domain.mapper.HomeModelToUiMapper +import br.com.stonks.feature.home.domain.mapper.WalletModelToChartMapper import br.com.stonks.feature.home.domain.mapper.WalletResponseToModelMapper import br.com.stonks.feature.home.domain.usecase.DailyTransactionUseCase import br.com.stonks.feature.home.domain.usecase.HomeContentUseCase @@ -48,7 +49,13 @@ val homeModule = module { } factory { - HomeModelToUiMapper() + WalletModelToChartMapper() + } + + factory { + HomeModelToUiMapper( + walletChartMapper = get(), + ) } factory { diff --git a/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapper.kt b/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapper.kt index 55d7cf8..2f2a66f 100644 --- a/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapper.kt +++ b/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapper.kt @@ -3,13 +3,10 @@ package br.com.stonks.feature.home.domain.mapper import br.com.stonks.common.formatters.DatePattern import br.com.stonks.common.formatters.formatTo import br.com.stonks.common.mapper.Mapper -import br.com.stonks.designsystem.components.PieChartData -import br.com.stonks.designsystem.components.PieChartDataProgress import br.com.stonks.feature.home.domain.model.DailyTransactionModel import br.com.stonks.feature.home.domain.model.HomeContentModel import br.com.stonks.feature.home.domain.model.PortfolioModel import br.com.stonks.feature.home.domain.model.TransactionModel -import br.com.stonks.feature.home.domain.model.WalletModel import br.com.stonks.feature.home.ui.model.DailyTransactionUiModel import br.com.stonks.feature.home.ui.model.HomeUiModel import br.com.stonks.feature.home.ui.model.PortfolioUiModel @@ -17,34 +14,17 @@ import br.com.stonks.feature.home.ui.model.TransactionUiModel import br.com.stonks.feature.home.utils.getColor import br.com.stonks.feature.home.utils.getIcon -internal class HomeModelToUiMapper : Mapper { +internal class HomeModelToUiMapper( + private val walletChartMapper: WalletModelToChartMapper, +) : Mapper { override fun mapper(input: HomeContentModel) = HomeUiModel( totalAssets = input.wallet.totalAssets, - portfolioChart = input.wallet.toPieChart(), + portfolioChart = walletChartMapper.mapper(input.wallet), portfolio = input.wallet.portfolio.map(::mapperPortfolio), dailyTransactions = input.dailyTransactions.map(::mapperDailyGroup), ) - private fun WalletModel.toPieChart(): PieChartData { - var incrementalProgress = 0f - - val dataProgress = this.portfolio.map { - incrementalProgress += it.allocation - - PieChartDataProgress( - progress = incrementalProgress, - progressColor = it.portfolioType.getColor() - ) - }.sortedByDescending { it.progress } - - return PieChartData( - title = "Todos os produtos", - value = this.totalAssets, - dataProgress = dataProgress, - ) - } - private fun mapperPortfolio(input: PortfolioModel) = PortfolioUiModel( tagColor = input.portfolioType.getColor(), portfolioName = input.portfolioName, diff --git a/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/WalletModelToChartMapper.kt b/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/WalletModelToChartMapper.kt new file mode 100644 index 0000000..54afa0d --- /dev/null +++ b/feature/home/src/main/kotlin/br/com/stonks/feature/home/domain/mapper/WalletModelToChartMapper.kt @@ -0,0 +1,56 @@ +package br.com.stonks.feature.home.domain.mapper + +import br.com.stonks.common.mapper.Mapper +import br.com.stonks.designsystem.components.PieChartData +import br.com.stonks.designsystem.components.PieChartDataProgress +import br.com.stonks.designsystem.tokens.ColorToken +import br.com.stonks.feature.home.domain.model.WalletModel +import br.com.stonks.feature.home.utils.getColor + +private const val SummarizedItemIndex = 0 + +internal class WalletModelToChartMapper : Mapper> { + + override fun mapper(input: WalletModel): List { + val dataChart = mutableListOf() + val dataProgress = mutableListOf() + var incrementalProgress = 0f + + input.portfolio.forEach { portfolio -> + incrementalProgress += portfolio.allocation + + dataChart.add( + PieChartData( + title = portfolio.portfolioName, + value = portfolio.totalInvestment, + progress = portfolio.allocation, + dataProgress = listOf( + PieChartDataProgress( + progress = portfolio.allocation, + progressColor = portfolio.portfolioType.getColor(), + trackColor = ColorToken.Grayscale100, + ) + ), + ) + ) + + dataProgress.add( + PieChartDataProgress( + progress = incrementalProgress, + progressColor = portfolio.portfolioType.getColor() + ) + ) + } + + val assetsChartData = PieChartData( + title = "Todos os produtos", + value = input.totalAssets, + progress = 1f, + dataProgress = dataProgress.sortedByDescending { it.progress }, + ) + + dataChart.add(SummarizedItemIndex, assetsChartData) + + return dataChart + } +} diff --git a/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/model/HomeUiModel.kt b/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/model/HomeUiModel.kt index 0e2ecad..8a868f4 100644 --- a/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/model/HomeUiModel.kt +++ b/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/model/HomeUiModel.kt @@ -25,7 +25,7 @@ internal data class DailyTransactionUiModel( internal data class HomeUiModel( val totalAssets: Double, - val portfolioChart: PieChartData, + val portfolioChart: List, val portfolio: List, val dailyTransactions: List, ) diff --git a/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/view/HomeScreen.kt b/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/view/HomeScreen.kt index ed080c9..1fb164e 100644 --- a/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/view/HomeScreen.kt +++ b/feature/home/src/main/kotlin/br/com/stonks/feature/home/ui/view/HomeScreen.kt @@ -33,6 +33,7 @@ import br.com.stonks.feature.home.ui.model.PortfolioUiModel import br.com.stonks.feature.home.ui.model.TransactionUiModel import br.com.stonks.feature.home.ui.states.HomeUiState import br.com.stonks.feature.home.ui.viewmodel.HOME_VM_QUALIFIER +import kotlinx.collections.immutable.toImmutableList import org.koin.androidx.compose.koinViewModel import org.koin.core.qualifier.named @@ -71,7 +72,7 @@ private fun HomeContent( item { SessionDivider() PieChartLayout( - data = uiModel.portfolioChart, + data = uiModel.portfolioChart.toImmutableList(), ) } items(uiModel.portfolio) { @@ -131,13 +132,16 @@ private fun HomeScreenPreview() { HomeContent( uiModel = HomeUiModel( totalAssets = 166300.0, - portfolioChart = PieChartData( - title = "Todos os produtos", - value = 160000.0, - dataProgress = listOf( - PieChartDataProgress( - progress = 1f, - progressColor = ColorToken.HighlightGreen, + portfolioChart = listOf( + PieChartData( + title = "Todos os produtos", + value = 160000.0, + progress = 1f, + dataProgress = listOf( + PieChartDataProgress( + progress = 1f, + progressColor = ColorToken.HighlightGreen, + ), ), ), ),