Skip to content

Commit 35d7fca

Browse files
authored
Implemented Account Filters in Bottom Sheet (Saving Account, Loan Account, Share Account) (#2994)
1 parent 43af85e commit 35d7fca

File tree

4 files changed

+79
-70
lines changed

4 files changed

+79
-70
lines changed

core/designsystem/src/commonMain/kotlin/org/mifos/mobile/core/designsystem/component/MifosBottomSheet.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.compose.animation.AnimatedVisibility
1313
import androidx.compose.foundation.layout.Box
1414
import androidx.compose.foundation.layout.height
1515
import androidx.compose.material3.ExperimentalMaterial3Api
16+
import androidx.compose.material3.MaterialTheme
1617
import androidx.compose.material3.ModalBottomSheet
1718
import androidx.compose.material3.rememberModalBottomSheetState
1819
import androidx.compose.runtime.Composable
@@ -22,7 +23,6 @@ import androidx.compose.runtime.remember
2223
import androidx.compose.runtime.rememberCoroutineScope
2324
import androidx.compose.runtime.setValue
2425
import androidx.compose.ui.Modifier
25-
import androidx.compose.ui.graphics.Color
2626
import androidx.compose.ui.unit.dp
2727
import com.arkivanov.essenty.backhandler.BackCallback
2828
import kotlinx.coroutines.launch
@@ -54,7 +54,7 @@ fun MifosBottomSheet(
5454

5555
AnimatedVisibility(visible = showBottomSheet) {
5656
ModalBottomSheet(
57-
containerColor = Color.White,
57+
containerColor = MaterialTheme.colorScheme.surface,
5858
onDismissRequest = {
5959
showBottomSheet = false
6060
dismissSheet()

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
<string name="feature_loan_account_title">Loan Accounts</string>
1515
<string name="feature_saving_account_title">Saving Accounts</string>
1616
<string name="feature_share_account_title">Share Accounts</string>
17+
18+
<string name="feature_accounts_filter_status">Status</string>
19+
<string name="feature_accounts_filter_type">Type</string>
20+
1721
<!-- Loan Account Filters-->
1822

1923
<string name="feature_loan_account_filter_active">Active</string>

feature/accounts/src/commonMain/kotlin/org/mifos/mobile/feature/accounts/accounts/AccountsScreen.kt

Lines changed: 53 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,21 @@ import androidx.compose.material3.HorizontalDivider
2222
import androidx.compose.material3.Surface
2323
import androidx.compose.runtime.Composable
2424
import androidx.compose.runtime.getValue
25-
import androidx.compose.runtime.mutableStateOf
2625
import androidx.compose.runtime.remember
27-
import androidx.compose.runtime.saveable.rememberSaveable
28-
import androidx.compose.runtime.setValue
2926
import androidx.compose.ui.Modifier
3027
import androidx.compose.ui.unit.dp
3128
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3229
import mifos_mobile.feature.accounts.generated.resources.Res
33-
import mifos_mobile.feature.accounts.generated.resources.feature_account_title
30+
import mifos_mobile.feature.accounts.generated.resources.feature_accounts_filter_status
31+
import mifos_mobile.feature.accounts.generated.resources.feature_accounts_filter_type
3432
import mifos_mobile.feature.accounts.generated.resources.feature_loan_account_title
3533
import mifos_mobile.feature.accounts.generated.resources.feature_saving_account_title
3634
import mifos_mobile.feature.accounts.generated.resources.feature_share_account_title
3735
import org.jetbrains.compose.resources.stringResource
3836
import org.koin.compose.viewmodel.koinViewModel
3937
import org.mifos.mobile.core.designsystem.component.BasicDialogState
4038
import org.mifos.mobile.core.designsystem.component.MifosBasicDialog
39+
import org.mifos.mobile.core.designsystem.component.MifosBottomSheet
4140
import org.mifos.mobile.core.designsystem.component.MifosElevatedScaffold
4241
import org.mifos.mobile.core.designsystem.component.rememberMifosPullToRefreshState
4342
import org.mifos.mobile.core.designsystem.theme.DesignToken
@@ -115,17 +114,22 @@ internal fun AccountsDialog(
115114
onDismissRequest = { onAction(AccountsAction.DismissDialog) },
116115
)
117116
}
118-
AccountsState.DialogState.Filters -> SavingsAccountFilters(
119-
state = state,
120-
onAction = onAction,
117+
AccountsState.DialogState.Filters -> MifosBottomSheet(
118+
content = {
119+
SavingsAccountFilters(
120+
state = state,
121+
onAction = onAction,
122+
)
123+
},
121124
modifier = modifier,
125+
onDismiss = { onAction(AccountsAction.DismissDialog) },
122126
)
123127
null -> {}
124128
}
125129
}
126130

127131
/**
128-
* Composable function that displays the Savings Account Filters Dialog.
132+
* Composable function that displays the Savings Account Filters Bottom Bar.
129133
*
130134
* @param state The state of the screen.
131135
* @param onAction The function to be called when an action is performed.
@@ -137,68 +141,51 @@ internal fun SavingsAccountFilters(
137141
onAction: (AccountsAction) -> Unit,
138142
modifier: Modifier = Modifier,
139143
) {
140-
var isTypeExpanded by rememberSaveable { mutableStateOf(true) }
141-
var isStatusExpanded by rememberSaveable { mutableStateOf(true) }
142-
143-
MifosElevatedScaffold(
144-
onNavigateBack = { onAction(AccountsAction.OnNavigateBack) },
145-
topBarTitle = stringResource(Res.string.feature_account_title),
146-
bottomBar = {
147-
Surface {
148-
MifosPoweredCard(
149-
modifier = modifier
150-
.fillMaxWidth()
151-
.navigationBarsPadding(),
152-
)
153-
}
154-
},
144+
Column(
145+
modifier = modifier
146+
.fillMaxSize()
147+
.verticalScroll(rememberScrollState())
148+
.padding(DesignToken.padding.large)
149+
.padding(top = DesignToken.padding.large),
155150
) {
156-
Column(
157-
modifier = Modifier
158-
.fillMaxSize()
159-
.verticalScroll(rememberScrollState())
160-
.padding(DesignToken.padding.large)
161-
.padding(top = DesignToken.padding.large),
162-
) {
163-
FilterTopSection(
164-
isAnyFilterSelected = state.isAnyFilterSelected,
165-
resetFilters = {
166-
onAction(AccountsAction.ResetFilters)
167-
},
168-
onApplyFilter = {
169-
onAction(AccountsAction.GetFilterResults)
170-
},
171-
dismissDialog = {
172-
onAction(AccountsAction.DismissDialog)
173-
},
174-
)
151+
FilterTopSection(
152+
isAnyFilterSelected = state.isAnyFilterSelected,
153+
resetFilters = {
154+
onAction(AccountsAction.ResetFilters)
155+
},
156+
onApplyFilter = {
157+
onAction(AccountsAction.GetFilterResults)
158+
},
159+
dismissDialog = {
160+
onAction(AccountsAction.DismissDialog)
161+
},
162+
)
175163

176-
Spacer(Modifier.height(DesignToken.spacing.largeIncreased))
164+
Spacer(Modifier.height(DesignToken.spacing.largeIncreased))
177165

178-
HorizontalDivider(modifier = Modifier.height(1.dp))
166+
HorizontalDivider(modifier = Modifier.height(1.dp))
179167

180-
FilterSection(
181-
title = "Type",
182-
filtersSelected = state.accountTypeFiltersCount ?: 0,
183-
isExpanded = isTypeExpanded,
184-
onToggle = { isTypeExpanded = !isTypeExpanded },
185-
filters = state.checkboxOptions.filter { it.type == FilterType.ACCOUNT_TYPE },
186-
onCheckChanged = { label ->
187-
onAction(AccountsAction.ToggleCheckbox(label, FilterType.ACCOUNT_TYPE))
188-
},
189-
)
168+
FilterSection(
169+
title = stringResource(Res.string.feature_accounts_filter_type),
170+
filtersSelected = state.accountTypeFiltersCount ?: 0,
171+
isExpanded = state.isTypeExpanded,
172+
onToggle = { onAction(AccountsAction.ToggleTypeExpanded) },
173+
filters = state.checkboxOptions.filter { it.type == FilterType.ACCOUNT_TYPE },
174+
onCheckChanged = { label ->
175+
onAction(AccountsAction.ToggleCheckbox(label, FilterType.ACCOUNT_TYPE))
176+
},
177+
)
190178

191-
FilterSection(
192-
title = "Status",
193-
filtersSelected = state.accountStatusFiltersCount ?: 0,
194-
isExpanded = isStatusExpanded,
195-
onToggle = { isStatusExpanded = !isStatusExpanded },
196-
filters = state.checkboxOptions.filter { it.type == FilterType.ACCOUNT_STATUS },
197-
onCheckChanged = { label ->
198-
onAction(AccountsAction.ToggleCheckbox(label, FilterType.ACCOUNT_STATUS))
199-
},
200-
)
201-
}
179+
FilterSection(
180+
title = stringResource(Res.string.feature_accounts_filter_status),
181+
filtersSelected = state.accountStatusFiltersCount ?: 0,
182+
isExpanded = state.isStatusExpanded,
183+
onToggle = { onAction(AccountsAction.ToggleStatusExpanded) },
184+
filters = state.checkboxOptions.filter { it.type == FilterType.ACCOUNT_STATUS },
185+
onCheckChanged = { label ->
186+
onAction(AccountsAction.ToggleCheckbox(label, FilterType.ACCOUNT_STATUS))
187+
},
188+
)
202189
}
203190
}
204191

@@ -207,13 +194,11 @@ internal fun SavingsAccountFilters(
207194
*
208195
* @param state The state of the screen.
209196
* @param onAction The function to be called when an action is performed.
210-
* @param modifier Modifier to be applied to the layout.
211197
*/
212198
@Composable
213199
internal fun AccountScreenContent(
214200
state: AccountsState,
215201
onAction: (AccountsAction) -> Unit,
216-
modifier: Modifier = Modifier,
217202
) {
218203
val isRefreshing = state.isRefreshing
219204
val pullToRefreshState = rememberMifosPullToRefreshState(
@@ -235,7 +220,7 @@ internal fun AccountScreenContent(
235220
bottomBar = {
236221
Surface {
237222
MifosPoweredCard(
238-
modifier = modifier
223+
modifier = Modifier
239224
.fillMaxWidth()
240225
.navigationBarsPadding(),
241226
)

feature/accounts/src/commonMain/kotlin/org/mifos/mobile/feature/accounts/accounts/AccountsViewModel.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ internal class AccountsViewModel(
8383
is AccountsAction.OnNavigateBack -> sendEvent(AccountsEvent.NavigateBack)
8484

8585
is AccountsAction.ToggleCheckbox -> toggleCheckbox(action.label, action.type)
86+
AccountsAction.ToggleTypeExpanded -> handleToggleTypeExpanded()
87+
AccountsAction.ToggleStatusExpanded -> handleToggleStatusExpanded()
8688
}
8789
}
8890

@@ -97,6 +99,20 @@ internal class AccountsViewModel(
9799
}
98100
}
99101

102+
/**
103+
* Toggles the expanded state of the type filter section.
104+
*/
105+
private fun handleToggleTypeExpanded() {
106+
mutableStateFlow.update { it.copy(isTypeExpanded = !it.isTypeExpanded) }
107+
}
108+
109+
/**
110+
* Toggles the expanded state of the status filter section.
111+
*/
112+
private fun handleToggleStatusExpanded() {
113+
mutableStateFlow.update { it.copy(isStatusExpanded = !it.isStatusExpanded) }
114+
}
115+
100116
/**
101117
* Resets all filter checkboxes and filter counters.
102118
*/
@@ -231,6 +247,8 @@ constructor(
231247
val refreshSignal: Long = Clock.System.now().epochSeconds,
232248
val dialogState: DialogState? = null,
233249
val uiState: ScreenUiState = ScreenUiState.Loading,
250+
val isTypeExpanded: Boolean = true,
251+
val isStatusExpanded: Boolean = true,
234252
) {
235253

236254
sealed interface DialogState {
@@ -258,6 +276,8 @@ constructor(
258276
internal sealed interface AccountsAction {
259277

260278
data object ToggleFilter : AccountsAction
279+
data object ToggleTypeExpanded : AccountsAction
280+
data object ToggleStatusExpanded : AccountsAction
261281

262282
data object ResetFilters : AccountsAction
263283

0 commit comments

Comments
 (0)