View and manage user profiles with betting statistics and privacy settings.
CentralHubProfileProvider handles user profile data including betting statistics, shared bets, and privacy settings.
User Data
Username, avatar, bio, and verification status.
Statistics
Followers count, following count, inspirations (bet shares copied), and reach (profile views).
Shared Bets
List of user's shared bets with full bet details and interaction counts.
Privacy Settings
Control profile visibility (public/private) and follow requirements.
class ProfileViewModel : ViewModel(), KoinComponent {
private val profileProvider:
CentralHubProfileProvider = get()
val profileState = profileProvider.profileState
fun loadProfile(userId: String) {
profileProvider.getUserData(userId)
}
fun getAvatarUrl(userId: String): String {
return profileProvider.getUserAvatarUrl(userId)
}
fun setPrivate() {
profileProvider.setProfileToPrivate(
onSuccess = { /* Profile now private */ },
onFailure = { error -> /* Handle error */ }
)
}
fun setPublic() {
profileProvider.setProfileToPublic(
onSuccess = { /* Profile now public */ },
onFailure = { error -> /* Handle error */ }
)
}
override fun onCleared() {
super.onCleared()
profileProvider.destroy()
}
}Compose UI:
@Composable
fun ProfileScreen(
userId: String,
viewModel: ProfileViewModel = viewModel()
) {
val state by viewModel.profileState
.collectAsStateWithLifecycle()
LaunchedEffect(userId) {
viewModel.loadProfile(userId)
}
Column {
// Avatar
AsyncImage(
model = viewModel.getAvatarUrl(state.user.id),
contentDescription = "User avatar"
)
// User info
Text(state.user.username)
// Statistics
Row {
Text("Followers: ${state.followersCount}")
Text("Following: ${state.followingCount}")
Text("Inspirations: ${state.inspirations}")
Text("Reach: ${state.reach}")
}
// Privacy toggle (for own profile)
if (state.isMyProfile) {
Switch(
checked = !state.isPrivate,
onCheckedChange = { isPublic ->
if (isPublic) {
viewModel.setPublic()
} else {
viewModel.setPrivate()
}
}
)
}
// Shared bets
LazyColumn {
items(state.sharedBets) { betShare ->
BetShareCard(betShare)
}
}
}
}State for user profiles:
data class CentralHubProfileState(
val user: User,
val isMyProfile: Boolean,
val isPrivate: Boolean,
val isFollowed: Boolean,
val followersCount: Int,
val followingCount: Int,
val inspirations: Int,
val reach: Int,
val sharedBets: List<BetShare>,
val loadingStatus: LoadingStatus,
val followActionLoadingStatus: LoadingStatus,
)