Skip to content

Commit 6b05e20

Browse files
authored
feat: Client identities list screen with new UI (#2483)
1 parent bc9b441 commit 6b05e20

9 files changed

Lines changed: 614 additions & 45 deletions

File tree

core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosActionsListingCardComponent.kt

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import androidclient.core.ui.generated.resources.core_ui_balance
1616
import androidclient.core.ui.generated.resources.core_ui_description
1717
import androidclient.core.ui.generated.resources.core_ui_document_id
1818
import androidclient.core.ui.generated.resources.core_ui_document_key
19-
import androidclient.core.ui.generated.resources.core_ui_document_type
2019
import androidclient.core.ui.generated.resources.core_ui_due
2120
import androidclient.core.ui.generated.resources.core_ui_due_as_of
2221
import androidclient.core.ui.generated.resources.core_ui_identify_documents
@@ -34,6 +33,13 @@ import androidclient.core.ui.generated.resources.core_ui_total_collateral_value
3433
import androidclient.core.ui.generated.resources.core_ui_total_value
3534
import androidclient.core.ui.generated.resources.core_ui_type
3635
import androidclient.core.ui.generated.resources.core_ui_waived
36+
import androidx.compose.animation.AnimatedVisibility
37+
import androidx.compose.animation.expandVertically
38+
import androidx.compose.animation.fadeIn
39+
import androidx.compose.animation.fadeOut
40+
import androidx.compose.animation.shrinkVertically
41+
import androidx.compose.animation.slideInVertically
42+
import androidx.compose.animation.slideOutVertically
3743
import androidx.compose.foundation.border
3844
import androidx.compose.foundation.clickable
3945
import androidx.compose.foundation.layout.Arrangement
@@ -56,12 +62,15 @@ import androidx.compose.runtime.saveable.rememberSaveable
5662
import androidx.compose.runtime.setValue
5763
import androidx.compose.ui.Alignment
5864
import androidx.compose.ui.Modifier
65+
import androidx.compose.ui.graphics.Color
5966
import androidx.compose.ui.graphics.vector.ImageVector
67+
import androidx.compose.ui.platform.LocalDensity
6068
import androidx.compose.ui.unit.dp
6169
import com.mifos.core.designsystem.icon.MifosIcons
6270
import com.mifos.core.designsystem.theme.AppColors
6371
import com.mifos.core.designsystem.theme.DesignToken
6472
import com.mifos.core.designsystem.theme.MifosTypography
73+
import com.mifos.core.designsystem.utils.onClick
6574
import org.jetbrains.compose.resources.stringResource
6675
import org.jetbrains.compose.ui.tooling.preview.Preview
6776

@@ -88,18 +97,21 @@ fun MifosActionsIdentifierListingComponent(
8897
type: String,
8998
id: String,
9099
key: String,
91-
status: Status,
100+
status: Status?,
92101
description: String,
93102
identifyDocuments: String,
103+
isExpanded: Boolean,
94104
menuList: List<Actions>,
95105
onActionClicked: (Actions) -> Unit,
106+
onClick: () -> Unit,
96107
) {
108+
val density = LocalDensity.current
109+
97110
MifosActionsListingComponentOutline {
98111
Column {
99-
Column(modifier = Modifier.padding(DesignToken.padding.large)) {
100-
MifosListingRowItem(
101-
key = stringResource(Res.string.core_ui_document_type),
102-
value = type,
112+
Column(modifier = Modifier.padding(DesignToken.padding.large).onClick { onClick() }) {
113+
MifosListingRowItemHeader(
114+
text = type,
103115
keyStyle = MifosTypography.titleSmallEmphasized,
104116
valueStyle = MifosTypography.titleSmall,
105117
)
@@ -117,8 +129,8 @@ fun MifosActionsIdentifierListingComponent(
117129
)
118130
MifosListingRowItem(
119131
key = stringResource(Res.string.core_ui_status),
120-
value = status.name,
121-
valueColor = status.color,
132+
value = status?.name ?: "Not Found",
133+
valueColor = if (status?.name != null) status.color else Color.Red,
122134
)
123135
MifosListingRowItem(
124136
key = stringResource(Res.string.core_ui_description),
@@ -130,40 +142,52 @@ fun MifosActionsIdentifierListingComponent(
130142
)
131143
}
132144
}
133-
Surface(
134-
modifier = Modifier.fillMaxWidth(),
135-
shape = RoundedCornerShape(
136-
bottomStart = DesignToken.padding.medium,
137-
bottomEnd = DesignToken.padding.medium,
145+
AnimatedVisibility(
146+
visible = isExpanded,
147+
enter = slideInVertically {
148+
with(density) { -40.dp.roundToPx() }
149+
} + expandVertically(
150+
expandFrom = Alignment.Top,
151+
) + fadeIn(
152+
initialAlpha = 0.3f,
138153
),
154+
exit = slideOutVertically() + shrinkVertically() + fadeOut(),
139155
) {
140-
Column(
141-
modifier = Modifier.padding(
142-
vertical = DesignToken.padding.small,
156+
Surface(
157+
modifier = Modifier.fillMaxWidth(),
158+
shape = RoundedCornerShape(
159+
bottomStart = DesignToken.padding.medium,
160+
bottomEnd = DesignToken.padding.medium,
143161
),
144162
) {
145-
menuList.map { menuItem ->
146-
Row(
147-
modifier = Modifier.fillMaxWidth()
148-
.height(DesignToken.sizes.avatarMedium)
149-
.clickable {
150-
onActionClicked(menuItem)
151-
},
152-
verticalAlignment = Alignment.CenterVertically,
153-
horizontalArrangement = Arrangement.Start,
154-
) {
155-
Icon(
156-
modifier = Modifier.padding(horizontal = DesignToken.padding.large),
157-
imageVector = menuItem.icon,
158-
contentDescription = "",
159-
)
163+
Column(
164+
modifier = Modifier.padding(
165+
vertical = DesignToken.padding.small,
166+
),
167+
) {
168+
menuList.map { menuItem ->
169+
Row(
170+
modifier = Modifier.fillMaxWidth()
171+
.height(DesignToken.sizes.avatarMedium)
172+
.clickable {
173+
onActionClicked(menuItem)
174+
},
175+
verticalAlignment = Alignment.CenterVertically,
176+
horizontalArrangement = Arrangement.Start,
177+
) {
178+
Icon(
179+
modifier = Modifier.padding(horizontal = DesignToken.padding.large),
180+
imageVector = menuItem.icon,
181+
contentDescription = "",
182+
)
160183

161-
Text(
162-
modifier = Modifier.fillMaxWidth(),
163-
text = menuItem.name,
164-
color = MaterialTheme.colorScheme.onSurface,
165-
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
166-
)
184+
Text(
185+
modifier = Modifier.fillMaxWidth(),
186+
text = menuItem.name,
187+
color = MaterialTheme.colorScheme.onSurface,
188+
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
189+
)
190+
}
167191
}
168192
}
169193
}
@@ -543,7 +567,7 @@ enum class Actions(val icon: ImageVector) {
543567

544568
@Preview
545569
@Composable
546-
fun PreviewMifosActionsIdentifierListingComponent() {
570+
private fun PreviewMifosActionsIdentifierListingComponent() {
547571
MaterialTheme {
548572
MifosActionsIdentifierListingComponent(
549573
type = "Passport",
@@ -565,13 +589,15 @@ fun PreviewMifosActionsIdentifierListingComponent() {
565589
else -> println("Action not Handled")
566590
}
567591
},
592+
onClick = {},
593+
isExpanded = true,
568594
)
569595
}
570596
}
571597

572598
@Preview
573599
@Composable
574-
fun PreviewMifosActionsClientFeeListingComponent() {
600+
private fun PreviewMifosActionsClientFeeListingComponent() {
575601
MaterialTheme {
576602
MifosActionsClientFeeListingComponent(
577603
name = "John Doe",
@@ -621,7 +647,7 @@ fun PreviewMifosActionsSavingsListingComponent() {
621647

622648
@Preview
623649
@Composable
624-
fun PreviewMifosActionsCollateralDataListingComponent() {
650+
private fun PreviewMifosActionsCollateralDataListingComponent() {
625651
MaterialTheme {
626652
MifosActionsCollateralDataListingComponent(
627653
name = "Gold Jewelry",
@@ -645,7 +671,7 @@ fun PreviewMifosActionsCollateralDataListingComponent() {
645671

646672
@Preview
647673
@Composable
648-
fun PreviewMifosActionsLoanListingComponent() {
674+
private fun PreviewMifosActionsLoanListingComponent() {
649675
MaterialTheme {
650676
MifosActionsLoanListingComponent(
651677
accountNo = "LN12345",

core/ui/src/commonMain/kotlin/com/mifos/core/ui/components/MifosListingComponent.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ import androidx.compose.foundation.layout.Spacer
5555
import androidx.compose.foundation.layout.fillMaxWidth
5656
import androidx.compose.foundation.layout.height
5757
import androidx.compose.foundation.layout.padding
58+
import androidx.compose.material3.Icon
5859
import androidx.compose.material3.MaterialTheme
5960
import androidx.compose.material3.Text
6061
import androidx.compose.runtime.Composable
6162
import androidx.compose.ui.Modifier
6263
import androidx.compose.ui.graphics.Color
6364
import androidx.compose.ui.text.TextStyle
6465
import androidx.compose.ui.unit.dp
66+
import com.mifos.core.designsystem.icon.MifosIcons
6567
import com.mifos.core.designsystem.theme.AppColors
6668
import com.mifos.core.designsystem.theme.DesignToken
6769
import com.mifos.core.designsystem.theme.MifosTheme
@@ -123,6 +125,28 @@ fun MifosListingRowItem(
123125
)
124126
}
125127

128+
@Composable
129+
fun MifosListingRowItemHeader(
130+
text: String,
131+
keyStyle: TextStyle = MifosTypography.labelMediumEmphasized,
132+
valueStyle: TextStyle = MifosTypography.labelMedium,
133+
valueColor: Color = MaterialTheme.colorScheme.onSurface,
134+
) {
135+
MifosListingRowItem(
136+
keyContent = {
137+
if (text.isNotBlank()) {
138+
Text(text = text, style = keyStyle)
139+
}
140+
},
141+
valueContent = {
142+
Icon(
143+
imageVector = MifosIcons.MoreHoriz,
144+
contentDescription = "More vert",
145+
)
146+
},
147+
)
148+
}
149+
126150
@Composable
127151
fun MifosDefaultListingComponent(
128152
color: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f),
@@ -427,7 +451,7 @@ fun MifosDelinquencyListingComponent(
427451
) {
428452
MifosListingRowItem(
429453
key = stringResource(Res.string.core_ui_action),
430-
value = if (isPause)"Pause" else "Resume",
454+
value = if (isPause) "Pause" else "Resume",
431455
valueColor = if (isPause) AppColors.customYellow else AppColors.customEnable,
432456
)
433457
MifosListingRowItem(
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2025 Mifos Initiative
4+
5+
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
6+
If a copy of the MPL was not distributed with this file,
7+
You can obtain one at https://mozilla.org/MPL/2.0/.
8+
9+
See https://github.com/openMF/android-client/blob/master/LICENSE.md
10+
-->
11+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
12+
android:width="20dp"
13+
android:height="20dp"
14+
android:viewportWidth="20"
15+
android:viewportHeight="20">
16+
17+
<path
18+
android:fillColor="#191C20"
19+
android:pathData="M15.8332 10.8327H10.8332V15.8327H9.1665V10.8327H4.1665V9.16602H9.1665V4.16602H10.8332V9.16602H15.8332V10.8327Z" />
20+
</vector>

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,16 @@
410410
<string name="client_collateral_success_message">Collateral created successfully. Click Continue to navigate to Client detail profile.</string>
411411
<string name="client_collateral_failure_title">Collateral Creation Failed</string>
412412

413-
<!-- Apply New Applications Screen -->
413+
<string name="client_identifiers_click_on_plus_button_to_add_an_item">Click on “+” Button to add an item.</string>
414+
<string name="client_identifiers_not_available">Not available</string>
415+
<string name="client_identifiers_identities">Identities</string>
416+
<string name="client_identifiers_identities_success_text">Success</string>
417+
<string name="client_identifiers_error_text">Error</string>
418+
<string name="client_identifiers_retry">Retry</string>
419+
<string name="client_identifiers_identities_client_identifier_deletion_success">Successfully deleted client identifier with id</string>
420+
<!-- <string name="client_identifiers_identities">Identities</string>-->
421+
422+
<!-- Apply New Applications Screen -->
414423
<string name="client_apply_new_applications_title">Choose Application Type</string>
415424
<string name="client_apply_new_applications_loan_account">New Loan Account</string>
416425
<string name="client_apply_new_applications_savings_account">New Savings Account</string>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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.clientIdentitiesList
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 class ClientIdentitiesListRoute(
19+
val clientId: Int = -1,
20+
)
21+
22+
fun NavGraphBuilder.clientIdentitiesListDestination(
23+
addNewClientIdentity: (Int) -> Unit,
24+
) {
25+
composable<ClientIdentitiesListRoute> {
26+
ClientIdentitiesListScreenRoute(
27+
addNewClientIdentity = addNewClientIdentity,
28+
)
29+
}
30+
}
31+
32+
fun NavController.navigateToClientIdentifiersScreen(
33+
clientId: Int,
34+
) {
35+
this.navigate(ClientIdentitiesListRoute(clientId = clientId))
36+
}

0 commit comments

Comments
 (0)