Bet Creation Screen : Answer tab
continuous-integration/drone/push Build is passing Details

pull/3/head
Arthur VALIN 2 years ago
parent 6f9f6e5be0
commit 16c6cb2309

@ -55,6 +55,7 @@ dependencies {
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.compose.material3:material3:1.2.0-alpha08' implementation 'androidx.compose.material3:material3:1.2.0-alpha08'
implementation "androidx.navigation:navigation-compose:2.7.3" implementation "androidx.navigation:navigation-compose:2.7.3"
implementation project(path: ':data')
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
implementation 'androidx.compose.material:material-icons-core' implementation 'androidx.compose.material:material-icons-core'
implementation 'androidx.compose.material:material-icons-extended' implementation 'androidx.compose.material:material-icons-extended'

@ -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
}
}

@ -3,23 +3,28 @@ package fr.iut.alldev.allin.ui.betcreation
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.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.BetCreationScreenAnswerTab
import fr.iut.alldev.allin.ui.betcreation.tabs.BetCreationScreenQuestionTab import fr.iut.alldev.allin.ui.betcreation.tabs.BetCreationScreenQuestionTab
import fr.iut.alldev.allin.ui.core.AllInSections import fr.iut.alldev.allin.ui.core.AllInSections
import fr.iut.alldev.allin.ui.core.RainbowButton import fr.iut.alldev.allin.ui.core.RainbowButton
import fr.iut.alldev.allin.ui.core.SectionElement import fr.iut.alldev.allin.ui.core.SectionElement
import fr.iut.alldev.allin.ui.core.SelectionElement
@Composable @Composable
fun BetCreationScreen( fun BetCreationScreen(
) { ) {
var theme by remember{ var theme by remember{
mutableStateOf("") mutableStateOf("")
} }
@ -29,15 +34,43 @@ fun BetCreationScreen(
var isPublic by remember{ var isPublic by remember{
mutableStateOf(true) mutableStateOf(true)
} }
val betTypes = remember {
BetType.values().toList()
}
val selectedFriends = remember {
mutableListOf<Int>()
}
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( Box(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(20.dp) .padding(top = 20.dp)
) { ) {
AllInSections( AllInSections(
modifier = Modifier modifier = Modifier
.align(Alignment.TopCenter) .align(Alignment.TopCenter)
.fillMaxSize(), .fillMaxSize()
.padding(bottom = 90.dp),
sections = listOf( sections = listOf(
SectionElement(stringResource(id = R.string.Question)){ SectionElement(stringResource(id = R.string.Question)){
BetCreationScreenQuestionTab( BetCreationScreenQuestionTab(
@ -46,11 +79,25 @@ fun BetCreationScreen(
betPhrase = phrase, betPhrase = phrase,
setBetPhrase = { phrase = it }, setBetPhrase = { phrase = it },
betTheme = theme, 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)){ 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), text = stringResource(id = R.string.Publish),
modifier = Modifier modifier = Modifier
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)
.padding(bottom = 14.dp), .padding(bottom = 14.dp)
.padding(horizontal = 20.dp),
onClick = { onClick = {
} }
) )

@ -1,10 +1,12 @@
package fr.iut.alldev.allin.ui.betcreation.components package fr.iut.alldev.allin.ui.betcreation.components
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@ -17,8 +19,9 @@ fun BetCreationScreenBottomText(
text = text, text = text,
color = AllInTheme.colors.allIn_Purple, color = AllInTheme.colors.allIn_Purple,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
style = AllInTheme.typography.h2, style = AllInTheme.typography.h2,
modifier = modifier.alpha(.5f) modifier = modifier.fillMaxWidth().alpha(.5f)
) )
} }

@ -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) {
}
}
}

@ -1,30 +1,54 @@
package fr.iut.alldev.allin.ui.betcreation.tabs package fr.iut.alldev.allin.ui.betcreation.tabs
import android.util.Log import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column import androidx.compose.runtime.*
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.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.core.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 @Composable
fun BetCreationScreenAnswerTab() { fun BetCreationScreenAnswerTab(
Column( modifier: Modifier = Modifier,
Modifier selected: SelectionElement,
.fillMaxSize() selectedBetType: BetType,
.padding(20.dp) setSelected: (SelectionElement)->Unit,
) { elements: List<SelectionElement>
AllInTextAndIcon( ) {
text = stringResource(id = R.string.Answer), var isOpen by remember{
icon = Icons.Outlined.QuestionAnswer mutableStateOf(false)
){ }
Log.d("ALLINNN", "AAAA")
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())
}
} }
} }
} }

