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
fun BetStatus.getColor(): Color {
return when (this) {

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

@ -1,6 +1,7 @@
package fr.iut.alldev.allin.ui.bet.components
import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.HorizontalDivider
@ -8,6 +9,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
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.unit.dp
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.bet.BetDateTimeRow
import fr.iut.alldev.allin.ui.core.bet.BetProfilePictureRow
import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader
import fr.iut.alldev.allin.ui.theme.AllInTheme
@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
@Composable
fun BetScreenCard(
creator: String,
@ -31,11 +34,13 @@ fun BetScreenCard(
time: String,
players: List<Painter?>,
modifier: Modifier = Modifier,
onClickParticipate: ()->Unit
onClickParticipate: ()->Unit,
onClickCard: ()->Unit
) {
AllInCard(
AllInBouncyCard(
modifier = modifier.fillMaxWidth(),
radius = 16.dp
radius = 16.dp,
onClick = onClickCard
){
Column(
Modifier.padding(horizontal = 19.dp, vertical = 11.dp)
@ -96,7 +101,8 @@ private fun BetScreenCardPreview() {
date = "12 Sept.",
time = "13:00",
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
private val visitor = BetStatusBottomSheetDisplayBetVisitor()
@OptIn(ExperimentalMaterial3Api::class)
@ -24,7 +23,8 @@ fun BetStatusBottomSheet(
sheetVisibility: Boolean,
sheetBackVisibility: Boolean,
bet: BetVO<Bet>?,
onDismiss: ()->Unit
onDismiss: ()->Unit,
visitor: BetStatusBottomSheetDisplayBetVisitor
) {
AnimatedVisibility(
visible = sheetBackVisibility,
@ -49,8 +49,7 @@ fun BetStatusBottomSheet(
scrimColor = Color.Transparent
){
Column(
Modifier
.fillMaxHeight(SHEET_HEIGHT)
Modifier.fillMaxHeight(SHEET_HEIGHT)
) {
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.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.data.ext.toPercentageString
@ -19,11 +18,10 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun YesNoStatBar(
yesPercentage: Float
yesPercentage: Float,
modifier: Modifier = Modifier
) {
Column(
Modifier.padding(horizontal = 9.dp)
){
Column(modifier){
Row{
Text(
text = stringResource(id = R.string.Yes).uppercase(),

@ -1,33 +1,233 @@
package fr.iut.alldev.allin.ui.betstatus.visitor
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
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.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.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.BetStatus
import fr.iut.alldev.allin.data.model.bet.MatchBet
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.theme.AllInTheme
import fr.iut.alldev.allin.vo.bet.factory.toBetVO
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
override fun visitYesNoBet(b: YesNoBet) {
Column {
BetTitleHeader(
title = b.phrase,
category = b.theme,
creator = "Lucas" /*TODO : Creator*/,
modifier = Modifier.padding(horizontal = 20.dp)
)
StatBar(percentage = .86f)
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.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)
}
)
}
}
BetStatusParticipationBottomSheet(
sheetVisibility = participateSheetVisibility && b.betStatus == BetStatus.WAITING,
safeBottomPadding = safeBottomPadding,
betPhrase = b.phrase,
coinAmount = userCoinAmount.value,
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 {
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.LocalLayoutDirection
import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.theme.AllInTheme
import racra.compose.smooth_corner_rect_library.AbsoluteSmoothCornerShape
@OptIn(ExperimentalMaterial3Api::class)
@ -16,6 +17,7 @@ fun AllInBottomSheet(
onDismiss: ()->Unit,
state: SheetState,
scrimColor: Color = BottomSheetDefaults.ScrimColor,
containerColor: Color = AllInTheme.themeColors.background,
content: @Composable ColumnScope.()->Unit
) {
val localDensity = LocalDensity.current
@ -25,6 +27,7 @@ fun AllInBottomSheet(
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = state,
containerColor = containerColor,
scrimColor = scrimColor,
shape = sheetShape,
windowInsets = BottomSheetDefaults.windowInsets.let {

@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
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.ui.theme.AllInTheme
@ -17,10 +18,16 @@ fun AllInButton(
color: Color,
text: String,
textColor: Color,
radius: Dp = 15.dp,
modifier: Modifier = Modifier,
onClick: ()->Unit
) {
AllInCard(onClick = onClick, modifier = modifier, radius = 50.dp, backgroundColor = color) {
AllInCard(
onClick = onClick,
modifier = modifier,
radius = radius,
backgroundColor = color
) {
Text(
text = text,
textAlign = TextAlign.Center,

@ -1,13 +1,23 @@
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.ExperimentalFoundationApi
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.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
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,49 +1,26 @@
package fr.iut.alldev.allin.ui.core
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.ui.Alignment
import androidx.compose.ui.Modifier
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.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun AllInCoinCount(
modifier: Modifier = Modifier,
amount: Int,
color: Color
color: Color,
position: IconPosition = IconPosition.TRAILING
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(7.dp)
) {
Text(
text = amount.toString(),
fontWeight = FontWeight.ExtraBold,
color = color,
style = AllInTheme.typography.h1,
fontSize = 16.sp
)
Icon(
painter = painterResource(id = R.drawable.allcoin),
contentDescription = null,
modifier = Modifier
.size(13.dp),
tint = color
)
}
AllInTextIcon(
text = amount.toString(),
icon = AllInTheme.icons.allCoins(),
color = color,
position = position,
modifier = modifier
)
}
@Preview

@ -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
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.*
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
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.Stroke
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.tooling.preview.Preview
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 kotlin.math.PI
import kotlin.math.abs
@ -34,26 +41,44 @@ import kotlin.math.max
@Composable
fun AllInLoading(
modifier: Modifier = Modifier,
visible: Boolean,
brush: Brush = AllInTheme.colors.allIn_MainGradient
) {
val interactionSource = remember { MutableInteractionSource() }
Box(
modifier = modifier
.fillMaxSize()
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = {}
)
.background(AllInTheme.themeColors.main_surface.copy(alpha = .4f))
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut()
) {
AllInCircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center)
.size(50.dp),
brush = brush,
strokeWidth = 7.dp
)
Dialog(
onDismissRequest = {},
properties = DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false,
decorFitsSystemWindows = false,
usePlatformDefaultWidth = false
)
) {
(LocalView.current.parent as DialogWindowProvider).window.setDimAmount(0f)
Box(
modifier = modifier
.fillMaxSize()
.clickable(
interactionSource = interactionSource,
indication = null,
onClick = {}
)
.background(AllInTheme.themeColors.main_surface.copy(alpha = .4f))
) {
AllInCircularProgressIndicator(
modifier = Modifier
.align(Alignment.Center)
.size(50.dp),
brush = brush,
strokeWidth = 7.dp
)
}
}
}
}
@ -204,6 +229,6 @@ private val CircularEasing = CubicBezierEasing(0.4f, 0f, 0.2f, 1f)
@Composable
private fun AllInLoadingPreview() {
AllInTheme {
AllInLoading()
AllInLoading(visible = true)
}
}

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

@ -1,6 +1,7 @@
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
@ -104,19 +105,20 @@ fun AllInSelectionBox(
if(isOpen) ExpandLess else ExpandMore
}
)
if(isOpen){
HorizontalDivider(color = AllInTheme.themeColors.border)
elements.filter { it != selected }.forEach{
element ->
AllInSelectionLine(
text = stringResource(id = element.textId),
iconVector = element.imageVector,
interactionSource = interactionSource,
onClick = {
setSelected(element)
setIsOpen(false)
}
)
AnimatedVisibility(isOpen){
Column {
HorizontalDivider(color = AllInTheme.themeColors.border)
elements.filter { it != selected }.forEach { element ->
AllInSelectionLine(
text = stringResource(id = element.textId),
iconVector = element.imageVector,
interactionSource = interactionSource,
onClick = {
setSelected(element)
setIsOpen(false)
}
)
}
}
}
}

@ -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) {
AllInCard(
borderWidth = if (enabled) 1.dp else 2.dp,
borderWidth = 1.dp,
onClick = onClick,
modifier = modifier.fillMaxWidth(),
enabled = enabled

@ -12,30 +12,35 @@ 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.painterResource
import androidx.compose.ui.graphics.Color
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 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)) {
Row(
modifier = Modifier
.background(AllInTheme.colors.white)
.background(backgroundColor)
.padding(horizontal = 13.dp, vertical = 5.dp),
horizontalArrangement = Arrangement.spacedBy(7.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(text = amount.toString(),
color = AllInTheme.colors.allIn_Dark,
color = textColor,
style = AllInTheme.typography.h1,
fontSize = 20.sp)
Icon(
painter = painterResource(R.drawable.allcoin),
tint = AllInTheme.colors.allIn_Blue,
painter = AllInTheme.icons.allCoins(),
tint = iconColor,
contentDescription = null,
)
}
@ -44,8 +49,8 @@ fun CoinCounter(amount:Int, modifier: Modifier = Modifier) {
@Preview
@Composable
private fun CoinCounterPreview() {
private fun AllInTopBarCoinCounterPreview() {
AllInTheme {
CoinCounter(547)
AllInTopBarCoinCounter(547)
}
}

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

@ -1,6 +1,5 @@
package fr.iut.alldev.allin.ui.login
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@ -161,9 +160,7 @@ fun LoginScreen(
}
}
}
AnimatedVisibility(visible = loading) {
AllInLoading()
}
AllInLoading(visible = loading)
AllInAlertDialog(
enabled = hasLoginError,
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.compose.rememberNavController
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.navigation.AllInDrawerNavHost
import fr.iut.alldev.allin.ui.navigation.Routes
@ -28,8 +30,10 @@ private val topLevelDestinations = listOf(
TopLevelDestination.FRIENDS,
TopLevelDestination.CURRENT_BETS
)
@Composable
private fun rememberBetStatusVisibilities(): Triple<MutableState<Boolean>, MutableState<Boolean>, (Boolean) -> Unit> {
private fun rememberBetStatusVisibilities()
: Triple<MutableState<Boolean>, MutableState<Boolean>, (Boolean) -> Unit> {
val statusVisibility = remember {
mutableStateOf(false)
}
@ -43,7 +47,11 @@ private fun rememberBetStatusVisibilities(): Triple<MutableState<Boolean>, Mutab
statusVisibility.value = it
if(it) sheetBackVisibility.value = true
}
return Triple(statusVisibility, sheetBackVisibility, setStatusVisibility)
return Triple(
statusVisibility,
sheetBackVisibility,
setStatusVisibility,
)
}
@OptIn(ExperimentalMaterial3Api::class)
@ -54,15 +62,25 @@ fun MainScreen(
startDestination: String = Routes.PUBLIC_BETS,
mainViewModel: MainViewModel = hiltViewModel()
) {
val loading by remember{ mainViewModel.loading }
val currentUser = remember{
mainViewModel.currentUser
mainViewModel.currentUserState
}
val (selectedBet, setSelectedBet) = remember{
mainViewModel.selectedBet
}
val betStatusDisplayVisitor = remember {
BetStatusBottomSheetDisplayBetVisitor(
userCoinAmount = currentUser.userCoins,
onParticipate = {
mainViewModel.participateToBet(it)
}
)
}
val scope = rememberCoroutineScope()
val (statusVisibility, sheetBackVisibility, setStatusVisibility)
@ -82,7 +100,7 @@ fun MainScreen(
drawerState = drawerState,
destinations = topLevelDestinations,
scope = scope,
username = currentUser.username,
username = currentUser.user.username,
nbFriends = 5,
nbBets = 35,
bestWin = 362,
@ -92,9 +110,12 @@ fun MainScreen(
){
AllInScaffold(
onMenuClicked = { scope.launch { drawerState.open() } },
coinAmount = currentUser.coins,
coinAmount = currentUser.userCoins.value,
drawerState = drawerState
) {
LaunchedEffect(key1 = it){
betStatusDisplayVisitor.paddingValues.value = it
}
Column(
modifier = Modifier
.padding(top = it.calculateTopPadding())
@ -104,8 +125,9 @@ fun MainScreen(
) {
AllInDrawerNavHost(
navController = navController,
selectBet = {
setSelectedBet(it)
selectBet = { bet, participate ->
setSelectedBet(bet)
betStatusDisplayVisitor.participateBottomSheetVisibility.value = participate
setStatusVisibility(true)
}
)
@ -120,8 +142,10 @@ fun MainScreen(
onDismiss = {
setStatusVisibility(false)
},
bet = selectedBet?.toBetVO()
bet = selectedBet?.toBetVO(),
visitor = betStatusDisplayVisitor
)
AllInLoading(visible = loading)
BackHandler(
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.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import fr.iut.alldev.allin.data.model.User
import fr.iut.alldev.allin.data.model.bet.Bet
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
class UserState(val user: User){
val userCoins = mutableStateOf(user.coins)
}
@HiltViewModel
class MainViewModel @Inject constructor(
@AllInCurrentUser val currentUser: User
) : ViewModel() {
var loading = mutableStateOf(false)
val currentUserState = UserState(currentUser)
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(
modifier: Modifier = Modifier,
navController: NavHostController,
selectBet: (Bet) -> Unit,
selectBet: (Bet, Boolean) -> Unit,
startDestination: String = Routes.PUBLIC_BETS
) {
NavHost(

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

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

@ -29,7 +29,7 @@ data class AllInTypography(
val xs: TextStyle
)
val LocalTypography = staticCompositionLocalOf {
internal val LocalTypography = staticCompositionLocalOf {
AllInTypography(
h1 = 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
interface ViewObject<V>{
interface ViewObject<V : Visitor>{
@Composable
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(),
MatchBet::class.java to MatchBetVOFactory()
)
abstract class BetVOFactory<out T : Bet> {
abstract fun create(bet: @UnsafeVariance T): BetVO<@UnsafeVariance T>
}
@ -26,5 +25,6 @@ class MatchBetVOFactory : BetVOFactory<MatchBet>() {
MatchBetVO(bet)
}
fun Bet.toBetVO() =
betTypeToVOMap[this.javaClass]?.create(this)
fun Bet.toBetVO() = betTypeToVOMap[this.javaClass]?.create(this)

@ -3,9 +3,10 @@ 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 {
interface DisplayBetVisitor : Visitor {
@Composable
fun visitYesNoBet(b: YesNoBet)

@ -20,6 +20,9 @@
<string name="FieldError_AlreadyUsed">%s est déjà utilisé.</string>
<string name="Yes">Oui</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-->
<string name="bets">Bets</string>
@ -82,6 +85,9 @@
<string name="Current">En cours</string>
<string name="Finished">Terminés</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="Proposed_by_x">Proposé par %1$s</string>
<plurals name="n_players_waiting">
@ -104,5 +110,6 @@
<string name="bet_status_finished">Terminé !</string>
<string name="bet_status_in_progress">En cours…</string>
<string name="bet_status_waiting">En attente…</string>
<string name="place_your_bets">Faites vos paris</string>
</resources>

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

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

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

@ -9,6 +9,12 @@ fun ZonedDateTime.formatToMediumDate(): String {
).replaceFirstChar { it.uppercase() }
}
fun ZonedDateTime.formatToMediumDateNoYear(): String {
return this.format(
DateTimeFormatter.ofPattern("dd MMM")
).replaceFirstChar { it.uppercase() }
}
fun ZonedDateTime.formatToTime(): String {
return this.format(
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.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 javax.inject.Inject
@ -22,7 +22,7 @@ class UserRepositoryImpl @Inject constructor(
override suspend fun register(username: String, email: String, password: String) {
currentUser = api.register(
ResponseUser(
RequestUser(
username = username,
email = email,
password = password,

Loading…
Cancel
Save