Fix events
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
58d788f58f
commit
53b6eacfff
@ -0,0 +1,30 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.betHistory
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import fr.iut.alldev.allin.R
|
||||||
|
import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear
|
||||||
|
import fr.iut.alldev.allin.data.ext.formatToTime
|
||||||
|
import fr.iut.alldev.allin.ui.betHistory.components.GenericHistory
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BetCurrentScreen(
|
||||||
|
viewModel: BetCurrentViewModel = hiltViewModel()
|
||||||
|
) {
|
||||||
|
val bets by viewModel.bets.collectAsState()
|
||||||
|
GenericHistory(
|
||||||
|
title = stringResource(id = R.string.bet_history_current_title),
|
||||||
|
bets = bets,
|
||||||
|
getTitle = { it.bet.phrase },
|
||||||
|
getCreator = { it.bet.creator },
|
||||||
|
getCategory = { it.bet.theme },
|
||||||
|
getEndRegisterDate = { it.bet.endRegisterDate.formatToMediumDateNoYear() },
|
||||||
|
getEndBetTime = { it.bet.endBetDate.formatToTime() },
|
||||||
|
getStatus = { it.bet.betStatus },
|
||||||
|
getNbCoins = { it.userParticipation?.stake ?: 0 },
|
||||||
|
getWon = { true }
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.betHistory
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||||
|
import fr.iut.alldev.allin.data.repository.BetRepository
|
||||||
|
import fr.iut.alldev.allin.keystore.AllInKeystoreManager
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class BetCurrentViewModel @Inject constructor(
|
||||||
|
private val betRepository: BetRepository,
|
||||||
|
private val keystoreManager: AllInKeystoreManager
|
||||||
|
) : ViewModel() {
|
||||||
|
private val _bets: MutableStateFlow<List<BetDetail>> by lazy {
|
||||||
|
MutableStateFlow(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
val bets: StateFlow<List<BetDetail>> by lazy {
|
||||||
|
_bets.asStateFlow()
|
||||||
|
.filterNotNull()
|
||||||
|
.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(5_000L),
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_bets.emit(
|
||||||
|
betRepository.getToConfirm(keystoreManager.getTokenOrEmpty())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,65 +1,30 @@
|
|||||||
package fr.iut.alldev.allin.ui.betHistory
|
package fr.iut.alldev.allin.ui.betHistory
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import fr.iut.alldev.allin.R
|
import fr.iut.alldev.allin.R
|
||||||
import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear
|
import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear
|
||||||
import fr.iut.alldev.allin.data.ext.formatToTime
|
import fr.iut.alldev.allin.data.ext.formatToTime
|
||||||
import fr.iut.alldev.allin.theme.AllInTheme
|
import fr.iut.alldev.allin.ui.betHistory.components.GenericHistory
|
||||||
import fr.iut.alldev.allin.ui.betHistory.components.BetHistoryScreenCard
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BetHistoryScreen(
|
fun BetHistoryScreen(
|
||||||
isCurrent: Boolean,
|
viewModel: BetHistoryViewModel = hiltViewModel()
|
||||||
viewModel: BetHistoryViewModel = hiltViewModel(),
|
|
||||||
) {
|
) {
|
||||||
val bets by viewModel.bets.collectAsState()
|
val bets by viewModel.bets.collectAsState()
|
||||||
|
GenericHistory(
|
||||||
LazyColumn(
|
title = stringResource(id = R.string.bet_history_title),
|
||||||
modifier = Modifier.fillMaxSize(),
|
bets = bets,
|
||||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 18.dp),
|
getTitle = { it.bet.phrase },
|
||||||
verticalArrangement = Arrangement.spacedBy(18.dp),
|
getCreator = { it.bet.creator },
|
||||||
) {
|
getCategory = { it.bet.theme },
|
||||||
item {
|
getEndRegisterDate = { it.bet.endRegisterDate.formatToMediumDateNoYear() },
|
||||||
Text(
|
getEndBetTime = { it.bet.endBetDate.formatToTime() },
|
||||||
text = stringResource(
|
getStatus = { it.bet.betStatus },
|
||||||
id = if (isCurrent) R.string.bet_history_current_title
|
getNbCoins = { it.amount },
|
||||||
else R.string.bet_history_title
|
getWon = { it.won }
|
||||||
),
|
|
||||||
style = AllInTheme.typography.h1,
|
|
||||||
color = AllInTheme.colors.allInGrey,
|
|
||||||
fontSize = 24.sp,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
bets?.let { bets ->
|
|
||||||
items(bets) {
|
|
||||||
BetHistoryScreenCard(
|
|
||||||
title = it.phrase,
|
|
||||||
creator = it.creator,
|
|
||||||
category = it.theme,
|
|
||||||
date = it.endRegisterDate.formatToMediumDateNoYear(),
|
|
||||||
time = it.endRegisterDate.formatToTime(),
|
|
||||||
status = it.betStatus,
|
|
||||||
nbCoins = 230
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,35 +1,44 @@
|
|||||||
package fr.iut.alldev.allin.ui.betHistory
|
package fr.iut.alldev.allin.ui.betHistory
|
||||||
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
import fr.iut.alldev.allin.data.model.bet.BetResultDetail
|
||||||
import fr.iut.alldev.allin.data.repository.BetRepository
|
import fr.iut.alldev.allin.data.repository.BetRepository
|
||||||
import fr.iut.alldev.allin.ui.navigation.NavArguments
|
import fr.iut.alldev.allin.keystore.AllInKeystoreManager
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.flatMapConcat
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class BetHistoryViewModel @Inject constructor(
|
class BetHistoryViewModel @Inject constructor(
|
||||||
savedStateHandle: SavedStateHandle,
|
|
||||||
private val betRepository: BetRepository,
|
private val betRepository: BetRepository,
|
||||||
|
private val keystoreManager: AllInKeystoreManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val isCurrent: Boolean? = savedStateHandle[NavArguments.ARG_BET_HISTORY_IS_CURRENT]
|
private val _bets: MutableStateFlow<List<BetResultDetail>> by lazy {
|
||||||
|
MutableStateFlow(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
val bets: StateFlow<List<Bet>?> by lazy {
|
val bets: StateFlow<List<BetResultDetail>> by lazy {
|
||||||
flowOf(isCurrent).filterNotNull().flatMapConcat {
|
_bets.asStateFlow()
|
||||||
if (it) betRepository.getCurrentBets()
|
.filterNotNull()
|
||||||
else betRepository.getHistory()
|
.stateIn(
|
||||||
}.stateIn(
|
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
SharingStarted.WhileSubscribed(5_000L),
|
SharingStarted.WhileSubscribed(5_000L),
|
||||||
null
|
emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_bets.emit(
|
||||||
|
betRepository.getHistory(keystoreManager.getTokenOrEmpty())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.betHistory.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||||
|
import fr.iut.alldev.allin.theme.AllInTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> GenericHistory(
|
||||||
|
title: String,
|
||||||
|
bets: List<T>,
|
||||||
|
getTitle: (T) -> String,
|
||||||
|
getCreator: (T) -> String,
|
||||||
|
getCategory: (T) -> String,
|
||||||
|
getEndRegisterDate: (T) -> String,
|
||||||
|
getEndBetTime: (T) -> String,
|
||||||
|
getStatus: (T) -> BetStatus,
|
||||||
|
getNbCoins: (T) -> Int,
|
||||||
|
getWon: (T) -> Boolean,
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 18.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(18.dp),
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = AllInTheme.typography.h1,
|
||||||
|
color = AllInTheme.colors.allInGrey,
|
||||||
|
fontSize = 24.sp,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
items(bets) {
|
||||||
|
BetHistoryScreenCard(
|
||||||
|
title = getTitle(it),
|
||||||
|
creator = getCreator(it),
|
||||||
|
category = getCategory(it),
|
||||||
|
date = getEndRegisterDate(it),
|
||||||
|
time = getEndBetTime(it),
|
||||||
|
status = getStatus(it),
|
||||||
|
nbCoins = getNbCoins(it),
|
||||||
|
won = getWon(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.main.event
|
||||||
|
|
||||||
|
import androidx.compose.material3.SheetState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
sealed class AllInEvent {
|
||||||
|
@Composable
|
||||||
|
abstract fun Display(
|
||||||
|
sheetState: SheetState,
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.main.event
|
||||||
|
|
||||||
|
import androidx.compose.material3.SheetState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||||
|
import fr.iut.alldev.allin.ui.betConfirmation.BetConfirmationBottomSheet
|
||||||
|
|
||||||
|
data class ToConfirmBet(
|
||||||
|
private val betDetail: BetDetail,
|
||||||
|
private val onConfirm: (String) -> Unit
|
||||||
|
) : AllInEvent() {
|
||||||
|
@Composable
|
||||||
|
override fun Display(
|
||||||
|
sheetState: SheetState,
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
BetConfirmationBottomSheet(
|
||||||
|
state = sheetState,
|
||||||
|
sheetVisibility = true,
|
||||||
|
betDetail = betDetail,
|
||||||
|
onDismiss = onDismiss,
|
||||||
|
onConfirm = onConfirm
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return betDetail.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ToConfirmBet
|
||||||
|
|
||||||
|
return betDetail == other.betDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package fr.iut.alldev.allin.ui.main.event
|
||||||
|
|
||||||
|
import androidx.compose.material3.SheetState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import fr.iut.alldev.allin.data.model.User
|
||||||
|
import fr.iut.alldev.allin.data.model.bet.BetResultDetail
|
||||||
|
import fr.iut.alldev.allin.ui.betResult.BetResultBottomSheet
|
||||||
|
|
||||||
|
data class WonBet(
|
||||||
|
private val user: User,
|
||||||
|
private val betResult: BetResultDetail,
|
||||||
|
) : AllInEvent() {
|
||||||
|
@Composable
|
||||||
|
override fun Display(
|
||||||
|
sheetState: SheetState,
|
||||||
|
onDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
BetResultBottomSheet(
|
||||||
|
state = sheetState,
|
||||||
|
sheetVisibility = true,
|
||||||
|
onDismiss = onDismiss,
|
||||||
|
bet = betResult.bet,
|
||||||
|
username = user.username,
|
||||||
|
coinAmount = betResult.amount,
|
||||||
|
stake = betResult.participation.stake,
|
||||||
|
winnings = betResult.amount,
|
||||||
|
odds = 1f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package fr.iut.alldev.allin.data.model.bet
|
||||||
|
|
||||||
|
data class BetResult(
|
||||||
|
val betId: String,
|
||||||
|
val result: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BetResultDetail(
|
||||||
|
val betResult: BetResult,
|
||||||
|
val bet: Bet,
|
||||||
|
val participation: Participation,
|
||||||
|
val amount: Int,
|
||||||
|
val won: Boolean
|
||||||
|
)
|
@ -1,19 +1,9 @@
|
|||||||
package fr.iut.alldev.allin.data.model.bet
|
package fr.iut.alldev.allin.data.model.bet
|
||||||
|
|
||||||
sealed class BetStatus {
|
enum class BetStatus {
|
||||||
data class Finished(val status: BetFinishedStatus) : BetStatus()
|
IN_PROGRESS,
|
||||||
|
WAITING,
|
||||||
data object InProgress : BetStatus()
|
CLOSING,
|
||||||
|
FINISHED,
|
||||||
data object Waiting : BetStatus()
|
CANCELLED
|
||||||
|
|
||||||
companion object {
|
|
||||||
val entries = sequenceOf(
|
|
||||||
InProgress,
|
|
||||||
Waiting,
|
|
||||||
Finished(BetFinishedStatus.WON),
|
|
||||||
Finished(BetFinishedStatus.LOST)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package fr.iut.alldev.allin.data.model.bet
|
package fr.iut.alldev.allin.data.model.bet
|
||||||
|
|
||||||
enum class BetType {
|
enum class BetType {
|
||||||
YES_NO,
|
BINARY,
|
||||||
MATCH,
|
MATCH,
|
||||||
CUSTOM
|
CUSTOM
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package fr.iut.alldev.allin.data.model.bet.vo
|
package fr.iut.alldev.allin.data.model.bet.vo
|
||||||
|
|
||||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
|
||||||
import fr.iut.alldev.allin.data.model.bet.Participation
|
|
||||||
|
|
||||||
data class BetResult(
|
data class BetResult(
|
||||||
val bet: Bet,
|
val betId: String,
|
||||||
val participations: List<Participation>,
|
val result: String
|
||||||
val answerDetail: BetAnswerDetail
|
|
||||||
)
|
)
|
@ -1,15 +1,18 @@
|
|||||||
package fr.iut.alldev.allin.data.repository
|
package fr.iut.alldev.allin.data.repository
|
||||||
|
|
||||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||||
|
import fr.iut.alldev.allin.data.model.bet.BetResultDetail
|
||||||
import fr.iut.alldev.allin.data.model.bet.Participation
|
import fr.iut.alldev.allin.data.model.bet.Participation
|
||||||
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
abstract class BetRepository {
|
abstract class BetRepository {
|
||||||
abstract suspend fun createBet(bet: Bet, token: String)
|
abstract suspend fun createBet(bet: Bet, token: String)
|
||||||
abstract suspend fun getHistory(): Flow<List<Bet>>
|
abstract suspend fun getHistory(token: String): List<BetResultDetail>
|
||||||
abstract suspend fun getCurrentBets(): Flow<List<Bet>>
|
abstract suspend fun getCurrentBets(token: String): List<BetDetail>
|
||||||
abstract suspend fun getBet(id: String, token: String): BetDetail
|
abstract suspend fun getBet(id: String, token: String): BetDetail
|
||||||
abstract suspend fun participateToBet(participation: Participation, token: String)
|
abstract suspend fun participateToBet(participation: Participation, token: String)
|
||||||
abstract suspend fun getAllBets(): List<Bet>
|
abstract suspend fun getAllBets(token: String): List<Bet>
|
||||||
|
abstract suspend fun confirmBet(token: String, id: String, response: String)
|
||||||
|
abstract suspend fun getToConfirm(token: String): List<BetDetail>
|
||||||
|
abstract suspend fun getWon(token: String): List<BetResultDetail>
|
||||||
}
|
}
|
Loading…
Reference in new issue