Skip to content

Commit

Permalink
#18 - US05 - android list improved design
Browse files Browse the repository at this point in the history
  • Loading branch information
Harold Jose committed Apr 14, 2024
1 parent de36a0a commit a79c342
Show file tree
Hide file tree
Showing 24 changed files with 354 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import dev.haroldjose.familysharedlist.AndroidPlatform
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.navigator.views.NavigatorView
import org.koin.compose.koinInject
import org.koin.androidx.compose.KoinAndroidContext
import org.koin.core.annotation.KoinExperimentalAPI

class MainActivity : ComponentActivity() {
@OptIn(KoinExperimentalAPI::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidPlatform.androidContextForKmm = this
Expand All @@ -23,7 +26,9 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
NavigatorView(viewModel = koinInject())
KoinAndroidContext() {
NavigatorView()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ class MainApplication : Application() {
modules(appModule() + androidModule)
}

AndroidKeyValueStorageDataSource.Companion.context = this
AndroidKeyValueStorageDataSource.Companion.context = this@MainApplication
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import dev.haroldjose.familysharedlist.android.presentationLayer.pages.quickInse
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.quickInsertList.viewmodesls.QuickInsertListViewModel
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.settings.viewmodels.ISettingsViewModel
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.settings.viewmodels.SettingsViewModel
import org.koin.core.module.dsl.factoryOf
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.dsl.bind
import org.koin.dsl.module

val androidModule = module {
//ViewModels
factoryOf(::SettingsViewModel) bind ISettingsViewModel::class
factoryOf(::FamilyListViewModel) bind IFamilyListViewModel::class
factoryOf(::QuickInsertListViewModel) bind IQuickInsertListViewModel::class
factoryOf(::NavigatorViewModel) bind INavigatorViewModel::class
viewModelOf(::NavigatorViewModel)
viewModelOf(::SettingsViewModel)
viewModelOf(::FamilyListViewModel)
viewModelOf(::QuickInsertListViewModel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun Double.toStringWithOnlyDigits(): String = this.toString().filter { it.isDigi
/**
* Returns a string with the currency format
*/
fun Double.ToCurrencyFormat(fractionDigits: Int = 2): String {
fun Double.toCurrencyFormat(fractionDigits: Int = 2): String {
val numberFormat = NumberFormat.getCurrencyInstance()
numberFormat.setMaximumFractionDigits(fractionDigits);
return numberFormat.format(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.text.isDigitsOnly
import androidx.lifecycle.ViewModel
import dev.haroldjose.familysharedlist.Logger
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.FamilyListPageTabEnum
import dev.haroldjose.familysharedlist.defaultLocalDateTime
import dev.haroldjose.familysharedlist.domainLayer.models.AccountModel
import dev.haroldjose.familysharedlist.domainLayer.models.FamilyListModel
import dev.haroldjose.familysharedlist.domainLayer.usecases.account.GetOrCreateAccountFromLocalUuidUseCase
Expand All @@ -14,7 +16,10 @@ import dev.haroldjose.familysharedlist.domainLayer.usecases.familyList.DeleteFam
import dev.haroldjose.familysharedlist.domainLayer.usecases.familyList.GetAllFamilyListUseCase
import dev.haroldjose.familysharedlist.domainLayer.usecases.familyList.UpdateFamilyListUseCase
import dev.haroldjose.familysharedlist.domainLayer.usecases.product.GetProductByCodeUseCase
import dev.haroldjose.familysharedlist.getPlatform
import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime

class FamilyListViewModel(
private val getAllFamilyListUseCase: GetAllFamilyListUseCase,
Expand All @@ -23,9 +28,10 @@ class FamilyListViewModel(
private val deleteFamilyListUseCase: DeleteFamilyListUseCase,
private val getOrCreateAccountFromLocalUuidUseCase: GetOrCreateAccountFromLocalUuidUseCase,
private val getProductByCodeUseCase: GetProductByCodeUseCase
): IFamilyListViewModel {
): ViewModel(), IFamilyListViewModel {
private var familyListModelsFull: List<FamilyListModel> by mutableStateOf(arrayListOf())
override var familyListModelsFiltered: List<FamilyListModel> by mutableStateOf(arrayListOf())
override var familyListModelsGrouped: Map<LocalDate, List<FamilyListModel>> by mutableStateOf(mapOf())
override var familyListModels: List<FamilyListModel> by mutableStateOf(arrayListOf())
override var loading:Boolean by mutableStateOf(false)
override var newItemName: String by mutableStateOf("")
override var selectedItemUuid: String = ""
Expand All @@ -36,7 +42,11 @@ class FamilyListViewModel(
override var goToSetting: () -> Unit = {}
override var goToQuickInsert: () -> Unit = {}

override suspend fun loadData(tabIndex: FamilyListPageTabEnum, fromNetwork: Boolean) {
override var sumOfPrioritized: Double by mutableStateOf(0.0)
override var sumOfPending: Double by mutableStateOf(0.0)
override var sumOfCompleted: Double by mutableStateOf(0.0)

override suspend fun loadData(fromNetwork: Boolean) {
this.tabIndex = tabIndex
loading = true

Expand All @@ -45,17 +55,20 @@ class FamilyListViewModel(
if (fromNetwork) {
familyListModelsFull = getAllFamilyListUseCase.execute().sortedBy { it.name.lowercase() }
}
familyListModels = when (tabIndex) {
FamilyListPageTabEnum.PRIORIZED -> familyListModelsFull.filter { it.isPrioritized }
FamilyListPageTabEnum.PENDING -> familyListModelsFull.filter { !it.isCompleted && !it.isPrioritized}
FamilyListPageTabEnum.COMPLETED -> familyListModelsFull.filter { it.isCompleted }
}

familyListModelsFiltered = when (tabIndex) {
FamilyListPageTabEnum.PRIORIZED -> familyListModelsFull
.filter { it.isPrioritized }

FamilyListPageTabEnum.PENDING -> familyListModelsFull
.filter { !it.isCompleted && !it.isPrioritized}
familyListModelsGrouped = familyListModelsFull
.filter { it.isCompleted }
.sortedByDescending { it.isCompletedDate?.date ?: defaultLocalDateTime.date}
.groupBy { it.isCompletedDate?.date ?: defaultLocalDateTime.date }

FamilyListPageTabEnum.COMPLETED -> familyListModelsFull
.filter { it.isCompleted }
}
sumOfPrioritized = familyListModelsFull.filter { it.isPrioritized }.sumOf { it.price * it.quantity }
sumOfPending = familyListModelsFull.filter { !it.isCompleted && !it.isPrioritized }.sumOf { it.price * it.quantity }
sumOfCompleted = familyListModelsGrouped.entries.sortedByDescending { it.key }.firstOrNull()?.value?.sumOf { it.price * it.quantity} ?: 0.0

loading = false
}
Expand All @@ -81,7 +94,7 @@ class FamilyListViewModel(
newItemName = ""
loading = true
createFamilyListUseCase.execute(item = item)
loadData(this.tabIndex, fromNetwork = true)
loadData(fromNetwork = true)
}

override suspend fun addBy(barcode: String) {
Expand Down Expand Up @@ -118,7 +131,7 @@ class FamilyListViewModel(
update(item = itemFounded)
if (this.tabIndex.isCompleted())
this.tabIndex = FamilyListPageTabEnum.PENDING
loadData(this.tabIndex, fromNetwork = true)
loadData(fromNetwork = true)
return
}

Expand All @@ -133,7 +146,7 @@ class FamilyListViewModel(

createFamilyListUseCase.execute(item = item)
Logger.d("FamilyListSharedViewModel", "createFamilyListUseCase executed")
loadData(this.tabIndex, fromNetwork = true)
loadData(fromNetwork = true)
Logger.d("FamilyListSharedViewModel", "loadData executed")
}
loading = false
Expand All @@ -149,7 +162,7 @@ class FamilyListViewModel(
loading = true
deleteFamilyListUseCase.execute(uuid = item.uuid)
familyListModelsFull = familyListModelsFull.filter { it.uuid != uuid }
loadData(this.tabIndex, fromNetwork = false)
loadData(fromNetwork = false)
loading = false
}
}
Expand All @@ -159,6 +172,7 @@ class FamilyListViewModel(
item.isCompleted = isCompleted
if (item.isCompleted) {
item.isPrioritized = false
item.isCompletedDate = Clock.System.now().toLocalDateTime(TimeZone.UTC)
}
update(item)
}
Expand Down Expand Up @@ -195,7 +209,7 @@ class FamilyListViewModel(
private suspend fun update(item: FamilyListModel){
loading = true
updateFamilyListUseCase.execute(item = item)
loadData(this.tabIndex, fromNetwork = false)
loadData(fromNetwork = false)
loading = false
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.viewmodels

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.FamilyListPageTabEnum
import dev.haroldjose.familysharedlist.defaultLocalDateTime
import dev.haroldjose.familysharedlist.domainLayer.extensions.Samples
import dev.haroldjose.familysharedlist.domainLayer.models.FamilyListModel
import kotlinx.datetime.LocalDate

class FamilyListViewModelMocked : IFamilyListViewModel {
override var familyListModelsFiltered: List<FamilyListModel> = emptyList() //Samples.FamilyList.list1
class FamilyListViewModelMocked: ViewModel(), IFamilyListViewModel {
override val familyListModelsGrouped: Map<LocalDate, List<FamilyListModel>> by mutableStateOf(
Samples.FamilyList.list1.groupBy { it.isCompletedDate?.date ?: defaultLocalDateTime.date }
)
override var familyListModels: List<FamilyListModel> = Samples.FamilyList.list1
override var loading: Boolean = false
override var newItemName: String = "newItem"
override var selectedItemUuid: String = ""
Expand All @@ -15,7 +23,11 @@ class FamilyListViewModelMocked : IFamilyListViewModel {
override var goToSetting: () -> Unit = {}
override var goToQuickInsert: () -> Unit = {}

override suspend fun loadData(tabIndex: FamilyListPageTabEnum, fromNetwork: Boolean) {}
override var sumOfPrioritized: Double = 0.0
override var sumOfPending: Double = 1.23
override var sumOfCompleted: Double = 44.92

override suspend fun loadData(fromNetwork: Boolean) {}
override suspend fun add() {}
override suspend fun addBy(barcode: String) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyLi

import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.FamilyListPageTabEnum
import dev.haroldjose.familysharedlist.domainLayer.models.FamilyListModel
import kotlinx.datetime.LocalDate

interface IFamilyListViewModel {
var familyListModelsFiltered: List<FamilyListModel>
val familyListModelsGrouped: Map<LocalDate, List<FamilyListModel>>
var familyListModels: List<FamilyListModel>
var loading: Boolean
var newItemName: String
var selectedItemUuid: String
Expand All @@ -14,7 +16,11 @@ interface IFamilyListViewModel {
var goToSetting: () -> Unit
var goToQuickInsert: () -> Unit

suspend fun loadData(tabIndex: FamilyListPageTabEnum, fromNetwork: Boolean)
var sumOfPrioritized: Double
var sumOfPending: Double
var sumOfCompleted: Double

suspend fun loadData(fromNetwork: Boolean)
suspend fun add()
suspend fun addBy(barcode: String)
fun showError(e: Throwable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.twotone.List
import androidx.compose.material.icons.twotone.CheckCircle
import androidx.compose.material.icons.twotone.ShoppingCart
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
Expand All @@ -16,20 +16,20 @@ import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import dev.haroldjose.familysharedlist.android.app.MyApplicationTheme
import dev.haroldjose.familysharedlist.android.extensions.toCurrencyFormat
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.viewmodels.FamilyListViewModelMocked
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.viewmodels.IFamilyListViewModel
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.components.FamilyListBottomSheetContent
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.components.FamilyListTabItemCompletedView
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.components.FamilyListTabItemView
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.views.components.FamilyListTopAppBarView
import dev.haroldjose.familysharedlist.android.presentationLayer.pages.familyList.viewmodels.FamilyListViewModelMocked
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
Expand All @@ -39,10 +39,9 @@ fun FamilyListPage(
) {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState()
val coroutineScope = rememberCoroutineScope()
var tabIndex: FamilyListPageTabEnum by remember { mutableStateOf(FamilyListPageTabEnum.PENDING) }

LaunchedEffect(key1 = "FamilyListPage") {
viewModel.loadData(tabIndex, fromNetwork = true)
viewModel.loadData(fromNetwork = true)
}
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
Expand All @@ -52,16 +51,27 @@ fun FamilyListPage(
Scaffold(
topBar = FamilyListTopAppBarView(viewModel)
) { innerPadding ->
val tabs = listOf("Priorizado", "Pendente", "Comprado")

val tabs = listOf(
Pair("Priorizado", viewModel.sumOfPrioritized),
Pair("Pendente", viewModel.sumOfPending),
Pair("Comprado", viewModel.sumOfCompleted),
)
Column(modifier = Modifier.padding(innerPadding)) {
TabRow(selectedTabIndex = tabIndex.value) {
tabs.forEachIndexed { index, title ->
Tab(text = { Text(title) },
selected = tabIndex.value == index,
TabRow(selectedTabIndex = viewModel.tabIndex.value) {
tabs.forEachIndexed { index, pair ->
Tab(
text = {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(pair.first)
Text(pair.second.toCurrencyFormat(), color = Color.Gray)
}
},
selected = viewModel.tabIndex.value == index,
onClick = {
tabIndex = FamilyListPageTabEnum.getBy(index)
viewModel.tabIndex = FamilyListPageTabEnum.getBy(index)
coroutineScope.launch {
viewModel.loadData(tabIndex, fromNetwork = false)
viewModel.loadData(fromNetwork = false)
}
},
icon = {
Expand All @@ -85,12 +95,25 @@ fun FamilyListPage(
)
}
}
FamilyListTabItemView(
viewModel = viewModel,
tabIndex = tabIndex,
bottomSheetScaffoldState = bottomSheetScaffoldState
)

when (viewModel.tabIndex.value) {
0 -> FamilyListTabItemView(
viewModel = viewModel,
bottomSheetScaffoldState = bottomSheetScaffoldState
)

1 -> FamilyListTabItemView(
viewModel = viewModel,
bottomSheetScaffoldState = bottomSheetScaffoldState
)

2 -> FamilyListTabItemCompletedView(
viewModel = viewModel,
bottomSheetScaffoldState = bottomSheetScaffoldState
)
}
}

}
}
)
Expand Down
Loading

0 comments on commit a79c342

Please sign in to comment.