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 2c7df10eac2..fd0c8882e41 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,12 +2,14 @@ package com.mifos.core.data.di import com.mifos.core.data.repository.CenterDetailsRepository import com.mifos.core.data.repository.CenterListRepository +import com.mifos.core.data.repository.CheckerInboxRepository import com.mifos.core.data.repository.CheckerInboxTasksRepository import com.mifos.core.data.repository.GroupDetailsRepository import com.mifos.core.data.repository.GroupsListRepository import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository import com.mifos.core.data.repository_imp.CenterDetailsRepositoryImp import com.mifos.core.data.repository_imp.CenterListRepositoryImp +import com.mifos.core.data.repository_imp.CheckerInboxRepositoryImp import com.mifos.core.data.repository_imp.CheckerInboxTasksRepositoryImp import com.mifos.core.data.repository_imp.GroupDetailsRepositoryImp import com.mifos.core.data.repository_imp.GroupsListRepositoryImpl @@ -40,4 +42,7 @@ abstract class DataModule { @Binds internal abstract fun bindCenterDetailsRepository(impl: CenterDetailsRepositoryImp): CenterDetailsRepository + + @Binds + internal abstract fun bindCheckerInboxRepository(impl: CheckerInboxRepositoryImp): CheckerInboxRepository } \ No newline at end of file diff --git a/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxRepository.kt b/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxRepository.kt new file mode 100644 index 00000000000..3e2b4577f36 --- /dev/null +++ b/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxRepository.kt @@ -0,0 +1,23 @@ +package com.mifos.core.data.repository + +import com.mifos.core.network.GenericResponse +import com.mifos.core.objects.checkerinboxandtasks.CheckerInboxSearchTemplate +import com.mifos.core.objects.checkerinboxandtasks.CheckerTask +import kotlinx.coroutines.flow.Flow + +interface CheckerInboxRepository { + + suspend fun loadCheckerTasks( + actionName: String? = null, entityName: String? = null, + resourceId: Int? = null + ): List + + suspend fun approveCheckerEntry(auditId: Int): GenericResponse + + suspend fun rejectCheckerEntry(auditId: Int): GenericResponse + + suspend fun deleteCheckerEntry(auditId: Int): GenericResponse + + suspend fun loadSearchTemplate(): CheckerInboxSearchTemplate + +} \ No newline at end of file diff --git a/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxTasksRepository.kt b/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxTasksRepository.kt index c8b70a79f08..74b75797b31 100644 --- a/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxTasksRepository.kt +++ b/core/data/src/main/java/com/mifos/core/data/repository/CheckerInboxTasksRepository.kt @@ -2,6 +2,7 @@ package com.mifos.core.data.repository import com.mifos.core.objects.checkerinboxandtasks.CheckerTask import com.mifos.core.objects.checkerinboxandtasks.RescheduleLoansTask +import kotlinx.coroutines.flow.Flow import rx.Observable @@ -11,11 +12,11 @@ import rx.Observable interface CheckerInboxTasksRepository { - fun getRescheduleLoansTaskList(): Observable> + suspend fun getRescheduleLoansTaskList(): Flow> - fun getCheckerTaskList( + suspend fun getCheckerTaskList( actionName: String? = null, entityName: String? = null, resourceId: Int? = null - ): Observable> + ): Flow> } \ No newline at end of file diff --git a/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxRepositoryImp.kt b/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxRepositoryImp.kt new file mode 100644 index 00000000000..60448e214fa --- /dev/null +++ b/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxRepositoryImp.kt @@ -0,0 +1,37 @@ +package com.mifos.core.data.repository_imp + +import com.mifos.core.data.repository.CheckerInboxRepository +import com.mifos.core.network.GenericResponse +import com.mifos.core.network.datamanager.DataManagerCheckerInbox +import com.mifos.core.objects.checkerinboxandtasks.CheckerInboxSearchTemplate +import com.mifos.core.objects.checkerinboxandtasks.CheckerTask +import javax.inject.Inject + +class CheckerInboxRepositoryImp @Inject constructor( + private val dataManagerCheckerInbox: DataManagerCheckerInbox +) : CheckerInboxRepository { + + override suspend fun loadCheckerTasks( + actionName: String?, + entityName: String?, + resourceId: Int? + ): List { + return dataManagerCheckerInbox.getCheckerTaskList() + } + + override suspend fun approveCheckerEntry(auditId: Int): GenericResponse { + return dataManagerCheckerInbox.approveCheckerEntry(auditId) + } + + override suspend fun rejectCheckerEntry(auditId: Int): GenericResponse { + return dataManagerCheckerInbox.rejectCheckerEntry(auditId) + } + + override suspend fun deleteCheckerEntry(auditId: Int): GenericResponse { + return dataManagerCheckerInbox.deleteCheckerEntry(auditId) + } + + override suspend fun loadSearchTemplate(): CheckerInboxSearchTemplate { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxTasksRepositoryImp.kt b/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxTasksRepositoryImp.kt index 4a5c181bedc..4a59b169c1a 100644 --- a/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxTasksRepositoryImp.kt +++ b/core/data/src/main/java/com/mifos/core/data/repository_imp/CheckerInboxTasksRepositoryImp.kt @@ -4,7 +4,8 @@ import com.mifos.core.data.repository.CheckerInboxTasksRepository import com.mifos.core.network.datamanager.DataManagerCheckerInbox import com.mifos.core.objects.checkerinboxandtasks.CheckerTask import com.mifos.core.objects.checkerinboxandtasks.RescheduleLoansTask -import rx.Observable +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import javax.inject.Inject @@ -15,15 +16,15 @@ import javax.inject.Inject class CheckerInboxTasksRepositoryImp @Inject constructor(private val dataManagerCheckerInbox: DataManagerCheckerInbox) : CheckerInboxTasksRepository { - override fun getRescheduleLoansTaskList(): Observable> { - return dataManagerCheckerInbox.getRechdeduleLoansTaskList() + override suspend fun getRescheduleLoansTaskList(): Flow> { + return flow { emit(dataManagerCheckerInbox.getRechdeduleLoansTaskList()) } } - override fun getCheckerTaskList( + override suspend fun getCheckerTaskList( actionName: String?, entityName: String?, resourceId: Int? - ): Observable> { - return dataManagerCheckerInbox.getCheckerTaskList() + ): Flow> { + return flow { emit(dataManagerCheckerInbox.getCheckerTaskList()) } } } \ No newline at end of file diff --git a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/CheckerTask.kt b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/CheckerTask.kt index 5f03874c370..76381e2c625 100644 --- a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/CheckerTask.kt +++ b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/CheckerTask.kt @@ -1,17 +1,21 @@ package com.mifos.core.objects.checkerinboxandtasks -import com.google.gson.annotations.SerializedName +import android.os.Parcelable +import kotlinx.parcelize.Parcelize import java.sql.Timestamp import java.text.SimpleDateFormat import java.util.Date -data class CheckerTask(@SerializedName("id") var id: Int, - @SerializedName("madeOnDate") var madeOnDate: Long, - @SerializedName("processingResult") var status: String, - @SerializedName("maker") var maker: String, - @SerializedName("actionName") var action: String, - @SerializedName("entityName") var entity: String, - @SerializedName("resourceId") var resourceId: String) { +@Parcelize +data class CheckerTask( + var id: Int, + var madeOnDate: Long, + var processingResult: String, + var maker: String, + var actionName: String, + var entityName: String, + var resourceId: String +) : Parcelable { var selectedFlag = false diff --git a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleLoansTask.kt b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleLoansTask.kt index 0ef659b230f..da5ae0d1c16 100644 --- a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleLoansTask.kt +++ b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleLoansTask.kt @@ -1,11 +1,15 @@ package com.mifos.core.objects.checkerinboxandtasks +import android.os.Parcelable import com.google.gson.annotations.SerializedName +import kotlinx.parcelize.Parcelize -data class RescheduleLoansTask (@SerializedName("id") var id: Int, - @SerializedName("clientName") var clientName: String, - @SerializedName("loanAccountNumber") var loanAccountNo: String, - @SerializedName("rescheduleFromDate") var rescheduleFromDate: Array, - @SerializedName("actionName") var action: String, - @SerializedName("rescheduleReasonCodeValue") - var rescheduleReasonCodeValue: RescheduleReasonCodeValue) \ No newline at end of file +@Parcelize +data class RescheduleLoansTask( + var id: Int, + var clientName: String, + var loanAccountNumber: String, + var rescheduleFromDate: Array, + var actionName: String, + var rescheduleReasonCodeValue: RescheduleReasonCodeValue +) : Parcelable \ No newline at end of file diff --git a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleReasonCodeValue.kt b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleReasonCodeValue.kt index 980612ade4c..134bbfddf97 100644 --- a/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleReasonCodeValue.kt +++ b/core/database/src/main/java/com/mifos/core/objects/checkerinboxandtasks/RescheduleReasonCodeValue.kt @@ -1,4 +1,12 @@ package com.mifos.core.objects.checkerinboxandtasks -data class RescheduleReasonCodeValue (var id : Int, var name : String, - var active : Boolean, var mandatory : Boolean) \ No newline at end of file +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class RescheduleReasonCodeValue( + var id: Int, + var name: String, + var active: Boolean, + var mandatory: Boolean +) : Parcelable \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosAlertDailog.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosAlertDailog.kt new file mode 100644 index 00000000000..76ed83e847e --- /dev/null +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/component/MifosAlertDailog.kt @@ -0,0 +1,44 @@ +package com.mifos.core.designsystem.component + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource + +@Composable +fun MifosDialogBox( + showDialogState: Boolean, + onDismiss: () -> Unit, + title: Int, + message: Int? = null, + confirmButtonText: Int, + onConfirm: () -> Unit, + dismissButtonText: Int +) { + if (showDialogState) { + AlertDialog( + onDismissRequest = onDismiss, + title = { Text(text = stringResource(id = title)) }, + text = { + if (message != null) { + Text(text = stringResource(id = message)) + } + }, + confirmButton = { + TextButton( + onClick = { + onConfirm() + } + ) { + Text(stringResource(id = confirmButtonText)) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(stringResource(id = dismissButtonText)) + } + } + ) + } +} diff --git a/core/designsystem/src/main/java/com/mifos/core/designsystem/icon/MifosIcon.kt b/core/designsystem/src/main/java/com/mifos/core/designsystem/icon/MifosIcon.kt index c115021a779..f9764397a57 100644 --- a/core/designsystem/src/main/java/com/mifos/core/designsystem/icon/MifosIcon.kt +++ b/core/designsystem/src/main/java/com/mifos/core/designsystem/icon/MifosIcon.kt @@ -6,7 +6,13 @@ import androidx.compose.material.icons.outlined.EventRepeat import androidx.compose.material.icons.outlined.Group import androidx.compose.material.icons.rounded.Add import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material.icons.rounded.Check +import androidx.compose.material.icons.rounded.Close +import androidx.compose.material.icons.rounded.Delete +import androidx.compose.material.icons.rounded.FilterList import androidx.compose.material.icons.rounded.PersonOutline +import androidx.compose.material.icons.rounded.Search +import androidx.compose.material.icons.rounded.Sync object MifosIcons { val Add = Icons.Rounded.Add @@ -15,4 +21,10 @@ object MifosIcons { val eventRepeat = Icons.Outlined.EventRepeat val date = Icons.Outlined.DateRange val arrowBack = Icons.Rounded.ArrowBackIosNew + val search = Icons.Rounded.Search + val filter = Icons.Rounded.FilterList + val sync = Icons.Rounded.Sync + val check = Icons.Rounded.Check + val close = Icons.Rounded.Close + val delete = Icons.Rounded.Delete } \ No newline at end of file diff --git a/core/domain/src/main/java/com/mifos/core/domain/use_cases/ApproveCheckerUseCase.kt b/core/domain/src/main/java/com/mifos/core/domain/use_cases/ApproveCheckerUseCase.kt new file mode 100644 index 00000000000..c013d0982f4 --- /dev/null +++ b/core/domain/src/main/java/com/mifos/core/domain/use_cases/ApproveCheckerUseCase.kt @@ -0,0 +1,21 @@ +package com.mifos.core.domain.use_cases + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.CheckerInboxRepository +import com.mifos.core.network.GenericResponse +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class ApproveCheckerUseCase @Inject constructor(val repository: CheckerInboxRepository) { + + suspend operator fun invoke(auditId: Int): Flow> = flow { + try { + emit(Resource.Loading()) + val response = repository.approveCheckerEntry(auditId) + emit(Resource.Success(response)) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/mifos/core/domain/use_cases/DeleteCheckerUseCase.kt b/core/domain/src/main/java/com/mifos/core/domain/use_cases/DeleteCheckerUseCase.kt new file mode 100644 index 00000000000..477dd622c12 --- /dev/null +++ b/core/domain/src/main/java/com/mifos/core/domain/use_cases/DeleteCheckerUseCase.kt @@ -0,0 +1,22 @@ +package com.mifos.core.domain.use_cases + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.CheckerInboxRepository +import com.mifos.core.network.GenericResponse +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class DeleteCheckerUseCase @Inject constructor(private val repository: CheckerInboxRepository) { + + operator fun invoke(auditId: Int): Flow> = flow { + try { + emit(Resource.Loading()) + val response = repository.deleteCheckerEntry(auditId) + emit(Resource.Success(response)) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } + +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerInboxBadgesUseCase.kt b/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerInboxBadgesUseCase.kt index 00a0a90cfff..59359eec6e3 100644 --- a/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerInboxBadgesUseCase.kt +++ b/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerInboxBadgesUseCase.kt @@ -2,13 +2,9 @@ package com.mifos.core.domain.use_cases import com.mifos.core.common.utils.Resource import com.mifos.core.data.repository.CheckerInboxTasksRepository -import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import rx.Observable -import rx.Subscriber -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.zip import javax.inject.Inject @@ -19,33 +15,17 @@ import javax.inject.Inject class GetCheckerInboxBadgesUseCase @Inject constructor( private val repository: CheckerInboxTasksRepository ) { - operator fun invoke(): Flow>> = callbackFlow { + operator fun invoke(): Flow>> = flow { try { - trySend(Resource.Loading()) - Observable.zip( - repository.getCheckerTaskList(), - repository.getRescheduleLoansTaskList() - ) { checkerTasks, rescheduleLoanTasks -> - Pair(checkerTasks.size, rescheduleLoanTasks.size) - }.observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() { - - } - - override fun onError(error: Throwable) { - trySend(Resource.Error(error.message.toString())) - } - - override fun onNext(badges: Pair) { - trySend(Resource.Success(badges)) - } - }) - - awaitClose { channel.close() } + emit(Resource.Loading()) + repository.getCheckerTaskList() + .zip(repository.getRescheduleLoansTaskList()) { checkerTasks, rescheduleLoanTasks -> + Pair(checkerTasks.size, rescheduleLoanTasks.size) + }.collect { + emit(Resource.Success(it)) + } } catch (e: Exception) { - trySend(Resource.Error(e.message.toString())) + emit(Resource.Error(e.message.toString())) } } } \ No newline at end of file diff --git a/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerTasksUseCase.kt b/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerTasksUseCase.kt new file mode 100644 index 00000000000..f9246290f8a --- /dev/null +++ b/core/domain/src/main/java/com/mifos/core/domain/use_cases/GetCheckerTasksUseCase.kt @@ -0,0 +1,24 @@ +package com.mifos.core.domain.use_cases + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.CheckerInboxRepository +import com.mifos.core.objects.checkerinboxandtasks.CheckerTask +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetCheckerTasksUseCase @Inject constructor(private val repository: CheckerInboxRepository) { + + suspend operator fun invoke( + actionName: String? = null, entityName: String? = null, + resourceId: Int? = null + ): Flow>> = flow { + try { + emit(Resource.Loading()) + val response = repository.loadCheckerTasks(actionName, entityName, resourceId) + emit(Resource.Success(response)) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/mifos/core/domain/use_cases/RejectCheckerUseCase.kt b/core/domain/src/main/java/com/mifos/core/domain/use_cases/RejectCheckerUseCase.kt new file mode 100644 index 00000000000..317eec83cd0 --- /dev/null +++ b/core/domain/src/main/java/com/mifos/core/domain/use_cases/RejectCheckerUseCase.kt @@ -0,0 +1,21 @@ +package com.mifos.core.domain.use_cases + +import com.mifos.core.common.utils.Resource +import com.mifos.core.data.repository.CheckerInboxRepository +import com.mifos.core.network.GenericResponse +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class RejectCheckerUseCase @Inject constructor(private val repository: CheckerInboxRepository) { + + operator fun invoke(auditId: Int): Flow> = flow { + try { + emit(Resource.Loading()) + val response = repository.rejectCheckerEntry(auditId) + emit(Resource.Success(response)) + } catch (exception: Exception) { + emit(Resource.Error(exception.message.toString())) + } + } +} \ No newline at end of file diff --git a/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCheckerInbox.kt b/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCheckerInbox.kt index 359c483dca3..11d4b632974 100644 --- a/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCheckerInbox.kt +++ b/core/network/src/main/java/com/mifos/core/network/datamanager/DataManagerCheckerInbox.kt @@ -14,28 +14,28 @@ class DataManagerCheckerInbox @Inject constructor( ) { - fun getCheckerTaskList( + suspend fun getCheckerTaskList( actionName: String? = null, entityName: String? = null, resourceId: Int? = null - ): Observable> { + ): List { return mBaseApiManager.checkerInboxApi.getCheckerList( actionName, entityName, resourceId ) } - fun approveCheckerEntry(auditId: Int): Observable { + suspend fun approveCheckerEntry(auditId: Int): GenericResponse { return mBaseApiManager.checkerInboxApi.approveCheckerEntry(auditId) } - fun rejectCheckerEntry(auditId: Int): Observable { + suspend fun rejectCheckerEntry(auditId: Int): GenericResponse { return mBaseApiManager.checkerInboxApi.rejectCheckerEntry(auditId) } - fun deleteCheckerEntry(auditId: Int): Observable { + suspend fun deleteCheckerEntry(auditId: Int): GenericResponse { return mBaseApiManager.checkerInboxApi.deleteCheckerEntry(auditId) } - fun getRechdeduleLoansTaskList(): Observable> { + suspend fun getRechdeduleLoansTaskList(): List { return mBaseApiManager.checkerInboxApi.getRescheduleLoansTaskList() } diff --git a/core/network/src/main/java/com/mifos/core/network/services/CheckerInboxService.kt b/core/network/src/main/java/com/mifos/core/network/services/CheckerInboxService.kt index 837110789ba..71650ef4162 100644 --- a/core/network/src/main/java/com/mifos/core/network/services/CheckerInboxService.kt +++ b/core/network/src/main/java/com/mifos/core/network/services/CheckerInboxService.kt @@ -5,29 +5,30 @@ import com.mifos.core.network.GenericResponse import com.mifos.core.objects.checkerinboxandtasks.CheckerInboxSearchTemplate import com.mifos.core.objects.checkerinboxandtasks.CheckerTask import com.mifos.core.objects.checkerinboxandtasks.RescheduleLoansTask +import kotlinx.coroutines.flow.Flow import retrofit2.http.* import rx.Observable interface CheckerInboxService { @GET(APIEndPoint.MAKER_CHECKER) - fun getCheckerList( + suspend fun getCheckerList( @Query("actionName") actionName: String? = null, @Query("entityName") entityName: String? = null, @Query("resourceId") resourceId: Int? = null - ): Observable> + ): List @POST(APIEndPoint.MAKER_CHECKER + "/{auditId}?command=approve") - fun approveCheckerEntry(@Path("auditId") auditId: Int): Observable + suspend fun approveCheckerEntry(@Path("auditId") auditId: Int): GenericResponse @POST(APIEndPoint.MAKER_CHECKER + "/{auditId}?command=reject") - fun rejectCheckerEntry(@Path("auditId") auditId: Int): Observable + suspend fun rejectCheckerEntry(@Path("auditId") auditId: Int): GenericResponse @DELETE(APIEndPoint.MAKER_CHECKER + "/{auditId}") - fun deleteCheckerEntry(@Path("auditId") auditId: Int): Observable + suspend fun deleteCheckerEntry(@Path("auditId") auditId: Int): GenericResponse @GET("rescheduleloans?command=pending") - fun getRescheduleLoansTaskList(): Observable> + suspend fun getRescheduleLoansTaskList(): List @GET(APIEndPoint.MAKER_CHECKER + "/searchtemplate?fields=entityNames,actionNames") fun getCheckerInboxSearchTempalate(): Observable diff --git a/core/ui/src/main/java/com/mifos/core/ui/components/MifosToolbar.kt b/core/ui/src/main/java/com/mifos/core/ui/components/MifosToolbar.kt index 118e2a9458c..c4953151d6a 100644 --- a/core/ui/src/main/java/com/mifos/core/ui/components/MifosToolbar.kt +++ b/core/ui/src/main/java/com/mifos/core/ui/components/MifosToolbar.kt @@ -1,5 +1,6 @@ package com.mifos.core.ui.components +import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Sync @@ -20,9 +21,9 @@ import com.mifos.core.designsystem.theme.BlueSecondary fun SelectionModeTopAppBar( modifier: Modifier = Modifier, itemCount: Int, - syncClicked: () -> Unit, resetSelectionMode: () -> Unit, containerColor: Color = BlueSecondary, + actions : @Composable RowScope.() -> Unit = {} ) { TopAppBar( modifier = modifier, @@ -42,19 +43,6 @@ fun SelectionModeTopAppBar( ) } }, - actions = { - FilledTonalButton( - onClick = { - syncClicked() - resetSelectionMode() - }, - ) { - Icon( - imageVector = Icons.Rounded.Sync, - contentDescription = "Sync Items", - ) - Text(text = "Sync") - } - } + actions = actions ) } \ No newline at end of file diff --git a/feature/center/src/main/java/com/mifos/feature/center/center_list/ui/CenterListScreen.kt b/feature/center/src/main/java/com/mifos/feature/center/center_list/ui/CenterListScreen.kt index 10d466d0504..e529ebb36d9 100644 --- a/feature/center/src/main/java/com/mifos/feature/center/center_list/ui/CenterListScreen.kt +++ b/feature/center/src/main/java/com/mifos/feature/center/center_list/ui/CenterListScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.CardDefaults +import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedCard @@ -140,8 +141,21 @@ fun CenterListScreen( if (isInSelectionMode) { SelectionModeTopAppBar( itemCount = selectedItems.size, - syncClicked = { syncClicked(selectedItems.toList()) }, - resetSelectionMode = resetSelectionMode + resetSelectionMode = resetSelectionMode, + actions = { + FilledTonalButton( + onClick = { + syncClicked(selectedItems.toList()) + resetSelectionMode() + }, + ) { + Icon( + imageVector = MifosIcons.sync, + contentDescription = "Sync Items", + ) + Text(text = stringResource(id = R.string.feature_center_sync)) + } + } ) } }, diff --git a/feature/center/src/main/res/values/strings.xml b/feature/center/src/main/res/values/strings.xml index 2a5b05610a1..f43464f4e1f 100644 --- a/feature/center/src/main/res/values/strings.xml +++ b/feature/center/src/main/res/values/strings.xml @@ -25,4 +25,5 @@ Summary Info Activate Center + Sync \ No newline at end of file diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxScreen.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxScreen.kt new file mode 100644 index 00000000000..6c3f61f541e --- /dev/null +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxScreen.kt @@ -0,0 +1,616 @@ +@file:OptIn( + ExperimentalMaterial3Api::class, ExperimentalMaterial3Api::class, + ExperimentalFoundationApi::class +) + +package com.mifos.feature.checker_inbox_task.checker_inbox.ui + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +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.TextField +import androidx.compose.material3.TextFieldDefaults +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 +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.SnapshotStateList +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.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.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.MifosDialogBox +import com.mifos.core.designsystem.component.MifosSweetError +import com.mifos.core.designsystem.icon.MifosIcons +import com.mifos.core.designsystem.theme.Black +import com.mifos.core.designsystem.theme.LightGray +import com.mifos.core.designsystem.theme.White +import com.mifos.core.objects.checkerinboxandtasks.CheckerTask +import com.mifos.core.ui.components.SelectionModeTopAppBar +import com.mifos.feature.checker_inbox_task.R + +@Composable +fun CheckerInboxScreen( + onBackPressed: () -> Unit, + filter: () -> Unit +) { + + val viewModel: CheckerInboxViewModel = hiltViewModel() + val state by viewModel.checkerInboxUiState.collectAsStateWithLifecycle() + + LaunchedEffect(key1 = true) { + viewModel.loadCheckerTasks() + } + + CheckerInboxScreen( + state = state, + onBackPressed = onBackPressed, + onApprove = { viewModel.approveCheckerEntry(it) }, + onReject = { viewModel.rejectCheckerEntry(it) }, + onDelete = { viewModel.deleteCheckerEntry(it) }, + onRetry = { viewModel.loadCheckerTasks() }, + onApproveList = { list -> + list.forEach { + viewModel.approveCheckerEntry(it) + } + }, + onRejectList = { list -> + list.forEach { + viewModel.rejectCheckerEntry(it) + } + }, + onDeleteList = { list -> + list.forEach { + viewModel.deleteCheckerEntry(it) + } + }, + filter = filter + ) +} + +@Composable +fun CheckerInboxScreen( + state: CheckerInboxUiState, + onBackPressed: () -> Unit, + onApprove: (Int) -> Unit, + onReject: (Int) -> Unit, + onDelete: (Int) -> Unit, + onRetry: () -> Unit = {}, + onApproveList: (List) -> Unit, + onRejectList: (List) -> Unit, + onDeleteList: (List) -> Unit, + filter: () -> Unit +) { + + val snackbarHostState = remember { SnackbarHostState() } + var searchInbox by rememberSaveable { mutableStateOf("") } + var approveId by rememberSaveable { mutableIntStateOf(0) } + var showApproveDialog by rememberSaveable { mutableStateOf(false) } + var rejectId by rememberSaveable { mutableIntStateOf(0) } + var showRejectDialog by rememberSaveable { mutableStateOf(false) } + var deleteId by rememberSaveable { mutableIntStateOf(0) } + var showDeleteDialog by rememberSaveable { mutableStateOf(false) } + + var isInSelectionMode by rememberSaveable { mutableStateOf(false) } + val selectedItems = remember { mutableStateListOf() } + + val resetSelectionMode = { + isInSelectionMode = false + selectedItems.clear() + } + BackHandler(enabled = isInSelectionMode) { + resetSelectionMode() + } + LaunchedEffect( + key1 = isInSelectionMode, + key2 = selectedItems.size, + ) { + if (isInSelectionMode && selectedItems.isEmpty()) { + isInSelectionMode = false + } + } + + + MifosDialogBox( + showDialogState = showApproveDialog, + onDismiss = { showApproveDialog = false }, + title = R.string.feature_checker_inbox_task_are_you_sure_you_want_to_approve_this_task, + confirmButtonText = R.string.feature_checker_inbox_task_yes, + onConfirm = { + onApprove(approveId) + showApproveDialog = false + }, + dismissButtonText = R.string.feature_checker_inbox_task_no + ) + + MifosDialogBox( + showDialogState = showRejectDialog, + onDismiss = { showRejectDialog = false }, + title = R.string.feature_checker_inbox_task_are_you_sure_you_want_to_reject_this_task, + confirmButtonText = R.string.feature_checker_inbox_task_yes, + onConfirm = { + onReject(rejectId) + showRejectDialog = false + }, + dismissButtonText = R.string.feature_checker_inbox_task_no + ) + + + MifosDialogBox( + showDialogState = showDeleteDialog, + onDismiss = { showDeleteDialog = false }, + title = R.string.feature_checker_inbox_task_are_you_sure_you_want_to_delete_this_task, + confirmButtonText = R.string.feature_checker_inbox_task_yes, + onConfirm = { + onDelete(deleteId) + showDeleteDialog = false + }, + dismissButtonText = R.string.feature_checker_inbox_task_no + ) + + Scaffold( + topBar = { + if (isInSelectionMode) { + SelectionModeTopAppBar( + itemCount = selectedItems.size, + resetSelectionMode = resetSelectionMode, + actions = { + IconButton(onClick = { + onApproveList(selectedItems) + resetSelectionMode() + }) { + Icon( + imageVector = MifosIcons.check, + tint = Color.Green, + contentDescription = null + ) + } + IconButton(onClick = { + onRejectList(selectedItems) + resetSelectionMode() + }) { + Icon( + imageVector = MifosIcons.close, + tint = Color.Yellow, + contentDescription = null + ) + } + IconButton(onClick = { + onDeleteList(selectedItems) + resetSelectionMode() + }) { + Icon( + imageVector = MifosIcons.delete, + tint = Color.Red, + contentDescription = null + ) + } + } + ) + } else { + TopAppBar( + colors = TopAppBarDefaults.mediumTopAppBarColors(containerColor = White), + navigationIcon = { + IconButton( + onClick = { onBackPressed() }, + ) { + Icon( + imageVector = MifosIcons.arrowBack, + contentDescription = null, + tint = Black, + ) + } + + }, + title = { + Text( + text = stringResource(id = R.string.feature_checker_inbox_task_checker_inbox), + style = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Medium, + fontStyle = FontStyle.Normal + ), + color = Black, + textAlign = TextAlign.Start + ) + }, + actions = { } + ) + } + }, + snackbarHost = { SnackbarHost(snackbarHostState) }, + contentColor = Color.White + ) { paddingValues -> + Column(modifier = Modifier.padding(paddingValues)) { + ElevatedCard( + modifier = Modifier.padding(8.dp), + elevation = CardDefaults.elevatedCardElevation(4.dp), + colors = CardDefaults.elevatedCardColors(White) + ) { + Row( + modifier = Modifier.padding(4.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + modifier = Modifier.weight(1f), + imageVector = MifosIcons.search, + contentDescription = null + ) + TextField( + modifier = Modifier + .height(52.dp) + .weight(4f), + value = searchInbox, + onValueChange = { + searchInbox = it + }, + placeholder = { Text(stringResource(id = R.string.feature_checker_inbox_task_search_by_user)) }, + colors = TextFieldDefaults.colors( + focusedContainerColor = White, + unfocusedContainerColor = White, + focusedIndicatorColor = Color.White, + unfocusedIndicatorColor = Color.White + ) + ) + IconButton(modifier = Modifier.weight(1f), onClick = { filter() }) { + Icon( + imageVector = MifosIcons.filter, + contentDescription = null + ) + } + } + } + + when (state) { + is CheckerInboxUiState.CheckerTasksList -> { + CheckerInboxContent( + checkerTaskList = state.checkerTasks.filter { checkerTask -> + checkerTask.maker.contains(searchInbox) + }, + onApprove = { + approveId = it + showApproveDialog = true + }, + onReject = { + rejectId = it + showRejectDialog = true + }, + onDelete = { + deleteId = it + showDeleteDialog = true + }, + isInSelectionMode = isInSelectionMode, + selectedItems = selectedItems, + selectedMode = { + isInSelectionMode = true + } + ) + } + + is CheckerInboxUiState.Error -> { + MifosSweetError( + message = stringResource(id = R.string.feature_checker_inbox_task_failed_to_Load_Check_Inbox) + ) { + onRetry() + } + } + + is CheckerInboxUiState.Loading -> { + MifosCircularProgress() + } + + is CheckerInboxUiState.SuccessResponse -> { + val message = stringResource(state.message) + LaunchedEffect(key1 = message) { + snackbarHostState.showSnackbar(message = message) + } + } + } + + } + } + +} + +@Composable +fun CheckerInboxContent( + checkerTaskList: List, + onApprove: (Int) -> Unit, + onReject: (Int) -> Unit, + onDelete: (Int) -> Unit, + isInSelectionMode: Boolean, + selectedItems: SnapshotStateList, + selectedMode: () -> Unit +) { + LazyColumn { + items(checkerTaskList.size) { index -> + CheckerInboxItem( + checkerTask = checkerTaskList[index], + onApprove = onApprove, + onReject = onReject, + onDelete = onDelete, + isInSelectionMode = isInSelectionMode, + selectedItems = selectedItems, + selectedMode = selectedMode + ) + } + } +} + + +@Composable +fun CheckerInboxItem( + checkerTask: CheckerTask, + onApprove: (Int) -> Unit, + onReject: (Int) -> Unit, + onDelete: (Int) -> Unit, + isInSelectionMode: Boolean, + selectedItems: SnapshotStateList, + selectedMode: () -> Unit +) { + val isSelected = selectedItems.contains(checkerTask.id) + var cardColor by remember { mutableStateOf(White) } + + var expendCheckerTask by remember { mutableStateOf(false) } + + Card( + modifier = Modifier + .fillMaxWidth() + .combinedClickable( + onClick = { + if (isInSelectionMode) { + cardColor = if (isSelected) { + selectedItems.remove(checkerTask.id) + White + } else { + selectedItems.add(checkerTask.id) + LightGray + } + } else { + expendCheckerTask = expendCheckerTask.not() + } + }, + onLongClick = { + if (isInSelectionMode) { + cardColor = if (isSelected) { + selectedItems.remove(checkerTask.id) + White + } else { + selectedItems.add(checkerTask.id) + LightGray + } + } else { + selectedMode() + selectedItems.add(checkerTask.id) + cardColor = LightGray + } + } + ), + colors = CardDefaults.cardColors( + containerColor = if (selectedItems.isEmpty()) { + cardColor = White + White + } else cardColor, + ) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Card( + modifier = Modifier + .width(8.dp) + .height(60.dp), colors = CardDefaults.cardColors(Color.Yellow) + ) { + } + Column( + modifier = Modifier.padding(16.dp) + ) { + Text( + text = "# ${checkerTask.id} ${checkerTask.actionName} ${checkerTask.entityName}", + style = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.Medium, + color = Black + ) + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = checkerTask.processingResult, + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Normal, + ) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row { + Text( + text = stringResource(id = R.string.feature_checker_inbox_task_create_by), + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Normal, + ) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = checkerTask.maker, + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + ) + ) + } + Text( + text = checkerTask.getDate(), + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + ) + ) + } + } + } + HorizontalDivider() + if (expendCheckerTask) { + Column(modifier = Modifier.padding(8.dp)) { + Text( + text = checkerTask.entityName, + style = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.Medium, + color = Black + ) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + IconButton(onClick = { onApprove(checkerTask.id) }) { + Icon( + imageVector = MifosIcons.check, + tint = Color.Green, + contentDescription = null + ) + } + IconButton(onClick = { onReject(checkerTask.id) }) { + Icon( + imageVector = MifosIcons.close, + tint = Color.Yellow, + contentDescription = null + ) + } + IconButton(onClick = { onDelete(checkerTask.id) }) { + Icon( + imageVector = MifosIcons.delete, + tint = Color.Red, + contentDescription = null + ) + } + } + Text( + modifier = Modifier.fillMaxWidth(), + text = checkerTask.getDate(), + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + ), + textAlign = TextAlign.Center + ) + } + HorizontalDivider() + } + } +} + +class CheckerInboxUiStateProvider : PreviewParameterProvider { + + override val values: Sequence + get() = sequenceOf( + CheckerInboxUiState.Loading, + CheckerInboxUiState.Error(R.string.feature_checker_inbox_task_failed_to_Load_Check_Inbox), + CheckerInboxUiState.CheckerTasksList(sampleCheckerTaskList), + CheckerInboxUiState.SuccessResponse(R.string.feature_checker_inbox_task_client_Approval) + ) +} + +@Preview +@Composable +private fun CheckerInboxItemPreview() { + CheckerInboxItem( + checkerTask = sampleCheckerTaskList[0], + onApprove = {}, + onReject = {}, + onDelete = {}, + isInSelectionMode = false, + selectedItems = remember { mutableStateListOf() }, + selectedMode = {} + ) +} + +@Preview(showBackground = true) +@Composable +private fun CheckerInboxContentPreview() { + CheckerInboxContent( + checkerTaskList = sampleCheckerTaskList, + onApprove = {}, + onReject = {}, + onDelete = {}, + isInSelectionMode = false, + selectedItems = remember { mutableStateListOf() }, + selectedMode = {} + ) +} + +@Preview(showBackground = true) +@Composable +private fun CheckerInboxScreenPreview( + @PreviewParameter(CheckerInboxUiStateProvider::class) state: CheckerInboxUiState +) { + CheckerInboxScreen( + state = state, + onBackPressed = {}, + onApprove = {}, + onReject = {}, + onDelete = {}, + onApproveList = {}, + onRejectList = {}, + onDeleteList = {}, + filter = {} + ) +} + +val sampleCheckerTaskList = List(10) { + CheckerTask( + id = it, + madeOnDate = it.toLong(), + processingResult = (it % 2 == 0).toString(), + maker = "maker $it", + actionName = "action $it", + entityName = "entity $it", + resourceId = "resourceId $it" + ) +} \ No newline at end of file diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxUiState.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxUiState.kt new file mode 100644 index 00000000000..1a904d83356 --- /dev/null +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxUiState.kt @@ -0,0 +1,15 @@ +package com.mifos.feature.checker_inbox_task.checker_inbox.ui + +import com.mifos.core.objects.checkerinboxandtasks.CheckerInboxSearchTemplate +import com.mifos.core.objects.checkerinboxandtasks.CheckerTask + +sealed class CheckerInboxUiState { + + data object Loading : CheckerInboxUiState() + + data class Error(val message: Int) : CheckerInboxUiState() + + data class CheckerTasksList(val checkerTasks: List) : CheckerInboxUiState() + + data class SuccessResponse(val message: Int) : CheckerInboxUiState() +} \ No newline at end of file diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxViewModel.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxViewModel.kt new file mode 100644 index 00000000000..e484e6808a4 --- /dev/null +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox/ui/CheckerInboxViewModel.kt @@ -0,0 +1,99 @@ +package com.mifos.feature.checker_inbox_task.checker_inbox.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mifos.core.common.utils.Resource +import com.mifos.core.domain.use_cases.ApproveCheckerUseCase +import com.mifos.core.domain.use_cases.DeleteCheckerUseCase +import com.mifos.core.domain.use_cases.GetCheckerTasksUseCase +import com.mifos.core.domain.use_cases.RejectCheckerUseCase +import com.mifos.feature.checker_inbox_task.R +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 CheckerInboxViewModel @Inject constructor( + val getCheckerInboxUseCase: GetCheckerTasksUseCase, + val approveCheckerUseCase: ApproveCheckerUseCase, + val rejectCheckerUseCase: RejectCheckerUseCase, + val deleteCheckerUseCase: DeleteCheckerUseCase +) : ViewModel() { + + private val _checkerInboxUiState = + MutableStateFlow(CheckerInboxUiState.Loading) + val checkerInboxUiState = _checkerInboxUiState.asStateFlow() + + + fun loadCheckerTasks( + actionName: String? = null, + entityName: String? = null, + resourceId: Int? = null + ) = viewModelScope.launch(Dispatchers.IO) { + getCheckerInboxUseCase(actionName, entityName, resourceId).collect { result -> + when (result) { + is Resource.Error -> _checkerInboxUiState.value = + CheckerInboxUiState.Error(R.string.feature_checker_inbox_task_failed_to_Load_Check_Inbox) + + is Resource.Loading -> _checkerInboxUiState.value = CheckerInboxUiState.Loading + + is Resource.Success -> _checkerInboxUiState.value = + CheckerInboxUiState.CheckerTasksList(result.data ?: emptyList()) + } + } + } + + fun approveCheckerEntry(auditId: Int) = viewModelScope.launch(Dispatchers.IO) { + approveCheckerUseCase(auditId).collect { result -> + when (result) { + is Resource.Error -> _checkerInboxUiState.value = + CheckerInboxUiState.Error(R.string.feature_checker_inbox_task_failed_to_approve) + + is Resource.Loading -> Unit + + is Resource.Success -> { + loadCheckerTasks() + _checkerInboxUiState.value = + CheckerInboxUiState.SuccessResponse(R.string.feature_checker_inbox_task_approve_success) + } + } + } + } + + fun rejectCheckerEntry(auditId: Int) = viewModelScope.launch(Dispatchers.IO) { + rejectCheckerUseCase(auditId).collect { result -> + when (result) { + is Resource.Error -> _checkerInboxUiState.value = + CheckerInboxUiState.Error(R.string.feature_checker_inbox_task_failed_to_reject) + + is Resource.Loading -> Unit + + is Resource.Success -> { + loadCheckerTasks() + _checkerInboxUiState.value = + CheckerInboxUiState.SuccessResponse(R.string.feature_checker_inbox_task_reject_success) + } + } + } + } + + fun deleteCheckerEntry(auditId: Int) = viewModelScope.launch(Dispatchers.IO) { + deleteCheckerUseCase(auditId).collect { result -> + when (result) { + is Resource.Error -> _checkerInboxUiState.value = + CheckerInboxUiState.Error(R.string.feature_checker_inbox_task_failed_to_delete) + + is Resource.Loading -> Unit + + is Resource.Success -> { + loadCheckerTasks() + _checkerInboxUiState.value = + CheckerInboxUiState.SuccessResponse(R.string.feature_checker_inbox_task_delete_success) + } + } + } + } +} \ No newline at end of file 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/checker_inbox_tasks/ui/CheckerInboxTasksScreen.kt similarity index 97% rename from feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksScreen.kt rename to feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksScreen.kt index 4aca866d34a..e7f166127d1 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/checker_inbox_tasks/ui/CheckerInboxTasksScreen.kt @@ -1,6 +1,4 @@ -@file:OptIn(ExperimentalMaterial3Api::class) - -package com.mifos.feature.checker_inbox_task.ui +package com.mifos.feature.checker_inbox_task.checker_inbox_tasks.ui import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -10,7 +8,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksUiState.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksUiState.kt similarity index 83% rename from feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksUiState.kt rename to feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksUiState.kt index 7538a0e67ad..a8d433a7620 100644 --- a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksUiState.kt +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksUiState.kt @@ -1,4 +1,4 @@ -package com.mifos.feature.checker_inbox_task.ui +package com.mifos.feature.checker_inbox_task.checker_inbox_tasks.ui /** diff --git a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksViewModel.kt b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksViewModel.kt similarity index 95% rename from feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksViewModel.kt rename to feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksViewModel.kt index bf5f455b316..a0694878bc2 100644 --- a/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/ui/CheckerInboxTasksViewModel.kt +++ b/feature/checker-inbox-task/src/main/java/com/mifos/feature/checker_inbox_task/checker_inbox_tasks/ui/CheckerInboxTasksViewModel.kt @@ -1,5 +1,6 @@ -package com.mifos.feature.checker_inbox_task.ui +package com.mifos.feature.checker_inbox_task.checker_inbox_tasks.ui +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mifos.core.common.utils.Resource diff --git a/feature/checker-inbox-task/src/main/res/values/strings.xml b/feature/checker-inbox-task/src/main/res/values/strings.xml index 389cee72690..e3405949dcf 100644 --- a/feature/checker-inbox-task/src/main/res/values/strings.xml +++ b/feature/checker-inbox-task/src/main/res/values/strings.xml @@ -9,4 +9,19 @@ Loan Disbursal Reschedule Loan + Checker Inbox + Failed to Approve + Approve Successfully + Failed to Reject + Reject Successfully + Failed to Delete + Delete Successfully + Created by + Search by user + Are you sure you want to approve this task? + Are you sure you want to reject this task? + Are you sure you want to delete this task? + Yes + No + \ No newline at end of file diff --git a/feature/groups/src/main/java/com/mifos/feature/groupsList/group_list/GroupsListScreen.kt b/feature/groups/src/main/java/com/mifos/feature/groupsList/group_list/GroupsListScreen.kt index 17ec2732881..e2a0b6fee1e 100644 --- a/feature/groups/src/main/java/com/mifos/feature/groupsList/group_list/GroupsListScreen.kt +++ b/feature/groups/src/main/java/com/mifos/feature/groupsList/group_list/GroupsListScreen.kt @@ -22,8 +22,10 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.DoneAll +import androidx.compose.material.icons.rounded.Sync import androidx.compose.material3.CardDefaults import androidx.compose.material3.FabPosition +import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard @@ -58,6 +60,7 @@ import com.mifos.core.designsystem.component.MifosCircularProgress import com.mifos.core.designsystem.component.MifosPaginationSweetError import com.mifos.core.designsystem.component.MifosPagingAppendProgress import com.mifos.core.designsystem.component.MifosSweetError +import com.mifos.core.designsystem.icon.MifosIcons import com.mifos.core.designsystem.theme.BluePrimary import com.mifos.core.designsystem.theme.BlueSecondary import com.mifos.core.designsystem.theme.DarkGray @@ -154,8 +157,21 @@ fun GroupsListScreen( contentDescription = "GroupList::ContextualTopAppBar" }, itemCount = selectedItems.size, - syncClicked = { onSyncClick(selectedItems.toList()) }, - resetSelectionMode = resetSelectionMode + resetSelectionMode = resetSelectionMode, + actions = { + FilledTonalButton( + onClick = { + onSyncClick(selectedItems.toList()) + resetSelectionMode() + }, + ) { + Icon( + imageVector = MifosIcons.sync, + contentDescription = "Sync Items", + ) + Text(text = stringResource(id = R.string.feature_groups_sync)) + } + } ) } }, diff --git a/feature/groups/src/main/res/values/strings.xml b/feature/groups/src/main/res/values/strings.xml index 94e1273ae4c..33456f14883 100644 --- a/feature/groups/src/main/res/values/strings.xml +++ b/feature/groups/src/main/res/values/strings.xml @@ -23,5 +23,6 @@ Savings Account Failed to Load Client Activate Group + Sync \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/adapters/CheckerTaskListAdapter.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/adapters/CheckerTaskListAdapter.kt index bdda645d932..f63c35e9864 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/adapters/CheckerTaskListAdapter.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/adapters/CheckerTaskListAdapter.kt @@ -65,11 +65,11 @@ class CheckerTaskListAdapter : ListAdapter() - - /**This list can be updated every time the RecyclerView needs to be updated. For example in - of filtering the list according to maker or applying different filter options. When it needs - to be updated to the full checkerTask list, it is being set to the 'fetchedCheckerTaskList'*/ - private var checkerTaskList = mutableListOf() - - /** This list is being used to keep track of selected items in case of Batch processing of - tasks.*/ - private var selectedCheckerTaskList = mutableListOf() - - private var adapterPosition: Int = -1 - var inBadgeProcessingMode = false +class CheckerInboxFragment : MifosBaseFragment(), CheckerTaskFilterDialogFragment.OnInputSelected { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = CheckerInboxFragmentBinding.inflate(inflater, container, false) - setToolbarTitle(resources.getString(R.string.checker_inbox)) - showMifosProgressBar() - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - binding.etSearch.addTextChangedListener(this) - binding.rvCheckerInbox.layoutManager = LinearLayoutManager(activity) - binding.rvCheckerInbox.hasFixedSize() - checkerTaskListAdapter = CheckerTaskListAdapter() - checkerTaskListAdapter.setBadgeProcessMode(this) - binding.rvCheckerInbox.adapter = checkerTaskListAdapter - setUpOnClickListeners() - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - viewModel = ViewModelProviders.of(this, factory) - .get(CheckerInboxViewModel::class.java) - - viewModel.getStatus().observe(viewLifecycleOwner, - Observer { - handleStatus(it) - }) - - viewModel.getCheckerTasks().observe(viewLifecycleOwner, Observer { - hideMifosProgressBar() - checkerTaskList.clear() - fetchedCheckerTaskList.addAll(it!!) - if (fetchedCheckerTaskList.isEmpty()) binding.tvEmptyCheckerInbox.visibility = - View.VISIBLE - checkerTaskList.addAll(fetchedCheckerTaskList) - checkerTaskListAdapter.submitList(checkerTaskList) - }) - } - - private fun showConfirmationDialog( - title: String, message: String, - onPositiveClick: DialogInterface.OnClickListener - ) { - MaterialDialog.Builder().init(activity) - .setTitle(title) - .setMessage(message) - .setPositiveButton(getString(R.string.yes), onPositiveClick) - .setNegativeButton(getString(R.string.cancel)) - .show() - } - - override fun onItemClick(position: Int) { - } - - /** - * This Method is executed when user clicks on Approve icon. - * It makes a network call to the server to Approve the task by - * passing task id as parameter. - * @param position Int - */ - override fun onApproveClick(position: Int) { - adapterPosition = position - showConfirmationDialog(getString(R.string.approve), - getString(R.string.approve_confirmation), - DialogInterface.OnClickListener { p0, p1 -> - showMifosProgressBar() - viewModel.approveCheckerEntry( - checkerTaskList[adapterPosition].id - ) - }) - } - - /** - * This Method is executed when user clicks on Reject icon. - * It makes a network call to the server to reject the task by - * passing task id as parameter. - * @param position Int - */ - override fun onRejectClick(position: Int) { - adapterPosition = position - showConfirmationDialog(getString(R.string.reject), - getString(R.string.reject_confirmation), - DialogInterface.OnClickListener { p0, p1 -> - showMifosProgressBar() - viewModel.rejectCheckerEntry( - checkerTaskList[adapterPosition].id - ) - }) - } - - /** - * This Method is executed when user clicks on Delete icon. - * It makes a network call to the server to delete the task by - * passing task id as parameter. - * @param position Int - */ - override fun onDeleteClick(position: Int) { - adapterPosition = position - showConfirmationDialog(getString(R.string.delete), - getString(R.string.delete_confirmation), - DialogInterface.OnClickListener { p0, p1 -> - showMifosProgressBar() - viewModel.deleteCheckerEntry( - checkerTaskList[adapterPosition].id - ) - }) - } - - /** - * This Method is executed whenever 'status' LiveData is updated. It can have 6 different - * values according to the result of the network call. Depending upon the 'status' value - * further execution is performed. For example, when the value of 'status' is - * Status.APPROVE_SUCCESS, it means that Approving of a checker task has been - * performed successfully. Now we can do further execution like updating of recycler view and - * other things according to the needs. - * @param status Status? - */ - private fun handleStatus(status: Status?) { - when (status) { - Status.APPROVE_SUCCESS -> { - // Check if the tasks are being approved using batch processing mode - if (selectedCheckerTaskList.isNotEmpty()) { - val task = selectedCheckerTaskList.removeAt(0) - checkerTaskList.remove(task) - fetchedCheckerTaskList.remove(task) - - // Check if more tasks are available for batch processing - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.approveCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - // No more tasks are available for batch processing - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - // Single Entry Approved (without batch processing) - hideMifosProgressBar() - updateRecyclerViewAfterOperation( - adapterPosition, - "APPROVED" - ) - } - } - - Status.REJECT_SUCCESS -> { - // Check if the tasks are being rejected using batch processing mode - if (selectedCheckerTaskList.isNotEmpty()) { - val task = selectedCheckerTaskList.removeAt(0) - checkerTaskList.remove(task) - fetchedCheckerTaskList.remove(task) - - // Check if more tasks are available for batch processing - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.rejectCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - // No more tasks are available for batch processing - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - // Single Entry Rejected (without batch processing) - hideMifosProgressBar() - updateRecyclerViewAfterOperation( - adapterPosition, - "REJECTED" - ) - } - } - - Status.DELETE_SUCCESS -> { - // Check if the tasks are being deleted using batch processing mode - if (selectedCheckerTaskList.isNotEmpty()) { - val task = selectedCheckerTaskList.removeAt(0) - checkerTaskList.remove(task) - fetchedCheckerTaskList.remove(task) - - // Check if more tasks are available for batch processing - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.deleteCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - // No more tasks are available for batch processing - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - // Single Entry Deleted (without batch processing) - hideMifosProgressBar() - updateRecyclerViewAfterOperation( - adapterPosition, - "DELETED" - ) - } - } - - Status.APPROVE_ERROR -> { - if (selectedCheckerTaskList.isNotEmpty()) { - selectedCheckerTaskList.removeAt(0) - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.approveCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - hideMifosProgressBar() - showNetworkError() - } - } - - Status.REJECT_ERROR -> { - if (selectedCheckerTaskList.isNotEmpty()) { - selectedCheckerTaskList.removeAt(0) - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.rejectCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - showNetworkError() - } - } - - Status.DELETE_ERROR -> { - if (selectedCheckerTaskList.isNotEmpty()) { - selectedCheckerTaskList.removeAt(0) - if (selectedCheckerTaskList.isNotEmpty()) { - viewModel.deleteCheckerEntry( - selectedCheckerTaskList[0].id - ) - } else { - hideMifosProgressBar() - binding.tvNoOfSelectedTasks.text = "0" - inBadgeProcessingMode = false - checkerTaskListAdapter.submitList(checkerTaskList) - binding.viewFlipper.showNext() - } - } else { - showNetworkError() - } + return ComposeView(requireActivity()).apply { + setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed + ) + setContent { + CheckerInboxScreen(onBackPressed = { + requireActivity().onBackPressed() + }, filter = { + // TODO implement filter dialog + }) } - - else -> {} - } - } - - private fun setUpOnClickListeners() { - checkerTaskListAdapter.setOnItemClickListener(this) - - binding.ivFilterSearchIcon.setOnClickListener { - val dialogSearchFilter = CheckerTaskFilterDialogFragment() - dialogSearchFilter.setTargetFragment(this, Constants.DIALOG_FRAGMENT) - dialogSearchFilter.show(parentFragmentManager, "DialogSearchFilter") } - - binding.ivBatchApproveIcon.setOnClickListener { - if (selectedCheckerTaskList.isNotEmpty()) { - showConfirmationDialog(getString(R.string.approve), - getString(R.string.approve_selected_entries), - DialogInterface.OnClickListener { p0, p1 -> - viewModel.approveCheckerEntry( - selectedCheckerTaskList[0].id - ) - showMifosProgressBar() - }) - } else { - Toast.makeText( - activity, getString(R.string.no_task_selected), - Toast.LENGTH_SHORT - ).show() - } - } - - binding.ivBatchRejectIcon.setOnClickListener { - if (selectedCheckerTaskList.isNotEmpty()) { - showConfirmationDialog(getString(R.string.reject), - getString(R.string.reject_selected_entries), - DialogInterface.OnClickListener { p0, p1 -> - viewModel.rejectCheckerEntry( - selectedCheckerTaskList[0].id - ) - showMifosProgressBar() - }) - } else { - Toast.makeText( - activity, getString(R.string.no_task_selected), - Toast.LENGTH_SHORT - ).show() - } - } - - binding.ivBatchDeleteIcon.setOnClickListener { - if (selectedCheckerTaskList.isNotEmpty()) { - showConfirmationDialog(getString(R.string.reject), - getString(R.string.reject_selected_entries), - DialogInterface.OnClickListener { p0, p1 -> - viewModel.rejectCheckerEntry( - selectedCheckerTaskList[0].id - ) - showMifosProgressBar() - }) - } else { - Toast.makeText( - activity, getString(R.string.no_task_selected), - Toast.LENGTH_SHORT - ).show() - } - } - - binding.ivDeselectAll.setOnClickListener { - binding.viewFlipper.showNext() - binding.tvNoOfSelectedTasks.text = "0" - selectedCheckerTaskList.clear() - inBadgeProcessingMode = false - checkerTaskListAdapter.notifyDataSetChanged() - } - } - - /** - * This method is executed after a successful Approve, Reject or Delete operation on a single - * checker task (i.e. in non-batch processing mode) - * @param position Int - * @param action String - */ - private fun updateRecyclerViewAfterOperation(position: Int, action: String) { - val task = checkerTaskList.removeAt(position) - fetchedCheckerTaskList.remove(task) - checkerTaskListAdapter.submitList(checkerTaskList) - Toast.makeText(activity, getString(R.string.entry) + action, Toast.LENGTH_SHORT).show() - } - - private fun showNetworkError() { - Toast.makeText( - activity, getString(R.string.something_went_wrong), - Toast.LENGTH_SHORT - ).show() } - override fun afterTextChanged(p0: Editable?) { - filter(p0.toString()) + override fun onResume() { + super.onResume() + (requireActivity() as AppCompatActivity).supportActionBar?.hide() } - override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + override fun onStop() { + super.onStop() + (requireActivity() as AppCompatActivity).supportActionBar?.show() } - override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { - } - - /** - * This Method is executed whenever something is typed in 'Search by user' EditText. It checks - * for the typed characters in the maker of different checker tasks and updates the list - * accordingly. In case it is empty or blank it simply sets the checkerTaskList to the - * fetchedCheckerTaskList to save the overload of checking every checkerTask. - * @param text String? - */ - private fun filter(text: String) { - if (text.isEmpty()) { - updateRecyclerViewWithNewList(fetchedCheckerTaskList) - } else { - val filteredList = mutableListOf() - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.maker.lowercase(Locale.getDefault()) - .contains(text.lowercase(Locale.getDefault())) - ) { - filteredList.add(checkerTask) - } - } - checkerTaskListAdapter.submitList(filteredList) - updateRecyclerViewWithNewList(filteredList) - } - } - - /** - * This Method is executed whenever checker tasks are checked - * or unchecked in the batch-processing mode. - * @param view View - * @param position Int - */ - override fun onItemSelectedOrDeselcted(view: View, position: Int) { - val task = checkerTaskList[position] - if ((view as CheckBox).isChecked) { - task.selectedFlag = true - checkerTaskListAdapter.notifyItemChanged(position) - selectedCheckerTaskList.add(task) - binding.tvNoOfSelectedTasks.text = selectedCheckerTaskList.size.toString() - } else { - task.selectedFlag = false - checkerTaskListAdapter.notifyItemChanged(position) - selectedCheckerTaskList.remove(task) - binding.tvNoOfSelectedTasks.text = selectedCheckerTaskList.size.toString() - } - } - - /** - * This Method is being used to get the filtered list by applying different types of search - * filters. - * @param fromDate Timestamp? - * @param toDate Timestamp? - * @param action String - * @param entity String - * @param resourceId String - * @return MutableList - */ - private fun getFilteredList( - fromDate: Timestamp?, toDate: Timestamp?, - action: String, entity: String, - resourceId: String - ) - : MutableList { - val filteredList = mutableListOf() - val ALL = "ALL" - - if (resourceId.isNotEmpty()) { - // If resource id is available there is no need to check for other filter options - for (checkerTask in fetchedCheckerTaskList) { - - if (resourceId == checkerTask.resourceId) { - filteredList.add(checkerTask) - } - } - return filteredList - } else { - // Resource Id is not available. - - // If Clear Filter clicked - if (fromDate == null && toDate == null) { - return fetchedCheckerTaskList - } else if (fromDate == null) { - // From Date is not available - if (action == ALL && entity == ALL) { - // No need to check for Action and Entity - for (checkerTask in fetchedCheckerTaskList) { - if (!checkerTask.getTimeStamp().after(toDate)) { - filteredList.add(checkerTask) - } - } - return filteredList - } else if (action == ALL) { - // Entity has a specific value - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().before(toDate)) { - if (entity.equals(checkerTask.entity, true)) { - filteredList.add(checkerTask) - } - - } - } - return filteredList - } else if (entity == ALL) { - // Action has a specific value - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().before(toDate)) { - if (action.equals(checkerTask.action, true)) { - filteredList.add(checkerTask) - } - } - } - return filteredList - } else { - // Both Action and Entity have specific values - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().before(toDate)) { - if (action.equals(checkerTask.action, true) && - entity.equals(checkerTask.entity, true) - ) { - filteredList.add(checkerTask) - } - } - } - return filteredList - } - } else { - // Both dates are available - if (action == ALL && entity == ALL) { - // No need to check for Action and Entity - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().after(fromDate) - && checkerTask.getTimeStamp().before(toDate) - ) { - filteredList.add(checkerTask) - } - } - return filteredList - } else if (action == ALL) { - // Entity has a specific value - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().after(fromDate) - && checkerTask.getTimeStamp().before(toDate) - ) { - if (entity.equals(checkerTask.entity, true)) { - filteredList.add(checkerTask) - } - - } - } - return filteredList - } else if (entity == ALL) { - // Action has a specific value - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().after(fromDate) - && checkerTask.getTimeStamp().before(toDate) - ) { - if (action.equals(checkerTask.action, true)) { - filteredList.add(checkerTask) - } - } - } - return filteredList - } else { - // Both Action and Entity have specific values - for (checkerTask in fetchedCheckerTaskList) { - if (checkerTask.getTimeStamp().after(fromDate) - && checkerTask.getTimeStamp().before(toDate) - ) { - if (action.equals(checkerTask.action, true) && - entity.equals(checkerTask.entity, true) - ) { - filteredList.add(checkerTask) - } - } - } - return filteredList - } - } - } + private fun setUpOnClickListeners() { + val dialogSearchFilter = CheckerTaskFilterDialogFragment() + dialogSearchFilter.setTargetFragment(this, Constants.DIALOG_FRAGMENT) + dialogSearchFilter.show(parentFragmentManager, "DialogSearchFilter") } - /** - * This method takes care of filtering the list and updating the RecyclerView on the basis of - * the values of the search filters sent by the Dialog Fragment. - * @param fromDate Timestamp? - * @param toDate Timestamp? - * @param action String - * @param entity String - * @param resourceId String - */ override fun sendInput( fromDate: Timestamp?, toDate: Timestamp?, action: String, entity: String, resourceId: String ) { - val filteredList = getFilteredList(fromDate, toDate, action, entity, resourceId) - updateRecyclerViewWithNewList(filteredList) - } - - /** - * This method takes updating the 'checkerTaskList' and the RecyclerView as per the - * requirements. - * @param updatedList List - */ - private fun updateRecyclerViewWithNewList(updatedList: List) { - checkerTaskList.clear() - checkerTaskList.addAll(updatedList) - checkerTaskListAdapter.submitList(checkerTaskList) +// val filteredList = getFilteredList(fromDate, toDate, action, entity, resourceId) +// updateRecyclerViewWithNewList(filteredList) } -} +} \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksFragment.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksFragment.kt index 8487ed8b026..e259a3d759e 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksFragment.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksFragment.kt @@ -8,7 +8,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.navigation.fragment.findNavController -import com.mifos.feature.checker_inbox_task.ui.CheckerInboxTasksScreen +import com.mifos.feature.checker_inbox_task.checker_inbox_tasks.ui.CheckerInboxTasksScreen import com.mifos.mifosxdroid.R import com.mifos.mifosxdroid.core.MifosBaseFragment import dagger.hilt.android.AndroidEntryPoint diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksViewModel.kt index 190e86cb79c..82e14f730b4 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksViewModel.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxTasksViewModel.kt @@ -3,18 +3,16 @@ package com.mifos.mifosxdroid.online.checkerinbox import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.mifos.core.network.datamanager.DataManagerCheckerInbox import com.mifos.core.objects.checkerinboxandtasks.CheckerTask import com.mifos.core.objects.checkerinboxandtasks.RescheduleLoansTask -import rx.Subscriber -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers -import rx.subscriptions.CompositeSubscription +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import javax.inject.Inject class CheckerInboxTasksViewModel @Inject constructor( - val dataManager: DataManagerCheckerInbox, - val subscription: CompositeSubscription + val dataManager: DataManagerCheckerInbox ) : ViewModel() { private val checkerTasksLive: MutableLiveData> by lazy { @@ -35,24 +33,13 @@ class CheckerInboxTasksViewModel @Inject constructor( return rescheduleLoanTasksLive } - fun loadRescheduleLoanTasks() { - subscription.add(dataManager.getRechdeduleLoansTaskList() - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() { - - } - - override fun onError(e: Throwable) { - status.value = false - } - - override fun onNext(rescheduleLoanTasks: List) { - rescheduleLoanTasksLive.postValue(rescheduleLoanTasks) - } - }) - ) + fun loadRescheduleLoanTasks() = viewModelScope.launch(Dispatchers.IO) { + try { + val response = dataManager.getRechdeduleLoansTaskList() + rescheduleLoanTasksLive.postValue(response) + } catch (exception: Exception) { + status.value = false + } } @@ -60,23 +47,13 @@ class CheckerInboxTasksViewModel @Inject constructor( return checkerTasksLive } - fun loadCheckerTasks() { - subscription.add(dataManager.getCheckerTaskList() - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - status.value = false - } - - override fun onNext(checkerTasks: List) { - checkerTasksLive.postValue(checkerTasks) - status.value = true - } - }) - ) + fun loadCheckerTasks() = viewModelScope.launch(Dispatchers.IO) { + try { + val response = dataManager.getCheckerTaskList() + checkerTasksLive.postValue(response) + status.value = true + } catch (exception: Exception) { + status.value = false + } } } \ No newline at end of file diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModel.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModel.kt index 3ff236f85b7..6bf829b1d91 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModel.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModel.kt @@ -27,11 +27,6 @@ class CheckerInboxViewModel @Inject constructor( val subscription: CompositeSubscription ) : ViewModel() { - private val checkerTasksLive: MutableLiveData> by lazy { - MutableLiveData>().also { - loadCheckerTasks() - } - } private val searchTemplateLive: MutableLiveData by lazy { MutableLiveData().also { @@ -41,9 +36,6 @@ class CheckerInboxViewModel @Inject constructor( private val status = MutableLiveData() - fun getCheckerTasks(): LiveData> { - return checkerTasksLive - } fun getSearchTemplate(): LiveData { return searchTemplateLive @@ -53,83 +45,6 @@ class CheckerInboxViewModel @Inject constructor( return status } - private fun loadCheckerTasks( - actionName: String? = null, entityName: String? = null, - resourceId: Int? = null - ) { - subscription.add(dataManager.getCheckerTaskList(actionName, entityName, resourceId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber>() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - } - - override fun onNext(checkerTasks: List) { - checkerTasksLive.postValue(checkerTasks) - } - }) - ) - } - - fun approveCheckerEntry(auditId: Int) { - subscription.add(dataManager.approveCheckerEntry(auditId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - status.value = Status.APPROVE_ERROR - } - - override fun onNext(Response: GenericResponse) { - status.value = Status.APPROVE_SUCCESS - } - }) - ) - } - - fun rejectCheckerEntry(auditId: Int) { - subscription.add(dataManager.rejectCheckerEntry(auditId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - status.value = Status.REJECT_ERROR - } - - override fun onNext(Response: GenericResponse) { - status.value = Status.REJECT_SUCCESS - } - }) - ) - } - - fun deleteCheckerEntry(auditId: Int) { - subscription.add(dataManager.deleteCheckerEntry(auditId) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeOn(Schedulers.io()) - .subscribe(object : Subscriber() { - override fun onCompleted() { - } - - override fun onError(e: Throwable) { - status.value = Status.DELETE_ERROR - } - - override fun onNext(Response: GenericResponse) { - status.value = Status.DELETE_SUCCESS - } - }) - ) - } private fun loadSearchTemplate() { subscription.add(dataManager.getCheckerInboxSearchTemplate() diff --git a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModelFactory.kt b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModelFactory.kt index 1e45dbb58d3..115f83433ea 100644 --- a/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModelFactory.kt +++ b/mifosng-android/src/main/java/com/mifos/mifosxdroid/online/checkerinbox/CheckerInboxViewModelFactory.kt @@ -17,7 +17,7 @@ class CheckerInboxViewModelFactory @Inject constructor( override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(CheckerInboxTasksViewModel::class.java)) { - return CheckerInboxTasksViewModel(dataManagerCheckerInbox, subscription) as T + return CheckerInboxTasksViewModel(dataManagerCheckerInbox) as T } if (modelClass.isAssignableFrom(CheckerInboxViewModel::class.java)) { return CheckerInboxViewModel(dataManagerCheckerInbox, subscription) as T