From 3f803434e1183f03cae4b74db68caa5676660660 Mon Sep 17 00:00:00 2001 From: Aditya Gupta <94394661+Aditya-gupta99@users.noreply.github.com> Date: Mon, 3 Jun 2024 22:09:17 +0530 Subject: [PATCH] refactor: refactor NewIndividual Collection Sheet screen to jetpack compose with multi module (#2100) * refactor: refactor NewIndividual Collection Sheet screen to jetpack compose with multi module * refactor: refactor NewIndividual Collection Sheet screen to jetpack compose with multi module * fix: log clean up * refactor: refactor NewIndividual Collection Sheet screen to jetpack compose with multi module * fix: added preview parameter --- .../java/com/mifos/core/data/di/DataModule.kt | 5 + .../NewIndividualCollectionSheetRepository.kt | 10 +- ...wIndividualCollectionSheetRepositoryImp.kt | 13 +- .../IndividualCollectionSheet.kt | 43 +-- .../component/MifosEditTextField.kt | 34 ++ .../designsystem/component/MifosScaffold.kt | 52 +-- .../component/MifosTextFieldDropdown.kt | 89 +++++ .../com/mifos/core/network/DataManager.kt | 5 +- .../datamanager/DataManagerCollectionSheet.kt | 4 +- .../services/CollectionSheetService.kt | 4 +- .../core/network/services/OfficeService.kt | 4 +- .../core/network/services/StaffService.kt | 2 +- .../ui/CheckerInboxTasksScreen.kt | 44 ++- .../clientDetails/ui/ClientDetailsScreen.kt | 139 +++++--- feature/collection-sheet/build.gradle.kts | 7 + .../GetIndividualCollectionSheetUseCase.kt | 22 ++ .../domain/use_case/GetOfficeListUseCase.kt | 20 ++ .../use_case/GetStaffInOfficeUseCase.kt | 20 ++ .../ui/NewIndividualCollectionSheetScreen.kt | 310 ++++++++++++++++++ .../ui/NewIndividualCollectionSheetUiState.kt | 21 ++ .../NewIndividualCollectionSheetViewModel.kt | 112 +++++++ .../src/main/res/values/strings.xml | 11 + mifosng-android/build.gradle.kts | 2 + .../injection/module/ApplicationModule.kt | 21 -- .../injection/module/RepositoryModule.kt | 9 - .../NewIndividualCollectionSheetFragment.kt | 236 ++----------- .../NewIndividualCollectionSheetUiState.kt | 27 -- .../NewIndividualCollectionSheetViewModel.kt | 144 -------- .../GenerateCollectionSheetViewModel.kt | 59 ++-- settings.gradle.kts | 2 +- 30 files changed, 858 insertions(+), 613 deletions(-) rename {mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual => core/data/src/main/java/com/mifos/core/data/repository}/NewIndividualCollectionSheetRepository.kt (61%) rename {mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual => core/data/src/main/java/com/mifos/core/data/repository_imp}/NewIndividualCollectionSheetRepositoryImp.kt (61%) create mode 100644 core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetIndividualCollectionSheetUseCase.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetOfficeListUseCase.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetStaffInOfficeUseCase.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetScreen.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetUiState.kt create mode 100644 feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetViewModel.kt delete mode 100644 mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetUiState.kt delete mode 100644 mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetViewModel.kt diff --git a/core/data/src/main/java/com/mifos/core/data/di/DataModule.kt b/core/data/src/main/java/com/mifos/core/data/di/DataModule.kt index 6a3787b6ee8..5d177775d65 100644 --- a/core/data/src/main/java/com/mifos/core/data/di/DataModule.kt +++ b/core/data/src/main/java/com/mifos/core/data/di/DataModule.kt @@ -2,8 +2,10 @@ package com.mifos.core.data.di import com.mifos.core.data.repository.CheckerInboxTasksRepository import com.mifos.core.data.repository.GroupsListRepository +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository import com.mifos.core.data.repository_imp.CheckerInboxTasksRepositoryImp import com.mifos.core.data.repository_imp.GroupsListRepositoryImpl +import com.mifos.core.data.repository_imp.NewIndividualCollectionSheetRepositoryImp import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -16,6 +18,9 @@ abstract class DataModule { @Binds abstract fun bindCheckerInboxTasksRepository(impl: CheckerInboxTasksRepositoryImp): CheckerInboxTasksRepository + @Binds + abstract fun bindNewIndividualCollectionSheetRepository(impl: NewIndividualCollectionSheetRepositoryImp): NewIndividualCollectionSheetRepository + @Binds internal abstract fun provideGroupListRepository( groupsListRepositoryImpl: GroupsListRepositoryImpl diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepository.kt b/core/data/src/main/java/com/mifos/core/data/repository/NewIndividualCollectionSheetRepository.kt similarity index 61% rename from mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepository.kt rename to core/data/src/main/java/com/mifos/core/data/repository/NewIndividualCollectionSheetRepository.kt index 141f493e7e7..87e05469b89 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepository.kt +++ b/core/data/src/main/java/com/mifos/core/data/repository/NewIndividualCollectionSheetRepository.kt @@ -1,4 +1,4 @@ -package com.mifos.mifosxdroid.online.collectionsheetindividual +package com.mifos.core.data.repository import com.mifos.core.network.model.RequestCollectionSheetPayload import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet @@ -11,12 +11,12 @@ import rx.Observable */ interface NewIndividualCollectionSheetRepository { - fun getIndividualCollectionSheet( + suspend fun getIndividualCollectionSheet( payload: RequestCollectionSheetPayload? - ): Observable + ): IndividualCollectionSheet - fun offices(): Observable> + suspend fun offices(): List - fun getStaffInOffice(officeId: Int): Observable> + suspend fun getStaffInOffice(officeId: Int): List } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepositoryImp.kt b/core/data/src/main/java/com/mifos/core/data/repository_imp/NewIndividualCollectionSheetRepositoryImp.kt similarity index 61% rename from mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepositoryImp.kt rename to core/data/src/main/java/com/mifos/core/data/repository_imp/NewIndividualCollectionSheetRepositoryImp.kt index eac18d706a0..9729ac94e23 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetRepositoryImp.kt +++ b/core/data/src/main/java/com/mifos/core/data/repository_imp/NewIndividualCollectionSheetRepositoryImp.kt @@ -1,5 +1,6 @@ -package com.mifos.mifosxdroid.online.collectionsheetindividual +package com.mifos.core.data.repository_imp +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository import com.mifos.core.network.DataManager import com.mifos.core.network.datamanager.DataManagerCollectionSheet import com.mifos.core.network.model.RequestCollectionSheetPayload @@ -12,20 +13,20 @@ import javax.inject.Inject /** * Created by Aditya Gupta on 10/08/23. */ -class NewIndividualCollectionSheetRepositoryImp @Inject internal constructor( +class NewIndividualCollectionSheetRepositoryImp @Inject constructor( private val dataManager: DataManager, private val dataManagerCollection: DataManagerCollectionSheet ) : NewIndividualCollectionSheetRepository { - override fun getIndividualCollectionSheet(payload: RequestCollectionSheetPayload?): Observable { + override suspend fun getIndividualCollectionSheet(payload: RequestCollectionSheetPayload?): IndividualCollectionSheet { return dataManagerCollection.getIndividualCollectionSheet(payload) } - override fun offices(): Observable> { - return dataManager.offices + override suspend fun offices(): List { + return dataManager.offices() } - override fun getStaffInOffice(officeId: Int): Observable> { + override suspend fun getStaffInOffice(officeId: Int): List { return dataManager.getStaffInOffice(officeId) } diff --git a/core/database/src/main/java/com/mifos/core/objects/collectionsheet/IndividualCollectionSheet.kt b/core/database/src/main/java/com/mifos/core/objects/collectionsheet/IndividualCollectionSheet.kt index 7ab6c042e6f..e625a4adf1c 100644 --- a/core/database/src/main/java/com/mifos/core/objects/collectionsheet/IndividualCollectionSheet.kt +++ b/core/database/src/main/java/com/mifos/core/objects/collectionsheet/IndividualCollectionSheet.kt @@ -1,48 +1,17 @@ package com.mifos.core.objects.collectionsheet -import android.os.Parcel import android.os.Parcelable -import com.google.gson.annotations.SerializedName import com.mifos.core.objects.accounts.loan.PaymentTypeOptions +import kotlinx.parcelize.Parcelize /** * Created by Tarun on 06-07-2017. */ -class IndividualCollectionSheet() : Parcelable { - var dueDate: IntArray? = null +@Parcelize +data class IndividualCollectionSheet( + var dueDate: IntArray? = null, - @SerializedName("clients") - var clients: ArrayList? = null + var clients: ArrayList? = null, var paymentTypeOptions: ArrayList? = null - - constructor(parcel: Parcel) : this() { - dueDate = parcel.createIntArray() - clients = ArrayList().apply { - parcel.readList(this, ClientCollectionSheet::class.java.classLoader) - } - paymentTypeOptions = ArrayList().apply { - parcel.readList(this, PaymentTypeOptions::class.java.classLoader) - } - } - - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeIntArray(dueDate) - dest.writeList(clients) - dest.writeList(paymentTypeOptions) - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): IndividualCollectionSheet { - return IndividualCollectionSheet(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } -} \ No newline at end of file +) : Parcelable \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt index 579017e918e..715677a322b 100644 --- a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosEditTextField.kt @@ -4,7 +4,10 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CalendarToday import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults @@ -80,4 +83,35 @@ fun MifosOutlinedTextField( } } ) +} + + +@Composable +fun MifosDatePickerTextField( + value: String, + label: Int, + openDatePicker: () -> Unit +) { + OutlinedTextField( + value = value, + onValueChange = { }, + label = { Text(text = stringResource(id = label)) }, + readOnly = true, + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), + maxLines = 1, + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, + ), + textStyle = LocalDensity.current.run { + TextStyle(fontSize = 18.sp) + }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + trailingIcon = { + IconButton(onClick = { openDatePicker() }) { + Icon(imageVector = Icons.Default.CalendarToday, null) + } + } + ) } \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt index d02723b6929..268a4a34a62 100644 --- a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosScaffold.kt @@ -4,74 +4,26 @@ package com.mifos.core.designsystem.component import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.sp -import com.mifos.core.designsystem.theme.Black import com.mifos.core.designsystem.theme.White @Composable fun MifosScaffold( - icon: ImageVector?, - title: String?, - onBackPressed: () -> Unit, - actions: @Composable () -> Unit, + topBar: @Composable () -> Unit, snackbarHostState: SnackbarHostState?, bottomBar: @Composable () -> Unit, content: @Composable (PaddingValues) -> Unit ) { Scaffold( - topBar = { - TopAppBar( - colors = TopAppBarDefaults.mediumTopAppBarColors(containerColor = White), - navigationIcon = { - if (icon != null) { - IconButton( - onClick = { onBackPressed() }, - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Black, - ) - } - } - }, - title = { - title?.let { - Text( - text = it, - style = TextStyle( - fontSize = 24.sp, - fontWeight = FontWeight.Medium, - fontStyle = FontStyle.Normal - ), - color = Black, - textAlign = TextAlign.Start - ) - } - }, - actions = { actions() } - ) - }, + topBar = topBar, snackbarHost = { snackbarHostState?.let { SnackbarHost(it) } }, containerColor = White, bottomBar = bottomBar ) { padding -> content(padding) } - } \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt new file mode 100644 index 00000000000..998efc52222 --- /dev/null +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosTextFieldDropdown.kt @@ -0,0 +1,89 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + +package com.mifos.core.designsystem.component + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.ArrowDropUp +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mifos.core.designsystem.theme.BluePrimary +import com.mifos.core.designsystem.theme.BluePrimaryDark + +@Composable +fun MifosTextFieldDropdown( + value: String, + onValueChanged: (String) -> Unit, + onOptionSelected: (Int, String) -> Unit, + label: Int, + options: List +) { + var isExpended by remember { mutableStateOf(false) } + + ExposedDropdownMenuBox( + expanded = isExpended, + onExpandedChange = { isExpended = it } + ) { + OutlinedTextField( + value = value, + onValueChange = { onValueChanged(it) }, + label = { Text(text = stringResource(id = label)) }, + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp) + .menuAnchor(), + maxLines = 1, + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary, + ), + textStyle = LocalDensity.current.run { + TextStyle(fontSize = 18.sp) + }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + trailingIcon = { + val image = + if (isExpended) Icons.Default.ArrowDropUp else Icons.Default.ArrowDropDown + IconButton(onClick = { isExpended = !isExpended }) { + Icon(imageVector = image, null) + } + } + ) + + ExposedDropdownMenu( + expanded = isExpended, + onDismissRequest = { isExpended = false } + ) { + options.forEachIndexed { index, value -> + DropdownMenuItem( + text = { Text(text = value) }, + onClick = { + isExpended = false + onOptionSelected(index, value) + } + ) + } + } + } +} \ No newline at end of file diff --git a/core/network/src/main/java/com/mifos/core/network/DataManager.kt b/core/network/src/main/java/com/mifos/core/network/DataManager.kt index 0d24acfb66e..1e275a1d7e4 100644 --- a/core/network/src/main/java/com/mifos/core/network/DataManager.kt +++ b/core/network/src/main/java/com/mifos/core/network/DataManager.kt @@ -137,13 +137,12 @@ class DataManager { /** * Offices API */ - val offices: Observable> - get() = mBaseApiManager.officeApi.allOffices + suspend fun offices(): List = mBaseApiManager.officeApi.allOffices() /** * Staff API */ - fun getStaffInOffice(officeId: Int): Observable> { + suspend fun getStaffInOffice(officeId: Int): List { return mBaseApiManager.staffApi.getStaffForOffice(officeId) } diff --git a/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCollectionSheet.kt b/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCollectionSheet.kt index 385c7b6711e..b19b5aea301 100644 --- a/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCollectionSheet.kt +++ b/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCollectionSheet.kt @@ -25,9 +25,9 @@ class DataManagerCollectionSheet @Inject constructor( /** * Individual CollectionSheet API */ - fun getIndividualCollectionSheet( + suspend fun getIndividualCollectionSheet( payload: RequestCollectionSheetPayload? - ): Observable { + ): IndividualCollectionSheet { return mBaseApiManager.collectionSheetApi.getIndividualCollectionSheet(payload) } diff --git a/core/network/src/main/java/com/mifos/core/network/services/CollectionSheetService.kt b/core/network/src/main/java/com/mifos/core/network/services/CollectionSheetService.kt index 02277cfb5cb..420732af65e 100644 --- a/core/network/src/main/java/com/mifos/core/network/services/CollectionSheetService.kt +++ b/core/network/src/main/java/com/mifos/core/network/services/CollectionSheetService.kt @@ -23,9 +23,9 @@ import rx.Observable */ interface CollectionSheetService { @POST(APIEndPoint.COLLECTION_SHEET + "?command=generateCollectionSheet") - fun getIndividualCollectionSheet( + suspend fun getIndividualCollectionSheet( @Body payload: RequestCollectionSheetPayload? - ): Observable + ): IndividualCollectionSheet @POST(APIEndPoint.COLLECTION_SHEET + "?command=saveCollectionSheet") fun saveindividualCollectionSheet( diff --git a/core/network/src/main/java/com/mifos/core/network/services/OfficeService.kt b/core/network/src/main/java/com/mifos/core/network/services/OfficeService.kt index 872bb1296d6..2127798d393 100644 --- a/core/network/src/main/java/com/mifos/core/network/services/OfficeService.kt +++ b/core/network/src/main/java/com/mifos/core/network/services/OfficeService.kt @@ -18,6 +18,6 @@ interface OfficeService { * * @param listOfOfficesCallback */ - @get:GET(APIEndPoint.OFFICES) - val allOffices: Observable> + @GET(APIEndPoint.OFFICES) + suspend fun allOffices(): List } \ No newline at end of file diff --git a/core/network/src/main/java/com/mifos/core/network/services/StaffService.kt b/core/network/src/main/java/com/mifos/core/network/services/StaffService.kt index b040e797118..7523e2548f0 100644 --- a/core/network/src/main/java/com/mifos/core/network/services/StaffService.kt +++ b/core/network/src/main/java/com/mifos/core/network/services/StaffService.kt @@ -15,7 +15,7 @@ import rx.Observable */ interface StaffService { @GET(APIEndPoint.STAFF + "?status=all") - fun getStaffForOffice(@Query("officeId") officeId: Int): Observable> + suspend fun getStaffForOffice(@Query("officeId") officeId: Int): List @get:GET(APIEndPoint.STAFF) val allStaff: Observable> diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksScreen.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksScreen.kt index 6c157fc88d8..a0d88f94462 100644 --- a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksScreen.kt +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksScreen.kt @@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + package com.mifos.feature.checker_inbox_task.ui import androidx.compose.foundation.layout.Column @@ -11,7 +13,11 @@ import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -20,7 +26,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -32,6 +40,7 @@ import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.mifos.core.designsystem.component.MifosCircularProgress import com.mifos.core.designsystem.component.MifosScaffold import com.mifos.core.designsystem.component.MifosSweetError +import com.mifos.core.designsystem.theme.Black import com.mifos.core.designsystem.theme.White import com.mifos.feature.checker_inbox_task.R @@ -56,10 +65,37 @@ fun CheckerInboxTasksScreen( } MifosScaffold( - icon = Icons.Rounded.ArrowBackIosNew, - title = stringResource(id = R.string.feature_checker_inbox_task_checker_inbox_and_pending_tasks), - onBackPressed = { onBackPressed() }, - actions = { }, + topBar = { + TopAppBar( + colors = TopAppBarDefaults.mediumTopAppBarColors(containerColor = White), + navigationIcon = { + IconButton( + onClick = { onBackPressed() }, + ) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = null, + tint = Black, + ) + } + + }, + title = { + Text( + text = stringResource(id = R.string.feature_checker_inbox_task_checker_inbox_and_pending_tasks), + style = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Medium, + fontStyle = FontStyle.Normal + ), + color = Black, + textAlign = TextAlign.Start + ) + }, + actions = { } + ) + + }, snackbarHostState = null, bottomBar = { }) { padding -> diff --git a/feature/client/src/main/java/com/mifos/feature/client/clientDetails/ui/ClientDetailsScreen.kt b/feature/client/src/main/java/com/mifos/feature/client/clientDetails/ui/ClientDetailsScreen.kt index 0ad1fd66b04..4725e4d8b55 100644 --- a/feature/client/src/main/java/com/mifos/feature/client/clientDetails/ui/ClientDetailsScreen.kt +++ b/feature/client/src/main/java/com/mifos/feature/client/clientDetails/ui/ClientDetailsScreen.kt @@ -51,6 +51,8 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -222,59 +224,87 @@ fun ClientDetailsScreen( } MifosScaffold( - icon = Icons.Rounded.ArrowBackIosNew, - title = stringResource(id = R.string.feature_client), - onBackPressed = { onBackPressed() }, - actions = { - IconButton(onClick = { showMenu = showMenu.not() }) { - Icon(imageVector = Icons.Default.MoreVert, contentDescription = null) - } - DropdownMenu( - modifier = Modifier.background(White), - expanded = showMenu, - onDismissRequest = { showMenu = false } - ) { - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_add_loan_account)) { - addLoanAccount(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_add_savings_account)) { - addSavingsAccount(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_charges)) { - charges(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_documents)) { - documents(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_identifiers)) { - identifiers(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_more_client_info)) { - moreClientInfo(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_notes)) { - notes(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_pinpoint_location)) { - pinpointLocation(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_survey)) { - survey(clientId) - showMenu = false - } - MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_upload_signature)) { - uploadSignature(clientId) - showMenu = false + topBar = { + TopAppBar( + colors = TopAppBarDefaults.mediumTopAppBarColors(containerColor = White), + navigationIcon = { + + IconButton( + onClick = { onBackPressed() }, + ) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = null, + tint = Black, + ) + } + + }, + title = { + Text( + text = stringResource(id = R.string.feature_client), + style = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Medium, + fontStyle = FontStyle.Normal + ), + color = Black, + textAlign = TextAlign.Start + ) + + }, + actions = { + IconButton(onClick = { showMenu = showMenu.not() }) { + Icon(imageVector = Icons.Default.MoreVert, contentDescription = null) + } + DropdownMenu( + modifier = Modifier.background(White), + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_add_loan_account)) { + addLoanAccount(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_add_savings_account)) { + addSavingsAccount(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_charges)) { + charges(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_documents)) { + documents(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_identifiers)) { + identifiers(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_more_client_info)) { + moreClientInfo(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_notes)) { + notes(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_pinpoint_location)) { + pinpointLocation(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_survey)) { + survey(clientId) + showMenu = false + } + MifosMenuDropDownItem(option = stringResource(id = R.string.feature_client_upload_signature)) { + uploadSignature(clientId) + showMenu = false + } + } } - } + ) }, snackbarHostState = snackbarHostState, bottomBar = { @@ -290,7 +320,10 @@ fun ClientDetailsScreen( containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary ) ) { - Text(text = stringResource(id = R.string.feature_client_activate_client), fontSize = 16.sp) + Text( + text = stringResource(id = R.string.feature_client_activate_client), + fontSize = 16.sp + ) } } diff --git a/feature/collection-sheet/build.gradle.kts b/feature/collection-sheet/build.gradle.kts index 5b11c7dba5a..ac925407062 100644 --- a/feature/collection-sheet/build.gradle.kts +++ b/feature/collection-sheet/build.gradle.kts @@ -10,6 +10,13 @@ android { dependencies { + implementation(projects.core.datastore) + implementation(projects.core.network) + + //DBFlow dependencies + kapt(libs.dbflow.processor) + implementation(libs.dbflow) + kapt(libs.github.dbflow.processor) testImplementation(libs.hilt.android.testing) testImplementation(projects.core.testing) diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetIndividualCollectionSheetUseCase.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetIndividualCollectionSheetUseCase.kt new file mode 100644 index 00000000000..963ccfb8b4a --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetIndividualCollectionSheetUseCase.kt @@ -0,0 +1,22 @@ +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository +import com.mifos.core.network.model.RequestCollectionSheetPayload +import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetIndividualCollectionSheetUseCase @Inject constructor(private val repository: NewIndividualCollectionSheetRepository) { + + suspend operator fun invoke(payload: RequestCollectionSheetPayload): Flow> = + flow { + try { + emit(Resource.Loading()) + emit(Resource.Success(repository.getIndividualCollectionSheet(payload))) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetOfficeListUseCase.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetOfficeListUseCase.kt new file mode 100644 index 00000000000..49031492f72 --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetOfficeListUseCase.kt @@ -0,0 +1,20 @@ +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository +import com.mifos.core.objects.organisation.Office +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetOfficeListUseCase @Inject constructor(private val repository: NewIndividualCollectionSheetRepository) { + + suspend operator fun invoke(): Flow>> = flow { + try { + emit(Resource.Loading()) + emit(Resource.Success(repository.offices())) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetStaffInOfficeUseCase.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetStaffInOfficeUseCase.kt new file mode 100644 index 00000000000..927eab8c264 --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/domain/use_case/GetStaffInOfficeUseCase.kt @@ -0,0 +1,20 @@ +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository +import com.mifos.core.objects.organisation.Staff +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetStaffInOfficeUseCase @Inject constructor(private val repository: NewIndividualCollectionSheetRepository) { + + suspend operator fun invoke(officeId: Int): Flow>> = flow { + try { + emit(Resource.Loading()) + emit(Resource.Success(repository.getStaffInOffice(officeId))) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetScreen.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetScreen.kt new file mode 100644 index 00000000000..47524248c6c --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetScreen.kt @@ -0,0 +1,310 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.ui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.DatePicker +import androidx.compose.material3.DatePickerDialog +import androidx.compose.material3.ExperimentalMaterial3Api +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 +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mifos.core.designsystem.component.MifosCircularProgress +import com.mifos.core.designsystem.component.MifosDatePickerTextField +import com.mifos.core.designsystem.component.MifosScaffold +import com.mifos.core.designsystem.component.MifosTextFieldDropdown +import com.mifos.core.designsystem.theme.BluePrimary +import com.mifos.core.designsystem.theme.BluePrimaryDark +import com.mifos.core.network.model.RequestCollectionSheetPayload +import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet +import com.mifos.core.objects.organisation.Office +import com.mifos.core.objects.organisation.Staff +import com.mifos.feature.collection_sheet.R +import java.text.SimpleDateFormat +import java.util.Locale + +@Composable +fun NewIndividualCollectionSheetScreen( + viewModel: NewIndividualCollectionSheetViewModel = hiltViewModel(), + popupDialog: (IndividualCollectionSheet) -> Unit, + repaymentDate: (String) -> Unit +) { + val state = viewModel.newIndividualCollectionSheetUiState.collectAsStateWithLifecycle().value + NewIndividualCollectionSheetScreen( + state = state, + getStaffList = { + viewModel.getStaffList(it) + }, + generateCollection = { _officeId, _staffId, _repaymentDate -> + viewModel.getIndividualCollectionSheet(RequestCollectionSheetPayload().apply { + officeId = _officeId + transactionDate = _repaymentDate + staffId = _staffId + }) + repaymentDate(_repaymentDate) + }, + popupDialog = popupDialog + ) +} + + +@Composable +fun NewIndividualCollectionSheetScreen( + state: NewIndividualCollectionSheetUiState, + getStaffList: (Int) -> Unit, + generateCollection: (Int, Int, String) -> Unit, + popupDialog: (IndividualCollectionSheet) -> Unit +) { + + val keyboardController = LocalSoftwareKeyboardController.current + + var selectedOffice by rememberSaveable { mutableStateOf("") } + var selectedStaff by rememberSaveable { mutableStateOf("") } + var officeId by rememberSaveable { mutableIntStateOf(0) } + var staffId by rememberSaveable { mutableIntStateOf(0) } + + val snackbarHostState = remember { SnackbarHostState() } + + var showDatePicker by rememberSaveable { mutableStateOf(false) } + var repaymentDate by rememberSaveable { mutableLongStateOf(System.currentTimeMillis()) } + val datePickerState = rememberDatePickerState( + initialSelectedDateMillis = repaymentDate, + selectableDates = object : SelectableDates { + override fun isSelectableDate(utcTimeMillis: Long): Boolean { + return utcTimeMillis >= System.currentTimeMillis() + } + } + ) + + LaunchedEffect(key1 = state.error) { + state.error?.let { snackbarHostState.showSnackbar(it) } + } + + LaunchedEffect(key1 = state.individualCollectionSheet) { + state.individualCollectionSheet?.let { + popupDialog(it) + } + } + + MifosScaffold( + topBar = { }, + snackbarHostState = snackbarHostState, + bottomBar = { } + ) { paddingValues -> + if (showDatePicker) { + DatePickerDialog( + onDismissRequest = { + showDatePicker = false + }, + confirmButton = { + TextButton( + onClick = { + showDatePicker = false + datePickerState.selectedDateMillis?.let { + repaymentDate = it + } + } + ) { Text(stringResource(id = R.string.feature_collection_sheet_select)) } + }, + dismissButton = { + TextButton( + onClick = { + showDatePicker = false + } + ) { Text(stringResource(id = R.string.feature_collection_sheet_cancel)) } + } + ) + { + DatePicker(state = datePickerState) + } + } + + if (state.isLoading) { + MifosCircularProgress() + } else { + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + Text( + modifier = Modifier.padding(16.dp), + text = stringResource(id = R.string.feature_collection_sheet_generate_new), + style = TextStyle( + fontSize = 24.sp + ) + ) + Text( + modifier = Modifier.padding(start = 16.dp, end = 16.dp), + text = stringResource(id = R.string.feature_collection_sheet_fill_collection_sheet_message), + style = TextStyle( + fontSize = 14.sp, + color = Color.Black + ) + ) + Spacer(modifier = Modifier.height(16.dp)) + MifosTextFieldDropdown( + value = selectedOffice, + onValueChanged = { + selectedOffice = it + selectedStaff = "" + }, + onOptionSelected = { index, value -> + state.officeList[index].id?.let { + getStaffList(it) + officeId = it + } + selectedOffice = value + selectedStaff = "" + }, + label = R.string.feature_collection_sheet_office, + options = state.officeList.map { it.name.toString() } + ) + Spacer(modifier = Modifier.height(8.dp)) + MifosDatePickerTextField( + value = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()).format( + repaymentDate + ), + label = R.string.feature_collection_sheet_repayment_date, + openDatePicker = { + showDatePicker = true + } + ) + Spacer(modifier = Modifier.height(8.dp)) + MifosTextFieldDropdown( + value = selectedStaff, + onValueChanged = { + selectedStaff = it + }, + onOptionSelected = { index, value -> + state.staffList[index].id?.let { + staffId = it + } + selectedStaff = value + }, + label = R.string.feature_collection_sheet_staff, + options = state.staffList.map { it.displayName.toString() } + ) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Button( + onClick = { + keyboardController?.hide() + generateCollection( + officeId, + staffId, + SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()).format( + repaymentDate + ) + ) + }, + modifier = Modifier + .weight(1f) + .padding(16.dp), + contentPadding = PaddingValues(), + enabled = selectedStaff != "" && selectedOffice != "", + colors = ButtonDefaults.buttonColors( + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + ) + ) { + Text( + text = stringResource(id = R.string.feature_collection_sheet_generate), + fontSize = 16.sp + ) + } + Button( + onClick = { + selectedOffice = "" + repaymentDate = System.currentTimeMillis() + selectedStaff = "" + }, + modifier = Modifier + .weight(1f) + .padding(16.dp), + contentPadding = PaddingValues(), + colors = ButtonDefaults.buttonColors( + containerColor = if (isSystemInDarkTheme()) BluePrimaryDark else BluePrimary + ) + ) { + Text( + text = stringResource(id = R.string.feature_collection_sheet_clear), + fontSize = 16.sp + ) + } + } + } + } + } +} + +class NewIndividualCollectionSheetUiStateProvider : + PreviewParameterProvider { + + override val values: Sequence + get() = sequenceOf( + NewIndividualCollectionSheetUiState(staffList = sampleStaffList), + NewIndividualCollectionSheetUiState(officeList = sampleOfficeList), + NewIndividualCollectionSheetUiState(error = "Error Occurred"), + NewIndividualCollectionSheetUiState(isLoading = true), + NewIndividualCollectionSheetUiState(individualCollectionSheet = IndividualCollectionSheet()) + ) +} + +@Preview(showBackground = true) +@Composable +private fun NewIndividualCollectionSheetPreview( + @PreviewParameter(NewIndividualCollectionSheetUiStateProvider::class) newIndividualCollectionSheetUiState: NewIndividualCollectionSheetUiState +) { + NewIndividualCollectionSheetScreen( + state = newIndividualCollectionSheetUiState, + getStaffList = {}, + generateCollection = { _, _, _ -> + }, + popupDialog = {} + ) +} + +val sampleStaffList = List(10) { + Staff(firstname = "FirstName", lastname = "LastName", isActive = true) +} + +val sampleOfficeList = List(10) { + Office(name = "Name") +} \ No newline at end of file diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetUiState.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetUiState.kt new file mode 100644 index 00000000000..c779c36675a --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetUiState.kt @@ -0,0 +1,21 @@ +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.ui + +import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet +import com.mifos.core.objects.organisation.Office +import com.mifos.core.objects.organisation.Staff + +/** + * Created by Aditya Gupta on 10/08/23. + */ +data class NewIndividualCollectionSheetUiState( + + val isLoading: Boolean = false, + + val error: String? = null, + + val officeList: List = emptyList(), + + val staffList: List = emptyList(), + + val individualCollectionSheet: IndividualCollectionSheet? = null +) \ No newline at end of file diff --git a/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetViewModel.kt b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetViewModel.kt new file mode 100644 index 00000000000..4f26c7e3c06 --- /dev/null +++ b/feature/collection-sheet/src/main/java/com/mifos/feature/individual_collection_sheet/new_individual_collection_sheet/ui/NewIndividualCollectionSheetViewModel.kt @@ -0,0 +1,112 @@ +package com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mifos.core.common.utils.Resource +import com.mifos.core.network.model.RequestCollectionSheetPayload +import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet +import com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case.GetIndividualCollectionSheetUseCase +import com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case.GetOfficeListUseCase +import com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.domain.use_case.GetStaffInOfficeUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class NewIndividualCollectionSheetViewModel @Inject constructor( + private val getOfficeListUseCase: GetOfficeListUseCase, + private val getStaffInOfficeUseCase: GetStaffInOfficeUseCase, + private val getIndividualCollectionSheetUseCase: GetIndividualCollectionSheetUseCase +) : ViewModel() { + + private val _newIndividualCollectionSheetUiState = + MutableStateFlow(NewIndividualCollectionSheetUiState()) + + val newIndividualCollectionSheetUiState = + _newIndividualCollectionSheetUiState.asStateFlow() + + init { + getOfficeList() + } + + private fun getOfficeList() = viewModelScope.launch(Dispatchers.IO) { + getOfficeListUseCase().collect { result -> + when (result) { + is Resource.Error -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + error = result.message + ) + } + + is Resource.Loading -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + isLoading = true + ) + } + + is Resource.Success -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + isLoading = false, + officeList = result.data ?: emptyList() + ) + } + } + } + } + + fun getStaffList(officeId: Int) = viewModelScope.launch(Dispatchers.IO) { + getStaffInOfficeUseCase(officeId).collect { result -> + when (result) { + is Resource.Error -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + error = result.message + ) + } + + is Resource.Loading -> { + + } + + is Resource.Success -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + staffList = result.data ?: emptyList() + ) + } + } + } + } + + fun getIndividualCollectionSheet(requestCollectionSheetPayload: RequestCollectionSheetPayload) = + viewModelScope.launch(Dispatchers.IO) { + getIndividualCollectionSheetUseCase(requestCollectionSheetPayload).collect { result -> + when (result) { + is Resource.Error -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + error = result.message + ) + } + + is Resource.Loading -> { + + } + + is Resource.Success -> { + _newIndividualCollectionSheetUiState.value = + _newIndividualCollectionSheetUiState.value.copy( + individualCollectionSheet = result.data + ?: IndividualCollectionSheet() + ) + } + } + } + } +} \ No newline at end of file diff --git a/feature/collection-sheet/src/main/res/values/strings.xml b/feature/collection-sheet/src/main/res/values/strings.xml index aafaead2508..37669aea858 100644 --- a/feature/collection-sheet/src/main/res/values/strings.xml +++ b/feature/collection-sheet/src/main/res/values/strings.xml @@ -1,5 +1,16 @@ No Saved Collection Sheet + Please fill in appropriate details to find the collection sheet to generate. + Generate New + Office + Repayment Date + Staff + Generate + Clear + Select + Cancel + Please Select a Office + Please Select a Staff \ No newline at end of file diff --git a/mifosng-android/build.gradle.kts b/mifosng-android/build.gradle.kts index 2c4e1ec0364..4806bb7d6ea 100644 --- a/mifosng-android/build.gradle.kts +++ b/mifosng-android/build.gradle.kts @@ -253,4 +253,6 @@ dependencies { // ViewModel utilities for Compose implementation(libs.androidx.lifecycle.viewModelCompose) implementation(libs.androidx.hilt.navigation.compose) + + implementation(libs.androidx.lifecycle.runtimeCompose) } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/ApplicationModule.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/ApplicationModule.kt index 1bea63b5164..ed414912e82 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/ApplicationModule.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/ApplicationModule.kt @@ -18,27 +18,6 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) class ApplicationModule { -// @Provides -// @Singleton -// fun provideBaseApiManager(prefManager: PrefManager): com.mifos.core.network.BaseApiManager { -// return com.mifos.core.network.BaseApiManager(prefManager) -// } -// -// @Provides -// @Singleton -// fun provideSdkBaseApiManager(prefManager: PrefManager): BaseApiManager { -// val usernamePassword: Pair = prefManager.usernamePassword -// val baseManager = getInstance() -// baseManager.createService( -// usernamePassword.first, -// usernamePassword.second, -// prefManager.getInstanceUrl(), -// prefManager.getTenant(), -// false -// ) -// return baseManager -// } - @Provides @Singleton fun provideNetworkUtilsWrapper(@ApplicationContext context: Context): NetworkUtilsWrapper { diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/RepositoryModule.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/RepositoryModule.kt index 445bed8a69f..46639145ad1 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/RepositoryModule.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/injection/module/RepositoryModule.kt @@ -87,8 +87,6 @@ import com.mifos.mifosxdroid.online.loantransactions.LoanTransactionsRepository import com.mifos.mifosxdroid.online.loantransactions.LoanTransactionsRepositoryImp import com.mifos.mifosxdroid.activity.login.LoginRepository import com.mifos.mifosxdroid.activity.login.LoginRepositoryImp -import com.mifos.mifosxdroid.online.collectionsheetindividual.NewIndividualCollectionSheetRepository -import com.mifos.mifosxdroid.online.collectionsheetindividual.NewIndividualCollectionSheetRepositoryImp import com.mifos.mifosxdroid.online.note.NoteRepository import com.mifos.mifosxdroid.online.note.NoteRepositoryImp import com.mifos.mifosxdroid.offline.offlinedashbarod.OfflineDashboardRepository @@ -296,13 +294,6 @@ class RepositoryModule { return CollectionSheetRepositoryImp(dataManager) } - @Provides - fun providesNewIndividualCollectionSheetRepository( - dataManager: DataManager, dataManagerCollection: DataManagerCollectionSheet - ): NewIndividualCollectionSheetRepository { - return NewIndividualCollectionSheetRepositoryImp(dataManager, dataManagerCollection) - } - @Provides fun providesIndividualCollectionSheetDetailsRepository(dataManagerCollection: DataManagerCollectionSheet): IndividualCollectionSheetDetailsRepository { return IndividualCollectionSheetDetailsRepositoryImp(dataManagerCollection) diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt index e25273f2921..d5e104e6c34 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetFragment.kt @@ -4,25 +4,17 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.lifecycle.ViewModelProvider +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.navigation.fragment.findNavController import com.mifos.core.common.utils.Constants -import com.mifos.core.network.model.RequestCollectionSheetPayload import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet -import com.mifos.core.objects.organisation.Office -import com.mifos.core.objects.organisation.Staff -import com.mifos.mifosxdroid.R +import com.mifos.feature.individual_collection_sheet.new_individual_collection_sheet.ui.NewIndividualCollectionSheetScreen import com.mifos.mifosxdroid.core.MifosBaseFragment -import com.mifos.mifosxdroid.core.util.Toaster -import com.mifos.mifosxdroid.databinding.FragmentNewCollectionSheetBinding import com.mifos.mifosxdroid.dialogfragments.collectionsheetdialog.CollectionSheetDialogFragment -import com.mifos.utils.DatePickerConstrainType import com.mifos.utils.FragmentConstants -import com.mifos.utils.getDatePickerDialog -import com.mifos.utils.getTodayFormatted import dagger.hilt.android.AndroidEntryPoint import java.text.SimpleDateFormat -import java.time.Instant import java.util.Locale @@ -30,33 +22,10 @@ import java.util.Locale * Created by aksh on 18/6/18. */ @AndroidEntryPoint -class NewIndividualCollectionSheetFragment : MifosBaseFragment(), View.OnClickListener { - - private lateinit var binding: FragmentNewCollectionSheetBinding - - private lateinit var viewModel: NewIndividualCollectionSheetViewModel +class NewIndividualCollectionSheetFragment : MifosBaseFragment() { private var sheet: IndividualCollectionSheet? = null - private var requestPayload: RequestCollectionSheetPayload? = null - private lateinit var officeNameList: ArrayList - private var officeList: List = ArrayList() - private lateinit var staffNameList: ArrayList - private var staffList: List = ArrayList() - private var officeId: Int? = 0 - private var staffId: Int? = 0 - private val requestCode = 1 - private var success = true - private var actualDisbursementDate: String? = null - private var transactionDate: String? = null - - private var selectedRepaymentDate: Instant = Instant.now() - private val datePickerDialog by lazy { - getDatePickerDialog(selectedRepaymentDate, DatePickerConstrainType.ONLY_FUTURE_DAYS) { - val formattedDate = SimpleDateFormat("dd MMMM yyyy", Locale.getDefault()).format(it) - selectedRepaymentDate = Instant.ofEpochMilli(it) - binding.repaymentDateFieldContainer.editText?.setText(formattedDate) - } - } + private lateinit var repaymentDate: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -64,164 +33,55 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), View.OnClickLi sheet = savedInstanceState[Constants.EXTRA_COLLECTION_INDIVIDUAL] as IndividualCollectionSheet } - setHasOptionsMenu(true) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = FragmentNewCollectionSheetBinding.inflate(inflater, container, false) - setToolbarTitle(getStringMessage(R.string.individual_collection_sheet)) - viewModel = ViewModelProvider(this)[NewIndividualCollectionSheetViewModel::class.java] - setUpUi() - - viewModel.newIndividualCollectionSheetUiState.observe(viewLifecycleOwner) { - when (it) { - is NewIndividualCollectionSheetUiState.SetOfficeSpinner -> { - showProgressbar(false) - setOfficeSpinner(it.officeList) - } - - is NewIndividualCollectionSheetUiState.SetStaffSpinner -> { - showProgressbar(false) - setStaffSpinner(it.staffList) - } - - is NewIndividualCollectionSheetUiState.ShowError -> { - showProgressbar(false) - showError(it.errorMessage) - } - - is NewIndividualCollectionSheetUiState.ShowNoSheetFound -> { - showProgressbar(false) - showNoSheetFound() - } - - is NewIndividualCollectionSheetUiState.ShowProgressbar -> showProgressbar(true) - is NewIndividualCollectionSheetUiState.ShowSheet -> { - showProgressbar(false) - showSheet(it.individualCollectionSheet) - } - - is NewIndividualCollectionSheetUiState.ShowSuccess -> { - showProgressbar(false) - showSuccess() - } - } - } - - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - binding.btnClear.setOnClickListener { - clear() - } - } - - private fun setUpUi() { - setRepaymentDate() - officeNameList = ArrayList() - binding.officeListField.setSimpleItems(officeNameList.toTypedArray()) - binding.officeListField.setOnItemClickListener { adapterView, view, relativePosition, l -> - val i = officeNameList.indexOf(adapterView.getItemAtPosition(relativePosition)) - Toaster.show(binding.root, officeNameList[i]) - officeId = officeList[i].id - viewModel.fetchStaff(officeId!!) - } - staffNameList = ArrayList() - binding.staffSelectionField.setSimpleItems(staffNameList.toTypedArray()) - binding.repaymentDateFieldContainer.setEndIconOnClickListener { - datePickerDialog.show( - requireActivity().supportFragmentManager, - FragmentConstants.DFRAG_DATE_PICKER + return ComposeView(requireContext()).apply { + setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) + setContent { + NewIndividualCollectionSheetScreen(popupDialog = { + popupDialog(it) + }, repaymentDate = { + repaymentDate = it + }) + } } - binding.btnFetchCollectionSheet.setOnClickListener(this) - viewModel.fetchOffices() - - } - - private fun setRepaymentDate() { - binding.repaymentDateFieldContainer.editText?.setText(getTodayFormatted()) - transactionDate = getTodayFormatted() - actualDisbursementDate = transactionDate - } - - private fun prepareRequestPayload() { - requestPayload = RequestCollectionSheetPayload() - requestPayload?.officeId = officeId - requestPayload?.staffId = staffId - requestPayload?.transactionDate = - binding.repaymentDateFieldContainer.editText?.text.toString() - } - - private fun setOfficeSpinner(offices: List?) { - if (offices != null) { - officeList = offices - } - officeNameList.clear() - officeNameList.addAll(viewModel.filterOffices(officeList)) - binding.officeListField.setSimpleItems(officeNameList.toTypedArray()) - } - - private fun retrieveCollectionSheet() { - prepareRequestPayload() - viewModel.fetchIndividualCollectionSheet(requestPayload) - } - - private fun setStaffSpinner(staffs: List?) { - binding.staffSelectionField.setOnItemClickListener { adapterView, _, relativePosition, _ -> - val i = staffNameList.indexOf(adapterView.getItemAtPosition(relativePosition)) - staffId = staffList[i].id - } - if (staffs != null) { - staffList = staffs - } - staffNameList.clear() - staffNameList.addAll(viewModel.filterStaff(staffList)) - binding.staffSelectionField.setSimpleItems(staffNameList.toTypedArray()) } - private fun popupDialog() { + private fun popupDialog(individualCollectionSheet: IndividualCollectionSheet) { + sheet = individualCollectionSheet val collectionSheetDialogFragment = CollectionSheetDialogFragment.newInstance( - binding.repaymentDateFieldContainer.editText?.text.toString(), + repaymentDate, sheet?.clients?.size ?: 0 ) - collectionSheetDialogFragment.setTargetFragment(this, requestCode) + collectionSheetDialogFragment.setTargetFragment(this, 1) val fragmentTransaction = requireActivity().supportFragmentManager .beginTransaction() fragmentTransaction.addToBackStack(FragmentConstants.FRAG_DOCUMENT_LIST) collectionSheetDialogFragment.show(fragmentTransaction, "Identifier Dialog Fragment") } - fun getResponse(response: String?) { + fun getResponse(response: String) { when (response) { Constants.FILLNOW -> { - val fm = activity - ?.supportFragmentManager - fm?.popBackStack() val action = sheet?.let { - actualDisbursementDate?.let { it1 -> - transactionDate?.let { it2 -> - NewIndividualCollectionSheetFragmentDirections.actionNewIndividualCollectionSheetFragmentToIndividualCollectionSheetDetailsFragment( - it, it1, it2 - ) - } - } + NewIndividualCollectionSheetFragmentDirections.actionNewIndividualCollectionSheetFragmentToIndividualCollectionSheetDetailsFragment( + it, SimpleDateFormat( + "dd MMMM yyyy", + Locale.getDefault() + ).format(System.currentTimeMillis()), repaymentDate + ) } action?.let { findNavController().navigate(it) } } } } - private fun showSheet(individualCollectionSheet: IndividualCollectionSheet?) { - sheet = individualCollectionSheet - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putParcelable( @@ -229,48 +89,4 @@ class NewIndividualCollectionSheetFragment : MifosBaseFragment(), View.OnClickLi sheet ) } - - private fun showSuccess() { - if (success) { - popupDialog() - } - } - - private fun showError(message: String?) { - Toaster.show(binding.root, message) - } - - private fun showNoSheetFound() { - success = false - Toaster.show(binding.root, getStringMessage(R.string.no_collectionsheet_found)) - } - - private fun showProgressbar(b: Boolean) { - if (b) { - showMifosProgressDialog() - } else { - hideMifosProgressDialog() - } - } - - override fun onClick(view: View) { - when (view.id) { - R.id.btn_fetch_collection_sheet -> { - if (!officeNameList.contains(binding.officeListField.text.toString())) - Toaster.show(binding.root, getStringMessage(R.string.error_select_office)) - else if (!staffNameList.contains(binding.staffSelectionField.text.toString())) - Toaster.show(binding.root, getStringMessage(R.string.error_select_staff)) - else - retrieveCollectionSheet() - } - } - } - - - private fun clear() { - binding.officeListField.setAdapter(null) - binding.staffSelectionField.setAdapter(null) - setUpUi() - } - } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetUiState.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetUiState.kt deleted file mode 100644 index 91ddc3716be..00000000000 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetUiState.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.mifos.mifosxdroid.online.collectionsheetindividual - -import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet -import com.mifos.core.objects.organisation.Office -import com.mifos.core.objects.organisation.Staff - -/** - * Created by Aditya Gupta on 10/08/23. - */ -sealed class NewIndividualCollectionSheetUiState { - - data object ShowProgressbar : NewIndividualCollectionSheetUiState() - - data object ShowSuccess : NewIndividualCollectionSheetUiState() - - data class ShowError(val errorMessage: String?) : NewIndividualCollectionSheetUiState() - - data class ShowSheet(val individualCollectionSheet: IndividualCollectionSheet?) : - NewIndividualCollectionSheetUiState() - - data object ShowNoSheetFound : NewIndividualCollectionSheetUiState() - - data class SetOfficeSpinner(val officeList: List) : - NewIndividualCollectionSheetUiState() - - data class SetStaffSpinner(val staffList: List) : NewIndividualCollectionSheetUiState() -} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetViewModel.kt deleted file mode 100644 index ace06bb7f2d..00000000000 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/collectionsheetindividual/NewIndividualCollectionSheetViewModel.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.mifos.mifosxdroid.online.collectionsheetindividual - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import com.mifos.core.network.model.RequestCollectionSheetPayload -import com.mifos.core.objects.collectionsheet.IndividualCollectionSheet -import com.mifos.core.objects.organisation.Office -import com.mifos.core.objects.organisation.Staff -import dagger.hilt.android.lifecycle.HiltViewModel -import retrofit2.HttpException -import rx.Observable -import rx.Subscriber -import rx.android.schedulers.AndroidSchedulers -import rx.plugins.RxJavaPlugins -import rx.schedulers.Schedulers -import javax.inject.Inject - -/** - * Created by Aditya Gupta on 10/08/23. - */ -@HiltViewModel -class NewIndividualCollectionSheetViewModel @Inject constructor(private val repository: NewIndividualCollectionSheetRepository) : - ViewModel() { - - private val _newIndividualCollectionSheetUiState = - MutableLiveData() - - val newIndividualCollectionSheetUiState: LiveData - get() = _newIndividualCollectionSheetUiState - - fun fetchIndividualCollectionSheet(requestCollectionSheetPayload: RequestCollectionSheetPayload?) { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowProgressbar - - repository.getIndividualCollectionSheet(requestCollectionSheetPayload) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowSuccess - } - - override fun onError(e: Throwable) { - if (e is HttpException) { - try { - val errorMessage = e.response()?.errorBody() - ?.string() - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowError(errorMessage) - } catch (throwable: Throwable) { - RxJavaPlugins.getInstance().errorHandler.handleError(e) - } - } else { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowError(e.localizedMessage) - } - } - - override fun onNext(individualCollectionSheet: IndividualCollectionSheet) { - if (individualCollectionSheet.clients?.size!! > 0) { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowSheet(individualCollectionSheet) - } else { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowNoSheetFound - } - } - }) - } - - fun fetchOffices() { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowProgressbar - repository.offices() - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - try { - if (e is HttpException) { - val errorMessage = e.response()?.errorBody() - ?.string() - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowError(errorMessage) - } - } catch (throwable: Throwable) { - RxJavaPlugins.getInstance().errorHandler.handleError(e) - } - } - - override fun onNext(officeList: List) { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.SetOfficeSpinner(officeList) - } - }) - } - - fun fetchStaff(officeId: Int) { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowProgressbar - repository.getStaffInOffice(officeId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - try { - if (e is HttpException) { - val errorMessage = e.response()?.errorBody() - ?.string() - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.ShowError(errorMessage) - } - } catch (throwable: Throwable) { - RxJavaPlugins.getInstance().errorHandler.handleError(e) - } - } - - override fun onNext(staffList: List) { - _newIndividualCollectionSheetUiState.value = - NewIndividualCollectionSheetUiState.SetStaffSpinner(staffList) - } - }) - - } - - fun filterOffices(offices: List): List { - val officesList: MutableList = ArrayList() - Observable.from(offices) - .subscribe { office -> office.name?.let { officesList.add(it) } } - return officesList - } - - fun filterStaff(staffs: List): List { - val staffList: MutableList = ArrayList() - Observable.from(staffs) - .subscribe { staff -> staff.displayName?.let { staffList.add(it) } } - return staffList - } - -} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetViewModel.kt index 548e0941852..c7e3c54db3b 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetViewModel.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/generatecollectionsheet/GenerateCollectionSheetViewModel.kt @@ -4,6 +4,8 @@ import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository import com.mifos.core.network.GenericResponse import com.mifos.core.objects.collectionsheet.AttendanceTypeOption import com.mifos.core.objects.collectionsheet.CenterDetail @@ -17,9 +19,9 @@ import com.mifos.core.objects.group.Group import com.mifos.core.objects.organisation.Office import com.mifos.core.objects.organisation.Staff import com.mifos.mifosxdroid.R -import com.mifos.mifosxdroid.online.collectionsheetindividual.NewIndividualCollectionSheetRepository import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.launch import rx.Observable import rx.Subscriber import rx.android.schedulers.AndroidSchedulers @@ -41,45 +43,30 @@ class GenerateCollectionSheetViewModel @Inject constructor( val generateCollectionSheetUiState: LiveData get() = _generateCollectionSheetUiState - fun loadOffices() { + fun loadOffices() = viewModelScope.launch { _generateCollectionSheetUiState.value = GenerateCollectionSheetUiState.ShowProgressbar - repositoryNewInd.offices() - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - _generateCollectionSheetUiState.value = - GenerateCollectionSheetUiState.ShowError(e.message.toString()) - } - - override fun onNext(offices: List) { - _generateCollectionSheetUiState.value = - GenerateCollectionSheetUiState.ShowOffices(offices) - } - }) + try { + _generateCollectionSheetUiState.value = + GenerateCollectionSheetUiState.ShowOffices(repositoryNewInd.offices()) + } catch (e: Exception) { + _generateCollectionSheetUiState.value = + GenerateCollectionSheetUiState.ShowError(e.message.toString()) + } } - fun loadStaffInOffice(officeId: Int) { + fun loadStaffInOffice(officeId: Int) = viewModelScope.launch { _generateCollectionSheetUiState.value = GenerateCollectionSheetUiState.ShowProgressbar - repositoryNewInd.getStaffInOffice(officeId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() {} - override fun onError(e: Throwable) { - _generateCollectionSheetUiState.value = - GenerateCollectionSheetUiState.ShowError(e.message.toString()) - } - - override fun onNext(staffs: List) { - _generateCollectionSheetUiState.value = - GenerateCollectionSheetUiState.ShowStaffInOffice(staffs, officeId) - } - }) - + try { + _generateCollectionSheetUiState.value = + GenerateCollectionSheetUiState.ShowStaffInOffice( + repositoryNewInd.getStaffInOffice( + officeId + ), officeId + ) + } catch (e: Exception) { + _generateCollectionSheetUiState.value = + GenerateCollectionSheetUiState.ShowError(e.message.toString()) + } } fun loadCentersInOffice(id: Int, params: Map) { diff --git a/settings.gradle.kts b/settings.gradle.kts index f10491afda7..6869a58132c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,6 +18,7 @@ dependencyResolutionManagement { } } +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") rootProject.name = "AndroidClient" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") include(":mifosng-android") @@ -37,4 +38,3 @@ include(":feature:client") include(":feature:checker-inbox-task") include(":feature:collection-sheet") include(":feature:groups") -