Skip to content

Commit ac16ab6

Browse files
committed
feat: Implement Interest Charts step in Fixed Deposit Account creation flow
- Add InterestChartsPage component with chart information display - Implement interest rate chart modal with CRUD operations - Add validation for interest rates and navigation controls - Setup state management and view model for the feature - Add download functionality for chart details Implements MIFOSAC-560
1 parent 5c6bb70 commit ac16ab6

File tree

3 files changed

+485
-0
lines changed

3 files changed

+485
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mifos.feature.client.fixedDepositAccount.creation
17+
18+
import com.mifos.feature.client.fixedDepositAccount.creation.pages.InterestRateChart
19+
20+
data class FixedDepositAccountState(
21+
val clientId: Int = -1,
22+
val currentStep: Int = 4,
23+
val template: FixedDepositTemplate? = null,
24+
val interestRateCharts: List<InterestRateChart> = emptyList(),
25+
val selectedChart: InterestRateChart? = null,
26+
val error: String? = null,
27+
val isLoading: Boolean = false
28+
)
29+
30+
data class FixedDepositTemplate(
31+
val chartName: String? = null,
32+
val fromDate: String? = null,
33+
val endDate: String? = null,
34+
val description: String? = null,
35+
val isAmountGrouped: Boolean? = false
36+
)
37+
38+
sealed class FixedDepositAccountAction {
39+
object NavigateBack : FixedDepositAccountAction()
40+
object NavigateNext : FixedDepositAccountAction()
41+
object DownloadChart : FixedDepositAccountAction()
42+
data class EditInterestRate(val chart: InterestRateChart) : FixedDepositAccountAction()
43+
data class DeleteInterestRate(val chartId: String) : FixedDepositAccountAction()
44+
data class AddInterestRate(
45+
val amountRange: String,
46+
val period: String,
47+
val interestRate: Double,
48+
val description: String?
49+
) : FixedDepositAccountAction()
50+
data class UpdateInterestRate(
51+
val chartId: String,
52+
val amountRange: String,
53+
val period: String,
54+
val interestRate: Double,
55+
val description: String?
56+
) : FixedDepositAccountAction()
57+
}
58+
59+
sealed class FixedDepositAccountEvent {
60+
data class ShowError(val message: String) : FixedDepositAccountEvent()
61+
data class NavigateToStep(val step: Int) : FixedDepositAccountEvent()
62+
object ShowDownloadSuccess : FixedDepositAccountEvent()
63+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mifos.feature.client.fixedDepositAccount.creation
17+
18+
import androidx.lifecycle.viewModelScope
19+
import com.mifos.core.base.BaseViewModel
20+
import com.mifos.feature.client.fixedDepositAccount.creation.pages.InterestRateChart
21+
import kotlinx.coroutines.flow.update
22+
import kotlinx.coroutines.launch
23+
import java.util.UUID
24+
25+
class FixedDepositAccountViewModel : BaseViewModel<
26+
FixedDepositAccountState,
27+
FixedDepositAccountEvent,
28+
FixedDepositAccountAction
29+
>(initialState = FixedDepositAccountState()) {
30+
31+
init {
32+
loadTemplate()
33+
}
34+
35+
private fun loadTemplate() {
36+
viewModelScope.launch {
37+
// TODO: Load actual template data from API
38+
val mockTemplate = FixedDepositTemplate(
39+
chartName = "Fixed Deposit Interest Chart",
40+
fromDate = "2025-01-01",
41+
endDate = "2025-12-31",
42+
description = "Standard fixed deposit interest rates",
43+
isAmountGrouped = true
44+
)
45+
46+
val mockCharts = listOf(
47+
InterestRateChart(
48+
id = UUID.randomUUID().toString(),
49+
amountRange = "1000-5000",
50+
period = "6 months",
51+
interestRate = 5.5,
52+
description = "Standard 6-month rate"
53+
),
54+
InterestRateChart(
55+
id = UUID.randomUUID().toString(),
56+
amountRange = "5001-10000",
57+
period = "12 months",
58+
interestRate = 6.5,
59+
description = "Standard 12-month rate"
60+
)
61+
)
62+
63+
mutableStateFlow.update {
64+
it.copy(
65+
template = mockTemplate,
66+
interestRateCharts = mockCharts
67+
)
68+
}
69+
}
70+
}
71+
72+
override fun handleAction(action: FixedDepositAccountAction) {
73+
when (action) {
74+
is FixedDepositAccountAction.NavigateBack -> {
75+
sendEvent(FixedDepositAccountEvent.NavigateToStep(3))
76+
}
77+
78+
is FixedDepositAccountAction.NavigateNext -> {
79+
if (state.interestRateCharts.isNotEmpty()) {
80+
sendEvent(FixedDepositAccountEvent.NavigateToStep(5))
81+
} else {
82+
sendEvent(FixedDepositAccountEvent.ShowError("At least one interest rate chart is required"))
83+
}
84+
}
85+
86+
is FixedDepositAccountAction.DownloadChart -> {
87+
// TODO: Implement chart download
88+
sendEvent(FixedDepositAccountEvent.ShowDownloadSuccess)
89+
}
90+
91+
is FixedDepositAccountAction.DeleteInterestRate -> {
92+
val updatedCharts = state.interestRateCharts.filter { it.id != action.chartId }
93+
mutableStateFlow.update {
94+
it.copy(interestRateCharts = updatedCharts)
95+
}
96+
}
97+
98+
is FixedDepositAccountAction.EditInterestRate -> {
99+
mutableStateFlow.update {
100+
it.copy(selectedChart = action.chart)
101+
}
102+
}
103+
104+
is FixedDepositAccountAction.AddInterestRate -> {
105+
val newChart = InterestRateChart(
106+
id = UUID.randomUUID().toString(),
107+
amountRange = action.amountRange,
108+
period = action.period,
109+
interestRate = action.interestRate,
110+
description = action.description
111+
)
112+
113+
val updatedCharts = state.interestRateCharts + newChart
114+
mutableStateFlow.update {
115+
it.copy(interestRateCharts = updatedCharts)
116+
}
117+
}
118+
119+
is FixedDepositAccountAction.UpdateInterestRate -> {
120+
val updatedCharts = state.interestRateCharts.map { chart ->
121+
if (chart.id == action.chartId) {
122+
chart.copy(
123+
amountRange = action.amountRange,
124+
period = action.period,
125+
interestRate = action.interestRate,
126+
description = action.description
127+
)
128+
} else {
129+
chart
130+
}
131+
}
132+
133+
mutableStateFlow.update {
134+
it.copy(
135+
interestRateCharts = updatedCharts,
136+
selectedChart = null
137+
)
138+
}
139+
}
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)