Binary file not shown.
@ -1,2 +0,0 @@
|
||||
store=keys/keystore.jks
|
||||
password=placeYourBets
|
Binary file not shown.
@ -1,21 +1,28 @@
|
||||
package fr.iut.alldev.allin.vo.bet.visitor
|
||||
package fr.iut.alldev.allin.vo.bet.displayer
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import fr.iut.alldev.allin.data.model.bet.CustomBet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.test.TestTags
|
||||
import fr.iut.alldev.allin.vo.bet.BetDisplayer
|
||||
|
||||
class BetTestVisitor : DisplayBetVisitor {
|
||||
class BetTestDisplayer : BetDisplayer {
|
||||
@Composable
|
||||
override fun VisitYesNoBet(b: YesNoBet) {
|
||||
override fun DisplayYesNoBet(bet: YesNoBet) {
|
||||
Text("This is a YesNo Bet", Modifier.testTag(TestTags.YES_NO_BET.tag))
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun VisitMatchBet(b: MatchBet) {
|
||||
override fun DisplayMatchBet(bet: MatchBet) {
|
||||
Text("This is a Match Bet", Modifier.testTag(TestTags.MATCH_BET.tag))
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun DisplayCustomBet(bet: CustomBet) {
|
||||
Text("This is a Custom Bet", Modifier.testTag(TestTags.CUSTOM_BET.tag))
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package fr.iut.alldev.allin.ext
|
||||
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
import java.util.Locale
|
||||
|
||||
fun Float.formatToSimple(locale: Locale): String {
|
||||
return DecimalFormat("0.##", DecimalFormatSymbols.getInstance(locale)).format(this)
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package fr.iut.alldev.allin.ext
|
||||
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
import java.util.Locale
|
||||
|
||||
fun String.verifyIsFloat(locale: Locale): String? {
|
||||
val pattern = Regex("^\\d+(\\.|\\,)?\\d*\$")
|
||||
val decimalSeparator = DecimalFormatSymbols.getInstance(locale).decimalSeparator.toString()
|
||||
|
||||
return if (this.matches(pattern)) {
|
||||
this.replace(Regex("[.,]"), decimalSeparator).format()
|
||||
} else if (this.isEmpty()) {
|
||||
this
|
||||
} else null
|
||||
}
|
||||
|
||||
fun String.toFloatOrNull(locale: Locale): Float? {
|
||||
val format = DecimalFormat("0.##", DecimalFormatSymbols.getInstance(locale))
|
||||
return format.parse(this)?.toFloat()
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package fr.iut.alldev.allin.ui.betResult
|
||||
|
||||
import androidx.compose.foundation.MarqueeSpacing
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.basicMarquee
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.betResult.components.BetResultBottomSheetBetCard
|
||||
import fr.iut.alldev.allin.ui.betResult.components.BetResultBottomSheetContentCoinAmount
|
||||
import fr.iut.alldev.allin.ui.betResult.components.BetResultBottomSheetContentCongratulations
|
||||
import fr.iut.alldev.allin.ui.core.AllInBottomSheet
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheet(
|
||||
state: SheetState,
|
||||
sheetVisibility: Boolean,
|
||||
username: String,
|
||||
coinAmount: Int,
|
||||
bet: Bet,
|
||||
stake: Int,
|
||||
winnings: Int,
|
||||
odds: Float,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
AllInBottomSheet(
|
||||
sheetVisibility = sheetVisibility,
|
||||
onDismiss = onDismiss,
|
||||
state = state,
|
||||
dragHandle = null
|
||||
) {
|
||||
BetResultBottomSheetContent(
|
||||
username = username,
|
||||
coinAmount = coinAmount,
|
||||
bet = bet,
|
||||
stake = stake,
|
||||
winnings = winnings,
|
||||
odds = odds,
|
||||
onClose = onDismiss
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheetContent(
|
||||
username: String,
|
||||
coinAmount: Int,
|
||||
bet: Bet,
|
||||
stake: Int,
|
||||
winnings: Int,
|
||||
odds: Float,
|
||||
onClose: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(AllInTheme.colors.allInMainGradientReverse),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.allin_marquee),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.rotate(11f)
|
||||
.scale(1.2f)
|
||||
.offset(x = (-24).dp)
|
||||
.basicMarquee(spacing = MarqueeSpacing(0.dp)),
|
||||
tint = AllInTheme.colors.white.copy(alpha = .05f)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
IconButton(
|
||||
onClick = onClose,
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.align(Alignment.TopStart)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
tint = AllInTheme.colors.white,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.allin),
|
||||
contentDescription = null,
|
||||
tint = AllInTheme.colors.white,
|
||||
modifier = Modifier
|
||||
.size(40.dp)
|
||||
.align(Alignment.TopCenter)
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
verticalArrangement = Arrangement.spacedBy(48.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
BetResultBottomSheetContentCongratulations(username = username)
|
||||
BetResultBottomSheetContentCoinAmount(amount = coinAmount)
|
||||
BetResultBottomSheetBetCard(
|
||||
title = bet.phrase,
|
||||
creator = bet.creator,
|
||||
category = bet.theme,
|
||||
date = bet.endBetDate.formatToMediumDateNoYear(),
|
||||
time = bet.endBetDate.formatToTime(),
|
||||
status = bet.betStatus,
|
||||
stake = stake,
|
||||
winnings = winnings,
|
||||
odds = odds
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(widthDp = 800, heightDp = 1280)
|
||||
@Composable
|
||||
private fun BetResultBottomSheetContentPreview() {
|
||||
AllInTheme {
|
||||
BetResultBottomSheetContent(
|
||||
username = "Pseudo",
|
||||
coinAmount = 3976,
|
||||
bet = YesNoBet(
|
||||
id = "1",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.InProgress,
|
||||
creator = "creator",
|
||||
),
|
||||
stake = 4175,
|
||||
winnings = 2600,
|
||||
odds = 6.7f
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package fr.iut.alldev.allin.ui.betResult.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import fr.iut.alldev.allin.data.model.bet.BetFinishedStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.bet.BetCard
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheetBetCard(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
creator: String,
|
||||
category: String,
|
||||
date: String,
|
||||
time: String,
|
||||
status: BetStatus,
|
||||
stake: Int,
|
||||
winnings: Int,
|
||||
odds: Float
|
||||
) {
|
||||
BetCard(
|
||||
title = title,
|
||||
creator = creator,
|
||||
category = category,
|
||||
date = date,
|
||||
time = time,
|
||||
status = status,
|
||||
modifier = modifier
|
||||
) {
|
||||
BetResultBottomSheetBetCardStats(
|
||||
stake = stake,
|
||||
winnings = winnings,
|
||||
odds = odds
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun BetResultBottomSheetBetCardPreview() {
|
||||
AllInTheme {
|
||||
BetResultBottomSheetBetCard(
|
||||
creator = "Creator",
|
||||
category = "Category",
|
||||
title = "Title",
|
||||
date = "Date",
|
||||
time = "Time",
|
||||
status = BetStatus.Finished(BetFinishedStatus.WON),
|
||||
stake = 2446,
|
||||
winnings = 6930,
|
||||
odds = 2.3f
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package fr.iut.alldev.allin.ui.betResult.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
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 fr.iut.alldev.allin.R
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||
import fr.iut.alldev.allin.ui.core.IconPosition
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheetBetCardStats(
|
||||
stake: Int,
|
||||
winnings: Int,
|
||||
odds: Float
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.background(AllInTheme.themeColors.background2)
|
||||
.padding(horizontal = 19.dp, vertical = 11.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.bet_result_stake),
|
||||
style = AllInTheme.typography.sm2,
|
||||
color = AllInTheme.themeColors.onMainSurface
|
||||
)
|
||||
|
||||
AllInCoinCount(
|
||||
amount = stake,
|
||||
color = AllInTheme.colors.allInPurple,
|
||||
textStyle = AllInTheme.typography.sm1,
|
||||
position = IconPosition.TRAILING
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.bet_result_winnings),
|
||||
style = AllInTheme.typography.sm2,
|
||||
color = AllInTheme.colors.allInPurple
|
||||
)
|
||||
AllInCoinCount(
|
||||
amount = winnings,
|
||||
textStyle = AllInTheme.typography.sm1,
|
||||
brush = AllInTheme.colors.allInMainGradient,
|
||||
position = IconPosition.TRAILING
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.bet_result_odds),
|
||||
style = AllInTheme.typography.sm2,
|
||||
color = AllInTheme.themeColors.onBackground2
|
||||
)
|
||||
AllInCard(
|
||||
radius = 8.dp,
|
||||
backgroundBrush = AllInTheme.colors.allInMainGradient
|
||||
) {
|
||||
Box(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) {
|
||||
Text(
|
||||
text = "$odds",
|
||||
style = AllInTheme.typography.sm1,
|
||||
color = AllInTheme.colors.white
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun BetResultBottomSheetBetCardStatsPreview() {
|
||||
AllInTheme {
|
||||
BetResultBottomSheetBetCardStats(
|
||||
stake = 2446,
|
||||
winnings = 6930,
|
||||
odds = 2.3f
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package fr.iut.alldev.allin.ui.betResult.components
|
||||
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import fr.iut.alldev.allin.R
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheetContentCongratulations(
|
||||
modifier: Modifier = Modifier,
|
||||
username: String
|
||||
) {
|
||||
val infiniteTransition = rememberInfiniteTransition(label = "")
|
||||
|
||||
val rotation by infiniteTransition.animateFloat(
|
||||
initialValue = -11f,
|
||||
targetValue = -5f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(900),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
), label = ""
|
||||
)
|
||||
|
||||
val scale by infiniteTransition.animateFloat(
|
||||
initialValue = 1f,
|
||||
targetValue = .9f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(900),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
), label = ""
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.rotate(rotation)
|
||||
.scale(scale),
|
||||
verticalAlignment = Alignment.Top,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text= stringResource(id = R.string.bet_result_congratulations),
|
||||
style = AllInTheme.typography.h1,
|
||||
fontSize = 25.sp,
|
||||
fontStyle = FontStyle.Italic,
|
||||
color = AllInTheme.colors.white
|
||||
)
|
||||
Text(
|
||||
text = "${username.uppercase()} !",
|
||||
style = AllInTheme.typography.h1,
|
||||
fontSize = 30.sp,
|
||||
fontStyle = FontStyle.Italic,
|
||||
color = AllInTheme.colors.white
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package fr.iut.alldev.allin.ui.betResult.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
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.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||
import fr.iut.alldev.allin.ui.core.IconPosition
|
||||
|
||||
@Composable
|
||||
fun BetResultBottomSheetContentCoinAmount(
|
||||
modifier: Modifier = Modifier,
|
||||
amount: Int
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.bet_result_you_win),
|
||||
style = AllInTheme.typography.sm2,
|
||||
color = AllInTheme.colors.white,
|
||||
fontSize = 20.sp
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier
|
||||
.border(
|
||||
width = 2.dp,
|
||||
shape = RoundedCornerShape(100.dp),
|
||||
color = AllInTheme.colors.white
|
||||
)
|
||||
.padding(vertical = 22.dp, horizontal = 33.dp)
|
||||
|
||||
) {
|
||||
AllInCoinCount(
|
||||
amount = amount,
|
||||
textStyle = AllInTheme.typography.h1,
|
||||
position = IconPosition.TRAILING,
|
||||
color = AllInTheme.colors.white,
|
||||
size = 60,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.offset(y = (-6).dp)
|
||||
)
|
||||
AllInCoinCount(
|
||||
amount = amount,
|
||||
textStyle = AllInTheme.typography.h1,
|
||||
position = IconPosition.TRAILING,
|
||||
color = AllInTheme.colors.white.copy(alpha = .32f),
|
||||
size = 60,
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun BetResultBottomSheetContentCoinAmountPreview() {
|
||||
AllInTheme {
|
||||
BetResultBottomSheetContentCoinAmount(amount = 1572)
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package fr.iut.alldev.allin.ui.betStatus.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.CustomBet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.NO_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.YES_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||
import fr.iut.alldev.allin.ext.formatToSimple
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||
import fr.iut.alldev.allin.ui.preview.BetDetailPreviewProvider
|
||||
import java.util.Locale
|
||||
|
||||
private val participationAnswerFontSize = 25.sp
|
||||
|
||||
@Composable
|
||||
fun BetDetail.getParticipationAnswers(): List<@Composable RowScope.() -> Unit> {
|
||||
val configuration = LocalConfiguration.current
|
||||
val locale = remember { ConfigurationCompat.getLocales(configuration).get(0) ?: Locale.getDefault() }
|
||||
|
||||
return when (this.bet) {
|
||||
is CustomBet -> (this.bet as CustomBet).possibleAnswers.map {
|
||||
{
|
||||
this@getParticipationAnswers.getAnswerOfResponse(it)?.let {
|
||||
ParticipationAnswerLine(
|
||||
text = it.response,
|
||||
odds = it.odds,
|
||||
locale = locale
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MatchBet -> buildList {
|
||||
val bet = (this@getParticipationAnswers.bet as MatchBet)
|
||||
add {
|
||||
this@getParticipationAnswers.getAnswerOfResponse(bet.nameTeam1)?.let {
|
||||
ParticipationAnswerLine(
|
||||
text = it.response,
|
||||
odds = it.odds,
|
||||
locale = locale
|
||||
)
|
||||
}
|
||||
}
|
||||
add {
|
||||
this@getParticipationAnswers.getAnswerOfResponse(bet.nameTeam2)?.let {
|
||||
ParticipationAnswerLine(
|
||||
text = it.response,
|
||||
color = AllInTheme.colors.allInBarPink,
|
||||
odds = it.odds,
|
||||
locale = locale
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is YesNoBet -> buildList {
|
||||
add {
|
||||
this@getParticipationAnswers.getAnswerOfResponse(YES_VALUE)?.let {
|
||||
ParticipationAnswerLine(
|
||||
text = it.response,
|
||||
odds = it.odds,
|
||||
locale = locale
|
||||
)
|
||||
}
|
||||
}
|
||||
add {
|
||||
this@getParticipationAnswers.getAnswerOfResponse(NO_VALUE)?.let {
|
||||
ParticipationAnswerLine(
|
||||
text = it.response,
|
||||
color = AllInTheme.colors.allInBarPink,
|
||||
odds = it.odds,
|
||||
locale = locale
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ParticipationAnswerLine(
|
||||
text: String,
|
||||
color: Color = AllInTheme.colors.allInBlue,
|
||||
locale: Locale,
|
||||
odds: Float
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = text.uppercase(),
|
||||
color = color,
|
||||
style = AllInTheme.typography.h1,
|
||||
fontSize = participationAnswerFontSize
|
||||
)
|
||||
|
||||
AllInCard(
|
||||
radius = 50.dp,
|
||||
backgroundColor = AllInTheme.colors.allInPurple
|
||||
) {
|
||||
Box(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) {
|
||||
Text(
|
||||
text = "x${odds.formatToSimple(locale)}",
|
||||
color = AllInTheme.colors.white,
|
||||
style = AllInTheme.typography.h2
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Bet.getAnswerFromParticipationIdx(idx: Int) =
|
||||
when (this) {
|
||||
is CustomBet -> this.possibleAnswers.getOrElse(idx) { "" }
|
||||
is MatchBet -> when (idx) {
|
||||
0 -> this.nameTeam1
|
||||
1 -> this.nameTeam2
|
||||
else -> ""
|
||||
}
|
||||
|
||||
is YesNoBet -> when (idx) {
|
||||
0 -> YES_VALUE
|
||||
1 -> NO_VALUE
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun ParticipationAnswersPreview(
|
||||
@PreviewParameter(BetDetailPreviewProvider::class) bet: BetDetail,
|
||||
) {
|
||||
AllInTheme {
|
||||
Column {
|
||||
bet.getParticipationAnswers().forEach {
|
||||
Row(Modifier.fillMaxWidth()) { it() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
package fr.iut.alldev.allin.ui.betStatus.visitor
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.EmojiEvents
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.WorkspacePremium
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.*
|
||||
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 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.data.model.bet.BetFinishedStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.ext.getDateEndLabelId
|
||||
import fr.iut.alldev.allin.ext.getDateStartLabelId
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.BetStatusParticipationBottomSheet
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.BetStatusWinner
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.YesNoDetailsLine
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.YesNoStatBar
|
||||
import fr.iut.alldev.allin.ui.core.AllInDetailsDrawer
|
||||
import fr.iut.alldev.allin.ui.core.RainbowButton
|
||||
import fr.iut.alldev.allin.ui.core.bet.BetDateTimeRow
|
||||
import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader
|
||||
import fr.iut.alldev.allin.vo.bet.factory.toBetVO
|
||||
import fr.iut.alldev.allin.vo.bet.visitor.DisplayBetVisitor
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
class BetStatusBottomSheetDisplayBetVisitor(
|
||||
val userCoinAmount: MutableIntState,
|
||||
val onParticipate: (Int) -> Unit,
|
||||
) : DisplayBetVisitor {
|
||||
|
||||
val participateBottomSheetVisibility = mutableStateOf(false)
|
||||
val paddingValues = mutableStateOf(PaddingValues())
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
override fun VisitYesNoBet(b: YesNoBet) {
|
||||
|
||||
val (participateSheetVisibility, setParticipateSheetVisibility) = remember {
|
||||
this.participateBottomSheetVisibility
|
||||
}
|
||||
|
||||
val safeBottomPadding = paddingValues.value.calculateBottomPadding()
|
||||
|
||||
Box(
|
||||
Modifier
|
||||
.padding(bottom = safeBottomPadding)
|
||||
) {
|
||||
Column {
|
||||
Column(Modifier.padding(horizontal = 20.dp)) {
|
||||
BetTitleHeader(
|
||||
title = b.phrase,
|
||||
category = b.theme,
|
||||
creator = "Lucas" /*TODO : Creator*/,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End
|
||||
) {
|
||||
BetDateTimeRow(
|
||||
label = stringResource(id = b.betStatus.getDateStartLabelId()),
|
||||
date = b.endRegisterDate.formatToMediumDateNoYear(),
|
||||
time = b.endRegisterDate.formatToTime(),
|
||||
modifier = Modifier.width(IntrinsicSize.Max)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(15.dp))
|
||||
BetDateTimeRow(
|
||||
label = stringResource(id = b.betStatus.getDateEndLabelId()),
|
||||
date = b.endBetDate.formatToMediumDateNoYear(),
|
||||
time = b.endBetDate.formatToTime(),
|
||||
modifier = Modifier.width(IntrinsicSize.Max)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
if (b.betStatus is BetStatus.Finished) {
|
||||
BetStatusWinner(
|
||||
answer = stringResource(id = R.string.Yes),
|
||||
color = AllInTheme.colors.allInBlue,
|
||||
coinAmount = 442,
|
||||
username = "Imri",
|
||||
multiplier = 1.2f
|
||||
)
|
||||
} else {
|
||||
HorizontalDivider(color = AllInTheme.themeColors.border)
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxHeight()
|
||||
.background(AllInTheme.themeColors.background2)
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
YesNoStatBar(yesPercentage = .86f)
|
||||
AllInDetailsDrawer {
|
||||
YesNoDetailsLine(
|
||||
icon = AllInTheme.icons.allCoins(),
|
||||
yesText = "550",
|
||||
noText = "330",
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.People,
|
||||
yesText = "12",
|
||||
noText = "5"
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.WorkspacePremium,
|
||||
yesText = "45",
|
||||
noText = "45"
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.EmojiEvents,
|
||||
yesText = "x1.2",
|
||||
noText = "x1.45"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b.betStatus !is BetStatus.Finished) {
|
||||
RainbowButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(horizontal = 7.dp),
|
||||
text = stringResource(id = R.string.Participate),
|
||||
enabled = b.betStatus == BetStatus.Waiting,
|
||||
onClick = {
|
||||
setParticipateSheetVisibility(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BetStatusParticipationBottomSheet(
|
||||
sheetVisibility = participateSheetVisibility && b.betStatus == BetStatus.Waiting,
|
||||
safeBottomPadding = safeBottomPadding,
|
||||
betPhrase = b.phrase,
|
||||
coinAmount = userCoinAmount.intValue,
|
||||
onDismiss = { setParticipateSheetVisibility(false) },
|
||||
state = rememberModalBottomSheetState()
|
||||
) {
|
||||
onParticipate(100)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun VisitMatchBet(b: MatchBet) {
|
||||
Text("This is a MATCH BET")
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun YesNoBetPreview() {
|
||||
AllInTheme {
|
||||
val coins = remember { mutableIntStateOf(100) }
|
||||
YesNoBet(
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.InProgress,
|
||||
creator = "creator"
|
||||
).toBetVO()?.Accept(
|
||||
BetStatusBottomSheetDisplayBetVisitor(
|
||||
userCoinAmount = coins,
|
||||
onParticipate = {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun YesNoBetFinishedPreview() {
|
||||
AllInTheme {
|
||||
val coins = remember { mutableIntStateOf(100) }
|
||||
YesNoBet(
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.Finished(BetFinishedStatus.WON),
|
||||
creator = "creator"
|
||||
).toBetVO()?.Accept(
|
||||
BetStatusBottomSheetDisplayBetVisitor(
|
||||
userCoinAmount = coins,
|
||||
onParticipate = {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun MatchBetPreview() {
|
||||
AllInTheme {
|
||||
val coins = remember { mutableIntStateOf(100) }
|
||||
MatchBet(
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.InProgress,
|
||||
nameTeam1 = "Team 1",
|
||||
nameTeam2 = "Team 2",
|
||||
creator = "creator"
|
||||
).toBetVO()?.Accept(
|
||||
BetStatusBottomSheetDisplayBetVisitor(
|
||||
userCoinAmount = coins,
|
||||
onParticipate = {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
package fr.iut.alldev.allin.ui.betStatus.vo
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.EmojiEvents
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.WorkspacePremium
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
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.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.NO_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.YES_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||
import fr.iut.alldev.allin.ext.formatToSimple
|
||||
import fr.iut.alldev.allin.ext.getDateEndLabelId
|
||||
import fr.iut.alldev.allin.ext.getDateStartLabelId
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.BetStatusWinner
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.BinaryStatBar
|
||||
import fr.iut.alldev.allin.ui.betStatus.components.YesNoDetailsLine
|
||||
import fr.iut.alldev.allin.ui.core.AllInCoinCount
|
||||
import fr.iut.alldev.allin.ui.core.AllInDetailsDrawer
|
||||
import fr.iut.alldev.allin.ui.core.ProfilePicture
|
||||
import fr.iut.alldev.allin.ui.core.RainbowButton
|
||||
import fr.iut.alldev.allin.ui.core.bet.BetDateTimeRow
|
||||
import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader
|
||||
import fr.iut.alldev.allin.ui.preview.BetDetailPreviewProvider
|
||||
import fr.iut.alldev.allin.vo.bet.BetDisplayer
|
||||
import java.util.Locale
|
||||
|
||||
class BetStatusBottomSheetBetDisplayer(
|
||||
val openParticipateSheet: () -> Unit
|
||||
) : BetDisplayer {
|
||||
val paddingValues = mutableStateOf(PaddingValues())
|
||||
|
||||
@Composable
|
||||
private fun DisplayBinaryBet(
|
||||
betDetail: BetDetail,
|
||||
response1: String,
|
||||
response2: String,
|
||||
response1Display: String = response1,
|
||||
response2Display: String = response2
|
||||
) {
|
||||
val safeBottomPadding = paddingValues.value.calculateBottomPadding()
|
||||
val configuration = LocalConfiguration.current
|
||||
val locale = remember { ConfigurationCompat.getLocales(configuration).get(0) ?: Locale.getDefault() }
|
||||
|
||||
val response1Answer = remember { betDetail.getAnswerOfResponse(response1) }
|
||||
val response2Answer = remember { betDetail.getAnswerOfResponse(response2) }
|
||||
|
||||
Box(Modifier.padding(bottom = safeBottomPadding)) {
|
||||
Column {
|
||||
Column(Modifier.padding(horizontal = 20.dp)) {
|
||||
BetTitleHeader(
|
||||
title = betDetail.bet.phrase,
|
||||
category = betDetail.bet.theme,
|
||||
creator = betDetail.bet.creator,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End
|
||||
) {
|
||||
BetDateTimeRow(
|
||||
label = stringResource(id = betDetail.bet.betStatus.getDateStartLabelId()),
|
||||
date = betDetail.bet.endRegisterDate.formatToMediumDateNoYear(),
|
||||
time = betDetail.bet.endRegisterDate.formatToTime(),
|
||||
modifier = Modifier.width(IntrinsicSize.Max)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(15.dp))
|
||||
BetDateTimeRow(
|
||||
label = stringResource(id = betDetail.bet.betStatus.getDateEndLabelId()),
|
||||
date = betDetail.bet.endBetDate.formatToMediumDateNoYear(),
|
||||
time = betDetail.bet.endBetDate.formatToTime(),
|
||||
modifier = Modifier.width(IntrinsicSize.Max)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
if (betDetail.bet.betStatus is BetStatus.Finished) {
|
||||
BetStatusWinner(
|
||||
answer = response1Display,
|
||||
color = AllInTheme.colors.allInBlue,
|
||||
coinAmount = 442,
|
||||
username = "Imri",
|
||||
multiplier = 1.2f
|
||||
)
|
||||
} else {
|
||||
HorizontalDivider(color = AllInTheme.themeColors.border)
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxHeight()
|
||||
.background(AllInTheme.themeColors.background2)
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
BinaryStatBar(
|
||||
response1Percentage = remember {
|
||||
val total = (response1Answer?.totalParticipants ?: 0) + (response2Answer?.totalParticipants ?: 0)
|
||||
if (total == 0) .5f else (response1Answer?.totalParticipants ?: 0) / total.toFloat()
|
||||
},
|
||||
response1 = response1Display,
|
||||
response2 = response2Display
|
||||
)
|
||||
AllInDetailsDrawer {
|
||||
YesNoDetailsLine(
|
||||
icon = AllInTheme.icons.allCoins(),
|
||||
yesText = response1Answer?.totalStakes?.toString() ?: "0",
|
||||
noText = response2Answer?.totalStakes?.toString() ?: "0"
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.People,
|
||||
yesText = response1Answer?.totalParticipants?.toString() ?: "0",
|
||||
noText = response2Answer?.totalParticipants?.toString() ?: "0"
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.WorkspacePremium,
|
||||
yesText = response1Answer?.highestStake?.toString() ?: "0",
|
||||
noText = response2Answer?.highestStake?.toString() ?: "0"
|
||||
)
|
||||
YesNoDetailsLine(
|
||||
icon = Icons.Filled.EmojiEvents,
|
||||
yesText = "x${response1Answer?.odds?.formatToSimple(locale) ?: "1.00"}",
|
||||
noText = "x${response2Answer?.odds?.formatToSimple(locale) ?: "1.00"}"
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(id = R.string.bet_status_participants_list),
|
||||
fontSize = 20.sp,
|
||||
color = AllInTheme.themeColors.onMainSurface,
|
||||
style = AllInTheme.typography.h1,
|
||||
modifier = Modifier.padding(vertical = 36.dp)
|
||||
)
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
contentPadding = PaddingValues(horizontal = 13.dp, vertical = 8.dp),
|
||||
modifier = Modifier.fillMaxHeight()
|
||||
) {
|
||||
betDetail.userParticipation?.let {
|
||||
item {
|
||||
BetStatusParticipant(
|
||||
username = it.username,
|
||||
allCoinsAmount = it.stake
|
||||
)
|
||||
HorizontalDivider(
|
||||
color = AllInTheme.themeColors.border,
|
||||
modifier = Modifier.padding(vertical = 8.dp, horizontal = 25.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
items(betDetail.participations) {
|
||||
if (it.username != betDetail.userParticipation?.username) {
|
||||
BetStatusParticipant(
|
||||
username = it.username,
|
||||
allCoinsAmount = it.stake
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (betDetail.bet.betStatus !is BetStatus.Finished && betDetail.userParticipation == null) {
|
||||
RainbowButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(horizontal = 7.dp),
|
||||
text = stringResource(id = R.string.Participate),
|
||||
enabled = betDetail.bet.betStatus == BetStatus.Waiting,
|
||||
onClick = openParticipateSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
override fun DisplayYesNoBet(betDetail: BetDetail) {
|
||||
DisplayBinaryBet(
|
||||
betDetail = betDetail,
|
||||
response1 = YES_VALUE,
|
||||
response2 = NO_VALUE,
|
||||
response1Display = stringResource(id = R.string.Yes).uppercase(),
|
||||
response2Display = stringResource(id = R.string.No).uppercase()
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun DisplayMatchBet(betDetail: BetDetail) {
|
||||
val bet = remember { betDetail.bet as MatchBet }
|
||||
DisplayBinaryBet(
|
||||
betDetail = betDetail,
|
||||
response1 = bet.nameTeam1,
|
||||
response2 = bet.nameTeam2
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun DisplayCustomBet(betDetail: BetDetail) {
|
||||
Text("This is a CUSTOM BET")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BetStatusParticipant(
|
||||
username: String,
|
||||
allCoinsAmount: Int
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(7.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
ProfilePicture(modifier = Modifier.size(25.dp))
|
||||
Text(
|
||||
text = username,
|
||||
fontWeight = FontWeight.Bold,
|
||||
style = AllInTheme.typography.h2,
|
||||
color = AllInTheme.themeColors.onMainSurface,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
AllInCoinCount(
|
||||
amount = allCoinsAmount,
|
||||
color = AllInTheme.colors.allInPurple
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun BetStatusBottomSheetPreview(
|
||||
@PreviewParameter(BetDetailPreviewProvider::class) bet: BetDetail
|
||||
) {
|
||||
AllInTheme {
|
||||
BetStatusBottomSheetBetDisplayer {
|
||||
|
||||
}.DisplayBet(bet)
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package fr.iut.alldev.allin.ui.core
|
||||
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithCache
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.CompositingStrategy
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
|
||||
@Composable
|
||||
fun Icon(
|
||||
painter: Painter,
|
||||
contentDescription: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = LocalContentColor.current,
|
||||
brush: Brush? = null,
|
||||
) {
|
||||
Icon(
|
||||
painter = painter,
|
||||
contentDescription = contentDescription,
|
||||
modifier = brush?.let {
|
||||
modifier
|
||||
.graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen }
|
||||
.drawWithCache {
|
||||
onDrawWithContent {
|
||||
drawContent()
|
||||
drawRect(brush, blendMode = BlendMode.SrcAtop)
|
||||
}
|
||||
}
|
||||
} ?: modifier,
|
||||
tint = tint
|
||||
)
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package fr.iut.alldev.allin.ui.core.bet
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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 fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.ext.getDateStartLabelId
|
||||
import fr.iut.alldev.allin.theme.AllInTheme
|
||||
import fr.iut.alldev.allin.ui.core.AllInCard
|
||||
|
||||
@Composable
|
||||
fun BetCard(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
creator: String,
|
||||
category: String,
|
||||
date: String,
|
||||
time: String,
|
||||
status: BetStatus,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
AllInCard(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
radius = 16.dp
|
||||
) {
|
||||
Column(
|
||||
Modifier.padding(horizontal = 19.dp, vertical = 11.dp)
|
||||
) {
|
||||
BetTitleHeader(
|
||||
title = title,
|
||||
category = category,
|
||||
creator = creator,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(11.dp))
|
||||
BetDateTimeRow(
|
||||
label = stringResource(id = status.getDateStartLabelId()),
|
||||
date = date,
|
||||
time = time
|
||||
)
|
||||
}
|
||||
HorizontalDivider(
|
||||
thickness = 1.dp,
|
||||
color = AllInTheme.themeColors.border
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun BetCardPreview() {
|
||||
AllInTheme {
|
||||
BetCard(
|
||||
creator = "Creator",
|
||||
category = "Category",
|
||||
title = "Title",
|
||||
date = "Date",
|
||||
time = "Time",
|
||||
status = BetStatus.Waiting
|
||||
){
|
||||
Text("Content")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package fr.iut.alldev.allin.ui.preview
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import fr.iut.alldev.allin.data.model.bet.NO_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.Participation
|
||||
import fr.iut.alldev.allin.data.model.bet.YES_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail
|
||||
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||
|
||||
class BetDetailPreviewProvider : PreviewParameterProvider<BetDetail> {
|
||||
override val values = BetWithStatusPreviewProvider().values.map {
|
||||
BetDetail(
|
||||
bet = it,
|
||||
answers = listOf(
|
||||
BetAnswerDetail(
|
||||
response = YES_VALUE,
|
||||
totalStakes = 300,
|
||||
totalParticipants = 2,
|
||||
highestStake = 200,
|
||||
odds = 1.0f
|
||||
),
|
||||
BetAnswerDetail(
|
||||
response = NO_VALUE,
|
||||
totalStakes = 150,
|
||||
totalParticipants = 1,
|
||||
highestStake = 150,
|
||||
odds = 2.0f
|
||||
),
|
||||
),
|
||||
participations = listOf(
|
||||
Participation(
|
||||
betId = it.id,
|
||||
username = "User1",
|
||||
response = YES_VALUE,
|
||||
stake = 200
|
||||
),
|
||||
Participation(
|
||||
betId = it.id,
|
||||
username = "User2",
|
||||
response = YES_VALUE,
|
||||
stake = 100
|
||||
),
|
||||
Participation(
|
||||
betId = it.id,
|
||||
username = "MyUser",
|
||||
response = NO_VALUE,
|
||||
stake = 150
|
||||
)
|
||||
),
|
||||
userParticipation = Participation(
|
||||
betId = it.id,
|
||||
username = "MyUser",
|
||||
response = NO_VALUE,
|
||||
stake = 150
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package fr.iut.alldev.allin.ui.preview
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.BetFinishedStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.CustomBet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
class BetPreviewProvider : PreviewParameterProvider<Bet> {
|
||||
override val values = sequenceOf(
|
||||
YesNoBet(
|
||||
id = "1",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.Finished(BetFinishedStatus.WON),
|
||||
creator = "creator"
|
||||
),
|
||||
MatchBet(
|
||||
id = "2",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.Finished(BetFinishedStatus.WON),
|
||||
creator = "creator",
|
||||
nameTeam1 = "The Monarchs",
|
||||
nameTeam2 = "Climate Change"
|
||||
),
|
||||
CustomBet(
|
||||
id = "3",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = BetStatus.Finished(BetFinishedStatus.WON),
|
||||
creator = "creator",
|
||||
possibleAnswers = listOf(
|
||||
"Answer 1",
|
||||
"Answer 2",
|
||||
"Answer 3",
|
||||
"Answer 4"
|
||||
)
|
||||
|
||||
),
|
||||
)
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package fr.iut.alldev.allin.ui.preview
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import fr.iut.alldev.allin.data.model.bet.BetFinishedStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
|
||||
class BetStatusPreviewProvider: PreviewParameterProvider<BetStatus> {
|
||||
override val values = sequenceOf(
|
||||
BetStatus.InProgress,
|
||||
BetStatus.Waiting,
|
||||
BetStatus.Finished(BetFinishedStatus.WON),
|
||||
BetStatus.Finished(BetFinishedStatus.LOST)
|
||||
)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package fr.iut.alldev.allin.ui.preview
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
|
||||
class BetStatusPreviewProvider : PreviewParameterProvider<BetStatus> {
|
||||
override val values = BetStatus.entries
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package fr.iut.alldev.allin.ui.preview
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.BetStatus
|
||||
import fr.iut.alldev.allin.data.model.bet.CustomBet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
|
||||
class BetWithStatusPreviewProvider : PreviewParameterProvider<Bet> {
|
||||
override val values = BetStatus.entries.flatMap { status ->
|
||||
sequenceOf(
|
||||
YesNoBet(
|
||||
id = "1",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = status,
|
||||
creator = "creator"
|
||||
),
|
||||
MatchBet(
|
||||
id = "2",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = status,
|
||||
creator = "creator",
|
||||
nameTeam1 = "The Monarchs",
|
||||
nameTeam2 = "Climate Change"
|
||||
),
|
||||
CustomBet(
|
||||
id = "3",
|
||||
theme = "Theme",
|
||||
phrase = "Phrase",
|
||||
endRegisterDate = ZonedDateTime.now(),
|
||||
endBetDate = ZonedDateTime.now(),
|
||||
isPublic = true,
|
||||
betStatus = status,
|
||||
creator = "creator",
|
||||
possibleAnswers = listOf(
|
||||
"Answer 1",
|
||||
"Answer 2",
|
||||
"Answer 3",
|
||||
"Answer 4"
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package fr.iut.alldev.allin.utils
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
data class Quadruple<out A, out B, out C, out D>(
|
||||
val first: A,
|
||||
val second: B,
|
||||
val third: C,
|
||||
val fourth: D
|
||||
) : Serializable {
|
||||
override fun toString(): String = "($first, $second, $third, $fourth)"
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package fr.iut.alldev.allin.vo
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
interface ViewObject<V : Visitor>{
|
||||
@Composable
|
||||
fun Accept(v: V)
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
package fr.iut.alldev.allin.vo
|
||||
|
||||
interface Visitor
|
@ -0,0 +1,27 @@
|
||||
package fr.iut.alldev.allin.vo.bet
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import fr.iut.alldev.allin.data.model.bet.CustomBet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.data.model.bet.vo.BetDetail
|
||||
|
||||
interface BetDisplayer {
|
||||
@Composable
|
||||
fun DisplayBet(betDetail: BetDetail) {
|
||||
when (betDetail.bet) {
|
||||
is CustomBet -> DisplayCustomBet(betDetail)
|
||||
is MatchBet -> DisplayMatchBet(betDetail)
|
||||
is YesNoBet -> DisplayYesNoBet(betDetail)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayYesNoBet(betDetail: BetDetail)
|
||||
|
||||
@Composable
|
||||
fun DisplayMatchBet(betDetail: BetDetail)
|
||||
|
||||
@Composable
|
||||
fun DisplayCustomBet(betDetail: BetDetail)
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package fr.iut.alldev.allin.vo.bet
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.vo.ViewObject
|
||||
import fr.iut.alldev.allin.vo.bet.visitor.DisplayBetVisitor
|
||||
|
||||
abstract class BetVO<T: Bet>(val bet: T)
|
||||
: ViewObject<DisplayBetVisitor> {
|
||||
@Composable
|
||||
abstract override fun Accept(v: DisplayBetVisitor)
|
||||
}
|
||||
|
||||
class YesNoBetVO(bet: YesNoBet) : BetVO<YesNoBet>(bet){
|
||||
@Composable
|
||||
override fun Accept(v: DisplayBetVisitor){
|
||||
v.VisitYesNoBet(b = bet)
|
||||
}
|
||||
}
|
||||
|
||||
class MatchBetVO(bet: MatchBet) : BetVO<MatchBet>(bet){
|
||||
@Composable
|
||||
override fun Accept(v: DisplayBetVisitor){
|
||||
v.VisitMatchBet(b = bet)
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package fr.iut.alldev.allin.vo.bet.factory
|
||||
|
||||
import fr.iut.alldev.allin.data.model.bet.Bet
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.vo.bet.BetVO
|
||||
import fr.iut.alldev.allin.vo.bet.MatchBetVO
|
||||
import fr.iut.alldev.allin.vo.bet.YesNoBetVO
|
||||
|
||||
private val betTypeToVOMap = mapOf(
|
||||
YesNoBet::class.java to YesNoBetVOFactory(),
|
||||
MatchBet::class.java to MatchBetVOFactory()
|
||||
)
|
||||
abstract class BetVOFactory<out T : Bet> {
|
||||
abstract fun create(bet: @UnsafeVariance T): BetVO<@UnsafeVariance T>
|
||||
}
|
||||
|
||||
class YesNoBetVOFactory : BetVOFactory<YesNoBet>() {
|
||||
override fun create(bet: YesNoBet) =
|
||||
YesNoBetVO(bet)
|
||||
}
|
||||
|
||||
class MatchBetVOFactory : BetVOFactory<MatchBet>() {
|
||||
override fun create(bet: MatchBet) =
|
||||
MatchBetVO(bet)
|
||||
}
|
||||
|
||||
fun Bet.toBetVO() = betTypeToVOMap[this.javaClass]?.create(this)
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
package fr.iut.alldev.allin.vo.bet.visitor
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import fr.iut.alldev.allin.data.model.bet.MatchBet
|
||||
import fr.iut.alldev.allin.data.model.bet.YesNoBet
|
||||
import fr.iut.alldev.allin.vo.Visitor
|
||||
|
||||
|
||||
interface DisplayBetVisitor : Visitor {
|
||||
@Composable
|
||||
fun VisitYesNoBet(b: YesNoBet)
|
||||
|
||||
@Composable
|
||||
fun VisitMatchBet(b: MatchBet)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<array name="com_google_android_gms_fonts_certs">
|
||||
<item>@array/com_google_android_gms_fonts_certs_dev</item>
|
||||
<item>@array/com_google_android_gms_fonts_certs_prod</item>
|
||||
</array>
|
||||
<string-array name="com_google_android_gms_fonts_certs_dev">
|
||||
<item>
|
||||
MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
|
||||
</item>
|
||||
</string-array>
|
||||
<string-array name="com_google_android_gms_fonts_certs_prod">
|
||||
<item>
|
||||
MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
|
||||
</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -0,0 +1,239 @@
|
||||
package fr.iut.alldev.allin.data.api
|
||||
|
||||
import fr.iut.alldev.allin.data.api.interceptors.AllInAPIException
|
||||
import fr.iut.alldev.allin.data.api.model.CheckUser
|
||||
import fr.iut.alldev.allin.data.api.model.RequestBet
|
||||
import fr.iut.alldev.allin.data.api.model.RequestParticipation
|
||||
import fr.iut.alldev.allin.data.api.model.RequestUser
|
||||
import fr.iut.alldev.allin.data.api.model.ResponseBet
|
||||
import fr.iut.alldev.allin.data.api.model.ResponseBetAnswerDetail
|
||||
import fr.iut.alldev.allin.data.api.model.ResponseBetDetail
|
||||
import fr.iut.alldev.allin.data.api.model.ResponseParticipation
|
||||
import fr.iut.alldev.allin.data.api.model.ResponseUser
|
||||
import fr.iut.alldev.allin.data.model.bet.NO_VALUE
|
||||
import fr.iut.alldev.allin.data.model.bet.YES_VALUE
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.UUID
|
||||
|
||||
class MockAllInApi : AllInApi {
|
||||
|
||||
private fun getUserFromToken(token: String) =
|
||||
mockUsers.find { it.first.token == token }
|
||||
|
||||
private fun getAnswerDetails(bet: ResponseBet, participations: List<ResponseParticipation>): List<ResponseBetAnswerDetail> {
|
||||
return bet.response.map { response ->
|
||||
val responseParticipations = participations.filter { it.answer == response }
|
||||
ResponseBetAnswerDetail(
|
||||
response = response,
|
||||
totalStakes = responseParticipations.sumOf { it.stake },
|
||||
totalParticipants = responseParticipations.size,
|
||||
highestStake = responseParticipations.maxOfOrNull { it.stake } ?: 0,
|
||||
odds = if (participations.isEmpty()) 0.0f else responseParticipations.size / participations.size.toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun login(body: CheckUser): ResponseUser {
|
||||
return mockUsers.find { it.first.username == body.login && it.second == body.password }?.first
|
||||
?: throw AllInAPIException("Invalid login/password.")
|
||||
}
|
||||
|
||||
override suspend fun login(token: String): ResponseUser {
|
||||
return getUserFromToken(token)?.first
|
||||
?: throw AllInAPIException("Invalid token")
|
||||
}
|
||||
|
||||
override suspend fun register(body: RequestUser): ResponseUser {
|
||||
val response = ResponseUser(
|
||||
id = UUID.randomUUID().toString(),
|
||||
username = body.username,
|
||||
email = body.email,
|
||||
nbCoins = 500,
|
||||
token = "${body.username} ${mockUsers.size}"
|
||||
) to body.password
|
||||
mockUsers.add(response)
|
||||
return response.first
|
||||
}
|
||||
|
||||
override suspend fun createBet(token: String, body: RequestBet) {
|
||||
mockBets.add(
|
||||
ResponseBet(
|
||||
id = UUID.randomUUID().toString(),
|
||||
theme = body.theme,
|
||||
sentenceBet = body.sentenceBet,
|
||||
endRegistration = body.endRegistration,
|
||||
endBet = body.endBet,
|
||||
isPrivate = body.isPrivate,
|
||||
response = body.response,
|
||||
createdBy = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getAllBets(): List<ResponseBet> = mockBets.toList()
|
||||
override suspend fun getBet(token: String, id: String): ResponseBetDetail {
|
||||
val bet = mockBets.find { it.id == id } ?: throw AllInAPIException("Bet not found")
|
||||
val user = getUserFromToken(token) ?: throw AllInAPIException("Invalid login/password.")
|
||||
val betParticipations = mockParticipations.filter { it.betId == bet.id }
|
||||
val userParticipation = betParticipations.find { it.username == user.first.username }
|
||||
|
||||
return ResponseBetDetail(
|
||||
bet = bet,
|
||||
answers = getAnswerDetails(bet, betParticipations),
|
||||
participations = betParticipations,
|
||||
userParticipation = userParticipation
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun participateToBet(token: String, body: RequestParticipation) {
|
||||
getUserFromToken(token)?.let {
|
||||
mockParticipations.add(
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = body.betId,
|
||||
username = it.first.username,
|
||||
answer = body.answer,
|
||||
stake = body.stake
|
||||
|
||||
)
|
||||
)
|
||||
} ?: throw AllInAPIException("Invalid token")
|
||||
}
|
||||
}
|
||||
|
||||
private val mockUsers = mutableListOf(
|
||||
ResponseUser(
|
||||
id = "UUID 1",
|
||||
username = "User 1",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 1"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 2",
|
||||
username = "User 2",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 2"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 3",
|
||||
username = "User 3",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 3"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 4",
|
||||
username = "User 4",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 4"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 5",
|
||||
username = "User 5",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 5"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 6",
|
||||
username = "User 6",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 6"
|
||||
) to "12345",
|
||||
ResponseUser(
|
||||
id = "UUID 7",
|
||||
username = "User 7",
|
||||
email = "john@doe.fr",
|
||||
nbCoins = 250,
|
||||
token = "token 7"
|
||||
) to "12345"
|
||||
)
|
||||
|
||||
private val mockParticipations = mutableListOf(
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[0].first.username,
|
||||
answer = YES_VALUE,
|
||||
stake = 200
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[1].first.username,
|
||||
answer = NO_VALUE,
|
||||
stake = 1500
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[2].first.username,
|
||||
answer = YES_VALUE,
|
||||
stake = 300
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[3].first.username,
|
||||
answer = YES_VALUE,
|
||||
stake = 25
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[4].first.username,
|
||||
answer = NO_VALUE,
|
||||
stake = 222
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[5].first.username,
|
||||
answer = NO_VALUE,
|
||||
stake = 222
|
||||
),
|
||||
ResponseParticipation(
|
||||
id = "",
|
||||
betId = "UUID1",
|
||||
username = mockUsers[6].first.username,
|
||||
answer = NO_VALUE,
|
||||
stake = 222
|
||||
)
|
||||
)
|
||||
|
||||
private val mockBets = mutableListOf(
|
||||
ResponseBet(
|
||||
id = "UUID1",
|
||||
theme = "Études",
|
||||
sentenceBet = "Dave va arriver en retard demain matin ?",
|
||||
endRegistration = ZonedDateTime.now().plusDays(3),
|
||||
endBet = ZonedDateTime.now().plusDays(4),
|
||||
isPrivate = false,
|
||||
response = listOf(YES_VALUE, NO_VALUE),
|
||||
createdBy = "Armure"
|
||||
),
|
||||
ResponseBet(
|
||||
id = "UUID2",
|
||||
theme = "Études",
|
||||
sentenceBet = "Dave va arriver en retard demain matin ?",
|
||||
endRegistration = ZonedDateTime.now().plusDays(3),
|
||||
endBet = ZonedDateTime.now().plusDays(4),
|
||||
isPrivate = false,
|
||||
response = listOf("Answer 1", "Answer 2", "Answer 3", "Answer 4"),
|
||||
createdBy = "User 2"
|
||||
),
|
||||
ResponseBet(
|
||||
id = "UUID3",
|
||||
theme = "Sport",
|
||||
sentenceBet = "Nouveau record du monde ?",
|
||||
endRegistration = ZonedDateTime.now().plusDays(3),
|
||||
endBet = ZonedDateTime.now().plusDays(4),
|
||||
isPrivate = false,
|
||||
response = listOf(YES_VALUE, NO_VALUE),
|
||||
createdBy = "Armure"
|
||||
)
|
||||
)
|
@ -0,0 +1,31 @@
|
||||
package fr.iut.alldev.allin.data.api.model
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import fr.iut.alldev.allin.data.model.bet.Participation
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Keep
|
||||
@Serializable
|
||||
data class ResponseParticipation(
|
||||
val id: String,
|
||||
val betId: String,
|
||||
val username: String,
|
||||
val answer: String,
|
||||
val stake: Int
|
||||
) {
|
||||
fun toParticipation() =
|
||||
Participation(
|
||||
betId = betId,
|
||||
username = username,
|
||||
response = answer,
|
||||
stake = stake
|
||||
)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@Serializable
|
||||
data class RequestParticipation(
|
||||
val betId: String,
|
||||
val answer: String,
|
||||
val stake: Int
|
||||
)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue