From 037bf876415c21ec3fba97ee21383301f60d49dc Mon Sep 17 00:00:00 2001 From: kartikey Date: Sat, 24 Jan 2026 14:12:03 +0530 Subject: [PATCH] feat(feature/client): default to "Active" status and apply filters on initial load feat(feature/client): default to "Active" status and apply filters on refresh feat(feature/client): default to "Active" status and apply filters on refresh feat(feature/client): default to "Active" status and apply filters on refresh feat(feature/client): default to "Active" status and apply filters on refresh feat(feature/client): default to "Active" status and apply filters on refresh --- .../clientsList/ClientListScreen.android.kt | 134 +++++++++--------- .../client/clientsList/ClientListViewModel.kt | 52 +++++-- 2 files changed, 108 insertions(+), 78 deletions(-) diff --git a/feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientsList/ClientListScreen.android.kt b/feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientsList/ClientListScreen.android.kt index fe38df6efa..83472f0d4c 100644 --- a/feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientsList/ClientListScreen.android.kt +++ b/feature/client/src/androidMain/kotlin/com/mifos/feature/client/clientsList/ClientListScreen.android.kt @@ -20,6 +20,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.paging.LoadState @@ -66,92 +67,89 @@ internal actual fun LazyColumnForClientListApi( is LoadState.NotLoading -> Unit } - if (sort != null) { + val displayList = remember(clientPagingList.itemSnapshotList, sort) { val currentItems = clientPagingList.itemSnapshotList.items - val sortedItems = when (sort) { - SortTypes.NAME -> { - currentItems.sortedBy { it.displayName?.lowercase() } - } - SortTypes.ACCOUNT_NUMBER -> { - currentItems.sortedBy { it.accountNo } - } - SortTypes.EXTERNAL_ID -> { - currentItems.sortedBy { it.externalId } - } - else -> currentItems + when (sort) { + SortTypes.NAME -> currentItems.sortedBy { it.displayName?.lowercase() } + SortTypes.ACCOUNT_NUMBER -> currentItems.sortedBy { it.accountNo } + SortTypes.EXTERNAL_ID -> currentItems.sortedBy { it.externalId } + else -> currentItems.sortedBy { getStatusOrder(it.status?.value) } } + } - LazyColumn( - modifier = modifier, - ) { - items( - items = sortedItems, - key = { client -> client.id }, - ) { client -> - LaunchedEffect(client.id) { - fetchImage(client.id) - } - ClientItem( - client = client, - byteArray = images[client.id], - onClientClick = onClientSelect, - ) + if (clientPagingList.itemCount > 0) { + LaunchedEffect(clientPagingList.itemCount, displayList.size) { + val lastRawIndex = clientPagingList.itemCount - 1 + if ((displayList.isEmpty() || displayList.size < 10) && lastRawIndex >= 0) { + clientPagingList[lastRawIndex] } } - } else { - LazyColumn( - modifier = modifier, - ) { - items( - count = clientPagingList.itemCount, - key = { index -> clientPagingList[index]?.id ?: index }, - ) { index -> - clientPagingList[index]?.let { client -> - LaunchedEffect(client.id) { - fetchImage(client.id) + } + + LazyColumn(modifier = modifier) { + items( + items = displayList, + key = { client -> client.id }, + ) { client -> + LaunchedEffect(client.id) { fetchImage(client.id) } + + if (client == displayList.last()) { + LaunchedEffect(Unit) { + val lastIndex = clientPagingList.itemCount - 1 + if (lastIndex >= 0) { + clientPagingList[lastIndex] } - ClientItem( - client = client, - byteArray = images[client.id], - onClientClick = onClientSelect, - ) } } - when (clientPagingList.loadState.append) { - is LoadState.Error -> { - item { - MifosSweetError(message = stringResource(Res.string.feature_client_failed_to_more_clients)) { - onRefresh() - } + ClientItem( + client = client, + byteArray = images[client.id], + onClientClick = onClientSelect, + ) + } + + when (clientPagingList.loadState.append) { + is LoadState.Error -> { + item { + MifosSweetError(message = stringResource(Res.string.feature_client_failed_to_more_clients)) { + onRefresh() } } + } - is LoadState.Loading -> { - item { - MifosPagingAppendProgress() - } + is LoadState.Loading -> { + item { + MifosPagingAppendProgress() } + } - is LoadState.NotLoading -> { - if (clientPagingList.loadState.append.endOfPaginationReached && - clientPagingList.itemCount > 0 - ) { - item { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = DesignToken.padding.extraExtraLarge) - .padding(bottom = DesignToken.padding.extraExtraLarge), - text = stringResource(Res.string.feature_client_no_more_clients_available), - style = MifosTypography.bodyMedium, - textAlign = TextAlign.Center, - ) - } + is LoadState.NotLoading -> { + if (clientPagingList.loadState.append.endOfPaginationReached && + clientPagingList.itemCount > 0 + ) { + item { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = DesignToken.padding.extraExtraLarge) + .padding(bottom = DesignToken.padding.extraExtraLarge), + text = stringResource(Res.string.feature_client_no_more_clients_available), + style = MifosTypography.bodyMedium, + textAlign = TextAlign.Center, + ) } } } } } } +fun getStatusOrder(status: String?): Int { + return when (status?.lowercase()) { + "active" -> 1 + "pending" -> 2 + "closed" -> 3 + else -> 4 + } +} diff --git a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientsList/ClientListViewModel.kt b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientsList/ClientListViewModel.kt index 7ca55c40be..47ed63fcab 100644 --- a/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientsList/ClientListViewModel.kt +++ b/feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientsList/ClientListViewModel.kt @@ -23,7 +23,6 @@ import com.mifos.core.ui.util.BaseViewModel import com.mifos.core.ui.util.imageToByteArray import com.mifos.room.entities.client.ClientEntity import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update @@ -149,23 +148,56 @@ internal class ClientListViewModel( ) } - is DataState.Success -> updateState { - val data = result.data.pageItems - if (data.isEmpty()) { - it.copy(isEmpty = true, dialogState = null) - } else { - it.copy(clients = data, dialogState = null, unfilteredClients = data) + is DataState.Success -> { + updateState { state -> + val data = result.data.pageItems + if (data.isEmpty()) { + state.copy(isEmpty = true, dialogState = null) + } else { + val filteredData = data.filter { client -> + val statusMatch = state.selectedStatus.isEmpty() || client.status?.value in state.selectedStatus + val officeMatch = state.selectedOffices.isEmpty() || (client.officeName ?: "Null") in state.selectedOffices + statusMatch && officeMatch + } + fun getStatusOrder(status: String?): Int { + return when (status?.lowercase()) { + "active" -> 1 + "pending" -> 2 + "closed" -> 3 + else -> 4 + } + } + val sortedList = when (state.sort) { + SortTypes.NAME -> filteredData.sortedBy { it.displayName?.lowercase() } + SortTypes.ACCOUNT_NUMBER -> filteredData.sortedBy { it.accountNo } + SortTypes.EXTERNAL_ID -> filteredData.sortedBy { it.externalId } + else -> filteredData.sortedBy { getStatusOrder(it.status?.value) } + } + state.copy( + clients = sortedList, + unfilteredClients = data, + dialogState = null, + ) + } } } } } private fun handleClientResult(result: Flow>) { - updateState { + updateState { state -> + val filteredFlow = result.map { pagingData -> + pagingData.filter { client -> + val statusMatch = state.selectedStatus.isEmpty() || client.status?.value in state.selectedStatus + val officeMatch = state.selectedOffices.isEmpty() || (client.officeName ?: "Null") in state.selectedOffices + statusMatch && officeMatch + } + } + state.copy( - clientsFlow = result, - dialogState = null, + clientsFlow = filteredFlow, unfilteredClientsFlow = result, + dialogState = null, ) } }