diff --git a/feature/make-transfer/src/androidTest/java/org/mifospay/feature/make/transfer/ExampleInstrumentedTest.kt b/feature/make-transfer/src/androidTest/java/org/mifospay/feature/make/transfer/ExampleInstrumentedTest.kt deleted file mode 100644 index 0d13a07f0..000000000 --- a/feature/make-transfer/src/androidTest/java/org/mifospay/feature/make/transfer/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.mifospay.feature.make.transfer - -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.make.transfer", appContext.packageName) - } -} \ No newline at end of file diff --git a/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/MakeTransferScreen.kt b/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/MakeTransferScreen.kt index b8fa36787..379ea1142 100644 --- a/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/MakeTransferScreen.kt +++ b/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/MakeTransferScreen.kt @@ -44,7 +44,8 @@ import org.mifospay.core.designsystem.component.MifosOverlayLoadingWheel @Composable fun MakeTransferScreenRoute( - viewModel: MakeTransferViewModel = hiltViewModel() + viewModel: MakeTransferViewModel = hiltViewModel(), + onDismiss: () -> Unit ) { val fetchPayeeClient by viewModel.fetchPayeeClient.collectAsStateWithLifecycle() val makeTransferState by viewModel.makeTransferState.collectAsStateWithLifecycle() @@ -58,7 +59,8 @@ fun MakeTransferScreenRoute( toClientId, transferAmount ) - } + }, + onDismiss = onDismiss ) } @@ -67,6 +69,7 @@ fun MakeTransferScreen( uiState: MakeTransferState, showTransactionStatus: ShowTransactionStatus, makeTransfer: (Long, Double) -> Unit, + onDismiss: () -> Unit ) { val context = LocalContext.current when (uiState) { @@ -97,7 +100,8 @@ fun MakeTransferScreen( externalId, transferAmount, showTransactionStatus, - makeTransfer = makeTransfer + makeTransfer = makeTransfer, + onDismiss = onDismiss ) } } @@ -113,6 +117,7 @@ fun MakeTransferBottomSheetContent( transferAmount: Double, showTransactionStatus: ShowTransactionStatus, makeTransfer: (Long, Double) -> Unit, + onDismiss: () -> Unit ) { val sheetState = rememberModalBottomSheetState() @@ -125,6 +130,7 @@ fun MakeTransferBottomSheetContent( sheetState = sheetState, onDismissRequest = { showBottomSheet = false + onDismiss.invoke() }, dragHandle = { BottomSheetDefaults.DragHandle() }, ) { @@ -340,7 +346,8 @@ fun PreviewWithMakeTransferContentLoading() { showSuccessStatus = false, showErrorStatus = false ), - makeTransfer = { _, _ -> } + makeTransfer = { _, _ -> }, + onDismiss = { } ) } @@ -359,7 +366,8 @@ fun PreviewWithMakeTransferContentSuccess() { showSuccessStatus = false, showErrorStatus = false ), - makeTransfer = { _, _ -> } + makeTransfer = { _, _ -> }, + onDismiss = { } ) } @@ -391,7 +399,8 @@ fun PreviewMakeTransferBottomSheetContent() { showSuccessStatus = false, showErrorStatus = false ), - makeTransfer = { _, _ -> } + makeTransfer = { _, _ -> }, + onDismiss = { } ) } @@ -404,7 +413,8 @@ fun PreviewWithMakeTransferContentError() { showSuccessStatus = false, showErrorStatus = false ), - makeTransfer = { _, _ -> } + makeTransfer = { _, _ -> }, + onDismiss = { } ) } diff --git a/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/navigation/MakeTransferNavigation.kt b/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/navigation/MakeTransferNavigation.kt index 2e3ff2392..0c70e60e6 100644 --- a/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/navigation/MakeTransferNavigation.kt +++ b/feature/make-transfer/src/main/kotlin/org/mifospay/feature/make/transfer/navigation/MakeTransferNavigation.kt @@ -30,7 +30,9 @@ fun NavController.navigateToMakeTransferScreen( navigate(route, navOptions) } -fun NavGraphBuilder.makeTransferScreen() { +fun NavGraphBuilder.makeTransferScreen( + onDismiss: () -> Unit +) { composable( route = MAKE_TRANSFER_ROUTE, arguments = listOf( @@ -46,6 +48,8 @@ fun NavGraphBuilder.makeTransferScreen() { } ) ) { - MakeTransferScreenRoute() + MakeTransferScreenRoute( + onDismiss = onDismiss + ) } } diff --git a/feature/send-money/.gitignore b/feature/send-money/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/feature/send-money/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/send-money/build.gradle.kts b/feature/send-money/build.gradle.kts new file mode 100644 index 000000000..4605e59c2 --- /dev/null +++ b/feature/send-money/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + alias(libs.plugins.mifospay.android.feature) + alias(libs.plugins.mifospay.android.library.compose) +} + +android { + namespace = "org.mifospay.feature.send.money" +} + +dependencies { + implementation(projects.core.data) + + // we need it for country picker library + implementation("androidx.compose.material:material:1.6.0") + implementation(libs.compose.country.code.picker) // remove after moving auth code to module + + // Google Bar code scanner + implementation(libs.google.play.services.code.scanner) +} diff --git a/feature/send-money/src/main/AndroidManifest.xml b/feature/send-money/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8072ee00d --- /dev/null +++ b/feature/send-money/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendPaymentViewModel.kt b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendPaymentViewModel.kt new file mode 100644 index 000000000..2ac79d260 --- /dev/null +++ b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendPaymentViewModel.kt @@ -0,0 +1,97 @@ +package org.mifospay.feature.send.money + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.mifospay.core.data.base.UseCase +import org.mifospay.core.data.base.UseCaseHandler +import org.mifospay.core.data.domain.usecase.account.FetchAccount +import org.mifospay.core.data.repository.local.LocalRepository +import javax.inject.Inject + +@HiltViewModel +class SendPaymentViewModel @Inject constructor( + private val useCaseHandler: UseCaseHandler, + private val localRepository: LocalRepository, + private val fetchAccount: FetchAccount +) : ViewModel() { + + private val _showProgress = MutableStateFlow(false) + val showProgress: StateFlow = _showProgress + + private val _vpa = MutableStateFlow("") + val vpa: StateFlow = _vpa + + private val _mobile = MutableStateFlow("") + val mobile: StateFlow = _mobile + + init { + fetchVpa() + fetchMobile() + } + + fun updateProgressState(isVisible: Boolean) { + _showProgress.update { isVisible } + } + + private fun fetchVpa() { + viewModelScope.launch { + _vpa.value = localRepository.clientDetails.externalId.toString() + } + } + + private fun fetchMobile() { + viewModelScope.launch { + _mobile.value = localRepository.preferencesHelper.mobile.toString() + } + } + + fun checkSelfTransfer( + selfVpa: String?, + selfMobile: String?, + externalIdOrMobile: String?, + sendMethodType: SendMethodType, + ): Boolean { + return when (sendMethodType) { + SendMethodType.VPA -> { + selfVpa.takeIf { !it.isNullOrEmpty() }?.let { it == externalIdOrMobile } ?: false + } + + SendMethodType.MOBILE -> { + selfMobile.takeIf { !it.isNullOrEmpty() }?.let { it == externalIdOrMobile } ?: false + } + } + } + + fun checkBalanceAvailabilityAndTransfer( + externalId: String?, + transferAmount: Double, + onAnyError: (Int) -> Unit, + proceedWithTransferFlow: (String, Double) -> Unit + ) { + updateProgressState(true) + useCaseHandler.execute(fetchAccount, + FetchAccount.RequestValues(localRepository.clientDetails.clientId), + object : UseCase.UseCaseCallback { + override fun onSuccess(response: FetchAccount.ResponseValue) { + updateProgressState(false) + if (transferAmount > response.account.balance) { + onAnyError(R.string.insufficient_balance) + } else { + if (externalId != null) { + proceedWithTransferFlow(externalId, transferAmount) + } + } + } + + override fun onError(message: String) { + updateProgressState(false) + onAnyError.invoke(R.string.error_fetching_balance) + } + }) + } +} \ No newline at end of file diff --git a/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt new file mode 100644 index 000000000..6f9c985ff --- /dev/null +++ b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt @@ -0,0 +1,388 @@ +package org.mifospay.feature.send.money + +import android.content.Context +import android.net.Uri +import android.provider.ContactsContract +import android.util.Log +import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.TextFieldDefaults +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.QrCode2 +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +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.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.google.mlkit.vision.barcode.common.Barcode +import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions +import com.google.mlkit.vision.codescanner.GmsBarcodeScanning +import com.togitech.ccp.component.TogiCountryCodePicker +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.mifospay.core.designsystem.component.MfOutlinedTextField +import org.mifospay.core.designsystem.component.MfOverlayLoadingWheel +import org.mifospay.core.designsystem.component.MifosButton +import org.mifospay.core.designsystem.component.MifosNavigationTopAppBar +import org.mifospay.core.designsystem.theme.styleMedium16sp +import org.mifospay.core.designsystem.theme.styleNormal18sp + + +enum class SendMethodType { + VPA, MOBILE +} + +@Composable +fun SendScreenRoute( + viewModel: SendPaymentViewModel = hiltViewModel(), + showToolBar: Boolean, + onBackClick: () -> Unit, + proceedWithMakeTransferFlow: (String, String) -> Unit +) { + val context = LocalContext.current + val selfVpa by viewModel.vpa.collectAsStateWithLifecycle() + val selfMobile by viewModel.mobile.collectAsStateWithLifecycle() + val showProgress by viewModel.showProgress.collectAsStateWithLifecycle() + + fun showToast(message: String) { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() + } + + SendMoneyScreen( + showToolBar = showToolBar, + onBackClick = onBackClick, + showProgress = showProgress, + onSubmit = { amount, externalIdOrMobile, sendMethodType -> + if (!viewModel.checkSelfTransfer( + selfVpa = selfVpa, + selfMobile = selfMobile, + sendMethodType = sendMethodType, + externalIdOrMobile = externalIdOrMobile + ) + ) { + viewModel.checkBalanceAvailabilityAndTransfer( + externalId = selfVpa, + transferAmount = amount.toDouble(), + onAnyError = { + showToast(context.getString(it)) + }, + proceedWithTransferFlow = { externalId, transferAmount -> + proceedWithMakeTransferFlow.invoke(externalIdOrMobile, transferAmount.toString()) + } + ) + } else { + showToast(context.getString(R.string.self_amount_transfer_is_not_allowed)) + } + } + ) +} + +@Composable +fun SendMoneyScreen( + showToolBar: Boolean, + showProgress: Boolean, + onSubmit: (String, String, SendMethodType) -> Unit, + onBackClick: () -> Unit, +) { + + val context = LocalContext.current + + var amount by rememberSaveable { mutableStateOf("") } + var vpa by rememberSaveable { mutableStateOf("") } + var mobileNumber by rememberSaveable { mutableStateOf("") } + var isValidMobileNumber by rememberSaveable { mutableStateOf(false) } + var sendMethodType by rememberSaveable { mutableStateOf(SendMethodType.VPA) } + var isValidInfo by rememberSaveable { mutableStateOf(false) } + + var contactUri by rememberSaveable { mutableStateOf(null) } + + fun validateInfo() { + isValidInfo = when (sendMethodType) { + SendMethodType.VPA -> amount.isNotEmpty() && vpa.isNotEmpty() + SendMethodType.MOBILE -> { + isValidMobileNumber && mobileNumber.isNotEmpty() && amount.isNotEmpty() + } + } + } + + val contactLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.PickContact() + ) { uri: Uri? -> + uri?.let { contactUri = uri } + } + + LaunchedEffect(key1 = contactUri) { + contactUri?.let { + mobileNumber = getContactPhoneNumber(it, context) + } + } + + val permissionLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.RequestPermission(), + onResult = { isGranted: Boolean -> + if (isGranted) { + contactLauncher.launch(null) + } else { + // Handle permission denial + } + } + ) + + val options = GmsBarcodeScannerOptions.Builder() + .setBarcodeFormats( + Barcode.FORMAT_QR_CODE, + Barcode.FORMAT_AZTEC + ) + .build() + + val scanner = GmsBarcodeScanning.getClient(context, options) + + fun startScan() { + scanner.startScan() + .addOnSuccessListener { barcode -> + barcode.rawValue?.let { + vpa = it + } + } + .addOnCanceledListener { + // Task canceled + } + .addOnFailureListener { e -> + // Task failed with an exception + e.localizedMessage?.let { Log.d("SendMoney: Barcode scan failed", it) } + } + } + + Box { + Column(Modifier.fillMaxSize()) { + if (showToolBar) { + MifosNavigationTopAppBar( + titleRes = R.string.send, + onNavigationClick = onBackClick + ) + } + Text( + modifier = Modifier.padding(start = 20.dp, top = 20.dp), + text = stringResource(id = R.string.select_transfer_method), + style = styleNormal18sp + ) + Column(modifier = Modifier.padding(16.dp)) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, bottom = 20.dp) + ) { + VpaMobileChip( + selected = sendMethodType == SendMethodType.VPA, + onClick = { sendMethodType = SendMethodType.VPA }, + label = stringResource(id = R.string.vpa) + ) + Spacer(modifier = Modifier.width(8.dp)) + VpaMobileChip( + selected = sendMethodType == SendMethodType.MOBILE, + onClick = { sendMethodType = SendMethodType.MOBILE }, + label = stringResource(id = R.string.mobile) + ) + } + MfOutlinedTextField( + value = amount, + onValueChange = { + amount = it + validateInfo() + }, + singleLine = true, + keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number), + label = stringResource(id = R.string.amount), + modifier = Modifier.fillMaxWidth() + ) + when (sendMethodType) { + SendMethodType.VPA -> { + MfOutlinedTextField( + value = vpa, + onValueChange = { + vpa = it + validateInfo() + }, + label = stringResource(id = R.string.virtual_payment_address), + modifier = Modifier.fillMaxWidth(), + trailingIcon = { + IconButton(onClick = { + startScan() + }) { + Icon( + imageVector = Icons.Filled.QrCode2, + contentDescription = "Scan QR", + tint = Color.Blue + ) + } + } + ) + } + + SendMethodType.MOBILE -> { + EnterPhoneScreen( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 8.dp), + initialPhoneNumber = mobileNumber, + onNumberUpdated = { _, fullPhone, valid -> + if (valid) { + mobileNumber = fullPhone + } + isValidMobileNumber = valid + validateInfo() + } + ) + } + } + Spacer(modifier = Modifier.height(16.dp)) + MifosButton( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp) + .align(Alignment.CenterHorizontally), + color = Color.Black, + enabled = isValidInfo, + onClick = { + if (!isValidInfo) return@MifosButton + onSubmit( + amount, + when (sendMethodType) { + SendMethodType.VPA -> vpa + SendMethodType.MOBILE -> mobileNumber + }, + sendMethodType + ) + //TODO: Navigate to MakeTransferScreenRoute + }, + contentPadding = PaddingValues(12.dp) + ) { + Text( + stringResource(id = R.string.submit), + style = styleMedium16sp.copy(color = Color.White) + ) + } + } + } + if (showProgress) { + MfOverlayLoadingWheel( + contentDesc = stringResource(id = R.string.please_wait) + ) + } + } +} + +@Composable +fun EnterPhoneScreen( + modifier: Modifier, + initialPhoneNumber: String? = null, + onNumberUpdated: (String, String, Boolean) -> Unit +) { + val keyboardController = LocalSoftwareKeyboardController.current + TogiCountryCodePicker( + modifier = modifier, + shape = RoundedCornerShape(8.dp), + colors = TextFieldDefaults.outlinedTextFieldColors( + focusedBorderColor = MaterialTheme.colorScheme.primary + ), + initialPhoneNumber = initialPhoneNumber, + onValueChange = { (code, phone), isValid -> + onNumberUpdated(phone, code + phone, isValid) + }, + label = { Text(stringResource(id = R.string.phone_number)) }, + keyboardActions = KeyboardActions { keyboardController?.hide() } + ) +} + +@Composable +fun VpaMobileChip(selected: Boolean, onClick: () -> Unit, label: String) { + MifosButton( + onClick = onClick, + color = if (selected) Color.Black else Color.LightGray, + modifier = Modifier + .padding(4.dp) + .wrapContentSize() + ) { + Text( + modifier = Modifier.padding(top = 4.dp, bottom = 4.dp), + text = label, + ) + } +} + +suspend fun getContactPhoneNumber(uri: Uri, context: Context): String { + val contactId: String = uri.lastPathSegment ?: return "" + return withContext(Dispatchers.IO) { + val phoneCursor = context.contentResolver.query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER), + "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?", + arrayOf(contactId), + null + ) + phoneCursor?.use { cursor -> + if (cursor.moveToFirst()) { + val phoneNumberIndex = + cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) + cursor.getString(phoneNumberIndex) + } else { + "" + } + } ?: "" + } +} + + +@Preview(showSystemUi = true, showBackground = true) +@Composable +fun SendMoneyScreenWithToolBarPreview() { + SendMoneyScreen( + onSubmit = { _, _, _ -> }, + onBackClick = {}, + showProgress = false, + showToolBar = true + ) +} + +@Preview(showSystemUi = true, showBackground = true) +@Composable +fun SendMoneyScreenWithoutToolBarPreview() { + SendMoneyScreen( + onSubmit = { _, _, _ -> }, + onBackClick = {}, + showProgress = false, + showToolBar = false + ) +} diff --git a/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/navigation/SendNavigation.kt b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/navigation/SendNavigation.kt new file mode 100644 index 000000000..49f0a0ad0 --- /dev/null +++ b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/navigation/SendNavigation.kt @@ -0,0 +1,26 @@ +package org.mifospay.feature.send.money.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import org.mifospay.feature.send.money.SendScreenRoute + +const val SEND_MONEY_ROUTE = "send_money_route" + +fun NavController.navigateToSendMoneyScreen( + navOptions: NavOptions? = null +) = navigate(SEND_MONEY_ROUTE, navOptions) + +fun NavGraphBuilder.sendMoneyScreen( + proceedWithMakeTransferFlow: (String, String?) -> Unit, + onBackClick: () -> Unit +) { + composable(route = SEND_MONEY_ROUTE) { + SendScreenRoute( + showToolBar = true, + onBackClick = onBackClick, + proceedWithMakeTransferFlow = proceedWithMakeTransferFlow + ) + } +} diff --git a/feature/send-money/src/main/res/values/strings.xml b/feature/send-money/src/main/res/values/strings.xml new file mode 100644 index 000000000..0a045245f --- /dev/null +++ b/feature/send-money/src/main/res/values/strings.xml @@ -0,0 +1,14 @@ + + Insufficient balance + Error fetching balance + Self Account transfer is not allowed + Send + Select transfer method + VPA + Mobile number + Amount + Virtual Payment Address + Submit + Please wait… + Phone Number + \ No newline at end of file diff --git a/feature/send-money/src/test/java/org/mifospay/feature/send/money/ExampleUnitTest.kt b/feature/send-money/src/test/java/org/mifospay/feature/send/money/ExampleUnitTest.kt new file mode 100644 index 000000000..1d7ba503a --- /dev/null +++ b/feature/send-money/src/test/java/org/mifospay/feature/send/money/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package org.mifospay.feature.send.money + +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) + } +} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/common/ui/MakeTransferFragment.kt b/mifospay/src/main/java/org/mifospay/common/ui/MakeTransferFragment.kt index ebd8198a9..1b43e8774 100644 --- a/mifospay/src/main/java/org/mifospay/common/ui/MakeTransferFragment.kt +++ b/mifospay/src/main/java/org/mifospay/common/ui/MakeTransferFragment.kt @@ -28,6 +28,7 @@ import javax.inject.Inject /** * Created by naman on 30/8/17. + * Moved to the feature/make-transfer */ @AndroidEntryPoint class MakeTransferFragment : BottomSheetDialogFragment(), TransferContract.TransferView { diff --git a/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt b/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt index ec3e87018..8576ab992 100644 --- a/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt +++ b/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt @@ -74,7 +74,9 @@ fun MifosNavHost( navController.navigateToMakeTransferScreen(externalId, transferAmount) } ) - makeTransferScreen() + makeTransferScreen( + onDismiss = navController::popBackStack + ) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 822ce0cba..94186a8da 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,3 +36,4 @@ include(":core:analytics") include(":feature:passcode") include(":feature:auth") include(":feature:make-transfer") +include(":feature:send-money")