@ -2,11 +2,13 @@ package fr.iut.alldev.allin.ui.betcreation.tabs
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.filled.Public import androidx.compose.material.icons.filled.Public
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -14,7 +16,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.betcreation.components.BetCreationScreenBottomText 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.AllInIconChip
import fr.iut.alldev.allin.ui.core.AllInRetractableCard
import fr.iut.alldev.allin.ui.core.AllInTextAndIcon import fr.iut.alldev.allin.ui.core.AllInTextAndIcon
import fr.iut.alldev.allin.ui.core.AllInTextField import fr.iut.alldev.allin.ui.core.AllInTextField
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@ -22,19 +26,18 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun BetCreationScreenQuestionTab( fun BetCreationScreenQuestionTab(
modifier: Modifier = Modifier,
nbFriends: Int,
betTheme: String, betTheme: String,
setBetTheme: (String)->Unit, setBetTheme: (String)->Unit,
betPhrase: String, betPhrase: String,
setBetPhrase: (String)->Unit, setBetPhrase: (String)->Unit,
isPublic: Boolean, isPublic: Boolean,
setIsPublic: (Boolean)->Unit setIsPublic: (Boolean)->Unit,
selectedFriends: MutableList<Int>
) { ) {
val bringIntoViewRequester = remember { BringIntoViewRequester() } val bringIntoViewRequester = remember { BringIntoViewRequester() }
Column( Column(modifier){
Modifier
.fillMaxSize()
.padding(20.dp)
){
AllInTextAndIcon( AllInTextAndIcon(
text = stringResource(id = R.string.Theme), text = stringResource(id = R.string.Theme),
icon = Icons.AutoMirrored.Outlined.HelpOutline, icon = Icons.AutoMirrored.Outlined.HelpOutline,
@ -79,6 +82,7 @@ fun BetCreationScreenQuestionTab(
onClick = {} onClick = {}
) )
Row( Row(
modifier = Modifier.padding(bottom = 10.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)
){ ){
AllInIconChip( AllInIconChip(
@ -99,17 +103,71 @@ fun BetCreationScreenQuestionTab(
) )
} }
Spacer(modifier = Modifier.height(52.dp))
Column( Column(
verticalArrangement = Arrangement.spacedBy(17.dp) verticalArrangement = Arrangement.spacedBy(17.dp)
) { ) {
var isOpen by remember{
mutableStateOf(false)
}
if(isPublic){ if(isPublic){
BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_1)) Column(
BetCreationScreenBottomText(text = stringResource(id = R.string.public_bottom_text_2)) 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{ }else{
BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_1)) AllInRetractableCard(
BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_2)) text = stringResource(
BetCreationScreenBottomText(text = stringResource(id = R.string.private_bottom_text_3)) 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))
}
} }
} }
} }

@ -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)
}
}

@ -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)
}
}

@ -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()
}
}
}
}

@ -1,36 +1,28 @@
package fr.iut.alldev.allin.ui.core package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.* import androidx.compose.foundation.gestures.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow 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.material3.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
import kotlinx.coroutines.launch
class SectionElement( class SectionElement(
val text: String, val text: String,
val content: @Composable ()->Unit val content: @Composable ()->Unit
) )
enum class DragAnchors(val fraction: Float) {
Start(-2f),
Center(0f),
End(2f),
}
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun AllInSections( fun AllInSections(
@ -38,97 +30,31 @@ fun AllInSections(
interSectionsPadding: Dp = 56.dp, interSectionsPadding: Dp = 56.dp,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
var selected by remember { val pagerState = rememberPagerState(pageCount = {
mutableStateOf(sections.firstOrNull()) sections.size
} })
var wasSwiped by remember{ val scope = rememberCoroutineScope()
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
}
}
Column( Column(
modifier = modifier, modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ){
LazyRow( LazyRow(
horizontalArrangement = Arrangement.spacedBy(interSectionsPadding) horizontalArrangement = Arrangement.spacedBy(interSectionsPadding)
) { ) {
items(sections) { section -> itemsIndexed(sections) { index, section ->
AllInSectionButton( AllInSectionButton(
text = section.text, text = section.text,
isSelected = selected == section, isSelected = index == pagerState.currentPage,
onClick = { selected = section } onClick = {
) scope.launch {
} pagerState.animateScrollToPage(index)
} }
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
}
} }
) )
}, }
){
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()
} }
} }
} }

@ -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<SelectionElement>
) {
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 = {},
)
}
}

@ -46,7 +46,7 @@ fun RainbowButton(
style = textStyle, style = textStyle,
fontSize = 30.sp, fontSize = 30.sp,
modifier = Modifier modifier = Modifier
.padding(vertical = 20.dp) .padding(vertical = 15.dp)
.fillMaxWidth(), .fillMaxWidth(),
) )
} }

