From b17c6d6df9110051d3802771c5f9d972c9480381 Mon Sep 17 00:00:00 2001 From: Pronay Sarker Date: Sat, 30 Nov 2024 18:15:04 +0600 Subject: [PATCH] applied spotless and detekt on groups module (#2248) --- config/detekt/detekt.yml | 6 +- feature/groups/build.gradle.kts | 9 + .../feature/groups/GroupListScreenTest.kt | 60 ++- feature/groups/src/main/AndroidManifest.xml | 9 + .../CreateNewGroupScreen.kt | 187 +++++---- .../CreateNewGroupUiState.kt | 13 +- .../createNewGroup/CreateNewGroupViewModel.kt | 85 ++++ .../CreateNewGroupViewModel.kt | 76 ---- .../GroupDetailsScreen.kt | 374 +++++++++--------- .../groupDetails/GroupDetailsUiState.kt | 24 ++ .../GroupDetailsViewModel.kt | 31 +- .../GroupsListScreen.kt | 104 ++--- .../GroupsListViewModel.kt | 18 +- .../group_details/GroupDetailsUiState.kt | 15 - .../groups/navigation/GroupNavGraph.kt | 39 +- .../feature/groups/navigation/GroupScreen.kt | 14 +- .../SyncGroupDialogScreen.kt | 79 ++-- .../SyncGroupsDialogUiState.kt | 37 ++ .../SyncGroupsDialogViewModel.kt | 88 +++-- .../SyncGroupsDialogUiState.kt | 28 -- .../groups/src/main/res/values/strings.xml | 9 + 21 files changed, 729 insertions(+), 576 deletions(-) rename feature/groups/src/main/java/com/mifos/feature/groups/{create_new_group => createNewGroup}/CreateNewGroupScreen.kt (77%) rename feature/groups/src/main/java/com/mifos/feature/groups/{create_new_group => createNewGroup}/CreateNewGroupUiState.kt (58%) create mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupViewModel.kt delete mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupViewModel.kt rename feature/groups/src/main/java/com/mifos/feature/groups/{group_details => groupDetails}/GroupDetailsScreen.kt (73%) create mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsUiState.kt rename feature/groups/src/main/java/com/mifos/feature/groups/{group_details => groupDetails}/GroupDetailsViewModel.kt (76%) rename feature/groups/src/main/java/com/mifos/feature/groups/{group_list => groupList}/GroupsListScreen.kt (88%) rename feature/groups/src/main/java/com/mifos/feature/groups/{group_list => groupList}/GroupsListViewModel.kt (65%) delete mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsUiState.kt rename feature/groups/src/main/java/com/mifos/feature/groups/{sync_group_dialog => syncGroupDialog}/SyncGroupDialogScreen.kt (78%) create mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogUiState.kt rename feature/groups/src/main/java/com/mifos/feature/groups/{sync_group_dialog => syncGroupDialog}/SyncGroupsDialogViewModel.kt (92%) delete mode 100644 feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogUiState.kt diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index dd953b74e18..6aa58f3f3c8 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -230,7 +230,7 @@ complexity: ] # Modifying default values 11 to 20 thresholdInFiles: 20 - thresholdInClasses: 20 + thresholdInClasses: 30 thresholdInInterfaces: 20 thresholdInObjects: 20 thresholdInEnums: 20 @@ -785,7 +785,7 @@ style: maxChainedCalls: 5 MaxLineLength: active: true - maxLineLength: 150 + maxLineLength: 250 excludePackageStatements: true excludeImportStatements: true excludeCommentStatements: false @@ -828,7 +828,7 @@ style: active: false ReturnCount: active: true - max: 4 + max: 5 excludedFunctions: - "equals" excludeLabeled: false diff --git a/feature/groups/build.gradle.kts b/feature/groups/build.gradle.kts index 88727e92de7..8488698a395 100644 --- a/feature/groups/build.gradle.kts +++ b/feature/groups/build.gradle.kts @@ -1,3 +1,12 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ plugins { alias(libs.plugins.mifos.android.feature) alias(libs.plugins.mifos.android.library.compose) diff --git a/feature/groups/src/androidTest/java/com/mifos/feature/groups/GroupListScreenTest.kt b/feature/groups/src/androidTest/java/com/mifos/feature/groups/GroupListScreenTest.kt index 5d8e92c1a05..e1ce2a374cf 100644 --- a/feature/groups/src/androidTest/java/com/mifos/feature/groups/GroupListScreenTest.kt +++ b/feature/groups/src/androidTest/java/com/mifos/feature/groups/GroupListScreenTest.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.groups import androidx.activity.ComponentActivity @@ -35,7 +44,7 @@ import com.mifos.core.domain.use_cases.GroupsListPagingDataSource import com.mifos.core.objects.group.Group import com.mifos.core.testing.repository.TestGroupsListRepository import com.mifos.core.testing.repository.sampleGroups -import com.mifos.feature.groups.group_list.GroupsListScreen +import com.mifos.feature.groups.groupList.GroupsListScreen import kotlinx.coroutines.delay import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.runBlocking @@ -43,7 +52,6 @@ import org.junit.Rule import org.junit.Test import kotlin.test.assertEquals - class GroupListScreenTest { @get:Rule @@ -61,7 +69,7 @@ class GroupListScreenTest { ), pagingSourceFactory: () -> PagingSource = { GroupsListPagingDataSource(repository, pageSize) - } + }, ): Pager { return Pager(config = config, pagingSourceFactory = pagingSourceFactory) } @@ -75,7 +83,7 @@ class GroupListScreenTest { ), pagingSourceFactory: () -> PagingSource = { GroupsListPagingDataSource(repository, pageSize) - } + }, ): Pager { return Pager(config = config, pagingSourceFactory = pagingSourceFactory) } @@ -98,9 +106,9 @@ class GroupListScreenTest { source = LoadStates( LoadState.Loading, LoadState.NotLoading(false), - LoadState.NotLoading(false) + LoadState.NotLoading(false), ), - mediator = null + mediator = null, ) assert(loadStates.isNotEmpty()) assertEquals(loadStates.first(), expected) @@ -124,7 +132,6 @@ class GroupListScreenTest { onGroupClick = {}, onSelectItem = {}, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = {}, ) } @@ -139,7 +146,6 @@ class GroupListScreenTest { .onChildren() .onLast() .assertTextContains(composeTestRule.activity.resources.getString(R.string.feature_groups_no_more_groups_available)) - } @Test @@ -153,7 +159,7 @@ class GroupListScreenTest { // Adding some delay to test refresh state lazyPagingItems = pager.flow.onStart { delay(5000) }.collectAsLazyPagingItems() refreshState = rememberSwipeRefreshState( - isRefreshing = lazyPagingItems.loadState.refresh is LoadState.Loading + isRefreshing = lazyPagingItems.loadState.refresh is LoadState.Loading, ) GroupsListScreen( @@ -164,7 +170,6 @@ class GroupListScreenTest { onGroupClick = {}, onSelectItem = {}, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = {}, ) } @@ -177,7 +182,7 @@ class GroupListScreenTest { // Check initial refresh state is true assertEquals(true, refreshState.isRefreshing) - //Perform refresh and check refresh state is true + // Perform refresh and check refresh state is true lazyPagingItems.refresh() assertEquals(true, refreshState.isRefreshing) @@ -201,7 +206,6 @@ class GroupListScreenTest { onGroupClick = {}, onSelectItem = {}, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = {}, ) } @@ -237,7 +241,6 @@ class GroupListScreenTest { repository.setGroupsData(sampleGroups) val pager = createPager() - lateinit var lazyPagingItems: LazyPagingItems lateinit var lazyListState: LazyListState @@ -253,7 +256,6 @@ class GroupListScreenTest { onGroupClick = {}, onSelectItem = {}, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = {}, ) } @@ -271,10 +273,10 @@ class GroupListScreenTest { assertEquals( expected = sampleGroups.take(pageSize), actual = lazyPagingItems.itemSnapshotList.items, - message = "Sample Groups are differ from Snapshot items" + message = "Sample Groups are differ from Snapshot items", ) - //Check paged item is being displayed + // Check paged item is being displayed sampleGroups.take(pageSize).forEach { group -> group.name?.let { composeTestRule @@ -312,7 +314,6 @@ class GroupListScreenTest { onGroupClick = {}, onSelectItem = {}, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = {}, ) } @@ -327,12 +328,12 @@ class GroupListScreenTest { assertEquals( pageSize * 2, - lazyPagingItems.itemSnapshotList.items.size + lazyPagingItems.itemSnapshotList.items.size, ) assertEquals( LoadState.NotLoading(false), - lazyPagingItems.loadState.append + lazyPagingItems.loadState.append, ) composeTestRule.runOnIdle { @@ -346,9 +347,8 @@ class GroupListScreenTest { // end of pagination reached so total item will be (pageSize * 3) + 1 = 31 assertEquals( pageSize * 3 + 1, - lazyListState.layoutInfo.totalItemsCount + lazyListState.layoutInfo.totalItemsCount, ) - } @Test @@ -380,7 +380,6 @@ class GroupListScreenTest { } }, onAddGroupClick = {}, - onSyncClick = {}, resetSelectionMode = { selectedItems.clear() }, @@ -429,14 +428,13 @@ class GroupListScreenTest { } } - // Check item has been selected assert(selectedItems.contains(sampleGroups[4])) - //Check both item has been selected + // Check both item has been selected assertEquals( 2, - selectedItems.size + selectedItems.size, ) composeTestRule.waitForIdle() @@ -456,18 +454,18 @@ class GroupListScreenTest { composeTestRule.waitForIdle() - //check for Contextual TopAppBar Visibility + // check for Contextual TopAppBar Visibility composeTestRule .onNodeWithContentDescription("GroupList::ContextualTopAppBar") .assertIsDisplayed() - //Check reset selection IconButton is visible or not + // Check reset selection IconButton is visible or not composeTestRule .onNodeWithContentDescription("reset selection") .assertIsDisplayed() .assertHasClickAction() - //Check selected text is visible or not + // Check selected text is visible or not composeTestRule .onNodeWithContentDescription("GroupList::ContextualTopAppBar") .assertIsDisplayed() @@ -475,7 +473,7 @@ class GroupListScreenTest { .assertTextContains("${selectedItems.size} selected") .assertIsDisplayed() - //Check Sync Button is visible or not + // Check Sync Button is visible or not composeTestRule .onNodeWithContentDescription("GroupList::ContextualTopAppBar") .assertIsDisplayed() @@ -497,7 +495,7 @@ class GroupListScreenTest { // and selected list only contain 1 item assert(selectedItems.size == 1) - //also check the background color of that item is set to surfaceColor + // also check the background color of that item is set to surfaceColor sampleGroups[2].name?.let { val data = composeTestRule .onNodeWithTag(it) @@ -518,4 +516,4 @@ class GroupListScreenTest { // check selected items list should be empty assert(selectedItems.isEmpty()) } -} \ No newline at end of file +} diff --git a/feature/groups/src/main/AndroidManifest.xml b/feature/groups/src/main/AndroidManifest.xml index a5918e68abc..1dc76da0f7e 100644 --- a/feature/groups/src/main/AndroidManifest.xml +++ b/feature/groups/src/main/AndroidManifest.xml @@ -1,4 +1,13 @@ + \ No newline at end of file diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupScreen.kt similarity index 77% rename from feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupScreen.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupScreen.kt index 222a10e7073..5a71c68ae20 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupScreen.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.create_new_group +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.createNewGroup import android.content.Context import android.widget.Toast @@ -28,8 +37,8 @@ import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.DatePicker import androidx.compose.material3.DatePickerDialog import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SelectableDates +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberDatePickerState @@ -39,6 +48,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -56,6 +66,7 @@ import com.mifos.core.common.utils.Network import com.mifos.core.designsystem.component.MifosCircularProgress import com.mifos.core.designsystem.component.MifosDatePickerTextField import com.mifos.core.designsystem.component.MifosOutlinedTextField +import com.mifos.core.designsystem.component.MifosScaffold import com.mifos.core.designsystem.component.MifosSweetError import com.mifos.core.designsystem.component.MifosTextFieldDropdown import com.mifos.core.designsystem.theme.BluePrimary @@ -72,7 +83,7 @@ import java.util.Locale */ @Composable -fun CreateNewGroupScreen( +internal fun CreateNewGroupScreen( viewModel: CreateNewGroupViewModel = hiltViewModel(), onGroupCreated: (group: SaveResponse?, userStatus: Boolean) -> Unit, ) { @@ -88,47 +99,57 @@ fun CreateNewGroupScreen( invokeGroupCreation = { groupPayload -> viewModel.createGroup(groupPayload) }, - onGroupCreated = { onGroupCreated( it, viewModel.getUserStatus() ) }, - getResponse = { viewModel.getResponse() } + onGroupCreated = { onGroupCreated(it, viewModel.getUserStatus()) }, + getResponse = { viewModel.getResponse() }, ) } @Composable -fun CreateNewGroupScreen( +internal fun CreateNewGroupScreen( uiState: CreateNewGroupUiState, onRetry: () -> Unit, invokeGroupCreation: (GroupPayload) -> Unit, onGroupCreated: (group: SaveResponse?) -> Unit, - getResponse: () -> String + modifier: Modifier = Modifier, + getResponse: () -> String, ) { val context = LocalContext.current + val snackbarHostState = remember { SnackbarHostState() } + + MifosScaffold( + modifier = modifier, + title = stringResource(id = R.string.feature_groups_create_new_group), + snackbarHostState = snackbarHostState, + ) { paddingValues -> + Box( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + ) { + when (uiState) { + is CreateNewGroupUiState.ShowFetchingError -> { + MifosSweetError( + message = uiState.message, + onclick = { onRetry.invoke() }, + ) + } - Box( - modifier = Modifier.fillMaxSize() - ) { - when (uiState) { - is CreateNewGroupUiState.ShowFetchingError -> { - MifosSweetError( - message = uiState.message, - onclick = { onRetry.invoke() } - ) - } - - is CreateNewGroupUiState.ShowGroupCreatedSuccessfully -> { - Toast.makeText(context, "Group " + getResponse(), Toast.LENGTH_LONG) - .show() - onGroupCreated.invoke(uiState.saveResponse) - } + is CreateNewGroupUiState.ShowGroupCreatedSuccessfully -> { + Toast.makeText(context, "Group " + getResponse(), Toast.LENGTH_LONG) + .show() + onGroupCreated.invoke(uiState.saveResponse) + } - is CreateNewGroupUiState.ShowOffices -> { - CreateNewGroupContent( - officeList = uiState.offices, - invokeGroupCreation = invokeGroupCreation - ) - } + is CreateNewGroupUiState.ShowOffices -> { + CreateNewGroupContent( + officeList = uiState.offices, + invokeGroupCreation = invokeGroupCreation, + ) + } - CreateNewGroupUiState.ShowProgressbar -> { - MifosCircularProgress() + CreateNewGroupUiState.ShowProgressbar -> { + MifosCircularProgress() + } } } } @@ -136,8 +157,9 @@ fun CreateNewGroupScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreateNewGroupContent( +private fun CreateNewGroupContent( officeList: List, + modifier: Modifier = Modifier, invokeGroupCreation: (GroupPayload) -> Unit, ) { var groupName by rememberSaveable { @@ -172,7 +194,7 @@ fun CreateNewGroupContent( override fun isSelectableDate(utcTimeMillis: Long): Boolean { return utcTimeMillis >= System.currentTimeMillis() } - } + }, ) val sumittedDatePickerState = rememberDatePickerState( initialSelectedDateMillis = submittedOnDate, @@ -180,7 +202,7 @@ fun CreateNewGroupContent( override fun isSelectableDate(utcTimeMillis: Long): Boolean { return utcTimeMillis >= System.currentTimeMillis() } - } + }, ) if (activationDatePicker || submitDatePicker) { @@ -203,7 +225,7 @@ fun CreateNewGroupContent( } submitDatePicker = false activationDatePicker = false - } + }, ) { Text(stringResource(id = R.string.feature_groups_select_date)) } }, dismissButton = { @@ -211,36 +233,26 @@ fun CreateNewGroupContent( onClick = { activationDatePicker = false submitDatePicker = false - } + }, ) { Text(stringResource(id = R.string.feature_groups_dismiss)) } - } - ) - { + }, + ) { DatePicker(state = if (submitDatePicker) sumittedDatePickerState else activateDatePickerState) - } } Column( - modifier = Modifier + modifier = modifier .fillMaxSize() - .verticalScroll(scrollState) + .verticalScroll(scrollState), ) { Spacer(modifier = Modifier.height(16.dp)) - Text( - style = MaterialTheme.typography.headlineSmall, - text = stringResource(id = R.string.feature_groups_create_new_group), - modifier = Modifier.padding(start = 16.dp) - ) - - Spacer(modifier = Modifier.height(16.dp)) - MifosOutlinedTextField( value = groupName, onValueChange = { groupName = it }, label = stringResource(id = R.string.feature_groups_name), - error = null + error = null, ) Spacer(modifier = Modifier.height(16.dp)) @@ -255,23 +267,22 @@ fun CreateNewGroupContent( officeList[index].id?.let { officeId = it } - }, label = R.string.feature_groups_office_name_mandatory, options = officeList.map { it.name.toString() }, - readOnly = true + readOnly = true, ) Spacer(modifier = Modifier.height(16.dp)) MifosDatePickerTextField( value = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()).format( - submittedOnDate + submittedOnDate, ), label = R.string.feature_groups_submit_date, openDatePicker = { submitDatePicker = true - } + }, ) Spacer(modifier = Modifier.height(16.dp)) @@ -280,7 +291,7 @@ fun CreateNewGroupContent( value = externalId, onValueChange = { externalId = it }, label = stringResource(id = R.string.feature_groups_external_id), - error = null + error = null, ) Spacer(modifier = Modifier.height(16.dp)) @@ -291,10 +302,10 @@ fun CreateNewGroupContent( Checkbox( modifier = Modifier.padding(start = 8.dp), colors = CheckboxDefaults.colors( - if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, ), checked = isActive, - onCheckedChange = { isActive = !isActive } + onCheckedChange = { isActive = !isActive }, ) Text(text = stringResource(id = R.string.feature_groups_active)) } @@ -304,22 +315,22 @@ fun CreateNewGroupContent( enter = slideInVertically { with(density) { -40.dp.roundToPx() } } + expandVertically( - expandFrom = Alignment.Top + expandFrom = Alignment.Top, ) + fadeIn( - initialAlpha = 0.3f + initialAlpha = 0.3f, ), - exit = slideOutVertically() + shrinkVertically() + fadeOut() + exit = slideOutVertically() + shrinkVertically() + fadeOut(), ) { Spacer(modifier = Modifier.height(16.dp)) MifosDatePickerTextField( value = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()).format( - activationDate + activationDate, ), label = R.string.feature_groups_activation_date, openDatePicker = { activationDatePicker = true - } + }, ) } @@ -331,23 +342,27 @@ fun CreateNewGroupContent( .padding(horizontal = 16.dp) .heightIn(46.dp), colors = ButtonDefaults.buttonColors( - containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, ), onClick = { if (validateFields(groupName, selectedOffice, context)) { if (Network.isOnline(context)) { - val activationDateInString = if (isActive) SimpleDateFormat( - "dd MMMM yyyy", - Locale.getDefault() - ).format( - activationDate - ) else null + val activationDateInString = if (isActive) { + SimpleDateFormat( + "dd MMMM yyyy", + Locale.getDefault(), + ).format( + activationDate, + ) + } else { + null + } val submittedOnDateInString = SimpleDateFormat( "dd MMMM yyyy", - Locale.getDefault() + Locale.getDefault(), ).format( - submittedOnDate + submittedOnDate, ) invokeGroupCreation.invoke( @@ -359,30 +374,31 @@ fun CreateNewGroupContent( submittedOnDate = submittedOnDateInString, officeId = officeId, dateFormat = "dd MMMM yyyy", - locale = "en" - ) + locale = "en", + ), ) } else { Toast.makeText( context, context.resources.getString(R.string.feature_groups_error_not_connected_internet), - Toast.LENGTH_SHORT + Toast.LENGTH_SHORT, ).show() } } - }) { + }, + ) { Text(text = stringResource(id = R.string.feature_groups_submit)) } } } -fun validateFields(groupName: String, officeName: String, context: Context): Boolean { +private fun validateFields(groupName: String, officeName: String, context: Context): Boolean { return when { groupName.isEmpty() -> { Toast.makeText( context, context.resources.getString(R.string.feature_groups_error_group_name_cannot_be_empty), - Toast.LENGTH_SHORT + Toast.LENGTH_SHORT, ).show() return false } @@ -391,7 +407,7 @@ fun validateFields(groupName: String, officeName: String, context: Context): Boo Toast.makeText( context, context.resources.getString(R.string.feature_groups_error_group_name_must_be_at_least_four_characters_long), - Toast.LENGTH_SHORT + Toast.LENGTH_SHORT, ).show() return false } @@ -400,7 +416,7 @@ fun validateFields(groupName: String, officeName: String, context: Context): Boo Toast.makeText( context, context.resources.getString(R.string.feature_groups_error_group_name_should_contain_only_alphabets), - Toast.LENGTH_SHORT + Toast.LENGTH_SHORT, ).show() return false } @@ -409,7 +425,7 @@ fun validateFields(groupName: String, officeName: String, context: Context): Boo Toast.makeText( context, context.resources.getString(R.string.feature_groups_error_office_not_selected), - Toast.LENGTH_SHORT + Toast.LENGTH_SHORT, ).show() return false } @@ -418,7 +434,7 @@ fun validateFields(groupName: String, officeName: String, context: Context): Boo } } -class CreateNewGroupScreenPreviewProvider : PreviewParameterProvider { +private class CreateNewGroupScreenPreviewProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( CreateNewGroupUiState.ShowProgressbar, @@ -430,16 +446,15 @@ class CreateNewGroupScreenPreviewProvider : PreviewParameterProvider - }, - getResponse = { "" } + getResponse = { "" }, ) } diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupUiState.kt b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupUiState.kt similarity index 58% rename from feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupUiState.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupUiState.kt index 1725c952593..3b9bbe9f53f 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupUiState.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupUiState.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.create_new_group +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.createNewGroup import com.mifos.core.objects.organisation.Office import com.mifos.core.objects.response.SaveResponse @@ -16,4 +25,4 @@ sealed class CreateNewGroupUiState { data class ShowGroupCreatedSuccessfully(val saveResponse: SaveResponse) : CreateNewGroupUiState() -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupViewModel.kt b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupViewModel.kt new file mode 100644 index 00000000000..7fb3e78d2f0 --- /dev/null +++ b/feature/groups/src/main/java/com/mifos/feature/groups/createNewGroup/CreateNewGroupViewModel.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.createNewGroup + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mifos.core.common.utils.Resource +import com.mifos.core.datastore.PrefManager +import com.mifos.core.domain.use_cases.CreateNewGroupUseCase +import com.mifos.core.domain.use_cases.GetGroupOfficesUseCase +import com.mifos.core.objects.group.GroupPayload +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +/** + * Created by Aditya Gupta on 10/08/23. + */ +@HiltViewModel +class CreateNewGroupViewModel @Inject constructor( + private val getGroupOfficesUseCase: GetGroupOfficesUseCase, + private val createNewGroupUseCase: CreateNewGroupUseCase, + private val prefManager: PrefManager, +) : ViewModel() { + + private val _createNewGroupUiState = MutableStateFlow( + CreateNewGroupUiState.ShowProgressbar, + ) + val createNewGroupUiState: StateFlow + get() = _createNewGroupUiState + + fun getUserStatus() = prefManager.userStatus + + fun getResponse(): String { + return when (prefManager.userStatus) { + false -> "created successfully" + true -> "Saved into DB Successfully" + } + } + + fun loadOffices() = viewModelScope.launch { + getGroupOfficesUseCase().collect { result -> + when (result) { + is Resource.Loading -> + _createNewGroupUiState.value = + CreateNewGroupUiState.ShowProgressbar + + is Resource.Error -> + _createNewGroupUiState.value = + CreateNewGroupUiState.ShowFetchingError(result.message.toString()) + + is Resource.Success -> + _createNewGroupUiState.value = + CreateNewGroupUiState.ShowOffices(result.data ?: emptyList()) + } + } + } + + fun createGroup(groupPayload: GroupPayload) = viewModelScope.launch { + createNewGroupUseCase(groupPayload).collect { result -> + when (result) { + is Resource.Error -> + _createNewGroupUiState.value = + CreateNewGroupUiState.ShowFetchingError(result.message.toString()) + + is Resource.Loading -> + _createNewGroupUiState.value = + CreateNewGroupUiState.ShowProgressbar + + is Resource.Success -> + _createNewGroupUiState.value = + result.data?.let { CreateNewGroupUiState.ShowGroupCreatedSuccessfully(it) }!! + } + } + } +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupViewModel.kt b/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupViewModel.kt deleted file mode 100644 index 00b1a6841f7..00000000000 --- a/feature/groups/src/main/java/com/mifos/feature/groups/create_new_group/CreateNewGroupViewModel.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.mifos.feature.groups.create_new_group - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.mifos.core.common.utils.Resource -import com.mifos.core.data.repository.CreateNewGroupRepository -import com.mifos.core.datastore.PrefManager -import com.mifos.core.domain.use_cases.GetGroupOfficesUseCase -import com.mifos.core.domain.use_cases.CreateNewGroupUseCase -import com.mifos.core.objects.group.GroupPayload -import com.mifos.core.objects.organisation.Office -import com.mifos.core.objects.response.SaveResponse -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import rx.Subscriber -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers -import javax.inject.Inject - -/** - * Created by Aditya Gupta on 10/08/23. - */ -@HiltViewModel -class CreateNewGroupViewModel @Inject constructor( - private val getGroupOfficesUseCase: GetGroupOfficesUseCase, - private val createNewGroupUseCase: CreateNewGroupUseCase, - private val prefManager: PrefManager -) : ViewModel() { - - private val _createNewGroupUiState = MutableStateFlow( - CreateNewGroupUiState.ShowProgressbar - ) - val createNewGroupUiState: StateFlow - get() = _createNewGroupUiState - - fun getUserStatus ( ) = prefManager.userStatus - - fun getResponse() : String { - return when(prefManager.userStatus){ - false -> "created successfully" - true -> "Saved into DB Successfully" - } - } - - fun loadOffices() = viewModelScope.launch { - getGroupOfficesUseCase().collect { result -> - when (result) { - is Resource.Loading -> _createNewGroupUiState.value = - CreateNewGroupUiState.ShowProgressbar - - is Resource.Error -> _createNewGroupUiState.value = - CreateNewGroupUiState.ShowFetchingError(result.message.toString()) - - is Resource.Success -> _createNewGroupUiState.value = - CreateNewGroupUiState.ShowOffices(result.data ?: emptyList()) - } - } - } - - fun createGroup(groupPayload: GroupPayload) = viewModelScope.launch { - createNewGroupUseCase(groupPayload).collect { result -> - when (result) { - is Resource.Error -> _createNewGroupUiState.value = - CreateNewGroupUiState.ShowFetchingError(result.message.toString()) - - is Resource.Loading -> _createNewGroupUiState.value = - CreateNewGroupUiState.ShowProgressbar - - is Resource.Success -> _createNewGroupUiState.value = - result.data?.let { CreateNewGroupUiState.ShowGroupCreatedSuccessfully(it) }!! - } - } - } -} \ No newline at end of file diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsScreen.kt similarity index 73% rename from feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsScreen.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsScreen.kt index 042c894483e..e10a8c1e93e 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsScreen.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.group_details +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.groupDetails import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.LinearOutSlowInEasing @@ -59,7 +68,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import com.mifos.core.common.utils.Constants import com.mifos.core.common.utils.Utils import com.mifos.core.designsystem.component.MifosCircularProgress @@ -81,22 +89,22 @@ import com.mifos.core.objects.group.Group import com.mifos.feature.groups.R @Composable -fun GroupDetailsScreen( +internal fun GroupDetailsScreen( onBackPressed: () -> Unit, addLoanAccount: (Int) -> Unit, - addSavingsAccount: (groupId : Int, clientId : Int, isGroupAccount : Boolean) -> Unit, + addSavingsAccount: (groupId: Int, clientId: Int, isGroupAccount: Boolean) -> Unit, documents: (Int, String) -> Unit, groupClients: (List) -> Unit, moreGroupInfo: (String, Int) -> Unit, notes: (Int, String) -> Unit, loanAccountSelected: (Int) -> Unit, savingsAccountSelected: (Int, DepositType) -> Unit, - activateGroup: (Int, String) -> Unit + activateGroup: (Int, String) -> Unit, + viewModel: GroupDetailsViewModel = hiltViewModel(), ) { - val viewModel: GroupDetailsViewModel = hiltViewModel() val groupId by viewModel.groupId.collectAsStateWithLifecycle() val state by viewModel.groupDetailsUiState.collectAsStateWithLifecycle() - val loanAccounts by viewModel.loanAccount.collectAsStateWithLifecycle() + val loanAccounts by viewModel.loanAccounts.collectAsStateWithLifecycle() val savingsAccounts by viewModel.savingsAccounts.collectAsStateWithLifecycle() val groupAssociateClients by viewModel.groupAssociateClients.collectAsStateWithLifecycle() var groupClientEnable by remember { mutableStateOf(false) } @@ -112,7 +120,6 @@ fun GroupDetailsScreen( } GroupDetailsScreen( - groupId = groupId, state = state, loanAccounts = loanAccounts, savingsAccounts = savingsAccounts, @@ -122,7 +129,7 @@ fun GroupDetailsScreen( onMenuClick = { menu -> when (menu) { MenuItems.ADD_LOAN_ACCOUNT -> addLoanAccount(groupId) - MenuItems.ADD_SAVINGS_ACCOUNT -> addSavingsAccount(groupId, 0,true ) + MenuItems.ADD_SAVINGS_ACCOUNT -> addSavingsAccount(groupId, 0, true) MenuItems.DOCUMENTS -> documents(groupId, Constants.ENTITY_TYPE_GROUPS) MenuItems.GROUP_CLIENTS -> { groupClientEnable = true @@ -133,14 +140,12 @@ fun GroupDetailsScreen( MenuItems.NOTES -> notes(groupId, Constants.ENTITY_TYPE_GROUPS) } }, - activateGroup = { activateGroup(groupId, Constants.ACTIVATE_GROUP) } + activateGroup = { activateGroup(groupId, Constants.ACTIVATE_GROUP) }, ) - } @Composable -fun GroupDetailsScreen( - groupId: Int, +internal fun GroupDetailsScreen( state: GroupDetailsUiState, loanAccounts: List, savingsAccounts: List, @@ -148,14 +153,15 @@ fun GroupDetailsScreen( savingsAccountSelected: (Int, DepositType) -> Unit, onBackPressed: () -> Unit, onMenuClick: (MenuItems) -> Unit, - activateGroup: () -> Unit + modifier: Modifier = Modifier, + activateGroup: () -> Unit, ) { - val snackbarHostState = remember { SnackbarHostState() } var showMenu by remember { mutableStateOf(false) } var groupActive by remember { mutableStateOf(true) } MifosScaffold( + modifier = modifier, icon = MifosIcons.arrowBack, title = stringResource(id = R.string.feature_groups_group), onBackPressed = onBackPressed, @@ -166,7 +172,7 @@ fun GroupDetailsScreen( DropdownMenu( modifier = Modifier.background(White), expanded = showMenu, - onDismissRequest = { showMenu = false } + onDismissRequest = { showMenu = false }, ) { MifosMenuDropDownItem(option = stringResource(id = R.string.feature_groups_add_loan_account)) { onMenuClick(MenuItems.ADD_LOAN_ACCOUNT) @@ -204,22 +210,20 @@ fun GroupDetailsScreen( .heightIn(44.dp) .padding(start = 16.dp, end = 16.dp), colors = ButtonDefaults.buttonColors( - containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary - ) + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, + ), ) { Text( text = stringResource(id = R.string.feature_groups_activate_group), - fontSize = 16.sp + fontSize = 16.sp, ) } - } - } + }, ) { paddingValue -> Column(modifier = Modifier.padding(paddingValue)) { when (state) { is GroupDetailsUiState.Error -> MifosSweetError(message = stringResource(id = state.message)) { - } is GroupDetailsUiState.Loading -> MifosCircularProgress() @@ -233,14 +237,12 @@ fun GroupDetailsScreen( savingsAccountSelected = savingsAccountSelected, activateGroup = { groupActive = false - } + }, ) } } } - } - } @Composable @@ -250,12 +252,13 @@ fun GroupDetailsContent( savingsAccounts: List, loanAccountSelected: (Int) -> Unit, savingsAccountSelected: (Int, DepositType) -> Unit, - activateGroup: () -> Unit + modifier: Modifier = Modifier, + activateGroup: () -> Unit, ) { if (group.active == false) { activateGroup() } - Column(modifier = Modifier) { + Column(modifier = modifier) { group.name?.let { Text( modifier = Modifier @@ -267,33 +270,33 @@ fun GroupDetailsContent( fontWeight = FontWeight.SemiBold, ), color = Black, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } group.externalId?.let { MifosCenterDetailsText( icon = Icons.Outlined.Numbers, field = stringResource(id = R.string.feature_groups_external_id), - value = it + value = it, ) } MifosCenterDetailsText( icon = Icons.Outlined.DateRange, field = stringResource(id = R.string.feature_groups_activation_date), - value = Utils.getStringOfDate(group.activationDate) + value = Utils.getStringOfDate(group.activationDate), ) group.officeName?.let { MifosCenterDetailsText( icon = Icons.Outlined.HomeWork, field = stringResource(id = R.string.feature_groups_office), - value = it + value = it, ) } group.staffName?.let { MifosCenterDetailsText( icon = Icons.Outlined.PersonOutline, field = stringResource(id = R.string.feature_groups_staff), - value = it + value = it, ) } Spacer(modifier = Modifier.height(16.dp)) @@ -304,10 +307,10 @@ fun GroupDetailsContent( style = TextStyle( fontSize = 21.sp, fontWeight = FontWeight.Medium, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) HorizontalDivider(modifier = Modifier.padding(start = 16.dp, end = 16.dp)) } @@ -315,32 +318,37 @@ fun GroupDetailsContent( MifosLoanAccountExpendableCard( stringResource(id = R.string.feature_groups_loan_account), loanAccounts, - loanAccountSelected = loanAccountSelected + loanAccountSelected = loanAccountSelected, ) } if (savingsAccounts.isNotEmpty()) { MifosSavingsAccountExpendableCard( stringResource(id = R.string.feature_groups_savings_account), savingsAccounts, - savingsAccountSelected = savingsAccountSelected + savingsAccountSelected = savingsAccountSelected, ) } } } @Composable -fun MifosCenterDetailsText(icon: ImageVector, field: String, value: String) { +fun MifosCenterDetailsText( + icon: ImageVector, + field: String, + value: String, + modifier: Modifier = Modifier, +) { Row( - modifier = Modifier + modifier = modifier .padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp) .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Icon( modifier = Modifier.size(18.dp), imageVector = icon, contentDescription = null, - tint = DarkGray + tint = DarkGray, ) Text( modifier = Modifier @@ -350,10 +358,10 @@ fun MifosCenterDetailsText(icon: ImageVector, field: String, value: String) { style = TextStyle( fontSize = 18.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) Text( @@ -361,40 +369,39 @@ fun MifosCenterDetailsText(icon: ImageVector, field: String, value: String) { style = TextStyle( fontSize = 18.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = DarkGray, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } } - @Composable fun MifosLoanAccountExpendableCard( accountType: String, loanAccounts: List, - loanAccountSelected: (Int) -> Unit + modifier: Modifier = Modifier, + loanAccountSelected: (Int) -> Unit, ) { - var expendableState by remember { mutableStateOf(false) } val rotateState by animateFloatAsState( targetValue = if (expendableState) 180f else 0f, - label = "" + label = "", ) Card( - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(8.dp) .animateContentSize( animationSpec = tween( durationMillis = 300, - easing = LinearOutSlowInEasing - ) + easing = LinearOutSlowInEasing, + ), ), shape = RoundedCornerShape(22.dp), - colors = CardDefaults.cardColors(BlueSecondary) + colors = CardDefaults.cardColors(BlueSecondary), ) { Column( modifier = Modifier @@ -402,7 +409,7 @@ fun MifosLoanAccountExpendableCard( .padding(10.dp), ) { Row( - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( modifier = Modifier @@ -412,94 +419,102 @@ fun MifosLoanAccountExpendableCard( style = TextStyle( fontSize = 18.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) IconButton( modifier = Modifier .size(24.dp), - onClick = { expendableState = !expendableState }) { + onClick = { expendableState = !expendableState }, + ) { Icon( modifier = Modifier.rotate(rotateState), - imageVector = Icons.Default.KeyboardArrowDown, contentDescription = null + imageVector = Icons.Default.KeyboardArrowDown, + contentDescription = null, ) } } if (expendableState) { - Spacer(modifier = Modifier.height(10.dp)) - MifosLoanAccountsLazyColumn(loanAccounts, loanAccountSelected) + MifosLoanAccountsLazyColumn( + loanAccounts = loanAccounts, + loanAccountSelected = loanAccountSelected, + ) } } } } - @Composable fun MifosLoanAccountsLazyColumn( loanAccounts: List, - loanAccountSelected: (Int) -> Unit + modifier: Modifier = Modifier, + loanAccountSelected: (Int) -> Unit, ) { - Card( - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(8.dp), shape = RoundedCornerShape(22.dp), - colors = CardDefaults.cardColors(White) + colors = CardDefaults.cardColors(White), ) { LazyColumn( modifier = Modifier .height((loanAccounts.size * 52).dp) - .padding(6.dp) + .padding(6.dp), ) { items(loanAccounts) { loanAccount -> Row( modifier = Modifier .padding(5.dp) - .clickable(onClick = { - loanAccount.id?.let { - loanAccountSelected( - it - ) - } - }), - verticalAlignment = Alignment.CenterVertically - ) { - Canvas(modifier = Modifier - .size(20.dp) - .padding(4.dp), onDraw = { - drawCircle( - color = when { - loanAccount.status?.active == true -> { - Color.Green - } - - loanAccount.status?.waitingForDisbursal == true -> { - Color.Blue - } - - loanAccount.status?.pendingApproval == true -> { - Color.Yellow - } - - loanAccount.status?.active == true && loanAccount.inArrears == true -> { - Color.Red - } - - else -> { - Color.DarkGray + .clickable( + onClick = { + loanAccount.id?.let { + loanAccountSelected( + it, + ) } - } - ) - }) + }, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + Canvas( + modifier = Modifier + .size(20.dp) + .padding(4.dp), + onDraw = { + drawCircle( + color = when { + loanAccount.status?.active == true -> { + Color.Green + } + + loanAccount.status?.waitingForDisbursal == true -> { + Color.Blue + } + + loanAccount.status?.pendingApproval == true -> { + Color.Yellow + } + + loanAccount.status?.active == true && loanAccount.inArrears == true -> { + Color.Red + } + + else -> { + Color.DarkGray + } + }, + ) + }, + ) Column( modifier = Modifier .weight(1f) - .padding(start = 4.dp) + .padding(start = 4.dp), ) { loanAccount.productName?.let { Text( @@ -507,10 +522,10 @@ fun MifosLoanAccountsLazyColumn( style = TextStyle( fontSize = 16.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } Text( @@ -518,10 +533,10 @@ fun MifosLoanAccountsLazyColumn( style = TextStyle( fontSize = 14.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = DarkGray, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } loanAccount.productId?.let { @@ -530,10 +545,10 @@ fun MifosLoanAccountsLazyColumn( style = TextStyle( fontSize = 16.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } } @@ -544,16 +559,15 @@ fun MifosLoanAccountsLazyColumn( } @Composable -fun MifosSavingsAccountExpendableCard( +private fun MifosSavingsAccountExpendableCard( accountType: String, savingsAccount: List, - savingsAccountSelected: (Int, DepositType) -> Unit + savingsAccountSelected: (Int, DepositType) -> Unit, ) { - var expendableState by remember { mutableStateOf(false) } val rotateState by animateFloatAsState( targetValue = if (expendableState) 180f else 0f, - label = "" + label = "", ) Card( @@ -563,11 +577,11 @@ fun MifosSavingsAccountExpendableCard( .animateContentSize( animationSpec = tween( durationMillis = 300, - easing = LinearOutSlowInEasing - ) + easing = LinearOutSlowInEasing, + ), ), shape = RoundedCornerShape(22.dp), - colors = CardDefaults.cardColors(BlueSecondary) + colors = CardDefaults.cardColors(BlueSecondary), ) { Column( modifier = Modifier @@ -575,7 +589,7 @@ fun MifosSavingsAccountExpendableCard( .padding(10.dp), ) { Row( - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( modifier = Modifier @@ -585,91 +599,101 @@ fun MifosSavingsAccountExpendableCard( style = TextStyle( fontSize = 18.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) IconButton( modifier = Modifier .size(24.dp), - onClick = { expendableState = !expendableState }) { + onClick = { expendableState = !expendableState }, + ) { Icon( modifier = Modifier.rotate(rotateState), - imageVector = Icons.Default.KeyboardArrowDown, contentDescription = null + imageVector = Icons.Default.KeyboardArrowDown, + contentDescription = null, ) } } if (expendableState) { - Spacer(modifier = Modifier.height(10.dp)) - MifosSavingsAccountsLazyColumn(savingsAccount, savingsAccountSelected) + MifosSavingsAccountsLazyColumn( + savingsAccounts = savingsAccount, + savingsAccountSelected = savingsAccountSelected, + ) } } } } @Composable -fun MifosSavingsAccountsLazyColumn( +private fun MifosSavingsAccountsLazyColumn( savingsAccounts: List, - savingsAccountSelected: (Int, DepositType) -> Unit + modifier: Modifier = Modifier, + savingsAccountSelected: (Int, DepositType) -> Unit, ) { - Card( - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(8.dp), shape = RoundedCornerShape(22.dp), - colors = CardDefaults.cardColors(White) + colors = CardDefaults.cardColors(White), ) { LazyColumn( modifier = Modifier .height((savingsAccounts.size * 50).dp) - .padding(6.dp) + .padding(6.dp), ) { items(savingsAccounts) { savingsAccount -> Row( modifier = Modifier .padding(5.dp) - .clickable(onClick = { - savingsAccount.id?.let { - savingsAccount.depositType?.let { it1 -> - savingsAccountSelected( - it, it1 - ) + .clickable( + onClick = { + savingsAccount.id?.let { + savingsAccount.depositType?.let { it1 -> + savingsAccountSelected( + it, + it1, + ) + } } - } - }), - verticalAlignment = Alignment.CenterVertically + }, + ), + verticalAlignment = Alignment.CenterVertically, ) { - Canvas(modifier = Modifier - .size(20.dp) - .padding(4.dp), onDraw = { - drawCircle( - color = when { - savingsAccount.status?.active == true -> { - Color.Green - } - - savingsAccount.status?.approved == true -> { - Color.Blue - } - - savingsAccount.status?.submittedAndPendingApproval == true -> { - Color.Yellow - } - - else -> { - Color.DarkGray - } - } - ) - }) + Canvas( + modifier = Modifier + .size(20.dp) + .padding(4.dp), + onDraw = { + drawCircle( + color = when { + savingsAccount.status?.active == true -> { + Color.Green + } + + savingsAccount.status?.approved == true -> { + Color.Blue + } + + savingsAccount.status?.submittedAndPendingApproval == true -> { + Color.Yellow + } + + else -> { + Color.DarkGray + } + }, + ) + }, + ) Column( modifier = Modifier .weight(1f) - .padding(start = 4.dp) + .padding(start = 4.dp), ) { savingsAccount.productName?.let { Text( @@ -677,10 +701,10 @@ fun MifosSavingsAccountsLazyColumn( style = TextStyle( fontSize = 16.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } Text( @@ -688,10 +712,10 @@ fun MifosSavingsAccountsLazyColumn( style = TextStyle( fontSize = 14.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = DarkGray, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } savingsAccount.productId?.let { @@ -700,10 +724,10 @@ fun MifosSavingsAccountsLazyColumn( style = TextStyle( fontSize = 16.sp, fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal + fontStyle = FontStyle.Normal, ), color = Black, - textAlign = TextAlign.Start + textAlign = TextAlign.Start, ) } } @@ -713,25 +737,23 @@ fun MifosSavingsAccountsLazyColumn( } } -class GroupDetailsUiStateProvider : PreviewParameterProvider { +private class GroupDetailsUiStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( GroupDetailsUiState.Loading, GroupDetailsUiState.Error(R.string.feature_groups_failed_to_fetch_group_and_account), GroupDetailsUiState.ShowGroup(group = Group(name = "Group", active = true)), - GroupDetailsUiState.ShowGroup(group = Group(name = "Group", active = false)) + GroupDetailsUiState.ShowGroup(group = Group(name = "Group", active = false)), ) } - @Preview @Composable private fun GroupDetailsScreenPreview( - @PreviewParameter(GroupDetailsUiStateProvider::class) state: GroupDetailsUiState + @PreviewParameter(GroupDetailsUiStateProvider::class) state: GroupDetailsUiState, ) { GroupDetailsScreen( - groupId = 1, state = state, onBackPressed = {}, onMenuClick = {}, @@ -740,7 +762,7 @@ private fun GroupDetailsScreenPreview( loanAccountSelected = {}, savingsAccountSelected = { _, _ -> }, - activateGroup = {} + activateGroup = {}, ) } @@ -750,13 +772,13 @@ enum class MenuItems { DOCUMENTS, GROUP_CLIENTS, MORE_GROUP_INFO, - NOTES + NOTES, } -val sampleLoanAccountList = List(10) { +private val sampleLoanAccountList = List(10) { LoanAccount(id = it, productName = "Product $it") } -val sampleSavingAccountList = List(10) { +private val sampleSavingAccountList = List(10) { SavingsAccount(id = it, productName = "Product $it") -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsUiState.kt b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsUiState.kt new file mode 100644 index 00000000000..1021599f574 --- /dev/null +++ b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsUiState.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.groupDetails + +import com.mifos.core.objects.group.Group + +/** + * Created by Aditya Gupta on 06/08/23. + */ +sealed class GroupDetailsUiState { + + data object Loading : GroupDetailsUiState() + + data class Error(val message: Int) : GroupDetailsUiState() + + data class ShowGroup(val group: Group) : GroupDetailsUiState() +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsViewModel.kt b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsViewModel.kt similarity index 76% rename from feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsViewModel.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsViewModel.kt index b7b3fb53df0..ddd18d6b420 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsViewModel.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/groupDetails/GroupDetailsViewModel.kt @@ -1,6 +1,14 @@ -package com.mifos.feature.groups.group_details +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.groupDetails -import androidx.compose.ui.unit.Constraints import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -23,7 +31,7 @@ import javax.inject.Inject class GroupDetailsViewModel @Inject constructor( private val getGroupDetailsUseCase: GetGroupDetailsUseCase, private val getGroupAssociateClientsUseCase: GetGroupAssociateClientsUseCase, - private val savedStateHandle: SavedStateHandle + private val savedStateHandle: SavedStateHandle, ) : ViewModel() { val groupId = savedStateHandle.getStateFlow(key = Constants.GROUP_ID, initialValue = 0) @@ -33,8 +41,7 @@ class GroupDetailsViewModel @Inject constructor( val groupDetailsUiState = _groupDetailsUiState.asStateFlow() private val _loanAccounts = MutableStateFlow>(emptyList()) - val loanAccount = _loanAccounts.asStateFlow() - + val loanAccounts = _loanAccounts.asStateFlow() private val _savingsAccounts = MutableStateFlow>(emptyList()) val savingsAccounts = _savingsAccounts.asStateFlow() @@ -42,12 +49,12 @@ class GroupDetailsViewModel @Inject constructor( private val _groupAssociateClients = MutableStateFlow>(emptyList()) val groupAssociateClients = _groupAssociateClients.asStateFlow() - fun getGroupDetails(groupId: Int) = viewModelScope.launch { getGroupDetailsUseCase(groupId).collect { result -> when (result) { - is Resource.Error -> _groupDetailsUiState.value = - GroupDetailsUiState.Error(R.string.feature_groups_failed_to_fetch_group_and_account) + is Resource.Error -> + _groupDetailsUiState.value = + GroupDetailsUiState.Error(R.string.feature_groups_failed_to_fetch_group_and_account) is Resource.Loading -> _groupDetailsUiState.value = GroupDetailsUiState.Loading @@ -65,13 +72,13 @@ class GroupDetailsViewModel @Inject constructor( fun getGroupAssociateClients(groupId: Int) = viewModelScope.launch { getGroupAssociateClientsUseCase(groupId).collect { result -> when (result) { - is Resource.Error -> _groupDetailsUiState.value = - GroupDetailsUiState.Error(R.string.feature_groups_failed_to_load_client) + is Resource.Error -> + _groupDetailsUiState.value = + GroupDetailsUiState.Error(R.string.feature_groups_failed_to_load_client) is Resource.Loading -> Unit is Resource.Success -> _groupAssociateClients.value = result.data ?: emptyList() } } } - -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListScreen.kt similarity index 88% rename from feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListScreen.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListScreen.kt index 0150efde996..3971dda8ca7 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListScreen.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.group_list +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.groupList import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility @@ -80,21 +89,21 @@ import com.mifos.core.ui.util.GroupListItemPreviewParameterProvider import com.mifos.core.ui.util.GroupListLoadingPreviewParameterProvider import com.mifos.core.ui.util.GroupListSuccessPreviewParameterProvider import com.mifos.feature.groups.R -import com.mifos.feature.groups.sync_group_dialog.SyncGroupDialogScreen +import com.mifos.feature.groups.syncGroupDialog.SyncGroupDialogScreen import kotlinx.coroutines.flow.Flow @Composable -fun GroupsListRoute( +internal fun GroupsListRoute( paddingValues: PaddingValues, onAddGroupClick: () -> Unit, - onGroupClick: (groupId : Int) -> Unit, - viewModel: GroupsListViewModel = hiltViewModel() + onGroupClick: (groupId: Int) -> Unit, + viewModel: GroupsListViewModel = hiltViewModel(), ) { val data = viewModel.data.collectAsLazyPagingItems() val lazyListState = rememberLazyListState() val swipeRefreshState = rememberSwipeRefreshState( - isRefreshing = data.loadState.refresh is LoadState.Loading + isRefreshing = data.loadState.refresh is LoadState.Loading, ) val selectedItems = remember { @@ -102,7 +111,7 @@ fun GroupsListRoute( } BackHandler( - enabled = selectedItems.isNotEmpty() + enabled = selectedItems.isNotEmpty(), ) { selectedItems.clear() } @@ -132,23 +141,23 @@ fun GroupsListRoute( @Composable fun GroupsListScreen( - modifier: Modifier = Modifier, lazyListState: LazyListState, swipeRefreshState: SwipeRefreshState, selectedItems: List, data: LazyPagingItems, onAddGroupClick: () -> Unit, - onGroupClick: (groupId : Int) -> Unit, + onGroupClick: (groupId: Int) -> Unit, onSelectItem: (Group) -> Unit, + modifier: Modifier = Modifier, resetSelectionMode: () -> Unit, ) { var syncGroups by rememberSaveable { mutableStateOf(false) } - if (syncGroups){ + if (syncGroups) { SyncGroupDialogScreen( dismiss = { syncGroups = false }, hide = { // TODO implement hide - } + }, ) } @@ -184,7 +193,7 @@ fun GroupsListScreen( ) Text(text = stringResource(id = R.string.feature_groups_sync)) } - } + }, ) } }, @@ -194,14 +203,14 @@ fun GroupsListScreen( contentDescription = "SwipeRefresh::GroupList" }, state = swipeRefreshState, - onRefresh = { data.refresh() } + onRefresh = { data.refresh() }, ) { LazyColumn( modifier = Modifier .fillMaxSize() .padding(paddingValues), state = lazyListState, - verticalArrangement = if (data.itemCount < 1) Arrangement.Center else Arrangement.Top + verticalArrangement = if (data.itemCount < 1) Arrangement.Center else Arrangement.Top, ) { refreshState(data) @@ -210,7 +219,7 @@ fun GroupsListScreen( isInSelectionMode = selectedItems.isNotEmpty(), isSelected = selectedItems::contains, onGroupClick = onGroupClick, - onSelectItem = onSelectItem + onSelectItem = onSelectItem, ) appendState(data) @@ -225,7 +234,7 @@ private fun LazyListScope.refreshState(data: LazyPagingItems) { item { MifosSweetError( message = stringResource(id = R.string.feature_groups_failed_to_fetch_groups), - onclick = { data.refresh() } + onclick = { data.refresh() }, ) } } @@ -240,13 +249,12 @@ private fun LazyListScope.refreshState(data: LazyPagingItems) { if (data.itemCount < 1) { item { MifosEmptyUi( - text = stringResource(id = R.string.feature_groups_no_more_groups_available) + text = stringResource(id = R.string.feature_groups_no_more_groups_available), ) } } } } - } private fun LazyListScope.appendState(data: LazyPagingItems) { @@ -275,7 +283,7 @@ private fun LazyListScope.appendState(data: LazyPagingItems) { text = stringResource(id = R.string.feature_groups_no_more_groups_available), style = TextStyle(fontSize = 14.sp), color = DarkGray, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } } @@ -287,11 +295,11 @@ private fun LazyListScope.successState( pagingItems: LazyPagingItems, isInSelectionMode: Boolean, isSelected: (Group) -> Boolean, - onGroupClick: (groupId : Int) -> Unit, - onSelectItem: (Group) -> Unit + onGroupClick: (groupId: Int) -> Unit, + onSelectItem: (Group) -> Unit, ) { items( - count = pagingItems.itemCount + count = pagingItems.itemCount, ) { index -> pagingItems[index]?.let { group -> GroupItem( @@ -303,24 +311,25 @@ private fun LazyListScope.successState( }, onSelectItem = { onSelectItem(group) - } + }, ) } } - } @OptIn(ExperimentalFoundationApi::class) @Composable -fun GroupItem( - modifier: Modifier = Modifier, +private fun GroupItem( group: Group, doesSelected: Boolean, inSelectionMode: Boolean, onGroupClick: () -> Unit, + modifier: Modifier = Modifier, onSelectItem: () -> Unit, ) { - val borderStroke = if (doesSelected) BorderStroke(1.dp, BluePrimary) else { + val borderStroke = if (doesSelected) { + BorderStroke(1.dp, BluePrimary) + } else { CardDefaults.outlinedCardBorder() } val containerColor = if (doesSelected) BlueSecondary else Color.Unspecified @@ -341,24 +350,24 @@ fun GroupItem( onGroupClick() } }, - onLongClick = onSelectItem + onLongClick = onSelectItem, ), shape = RoundedCornerShape(8.dp), colors = CardDefaults.outlinedCardColors( - containerColor = containerColor + containerColor = containerColor, ), - border = borderStroke + border = borderStroke, ) { Row( modifier = Modifier .fillMaxSize() .padding(12.dp), horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( text = it, - style = MaterialTheme.typography.titleMedium + style = MaterialTheme.typography.titleMedium, ) if (group.sync) { @@ -369,12 +378,11 @@ fun GroupItem( } } - @Preview @Composable -fun GroupListScreenLoadingState( +private fun GroupListScreenLoadingState( @PreviewParameter(GroupListLoadingPreviewParameterProvider::class) - data: Flow> + data: Flow>, ) { GroupsListScreen( lazyListState = rememberLazyListState(), @@ -390,9 +398,9 @@ fun GroupListScreenLoadingState( @Preview @Composable -fun GroupListScreenEmptyState( +private fun GroupListScreenEmptyState( @PreviewParameter(GroupListEmptyPreviewParameterProvider::class) - data: Flow> + data: Flow>, ) { GroupsListScreen( lazyListState = rememberLazyListState(), @@ -408,9 +416,9 @@ fun GroupListScreenEmptyState( @Preview @Composable -fun GroupListScreenErrorState( +private fun GroupListScreenErrorState( @PreviewParameter(GroupListErrorPreviewParameterProvider::class) - data: Flow> + data: Flow>, ) { GroupsListScreen( lazyListState = rememberLazyListState(), @@ -426,9 +434,9 @@ fun GroupListScreenErrorState( @Preview @Composable -fun GroupListScreenPopulatedAndSuccessState( +private fun GroupListScreenPopulatedAndSuccessState( @PreviewParameter(GroupListSuccessPreviewParameterProvider::class) - data: Flow> + data: Flow>, ) { GroupsListScreen( lazyListState = rememberLazyListState(), @@ -444,9 +452,9 @@ fun GroupListScreenPopulatedAndSuccessState( @Preview @Composable -fun GroupListScreenPopulatedAndSelectedItem( +private fun GroupListScreenPopulatedAndSelectedItem( @PreviewParameter(GroupListSuccessPreviewParameterProvider::class) - data: Flow> + data: Flow>, ) { GroupsListScreen( lazyListState = rememberLazyListState(), @@ -462,9 +470,9 @@ fun GroupListScreenPopulatedAndSelectedItem( @DevicePreviews @Composable -fun GroupItemSelectedState( +private fun GroupItemSelectedState( @PreviewParameter(GroupListItemPreviewParameterProvider::class) - group: Group + group: Group, ) { GroupItem( group = group, @@ -477,9 +485,9 @@ fun GroupItemSelectedState( @DevicePreviews @Composable -fun GroupItemIsNotSelectedState( +private fun GroupItemIsNotSelectedState( @PreviewParameter(GroupListItemPreviewParameterProvider::class) - group: Group + group: Group, ) { GroupItem( group = group, @@ -488,4 +496,4 @@ fun GroupItemIsNotSelectedState( onGroupClick = {}, onSelectItem = {}, ) -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListViewModel.kt b/feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListViewModel.kt similarity index 65% rename from feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListViewModel.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListViewModel.kt index 55677c8d175..d1f3e2d882a 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/group_list/GroupsListViewModel.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/groupList/GroupsListViewModel.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.group_list +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.groupList import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -13,7 +22,7 @@ const val PAGE_SIZE = 10 @HiltViewModel class GroupsListViewModel @Inject constructor( - repository: GroupsListRepository + repository: GroupsListRepository, ) : ViewModel() { val data = Pager( @@ -25,7 +34,6 @@ class GroupsListViewModel @Inject constructor( ), pagingSourceFactory = { com.mifos.core.domain.use_cases.GroupsListPagingDataSource(repository, PAGE_SIZE) - } + }, ).flow.cachedIn(viewModelScope) - -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsUiState.kt b/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsUiState.kt deleted file mode 100644 index 843a9284ad6..00000000000 --- a/feature/groups/src/main/java/com/mifos/feature/groups/group_details/GroupDetailsUiState.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.mifos.feature.groups.group_details - -import com.mifos.core.objects.group.Group - -/** - * Created by Aditya Gupta on 06/08/23. - */ -sealed class GroupDetailsUiState { - - data object Loading : GroupDetailsUiState() - - data class Error(val message: Int) : GroupDetailsUiState() - - data class ShowGroup(val group: Group) : GroupDetailsUiState() -} \ No newline at end of file diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupNavGraph.kt b/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupNavGraph.kt index 956ca163d4b..4b21e97ccb8 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupNavGraph.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupNavGraph.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.groups.navigation import androidx.compose.foundation.layout.PaddingValues @@ -8,14 +17,12 @@ import androidx.navigation.compose.composable import androidx.navigation.navArgument import androidx.navigation.navigation import com.mifos.core.common.utils.Constants -import com.mifos.core.datastore.PrefManager import com.mifos.core.objects.accounts.savings.DepositType import com.mifos.core.objects.client.Client -import com.mifos.core.objects.group.Group import com.mifos.core.objects.response.SaveResponse -import com.mifos.feature.groups.create_new_group.CreateNewGroupScreen -import com.mifos.feature.groups.group_details.GroupDetailsScreen -import com.mifos.feature.groups.group_list.GroupsListRoute +import com.mifos.feature.groups.createNewGroup.CreateNewGroupScreen +import com.mifos.feature.groups.groupDetails.GroupDetailsScreen +import com.mifos.feature.groups.groupList.GroupsListRoute /** * Created by Pronay Sarker on 13/08/2024 @@ -32,11 +39,11 @@ fun NavGraphBuilder.groupNavGraph( loadNotes: (Int, String) -> Unit, loadLoanAccountSummary: (Int) -> Unit, loadSavingsAccountSummary: (Int, DepositType) -> Unit, - activateGroup: (Int, String) -> Unit + activateGroup: (Int, String) -> Unit, ) { navigation( startDestination = GroupScreen.GroupListScreen.route, - route = "group_list_routes" + route = "group_list_routes", ) { groupListScreenRoute( paddingValues = paddingValues, @@ -54,7 +61,7 @@ fun NavGraphBuilder.groupNavGraph( loadNotes = loadNotes, loadLoanAccountSummary = loadLoanAccountSummary, loadSavingsAccountSummary = loadSavingsAccountSummary, - activateGroup = activateGroup + activateGroup = activateGroup, ) addNewGroupRoute( @@ -63,7 +70,7 @@ fun NavGraphBuilder.groupNavGraph( if (userStatus == Constants.USER_ONLINE) { groups?.groupId?.let { navController.navigateToGroupDetailsScreen(it) } } - } + }, ) } } @@ -92,13 +99,13 @@ fun NavGraphBuilder.groupDetailsRoute( loadNotes: (Int, String) -> Unit, loadLoanAccountSummary: (Int) -> Unit, loadSavingsAccountSummary: (Int, DepositType) -> Unit, - activateGroup: (Int, String) -> Unit + activateGroup: (Int, String) -> Unit, ) { composable( route = GroupScreen.GroupDetailsScreen.route, arguments = listOf( - navArgument(name = Constants.GROUP_ID, builder = { type = NavType.IntType }) - ) + navArgument(name = Constants.GROUP_ID, builder = { type = NavType.IntType }), + ), ) { GroupDetailsScreen( onBackPressed = onBackPressed, @@ -110,7 +117,7 @@ fun NavGraphBuilder.groupDetailsRoute( notes = loadNotes, loanAccountSelected = loadLoanAccountSummary, savingsAccountSelected = loadSavingsAccountSummary, - activateGroup = activateGroup + activateGroup = activateGroup, ) } } @@ -120,7 +127,7 @@ fun NavGraphBuilder.addNewGroupRoute( ) { composable(route = GroupScreen.CreateNewGroupScreen.route) { CreateNewGroupScreen( - onGroupCreated = onGroupCreated + onGroupCreated = onGroupCreated, ) } } @@ -132,7 +139,3 @@ fun NavController.navigateToCreateNewGroupScreen() { fun NavController.navigateToGroupDetailsScreen(groupId: Int) { navigate(GroupScreen.GroupDetailsScreen.argument(groupId)) } - - - - diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupScreen.kt index 23fed0f4c92..b3162720fc8 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/navigation/GroupScreen.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ package com.mifos.feature.groups.navigation import com.mifos.core.common.utils.Constants @@ -11,8 +20,7 @@ sealed class GroupScreen(val route: String) { data object CreateNewGroupScreen : GroupScreen("create_new_group") - data object GroupDetailsScreen : GroupScreen("group_details_screen/{${Constants.GROUP_ID}}"){ - fun argument(groupId : Int) = "group_details_screen/${groupId}" + data object GroupDetailsScreen : GroupScreen("group_details_screen/{${Constants.GROUP_ID}}") { + fun argument(groupId: Int) = "group_details_screen/$groupId" } } - diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupDialogScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupDialogScreen.kt similarity index 78% rename from feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupDialogScreen.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupDialogScreen.kt index 5fd01d64af6..d07c590d374 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupDialogScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupDialogScreen.kt @@ -1,6 +1,15 @@ -package com.mifos.feature.groups.sync_group_dialog - - +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.syncGroupDialog + +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -20,6 +29,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -31,9 +41,9 @@ import com.mifos.core.designsystem.component.MifosCircularProgress import com.mifos.feature.groups.R @Composable -fun SyncGroupDialogScreen( - viewModel: SyncGroupsDialogViewModel = hiltViewModel(), +internal fun SyncGroupDialogScreen( dismiss: () -> Unit, + viewModel: SyncGroupsDialogViewModel = hiltViewModel(), hide: () -> Unit, ) { val uiState by viewModel.syncGroupsDialogUiState.collectAsStateWithLifecycle() @@ -47,25 +57,26 @@ fun SyncGroupDialogScreen( uiState = uiState, uiData = uiData, dismiss = dismiss, - hide = hide + hide = hide, ) } @Composable -fun SyncGroupDialogScreen( +internal fun SyncGroupDialogScreen( uiState: SyncGroupsDialogUiState, uiData: SyncGroupDialogData, dismiss: () -> Unit, - hide: () -> Unit + modifier: Modifier = Modifier, + hide: () -> Unit, ) { val snackBarHostState = remember { SnackbarHostState() } - Box { + Box(modifier = modifier) { SyncGroupDialogContent( uiData = uiData, okClicked = dismiss, hideClicked = hide, - cancelClicked = dismiss + cancelClicked = dismiss, ) when (uiState) { @@ -87,22 +98,24 @@ fun SyncGroupDialogScreen( } @Composable -fun SyncGroupDialogContent( +private fun SyncGroupDialogContent( uiData: SyncGroupDialogData, okClicked: () -> Unit, hideClicked: () -> Unit, - cancelClicked: () -> Unit + modifier: Modifier = Modifier, + cancelClicked: () -> Unit, ) { Column( - modifier = Modifier + modifier = modifier .fillMaxWidth() - .padding(8.dp), - horizontalAlignment = Alignment.CenterHorizontally + .padding(8.dp) + .background(color = Color.White), + horizontalAlignment = Alignment.CenterHorizontally, ) { Text( modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, - text = stringResource(id = R.string.feature_groups_sync_groups_full_information) + text = stringResource(id = R.string.feature_groups_sync_groups_full_information), ) GroupPayloadField( @@ -136,7 +149,7 @@ fun SyncGroupDialogContent( ) LinearProgressIndicator( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) Spacer(modifier = Modifier.height(12.dp)) @@ -147,7 +160,7 @@ fun SyncGroupDialogContent( ) LinearProgressIndicator( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) Spacer(modifier = Modifier.height(12.dp)) @@ -160,19 +173,19 @@ fun SyncGroupDialogContent( Spacer(modifier = Modifier.height(12.dp)) Row( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { - if(uiData.isSyncSuccess) { + if (uiData.isSyncSuccess) { FilledTonalButton( onClick = { okClicked() }, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(text = stringResource(id = R.string.feature_groups_dialog_action_ok)) } } else { FilledTonalButton( onClick = { cancelClicked() }, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(text = stringResource(id = R.string.feature_groups_cancel)) } @@ -181,7 +194,7 @@ fun SyncGroupDialogContent( FilledTonalButton( onClick = { hideClicked() }, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(text = stringResource(id = R.string.feature_groups_hide)) } @@ -191,33 +204,37 @@ fun SyncGroupDialogContent( } @Composable -fun GroupPayloadField(label: String, value: String) { +private fun GroupPayloadField( + label: String, + value: String, + modifier: Modifier = Modifier, +) { Row( - modifier = Modifier + modifier = modifier .fillMaxWidth() - .padding(vertical = 4.dp) + .padding(vertical = 4.dp), ) { Text( text = label, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) Text( text = value, style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) } } @Preview(showBackground = true, backgroundColor = 0xFFFFFFFF) @Composable -fun SyncGroupDialogScreenPreview() { +private fun SyncGroupDialogScreenPreview() { SyncGroupDialogScreen( dismiss = { }, uiState = SyncGroupsDialogUiState.Success, uiData = SyncGroupDialogData(), - hide = { } + hide = { }, ) -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogUiState.kt b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogUiState.kt new file mode 100644 index 00000000000..02c9820c8e5 --- /dev/null +++ b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogUiState.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.syncGroupDialog + +import androidx.compose.ui.graphics.vector.ImageVector +import com.mifos.core.objects.group.Group + +/** + * Created by Aditya Gupta on 16/08/23. + */ +sealed class SyncGroupsDialogUiState { + data object Loading : SyncGroupsDialogUiState() + data object Success : SyncGroupsDialogUiState() + data class Error( + val messageResId: Int? = null, + val imageVector: ImageVector? = null, + val message: String? = null, + ) : SyncGroupsDialogUiState() +} + +data class SyncGroupDialogData( + val totalSyncCount: Int = 0, + val groupName: String = "", + val isSyncSuccess: Boolean = false, + val singleSyncCount: Int = 0, + val totalClientSyncCount: Int = 0, + val clientSyncCount: Int = 0, + val failedSyncGroupCount: Int = 0, + val groupList: List = listOf(), +) diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogViewModel.kt b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogViewModel.kt similarity index 92% rename from feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogViewModel.kt rename to feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogViewModel.kt index 3eb2287faf8..c372797c21e 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogViewModel.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groups/syncGroupDialog/SyncGroupsDialogViewModel.kt @@ -1,4 +1,13 @@ -package com.mifos.feature.groups.sync_group_dialog +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/android-client/blob/master/LICENSE.md + */ +package com.mifos.feature.groups.syncGroupDialog import androidx.lifecycle.ViewModel import com.mifos.core.common.utils.Constants @@ -35,7 +44,7 @@ import javax.inject.Inject class SyncGroupsDialogViewModel @Inject constructor( private val repository: SyncGroupsDialogRepository, private val networkUtilsWrapper: NetworkUtilsWrapper, - private val prefManager: PrefManager + private val prefManager: PrefManager, ) : ViewModel() { private var mGroupList: List = ArrayList() @@ -51,11 +60,12 @@ class SyncGroupsDialogViewModel @Inject constructor( private var maxSingleSyncGroupProgressBar = 0 private val _syncGroupsDialogUiState = MutableStateFlow( - SyncGroupsDialogUiState.Loading) + SyncGroupsDialogUiState.Loading, + ) val syncGroupsDialogUiState: StateFlow = _syncGroupsDialogUiState private val _syncGroupData: MutableStateFlow = MutableStateFlow( - SyncGroupDialogData() + SyncGroupDialogData(), ) val syncGroupData: StateFlow = _syncGroupData @@ -68,7 +78,7 @@ class SyncGroupsDialogViewModel @Inject constructor( * This Method checking network connection before starting group synchronization */ fun syncGroups() { - if(prefManager.userStatus == Constants.USER_ONLINE) { + if (prefManager.userStatus == Constants.USER_ONLINE) { checkNetworkConnection { syncGroupAndUpdateUI() } @@ -90,7 +100,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } - /** * This Method Checking network connection and Syncing the LoanAndLoanRepayment. * If found no internet connection then stop syncing the groups and dismiss the dialog. @@ -109,7 +118,7 @@ class SyncGroupsDialogViewModel @Inject constructor( checkNetworkConnection { val endPoint = mSavingsAccountList[mSavingsAndTransactionSyncIndex].depositType?.endpoint val id = mSavingsAccountList[mSavingsAndTransactionSyncIndex].id - if(endPoint != null && id != null) { + if (endPoint != null && id != null) { syncSavingsAccountAndTemplate(endPoint, id) } } @@ -123,10 +132,10 @@ class SyncGroupsDialogViewModel @Inject constructor( */ private fun checkAccountsSyncStatusAndSyncAccounts() { if (mLoanAccountList.isNotEmpty() && !mLoanAccountSyncStatus) { - //Sync the Active Loan and LoanRepayment + // Sync the Active Loan and LoanRepayment checkNetworkConnectionAndSyncLoanAndLoanRepayment() } else if (mSavingsAccountList.isNotEmpty()) { - //Sync the Active Savings Account + // Sync the Active Savings Account checkNetworkConnectionAndSyncSavingsAccountAndTransactionTemplate() } else { // If LoanAccounts and SavingsAccount are null then sync Client to Database @@ -200,18 +209,17 @@ class SyncGroupsDialogViewModel @Inject constructor( override fun onNext(groupAccounts: GroupAccounts) { mLoanAccountList = getActiveLoanAccounts( - groupAccounts.loanAccounts + groupAccounts.loanAccounts, ) mSavingsAccountList = getActiveSavingsAccounts( - groupAccounts.savingsAccounts + groupAccounts.savingsAccounts, ) - //Updating UI + // Updating UI maxSingleSyncGroupProgressBar = mLoanAccountList.size + mSavingsAccountList.size checkAccountsSyncStatusAndSyncAccounts() } }) - } /** @@ -243,7 +251,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -271,7 +278,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -302,7 +308,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -334,7 +339,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -345,12 +349,12 @@ class SyncGroupsDialogViewModel @Inject constructor( */ private fun checkAccountsSyncStatusAndSyncClientAccounts() { if (mLoanAccountList.isNotEmpty() && !mLoanAccountSyncStatus) { - //Sync the Active Loan and LoanRepayment + // Sync the Active Loan and LoanRepayment mLoanAccountList[mLoanAndRepaymentSyncIndex].id?.let { syncClientLoanAndLoanRepayment(it) } } else if (mSavingsAccountList.isNotEmpty()) { - //Sync the Active Savings Account + // Sync the Active Savings Account mSavingsAccountList[mSavingsAndTransactionSyncIndex].depositType?.endpoint?.let { mSavingsAccountList[mSavingsAndTransactionSyncIndex].id?.let { it1 -> syncClientSavingsAccountAndTemplate(it, it1) @@ -387,16 +391,15 @@ class SyncGroupsDialogViewModel @Inject constructor( override fun onNext(clientAccounts: ClientAccounts) { mLoanAccountList = getActiveLoanAccounts( clientAccounts - .loanAccounts + .loanAccounts, ) mSavingsAccountList = getSyncableSavingsAccounts( clientAccounts - .savingsAccounts + .savingsAccounts, ) checkAccountsSyncStatusAndSyncClientAccounts() } }) - } /** @@ -428,7 +431,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -440,7 +442,7 @@ class SyncGroupsDialogViewModel @Inject constructor( */ private fun syncClientSavingsAccountAndTemplate( savingsAccountType: String, - savingsAccountId: Int + savingsAccountId: Int, ) { getSavingsAccountAndTemplate(savingsAccountType, savingsAccountId) .subscribe(object : Subscriber() { @@ -457,7 +459,7 @@ class SyncGroupsDialogViewModel @Inject constructor( mSavingsAccountList[mSavingsAndTransactionSyncIndex].id?.let { it1 -> syncClientSavingsAccountAndTemplate( it, - it1 + it1, ) } } @@ -466,7 +468,6 @@ class SyncGroupsDialogViewModel @Inject constructor( } } }) - } /** @@ -486,7 +487,6 @@ class SyncGroupsDialogViewModel @Inject constructor( mGroupSyncIndex += 1 syncGroups() } - } /** @@ -498,11 +498,11 @@ class SyncGroupsDialogViewModel @Inject constructor( private fun getLoanAndLoanRepayment(loanId: Int): Observable { return Observable.combineLatest( repository.syncLoanById(loanId), - repository.syncLoanRepaymentTemplate(loanId) + repository.syncLoanRepaymentTemplate(loanId), ) { loanWithAssociations, loanRepaymentTemplate -> LoanAndLoanRepayment( loanWithAssociations, - loanRepaymentTemplate + loanRepaymentTemplate, ) } .observeOn(AndroidSchedulers.mainThread()) @@ -517,20 +517,24 @@ class SyncGroupsDialogViewModel @Inject constructor( * @return SavingsAccountAndTransactionTemplate */ private fun getSavingsAccountAndTemplate( - savingsAccountType: String, savingsAccountId: Int + savingsAccountType: String, + savingsAccountId: Int, ): Observable { return Observable.combineLatest( repository.syncSavingsAccount( - savingsAccountType, savingsAccountId, - Constants.TRANSACTIONS + savingsAccountType, + savingsAccountId, + Constants.TRANSACTIONS, ), repository.syncSavingsAccountTransactionTemplate( savingsAccountType, - savingsAccountId, Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT - ) + savingsAccountId, + Constants.SAVINGS_ACCOUNT_TRANSACTION_DEPOSIT, + ), ) { savingsAccountWithAssociations, savingsAccountTransactionTemplate -> SavingsAccountAndTransactionTemplate( - savingsAccountWithAssociations, savingsAccountTransactionTemplate + savingsAccountWithAssociations, + savingsAccountTransactionTemplate, ) } .observeOn(AndroidSchedulers.mainThread()) @@ -549,14 +553,14 @@ class SyncGroupsDialogViewModel @Inject constructor( } private fun checkNetworkConnection( - taskWhenOnline: () -> Unit + taskWhenOnline: () -> Unit, ) { - if(networkUtilsWrapper.isNetworkConnected()) { + if (networkUtilsWrapper.isNetworkConnected()) { taskWhenOnline.invoke() } else { _syncGroupsDialogUiState.value = SyncGroupsDialogUiState.Error( messageResId = R.string.feature_groups_error_not_connected_internet, - imageVector = MifosIcons.WifiOff + imageVector = MifosIcons.WifiOff, ) } } @@ -574,7 +578,7 @@ class SyncGroupsDialogViewModel @Inject constructor( Observable.from(savingsAccounts) .filter { savingsAccount -> savingsAccount.status?.active == true && - !savingsAccount.depositType!!.isRecurring + !savingsAccount.depositType!!.isRecurring } .subscribe { savingsAccount -> accounts.add(savingsAccount) } return accounts @@ -585,10 +589,10 @@ class SyncGroupsDialogViewModel @Inject constructor( Observable.from(savingsAccounts) .filter { savingsAccount -> savingsAccount.depositType?.value == "Savings" && - savingsAccount.status?.active == true && - !savingsAccount.depositType!!.isRecurring + savingsAccount.status?.active == true && + !savingsAccount.depositType!!.isRecurring } .subscribe { savingsAccount -> accounts.add(savingsAccount) } return accounts } -} \ No newline at end of file +} diff --git a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogUiState.kt b/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogUiState.kt deleted file mode 100644 index 9174987e15a..00000000000 --- a/feature/groups/src/main/java/com/mifos/feature/groups/sync_group_dialog/SyncGroupsDialogUiState.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.mifos.feature.groups.sync_group_dialog - -import androidx.compose.ui.graphics.vector.ImageVector -import com.mifos.core.objects.group.Group - -/** - * Created by Aditya Gupta on 16/08/23. - */ -sealed class SyncGroupsDialogUiState { - data object Loading: SyncGroupsDialogUiState() - data object Success: SyncGroupsDialogUiState() - data class Error( - val messageResId: Int? = null, - val imageVector: ImageVector? = null, - val message: String? = null - ): SyncGroupsDialogUiState() -} - -data class SyncGroupDialogData( - val totalSyncCount: Int = 0, - val groupName: String = "", - val isSyncSuccess: Boolean = false, - val singleSyncCount: Int = 0, - val totalClientSyncCount: Int = 0, - val clientSyncCount: Int = 0, - val failedSyncGroupCount: Int = 0, - val groupList: List = listOf() -) \ No newline at end of file diff --git a/feature/groups/src/main/res/values/strings.xml b/feature/groups/src/main/res/values/strings.xml index 2cb1d0cc5dd..850534ca91b 100644 --- a/feature/groups/src/main/res/values/strings.xml +++ b/feature/groups/src/main/res/values/strings.xml @@ -1,4 +1,13 @@ + Groups Empty GroupList