diff --git a/src/app/src/main/java/fr/iut/alldev/allin/di/CurrentUserModule.kt b/src/app/src/main/java/fr/iut/alldev/allin/di/CurrentUserModule.kt index 2010974..fee0dc8 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/di/CurrentUserModule.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/di/CurrentUserModule.kt @@ -16,7 +16,5 @@ annotation class AllInCurrentUser internal object CurrentUserModule { @AllInCurrentUser @Provides - fun provideUser( - userRepository: UserRepository - ) = userRepository.currentUser + fun provideUser(userRepository: UserRepository) = userRepository.currentUser } \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/theme/Icons.kt b/src/app/src/main/java/fr/iut/alldev/allin/theme/Icons.kt index 819c5b5..8382348 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/theme/Icons.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/theme/Icons.kt @@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.painter.Painter @Immutable data class AllInIcons( - val allCoins: @Composable ()->Painter, + val allCoins: @Composable () -> Painter, ) internal val LocalIcons = staticCompositionLocalOf { diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt index 71d3aae..5e420ea 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/BetCreationViewModel.kt @@ -110,6 +110,7 @@ class BetCreationViewModel @Inject constructor( if (!hasError.value) { try { val bet = BetFactory.createBet( + id = "", betType = selectedBetType.value, theme = theme.value, phrase = phrase.value, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/tabs/BetCreationScreenQuestionTab.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/tabs/BetCreationScreenQuestionTab.kt index 5edafd5..1065e7e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/tabs/BetCreationScreenQuestionTab.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betCreation/tabs/BetCreationScreenQuestionTab.kt @@ -1,10 +1,10 @@ package fr.iut.alldev.allin.ui.betCreation.tabs -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.relocation.BringIntoViewRequester -import androidx.compose.runtime.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import fr.iut.alldev.allin.data.ext.formatToMediumDate @@ -14,7 +14,6 @@ import fr.iut.alldev.allin.ui.betCreation.tabs.sections.QuestionTabPrivacySectio import fr.iut.alldev.allin.ui.betCreation.tabs.sections.QuestionTabThemePhraseSection import java.time.ZonedDateTime -@OptIn(ExperimentalFoundationApi::class) @Composable fun BetCreationScreenQuestionTab( modifier: Modifier = Modifier, @@ -38,7 +37,6 @@ fun BetCreationScreenQuestionTab( setEndTimeDialog: (Boolean) -> Unit, interactionSource: MutableInteractionSource ) { - val bringIntoViewRequester = remember { BringIntoViewRequester() } Column(modifier) { QuestionTabThemePhraseSection( betTheme = betTheme, diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt index 3eebfbe..7fd4eeb 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betResult/BetResultBottomSheet.kt @@ -154,6 +154,7 @@ private fun BetResultBottomSheetContentPreview() { username = "Pseudo", coinAmount = 3976, bet = YesNoBet( + id = "1", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/BetStatusBottomSheet.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/BetStatusBottomSheet.kt index da23df3..7e193fc 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/BetStatusBottomSheet.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/BetStatusBottomSheet.kt @@ -6,10 +6,11 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -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.vo.BetDetail import fr.iut.alldev.allin.ui.betStatus.components.BetStatusBottomSheetBack import fr.iut.alldev.allin.ui.betStatus.components.BetStatusParticipationBottomSheet +import fr.iut.alldev.allin.ui.betStatus.components.getAnswerFromParticipationIdx import fr.iut.alldev.allin.ui.betStatus.components.getParticipationAnswers import fr.iut.alldev.allin.ui.core.AllInBottomSheet @@ -23,14 +24,14 @@ fun BetStatusBottomSheet( state: SheetState, sheetVisibility: Boolean, sheetBackVisibility: Boolean, - bet: Bet?, + betDetail: BetDetail?, paddingValues: PaddingValues, userCoinAmount: MutableIntState, - onParticipate: (Int) -> Unit, + onParticipate: (stake: Int, response: String) -> Unit, onDismiss: () -> Unit, participateSheetVisibility: Boolean, setParticipateSheetVisibility: (Boolean) -> Unit, - displayBet: @Composable (Bet) -> Unit + displayBet: @Composable (BetDetail) -> Unit ) { AnimatedVisibility( visible = sheetBackVisibility, @@ -41,9 +42,9 @@ fun BetStatusBottomSheet( targetOffsetY = { it } ) ) { - bet?.let { + betDetail?.let { BetStatusBottomSheetBack( - status = it.betStatus + status = it.bet.betStatus ) } } @@ -61,14 +62,15 @@ fun BetStatusBottomSheet( Column( Modifier.fillMaxHeight(SHEET_HEIGHT) ) { - bet?.let { - val elements = bet.getParticipationAnswers() + betDetail?.let { + val elements = betDetail.getParticipationAnswers() displayBet(it) BetStatusParticipationBottomSheet( - sheetVisibility = participateSheetVisibility && bet.betStatus == BetStatus.Waiting && state.hasExpandedState, + sheetVisibility = participateSheetVisibility && betDetail.bet.betStatus == BetStatus.Waiting && state.hasExpandedState, safeBottomPadding = paddingValues.calculateBottomPadding(), - betPhrase = bet.phrase, + odds = betDetail.answers.getOrNull(selectedAnswer)?.odds ?: 1f, + betPhrase = betDetail.bet.phrase, coinAmount = userCoinAmount.intValue, onDismiss = { setParticipateSheetVisibility(false) }, state = rememberModalBottomSheetState(skipPartiallyExpanded = true), @@ -80,8 +82,11 @@ fun BetStatusBottomSheet( enabled = stake != null && (stake ?: 0) <= userCoinAmount.intValue ) { - stake?.let { - onParticipate(it) + stake?.let { stake -> + onParticipate( + stake, + betDetail.bet.getAnswerFromParticipationIdx(selectedAnswer) + ) } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt index fa0511f..735ad70 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationAnswers.kt @@ -1,82 +1,138 @@ package fr.iut.alldev.allin.ui.betStatus.components import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text - import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import fr.iut.alldev.allin.R +import androidx.core.os.ConfigurationCompat import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail +import fr.iut.alldev.allin.ext.formatToSimple import fr.iut.alldev.allin.theme.AllInTheme -import fr.iut.alldev.allin.ui.preview.BetPreviewProvider +import fr.iut.alldev.allin.ui.core.AllInCard +import fr.iut.alldev.allin.ui.preview.BetDetailPreviewProvider +import java.util.Locale private val participationAnswerFontSize = 25.sp @Composable -fun Bet.getParticipationAnswers(): List<@Composable RowScope.() -> Unit> = - when (this) { - is CustomBet -> this.possibleAnswers.map { +fun BetDetail.getParticipationAnswers(): List<@Composable RowScope.() -> Unit> { + val configuration = LocalConfiguration.current + val locale = remember { ConfigurationCompat.getLocales(configuration).get(0) ?: Locale.getDefault() } + + return when (this.bet) { + is CustomBet -> (this.bet as CustomBet).possibleAnswers.map { { - Text( - text = it, - color = AllInTheme.colors.allInBlue, - style = AllInTheme.typography.h1, - fontSize = participationAnswerFontSize - ) + this@getParticipationAnswers.getAnswerOfResponse(it)?.let { + ParticipationAnswerLine( + text = it.response, + odds = it.odds, + locale = locale + ) + } } } - is MatchBet -> listOf( - { - Text( - text = this@getParticipationAnswers.nameTeam1, - color = AllInTheme.colors.allInBlue, - style = AllInTheme.typography.h1, - fontSize = participationAnswerFontSize - ) - }, - { - Text( - text = this@getParticipationAnswers.nameTeam2, - color = AllInTheme.colors.allInBarPink, - style = AllInTheme.typography.h1, - fontSize = participationAnswerFontSize - ) + is MatchBet -> buildList { + val bet = (this@getParticipationAnswers.bet as MatchBet) + add { + this@getParticipationAnswers.getAnswerOfResponse(bet.nameTeam1)?.let { + ParticipationAnswerLine( + text = it.response, + odds = it.odds, + locale = locale + ) + } } + add { + this@getParticipationAnswers.getAnswerOfResponse(bet.nameTeam2)?.let { + ParticipationAnswerLine( + text = it.response, + color = AllInTheme.colors.allInBarPink, + odds = it.odds, + locale = locale + ) + } + } + } + + is YesNoBet -> buildList { + add { + this@getParticipationAnswers.getAnswerOfResponse(YES_VALUE)?.let { + ParticipationAnswerLine( + text = it.response, + odds = it.odds, + locale = locale + ) + } + } + add { + this@getParticipationAnswers.getAnswerOfResponse(NO_VALUE)?.let { + ParticipationAnswerLine( + text = it.response, + color = AllInTheme.colors.allInBarPink, + odds = it.odds, + locale = locale + ) + } + } + } + } +} + +@Composable +private fun ParticipationAnswerLine( + text: String, + color: Color = AllInTheme.colors.allInBlue, + locale: Locale, + odds: Float +) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = text.uppercase(), + color = color, + style = AllInTheme.typography.h1, + fontSize = participationAnswerFontSize ) - is YesNoBet -> listOf( - { - Text( - text = stringResource(id = R.string.Yes).uppercase(), - color = AllInTheme.colors.allInBlue, - style = AllInTheme.typography.h1, - fontSize = participationAnswerFontSize - ) - }, - { + AllInCard( + radius = 50.dp, + backgroundColor = AllInTheme.colors.allInPurple + ) { + Box(Modifier.padding(vertical = 4.dp, horizontal = 8.dp)) { Text( - text = stringResource(id = R.string.No).uppercase(), - color = AllInTheme.colors.allInBarPink, - style = AllInTheme.typography.h1, - fontSize = participationAnswerFontSize + text = "x${odds.formatToSimple(locale)}", + color = AllInTheme.colors.white, + style = AllInTheme.typography.h2 ) } - ) + } } +} fun Bet.getAnswerFromParticipationIdx(idx: Int) = when (this) { @@ -98,7 +154,7 @@ fun Bet.getAnswerFromParticipationIdx(idx: Int) = @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable private fun ParticipationAnswersPreview( - @PreviewParameter(BetPreviewProvider::class) bet: Bet, + @PreviewParameter(BetDetailPreviewProvider::class) bet: BetDetail, ) { AllInTheme { Column { diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationBottomSheet.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationBottomSheet.kt index 0b2db92..7892162 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationBottomSheet.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/BetStatusParticipationBottomSheet.kt @@ -24,6 +24,7 @@ import fr.iut.alldev.allin.ui.core.AllInIntTextField import fr.iut.alldev.allin.ui.core.AllInSelectionBox import fr.iut.alldev.allin.ui.core.topbar.AllInTopBarCoinCounter import kotlinx.coroutines.launch +import kotlin.math.roundToInt @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -35,6 +36,7 @@ fun BetStatusParticipationBottomSheet( onDismiss: () -> Unit, state: SheetState, enabled: Boolean, + odds: Float, stake: Int?, setStake: (Int?) -> Unit, elements: List<@Composable RowScope.() -> Unit>, @@ -58,6 +60,7 @@ fun BetStatusParticipationBottomSheet( setElement = setElement, enabled = enabled, stake = stake, + odds = odds, setStake = setStake ) { scope.launch { @@ -76,6 +79,7 @@ private fun ColumnScope.BetStatusParticipationBottomSheetContent( coinAmount: Int, enabled: Boolean, stake: Int?, + odds: Float, setStake: (Int?) -> Unit, selectedElement: (@Composable RowScope.() -> Unit)?, elements: List<@Composable RowScope.() -> Unit>, @@ -150,7 +154,7 @@ private fun ColumnScope.BetStatusParticipationBottomSheetContent( color = AllInTheme.themeColors.onBackground ) AllInCoinCount( - amount = 121, + amount = stake?.let { (it + (it * odds)).roundToInt() } ?: 0, color = AllInTheme.themeColors.onBackground ) } @@ -181,6 +185,7 @@ private fun BetStatusParticipationBottomSheetContentPreview() { selectedElement = null, enabled = true, stake = 123, + odds = 0.42f, setStake = {} ) } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/YesNoStarBar.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/YesNoStarBar.kt index 5abafbd..1aad42e 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/YesNoStarBar.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/components/YesNoStarBar.kt @@ -4,27 +4,27 @@ import androidx.compose.foundation.layout.* import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.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.sp -import fr.iut.alldev.allin.R import fr.iut.alldev.allin.data.ext.toPercentageString import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.core.PercentagePositionnedElement import fr.iut.alldev.allin.ui.core.StatBar @Composable -fun YesNoStatBar( - yesPercentage: Float, +fun BinaryStatBar( + response1Percentage: Float, + response1: String, + response2: String, modifier: Modifier = Modifier, ) { Column(modifier) { Row { Text( - text = stringResource(id = R.string.Yes).uppercase(), + text = response1, color = AllInTheme.colors.allInBlue, style = AllInTheme.typography.h1, fontStyle = FontStyle.Italic, @@ -32,19 +32,19 @@ fun YesNoStatBar( modifier = Modifier.weight(1f) ) Text( - text = stringResource(id = R.string.No).uppercase(), + text = response2, style = AllInTheme.typography.h1, fontStyle = FontStyle.Italic, fontSize = 30.sp, color = AllInTheme.colors.allInBarPink ) } - StatBar(percentage = yesPercentage) + StatBar(percentage = response1Percentage) PercentagePositionnedElement( - percentage = yesPercentage + percentage = response1Percentage ) { Text( - text = yesPercentage.toPercentageString(), + text = response1Percentage.toPercentageString(), style = AllInTheme.typography.sm1, color = AllInTheme.colors.allInBarPurple ) @@ -64,6 +64,10 @@ private fun YesNoStatBarPreview( @PreviewParameter(YesNoStatBarPreviewProvider::class) percentage: Float, ) { AllInTheme { - YesNoStatBar(percentage) + BinaryStatBar( + percentage, + "Answer 1", + "Answer 2" + ) } } \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt index 4c9a268..e316c59 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betStatus/vo/BetStatusBottomSheetBetDisplayer.kt @@ -3,6 +3,8 @@ package fr.iut.alldev.allin.ui.betStatus.vo import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.EmojiEvents import androidx.compose.material.icons.filled.People @@ -13,48 +15,67 @@ import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.os.ConfigurationCompat import fr.iut.alldev.allin.R import fr.iut.alldev.allin.data.ext.formatToMediumDateNoYear import fr.iut.alldev.allin.data.ext.formatToTime -import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.BetStatus -import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.NO_VALUE +import fr.iut.alldev.allin.data.model.bet.YES_VALUE +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail +import fr.iut.alldev.allin.ext.formatToSimple import fr.iut.alldev.allin.ext.getDateEndLabelId import fr.iut.alldev.allin.ext.getDateStartLabelId import fr.iut.alldev.allin.theme.AllInTheme import fr.iut.alldev.allin.ui.betStatus.components.BetStatusWinner +import fr.iut.alldev.allin.ui.betStatus.components.BinaryStatBar import fr.iut.alldev.allin.ui.betStatus.components.YesNoDetailsLine -import fr.iut.alldev.allin.ui.betStatus.components.YesNoStatBar +import fr.iut.alldev.allin.ui.core.AllInCoinCount import fr.iut.alldev.allin.ui.core.AllInDetailsDrawer +import fr.iut.alldev.allin.ui.core.ProfilePicture import fr.iut.alldev.allin.ui.core.RainbowButton import fr.iut.alldev.allin.ui.core.bet.BetDateTimeRow import fr.iut.alldev.allin.ui.core.bet.BetTitleHeader -import fr.iut.alldev.allin.ui.preview.BetWithStatusPreviewProvider +import fr.iut.alldev.allin.ui.preview.BetDetailPreviewProvider import fr.iut.alldev.allin.vo.bet.BetDisplayer +import java.util.Locale class BetStatusBottomSheetBetDisplayer( val openParticipateSheet: () -> Unit ) : BetDisplayer { val paddingValues = mutableStateOf(PaddingValues()) - @OptIn(ExperimentalMaterial3Api::class) @Composable - override fun DisplayYesNoBet(bet: YesNoBet) { + private fun DisplayBinaryBet( + betDetail: BetDetail, + response1: String, + response2: String, + response1Display: String = response1, + response2Display: String = response2 + ) { val safeBottomPadding = paddingValues.value.calculateBottomPadding() + val configuration = LocalConfiguration.current + val locale = remember { ConfigurationCompat.getLocales(configuration).get(0) ?: Locale.getDefault() } + + val response1Answer = remember { betDetail.getAnswerOfResponse(response1) } + val response2Answer = remember { betDetail.getAnswerOfResponse(response2) } Box(Modifier.padding(bottom = safeBottomPadding)) { Column { Column(Modifier.padding(horizontal = 20.dp)) { BetTitleHeader( - title = bet.phrase, - category = bet.theme, - creator = bet.creator, + title = betDetail.bet.phrase, + category = betDetail.bet.theme, + creator = betDetail.bet.creator, modifier = Modifier.fillMaxWidth() ) Spacer(modifier = Modifier.height(20.dp)) @@ -62,24 +83,24 @@ class BetStatusBottomSheetBetDisplayer( horizontalAlignment = Alignment.End ) { BetDateTimeRow( - label = stringResource(id = bet.betStatus.getDateStartLabelId()), - date = bet.endRegisterDate.formatToMediumDateNoYear(), - time = bet.endRegisterDate.formatToTime(), + label = stringResource(id = betDetail.bet.betStatus.getDateStartLabelId()), + date = betDetail.bet.endRegisterDate.formatToMediumDateNoYear(), + time = betDetail.bet.endRegisterDate.formatToTime(), modifier = Modifier.width(IntrinsicSize.Max) ) Spacer(modifier = Modifier.height(15.dp)) BetDateTimeRow( - label = stringResource(id = bet.betStatus.getDateEndLabelId()), - date = bet.endBetDate.formatToMediumDateNoYear(), - time = bet.endBetDate.formatToTime(), + label = stringResource(id = betDetail.bet.betStatus.getDateEndLabelId()), + date = betDetail.bet.endBetDate.formatToMediumDateNoYear(), + time = betDetail.bet.endBetDate.formatToTime(), modifier = Modifier.width(IntrinsicSize.Max) ) } Spacer(modifier = Modifier.height(20.dp)) } - if (bet.betStatus is BetStatus.Finished) { + if (betDetail.bet.betStatus is BetStatus.Finished) { BetStatusWinner( - answer = stringResource(id = R.string.Yes), + answer = response1Display, color = AllInTheme.colors.allInBlue, coinAmount = 442, username = "Imri", @@ -95,63 +116,150 @@ class BetStatusBottomSheetBetDisplayer( .padding(horizontal = 20.dp) ) { Spacer(modifier = Modifier.height(20.dp)) - YesNoStatBar(yesPercentage = .86f) + BinaryStatBar( + response1Percentage = remember { + val total = (response1Answer?.totalParticipants ?: 0) + (response2Answer?.totalParticipants ?: 0) + if (total == 0) .5f else (response1Answer?.totalParticipants ?: 0) / total.toFloat() + }, + response1 = response1Display, + response2 = response2Display + ) AllInDetailsDrawer { YesNoDetailsLine( icon = AllInTheme.icons.allCoins(), - yesText = "550", - noText = "330", + yesText = response1Answer?.totalStakes?.toString() ?: "0", + noText = response2Answer?.totalStakes?.toString() ?: "0" ) YesNoDetailsLine( icon = Icons.Filled.People, - yesText = "12", - noText = "5" + yesText = response1Answer?.totalParticipants?.toString() ?: "0", + noText = response2Answer?.totalParticipants?.toString() ?: "0" ) YesNoDetailsLine( icon = Icons.Filled.WorkspacePremium, - yesText = "45", - noText = "45" + yesText = response1Answer?.highestStake?.toString() ?: "0", + noText = response2Answer?.highestStake?.toString() ?: "0" ) YesNoDetailsLine( icon = Icons.Filled.EmojiEvents, - yesText = "x1.2", - noText = "x1.45" + yesText = "x${response1Answer?.odds?.formatToSimple(locale) ?: "1.00"}", + noText = "x${response2Answer?.odds?.formatToSimple(locale) ?: "1.00"}" ) } + + Text( + text = stringResource(id = R.string.bet_status_participants_list), + fontSize = 20.sp, + color = AllInTheme.themeColors.onMainSurface, + style = AllInTheme.typography.h1, + modifier = Modifier.padding(vertical = 36.dp) + ) + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + contentPadding = PaddingValues(horizontal = 13.dp, vertical = 8.dp), + modifier = Modifier.fillMaxHeight() + ) { + betDetail.userParticipation?.let { + item { + BetStatusParticipant( + username = it.username, + allCoinsAmount = it.stake + ) + HorizontalDivider( + color = AllInTheme.themeColors.border, + modifier = Modifier.padding(vertical = 8.dp, horizontal = 25.dp) + ) + } + } + items(betDetail.participations) { + if (it.username != betDetail.userParticipation?.username) { + BetStatusParticipant( + username = it.username, + allCoinsAmount = it.stake + ) + } + } + } } } - if (bet.betStatus !is BetStatus.Finished) { + if (betDetail.bet.betStatus !is BetStatus.Finished && betDetail.userParticipation == null) { RainbowButton( modifier = Modifier .align(Alignment.BottomCenter) .padding(horizontal = 7.dp), text = stringResource(id = R.string.Participate), - enabled = bet.betStatus == BetStatus.Waiting, + enabled = betDetail.bet.betStatus == BetStatus.Waiting, onClick = openParticipateSheet ) } } } + @OptIn(ExperimentalMaterial3Api::class) @Composable - override fun DisplayMatchBet(bet: MatchBet) { - Text("This is a MATCH BET") + override fun DisplayYesNoBet(betDetail: BetDetail) { + DisplayBinaryBet( + betDetail = betDetail, + response1 = YES_VALUE, + response2 = NO_VALUE, + response1Display = stringResource(id = R.string.Yes).uppercase(), + response2Display = stringResource(id = R.string.No).uppercase() + ) } @Composable - override fun DisplayCustomBet(bet: CustomBet) { + override fun DisplayMatchBet(betDetail: BetDetail) { + val bet = remember { betDetail.bet as MatchBet } + DisplayBinaryBet( + betDetail = betDetail, + response1 = bet.nameTeam1, + response2 = bet.nameTeam2 + ) + } + + @Composable + override fun DisplayCustomBet(betDetail: BetDetail) { Text("This is a CUSTOM BET") } } +@Composable +fun BetStatusParticipant( + username: String, + allCoinsAmount: Int +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(7.dp), + verticalAlignment = Alignment.CenterVertically + ) { + ProfilePicture(modifier = Modifier.size(25.dp)) + Text( + text = username, + fontWeight = FontWeight.Bold, + style = AllInTheme.typography.h2, + color = AllInTheme.themeColors.onMainSurface, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + AllInCoinCount( + amount = allCoinsAmount, + color = AllInTheme.colors.allInPurple + ) + } +} + @Preview @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable private fun BetStatusBottomSheetPreview( - @PreviewParameter(BetWithStatusPreviewProvider::class) bet: Bet + @PreviewParameter(BetDetailPreviewProvider::class) bet: BetDetail ) { AllInTheme { - val coins = remember { mutableIntStateOf(100) } - BetStatusBottomSheetBetDisplayer {}.DisplayBet(bet) + BetStatusBottomSheetBetDisplayer { + + }.DisplayBet(bet) } } \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainScreen.kt index 7f57f2e..fdd9642 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainScreen.kt @@ -67,7 +67,7 @@ fun MainScreen( var loading by remember { mainViewModel.loading } val currentUser = remember { mainViewModel.currentUserState } - val (selectedBet, setSelectedBet) = remember { mainViewModel.selectedBet } + val selectedBet by remember { mainViewModel.selectedBet } val (wonBet, setWonBet) = remember { mainViewModel.wonBet } val (statusVisibility, sheetBackVisibility, setStatusVisibility) = rememberBetStatusVisibilities() val (participateSheetVisibility, setParticipateSheetVisibility) = remember { @@ -152,7 +152,7 @@ fun MainScreen( AllInDrawerNavHost( navController = navController, selectBet = { bet, participate -> - setSelectedBet(bet) + mainViewModel.openBetDetail(bet) setParticipateSheetVisibility(participate) setStatusVisibility(true) }, @@ -182,11 +182,11 @@ fun MainScreen( sheetVisibility = statusVisibility.value, sheetBackVisibility = sheetBackVisibility.value, onDismiss = { setStatusVisibility(false) }, - bet = selectedBet, + betDetail = selectedBet, paddingValues = betStatusDisplayer.paddingValues.value, displayBet = { betStatusDisplayer.DisplayBet(it) }, userCoinAmount = mainViewModel.currentUserState.userCoins, - onParticipate = { mainViewModel.participateToBet(it) }, + onParticipate = { stake, response -> mainViewModel.participateToBet(stake, response) }, participateSheetVisibility = participateSheetVisibility, setParticipateSheetVisibility = setParticipateSheetVisibility ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt index aac1fcf..a666bef 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/main/MainViewModel.kt @@ -8,16 +8,15 @@ 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.data.model.bet.BetFinishedStatus -import fr.iut.alldev.allin.data.model.bet.BetStatus -import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.Participation +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail +import fr.iut.alldev.allin.data.repository.BetRepository import fr.iut.alldev.allin.di.AllInCurrentUser import fr.iut.alldev.allin.keystore.AllInKeystoreManager import fr.iut.alldev.allin.ui.core.snackbar.SnackbarType import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.time.ZonedDateTime import javax.inject.Inject class UserState(val user: User) { @@ -27,23 +26,26 @@ class UserState(val user: User) { @HiltViewModel class MainViewModel @Inject constructor( @AllInCurrentUser val currentUser: User, + private val betRepository: BetRepository, private val keystoreManager: AllInKeystoreManager ) : ViewModel() { var loading = mutableStateOf(false) val currentUserState = UserState(currentUser) - val selectedBet = mutableStateOf(null) + val selectedBet = mutableStateOf(null) val wonBet = mutableStateOf( - YesNoBet( - theme = "Theme", - phrase = "Phrase", - endRegisterDate = ZonedDateTime.now(), - endBetDate = ZonedDateTime.now(), - isPublic = true, - betStatus = BetStatus.Finished(BetFinishedStatus.WON), - creator = "creator" - ) + null + /* YesNoBet( + id = "1", + theme = "Theme", + phrase = "Phrase", + endRegisterDate = ZonedDateTime.now(), + endBetDate = ZonedDateTime.now(), + isPublic = true, + betStatus = BetStatus.Finished(BetFinishedStatus.WON), + creator = "creator" + )*/ ) val snackbarContent: MutableState by lazy { mutableStateOf(null) } @@ -51,6 +53,11 @@ class MainViewModel @Inject constructor( snackbarContent.value = content } + fun openBetDetail(bet: Bet) { + viewModelScope.launch { + selectedBet.value = betRepository.getBet(bet.id, keystoreManager.getToken() ?: "") + } + } fun deleteToken() { viewModelScope.launch { @@ -58,12 +65,20 @@ class MainViewModel @Inject constructor( } } - fun participateToBet(stake: Int) { + fun participateToBet(stake: Int, response: String) { viewModelScope.launch { withContext(Dispatchers.IO) { loading.value = true currentUserState.userCoins.intValue -= stake - Thread.sleep(1000) + selectedBet.value?.bet?.let { + val participation = Participation( + betId = it.id, + username = currentUser.username, + response = response, + stake = stake + ) + betRepository.participateToBet(participation, keystoreManager.getToken() ?: "") + } loading.value = false } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt new file mode 100644 index 0000000..154f04c --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetDetailPreviewProvider.kt @@ -0,0 +1,58 @@ +package fr.iut.alldev.allin.ui.preview + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import fr.iut.alldev.allin.data.model.bet.NO_VALUE +import fr.iut.alldev.allin.data.model.bet.Participation +import fr.iut.alldev.allin.data.model.bet.YES_VALUE +import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail + +class BetDetailPreviewProvider : PreviewParameterProvider { + override val values = BetWithStatusPreviewProvider().values.map { + BetDetail( + bet = it, + answers = listOf( + BetAnswerDetail( + response = YES_VALUE, + totalStakes = 300, + totalParticipants = 2, + highestStake = 200, + odds = 1.0f + ), + BetAnswerDetail( + response = NO_VALUE, + totalStakes = 150, + totalParticipants = 1, + highestStake = 150, + odds = 2.0f + ), + ), + participations = listOf( + Participation( + betId = it.id, + username = "User1", + response = YES_VALUE, + stake = 200 + ), + Participation( + betId = it.id, + username = "User2", + response = YES_VALUE, + stake = 100 + ), + Participation( + betId = it.id, + username = "MyUser", + response = NO_VALUE, + stake = 150 + ) + ), + userParticipation = Participation( + betId = it.id, + username = "MyUser", + response = NO_VALUE, + stake = 150 + ) + ) + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt index dabcded..3a97a59 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetPreviewProvider.kt @@ -12,6 +12,7 @@ import java.time.ZonedDateTime class BetPreviewProvider : PreviewParameterProvider { override val values = sequenceOf( YesNoBet( + id = "1", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), @@ -21,6 +22,7 @@ class BetPreviewProvider : PreviewParameterProvider { creator = "creator" ), MatchBet( + id = "2", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), @@ -32,6 +34,7 @@ class BetPreviewProvider : PreviewParameterProvider { nameTeam2 = "Climate Change" ), CustomBet( + id = "3", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt index fcc5adb..e5b3721 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/preview/BetWithStatusPreviewProvider.kt @@ -13,6 +13,7 @@ class BetWithStatusPreviewProvider : PreviewParameterProvider { override val values = BetStatus.entries.flatMap { status -> sequenceOf( YesNoBet( + id = "1", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), @@ -22,6 +23,7 @@ class BetWithStatusPreviewProvider : PreviewParameterProvider { creator = "creator" ), MatchBet( + id = "2", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), @@ -33,6 +35,7 @@ class BetWithStatusPreviewProvider : PreviewParameterProvider { nameTeam2 = "Climate Change" ), CustomBet( + id = "3", theme = "Theme", phrase = "Phrase", endRegisterDate = ZonedDateTime.now(), diff --git a/src/app/src/main/java/fr/iut/alldev/allin/utils/Tuples.kt b/src/app/src/main/java/fr/iut/alldev/allin/utils/Tuples.kt deleted file mode 100644 index 922ca6e..0000000 --- a/src/app/src/main/java/fr/iut/alldev/allin/utils/Tuples.kt +++ /dev/null @@ -1,12 +0,0 @@ -package fr.iut.alldev.allin.utils - -import java.io.Serializable - -data class Quadruple( - val first: A, - val second: B, - val third: C, - val fourth: D -) : Serializable { - override fun toString(): String = "($first, $second, $third, $fourth)" -} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt b/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt index be89c05..40b2cb8 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/vo/bet/BetDisplayer.kt @@ -1,27 +1,27 @@ package fr.iut.alldev.allin.vo.bet import androidx.compose.runtime.Composable -import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.MatchBet import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail interface BetDisplayer { @Composable - fun DisplayBet(bet: Bet){ - when(bet){ - is CustomBet -> DisplayCustomBet(bet) - is MatchBet -> DisplayMatchBet(bet) - is YesNoBet -> DisplayYesNoBet(bet) + fun DisplayBet(betDetail: BetDetail) { + when (betDetail.bet) { + is CustomBet -> DisplayCustomBet(betDetail) + is MatchBet -> DisplayMatchBet(betDetail) + is YesNoBet -> DisplayYesNoBet(betDetail) } } @Composable - fun DisplayYesNoBet(bet: YesNoBet) + fun DisplayYesNoBet(betDetail: BetDetail) @Composable - fun DisplayMatchBet(bet: MatchBet) + fun DisplayMatchBet(betDetail: BetDetail) @Composable - fun DisplayCustomBet(bet: CustomBet) + fun DisplayCustomBet(betDetail: BetDetail) } \ No newline at end of file diff --git a/src/app/src/main/res/values-fr/strings.xml b/src/app/src/main/res/values-fr/strings.xml index 0b953ca..0f1e299 100644 --- a/src/app/src/main/res/values-fr/strings.xml +++ b/src/app/src/main/res/values-fr/strings.xml @@ -118,6 +118,7 @@ En cours… En attente… Faites vos paris + Liste des participants En cours diff --git a/src/app/src/main/res/values/strings.xml b/src/app/src/main/res/values/strings.xml index f1c5ad9..328e981 100644 --- a/src/app/src/main/res/values/strings.xml +++ b/src/app/src/main/res/values/strings.xml @@ -118,6 +118,7 @@ In progress… Waiting… Place your bets + Participants Current diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt index 413113e..550c182 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/AllInApi.kt @@ -2,15 +2,22 @@ package fr.iut.alldev.allin.data.api import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.RequestBet +import fr.iut.alldev.allin.data.api.model.RequestParticipation import fr.iut.alldev.allin.data.api.model.RequestUser import fr.iut.alldev.allin.data.api.model.ResponseBet +import fr.iut.alldev.allin.data.api.model.ResponseBetDetail import fr.iut.alldev.allin.data.api.model.ResponseUser import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.POST +import retrofit2.http.Path interface AllInApi { + companion object { + fun String.formatBearerToken() = "Bearer $this" + } + @POST("users/login") suspend fun login(@Body body: CheckUser): ResponseUser @@ -25,4 +32,10 @@ interface AllInApi { @GET("bets/gets") suspend fun getAllBets(): List + + @GET("betdetail/get/{id}") + suspend fun getBet(@Header("Authorization") token: String, @Path("id") id: String): ResponseBetDetail + + @POST("participations/add") + suspend fun participateToBet(@Header("Authorization") token: String, @Body body: RequestParticipation) } \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt index 4b61b9b..f2b7f72 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/MockAllInApi.kt @@ -3,8 +3,12 @@ package fr.iut.alldev.allin.data.api import fr.iut.alldev.allin.data.api.interceptors.AllInAPIException import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.RequestBet +import fr.iut.alldev.allin.data.api.model.RequestParticipation import fr.iut.alldev.allin.data.api.model.RequestUser import fr.iut.alldev.allin.data.api.model.ResponseBet +import fr.iut.alldev.allin.data.api.model.ResponseBetAnswerDetail +import fr.iut.alldev.allin.data.api.model.ResponseBetDetail +import fr.iut.alldev.allin.data.api.model.ResponseParticipation import fr.iut.alldev.allin.data.api.model.ResponseUser import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE @@ -12,13 +16,30 @@ import java.time.ZonedDateTime import java.util.UUID class MockAllInApi : AllInApi { + + private fun getUserFromToken(token: String) = + mockUsers.find { it.first.token == token } + + private fun getAnswerDetails(bet: ResponseBet, participations: List): List { + return bet.response.map { response -> + val responseParticipations = participations.filter { it.answer == response } + ResponseBetAnswerDetail( + response = response, + totalStakes = responseParticipations.sumOf { it.stake }, + totalParticipants = responseParticipations.size, + highestStake = responseParticipations.maxOfOrNull { it.stake } ?: 0, + odds = if (participations.isEmpty()) 0.0f else responseParticipations.size / participations.size.toFloat() + ) + } + } + override suspend fun login(body: CheckUser): ResponseUser { - return users.find { it.first.username == body.login && it.second == body.password }?.first + return mockUsers.find { it.first.username == body.login && it.second == body.password }?.first ?: throw AllInAPIException("Invalid login/password.") } override suspend fun login(token: String): ResponseUser { - return users.find { it.first.token == token }?.first + return getUserFromToken(token)?.first ?: throw AllInAPIException("Invalid token") } @@ -27,10 +48,10 @@ class MockAllInApi : AllInApi { id = UUID.randomUUID().toString(), username = body.username, email = body.email, - nbCoins = body.nbCoins, - token = "${body.username} ${users.size}" + nbCoins = 500, + token = "${body.username} ${mockUsers.size}" ) to body.password - users.add(response) + mockUsers.add(response) return response.first } @@ -50,16 +71,138 @@ class MockAllInApi : AllInApi { } override suspend fun getAllBets(): List = mockBets.toList() + override suspend fun getBet(token: String, id: String): ResponseBetDetail { + val bet = mockBets.find { it.id == id } ?: throw AllInAPIException("Bet not found") + val user = getUserFromToken(token) ?: throw AllInAPIException("Invalid login/password.") + val betParticipations = mockParticipations.filter { it.betId == bet.id } + val userParticipation = betParticipations.find { it.username == user.first.username } + + return ResponseBetDetail( + bet = bet, + answers = getAnswerDetails(bet, betParticipations), + participations = betParticipations, + userParticipation = userParticipation + ) + } + + override suspend fun participateToBet(token: String, body: RequestParticipation) { + getUserFromToken(token)?.let { + mockParticipations.add( + ResponseParticipation( + id = "", + betId = body.betId, + username = it.first.username, + answer = body.answer, + stake = body.stake + + ) + ) + } ?: throw AllInAPIException("Invalid token") + } } -private val users = mutableListOf( +private val mockUsers = mutableListOf( ResponseUser( id = "UUID 1", username = "User 1", email = "john@doe.fr", nbCoins = 250, token = "token 1" - ) to "psswrd" + ) to "12345", + ResponseUser( + id = "UUID 2", + username = "User 2", + email = "john@doe.fr", + nbCoins = 250, + token = "token 2" + ) to "12345", + ResponseUser( + id = "UUID 3", + username = "User 3", + email = "john@doe.fr", + nbCoins = 250, + token = "token 3" + ) to "12345", + ResponseUser( + id = "UUID 4", + username = "User 4", + email = "john@doe.fr", + nbCoins = 250, + token = "token 4" + ) to "12345", + ResponseUser( + id = "UUID 5", + username = "User 5", + email = "john@doe.fr", + nbCoins = 250, + token = "token 5" + ) to "12345", + ResponseUser( + id = "UUID 6", + username = "User 6", + email = "john@doe.fr", + nbCoins = 250, + token = "token 6" + ) to "12345", + ResponseUser( + id = "UUID 7", + username = "User 7", + email = "john@doe.fr", + nbCoins = 250, + token = "token 7" + ) to "12345" +) + +private val mockParticipations = mutableListOf( + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[0].first.username, + answer = YES_VALUE, + stake = 200 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[1].first.username, + answer = NO_VALUE, + stake = 1500 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[2].first.username, + answer = YES_VALUE, + stake = 300 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[3].first.username, + answer = YES_VALUE, + stake = 25 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[4].first.username, + answer = NO_VALUE, + stake = 222 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[5].first.username, + answer = NO_VALUE, + stake = 222 + ), + ResponseParticipation( + id = "", + betId = "UUID1", + username = mockUsers[6].first.username, + answer = NO_VALUE, + stake = 222 + ) ) private val mockBets = mutableListOf( diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/interceptors/ErrorInterceptor.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/interceptors/ErrorInterceptor.kt index 16abb5a..ebbd8a7 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/interceptors/ErrorInterceptor.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/interceptors/ErrorInterceptor.kt @@ -14,14 +14,15 @@ class ErrorInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() val response = chain.proceed(request) - if(!response.isSuccessful){ + if (!response.isSuccessful) { when (response.code) { 404 -> throw AllInNotFoundException(response.message) 401 -> throw AllInUnauthorizedException(response.message) else -> throw AllInUnsuccessfulException(response.message) } } - if (response.body?.contentType()?.subtype != "json") { + + response.body?.contentType()?.subtype?.takeIf { it != "json" }?.let { throw AllInAPIException(response.message) } diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt index 4eca5f1..3610752 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiBet.kt @@ -7,7 +7,9 @@ import fr.iut.alldev.allin.data.model.bet.CustomBet import fr.iut.alldev.allin.data.model.bet.NO_VALUE import fr.iut.alldev.allin.data.model.bet.YES_VALUE import fr.iut.alldev.allin.data.model.bet.YesNoBet -import fr.iut.alldev.allin.data.serialization.SimpleDateSerializer +import fr.iut.alldev.allin.data.model.bet.vo.BetAnswerDetail +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail +import fr.iut.alldev.allin.data.serialization.ZonedDateTimeSerializer import kotlinx.serialization.Serializable import java.time.ZonedDateTime @@ -17,8 +19,8 @@ data class ResponseBet( val id: String?, val theme: String, val sentenceBet: String, - @Serializable(SimpleDateSerializer::class) val endRegistration: ZonedDateTime, - @Serializable(SimpleDateSerializer::class) var endBet: ZonedDateTime, + @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime, + @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime, var isPrivate: Boolean, var response: List, val createdBy: String @@ -26,6 +28,7 @@ data class ResponseBet( fun toBet(): Bet { if (response.toSet() == setOf(YES_VALUE, NO_VALUE)) { return YesNoBet( + id = id ?: "", theme = theme, phrase = sentenceBet, endRegisterDate = endRegistration, @@ -36,6 +39,7 @@ data class ResponseBet( ) } else { return CustomBet( + id = id ?: "", theme = theme, phrase = sentenceBet, endRegisterDate = endRegistration, @@ -52,10 +56,48 @@ data class ResponseBet( @Keep @Serializable data class RequestBet( + val id: String = "", val theme: String, val sentenceBet: String, - @Serializable(SimpleDateSerializer::class) val endRegistration: ZonedDateTime, - @Serializable(SimpleDateSerializer::class) var endBet: ZonedDateTime, + @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime, + @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime, var isPrivate: Boolean, var response: List ) + +@Keep +@Serializable +data class ResponseBetAnswerDetail( + val response: String, + val totalStakes: Int, + val totalParticipants: Int, + val highestStake: Int, + val odds: Float +) { + fun toAnswerDetail() = + BetAnswerDetail( + response = response, + totalStakes = totalStakes, + totalParticipants = totalParticipants, + highestStake = highestStake, + odds = odds + ) +} + +@Keep +@Serializable +data class ResponseBetDetail( + val bet: ResponseBet, + val answers: List, + val participations: List, + val userParticipation: ResponseParticipation? = null +) { + fun toBetDetail() = + BetDetail( + bet = bet.toBet(), + answers = answers.map { it.toAnswerDetail() }, + participations = participations.map { it.toParticipation() }, + userParticipation = userParticipation?.toParticipation() + + ) +} \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiParticipation.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiParticipation.kt new file mode 100644 index 0000000..488ca34 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiParticipation.kt @@ -0,0 +1,31 @@ +package fr.iut.alldev.allin.data.api.model + +import androidx.annotation.Keep +import fr.iut.alldev.allin.data.model.bet.Participation +import kotlinx.serialization.Serializable + +@Keep +@Serializable +data class ResponseParticipation( + val id: String, + val betId: String, + val username: String, + val answer: String, + val stake: Int +) { + fun toParticipation() = + Participation( + betId = betId, + username = username, + response = answer, + stake = stake + ) +} + +@Keep +@Serializable +data class RequestParticipation( + val betId: String, + val answer: String, + val stake: Int +) \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiUser.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiUser.kt index 79d1681..f6e021c 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiUser.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/api/model/ApiUser.kt @@ -9,24 +9,23 @@ import kotlinx.serialization.Serializable data class RequestUser( val username: String, val email: String, - val password: String, - var nbCoins: Int, + val password: String ) @Keep @Serializable data class ResponseUser( - val id: String, + val id: String = "", val username: String, val email: String, var nbCoins: Int, - var token: String? = null, + var token: String? = null ) { fun toUser() = User( id = id, username = username, email = email, - coins = nbCoins + coins = nbCoins.toInt() ) } diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/di/ApiModule.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/di/ApiModule.kt index 50c387a..9072cd8 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/di/ApiModule.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/di/ApiModule.kt @@ -11,7 +11,7 @@ import okhttp3.HttpUrl import okhttp3.OkHttpClient import javax.inject.Singleton -const val mock = true +const val mock = false @Module @InstallIn(SingletonComponent::class) diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/di/NetworkModule.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/di/NetworkModule.kt index 0c26aae..981005a 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/di/NetworkModule.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/di/NetworkModule.kt @@ -17,7 +17,7 @@ import javax.inject.Qualifier internal val json by lazy { Json { ignoreUnknownKeys = true - encodeDefaults = false + encodeDefaults = true } } diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/User.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/User.kt index 5a4e882..21d650b 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/User.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/User.kt @@ -1,8 +1,8 @@ package fr.iut.alldev.allin.data.model data class User( - val id : String, - val username : String, - val email : String, - val coins : Int + val id: String, + val username: String, + val email: String, + val coins: Int ) \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Bet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Bet.kt index cc1910a..1f9cc17 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Bet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Bet.kt @@ -4,7 +4,7 @@ import fr.iut.alldev.allin.data.api.model.RequestBet import java.time.ZonedDateTime sealed class Bet( - open val id: String? = null, + open val id: String, open val creator: String, open val theme: String, open val phrase: String, @@ -16,6 +16,7 @@ sealed class Bet( abstract fun getResponses(): List fun toRequestBet(): RequestBet { return RequestBet( + id = "", theme = theme, sentenceBet = phrase, endRegistration = endRegisterDate, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt index c194a30..8df4afb 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/BetFactory.kt @@ -5,6 +5,7 @@ import java.time.ZonedDateTime class BetFactory { companion object { fun createBet( + id: String, betType: BetType, creator: String, theme: String, @@ -20,6 +21,7 @@ class BetFactory { when (betType) { BetType.YES_NO -> { YesNoBet( + id = id, theme = theme, creator = creator, phrase = phrase, @@ -32,6 +34,7 @@ class BetFactory { BetType.MATCH -> { MatchBet( + id = id, theme = theme, creator = creator, phrase = phrase, @@ -47,6 +50,7 @@ class BetFactory { BetType.CUSTOM -> { CustomBet( + id = id, theme = theme, creator = creator, phrase = phrase, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/CustomBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/CustomBet.kt index 8af1e5e..a252e51 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/CustomBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/CustomBet.kt @@ -3,7 +3,7 @@ package fr.iut.alldev.allin.data.model.bet import java.time.ZonedDateTime data class CustomBet( - override val id: String? = null, + override val id: String, override val creator: String, override val theme: String, override val phrase: String, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/MatchBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/MatchBet.kt index 4e96674..03a829e 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/MatchBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/MatchBet.kt @@ -3,7 +3,7 @@ package fr.iut.alldev.allin.data.model.bet import java.time.ZonedDateTime data class MatchBet( - override val id: String? = null, + override val id: String, override val creator: String, override val theme: String, override val phrase: String, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Participation.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Participation.kt new file mode 100644 index 0000000..e2f15b1 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/Participation.kt @@ -0,0 +1,17 @@ +package fr.iut.alldev.allin.data.model.bet + +import fr.iut.alldev.allin.data.api.model.RequestParticipation + +data class Participation( + val betId: String, + val username: String, + val response: String, + val stake: Int +) { + fun toRequestParticipation() = + RequestParticipation( + betId = betId, + answer = response, + stake = stake + ) +} \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt index 2c57d4e..5e28f06 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/YesNoBet.kt @@ -6,7 +6,7 @@ const val YES_VALUE = "Yes" const val NO_VALUE = "No" data class YesNoBet( - override val id: String? = null, + override val id: String, override val creator: String, override val theme: String, override val phrase: String, diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetAnswerDetail.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetAnswerDetail.kt new file mode 100644 index 0000000..382a4b3 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetAnswerDetail.kt @@ -0,0 +1,9 @@ +package fr.iut.alldev.allin.data.model.bet.vo + +data class BetAnswerDetail( + val response: String, + val totalStakes: Int, + val totalParticipants: Int, + val highestStake: Int, + val odds: Float +) \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetDetail.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetDetail.kt new file mode 100644 index 0000000..a77f6dd --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetDetail.kt @@ -0,0 +1,14 @@ +package fr.iut.alldev.allin.data.model.bet.vo + +import fr.iut.alldev.allin.data.model.bet.Bet +import fr.iut.alldev.allin.data.model.bet.Participation + +data class BetDetail( + val bet: Bet, + val answers: List, + val participations: List, + val userParticipation: Participation? +) { + fun getAnswerOfResponse(response: String) = + answers.find { it.response == response } +} \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetResult.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetResult.kt new file mode 100644 index 0000000..407bc4e --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/bet/vo/BetResult.kt @@ -0,0 +1,10 @@ +package fr.iut.alldev.allin.data.model.bet.vo + +import fr.iut.alldev.allin.data.model.bet.Bet +import fr.iut.alldev.allin.data.model.bet.Participation + +data class BetResult( + val bet: Bet, + val participations: List, + val answerDetail: BetAnswerDetail +) \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/BetRepository.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/BetRepository.kt index bec1d9c..ed4bcd8 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/BetRepository.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/BetRepository.kt @@ -1,11 +1,15 @@ package fr.iut.alldev.allin.data.repository import fr.iut.alldev.allin.data.model.bet.Bet +import fr.iut.alldev.allin.data.model.bet.Participation +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import kotlinx.coroutines.flow.Flow abstract class BetRepository { abstract suspend fun createBet(bet: Bet, token: String) abstract suspend fun getHistory(): Flow> abstract suspend fun getCurrentBets(): Flow> + abstract suspend fun getBet(id: String, token: String): BetDetail + abstract suspend fun participateToBet(participation: Participation, token: String) abstract suspend fun getAllBets(): Flow> } \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt index 338b8aa..b9a22ac 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/UserRepository.kt @@ -4,16 +4,9 @@ import fr.iut.alldev.allin.data.model.User abstract class UserRepository { lateinit var currentUser: User - abstract suspend fun login( - username: String, - password: String - ): String? + abstract suspend fun login(username: String, password: String): String? abstract suspend fun login(token: String): String? - abstract suspend fun register( - username: String, - email: String, - password: String - ): String? + abstract suspend fun register(username: String, email: String, password: String): String? } \ No newline at end of file diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/BetRepositoryImpl.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/BetRepositoryImpl.kt index 1c21c87..7748092 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/BetRepositoryImpl.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/BetRepositoryImpl.kt @@ -1,10 +1,13 @@ package fr.iut.alldev.allin.data.repository.impl import fr.iut.alldev.allin.data.api.AllInApi +import fr.iut.alldev.allin.data.api.AllInApi.Companion.formatBearerToken import fr.iut.alldev.allin.data.model.bet.Bet import fr.iut.alldev.allin.data.model.bet.BetFinishedStatus import fr.iut.alldev.allin.data.model.bet.BetStatus +import fr.iut.alldev.allin.data.model.bet.Participation import fr.iut.alldev.allin.data.model.bet.YesNoBet +import fr.iut.alldev.allin.data.model.bet.vo.BetDetail import fr.iut.alldev.allin.data.repository.BetRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf @@ -16,7 +19,7 @@ class BetRepositoryImpl @Inject constructor( ) : BetRepository() { override suspend fun createBet(bet: Bet, token: String) { api.createBet( - token = token, + token = token.formatBearerToken(), body = bet.toRequestBet() ) } @@ -25,6 +28,7 @@ class BetRepositoryImpl @Inject constructor( return flowOf( listOf( YesNoBet( + id = "1", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 1", @@ -34,6 +38,7 @@ class BetRepositoryImpl @Inject constructor( betStatus = BetStatus.Finished(BetFinishedStatus.WON) ), YesNoBet( + id = "2", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 2", @@ -43,6 +48,7 @@ class BetRepositoryImpl @Inject constructor( betStatus = BetStatus.Finished(BetFinishedStatus.LOST) ), YesNoBet( + id = "3", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 3", @@ -60,6 +66,7 @@ class BetRepositoryImpl @Inject constructor( return flowOf( listOf( YesNoBet( + id = "1", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 1", @@ -69,6 +76,7 @@ class BetRepositoryImpl @Inject constructor( betStatus = BetStatus.InProgress ), YesNoBet( + id = "2", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 2", @@ -78,6 +86,7 @@ class BetRepositoryImpl @Inject constructor( betStatus = BetStatus.InProgress ), YesNoBet( + id = "3", creator = "Lucas", theme = "Theme", phrase = "Bet phrase 3", @@ -90,6 +99,17 @@ class BetRepositoryImpl @Inject constructor( ) } + override suspend fun getBet(id: String, token: String): BetDetail { + return api.getBet( + token = token.formatBearerToken(), + id = id + ).toBetDetail() + } + + override suspend fun participateToBet(participation: Participation, token: String) { + api.participateToBet(token = token.formatBearerToken(), body = participation.toRequestParticipation()) + } + override suspend fun getAllBets(): Flow> { return flowOf( api.getAllBets().map { it.toBet() } diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt index 54f3889..6c23cd8 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/repository/impl/UserRepositoryImpl.kt @@ -1,6 +1,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.Companion.formatBearerToken import fr.iut.alldev.allin.data.api.model.CheckUser import fr.iut.alldev.allin.data.api.model.RequestUser import fr.iut.alldev.allin.data.repository.UserRepository @@ -22,7 +23,7 @@ class UserRepositoryImpl @Inject constructor( } override suspend fun login(token: String): String? { - val response = api.login(token = "Bearer $token") + val response = api.login(token = token.formatBearerToken()) currentUser = response.toUser() return response.token } @@ -33,8 +34,7 @@ class UserRepositoryImpl @Inject constructor( RequestUser( username = username, email = email, - password = password, - nbCoins = 0 + password = password ) ) currentUser = response.toUser() diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/serialization/ZonedDateTimeSerializer.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/serialization/ZonedDateTimeSerializer.kt index 5810189..ae4742b 100644 --- a/src/data/src/main/java/fr/iut/alldev/allin/data/serialization/ZonedDateTimeSerializer.kt +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/serialization/ZonedDateTimeSerializer.kt @@ -6,39 +6,22 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import java.time.Instant -import java.time.LocalDate -import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter object ZonedDateTimeSerializer : KSerializer { + private val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss Z") + override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.LONG) + PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: ZonedDateTime) { - encoder.encodeLong(value.toEpochSecond()) + encoder.encodeString(formatter.format(value)) } override fun deserialize(decoder: Decoder): ZonedDateTime { - val epoch = decoder.decodeLong() - return ZonedDateTime.ofInstant(Instant.ofEpochSecond(epoch), ZoneId.systemDefault()) + val dateString = decoder.decodeString() + return ZonedDateTime.parse(dateString, formatter) } } -class SimpleDateSerializer : KSerializer { - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING) - - private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - - override fun deserialize(decoder: Decoder): ZonedDateTime { - val date = LocalDate.parse(decoder.decodeString(), formatter) - return date.atStartOfDay(ZoneId.systemDefault()) - } - - override fun serialize(encoder: Encoder, value: ZonedDateTime) { - val dateString = formatter.format(value) - encoder.encodeString(dateString) - } -}