Skip to content

Commit

Permalink
Converting the account list re-order to access via state and action
Browse files Browse the repository at this point in the history
  • Loading branch information
nkuppan committed Jun 1, 2024
1 parent 50e2191 commit ba7ae9d
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.naveenapps.expensemanager.core.common.utils.UiState
import com.naveenapps.expensemanager.core.testing.TestMainActivity
import org.junit.Rule
import org.junit.Test
Expand All @@ -20,30 +19,30 @@ class AccountListScreenKtTest {
val composeTestRule = createAndroidComposeRule<TestMainActivity>()

@Test
fun openAccountListScreenAndClickCreateButton() {
fun openAccountListScreenAndClickCreateButton() {
// Start the app
composeTestRule.setContent {
AccountListContentView(
state = UiState.Success(emptyList()),
onAction = false,
openAccountReOrderScreen = {},
closePage = {},
openCreateScreen = {}
state = AccountListState(
accounts = emptyList(),
showReOrder = false
),
onAction = { },
)
}

composeTestRule.onNodeWithTag("Create").performClick()
}

@Test
fun openAccountListScreenWithDataShouldShowAccountList() {
fun openAccountListScreenWithDataShouldShowAccountList() {
composeTestRule.setContent {
AccountListContentView(
state = UiState.Success(getRandomAccountUiModel(5)),
onAction = true,
openAccountReOrderScreen = {},
closePage = {},
openCreateScreen = {}
state = AccountListState(
accounts = getRandomAccountUiModel(5),
showReOrder = false
),
onAction = { },
)
}

Expand All @@ -52,14 +51,14 @@ class AccountListScreenKtTest {
}

@Test
fun showAccountListEmptyStateWhenNoItemsAvailable() {
fun showAccountListEmptyStateWhenNoItemsAvailable() {
composeTestRule.setContent {
AccountListContentView(
state = UiState.Empty,
onAction = true,
openAccountReOrderScreen = {},
closePage = {},
openCreateScreen = {}
state = AccountListState(
accounts = emptyList(),
showReOrder = false
),
onAction = { },
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.naveenapps.expensemanager.feature.account.reorder

sealed class AccountReOrderAction {

data object ClosePage : AccountReOrderAction()

data object Save : AccountReOrderAction()

data class Swap(val fromIndex: Int, val toIndex: Int) : AccountReOrderAction()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.outlined.Reorder
import androidx.compose.material3.FloatingActionButton
Expand All @@ -32,8 +33,8 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.naveenapps.expensemanager.core.designsystem.AppPreviewsLightAndDarkMode
import com.naveenapps.expensemanager.core.designsystem.components.dragGestureHandler
import com.naveenapps.expensemanager.core.designsystem.components.rememberDragDropListState
import com.naveenapps.expensemanager.core.designsystem.ui.components.AppTopNavigationBar
import com.naveenapps.expensemanager.core.designsystem.ui.components.IconAndBackgroundView
import com.naveenapps.expensemanager.core.designsystem.ui.components.TopNavigationBar
import com.naveenapps.expensemanager.core.designsystem.ui.theme.ExpenseManagerTheme
import com.naveenapps.expensemanager.core.designsystem.ui.utils.ItemSpecModifier
import com.naveenapps.expensemanager.core.model.Account
Expand All @@ -45,25 +46,18 @@ import kotlinx.coroutines.Job
fun AccountReOrderScreen(
viewModel: AccountReOrderViewModel = hiltViewModel(),
) {
val accounts by viewModel.accounts.collectAsState()
val showActionButton by viewModel.showActionButton.collectAsState()
val state by viewModel.state.collectAsState()

AccountReOrderScaffoldView(
accounts = accounts,
showActionButton = showActionButton,
backPress = viewModel::closePage,
saveChanges = viewModel::saveChanges,
onMove = viewModel::swap,
state = state,
onAction = viewModel::processAction,
)
}

@Composable
private fun AccountReOrderScaffoldView(
accounts: List<Account>,
showActionButton: Boolean,
onMove: (Int, Int) -> Unit,
saveChanges: () -> Unit,
backPress: () -> Unit,
state: AccountReOrderState,
onAction: (AccountReOrderAction) -> Unit,
) {
val snackbarHostState = remember { SnackbarHostState() }

Expand All @@ -72,14 +66,21 @@ private fun AccountReOrderScaffoldView(
SnackbarHost(hostState = snackbarHostState)
},
topBar = {
TopNavigationBar(
AppTopNavigationBar(
title = stringResource(R.string.accounts_re_order),
onClick = backPress,
navigationIcon = Icons.AutoMirrored.Filled.ArrowBack,
navigationBackClick = {
onAction.invoke(AccountReOrderAction.ClosePage)
},
)
},
floatingActionButton = {
if (showActionButton) {
FloatingActionButton(onClick = saveChanges) {
if (state.showSaveButton) {
FloatingActionButton(
onClick = {
onAction.invoke(AccountReOrderAction.Save)
}
) {
Icon(
imageVector = Icons.Default.Done,
contentDescription = "",
Expand All @@ -89,8 +90,12 @@ private fun AccountReOrderScaffoldView(
},
) { innerPadding ->
ReOrderContent(
accounts = accounts,
onMove = onMove,
accounts = state.accounts,
onMove = { from, to ->
onAction.invoke(
AccountReOrderAction.Swap(from, to)
)
},
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
Expand Down Expand Up @@ -179,12 +184,11 @@ fun AccountReOrderItem(
fun AccountReOrderScaffoldViewPreview() {
ExpenseManagerTheme {
AccountReOrderScaffoldView(
accounts = getRandomAccountData(5),
showActionButton = true,
onMove = { i, j ->

},
saveChanges = {},
backPress = {})
state = AccountReOrderState(
accounts = getRandomAccountData(5),
showSaveButton = true
),
onAction = {},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.naveenapps.expensemanager.feature.account.reorder

import com.naveenapps.expensemanager.core.model.Account

data class AccountReOrderState(
val accounts: List<Account>,
val showSaveButton: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import androidx.lifecycle.viewModelScope
import com.naveenapps.expensemanager.core.designsystem.components.swap
import com.naveenapps.expensemanager.core.domain.usecase.account.GetAllAccountsUseCase
import com.naveenapps.expensemanager.core.domain.usecase.account.UpdateAllAccountUseCase
import com.naveenapps.expensemanager.core.model.Account
import com.naveenapps.expensemanager.core.navigation.AppComposeNavigator
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

Expand All @@ -22,26 +22,28 @@ class AccountReOrderViewModel @Inject constructor(
private val appComposeNavigator: AppComposeNavigator,
) : ViewModel() {

private val _showActionButton = MutableStateFlow<Boolean>(false)
val showActionButton = _showActionButton.asStateFlow()

private val _accounts = MutableStateFlow<List<Account>>(emptyList())
val accounts = _accounts.asStateFlow()
private val _state = MutableStateFlow(
AccountReOrderState(
accounts = emptyList(),
showSaveButton = false
)
)
val state = _state.asStateFlow()

init {
getAllAccountsUseCase.invoke().onEach {
_accounts.value = it
getAllAccountsUseCase.invoke().onEach { accounts ->
_state.update { it.copy(accounts = accounts, showSaveButton = false) }
}.launchIn(viewModelScope)
}

fun closePage() {
private fun closePage() {
appComposeNavigator.popBackStack()
}

fun saveChanges() {
private fun saveChanges() {
viewModelScope.launch {
updateAllAccountUseCase.invoke(
_accounts.value.mapIndexed { index, item ->
_state.value.accounts.mapIndexed { index, item ->
item.copy(sequence = index)
},
)
Expand All @@ -50,12 +52,19 @@ class AccountReOrderViewModel @Inject constructor(
}
}

fun swap(fromIndex: Int, toIndex: Int) {
private fun swap(fromIndex: Int, toIndex: Int) {
viewModelScope.launch {
val updatedPomodoroList = _accounts.value.toMutableList()
val updatedPomodoroList = _state.value.accounts.toMutableList()
val swappedList = updatedPomodoroList.swap(fromIndex, toIndex)
_accounts.value = swappedList
_showActionButton.value = true
_state.update { it.copy(accounts = swappedList, showSaveButton = true) }
}
}

fun processAction(action: AccountReOrderAction) {
when (action) {
AccountReOrderAction.ClosePage -> closePage()
AccountReOrderAction.Save -> saveChanges()
is AccountReOrderAction.Swap -> swap(action.fromIndex, action.toIndex)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ import com.naveenapps.expensemanager.feature.category.transaction.CategoryTransa
fun CategoryDetailScreen(
viewModel: CategoryDetailViewModel = hiltViewModel(),
) {
val category by viewModel.category.collectAsState()
val categoryTransactions by viewModel.categoryTransactions.collectAsState()
val state by viewModel.state.collectAsState()

val snackbarHostState = remember { SnackbarHostState() }

Expand All @@ -79,7 +78,7 @@ fun CategoryDetailScreen(
title = {
},
actions = {
category?.let {
state.categoryTransaction?.let {
IconButton(onClick = {
viewModel.openCategoryEditScreen()
}) {
Expand All @@ -91,7 +90,7 @@ fun CategoryDetailScreen(
}
},
)
category?.let { categoryTransaction ->
state.categoryTransaction?.let { categoryTransaction ->
CategoryTransactionItem(
modifier = Modifier.padding(16.dp),
name = categoryTransaction.category.name,
Expand Down Expand Up @@ -121,7 +120,7 @@ fun CategoryDetailScreen(
.padding(innerPadding)
.fillMaxSize(),
) {
if (categoryTransactions.isEmpty()) {
if (state.transactions.isEmpty()) {
Text(
modifier = Modifier
.wrapContentSize()
Expand All @@ -131,7 +130,7 @@ fun CategoryDetailScreen(
)
} else {
Column(modifier = Modifier.padding(top = 16.dp)) {
categoryTransactions.forEach { item ->
state.transactions.forEach { item ->
TransactionItem(
categoryName = item.categoryName,
fromAccountName = item.fromAccountName,
Expand Down
Loading

0 comments on commit ba7ae9d

Please sign in to comment.