Continue displaying of bets
continuous-integration/drone/push Build is passing Details

pull/3/head
Arthur VALIN 2 years ago
parent 038781de5a
commit 716a389be0

@ -14,6 +14,20 @@ fun BetStatus.getTitle(): Int {
} }
} }
fun BetStatus.getDateStartLabel(): Int {
return when (this) {
BetStatus.FINISHED -> R.string.Started
else -> R.string.Starting
}
}
fun BetStatus.getDateEndLabel(): Int {
return when (this) {
BetStatus.FINISHED -> R.string.Ended
else -> R.string.Ends
}
}
@Composable @Composable
fun BetStatus.getColor(): Color { fun BetStatus.getColor(): Color {
return when (this) { return when (this) {

@ -23,6 +23,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
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.BetStatus 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.data.model.bet.YesNoBet
import fr.iut.alldev.allin.ui.bet.components.BetScreenCard import fr.iut.alldev.allin.ui.bet.components.BetScreenCard
import fr.iut.alldev.allin.ui.bet.components.BetScreenPopularCard import fr.iut.alldev.allin.ui.bet.components.BetScreenPopularCard
@ -32,12 +33,38 @@ import java.time.ZonedDateTime
private val bets = listOf( private val bets = listOf(
YesNoBet( YesNoBet(
"Études", theme = "Études",
"Emre va t'il finir son TP de MAUI?", phrase = "Emre va t'il finir son TP de MAUI?",
ZonedDateTime.now(), endRegisterDate = ZonedDateTime.now(),
ZonedDateTime.now(), endBetDate = ZonedDateTime.now(),
true, isPublic = true,
BetStatus.IN_PROGRESS betStatus = BetStatus.WAITING
),
YesNoBet(
theme = "Études",
phrase = "Emre va t'il finir son TP de MAUI?",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.IN_PROGRESS
),
YesNoBet(
theme = "Études",
phrase = "Emre va t'il finir son TP de MAUI?",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.FINISHED
),
MatchBet(
theme = "Études",
phrase = "Emre va t'il finir son TP de MAUI?",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.WAITING,
nameTeam1 = "Team 1",
nameTeam2 = "Team 2"
), ),
) )
@ -45,7 +72,7 @@ private val bets = listOf(
@Composable @Composable
fun BetScreen( fun BetScreen(
viewModel: BetViewModel = hiltViewModel(), viewModel: BetViewModel = hiltViewModel(),
selectBet: (Bet)->Unit selectBet: (Bet, Boolean)->Unit
){ ){
val horizontalPadding = 23.dp val horizontalPadding = 23.dp
@ -122,7 +149,8 @@ fun BetScreen(
date = "11 Sept.", date = "11 Sept.",
time = "13:00", time = "13:00",
players = List(3){ null }, players = List(3){ null },
onClickParticipate = { selectBet(it) }, onClickParticipate = { selectBet(it, true) },
onClickCard = { selectBet(it, false) },
modifier = Modifier.padding(horizontal = horizontalPadding) modifier = Modifier.padding(horizontal = horizontalPadding)
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))

@ -1,6 +1,7 @@
package fr.iut.alldev.allin.ui.bet.components package fr.iut.alldev.allin.ui.bet.components
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -8,6 +9,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
@ -15,13 +17,14 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.core.AllInCard import fr.iut.alldev.allin.ui.core.AllInBouncyCard
import fr.iut.alldev.allin.ui.core.RainbowButton 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.BetDateTimeRow
import fr.iut.alldev.allin.ui.core.bet.BetProfilePictureRow import fr.iut.alldev.allin.ui.core.bet.BetProfilePictureRow
import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
@Composable @Composable
fun BetScreenCard( fun BetScreenCard(
creator: String, creator: String,
@ -31,11 +34,13 @@ fun BetScreenCard(
time: String, time: String,
players: List<Painter?>, players: List<Painter?>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClickParticipate: ()->Unit onClickParticipate: ()->Unit,
onClickCard: ()->Unit
) { ) {
AllInCard( AllInBouncyCard(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
radius = 16.dp radius = 16.dp,
onClick = onClickCard
){ ){
Column( Column(
Modifier.padding(horizontal = 19.dp, vertical = 11.dp) Modifier.padding(horizontal = 19.dp, vertical = 11.dp)
@ -96,7 +101,8 @@ private fun BetScreenCardPreview() {
date = "12 Sept.", date = "12 Sept.",
time = "13:00", time = "13:00",
players = List(3){ null }, players = List(3){ null },
onClickParticipate = {} onClickParticipate = {},
onClickCard = {}
) )
} }
} }

@ -14,7 +14,6 @@ import fr.iut.alldev.allin.vo.bet.BetVO
internal const val SHEET_HEIGHT = .85f internal const val SHEET_HEIGHT = .85f
private val visitor = BetStatusBottomSheetDisplayBetVisitor()
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -24,7 +23,8 @@ fun BetStatusBottomSheet(
sheetVisibility: Boolean, sheetVisibility: Boolean,
sheetBackVisibility: Boolean, sheetBackVisibility: Boolean,
bet: BetVO<Bet>?, bet: BetVO<Bet>?,
onDismiss: ()->Unit onDismiss: ()->Unit,
visitor: BetStatusBottomSheetDisplayBetVisitor
) { ) {
AnimatedVisibility( AnimatedVisibility(
visible = sheetBackVisibility, visible = sheetBackVisibility,
@ -49,8 +49,7 @@ fun BetStatusBottomSheet(
scrimColor = Color.Transparent scrimColor = Color.Transparent
){ ){
Column( Column(
Modifier Modifier.fillMaxHeight(SHEET_HEIGHT)
.fillMaxHeight(SHEET_HEIGHT)
) { ) {
bet?.accept(visitor) bet?.accept(visitor)
} }

@ -0,0 +1,126 @@
package fr.iut.alldev.allin.ui.betstatus.components
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
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.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.core.AllInBottomSheet
import fr.iut.alldev.allin.ui.core.AllInButton
import fr.iut.alldev.allin.ui.core.AllInCoinCount
import fr.iut.alldev.allin.ui.core.topbar.AllInTopBarCoinCounter
import fr.iut.alldev.allin.ui.theme.AllInTheme
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BetStatusParticipationBottomSheet(
sheetVisibility: Boolean,
safeBottomPadding: Dp,
betPhrase: String,
coinAmount: Int,
onDismiss: ()->Unit,
state: SheetState,
onParticipate: ()->Unit
) {
val scope = rememberCoroutineScope()
AllInBottomSheet(
sheetVisibility = sheetVisibility,
onDismiss = onDismiss,
state = state,
containerColor = AllInTheme.themeColors.background_2
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(id = R.string.place_your_bets),
style = AllInTheme.typography.h2,
color = AllInTheme.themeColors.on_main_surface,
fontSize = 20.sp,
modifier = Modifier.padding(start = 18.dp)
)
AllInTopBarCoinCounter(
amount = coinAmount,
backgroundColor = AllInTheme.colors.allIn_Blue,
textColor = AllInTheme.colors.white,
iconColor = AllInTheme.colors.white,
)
}
Spacer(modifier = Modifier.height(30.dp))
Text(
text = betPhrase,
style = AllInTheme.typography.s,
color = AllInTheme.themeColors.on_main_surface,
modifier = Modifier.padding(horizontal = 18.dp)
)
Spacer(modifier = Modifier.height(100.dp))
HorizontalDivider(color = AllInTheme.themeColors.border)
Column(
modifier = Modifier
.background(AllInTheme.themeColors.background)
.padding(horizontal = 7.dp)
.padding(bottom = safeBottomPadding, top = 7.dp),
verticalArrangement = Arrangement.spacedBy(7.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
){
Text(
text = stringResource(id = R.string.Possible_winnings),
style = AllInTheme.typography.r,
color = AllInTheme.themeColors.on_background
)
AllInCoinCount(
amount = 121,
color = AllInTheme.themeColors.on_background
)
}
AllInButton(
color = AllInTheme.colors.allIn_Purple,
text = stringResource(id = R.string.Participate),
textColor = AllInTheme.colors.white,
radius = 5.dp
){
scope.launch{
onParticipate()
state.hide()
onDismiss()
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun BetStatusParticipationBottomSheetPreview() {
AllInTheme {
BetStatusParticipationBottomSheet(
sheetVisibility = true,
safeBottomPadding = 5.dp,
betPhrase = "Lorem Ipsum",
coinAmount = 125,
onDismiss = {},
state = rememberModalBottomSheetState(),
onParticipate = {}
)
}
}

@ -0,0 +1,84 @@
package fr.iut.alldev.allin.ui.betstatus.components
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.material3.HorizontalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.core.AllInCoinCount
import fr.iut.alldev.allin.ui.core.AllInTextIcon
import fr.iut.alldev.allin.ui.core.IconPosition
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun BetStatusWinner(
answer: String,
coinAmount: Int,
username: String,
multiplier: Float,
color: Color = AllInTheme.themeColors.on_main_surface
) {
Column {
HorizontalDivider(color = color.copy(alpha = .4f))
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.background(color.copy(alpha = .2f))
.padding(vertical = 20.dp)
) {
AllInTextIcon(
text = answer,
icon = Icons.Filled.EmojiEvents,
color = color,
size = 50,
iconSize = 60,
position = IconPosition.LEADING
)
Row(
horizontalArrangement = Arrangement.spacedBy(17.dp)
) {
AllInCoinCount(
amount = coinAmount,
color = color,
position = IconPosition.LEADING
)
AllInTextIcon(
text = username,
icon = Icons.Filled.People,
color = color,
position = IconPosition.LEADING
)
AllInTextIcon(
text = "x" + String.format("%.1f", multiplier),
icon = Icons.Filled.EmojiEvents,
color = color,
position = IconPosition.LEADING
)
}
}
}
HorizontalDivider(color = color.copy(alpha = .4f))
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun BetStatusWinnerPreview() {
AllInTheme {
BetStatusWinner(
answer = "Answer",
coinAmount = 435,
username = "Imri",
multiplier = 1.2f,
)
}
}

@ -0,0 +1,85 @@
package fr.iut.alldev.allin.ui.betstatus.components
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import fr.iut.alldev.allin.ui.core.AllInTextIcon
import fr.iut.alldev.allin.ui.core.IconPosition
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun YesNoDetailsLine(
icon: ImageVector,
yesText: String,
noText: String
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
AllInTextIcon(
text = yesText,
color = AllInTheme.colors.allIn_Blue,
icon = icon,
position = IconPosition.LEADING,
size = 10,
iconSize = 15
)
AllInTextIcon(
text = noText,
color = AllInTheme.colors.allIn_BarPink,
icon = icon,
position = IconPosition.TRAILING,
size = 10,
iconSize = 15
)
}
}
@Composable
fun YesNoDetailsLine(
icon: Painter,
yesText: String,
noText: String
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
AllInTextIcon(
text = yesText,
color = AllInTheme.colors.allIn_Blue,
icon = icon,
position = IconPosition.LEADING,
size = 10,
iconSize = 15
)
AllInTextIcon(
text = noText,
color = AllInTheme.colors.allIn_BarPink,
icon = icon,
position = IconPosition.TRAILING,
size = 10,
iconSize = 15
)
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun YesNoDetailsLinePreview() {
AllInTheme {
YesNoDetailsLine(
icon = AllInTheme.icons.allCoins(),
yesText = "550",
noText = "330"
)
}
}

@ -9,7 +9,6 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.data.ext.toPercentageString import fr.iut.alldev.allin.data.ext.toPercentageString
@ -19,11 +18,10 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable @Composable
fun YesNoStatBar( fun YesNoStatBar(
yesPercentage: Float yesPercentage: Float,
) { modifier: Modifier = Modifier
Column(
Modifier.padding(horizontal = 9.dp)
) { ) {
Column(modifier){
Row{ Row{
Text( Text(
text = stringResource(id = R.string.Yes).uppercase(), text = stringResource(id = R.string.Yes).uppercase(),

@ -1,33 +1,233 @@
package fr.iut.alldev.allin.ui.betstatus.visitor package fr.iut.alldev.allin.ui.betstatus.visitor
import androidx.compose.foundation.layout.Column import android.content.res.Configuration
import androidx.compose.foundation.layout.padding 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.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.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.BetStatus
import fr.iut.alldev.allin.data.model.bet.MatchBet 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.YesNoBet
import fr.iut.alldev.allin.ui.core.StatBar import fr.iut.alldev.allin.ext.getDateEndLabel
import fr.iut.alldev.allin.ext.getDateStartLabel
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.ui.core.bet.BetTitleHeader
import fr.iut.alldev.allin.ui.theme.AllInTheme
import fr.iut.alldev.allin.vo.bet.factory.toBetVO
import fr.iut.alldev.allin.vo.bet.visitor.DisplayBetVisitor import fr.iut.alldev.allin.vo.bet.visitor.DisplayBetVisitor
import java.time.ZonedDateTime
class BetStatusBottomSheetDisplayBetVisitor : DisplayBetVisitor { class BetStatusBottomSheetDisplayBetVisitor(
val userCoinAmount: MutableState<Int>,
val onParticipate: (Int)->Unit
) : DisplayBetVisitor {
val participateBottomSheetVisibility = mutableStateOf(false)
val paddingValues = mutableStateOf(PaddingValues())
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
override fun visitYesNoBet(b: YesNoBet) { override fun visitYesNoBet(b: YesNoBet) {
val (participateSheetVisibility, setParticipateSheetVisibility) = remember{
this.participateBottomSheetVisibility
}
val safeBottomPadding = paddingValues.value.calculateBottomPadding()
Box(
Modifier
.padding(bottom = safeBottomPadding)
) {
Column{ Column{
Column(
Modifier.padding(horizontal = 20.dp)
) {
BetTitleHeader( BetTitleHeader(
title = b.phrase, title = b.phrase,
category = b.theme, category = b.theme,
creator = "Lucas" /*TODO : Creator*/, creator = "Lucas" /*TODO : Creator*/,
modifier = Modifier.padding(horizontal = 20.dp) modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(20.dp))
Column(
horizontalAlignment = Alignment.End
) {
BetDateTimeRow(
label = stringResource(id = b.betStatus.getDateStartLabel()),
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.getDateEndLabel()),
date = b.endBetDate.formatToMediumDateNoYear(),
time = b.endBetDate.formatToTime(),
modifier = Modifier.width(IntrinsicSize.Max)
)
}
Spacer(modifier = Modifier.height(20.dp))
}
if (b.betStatus == BetStatus.FINISHED) {
BetStatusWinner(
answer = stringResource(id = R.string.Yes),
color = AllInTheme.colors.allIn_Blue,
coinAmount = 442,
username = "Imri",
multiplier = 1.2f
)
} else {
HorizontalDivider(color = AllInTheme.themeColors.border)
}
Column(
Modifier
.fillMaxHeight()
.background(AllInTheme.themeColors.background_2)
.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 != 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)
}
) )
StatBar(percentage = .86f)
} }
} }
BetStatusParticipationBottomSheet(
sheetVisibility = participateSheetVisibility && b.betStatus == BetStatus.WAITING,
safeBottomPadding = safeBottomPadding,
betPhrase = b.phrase,
coinAmount = userCoinAmount.value,
onDismiss = { setParticipateSheetVisibility(false) },
state = rememberModalBottomSheetState()
){
onParticipate(100)
}
}
@Composable @Composable
override fun visitMatchBet(b: MatchBet) { override fun visitMatchBet(b: MatchBet) {
Text("This is a MATCH BET") Text("This is a MATCH BET")
} }
} }
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun YesNoBetPreview() {
AllInTheme {
YesNoBet(
theme = "Theme",
phrase = "Phrase",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.IN_PROGRESS
).toBetVO()?.accept(
BetStatusBottomSheetDisplayBetVisitor(
userCoinAmount = mutableStateOf(100),
onParticipate = {}
)
)
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun YesNoBetFinishedPreview() {
AllInTheme {
YesNoBet(
theme = "Theme",
phrase = "Phrase",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.FINISHED
).toBetVO()?.accept(
BetStatusBottomSheetDisplayBetVisitor(
userCoinAmount = mutableStateOf(100),
onParticipate = {}
)
)
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun MatchBetPreview() {
AllInTheme {
MatchBet(
theme = "Theme",
phrase = "Phrase",
endRegisterDate = ZonedDateTime.now(),
endBetDate = ZonedDateTime.now(),
isPublic = true,
betStatus = BetStatus.IN_PROGRESS,
nameTeam1 = "Team 1",
nameTeam2 = "Team 2"
).toBetVO()?.accept(
BetStatusBottomSheetDisplayBetVisitor(
userCoinAmount = mutableStateOf(100),
onParticipate = {}
)
)
}
}

@ -7,6 +7,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.theme.AllInTheme
import racra.compose.smooth_corner_rect_library.AbsoluteSmoothCornerShape import racra.compose.smooth_corner_rect_library.AbsoluteSmoothCornerShape
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -16,6 +17,7 @@ fun AllInBottomSheet(
onDismiss: ()->Unit, onDismiss: ()->Unit,
state: SheetState, state: SheetState,
scrimColor: Color = BottomSheetDefaults.ScrimColor, scrimColor: Color = BottomSheetDefaults.ScrimColor,
containerColor: Color = AllInTheme.themeColors.background,
content: @Composable ColumnScope.()->Unit content: @Composable ColumnScope.()->Unit
) { ) {
val localDensity = LocalDensity.current val localDensity = LocalDensity.current
@ -25,6 +27,7 @@ fun AllInBottomSheet(
ModalBottomSheet( ModalBottomSheet(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
sheetState = state, sheetState = state,
containerColor = containerColor,
scrimColor = scrimColor, scrimColor = scrimColor,
shape = sheetShape, shape = sheetShape,
windowInsets = BottomSheetDefaults.windowInsets.let { windowInsets = BottomSheetDefaults.windowInsets.let {

@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@ -17,10 +18,16 @@ fun AllInButton(
color: Color, color: Color,
text: String, text: String,
textColor: Color, textColor: Color,
radius: Dp = 15.dp,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: ()->Unit onClick: ()->Unit
) { ) {
AllInCard(onClick = onClick, modifier = modifier, radius = 50.dp, backgroundColor = color) { AllInCard(
onClick = onClick,
modifier = modifier,
radius = radius,
backgroundColor = color
) {
Text( Text(
text = text, text = text,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,

@ -1,13 +1,23 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
@ -69,3 +79,52 @@ fun AllInCard(
} }
} }
} }
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AllInBouncyCard(
modifier: Modifier = Modifier,
onClick: (()->Unit)? = null,
radius: Dp = 15.dp,
enabled: Boolean = true,
backgroundColor: Color = AllInTheme.themeColors.background,
disabledBackgroundColor: Color = AllInTheme.themeColors.disabled,
backgroundBrush: Brush? = null,
borderWidth: Dp? = null,
borderColor: Color = AllInTheme.themeColors.border,
disabledBorderColor: Color = AllInTheme.themeColors.disabled_border,
borderBrush: Brush? = null,
content: @Composable ()->Unit
){
val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()
val scale by animateFloatAsState(
targetValue = if(isPressed) .95f else 1f,
animationSpec = spring(
Spring.DampingRatioHighBouncy,
Spring.StiffnessMediumLow
)
)
AllInCard(
modifier = modifier
.combinedClickable(
interactionSource = interactionSource,
indication = null,
onClick = { onClick?.let { it() } }
)
.scale(scale),
onClick = null,
radius = radius,
enabled = enabled,
backgroundColor = backgroundColor,
disabledBackgroundColor = disabledBackgroundColor,
backgroundBrush = backgroundBrush,
borderWidth = borderWidth,
borderColor = borderColor,
disabledBorderColor = disabledBorderColor,
borderBrush = borderBrush,
content = content
)
}

@ -1,50 +1,27 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview 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.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable @Composable
fun AllInCoinCount( fun AllInCoinCount(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
amount: Int, amount: Int,
color: Color color: Color,
position: IconPosition = IconPosition.TRAILING
) { ) {
Row( AllInTextIcon(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(7.dp)
) {
Text(
text = amount.toString(), text = amount.toString(),
fontWeight = FontWeight.ExtraBold, icon = AllInTheme.icons.allCoins(),
color = color, color = color,
style = AllInTheme.typography.h1, position = position,
fontSize = 16.sp modifier = modifier
)
Icon(
painter = painterResource(id = R.drawable.allcoin),
contentDescription = null,
modifier = Modifier
.size(13.dp),
tint = color
) )
} }
}
@Preview @Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)

@ -0,0 +1,81 @@
package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
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.ui.theme.AllInTheme
@Composable
fun AllInDetailsDrawer(
text: String = stringResource(id = R.string.Details),
textColor: Color = AllInTheme.themeColors.on_background_2,
content: @Composable ColumnScope.()->Unit
){
val interactionSource = remember { MutableInteractionSource() }
var isOpen by remember { mutableStateOf(false) }
Column(
Modifier
.fillMaxWidth()
.animateContentSize()
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(Alignment.End)
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = {
isOpen = !isOpen
}
)
){
Text(
text = text,
style = AllInTheme.typography.s,
color = textColor,
fontSize = 15.sp
)
Icon(
imageVector = with(Icons.Default){
if(isOpen) ExpandLess else ExpandMore
},
contentDescription = null,
tint = textColor,
modifier = Modifier.size(15.dp)
)
}
AnimatedVisibility(visible = isOpen){
Column {
content()
}
}
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun AllInDetailsDrawerPreview() {
AllInTheme {
AllInDetailsDrawer{}
}
}

@ -1,7 +1,10 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.* import androidx.compose.animation.core.*
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -23,9 +26,13 @@ import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.DialogWindowProvider
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.abs import kotlin.math.abs
@ -34,9 +41,25 @@ import kotlin.math.max
@Composable @Composable
fun AllInLoading( fun AllInLoading(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
visible: Boolean,
brush: Brush = AllInTheme.colors.allIn_MainGradient brush: Brush = AllInTheme.colors.allIn_MainGradient
) { ) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut()
) {
Dialog(
onDismissRequest = {},
properties = DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false,
decorFitsSystemWindows = false,
usePlatformDefaultWidth = false
)
) {
(LocalView.current.parent as DialogWindowProvider).window.setDimAmount(0f)
Box( Box(
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
@ -56,6 +79,8 @@ fun AllInLoading(
) )
} }
} }
}
}
@Composable @Composable
fun AllInCircularProgressIndicator( fun AllInCircularProgressIndicator(
@ -204,6 +229,6 @@ private val CircularEasing = CubicBezierEasing(0.4f, 0f, 0.2f, 1f)
@Composable @Composable
private fun AllInLoadingPreview() { private fun AllInLoadingPreview() {
AllInTheme { AllInTheme {
AllInLoading() AllInLoading(visible = true)
} }
} }

@ -1,5 +1,6 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
@ -71,10 +72,12 @@ fun AllInRetractableCard(
modifier = Modifier.size(30.dp) modifier = Modifier.size(30.dp)
) )
} }
if(isOpen){ AnimatedVisibility(isOpen){
Column{
HorizontalDivider(color = AllInTheme.themeColors.border) HorizontalDivider(color = AllInTheme.themeColors.border)
content() content()
} }
} }
} }
} }
}

@ -1,6 +1,7 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
@ -104,10 +105,10 @@ fun AllInSelectionBox(
if(isOpen) ExpandLess else ExpandMore if(isOpen) ExpandLess else ExpandMore
} }
) )
if(isOpen){ AnimatedVisibility(isOpen){
Column {
HorizontalDivider(color = AllInTheme.themeColors.border) HorizontalDivider(color = AllInTheme.themeColors.border)
elements.filter { it != selected }.forEach{ elements.filter { it != selected }.forEach { element ->
element ->
AllInSelectionLine( AllInSelectionLine(
text = stringResource(id = element.textId), text = stringResource(id = element.textId),
iconVector = element.imageVector, iconVector = element.imageVector,
@ -122,6 +123,7 @@ fun AllInSelectionBox(
} }
} }
} }
}
@Preview @Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)

@ -0,0 +1,132 @@
package fr.iut.alldev.allin.ui.core
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Fireplace
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.ui.theme.AllInTheme
enum class IconPosition{
LEADING,
TRAILING
}
@Composable
fun AllInTextIcon(
modifier: Modifier = Modifier,
text: String,
icon: Painter,
color: Color,
position: IconPosition = IconPosition.TRAILING,
size: Int = 15,
iconSize: Int = size
) {
val direction =
if(position==IconPosition.LEADING) LayoutDirection.Rtl
else LayoutDirection.Ltr
Box(modifier) {
CompositionLocalProvider(
LocalLayoutDirection provides direction
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(7.dp)
) {
Text(
text = text,
color = color,
style = AllInTheme.typography.h1,
fontSize = size.sp
)
Icon(
painter = icon,
contentDescription = null,
modifier = Modifier.size(iconSize.dp),
tint = color
)
}
}
}
}
@Composable
fun AllInTextIcon(
modifier: Modifier = Modifier,
text: String,
icon: ImageVector,
color: Color,
position: IconPosition = IconPosition.TRAILING,
size: Int = 15,
iconSize: Int = size
) {
val direction =
if(position==IconPosition.LEADING) LayoutDirection.Rtl
else LayoutDirection.Ltr
Box(modifier) {
CompositionLocalProvider(
LocalLayoutDirection provides direction
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(7.dp)
) {
Text(
text = text,
color = color,
style = AllInTheme.typography.h1,
fontSize = size.sp
)
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.size(iconSize.dp),
tint = color
)
}
}
}
}
@Preview
@Composable
private fun AllInTextIconPreview() {
AllInTheme {
AllInTextIcon(
text = "value",
icon = Icons.Default.Fireplace,
color = AllInTheme.colors.allIn_Blue
)
}
}
@Preview
@Composable
private fun AllInTextIconReversePreview() {
AllInTheme {
AllInTextIcon(
text = "value",
icon = AllInTheme.icons.allCoins(),
color = AllInTheme.colors.allIn_Blue,
position = IconPosition.LEADING
)
}
}

@ -23,7 +23,7 @@ fun RainbowButton(
) { ) {
AllInRipple(rippleColor) { AllInRipple(rippleColor) {
AllInCard( AllInCard(
borderWidth = if (enabled) 1.dp else 2.dp, borderWidth = 1.dp,
onClick = onClick, onClick = onClick,
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
enabled = enabled enabled = enabled

@ -12,30 +12,35 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable @Composable
fun CoinCounter(amount:Int, modifier: Modifier = Modifier) { fun AllInTopBarCoinCounter(
amount:Int,
backgroundColor: Color = AllInTheme.colors.white,
textColor: Color = AllInTheme.colors.allIn_Dark,
iconColor: Color = AllInTheme.colors.allIn_Blue,
modifier: Modifier = Modifier
) {
Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) { Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) {
Row( Row(
modifier = Modifier modifier = Modifier
.background(AllInTheme.colors.white) .background(backgroundColor)
.padding(horizontal = 13.dp, vertical = 5.dp), .padding(horizontal = 13.dp, vertical = 5.dp),
horizontalArrangement = Arrangement.spacedBy(7.dp), horizontalArrangement = Arrangement.spacedBy(7.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Text(text = amount.toString(), Text(text = amount.toString(),
color = AllInTheme.colors.allIn_Dark, color = textColor,
style = AllInTheme.typography.h1, style = AllInTheme.typography.h1,
fontSize = 20.sp) fontSize = 20.sp)
Icon( Icon(
painter = painterResource(R.drawable.allcoin), painter = AllInTheme.icons.allCoins(),
tint = AllInTheme.colors.allIn_Blue, tint = iconColor,
contentDescription = null, contentDescription = null,
) )
} }
@ -44,8 +49,8 @@ fun CoinCounter(amount:Int, modifier: Modifier = Modifier) {
@Preview @Preview
@Composable @Composable
private fun CoinCounterPreview() { private fun AllInTopBarCoinCounterPreview() {
AllInTheme { AllInTheme {
CoinCounter(547) AllInTopBarCoinCounter(547)
} }
} }

@ -45,7 +45,7 @@ fun AllInTopBar(
.size(40.dp) .size(40.dp)
.align(Alignment.Center) .align(Alignment.Center)
) )
CoinCounter( AllInTopBarCoinCounter(
amount = coinAmount, amount = coinAmount,
modifier = Modifier modifier = Modifier
.align(Alignment.CenterEnd) .align(Alignment.CenterEnd)

@ -1,6 +1,5 @@
package fr.iut.alldev.allin.ui.login package fr.iut.alldev.allin.ui.login
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -161,9 +160,7 @@ fun LoginScreen(
} }
} }
} }
AnimatedVisibility(visible = loading) { AllInLoading(visible = loading)
AllInLoading()
}
AllInAlertDialog( AllInAlertDialog(
enabled = hasLoginError, enabled = hasLoginError,
title = stringResource(id = R.string.Login_Error_Title), title = stringResource(id = R.string.Login_Error_Title),

@ -11,6 +11,8 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import fr.iut.alldev.allin.ui.betstatus.BetStatusBottomSheet import fr.iut.alldev.allin.ui.betstatus.BetStatusBottomSheet
import fr.iut.alldev.allin.ui.betstatus.visitor.BetStatusBottomSheetDisplayBetVisitor
import fr.iut.alldev.allin.ui.core.AllInLoading
import fr.iut.alldev.allin.ui.main.components.AllInScaffold import fr.iut.alldev.allin.ui.main.components.AllInScaffold
import fr.iut.alldev.allin.ui.navigation.AllInDrawerNavHost import fr.iut.alldev.allin.ui.navigation.AllInDrawerNavHost
import fr.iut.alldev.allin.ui.navigation.Routes import fr.iut.alldev.allin.ui.navigation.Routes
@ -28,8 +30,10 @@ private val topLevelDestinations = listOf(
TopLevelDestination.FRIENDS, TopLevelDestination.FRIENDS,
TopLevelDestination.CURRENT_BETS TopLevelDestination.CURRENT_BETS
) )
@Composable @Composable
private fun rememberBetStatusVisibilities(): Triple<MutableState<Boolean>, MutableState<Boolean>, (Boolean) -> Unit> { private fun rememberBetStatusVisibilities()
: Triple<MutableState<Boolean>, MutableState<Boolean>, (Boolean) -> Unit> {
val statusVisibility = remember { val statusVisibility = remember {
mutableStateOf(false) mutableStateOf(false)
} }
@ -43,7 +47,11 @@ private fun rememberBetStatusVisibilities(): Triple<MutableState<Boolean>, Mutab
statusVisibility.value = it statusVisibility.value = it
if(it) sheetBackVisibility.value = true if(it) sheetBackVisibility.value = true
} }
return Triple(statusVisibility, sheetBackVisibility, setStatusVisibility) return Triple(
statusVisibility,
sheetBackVisibility,
setStatusVisibility,
)
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -54,15 +62,25 @@ fun MainScreen(
startDestination: String = Routes.PUBLIC_BETS, startDestination: String = Routes.PUBLIC_BETS,
mainViewModel: MainViewModel = hiltViewModel() mainViewModel: MainViewModel = hiltViewModel()
) { ) {
val loading by remember{ mainViewModel.loading }
val currentUser = remember{ val currentUser = remember{
mainViewModel.currentUser mainViewModel.currentUserState
} }
val (selectedBet, setSelectedBet) = remember{ val (selectedBet, setSelectedBet) = remember{
mainViewModel.selectedBet mainViewModel.selectedBet
} }
val betStatusDisplayVisitor = remember {
BetStatusBottomSheetDisplayBetVisitor(
userCoinAmount = currentUser.userCoins,
onParticipate = {
mainViewModel.participateToBet(it)
}
)
}
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val (statusVisibility, sheetBackVisibility, setStatusVisibility) val (statusVisibility, sheetBackVisibility, setStatusVisibility)
@ -82,7 +100,7 @@ fun MainScreen(
drawerState = drawerState, drawerState = drawerState,
destinations = topLevelDestinations, destinations = topLevelDestinations,
scope = scope, scope = scope,
username = currentUser.username, username = currentUser.user.username,
nbFriends = 5, nbFriends = 5,
nbBets = 35, nbBets = 35,
bestWin = 362, bestWin = 362,
@ -92,9 +110,12 @@ fun MainScreen(
){ ){
AllInScaffold( AllInScaffold(
onMenuClicked = { scope.launch { drawerState.open() } }, onMenuClicked = { scope.launch { drawerState.open() } },
coinAmount = currentUser.coins, coinAmount = currentUser.userCoins.value,
drawerState = drawerState drawerState = drawerState
) { ) {
LaunchedEffect(key1 = it){
betStatusDisplayVisitor.paddingValues.value = it
}
Column( Column(
modifier = Modifier modifier = Modifier
.padding(top = it.calculateTopPadding()) .padding(top = it.calculateTopPadding())
@ -104,8 +125,9 @@ fun MainScreen(
) { ) {
AllInDrawerNavHost( AllInDrawerNavHost(
navController = navController, navController = navController,
selectBet = { selectBet = { bet, participate ->
setSelectedBet(it) setSelectedBet(bet)
betStatusDisplayVisitor.participateBottomSheetVisibility.value = participate
setStatusVisibility(true) setStatusVisibility(true)
} }
) )
@ -120,8 +142,10 @@ fun MainScreen(
onDismiss = { onDismiss = {
setStatusVisibility(false) setStatusVisibility(false)
}, },
bet = selectedBet?.toBetVO() bet = selectedBet?.toBetVO(),
visitor = betStatusDisplayVisitor
) )
AllInLoading(visible = loading)
BackHandler( BackHandler(
enabled = drawerState.isOpen enabled = drawerState.isOpen
) { ) {
@ -130,13 +154,6 @@ fun MainScreen(
} }
} }
BackHandler(
enabled = statusVisibility.value
) {
scope.launch {
setStatusVisibility(false)
}
}
} }

@ -2,16 +2,41 @@ package fr.iut.alldev.allin.ui.main
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import fr.iut.alldev.allin.data.model.User
import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.Bet
import fr.iut.alldev.allin.di.AllInCurrentUser import fr.iut.alldev.allin.di.AllInCurrentUser
import fr.iut.alldev.allin.data.model.User import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
class UserState(val user: User){
val userCoins = mutableStateOf(user.coins)
}
@HiltViewModel @HiltViewModel
class MainViewModel @Inject constructor( class MainViewModel @Inject constructor(
@AllInCurrentUser val currentUser: User @AllInCurrentUser val currentUser: User
) : ViewModel() { ) : ViewModel() {
var loading = mutableStateOf(false)
val currentUserState = UserState(currentUser)
val selectedBet = mutableStateOf<Bet?>(null) val selectedBet = mutableStateOf<Bet?>(null)
fun participateToBet(
stake: Int
){
viewModelScope.launch {
withContext(Dispatchers.IO) {
loading.value = true
currentUserState.userCoins.value += 50
Thread.sleep(1000)
loading.value = false
}
}
}
} }

@ -81,7 +81,7 @@ fun AllInNavHost(modifier: Modifier = Modifier,
internal fun AllInDrawerNavHost( internal fun AllInDrawerNavHost(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
navController: NavHostController, navController: NavHostController,
selectBet: (Bet) -> Unit, selectBet: (Bet, Boolean) -> Unit,
startDestination: String = Routes.PUBLIC_BETS startDestination: String = Routes.PUBLIC_BETS
) { ) {
NavHost( NavHost(

@ -1,6 +1,5 @@
package fr.iut.alldev.allin.ui.register package fr.iut.alldev.allin.ui.register
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.BringIntoViewRequester
@ -201,7 +200,5 @@ fun RegisterScreen(
} }
} }
} }
AnimatedVisibility(visible = loading) { AllInLoading(visible = loading)
AllInLoading()
}
} }

@ -0,0 +1,19 @@
package fr.iut.alldev.allin.ui.theme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.graphics.painter.Painter
@Immutable
data class AllInIcons(
val allCoins: @Composable ()->Painter,
)
internal val LocalIcons = staticCompositionLocalOf {
AllInIcons(
allCoins = { ColorPainter(Color.Unspecified) }
)
}

@ -9,8 +9,10 @@ import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import fr.iut.alldev.allin.R
@Composable @Composable
@ -134,8 +136,13 @@ fun AllInTheme(
) )
} }
val customIcons = AllInIcons(
allCoins = { painterResource(id = R.drawable.allcoin) }
)
CompositionLocalProvider( CompositionLocalProvider(
LocalColors provides customColors, LocalColors provides customColors,
LocalIcons provides customIcons,
LocalTypography provides customTypography, LocalTypography provides customTypography,
LocalThemeColors provides customTheme LocalThemeColors provides customTheme
){ ){
@ -149,6 +156,11 @@ object AllInTheme {
@ReadOnlyComposable @ReadOnlyComposable
get() = LocalColors.current get() = LocalColors.current
val icons: AllInIcons
@Composable
@ReadOnlyComposable
get() = LocalIcons.current
val typography: AllInTypography val typography: AllInTypography
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable

@ -29,7 +29,7 @@ data class AllInTypography(
val xs: TextStyle val xs: TextStyle
) )
val LocalTypography = staticCompositionLocalOf { internal val LocalTypography = staticCompositionLocalOf {
AllInTypography( AllInTypography(
h1 = TextStyle.Default, h1 = TextStyle.Default,
h2 = TextStyle.Default, h2 = TextStyle.Default,

@ -0,0 +1,12 @@
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)"
}

@ -2,7 +2,7 @@ package fr.iut.alldev.allin.vo
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
interface ViewObject<V>{ interface ViewObject<V : Visitor>{
@Composable @Composable
fun accept(v: V) fun accept(v: V)
} }

@ -0,0 +1,3 @@
package fr.iut.alldev.allin.vo
interface Visitor

@ -11,7 +11,6 @@ private val betTypeToVOMap = mapOf(
YesNoBet::class.java to YesNoBetVOFactory(), YesNoBet::class.java to YesNoBetVOFactory(),
MatchBet::class.java to MatchBetVOFactory() MatchBet::class.java to MatchBetVOFactory()
) )
abstract class BetVOFactory<out T : Bet> { abstract class BetVOFactory<out T : Bet> {
abstract fun create(bet: @UnsafeVariance T): BetVO<@UnsafeVariance T> abstract fun create(bet: @UnsafeVariance T): BetVO<@UnsafeVariance T>
} }
@ -26,5 +25,6 @@ class MatchBetVOFactory : BetVOFactory<MatchBet>() {
MatchBetVO(bet) MatchBetVO(bet)
} }
fun Bet.toBetVO() = fun Bet.toBetVO() = betTypeToVOMap[this.javaClass]?.create(this)
betTypeToVOMap[this.javaClass]?.create(this)

@ -3,9 +3,10 @@ package fr.iut.alldev.allin.vo.bet.visitor
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import fr.iut.alldev.allin.data.model.bet.MatchBet 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.YesNoBet
import fr.iut.alldev.allin.vo.Visitor
interface DisplayBetVisitor { interface DisplayBetVisitor : Visitor {
@Composable @Composable
fun visitYesNoBet(b: YesNoBet) fun visitYesNoBet(b: YesNoBet)

@ -20,6 +20,9 @@
<string name="FieldError_AlreadyUsed">%s est déjà utilisé.</string> <string name="FieldError_AlreadyUsed">%s est déjà utilisé.</string>
<string name="Yes">Oui</string> <string name="Yes">Oui</string>
<string name="No">Non</string> <string name="No">Non</string>
<string name="Details">Détails</string>
<string name="Stake">Mise</string>
<string name="Possible_winnings">Gains possibles</string>
<!--Drawer--> <!--Drawer-->
<string name="bets">Bets</string> <string name="bets">Bets</string>
@ -82,6 +85,9 @@
<string name="Current">En cours</string> <string name="Current">En cours</string>
<string name="Finished">Terminés</string> <string name="Finished">Terminés</string>
<string name="Starting">Commence le</string> <string name="Starting">Commence le</string>
<string name="Started">A commencé le</string>
<string name="Ends">Prend fin le</string>
<string name="Ended">A pris fin le</string>
<string name="Participate">Participer</string> <string name="Participate">Participer</string>
<string name="Proposed_by_x">Proposé par %1$s</string> <string name="Proposed_by_x">Proposé par %1$s</string>
<plurals name="n_players_waiting"> <plurals name="n_players_waiting">
@ -104,5 +110,6 @@
<string name="bet_status_finished">Terminé !</string> <string name="bet_status_finished">Terminé !</string>
<string name="bet_status_in_progress">En cours…</string> <string name="bet_status_in_progress">En cours…</string>
<string name="bet_status_waiting">En attente…</string> <string name="bet_status_waiting">En attente…</string>
<string name="place_your_bets">Faites vos paris</string>
</resources> </resources>

@ -22,6 +22,9 @@
<string name="FieldError_AlreadyUsed">%s is already used.</string> <string name="FieldError_AlreadyUsed">%s is already used.</string>
<string name="Yes">Yes</string> <string name="Yes">Yes</string>
<string name="No">No</string> <string name="No">No</string>
<string name="Details">Details</string>
<string name="Stake">Stake</string>
<string name="Possible_winnings">Possible winnings</string>
<!--Drawer--> <!--Drawer-->
<string name="bets">Bets</string> <string name="bets">Bets</string>
@ -84,7 +87,10 @@
<string name="Invitation">Invitation</string> <string name="Invitation">Invitation</string>
<string name="Current">Current</string> <string name="Current">Current</string>
<string name="Finished">Finished</string> <string name="Finished">Finished</string>
<string name="Starting">Starting</string> <string name="Starting">Starting on</string>
<string name="Started">Started on</string>
<string name="Ends">Ends on</string>
<string name="Ended">Ended on</string>
<string name="Participate">Participate</string> <string name="Participate">Participate</string>
<string name="Proposed_by_x">Proposed by %1$s</string> <string name="Proposed_by_x">Proposed by %1$s</string>
<plurals name="n_players_waiting"> <plurals name="n_players_waiting">
@ -103,4 +109,5 @@
<string name="bet_status_finished">Finished !</string> <string name="bet_status_finished">Finished !</string>
<string name="bet_status_in_progress">In progress…</string> <string name="bet_status_in_progress">In progress…</string>
<string name="bet_status_waiting">Waiting…</string> <string name="bet_status_waiting">Waiting…</string>
<string name="place_your_bets">Place your bets</string>
</resources> </resources>

@ -1,6 +1,7 @@
package fr.iut.alldev.allin.data.api package fr.iut.alldev.allin.data.api
import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.CheckUser
import fr.iut.alldev.allin.data.api.model.RequestUser
import fr.iut.alldev.allin.data.api.model.ResponseUser import fr.iut.alldev.allin.data.api.model.ResponseUser
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.POST import retrofit2.http.POST
@ -13,6 +14,6 @@ interface AllInApi {
@POST("users/register") @POST("users/register")
suspend fun register( suspend fun register(
@Body body: ResponseUser @Body body: RequestUser
): ResponseUser ): ResponseUser
} }

@ -6,11 +6,19 @@ import kotlinx.serialization.Serializable
@Keep @Keep
@Serializable @Serializable
data class ResponseUser( data class RequestUser(
val username: String, val username: String,
val email: String, val email: String,
val password: String, val password: String,
var nbCoins: Int, var nbCoins: Int,
)
@Keep
@Serializable
data class ResponseUser(
val username: String,
val email: String,
var nbCoins: Int,
){ ){
fun toUser() = User( fun toUser() = User(
username = username, username = username,

@ -9,6 +9,12 @@ fun ZonedDateTime.formatToMediumDate(): String {
).replaceFirstChar { it.uppercase() } ).replaceFirstChar { it.uppercase() }
} }
fun ZonedDateTime.formatToMediumDateNoYear(): String {
return this.format(
DateTimeFormatter.ofPattern("dd MMM")
).replaceFirstChar { it.uppercase() }
}
fun ZonedDateTime.formatToTime(): String { fun ZonedDateTime.formatToTime(): String {
return this.format( return this.format(
DateTimeFormatter.ofPattern("HH:mm") DateTimeFormatter.ofPattern("HH:mm")

@ -2,7 +2,7 @@ package fr.iut.alldev.allin.data.repository.impl
import fr.iut.alldev.allin.data.api.AllInApi import fr.iut.alldev.allin.data.api.AllInApi
import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.CheckUser
import fr.iut.alldev.allin.data.api.model.ResponseUser import fr.iut.alldev.allin.data.api.model.RequestUser
import fr.iut.alldev.allin.data.repository.UserRepository import fr.iut.alldev.allin.data.repository.UserRepository
import javax.inject.Inject import javax.inject.Inject
@ -22,7 +22,7 @@ class UserRepositoryImpl @Inject constructor(
override suspend fun register(username: String, email: String, password: String) { override suspend fun register(username: String, email: String, password: String) {
currentUser = api.register( currentUser = api.register(
ResponseUser( RequestUser(
username = username, username = username,
email = email, email = email,
password = password, password = password,

Loading…
Cancel
Save