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