diff --git a/src/app/build.gradle b/src/app/build.gradle index acdc3c4..dcd6d53 100644 --- a/src/app/build.gradle +++ b/src/app/build.gradle @@ -55,6 +55,7 @@ dependencies { implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.compose.material3:material3:1.2.0-alpha08' implementation "androidx.navigation:navigation-compose:2.7.3" + implementation project(path: ':data') testImplementation 'junit:junit:4.13.2' implementation 'androidx.compose.material:material-icons-core' implementation 'androidx.compose.material:material-icons-extended' diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ext/BetTypeExt.kt b/src/app/src/main/java/fr/iut/alldev/allin/ext/BetTypeExt.kt new file mode 100644 index 0000000..19afd9a --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ext/BetTypeExt.kt @@ -0,0 +1,29 @@ +package fr.iut.alldev.allin.ext + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.HelpOutline +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.SportsSoccer +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import fr.iut.alldev.allin.R +import fr.iut.alldev.allin.data.model.BetType + +@Composable +fun BetType.getTitle(): String { + return when (this) { + BetType.YES_NO -> stringResource(id = R.string.yes_no) + BetType.MATCH -> stringResource(id = R.string.sport_match) + BetType.CUSTOM -> stringResource(id = R.string.custom_answers) + } +} + +@Composable +fun BetType.getIcon(): ImageVector { + return when (this) { + BetType.YES_NO -> Icons.AutoMirrored.Default.HelpOutline + BetType.MATCH -> Icons.Default.SportsSoccer + BetType.CUSTOM -> Icons.Default.Edit + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/BetCreationScreen.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/BetCreationScreen.kt index a429869..1a2fe70 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/BetCreationScreen.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/BetCreationScreen.kt @@ -3,23 +3,28 @@ package fr.iut.alldev.allin.ui.betcreation import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import fr.iut.alldev.allin.R +import fr.iut.alldev.allin.data.model.BetType +import fr.iut.alldev.allin.ext.getIcon +import fr.iut.alldev.allin.ext.getTitle import fr.iut.alldev.allin.ui.betcreation.tabs.BetCreationScreenAnswerTab import fr.iut.alldev.allin.ui.betcreation.tabs.BetCreationScreenQuestionTab import fr.iut.alldev.allin.ui.core.AllInSections import fr.iut.alldev.allin.ui.core.RainbowButton import fr.iut.alldev.allin.ui.core.SectionElement +import fr.iut.alldev.allin.ui.core.SelectionElement @Composable fun BetCreationScreen( ) { - var theme by remember{ mutableStateOf("") } @@ -29,15 +34,43 @@ fun BetCreationScreen( var isPublic by remember{ mutableStateOf(true) } + + val betTypes = remember { + BetType.values().toList() + } + + val selectedFriends = remember { + mutableListOf() + } + + val elements = betTypes.map { + SelectionElement( + it.getTitle(), + it.getIcon() + ) + } + + + var selected by remember { + mutableStateOf(elements[0]) + } + + val selectedBetType by remember { + derivedStateOf { + betTypes[elements.indexOf(selected)] + } + } + Box( Modifier .fillMaxSize() - .padding(20.dp) + .padding(top = 20.dp) ) { AllInSections( modifier = Modifier .align(Alignment.TopCenter) - .fillMaxSize(), + .fillMaxSize() + .padding(bottom = 90.dp), sections = listOf( SectionElement(stringResource(id = R.string.Question)){ BetCreationScreenQuestionTab( @@ -46,11 +79,25 @@ fun BetCreationScreen( betPhrase = phrase, setBetPhrase = { phrase = it }, betTheme = theme, - setBetTheme = { theme = it } + setBetTheme = { theme = it }, + nbFriends = 42, + selectedFriends = selectedFriends, + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(vertical = 12.dp, horizontal = 20.dp) ) }, SectionElement(stringResource(id = R.string.Answer)){ - BetCreationScreenAnswerTab() + BetCreationScreenAnswerTab( + selectedBetType = selectedBetType, + selected = selected, + setSelected = { selected = it }, + elements = elements, + modifier = Modifier + .fillMaxSize() + .padding(vertical = 12.dp, horizontal = 20.dp) + ) } ) ) @@ -58,7 +105,8 @@ fun BetCreationScreen( text = stringResource(id = R.string.Publish), modifier = Modifier .align(Alignment.BottomCenter) - .padding(bottom = 14.dp), + .padding(bottom = 14.dp) + .padding(horizontal = 20.dp), onClick = { } ) diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenBottomText.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenBottomText.kt index fc214ea..6202ba2 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenBottomText.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenBottomText.kt @@ -1,10 +1,12 @@ package fr.iut.alldev.allin.ui.betcreation.components +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import fr.iut.alldev.allin.ui.theme.AllInTheme @@ -17,8 +19,9 @@ fun BetCreationScreenBottomText( text = text, color = AllInTheme.colors.allIn_Purple, fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, style = AllInTheme.typography.h2, - modifier = modifier.alpha(.5f) + modifier = modifier.fillMaxWidth().alpha(.5f) ) } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenFriendLine.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenFriendLine.kt new file mode 100644 index 0000000..9b0a346 --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/components/BetCreationScreenFriendLine.kt @@ -0,0 +1,86 @@ +package fr.iut.alldev.allin.ui.betcreation.components + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.unit.dp +import fr.iut.alldev.allin.ui.core.AllInCoinCount +import fr.iut.alldev.allin.ui.core.AllInRadioButton +import fr.iut.alldev.allin.ui.core.ProfilePicture +import fr.iut.alldev.allin.ui.theme.AllInTheme + +@Composable +fun BetCreationScreenFriendLine( + username: String, + allCoinsAmount: Int, + isSelected: Boolean, + onClick: ()->Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .background( + if (isSelected) AllInTheme.colors.allIn_Purple.copy(alpha = .13f) + else AllInTheme.themeColors.background + ) + .padding(15.dp), + horizontalArrangement = Arrangement.spacedBy(7.dp), + verticalAlignment = Alignment.CenterVertically + ) { + AllInRadioButton( + checked = isSelected, + modifier = Modifier.padding(end = 7.dp) + ) + ProfilePicture(modifier = Modifier.size(25.dp)) + Text( + text = username, + fontWeight = FontWeight.Bold, + style = AllInTheme.typography.h2, + color = AllInTheme.themeColors.on_main_surface, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + AllInCoinCount( + amount = allCoinsAmount, + color = AllInTheme.colors.allIn_Purple + ) + } +} + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun BetCreationScreenFriendLinePreview() { + AllInTheme { + BetCreationScreenFriendLine( + username = "David", + allCoinsAmount = 542, + isSelected = false) { + + } + } +} + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun BetCreationScreenFriendLineSelectedPreview() { + AllInTheme { + BetCreationScreenFriendLine( + username = "David", + allCoinsAmount = 542, + isSelected = true) { + + } + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/tabs/BetCreationScreenAnswerTab.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/tabs/BetCreationScreenAnswerTab.kt index 27ad1f2..aecee0c 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/tabs/BetCreationScreenAnswerTab.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/betcreation/tabs/BetCreationScreenAnswerTab.kt @@ -1,30 +1,54 @@ package fr.iut.alldev.allin.ui.betcreation.tabs -import android.util.Log -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.QuestionAnswer -import androidx.compose.runtime.Composable +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import fr.iut.alldev.allin.R -import fr.iut.alldev.allin.ui.core.AllInTextAndIcon +import fr.iut.alldev.allin.data.model.BetType +import fr.iut.alldev.allin.ext.getTitle +import fr.iut.alldev.allin.ui.betcreation.components.BetCreationScreenBottomText +import fr.iut.alldev.allin.ui.core.AllInSelectionBox +import fr.iut.alldev.allin.ui.core.SelectionElement @Composable -fun BetCreationScreenAnswerTab() { - Column( - Modifier - .fillMaxSize() - .padding(20.dp) - ) { - AllInTextAndIcon( - text = stringResource(id = R.string.Answer), - icon = Icons.Outlined.QuestionAnswer - ){ - Log.d("ALLINNN", "AAAA") +fun BetCreationScreenAnswerTab( + modifier: Modifier = Modifier, + selected: SelectionElement, + selectedBetType: BetType, + setSelected: (SelectionElement)->Unit, + elements: List +) { + var isOpen by remember{ + mutableStateOf(false) + } + + Column(modifier) { + AllInSelectionBox( + isOpen = isOpen, + setIsOpen = { isOpen = it }, + selected = selected, + setSelected = setSelected, + elements = elements + ) + Spacer(modifier = Modifier.height(26.dp)) + when(selectedBetType){ + BetType.YES_NO -> { + Column( + modifier = Modifier.padding(vertical = 20.dp), + verticalArrangement = Arrangement.spacedBy(17.dp) + ) { + BetCreationScreenBottomText(text = stringResource(id = R.string.yes_no_bottom_text_1)) + BetCreationScreenBottomText(text = stringResource(id = R.string.yes_no_bottom_text_2)) + } + } + BetType.MATCH -> { + BetCreationScreenBottomText(text = selectedBetType.getTitle()) + } + BetType.CUSTOM -> { + BetCreationScreenBottomText(text = selectedBetType.getTitle()) + } } } } \ No newline at end of file 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 af16752..855e0c5 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 @@ -2,11 +2,13 @@ package fr.iut.alldev.allin.ui.betcreation.tabs import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Public +import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -14,7 +16,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import fr.iut.alldev.allin.R import fr.iut.alldev.allin.ui.betcreation.components.BetCreationScreenBottomText +import fr.iut.alldev.allin.ui.betcreation.components.BetCreationScreenFriendLine import fr.iut.alldev.allin.ui.core.AllInIconChip +import fr.iut.alldev.allin.ui.core.AllInRetractableCard import fr.iut.alldev.allin.ui.core.AllInTextAndIcon import fr.iut.alldev.allin.ui.core.AllInTextField import fr.iut.alldev.allin.ui.theme.AllInTheme @@ -22,19 +26,18 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme @OptIn(ExperimentalFoundationApi::class) @Composable fun BetCreationScreenQuestionTab( + modifier: Modifier = Modifier, + nbFriends: Int, betTheme: String, setBetTheme: (String)->Unit, betPhrase: String, setBetPhrase: (String)->Unit, isPublic: Boolean, - setIsPublic: (Boolean)->Unit + setIsPublic: (Boolean)->Unit, + selectedFriends: MutableList ) { val bringIntoViewRequester = remember { BringIntoViewRequester() } - Column( - Modifier - .fillMaxSize() - .padding(20.dp) - ){ + Column(modifier){ AllInTextAndIcon( text = stringResource(id = R.string.Theme), icon = Icons.AutoMirrored.Outlined.HelpOutline, @@ -79,6 +82,7 @@ fun BetCreationScreenQuestionTab( onClick = {} ) Row( + modifier = Modifier.padding(bottom = 10.dp), horizontalArrangement = Arrangement.spacedBy(8.dp) ){ AllInIconChip( @@ -99,17 +103,71 @@ fun BetCreationScreenQuestionTab( ) } - Spacer(modifier = Modifier.height(52.dp)) Column( verticalArrangement = Arrangement.spacedBy(17.dp) ) { + var isOpen by remember{ + mutableStateOf(false) + } + if(isPublic){ - BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_1)) - BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_2)) + Column( + modifier = Modifier.padding(vertical = 20.dp), + verticalArrangement = Arrangement.spacedBy(17.dp) + ) { + BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_1)) + BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_2)) + } }else{ - BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_1)) - BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_2)) - BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_3)) + AllInRetractableCard( + text = stringResource( + id = R.string.n_friends_available, + nbFriends, + nbFriends + ), + borderWidth = 1.dp, + boldText = nbFriends.toString(), + isOpen = isOpen, + setIsOpen = { isOpen = it } + ) { + LazyColumn( + modifier = Modifier.height(172.dp) + ){ + items(nbFriends){ + val isSelected = remember{ + selectedFriends.contains(it) + } + + var wasClicked by remember{ + mutableStateOf(isSelected) + } + + if(it!=0){ + HorizontalDivider(color = AllInTheme.themeColors.border) + } + BetCreationScreenFriendLine( + username = "Dave", + allCoinsAmount = 542, + isSelected = wasClicked + ) { + wasClicked = ! wasClicked + if (isSelected) { + selectedFriends.remove(it) + } else { + selectedFriends.add(it) + } + } + } + } + } + Column( + modifier = Modifier.padding(vertical = 20.dp), + verticalArrangement = Arrangement.spacedBy(17.dp) + ) { + BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_1)) + BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_2)) + BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_3)) + } } } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInCoinCount.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInCoinCount.kt new file mode 100644 index 0000000..afbdead --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInCoinCount.kt @@ -0,0 +1,56 @@ +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 +) { + 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 + ) + } +} + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun AllInCoinCountPreview() { + AllInTheme { + AllInCoinCount(amount = 542, color = AllInTheme.colors.allIn_Purple) + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRadioButton.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRadioButton.kt new file mode 100644 index 0000000..6697a6d --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRadioButton.kt @@ -0,0 +1,48 @@ +package fr.iut.alldev.allin.ui.core + +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +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.theme.AllInTheme + +@Composable +fun AllInRadioButton( + modifier: Modifier = Modifier, + checked: Boolean, + unCheckedColor: Color = Color.Transparent +) { + AllInCard( + radius = 100.dp, + borderColor = AllInTheme.colors.allIn_Mint, + borderWidth = if(!checked) 1.dp else null, + backgroundColor = if (checked) AllInTheme.colors.allIn_Purple else unCheckedColor, + modifier = modifier.size(12.dp) + ){} +} + +@Preview +@Composable +private fun AllInRadioButtonNotCheckedPreview() { + AllInTheme { + AllInRadioButton(checked = false) + } +} + +@Preview +@Composable +private fun AllInRadioButtonNotCheckedFilledPreview() { + AllInTheme { + AllInRadioButton(checked = false, unCheckedColor = AllInTheme.colors.allIn_Mint) + } +} + +@Preview +@Composable +private fun AllInRadioButtonCheckedPreview() { + AllInTheme { + AllInRadioButton(checked = true) + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRetractableCard.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRetractableCard.kt new file mode 100644 index 0000000..b05e419 --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInRetractableCard.kt @@ -0,0 +1,80 @@ +package fr.iut.alldev.allin.ui.core + +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.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.font.FontWeight +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 + +@Composable +fun AllInRetractableCard( + modifier: Modifier = Modifier, + text: String, + boldText: String = "", + isOpen: Boolean, + setIsOpen: (Boolean)->Unit, + borderWidth: Dp? = null, + interactionSource: MutableInteractionSource = MutableInteractionSource(), + content: @Composable ()->Unit +) { + AllInCard( + modifier = modifier, + borderWidth = borderWidth, + borderColor = AllInTheme.colors.allIn_Purple.copy(.5f) + ){ + Column( + Modifier.animateContentSize() + ) { + Row( + modifier = Modifier + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = { setIsOpen(!isOpen) } + ) + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(7.dp) + ) { + HighlightedText( + text = text, + query = boldText, + highlightStyle = SpanStyle( + fontWeight = FontWeight.Bold, + color = AllInTheme.themeColors.on_main_surface, + fontStyle = AllInTheme.typography.h2.fontStyle + ), + color = AllInTheme.themeColors.on_background_2, + style = AllInTheme.typography.r, + fontSize = 16.sp, + modifier = Modifier.weight(1f) + ) + Icon( + imageVector = with(Icons.Default){ + if(isOpen) ExpandLess else ExpandMore + }, + contentDescription = null, + tint = AllInTheme.colors.allIn_Purple, + modifier = Modifier.size(30.dp) + ) + } + if(isOpen){ + HorizontalDivider(color = AllInTheme.themeColors.border) + content() + } + } + } +} \ No newline at end of file diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSections.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSections.kt index 67ea51a..61a047f 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSections.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSections.kt @@ -1,36 +1,28 @@ package fr.iut.alldev.allin.ui.core import android.content.res.Configuration -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.spring import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.onSizeChanged -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import fr.iut.alldev.allin.ui.theme.AllInTheme +import kotlinx.coroutines.launch class SectionElement( val text: String, val content: @Composable ()->Unit ) -enum class DragAnchors(val fraction: Float) { - Start(-2f), - Center(0f), - End(2f), -} - @OptIn(ExperimentalFoundationApi::class) @Composable fun AllInSections( @@ -38,97 +30,31 @@ fun AllInSections( interSectionsPadding: Dp = 56.dp, modifier: Modifier = Modifier ) { - var selected by remember { - mutableStateOf(sections.firstOrNull()) - } - var wasSwiped by remember{ - mutableStateOf(false) - } - - val density = LocalDensity.current - val draggableState = remember { - AnchoredDraggableState( - initialValue = DragAnchors.Center, - positionalThreshold = { distance: Float -> distance * .5f }, - velocityThreshold = { with(density) { 50.dp.toPx() } }, - animationSpec = spring( - dampingRatio = 0.66f, - stiffness = Spring.StiffnessMediumLow, - ), - ){ - val idx = sections.indexOf(selected) - val add = when(it.fraction){ - DragAnchors.End.fraction-> { - -1 - } - DragAnchors.Start.fraction-> { - 1 - } - else -> 0 - } - selected=sections.getOrElse(idx+add){ - sections[idx] - } - if(selected!=sections[idx]){ - wasSwiped=true - } - false - } - } + val pagerState = rememberPagerState(pageCount = { + sections.size + }) + val scope = rememberCoroutineScope() Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally - ) { + ){ LazyRow( - horizontalArrangement = Arrangement.spacedBy(interSectionsPadding) - ) { - items(sections) { section -> - AllInSectionButton( - text = section.text, - isSelected = selected == section, - onClick = { selected = section } - ) - } - } - - Box( - Modifier - .wrapContentSize() - .anchoredDraggable(draggableState, Orientation.Horizontal) - .onSizeChanged { layoutSize -> - val dragEndPoint = layoutSize.width - draggableState.updateAnchors( - DraggableAnchors { - DragAnchors - .values() - .forEach { anchor -> - anchor at dragEndPoint * anchor.fraction - } + horizontalArrangement = Arrangement.spacedBy(interSectionsPadding) + ) { + itemsIndexed(sections) { index, section -> + AllInSectionButton( + text = section.text, + isSelected = index == pagerState.currentPage, + onClick = { + scope.launch { + pagerState.animateScrollToPage(index) + } } ) - }, - ){ - Box( - Modifier - .wrapContentSize() - .offset { - val offset = - if ( - wasSwiped - ) { - if (!draggableState.isAnimationRunning) { - wasSwiped = false - } - -draggableState.offset.toInt() - - } else { - draggableState.offset.toInt() - } - IntOffset(x = offset, y = 0) - } - ){ - selected?.content?.let { it() } + } } + HorizontalPager(state = pagerState) { page -> + sections[page].content() } } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSelectionBox.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSelectionBox.kt new file mode 100644 index 0000000..0611032 --- /dev/null +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/AllInSelectionBox.kt @@ -0,0 +1,156 @@ +package fr.iut.alldev.allin.ui.core + +import android.content.res.Configuration +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.automirrored.filled.HelpOutline +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import fr.iut.alldev.allin.ui.theme.AllInTheme + + +class SelectionElement( + val text: String, + val iconVector: ImageVector +) + +@Composable +fun AllInSelectionLine( + text: String, + iconVector: ImageVector, + modifier: Modifier = Modifier, + onClick: ()->Unit, + trailingIcon: ImageVector? = null, + interactionSource: MutableInteractionSource +){ + Row( + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick + ) + .padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(7.dp) + ) { + Icon( + imageVector = iconVector, + contentDescription = null, + tint = AllInTheme.colors.allIn_Purple, + modifier = Modifier.size(20.dp) + ) + Text( + text = text, + color = AllInTheme.colors.allIn_Purple, + style = AllInTheme.typography.h2, + fontWeight = FontWeight.Bold, + modifier = Modifier.weight(1f) + ) + trailingIcon?.let { + Icon( + imageVector = trailingIcon, + contentDescription = null, + tint = AllInTheme.colors.allIn_Purple, + modifier = Modifier + .size(30.dp) + ) + } + } +} + + +@Composable +fun AllInSelectionBox( + modifier: Modifier = Modifier, + isOpen: Boolean, + setIsOpen: (Boolean)->Unit, + selected: SelectionElement, + setSelected: (SelectionElement)->Unit, + elements: List +) { + val interactionSource = remember { MutableInteractionSource() } + AllInCard(modifier){ + Column( + Modifier.animateContentSize() + ) { + AllInSelectionLine( + text = selected.text, + iconVector = selected.iconVector, + onClick = { setIsOpen(!isOpen) }, + interactionSource = interactionSource, + trailingIcon = with(Icons.Default){ + if(isOpen) ExpandLess else ExpandMore + } + ) + if(isOpen){ + HorizontalDivider(color = AllInTheme.themeColors.border) + elements.filter { it != selected }.forEach{ + element -> + AllInSelectionLine( + text = element.text, + iconVector = element.iconVector, + interactionSource = interactionSource, + onClick = { + setSelected(element) + setIsOpen(false) + } + ) + } + } + } + } +} + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun AllInSelectionBoxClosedPreview() { + AllInTheme { + val elements = listOf( + SelectionElement("Oui/Non", Icons.AutoMirrored.Default.HelpOutline), + SelectionElement("Sport", Icons.Default.SportsFootball), + SelectionElement("Perso", Icons.Default.PinEnd) + ) + AllInSelectionBox( + isOpen = false, + selected = elements[0], + elements = elements, + setSelected = {}, + setIsOpen = {}, + ) + } +} + +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun AllInSelectionBoxOpenPreview() { + AllInTheme { + val elements = listOf( + SelectionElement("Oui/Non", Icons.AutoMirrored.Default.HelpOutline), + SelectionElement("Sport", Icons.Default.SportsFootball), + SelectionElement("Perso", Icons.Default.Edit) + ) + AllInSelectionBox( + isOpen = true, + selected = elements[0], + elements = elements, + setSelected = {}, + setIsOpen = {}, + ) + } +} diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/RainbowButton.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/RainbowButton.kt index 0850082..f24f554 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/RainbowButton.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/RainbowButton.kt @@ -46,7 +46,7 @@ fun RainbowButton( style = textStyle, fontSize = 30.sp, modifier = Modifier - .padding(vertical = 20.dp) + .padding(vertical = 15.dp) .fillMaxWidth(), ) } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/topbar/coinCounter.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/topbar/coinCounter.kt index 95bbeb0..90b27ef 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/core/topbar/coinCounter.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/core/topbar/coinCounter.kt @@ -1,6 +1,7 @@ package fr.iut.alldev.allin.ui.core.topbar import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize @@ -21,19 +22,22 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme @Composable fun CoinCounter(amount:Int, modifier: Modifier = Modifier) { Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) { - Row(modifier = Modifier + Row( + modifier = Modifier .background(AllInTheme.colors.white) .padding(horizontal = 13.dp, vertical = 5.dp), - verticalAlignment = Alignment.CenterVertically) { - Icon( - painter = painterResource(R.drawable.allcoin), - tint = AllInTheme.colors.allIn_Blue, - contentDescription = null, - modifier = Modifier.padding(end = 8.dp)) + horizontalArrangement = Arrangement.spacedBy(7.dp), + verticalAlignment = Alignment.CenterVertically + ) { Text(text = amount.toString(), color = AllInTheme.colors.allIn_Dark, style = AllInTheme.typography.h1, fontSize = 20.sp) + Icon( + painter = painterResource(R.drawable.allcoin), + tint = AllInTheme.colors.allIn_Blue, + contentDescription = null, + ) } } } diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Color.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Color.kt index ec71c8b..3234143 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Color.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Color.kt @@ -22,6 +22,7 @@ data class AllInColors( val white: Color, val black: Color, val allIn_Pink: Color, + val allIn_Mint: Color, val allIn_Purple: Color, val allIn_LoginPurple: Color, val allIn_Blue: Color, @@ -56,6 +57,7 @@ internal val LocalColors = staticCompositionLocalOf { allIn_BarPurple = Color.Unspecified, allIn_BarPink = Color.Unspecified, allIn_Blue = Color.Unspecified, + allIn_Mint = Color.Unspecified, allIn_DarkBlue = Color.Unspecified, allIn_MainGradient = Brush.linearGradient( diff --git a/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Theme.kt b/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Theme.kt index b1c7941..7efb2e9 100644 --- a/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Theme.kt +++ b/src/app/src/main/java/fr/iut/alldev/allin/ui/theme/Theme.kt @@ -37,6 +37,7 @@ fun AllInTheme( allIn_BarPurple = Color(0xFF846AC9), allIn_BarPink = Color(0xFFFE2B8A), allIn_Blue = Color(0xFF6a89fa), + allIn_Mint = Color(0xFFC4DEE9), allIn_DarkBlue = Color(0xFF323078), allIn_MainGradient = Brush.linearGradient( diff --git a/src/app/src/main/res/values-fr/strings.xml b/src/app/src/main/res/values-fr/strings.xml index 194fc56..bbc513a 100644 --- a/src/app/src/main/res/values-fr/strings.xml +++ b/src/app/src/main/res/values-fr/strings.xml @@ -51,6 +51,9 @@ Seulement vos amis pourront rejoindre le bet. Vous pourrez inviter des amis à tout moment pendant la période d’inscription. Oui / Non + Match sportif + Les utilisateurs devront répondre au pari avec OUI ou NON. + Aucune autre réponse ne sera acceptée. Réponses personnalisées Populaire diff --git a/src/app/src/main/res/values/strings.xml b/src/app/src/main/res/values/strings.xml index a9fa8df..bd1107c 100644 --- a/src/app/src/main/res/values/strings.xml +++ b/src/app/src/main/res/values/strings.xml @@ -56,6 +56,9 @@ Only your friends will be able to join the bet. You can invite friends at any moment during the registration period. Yes / No + The participants will have to respond with either YES or NO. + No other answer will be accepted. + Sport match Custom answers Popular diff --git a/src/data/src/main/java/fr/iut/alldev/allin/data/model/BetType.kt b/src/data/src/main/java/fr/iut/alldev/allin/data/model/BetType.kt new file mode 100644 index 0000000..ac8e8a7 --- /dev/null +++ b/src/data/src/main/java/fr/iut/alldev/allin/data/model/BetType.kt @@ -0,0 +1,7 @@ +package fr.iut.alldev.allin.data.model + +enum class BetType { + YES_NO, + MATCH, + CUSTOM +}