mirror of
https://github.com/openMF/mobile-wallet.git
synced 2026-02-06 11:36:57 +00:00
Moved standingInstruction to feature module (#1671)
Co-authored-by: Rajan Maurya <therajanmaurya@users.noreply.github.com>
This commit is contained in:
parent
7b8876306e
commit
23649dd8d8
1
feature/standing-instruction/.gitignore
vendored
Normal file
1
feature/standing-instruction/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
12
feature/standing-instruction/build.gradle.kts
Normal file
12
feature/standing-instruction/build.gradle.kts
Normal file
@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
alias(libs.plugins.mifospay.android.feature)
|
||||
alias(libs.plugins.mifospay.android.library.compose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "org.mifospay.feature.standing.instruction"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.data)
|
||||
}
|
||||
0
feature/standing-instruction/consumer-rules.pro
Normal file
0
feature/standing-instruction/consumer-rules.pro
Normal file
21
feature/standing-instruction/proguard-rules.pro
vendored
Normal file
21
feature/standing-instruction/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@ -0,0 +1,24 @@
|
||||
package org.mifospay.feature.standing.instruction
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("org.mifospay.feature.standing.instruction.test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@ -0,0 +1,65 @@
|
||||
package org.mifospay.feature.standing.instruction
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun SIContent(
|
||||
fromClientName: String,
|
||||
toClientName: String,
|
||||
validTill: String,
|
||||
amount: String
|
||||
) {
|
||||
Column(modifier = Modifier.padding(10.dp)) {
|
||||
Text(
|
||||
text = fromClientName,
|
||||
color = Color.Black,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.padding(bottom = 20.dp)
|
||||
)
|
||||
|
||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
Text(
|
||||
text = toClientName,
|
||||
color = Color.Black,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.padding(bottom = 4.dp)
|
||||
)
|
||||
Text(
|
||||
text = amount,
|
||||
color = Color.Black,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.padding(end = 8.dp, bottom = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = validTill,
|
||||
color = Color.Gray,
|
||||
modifier = Modifier.padding(bottom = 4.dp)
|
||||
)
|
||||
|
||||
Divider(
|
||||
color = Color.Black,
|
||||
thickness = 1.dp,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun SIContentPreview() {
|
||||
SIContent("From Client", "To Client", "Date", "Amount")
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
package org.mifospay.feature.standing.instruction
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Info
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.mifospay.core.model.entity.accounts.savings.SavingAccount
|
||||
import com.mifospay.core.model.entity.client.Client
|
||||
import com.mifospay.core.model.entity.client.Status
|
||||
import com.mifospay.core.model.entity.standinginstruction.StandingInstruction
|
||||
import org.mifospay.core.designsystem.component.MifosLoadingWheel
|
||||
import org.mifospay.core.designsystem.icon.MifosIcons
|
||||
import org.mifospay.core.ui.EmptyContentScreen
|
||||
|
||||
@Composable
|
||||
fun StandingInstructionsScreen(
|
||||
viewModel: StandingInstructionViewModel = hiltViewModel(),
|
||||
onNewSI: () -> Unit
|
||||
) {
|
||||
val standingInstructionsUiState by viewModel.standingInstructionsUiState.collectAsStateWithLifecycle()
|
||||
StandingInstructionScreen(
|
||||
standingInstructionsUiState = standingInstructionsUiState,
|
||||
onNewSI = onNewSI
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StandingInstructionScreen(
|
||||
standingInstructionsUiState: StandingInstructionsUiState,
|
||||
onNewSI: () -> Unit
|
||||
) = when (standingInstructionsUiState) {
|
||||
StandingInstructionsUiState.Empty -> {
|
||||
EmptyContentScreen(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.feature_standing_instruction_error_oops),
|
||||
subTitle = stringResource(id = R.string.feature_standing_instruction_empty_standing_instructions),
|
||||
iconTint = Color.Black,
|
||||
iconImageVector = Icons.Rounded.Info
|
||||
)
|
||||
}
|
||||
|
||||
is StandingInstructionsUiState.Error -> {
|
||||
EmptyContentScreen(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.feature_standing_instruction_error_oops),
|
||||
subTitle = stringResource(id = R.string.feature_standing_instruction_error_fetching_si_list),
|
||||
iconTint = Color.Black,
|
||||
iconImageVector = Icons.Rounded.Info
|
||||
)
|
||||
}
|
||||
|
||||
StandingInstructionsUiState.Loading -> {
|
||||
MifosLoadingWheel(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentDesc = stringResource(R.string.feature_standing_instruction_loading)
|
||||
)
|
||||
}
|
||||
|
||||
is StandingInstructionsUiState.StandingInstructionList -> {
|
||||
Scaffold(
|
||||
modifier = Modifier,
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
onClick = { onNewSI.invoke() },
|
||||
) {
|
||||
Icon(
|
||||
painter = rememberVectorPainter(MifosIcons.Add),
|
||||
contentDescription = null,
|
||||
tint = Color.Black
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
) {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
items(standingInstructionsUiState.standingInstructionList) { items ->
|
||||
SIContent(
|
||||
fromClientName = items.fromClient.displayName.toString(),
|
||||
toClientName = items.toClient.displayName.toString(),
|
||||
validTill = items.validTill.toString(),
|
||||
amount = items.amount.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class StandingInstructionPreviewParameterProvider : PreviewParameterProvider<StandingInstructionsUiState> {
|
||||
override val values: Sequence<StandingInstructionsUiState> = sequenceOf(
|
||||
StandingInstructionsUiState.Loading,
|
||||
StandingInstructionsUiState.Empty,
|
||||
StandingInstructionsUiState.Error("Error Screen"),
|
||||
StandingInstructionsUiState.StandingInstructionList(
|
||||
standingInstructionList = listOf(
|
||||
StandingInstruction(
|
||||
id = 1,
|
||||
name = "Instruction 1",
|
||||
fromClient = Client(displayName = "Alice"),
|
||||
fromAccount = SavingAccount(),
|
||||
toClient = Client(displayName = "Bob"),
|
||||
toAccount = SavingAccount(),
|
||||
status = Status(),
|
||||
amount = 100.0,
|
||||
validFrom = listOf(2022, 1, 1),
|
||||
validTill = listOf(2024, 12, 31),
|
||||
recurrenceInterval = 30,
|
||||
recurrenceOnMonthDay = listOf(1)
|
||||
),
|
||||
StandingInstruction(
|
||||
id = 2,
|
||||
name = "Instruction 2",
|
||||
fromClient = Client(displayName = "Charlie"),
|
||||
fromAccount = SavingAccount(),
|
||||
toClient = Client(displayName = "Dave"),
|
||||
toAccount = SavingAccount(),
|
||||
status = Status(),
|
||||
amount = 200.0,
|
||||
validFrom = listOf(2022, 1, 1),
|
||||
validTill = listOf(2024, 12, 31),
|
||||
recurrenceInterval = 30,
|
||||
recurrenceOnMonthDay = listOf(1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun StandingInstructionsScreenPreview(
|
||||
@PreviewParameter(StandingInstructionPreviewParameterProvider::class) standingInstructionsUiState: StandingInstructionsUiState
|
||||
) {
|
||||
StandingInstructionScreen(
|
||||
standingInstructionsUiState = standingInstructionsUiState,
|
||||
onNewSI = {}
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package org.mifospay.feature.standing.instruction
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.mifospay.core.model.entity.standinginstruction.StandingInstruction
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import org.mifospay.core.data.base.UseCase
|
||||
import org.mifospay.core.data.base.UseCaseHandler
|
||||
import org.mifospay.core.data.domain.usecase.standinginstruction.GetAllStandingInstructions
|
||||
import org.mifospay.core.data.repository.local.LocalRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class StandingInstructionViewModel @Inject constructor(
|
||||
private val mUseCaseHandler: UseCaseHandler,
|
||||
private val localRepository: LocalRepository,
|
||||
private val getAllStandingInstructions: GetAllStandingInstructions
|
||||
) : ViewModel() {
|
||||
|
||||
private val _standingInstructionsUiState =
|
||||
MutableStateFlow<StandingInstructionsUiState>(StandingInstructionsUiState.Loading)
|
||||
val standingInstructionsUiState: StateFlow<StandingInstructionsUiState> =
|
||||
_standingInstructionsUiState
|
||||
|
||||
private fun getAllSI() {
|
||||
val client = localRepository.clientDetails
|
||||
_standingInstructionsUiState.value = StandingInstructionsUiState.Loading
|
||||
mUseCaseHandler.execute(getAllStandingInstructions,
|
||||
GetAllStandingInstructions.RequestValues(client.clientId), object :
|
||||
UseCase.UseCaseCallback<GetAllStandingInstructions.ResponseValue> {
|
||||
|
||||
override fun onSuccess(response: GetAllStandingInstructions.ResponseValue) {
|
||||
if (response.standingInstructionsList.isEmpty()) {
|
||||
_standingInstructionsUiState.value = StandingInstructionsUiState.Empty
|
||||
} else {
|
||||
_standingInstructionsUiState.value =
|
||||
StandingInstructionsUiState.StandingInstructionList(response.standingInstructionsList)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
_standingInstructionsUiState.value = StandingInstructionsUiState.Error(message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
init {
|
||||
getAllSI()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class StandingInstructionsUiState {
|
||||
data object Loading : StandingInstructionsUiState()
|
||||
data object Empty : StandingInstructionsUiState()
|
||||
data class Error(val message: String) : StandingInstructionsUiState()
|
||||
data class StandingInstructionList(val standingInstructionList: List<StandingInstruction>) :
|
||||
StandingInstructionsUiState()
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="feature_standing_instruction_error_oops">Oops!</string>
|
||||
<string name="feature_standing_instruction_empty_standing_instructions">No standing instructions to show</string>
|
||||
<string name="feature_standing_instruction_error_fetching_si_list">Couldn\'t fetch Standing Instructions. Please, try again.</string>
|
||||
<string name="feature_standing_instruction_loading">Loading</string>
|
||||
</resources>
|
||||
@ -0,0 +1,17 @@
|
||||
package org.mifospay.feature.standing.instruction
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@ -48,4 +48,5 @@ include(":feature:invoices")
|
||||
include(":feature:invoices")
|
||||
include(":feature:settings")
|
||||
include(":feature:profile")
|
||||
include(":feature:standing-instruction")
|
||||
include(":feature:payments")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user