Skip to content

Commit 28b549c

Browse files
authored
feat: implement recurring deposit account with stepper UI (#2523)
Co-authored-by: kampit ojha <97059622+Itskampitojha@users.noreply.github.com>
1 parent bb4e8b8 commit 28b549c

File tree

10 files changed

+367
-1
lines changed

10 files changed

+367
-1
lines changed

feature/client/src/commonMain/composeResources/values/strings.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@
481481
<string name="client_apply_new_applications_apply_recurring_account">Apply for new recurring deposit account</string>
482482
<string name="client_apply_new_applications_apply_fixed_account">Apply for new fixed deposit account</string>
483483

484+
<string name="step_details">Details</string>
485+
<string name="step_terms">Terms</string>
486+
<string name="step_settings">Settings</string>
487+
<string name="step_interest">Interest</string>
488+
<string name="step_charges">Charges</string>
489+
<string name="create_recurring_deposit_account">Create Recurring Deposit Account</string>
490+
491+
484492
<!-- Client Signature -->
485493
<string name="client_signature_delete">Delete Signature</string>
486494
<string name="client_signature_upload">Upload New Signature</string>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount
11+
12+
import androidx.navigation.NavController
13+
import androidx.navigation.NavGraphBuilder
14+
import androidx.navigation.compose.composable
15+
import kotlinx.serialization.Serializable
16+
17+
@Serializable
18+
data object RecurringAccountRoute
19+
20+
fun NavGraphBuilder.recurringAccountDestination() {
21+
composable<RecurringAccountRoute> {
22+
RecurringAccountScreen(
23+
onNavigateBack = {},
24+
onFinish = {},
25+
)
26+
}
27+
}
28+
29+
fun NavController.navigateToRecurringAccountRoute() {
30+
this.navigate(
31+
RecurringAccountRoute,
32+
)
33+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount
11+
12+
import androidclient.feature.client.generated.resources.Res
13+
import androidclient.feature.client.generated.resources.create_recurring_deposit_account
14+
import androidclient.feature.client.generated.resources.step_charges
15+
import androidclient.feature.client.generated.resources.step_details
16+
import androidclient.feature.client.generated.resources.step_interest
17+
import androidclient.feature.client.generated.resources.step_settings
18+
import androidclient.feature.client.generated.resources.step_terms
19+
import androidx.compose.foundation.layout.fillMaxWidth
20+
import androidx.compose.foundation.layout.padding
21+
import androidx.compose.runtime.Composable
22+
import androidx.compose.runtime.getValue
23+
import androidx.compose.ui.Modifier
24+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
25+
import androidx.lifecycle.viewmodel.compose.viewModel
26+
import com.mifos.core.designsystem.component.MifosScaffold
27+
import com.mifos.core.ui.components.MifosStepper
28+
import com.mifos.core.ui.components.Step
29+
import com.mifos.core.ui.util.EventsEffect
30+
import com.mifos.feature.client.createRecurringDepositAccount.pages.ChargesPage
31+
import com.mifos.feature.client.createRecurringDepositAccount.pages.DetailsPage
32+
import com.mifos.feature.client.createRecurringDepositAccount.pages.InterestPage
33+
import com.mifos.feature.client.createRecurringDepositAccount.pages.SettingPage
34+
import com.mifos.feature.client.createRecurringDepositAccount.pages.TermsPage
35+
import org.jetbrains.compose.resources.stringResource
36+
37+
@Composable
38+
internal fun RecurringAccountScreen(
39+
onNavigateBack: () -> Unit,
40+
onFinish: () -> Unit,
41+
modifier: Modifier = Modifier,
42+
viewModel: RecurringAccountViewModel = viewModel(),
43+
) {
44+
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
45+
46+
EventsEffect(viewModel.eventFlow) { event ->
47+
when (event) {
48+
RecurringAccountEvent.NavigateBack -> onNavigateBack()
49+
RecurringAccountEvent.Finish -> onFinish()
50+
}
51+
}
52+
53+
RecurringAccountScaffold(
54+
modifier = modifier,
55+
state = state,
56+
onAction = { viewModel.trySendAction(it) },
57+
)
58+
}
59+
60+
@Composable
61+
private fun RecurringAccountScaffold(
62+
state: RecurringAccountState,
63+
modifier: Modifier = Modifier,
64+
onAction: (RecurringAccountAction) -> Unit,
65+
) {
66+
val steps = listOf(
67+
Step(name = stringResource(Res.string.step_details)) {
68+
DetailsPage(
69+
onNext = { onAction(RecurringAccountAction.NextStep) },
70+
)
71+
},
72+
Step(name = stringResource(Res.string.step_terms)) {
73+
TermsPage(
74+
onNext = { onAction(RecurringAccountAction.NextStep) },
75+
)
76+
},
77+
Step(name = stringResource(Res.string.step_settings)) {
78+
SettingPage(
79+
onNext = { onAction(RecurringAccountAction.NextStep) },
80+
)
81+
},
82+
Step(name = stringResource(Res.string.step_interest)) {
83+
InterestPage(
84+
onNext = { onAction(RecurringAccountAction.NextStep) },
85+
)
86+
},
87+
Step(name = stringResource(Res.string.step_charges)) {
88+
ChargesPage(
89+
onNext = { onAction(RecurringAccountAction.NextStep) },
90+
)
91+
},
92+
)
93+
94+
MifosScaffold(
95+
title = stringResource(Res.string.create_recurring_deposit_account),
96+
onBackPressed = { onAction(RecurringAccountAction.NavigateBack) },
97+
modifier = modifier,
98+
) { paddingValues ->
99+
if (state.dialogState == null) {
100+
MifosStepper(
101+
steps = steps,
102+
currentIndex = state.currentStep,
103+
onStepChange = { newIndex ->
104+
onAction(RecurringAccountAction.OnStepChange(newIndex))
105+
},
106+
modifier = Modifier
107+
.fillMaxWidth()
108+
.padding(paddingValues),
109+
)
110+
}
111+
}
112+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount
11+
12+
import com.mifos.core.ui.util.BaseViewModel
13+
import kotlinx.coroutines.flow.update
14+
15+
class RecurringAccountViewModel :
16+
BaseViewModel<RecurringAccountState, RecurringAccountEvent, RecurringAccountAction>(RecurringAccountState()) {
17+
18+
override fun handleAction(action: RecurringAccountAction) {
19+
when (action) {
20+
RecurringAccountAction.NextStep -> {
21+
mutableStateFlow.update { state ->
22+
val maxIndex = 4
23+
state.copy(currentStep = (state.currentStep + 1).coerceAtMost(maxIndex))
24+
}
25+
}
26+
is RecurringAccountAction.OnStepChange -> {
27+
mutableStateFlow.update { it.copy(currentStep = action.index) }
28+
}
29+
RecurringAccountAction.NavigateBack -> {
30+
sendEvent(RecurringAccountEvent.NavigateBack)
31+
}
32+
RecurringAccountAction.Finish -> {
33+
sendEvent(RecurringAccountEvent.Finish)
34+
}
35+
}
36+
}
37+
}
38+
39+
data class RecurringAccountState(
40+
val currentStep: Int = 0,
41+
val dialogState: Any? = null,
42+
)
43+
44+
sealed class RecurringAccountAction {
45+
object NextStep : RecurringAccountAction()
46+
data class OnStepChange(val index: Int) : RecurringAccountAction()
47+
object NavigateBack : RecurringAccountAction()
48+
object Finish : RecurringAccountAction()
49+
}
50+
51+
sealed class RecurringAccountEvent {
52+
object NavigateBack : RecurringAccountEvent()
53+
object Finish : RecurringAccountEvent()
54+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount.pages
11+
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Spacer
14+
import androidx.compose.foundation.layout.height
15+
import androidx.compose.material3.Button
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
22+
@Composable
23+
fun ChargesPage(onNext: () -> Unit) {
24+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
25+
Text("Charges Page")
26+
Spacer(Modifier.height(8.dp))
27+
Button(onClick = onNext) {
28+
Text("Next Button")
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount.pages
11+
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Spacer
14+
import androidx.compose.foundation.layout.height
15+
import androidx.compose.material3.Button
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
22+
@Composable
23+
fun DetailsPage(onNext: () -> Unit) {
24+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
25+
Text("Details Page")
26+
Spacer(Modifier.height(8.dp))
27+
Button(onClick = onNext) {
28+
Text("Next Button")
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount.pages
11+
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Spacer
14+
import androidx.compose.foundation.layout.height
15+
import androidx.compose.material3.Button
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
22+
@Composable
23+
fun InterestPage(onNext: () -> Unit) {
24+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
25+
Text("Interest Page")
26+
Spacer(Modifier.height(8.dp))
27+
Button(onClick = onNext) {
28+
Text("Next Button")
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount.pages
11+
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Spacer
14+
import androidx.compose.foundation.layout.height
15+
import androidx.compose.material3.Button
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
22+
@Composable
23+
fun SettingPage(onNext: () -> Unit) {
24+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
25+
Text("Settings Page")
26+
Spacer(Modifier.height(8.dp))
27+
Button(onClick = onNext) {
28+
Text("Next Button")
29+
}
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
9+
*/
10+
package com.mifos.feature.client.createRecurringDepositAccount.pages
11+
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Spacer
14+
import androidx.compose.foundation.layout.height
15+
import androidx.compose.material3.Button
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
22+
@Composable
23+
fun TermsPage(onNext: () -> Unit) {
24+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
25+
Text("Terms Page")
26+
Spacer(Modifier.height(8.dp))
27+
Button(onClick = onNext) {
28+
Text("Next Button")
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)