Skip to content

Commit

Permalink
refactor: refactor loan charges fragment to compose (#2141)
Browse files Browse the repository at this point in the history
* refactor: refactor loan charges fragment to compose

* refactor: refactor loan charges fragment to compose
  • Loading branch information
Aditya-gupta99 committed Jul 15, 2024
1 parent 6074317 commit 66d304a
Show file tree
Hide file tree
Showing 17 changed files with 383 additions and 340 deletions.
9 changes: 7 additions & 2 deletions core/data/src/main/java/com/mifos/core/data/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import com.mifos.core.data.repository.GroupListRepository
import com.mifos.core.data.repository.GroupsListRepository
import com.mifos.core.data.repository.IndividualCollectionSheetDetailsRepository
import com.mifos.core.data.repository.LoanAccountRepository
import com.mifos.core.data.repository.LoanChargeRepository
import com.mifos.core.data.repository.NewIndividualCollectionSheetRepository
import com.mifos.core.data.repository.PathTrackingRepository
import com.mifos.core.data.repository.ReportCategoryRepository
import com.mifos.core.data.repository_imp.ActivateRepositoryImp
import com.mifos.core.data.repository.ReportDetailRepository
import com.mifos.core.data.repository_imp.ActivateRepositoryImp
import com.mifos.core.data.repository_imp.CenterDetailsRepositoryImp
import com.mifos.core.data.repository_imp.CenterListRepositoryImp
import com.mifos.core.data.repository_imp.CheckerInboxRepositoryImp
Expand All @@ -33,6 +34,7 @@ import com.mifos.core.data.repository_imp.GroupListRepositoryImp
import com.mifos.core.data.repository_imp.GroupsListRepositoryImpl
import com.mifos.core.data.repository_imp.IndividualCollectionSheetDetailsRepositoryImp
import com.mifos.core.data.repository_imp.LoanAccountRepositoryImp
import com.mifos.core.data.repository_imp.LoanChargeRepositoryImp
import com.mifos.core.data.repository_imp.NewIndividualCollectionSheetRepositoryImp
import com.mifos.core.data.repository_imp.PathTrackingRepositoryImp
import com.mifos.core.data.repository_imp.ReportCategoryRepositoryImp
Expand Down Expand Up @@ -98,7 +100,10 @@ abstract class DataModule {

@Binds
internal abstract fun bindIndividualCollectionSheetDetailsRepositoryImp(impl: IndividualCollectionSheetDetailsRepositoryImp): IndividualCollectionSheetDetailsRepository

@Binds
internal abstract fun bindGroupListRepository(impl: GroupListRepositoryImp): GroupListRepository

@Binds
internal abstract fun bindLoanChargeRepository(impl: LoanChargeRepositoryImp): LoanChargeRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mifos.core.data.repository

import com.mifos.core.objects.client.Charges

/**
* Created by Aditya Gupta on 10/08/23.
*/
interface LoanChargeRepository {

suspend fun getListOfLoanCharges(loanId: Int): List<Charges>

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.mifos.mifosxdroid.online.loancharge
package com.mifos.core.data.repository_imp

import com.mifos.core.data.repository.LoanChargeRepository
import com.mifos.core.network.DataManager
import com.mifos.core.objects.client.Charges
import rx.Observable
import javax.inject.Inject

/**
Expand All @@ -11,7 +11,7 @@ import javax.inject.Inject
class LoanChargeRepositoryImp @Inject constructor(private val dataManager: DataManager) :
LoanChargeRepository {

override fun getListOfLoanCharges(loanId: Int): Observable<List<Charges>> {
override suspend fun getListOfLoanCharges(loanId: Int): List<Charges> {
return dataManager.getListOfLoanCharges(loanId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mifos.core.domain.use_cases

import com.mifos.core.common.utils.Resource
import com.mifos.core.data.repository.LoanChargeRepository
import com.mifos.core.objects.client.Charges
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject

class GetListOfLoanChargesUseCase @Inject constructor(private val repository: LoanChargeRepository) {

suspend operator fun invoke(loanId: Int): Flow<Resource<List<Charges>>> = flow {
try {
emit(Resource.Loading())
val response = repository.getListOfLoanCharges(loanId)
emit(Resource.Success(response))
} catch (exception: Exception) {
emit(Resource.Error(exception.message.toString()))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class DataManager {
return mBaseApiManager.loanApi.approveLoanApplication(loanId, loanApproval)
}

fun getListOfLoanCharges(loanId: Int): Observable<List<Charges>> {
suspend fun getListOfLoanCharges(loanId: Int): List<Charges> {
return mBaseApiManager.loanApi.getListOfLoanCharges(loanId)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ interface LoanService {
): Observable<GroupLoanTemplate>

@GET(APIEndPoint.LOANS + "/{loanId}/" + APIEndPoint.CHARGES)
fun getListOfLoanCharges(@Path("loanId") loanId: Int): Observable<List<Charges>>
suspend fun getListOfLoanCharges(@Path("loanId") loanId: Int): List<Charges>

@GET(APIEndPoint.CLIENTS + "/{clientId}/" + APIEndPoint.CHARGES)
fun getListOfCharges(@Path("clientId") clientId: Int): Observable<Page<Charges>>
Expand Down
2 changes: 2 additions & 0 deletions feature/loan/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ dependencies {
testImplementation(projects.core.testing)

androidTestImplementation(projects.core.testing)

implementation(libs.androidx.material)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
@file:OptIn(ExperimentalMaterialApi::class)

package com.mifos.feature.loan.loan_charge

import androidx.compose.foundation.layout.Box
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.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.MifosScaffold
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.BlueSecondary
import com.mifos.core.designsystem.theme.DarkGray
import com.mifos.core.objects.client.Charges
import com.mifos.core.ui.components.MifosEmptyUi
import com.mifos.feature.loan.R

@Composable
fun LoanChargeScreen(loanAccountNumber: Int, onBackPressed: () -> Unit) {

val viewModel: LoanChargeViewModel = hiltViewModel()
val state by viewModel.loanChargeUiState.collectAsStateWithLifecycle()
val refreshState by viewModel.isRefreshing.collectAsStateWithLifecycle()

LaunchedEffect(Unit) {
viewModel.loadLoanChargesList(loanAccountNumber)
}

LoanChargeScreen(
state = state,
onBackPressed = onBackPressed,
onRetry = {
viewModel.loadLoanChargesList(loanAccountNumber)
},
refreshState = refreshState,
onRefresh = {
viewModel.refreshLoanChargeList(loanAccountNumber)
}
)

}

@Composable
fun LoanChargeScreen(
state: LoanChargeUiState,
onBackPressed: () -> Unit,
onRetry: () -> Unit,
refreshState: Boolean,
onRefresh: () -> Unit,
) {
val snackbarHostState by remember { mutableStateOf(SnackbarHostState()) }
val pullRefreshState = rememberPullRefreshState(
refreshing = refreshState,
onRefresh = onRefresh
)

MifosScaffold(
icon = MifosIcons.arrowBack,
title = stringResource(id = R.string.feature_loan_loan_charges),
onBackPressed = onBackPressed,
actions = {
IconButton(onClick = {
// TODO Implement Loan Charges Add Dialog
}) {
Icon(imageVector = MifosIcons.Add, contentDescription = null)
}
},
snackbarHostState = snackbarHostState
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
Box(modifier = Modifier.pullRefresh(pullRefreshState)) {
when (state) {
is LoanChargeUiState.Error -> MifosSweetError(message = stringResource(id = state.message)) {
onRetry()
}

is LoanChargeUiState.Loading -> MifosCircularProgress()

is LoanChargeUiState.LoanChargesList -> {
if (state.loanCharges.isEmpty()) {
MifosEmptyUi(
text = stringResource(id = R.string.feature_loan_no_loan_charges),
icon = MifosIcons.fileTask
)
} else {
LoanChargesContent(loanCharges = state.loanCharges)
}
}
}

PullRefreshIndicator(
refreshing = refreshState,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter)
)
}
}
}
}

@Composable
fun LoanChargesContent(
loanCharges: List<Charges>
) {
LazyColumn {
items(loanCharges) { charges ->
LoanChargeItem(
charges = charges
)
}
}
}

@Composable
fun LoanChargeItem(
charges: Charges
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
shape = RoundedCornerShape(0.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
colors = CardDefaults.cardColors(
containerColor = BlueSecondary
)
) {
Spacer(modifier = Modifier.height(8.dp))
MifosLoanChargeDetailsText(
stringResource(id = R.string.feature_loan_client_id),
charges.chargeId.toString()
)
MifosLoanChargeDetailsText(
stringResource(id = R.string.feature_loan_charge_name),
charges.name ?: ""
)
MifosLoanChargeDetailsText(
stringResource(id = R.string.feature_loan_charge_amount),
charges.amount.toString()
)
MifosLoanChargeDetailsText(
stringResource(id = R.string.feature_loan_charge_due_date),
charges.formattedDueDate
)
Spacer(modifier = Modifier.height(8.dp))
}
}

@Composable
fun MifosLoanChargeDetailsText(field: String, value: String) {
Row(
modifier = Modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier
.weight(1f)
.padding(start = 16.dp),
text = field,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Normal
),
color = Black,
textAlign = TextAlign.Start
)
Text(
modifier = Modifier.weight(1f),
text = value,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Normal
),
color = DarkGray,
textAlign = TextAlign.Start
)
}
}

class LoanChargeUiStateProvider : PreviewParameterProvider<LoanChargeUiState> {

override val values: Sequence<LoanChargeUiState>
get() = sequenceOf(
LoanChargeUiState.Loading,
LoanChargeUiState.Error(R.string.feature_loan_failed_to_load_loan_charges),
LoanChargeUiState.LoanChargesList(sampleLoanChargeList)
)
}


@Preview(showBackground = true)
@Composable
private fun LoanChargeScreenPreview(
@PreviewParameter(LoanChargeUiStateProvider::class) state: LoanChargeUiState
) {
LoanChargeScreen(
state = state,
onBackPressed = {},
onRetry = {},
refreshState = false,
onRefresh = {}
)
}

val sampleLoanChargeList = List(10) {
Charges(name = "name $it", chargeId = it, amount = it.toDouble())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mifos.feature.loan.loan_charge

import com.mifos.core.objects.client.Charges

/**
* Created by Aditya Gupta on 10/08/23.
*/
sealed class LoanChargeUiState {

data object Loading : LoanChargeUiState()

data class Error(val message: Int) : LoanChargeUiState()

data class LoanChargesList(val loanCharges: List<Charges>) : LoanChargeUiState()
}
Loading

0 comments on commit 66d304a

Please sign in to comment.