@ -1,6 +1,7 @@
package fr.iut.alldev.allin.ui.core.topbar package fr.iut.alldev.allin.ui.core.topbar
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentSize
@ -21,19 +22,22 @@ import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable @Composable
fun CoinCounter(amount:Int, modifier: Modifier = Modifier) { fun CoinCounter(amount:Int, modifier: Modifier = Modifier) {
Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) { Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) {
Row(modifier = Modifier Row(
modifier = Modifier
.background(AllInTheme.colors.white) .background(AllInTheme.colors.white)
.padding(horizontal = 13.dp, vertical = 5.dp), .padding(horizontal = 13.dp, vertical = 5.dp),
verticalAlignment = Alignment.CenterVertically) { horizontalArrangement = Arrangement.spacedBy(7.dp),
Icon( verticalAlignment = Alignment.CenterVertically
painter = painterResource(R.drawable.allcoin), ) {
tint = AllInTheme.colors.allIn_Blue,
contentDescription = null,
modifier = Modifier.padding(end = 8.dp))
Text(text = amount.toString(), Text(text = amount.toString(),
color = AllInTheme.colors.allIn_Dark, color = AllInTheme.colors.allIn_Dark,
style = AllInTheme.typography.h1, style = AllInTheme.typography.h1,
fontSize = 20.sp) fontSize = 20.sp)
Icon(
painter = painterResource(R.drawable.allcoin),
tint = AllInTheme.colors.allIn_Blue,
contentDescription = null,
)
} }
} }
} }

@ -22,6 +22,7 @@ data class AllInColors(
val white: Color, val white: Color,
val black: Color, val black: Color,
val allIn_Pink: Color, val allIn_Pink: Color,
val allIn_Mint: Color,
val allIn_Purple: Color, val allIn_Purple: Color,
val allIn_LoginPurple: Color, val allIn_LoginPurple: Color,
val allIn_Blue: Color, val allIn_Blue: Color,
@ -56,6 +57,7 @@ internal val LocalColors = staticCompositionLocalOf {
allIn_BarPurple = Color.Unspecified, allIn_BarPurple = Color.Unspecified,
allIn_BarPink = Color.Unspecified, allIn_BarPink = Color.Unspecified,
allIn_Blue = Color.Unspecified, allIn_Blue = Color.Unspecified,
allIn_Mint = Color.Unspecified,
allIn_DarkBlue = Color.Unspecified, allIn_DarkBlue = Color.Unspecified,
allIn_MainGradient = Brush.linearGradient( allIn_MainGradient = Brush.linearGradient(

@ -37,6 +37,7 @@ fun AllInTheme(
allIn_BarPurple = Color(0xFF846AC9), allIn_BarPurple = Color(0xFF846AC9),
allIn_BarPink = Color(0xFFFE2B8A), allIn_BarPink = Color(0xFFFE2B8A),
allIn_Blue = Color(0xFF6a89fa), allIn_Blue = Color(0xFF6a89fa),
allIn_Mint = Color(0xFFC4DEE9),
allIn_DarkBlue = Color(0xFF323078), allIn_DarkBlue = Color(0xFF323078),
allIn_MainGradient = Brush.linearGradient( allIn_MainGradient = Brush.linearGradient(

@ -51,6 +51,9 @@
<string name="private_bottom_text_2">Seulement vos amis pourront rejoindre le bet.</string> <string name="private_bottom_text_2">Seulement vos amis pourront rejoindre le bet.</string>
<string name="private_bottom_text_3">Vous pourrez inviter des amis à tout moment pendant la période dinscription.</string> <string name="private_bottom_text_3">Vous pourrez inviter des amis à tout moment pendant la période dinscription.</string>
<string name="yes_no">Oui / Non</string> <string name="yes_no">Oui / Non</string>
<string name="sport_match">Match sportif</string>
<string name="yes_no_bottom_text_1">Les utilisateurs devront répondre au pari avec OUI ou NON.</string>
<string name="yes_no_bottom_text_2">Aucune autre réponse ne sera acceptée.</string>
<string name="custom_answers">Réponses personnalisées</string> <string name="custom_answers">Réponses personnalisées</string>
<!--Bet Page--> <!--Bet Page-->
<string name="Popular">Populaire</string> <string name="Popular">Populaire</string>

@ -56,6 +56,9 @@
<string name="private_bottom_text_2">Only your friends will be able to join the bet.</string> <string name="private_bottom_text_2">Only your friends will be able to join the bet.</string>
<string name="private_bottom_text_3">You can invite friends at any moment during the registration period.</string> <string name="private_bottom_text_3">You can invite friends at any moment during the registration period.</string>
<string name="yes_no">Yes / No</string> <string name="yes_no">Yes / No</string>
<string name="yes_no_bottom_text_1">The participants will have to respond with either YES or NO.</string>
<string name="yes_no_bottom_text_2">No other answer will be accepted.</string>
<string name="sport_match">Sport match</string>
<string name="custom_answers">Custom answers</string> <string name="custom_answers">Custom answers</string>
<!--Bet Page--> <!--Bet Page-->
<string name="Popular">Popular</string> <string name="Popular">Popular</string>

@ -0,0 +1,7 @@
package fr.iut.alldev.allin.data.model
enum class BetType {
YES_NO,
MATCH,
CUSTOM
}
Loading…
Cancel
Save