Friends Screen + fix string resources format
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
e29c5d7152
commit
9d7061fa62
@ -1,9 +0,0 @@
|
||||
package fr.iut.alldev.allin.ui.profile
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun Profile(){
|
||||
Text(text = "PROFILE")
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package fr.iut.alldev.allin.ui.profile
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import fr.iut.alldev.allin.ui.profile.components.ProfileScreenHeader
|
||||
|
||||
@Composable
|
||||
fun ProfileScreen(
|
||||
viewModel: ProfileViewModel = hiltViewModel()
|
||||
) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
Column {
|
||||
when (val s = state) {
|
||||
is ProfileViewModel.State.Loaded -> {
|
||||
ProfileScreenHeader(
|
||||
username = s.user.username,
|
||||
totalBets = 333,
|
||||
bestWin = 365,
|
||||
friends = 3
|
||||
)
|
||||
}
|
||||
|
||||
ProfileViewModel.State.Loading -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package fr.iut.alldev.allin.ui.profile
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import fr.iut.alldev.allin.data.model.User
|
||||
import fr.iut.alldev.allin.data.repository.UserRepository
|
||||
import fr.iut.alldev.allin.ui.navigation.Arguments
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ProfileViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val userRepository: UserRepository
|
||||
) : ViewModel() {
|
||||
private val userId: String? = savedStateHandle[Arguments.USER_ID]
|
||||
|
||||
private val _state by lazy { MutableStateFlow<State>(State.Loading) }
|
||||
val state: StateFlow<State> get() = _state.asStateFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
|
||||
userRepository.currentUserState.value?.let { currentUser ->
|
||||
if (userId == currentUser.id) {
|
||||
_state.emit(State.Loaded(currentUser))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface State {
|
||||
data object Loading : State
|
||||
data class Loaded(val user: User) : State
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package fr.iut.alldev.allin.ui.profile.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import fr.iut.alldev.allin.R
|
||||
import fr.iut.alldev.allin.ext.asFallbackProfileUsername
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||
|
||||
@Composable
|
||||
fun ProfileScreenHeader(
|
||||
username: String,
|
||||
totalBets: Int,
|
||||
bestWin: Int,
|
||||
friends: Int
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
ProfilePicture(
|
||||
fallback = username.asFallbackProfileUsername(),
|
||||
size = 68.dp
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.SpaceEvenly,
|
||||
modifier = Modifier.height(68.dp)
|
||||
) {
|
||||
Text(
|
||||
text = username,
|
||||
style = AllInTheme.typography.h2,
|
||||
color = AllInTheme.colors.onMainSurface,
|
||||
fontSize = 20.sp
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(20.dp)
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(
|
||||
text = totalBets.toString(),
|
||||
style = AllInTheme.typography.h1,
|
||||
color = AllInTheme.colors.onMainSurface,
|
||||
fontSize = 14.sp,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.drawer_bets),
|
||||
style = AllInTheme.typography.p1,
|
||||
color = AllInTheme.colors.onBackground2
|
||||
)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(
|
||||
text = bestWin.toString(),
|
||||
style = AllInTheme.typography.h1,
|
||||
color = AllInTheme.colors.onMainSurface,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.drawer_best_win),
|
||||
style = AllInTheme.typography.p1,
|
||||
color = AllInTheme.colors.onBackground2
|
||||
)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(
|
||||
text = friends.toString(),
|
||||
style = AllInTheme.typography.h1,
|
||||
color = AllInTheme.colors.onMainSurface,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.drawer_friends),
|
||||
style = AllInTheme.typography.p1,
|
||||
color = AllInTheme.colors.onBackground2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun ProfileScreenHeaderPreview() {
|
||||
AllInTheme {
|
||||
ProfileScreenHeader(
|
||||
username = "User 1",
|
||||
totalBets = 12,
|
||||
bestWin = 365,
|
||||
friends = 5
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package fr.iut.alldev.allin.data.api.model
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Keep
|
||||
@Serializable
|
||||
data class RequestFriend(val username: String)
|
@ -0,0 +1,9 @@
|
||||
package fr.iut.alldev.allin.data.repository
|
||||
|
||||
import fr.iut.alldev.allin.data.model.User
|
||||
|
||||
abstract class FriendRepository {
|
||||
abstract suspend fun getFriends(token: String): List<User>
|
||||
abstract suspend fun add(token: String, username: String)
|
||||
abstract suspend fun remove(token: String, username: String)
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package fr.iut.alldev.allin.data.repository.impl
|
||||
|
||||
import fr.iut.alldev.allin.data.api.AllInApi
|
||||
import fr.iut.alldev.allin.data.api.AllInApi.Companion.formatBearerToken
|
||||
import fr.iut.alldev.allin.data.api.model.RequestFriend
|
||||
import fr.iut.alldev.allin.data.model.User
|
||||
import fr.iut.alldev.allin.data.repository.FriendRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class FriendRepositoryImpl @Inject constructor(
|
||||
private val api: AllInApi
|
||||
) : FriendRepository() {
|
||||
override suspend fun getFriends(token: String): List<User> {
|
||||
return api.getFriends(token.formatBearerToken()).map { it.toUser() }
|
||||
}
|
||||
|
||||
override suspend fun add(token: String, username: String) {
|
||||
return api.addFriend(
|
||||
token = token.formatBearerToken(),
|
||||
request = RequestFriend(username)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun remove(token: String, username: String) {
|
||||
return api.deleteFriend(
|
||||
token = token.formatBearerToken(),
|
||||
request = RequestFriend(username)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in new issue