Skip to content

Commit f384d91

Browse files
authored
fix: Display Client Group Name and enable navigation (#2571)
1 parent 66bd691 commit f384d91

11 files changed

Lines changed: 111 additions & 8 deletions

File tree

core/data/src/commonMain/kotlin/com/mifos/core/data/repositoryImp/ClientDetailsRepositoryImp.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,17 @@ class ClientDetailsRepositoryImp(
9494
}
9595

9696
override suspend fun getClient(clientId: Int): ClientEntity {
97-
return dataManagerClient.getClient(clientId)
97+
val client = dataManagerClient.getClient(clientId)
98+
99+
if (client.groupName.isNullOrBlank() && !client.groups.isNullOrEmpty()) {
100+
client.groups?.firstOrNull()?.let { firstGroup ->
101+
return client.copy(
102+
groupName = firstGroup.name,
103+
groupId = firstGroup.id,
104+
)
105+
}
106+
}
107+
return client
98108
}
99109

100110
override fun getImage(clientId: Int): Flow<DataState<String>> {

core/database/src/commonMain/kotlin/com/mifos/room/entities/client/ClientEntity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ data class ClientEntity(
5858

5959
val groupId: Int? = 0,
6060

61+
val groupName: String? = null,
62+
6163
val accountNo: String? = null,
6264

6365
val clientId: Int? = null,

core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/ClientMapper.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ object ClientMapper : AbstractMapper<GetClientsPageItemsResponse, ClientEntity>(
2828
displayName = entity.displayName,
2929
officeId = entity.officeId!!.toInt(),
3030
officeName = entity.officeName,
31+
groupId = entity.groupId,
32+
groupName = entity.groupName,
3133
active = entity.active!!,
3234
status = ClientStatusEntity(
3335
id = entity.status?.id!!.toInt(),
@@ -53,6 +55,8 @@ object ClientMapper : AbstractMapper<GetClientsPageItemsResponse, ClientEntity>(
5355
displayName = domainModel.displayName,
5456
officeId = domainModel.officeId.toLong(),
5557
officeName = domainModel.officeName,
58+
groupId = domainModel.groupId,
59+
groupName = domainModel.groupName,
5660
active = domainModel.active,
5761
status = GetClientStatus(
5862
id = domainModel.status?.id?.toLong(),

core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsPageItemsResponse.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ data class GetClientsPageItemsResponse(
4545

4646
val officeName: String? = null,
4747

48+
val groupId: Int? = null,
49+
50+
val groupName: String? = null,
51+
4852
val status: GetClientStatus? = null,
4953

5054
val externalId: String? = null,

feature/client/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ kotlin {
3030
implementation(projects.feature.loan)
3131
implementation(projects.feature.document)
3232
implementation(projects.feature.recurringDeposit)
33+
implementation(projects.feature.groups)
3334

3435
implementation(compose.ui)
3536
implementation(compose.material3)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@
388388
<string name="mobile_na">Mobile: N/A</string>
389389
<string name="email_na">Email: N/A</string>
390390
<string name="office_na">Office: N/A</string>
391+
<string name="group_na">N/A</string>
392+
<string name="group_label">Group:</string>
391393

392394
<!-- Titles -->
393395
<string name="title_client_assign_staff">Client Assign Staff</string>

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileNavigation.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ fun NavGraphBuilder.clientProfileDestination(
2828
documents: (Int) -> Unit,
2929
identifiers: (Int) -> Unit,
3030
navigateToClientDetailsScreen: (Int) -> Unit,
31+
navigateToGroupDetails: (Int) -> Unit,
3132
viewAddress: (Int) -> Unit,
3233
viewAssociatedAccounts: (Int) -> Unit,
3334
navigateToAddCharge: (Int) -> Unit,
@@ -40,6 +41,7 @@ fun NavGraphBuilder.clientProfileDestination(
4041
identifiers = identifiers,
4142
onNavigateBack = onNavigateBack,
4243
navigateToClientDetailsScreen = navigateToClientDetailsScreen,
44+
navigateToGroupDetails = navigateToGroupDetails,
4345
viewAddress = viewAddress,
4446
viewAssociatedAccounts = viewAssociatedAccounts,
4547
pinpointLocation = pinpointLocation,

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileScreen.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidclient.feature.client.generated.resources.Res
1313
import androidclient.feature.client.generated.resources.client_profile_actions
1414
import androidclient.feature.client.generated.resources.client_profile_profile
1515
import androidclient.feature.client.generated.resources.client_profile_title
16+
import androidclient.feature.client.generated.resources.group_na
1617
import androidclient.feature.client.generated.resources.name_na
1718
import androidclient.feature.client.generated.resources.office_na
1819
import androidclient.feature.client.generated.resources.string_not_available
@@ -56,6 +57,7 @@ internal fun ClientProfileScreen(
5657
identifiers: (Int) -> Unit,
5758
onNavigateBack: () -> Unit,
5859
navigateToClientDetailsScreen: (Int) -> Unit,
60+
navigateToGroupDetails: (Int) -> Unit,
5961
viewAddress: (Int) -> Unit,
6062
modifier: Modifier = Modifier,
6163
viewModel: ClientProfileViewModel = koinViewModel(),
@@ -101,6 +103,10 @@ internal fun ClientProfileScreen(
101103
ClientProfileEvent.NavigateToClientDetailsScreen -> {
102104
navigateToClientDetailsScreen(state.client?.id ?: -1)
103105
}
106+
107+
is ClientProfileEvent.NavigateToGroupDetails -> {
108+
navigateToGroupDetails(event.groupId)
109+
}
104110
}
105111
}
106112

@@ -159,6 +165,12 @@ private fun ClientProfileScaffold(
159165
accountNo = state.client?.accountNo
160166
?: stringResource(Res.string.string_not_available),
161167
office = state.client?.officeName ?: stringResource(Res.string.office_na),
168+
groupName = state.client?.groupName ?: stringResource(Res.string.group_na),
169+
onGroupClick = {
170+
state.client?.groupId?.let { groupId ->
171+
onAction(ClientProfileAction.OnGroupClick(groupId))
172+
}
173+
},
162174
onClick = {
163175
onAction(
164176
ClientProfileAction.NavigateToClientDetailsScreen,

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/ClientProfileViewModel.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ internal class ClientProfileViewModel(
141141
ClientProfileAction.NavigateToClientDetailsScreen -> sendEvent(
142142
ClientProfileEvent.NavigateToClientDetailsScreen,
143143
)
144+
145+
is ClientProfileAction.OnGroupClick -> sendEvent(
146+
ClientProfileEvent.NavigateToGroupDetails(action.groupId),
147+
)
144148
}
145149
}
146150
}
@@ -176,6 +180,8 @@ sealed interface ClientProfileEvent {
176180
data class OnActionClick(val action: ClientProfileActionItem) : ClientProfileEvent
177181

178182
data object NavigateToClientDetailsScreen : ClientProfileEvent
183+
184+
data class NavigateToGroupDetails(val groupId: Int) : ClientProfileEvent
179185
}
180186

181187
/**
@@ -192,4 +198,6 @@ sealed interface ClientProfileAction {
192198
data object OnRetry : ClientProfileAction
193199

194200
data object NavigateToClientDetailsScreen : ClientProfileAction
201+
202+
data class OnGroupClick(val groupId: Int) : ClientProfileAction
195203
}

feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientProfile/components/ProfileCard.kt

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99
*/
1010
package com.mifos.feature.client.clientProfile.components
1111

12+
import androidclient.feature.client.generated.resources.Res
13+
import androidclient.feature.client.generated.resources.group_label
14+
import androidclient.feature.client.generated.resources.group_na
15+
import androidx.compose.foundation.background
1216
import androidx.compose.foundation.clickable
1317
import androidx.compose.foundation.layout.Arrangement
18+
import androidx.compose.foundation.layout.Box
1419
import androidx.compose.foundation.layout.Column
1520
import androidx.compose.foundation.layout.Row
1621
import androidx.compose.foundation.layout.Spacer
1722
import androidx.compose.foundation.layout.fillMaxWidth
23+
import androidx.compose.foundation.layout.height
1824
import androidx.compose.foundation.layout.padding
1925
import androidx.compose.foundation.layout.size
2026
import androidx.compose.foundation.layout.width
@@ -25,13 +31,16 @@ import androidx.compose.material3.Text
2531
import androidx.compose.runtime.Composable
2632
import androidx.compose.ui.Alignment
2733
import androidx.compose.ui.Modifier
34+
import androidx.compose.ui.draw.clip
35+
import androidx.compose.ui.text.font.FontWeight
2836
import com.mifos.core.designsystem.component.MifosCard
2937
import com.mifos.core.designsystem.icon.MifosIcons
3038
import com.mifos.core.designsystem.theme.AppColors
3139
import com.mifos.core.designsystem.theme.DesignToken
3240
import com.mifos.core.designsystem.theme.MifosTheme
3341
import com.mifos.core.designsystem.theme.MifosTypography
3442
import com.mifos.core.ui.components.MifosUserImage
43+
import org.jetbrains.compose.resources.stringResource
3544
import org.jetbrains.compose.ui.tooling.preview.Preview
3645

3746
@Composable
@@ -40,12 +49,12 @@ fun ProfileCard(
4049
name: String,
4150
accountNo: String,
4251
office: String,
52+
groupName: String? = null,
53+
onGroupClick: () -> Unit = {},
4354
onClick: () -> Unit,
4455
) {
4556
MifosCard(
46-
modifier = Modifier.clickable {
47-
onClick()
48-
},
57+
modifier = Modifier.clickable { onClick() },
4958
colors = CardColors(
5059
containerColor = MaterialTheme.colorScheme.primary,
5160
contentColor = AppColors.customWhite,
@@ -54,7 +63,8 @@ fun ProfileCard(
5463
),
5564
) {
5665
Row(
57-
Modifier.fillMaxWidth()
66+
modifier = Modifier
67+
.fillMaxWidth()
5868
.padding(DesignToken.padding.largeIncreasedExtra),
5969
verticalAlignment = Alignment.CenterVertically,
6070
) {
@@ -64,7 +74,7 @@ fun ProfileCard(
6474
)
6575
Spacer(Modifier.width(DesignToken.padding.medium))
6676
Column(
67-
Modifier.weight(1f),
77+
modifier = Modifier.weight(1f),
6878
verticalArrangement = Arrangement.spacedBy(DesignToken.padding.extraExtraSmall),
6979
) {
7080
Text(
@@ -75,19 +85,64 @@ fun ProfileCard(
7585
Text(
7686
text = "Acc. No. $accountNo",
7787
style = MifosTypography.bodySmall,
78-
color = MaterialTheme.colorScheme.secondaryContainer,
88+
color = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.8f),
7989
)
8090
Text(
8191
text = office,
8292
style = MifosTypography.bodySmall,
83-
color = MaterialTheme.colorScheme.secondaryContainer,
93+
color = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.8f),
94+
)
95+
96+
Spacer(Modifier.height(DesignToken.padding.small))
97+
98+
val displayGroupName = groupName ?: stringResource(Res.string.group_na)
99+
val isClickable = !groupName.isNullOrBlank() && groupName != stringResource(Res.string.group_na)
100+
val groupLabel = stringResource(Res.string.group_label)
101+
102+
GroupChip(
103+
text = "$groupLabel $displayGroupName",
104+
isClickable = isClickable,
105+
onClick = onGroupClick,
84106
)
85107
}
86108
Spacer(Modifier.width(DesignToken.padding.medium))
87109
Icon(
88110
imageVector = MifosIcons.ChevronRight,
89111
contentDescription = null,
90112
modifier = Modifier.size(DesignToken.sizes.iconSmall),
113+
tint = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.6f),
114+
)
115+
}
116+
}
117+
}
118+
119+
@Composable
120+
private fun GroupChip(
121+
text: String,
122+
isClickable: Boolean,
123+
onClick: () -> Unit,
124+
) {
125+
Box(
126+
modifier = Modifier
127+
.clip(DesignToken.shapes.small)
128+
.background(
129+
color = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.15f),
130+
)
131+
.clickable(enabled = isClickable, onClick = onClick)
132+
.padding(horizontal = DesignToken.padding.small, vertical = DesignToken.padding.extraSmall),
133+
) {
134+
Row(verticalAlignment = Alignment.CenterVertically) {
135+
Icon(
136+
imageVector = MifosIcons.Group,
137+
contentDescription = null,
138+
modifier = Modifier.size(DesignToken.sizes.iconSmall),
139+
tint = MaterialTheme.colorScheme.onPrimary,
140+
)
141+
Spacer(modifier = Modifier.width(DesignToken.padding.extraSmall))
142+
Text(
143+
text = text,
144+
style = MifosTypography.bodySmall.copy(fontWeight = FontWeight.Medium),
145+
color = MaterialTheme.colorScheme.onPrimary,
91146
)
92147
}
93148
}
@@ -102,6 +157,7 @@ fun ProfileCardPreview() {
102157
name = "John",
103158
accountNo = "2344",
104159
office = "Head Office",
160+
groupName = "Finance",
105161
onClick = {},
106162
)
107163
}

0 commit comments

Comments
 (0)