diff --git a/app/src/main/java/com/cornellappdev/score/MainActivity.kt b/app/src/main/java/com/cornellappdev/score/MainActivity.kt index c0c6e5a..a210107 100644 --- a/app/src/main/java/com/cornellappdev/score/MainActivity.kt +++ b/app/src/main/java/com/cornellappdev/score/MainActivity.kt @@ -4,14 +4,16 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.edit import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.core.content.edit import com.cornellappdev.score.model.OnboardingPreferencesRepository import com.cornellappdev.score.nav.root.RootNavigation +import com.cornellappdev.score.screen.FavoriteSport +import com.cornellappdev.score.screen.OnboardingFavoriteSportsScreen import com.cornellappdev.score.screen.OnboardingProfileSelectScreen import com.cornellappdev.score.screen.OnboardingScreen import com.google.firebase.Firebase @@ -22,12 +24,14 @@ import javax.inject.Inject private const val APP_PREFERENCES = "score_app_preferences" private const val KEY_ONBOARDING_PROFILE_PICTURE = "onboarding_profile_picture" +private const val KEY_ONBOARDING_FAVORITE_SPORTS = "onboarding_favorite_sports" private lateinit var firebaseAnalytics: FirebaseAnalytics private enum class OnboardingStep { WELCOME, PROFILE_SELECT, + SPORT_SELECT, COMPLETE } @@ -42,6 +46,10 @@ class MainActivity : AppCompatActivity() { val onboardingCompleted = onboardingPreferencesRepository.isOnboardingCompleted() val preferences = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE) + val savedFavoriteSportKeys = preferences + .getStringSet(KEY_ONBOARDING_FAVORITE_SPORTS, emptySet()) + .orEmpty() + .joinToString("|") setContent { var onboardingStep by rememberSaveable { @@ -69,6 +77,19 @@ class MainActivity : AppCompatActivity() { preferences.edit { putString(KEY_ONBOARDING_PROFILE_PICTURE, selectedPicture.name) } + onboardingStep = OnboardingStep.SPORT_SELECT + } + ) + + OnboardingStep.SPORT_SELECT -> OnboardingFavoriteSportsScreen( + initiallySelectedKeys = savedFavoriteSportKeys, + onFinish = { selectedSports -> + preferences.edit { + putStringSet( + KEY_ONBOARDING_FAVORITE_SPORTS, + selectedSports.map(FavoriteSport::storageKey).toSet() + ) + } completeOnboarding() } ) diff --git a/app/src/main/java/com/cornellappdev/score/components/GenderDivisionFilter.kt b/app/src/main/java/com/cornellappdev/score/components/GenderDivisionFilter.kt new file mode 100644 index 0000000..bfe545a --- /dev/null +++ b/app/src/main/java/com/cornellappdev/score/components/GenderDivisionFilter.kt @@ -0,0 +1,95 @@ +package com.cornellappdev.score.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.cornellappdev.score.model.GenderDivision +import com.cornellappdev.score.theme.CrimsonPrimary +import com.cornellappdev.score.theme.GrayLight +import com.cornellappdev.score.theme.GrayMedium +import com.cornellappdev.score.theme.Style +import com.cornellappdev.score.theme.White + +/** Accessible, single-choice filter shared by the Home screen and onboarding. */ +@Composable +fun GenderDivisionFilter( + selectedGender: GenderDivision, + onGenderSelected: (GenderDivision) -> Unit, + modifier: Modifier = Modifier +) { + val options = listOf( + GenderDivision.ALL, + GenderDivision.MALE, + GenderDivision.FEMALE + ) + + Row( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .height(48.dp) + .border(BorderStroke(1.dp, GrayLight), CircleShape) + .padding(5.dp) + .selectableGroup(), + verticalAlignment = Alignment.CenterVertically + ) { + options.forEach { gender -> + val selected = gender == selectedGender + Box( + modifier = Modifier + .weight(1f) + .fillMaxHeight() + .background( + color = if (selected) CrimsonPrimary else Color.Transparent, + shape = CircleShape + ) + .selectable( + selected = selected, + role = Role.RadioButton, + onClick = { onGenderSelected(gender) } + ), + contentAlignment = Alignment.Center + ) { + Text( + text = gender.displayName, + style = if (selected) Style.bodySemibold else Style.bodyMedium, + color = if (selected) White else GrayMedium + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +private fun GenderDivisionFilterPreview() { + ScorePreview { + var selectedGender by remember { mutableStateOf(GenderDivision.ALL) } + + GenderDivisionFilter( + selectedGender = selectedGender, + onGenderSelected = { selectedGender = it } + ) + } +} diff --git a/app/src/main/java/com/cornellappdev/score/components/SportSelectorHeader.kt b/app/src/main/java/com/cornellappdev/score/components/SportSelectorHeader.kt index fd09f9a..a36471c 100644 --- a/app/src/main/java/com/cornellappdev/score/components/SportSelectorHeader.kt +++ b/app/src/main/java/com/cornellappdev/score/components/SportSelectorHeader.kt @@ -1,14 +1,10 @@ package com.cornellappdev.score.components -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable 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.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -17,7 +13,6 @@ import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -26,7 +21,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview @@ -35,10 +29,7 @@ import com.cornellappdev.score.R import com.cornellappdev.score.model.GenderDivision import com.cornellappdev.score.model.SportSelection import com.cornellappdev.score.theme.CrimsonPrimary -import com.cornellappdev.score.theme.GrayLight import com.cornellappdev.score.theme.GrayMedium -import com.cornellappdev.score.theme.Style.bodyMedium -import com.cornellappdev.score.theme.Style.bodySemibold import com.cornellappdev.score.theme.Style.labelsMedium import com.cornellappdev.score.theme.Style.labelsNormal import com.cornellappdev.score.theme.White @@ -59,24 +50,10 @@ fun SportSelectorHeader( .background(color = White), horizontalAlignment = Alignment.CenterHorizontally ) { - Row( - modifier = Modifier - .border( - border = BorderStroke(1.dp, GrayLight), - shape = RoundedCornerShape(100) - ) - .padding(6.dp) - ) { - GenderSelector(GenderDivision.ALL, selectedGender == GenderDivision.ALL) { - onGenderSelected(GenderDivision.ALL) - } - GenderSelector(GenderDivision.MALE, selectedGender == GenderDivision.MALE) { - onGenderSelected(GenderDivision.MALE) - } - GenderSelector(GenderDivision.FEMALE, selectedGender == GenderDivision.FEMALE) { - onGenderSelected(GenderDivision.FEMALE) - } - } + GenderDivisionFilter( + selectedGender = selectedGender, + onGenderSelected = onGenderSelected + ) Spacer(Modifier.height(24.dp)) LazyRow( Modifier.fillMaxWidth(), @@ -116,29 +93,6 @@ fun SportSelectorHeader( } } -@Composable -fun GenderSelector(option: GenderDivision, isSelected: Boolean, onSelect: () -> Unit) { - Box( - modifier = Modifier - .clickable(onClick = { - onSelect() - }) - .width(111.dp) - .background( - color = if (isSelected) CrimsonPrimary else Color.Transparent, - shape = RoundedCornerShape(100) // Rounded background - ) - .padding(vertical = 8.dp, horizontal = 12.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = option.displayName, - style = if (isSelected) bodySemibold else bodyMedium, - color = if (isSelected) White else GrayMedium - ) - } -} - @Composable fun SportSelector( empty: Painter, diff --git a/app/src/main/java/com/cornellappdev/score/screen/OnboardingFavoriteSportsScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/OnboardingFavoriteSportsScreen.kt new file mode 100644 index 0000000..56cda4c --- /dev/null +++ b/app/src/main/java/com/cornellappdev/score/screen/OnboardingFavoriteSportsScreen.kt @@ -0,0 +1,323 @@ +package com.cornellappdev.score.screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.cornellappdev.score.R +import com.cornellappdev.score.components.GenderDivisionFilter +import com.cornellappdev.score.components.ScorePreview +import com.cornellappdev.score.model.GenderDivision +import com.cornellappdev.score.model.Sport +import com.cornellappdev.score.theme.CrimsonPrimary +import com.cornellappdev.score.theme.GrayPrimary +import com.cornellappdev.score.theme.GrayStroke +import com.cornellappdev.score.theme.GreenWash +import com.cornellappdev.score.theme.Style +import com.cornellappdev.score.theme.White +import com.cornellappdev.score.theme.saturatedGreen +import com.cornellappdev.score.util.isValidSport + +data class FavoriteSport( + val sport: Sport, + val gender: GenderDivision +) { + //combines sport and gender into one identifier for favorite team selection + val storageKey: String get() = "${sport.name}:${gender.name}" + + companion object { + fun fromStorageKey(key: String): FavoriteSport? { + val parts = key.split(':', limit = 2) + if (parts.size != 2) return null + val sport = runCatching { Sport.valueOf(parts[0]) }.getOrNull() ?: return null + val gender = runCatching { GenderDivision.valueOf(parts[1]) }.getOrNull() + ?: return null + if (gender == GenderDivision.ALL) return null + return FavoriteSport(sport, gender) + } + } +} + +@Composable +fun OnboardingFavoriteSportsScreen( + onFinish: (Set) -> Unit, + modifier: Modifier = Modifier, + initiallySelectedKeys: String = "" +) { + var selectedGender by rememberSaveable { mutableStateOf(GenderDivision.ALL) } + var selectedKeys by rememberSaveable { + mutableStateOf(initiallySelectedKeys) + } + val selectedSports = selectedKeys.split('|').filter(String::isNotBlank).toSet() + val allOptions = rememberFavoriteSportOptions() + val visibleOptions = when (selectedGender) { + GenderDivision.ALL -> allOptions + else -> allOptions.filter { it.gender == selectedGender } + } + + Box( + modifier = modifier + .fillMaxSize() + .background(White) + ) { + Column(modifier = Modifier.fillMaxSize()) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 79.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(R.string.select_favorite_sports), + style = Style.heading1, + color = GrayPrimary, + textAlign = TextAlign.Center + ) + Spacer(Modifier.height(4.dp)) + Text( + text = stringResource(R.string.favorite_sports_subtitle), + style = Style.bodyMedium, + color = GrayPrimary, + textAlign = TextAlign.Center + ) + Spacer(Modifier.height(32.dp)) + GenderDivisionFilter( + selectedGender = selectedGender, + onGenderSelected = { selectedGender = it } + ) + } + + Spacer(Modifier.height(32.dp)) + LazyVerticalGrid( + columns = GridCells.Fixed(3), + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + contentPadding = PaddingValues( + start = 24.dp, + end = 24.dp, + top = 8.dp, + bottom = 8.dp + ), + horizontalArrangement = Arrangement.spacedBy(24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + items(visibleOptions, key = { it.storageKey }) { option -> + FavoriteSportCard( + option = option, + selected = option.storageKey in selectedSports, + onClick = { + selectedKeys = if (option.storageKey in selectedSports) { + selectedSports - option.storageKey + } else { + selectedSports + option.storageKey + }.joinToString("|") + } + ) + } + } + + OnboardingFooter( + buttonText = when (selectedSports.size) { + 0 -> stringResource(R.string.finish) + 1 -> stringResource(R.string.finish_with_one_sport) + else -> stringResource(R.string.finish_with_sports, selectedSports.size) + }, + onClick = { + onFinish(selectedSports.mapNotNull(FavoriteSport::fromStorageKey).toSet()) + }, + activeStep = OnboardingState.SPORT_SELECT + ) + } + } +} + +@Composable +private fun rememberFavoriteSportOptions(): List { + return remember { + Sport.entries + .filter { sport -> isValidSport(sport.displayName) } + .flatMap { sport -> + when (sport.gender) { + GenderDivision.ALL -> listOf( + FavoriteSport(sport, GenderDivision.MALE), + FavoriteSport(sport, GenderDivision.FEMALE) + ) + + GenderDivision.MALE -> listOf(FavoriteSport(sport, GenderDivision.MALE)) + GenderDivision.FEMALE -> listOf(FavoriteSport(sport, GenderDivision.FEMALE)) + } + } + .sortedWith( + compareBy { it.sport.displayName } + .thenBy { if (it.gender == GenderDivision.MALE) 0 else 1 } + ) + } +} + +@Composable +private fun FavoriteSportCard( + option: FavoriteSport, + selected: Boolean, + onClick: () -> Unit +) { + val cardShape = RoundedCornerShape(20.dp) + Column( + modifier = Modifier + .fillMaxWidth() + .selectable( + selected = selected, + role = Role.Checkbox, + onClick = onClick + ), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box(modifier = Modifier + .fillMaxWidth() + .aspectRatio(1f)) { + Box( + modifier = Modifier + .fillMaxSize() + .clip(cardShape) + .background(if (selected) GreenWash else GrayStroke) + .border( + width = if (selected) 3.dp else 1.dp, + color = if (selected) saturatedGreen else GrayStroke, + shape = cardShape + ), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(option.sport.emptyIcon), + contentDescription = null, + modifier = Modifier.size(45.dp), + colorFilter = ColorFilter.tint( + if (selected) saturatedGreen else GrayPrimary + ) + ) + } + + if (selected) { + Box( + modifier = Modifier + .align(Alignment.TopStart) + .offset(x = (-8).dp, y = (-8).dp) + .size(32.dp) + .background(CrimsonPrimary, CircleShape), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(R.drawable.ic_round_minus), + contentDescription = stringResource(R.string.remove_favorite_sport), + modifier = Modifier.size(24.dp), + colorFilter = ColorFilter.tint(White) + ) + } + } + } + + Spacer(Modifier.height(8.dp)) + Text( + text = option.sport.displayName, + style = Style.bodyMedium, + color = GrayPrimary, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + Spacer(Modifier.height(2.dp)) + FavoriteSportGenderTag(option.gender) + } +} + +@Composable +private fun FavoriteSportGenderTag( + gender: GenderDivision, +) { + val label = if (gender == GenderDivision.FEMALE) "W" else "M" + val genderIcon = if (gender == GenderDivision.FEMALE) { + R.drawable.ic_light_gray_female_gender + } else { + R.drawable.ic_light_gray_male_gender + } + + Row( + modifier = Modifier + .background(White, RoundedCornerShape(100)) + .padding(horizontal = 2.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(2.dp) + ) { + Box( + modifier = Modifier + .size(18.dp) + .background(GrayStroke, CircleShape), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(genderIcon), + contentDescription = null, + modifier = Modifier.size(12.dp) + ) + } + Text( + text = label, + style = Style.labelsNormal, + color = GrayPrimary + ) + } +} + + +@Preview +@Composable +private fun OnboardingFavoriteSportsScreenPreview() { + ScorePreview { + OnboardingFavoriteSportsScreen(onFinish = {}) + } +} + +@Preview +@Composable +private fun OnboardingFavoriteSportsSelectedScreenPreview() { + ScorePreview { + OnboardingFavoriteSportsScreen( + onFinish = {}, + initiallySelectedKeys = "BASEBALL:MALE|CROSS_COUNTRY:FEMALE" + ) + } +} diff --git a/app/src/main/java/com/cornellappdev/score/screen/OnboardingFooter.kt b/app/src/main/java/com/cornellappdev/score/screen/OnboardingFooter.kt new file mode 100644 index 0000000..4af4f06 --- /dev/null +++ b/app/src/main/java/com/cornellappdev/score/screen/OnboardingFooter.kt @@ -0,0 +1,94 @@ +package com.cornellappdev.score.screen + +import androidx.compose.foundation.background +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.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.cornellappdev.score.components.ScorePreview +import com.cornellappdev.score.theme.CrimsonPrimary +import com.cornellappdev.score.theme.GrayStroke +import com.cornellappdev.score.theme.Style +import com.cornellappdev.score.theme.White + +enum class OnboardingState{ + PROFILE_SELECT, SPORT_SELECT +} + +@Composable +fun OnboardingFooter( + buttonText: String, + onClick: () -> Unit, + activeStep: OnboardingState +) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(White) + .padding( + start = 24.dp, + end = 24.dp, + top = 24.dp, + bottom = 60.dp + ), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Button( + onClick = onClick, + modifier = Modifier + .fillMaxWidth() + .height(48.dp), + shape = CircleShape, + colors = ButtonDefaults.buttonColors( + containerColor = CrimsonPrimary, + contentColor = White + ) + ) { + Text(buttonText, style = Style.heading3, color = White) + } + + Spacer(Modifier.height(16.dp)) + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + repeat(2) { index -> + val isActive = when (activeStep) { + OnboardingState.PROFILE_SELECT -> index == 0 + OnboardingState.SPORT_SELECT -> index == 1 + } + Box( + Modifier + .size(8.dp) + .background(if (isActive) CrimsonPrimary else GrayStroke, CircleShape) + ) + } + } + } +} + +@Preview +@Composable +private fun OnboardingFooterPreview() { + ScorePreview { + OnboardingFooter( + buttonText = "Next", + onClick = {}, + activeStep = OnboardingState.PROFILE_SELECT + ) + } +} diff --git a/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt index 30d0223..bca920f 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/OnboardingProfileSelectScreen.kt @@ -2,9 +2,7 @@ package com.cornellappdev.score.screen import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -12,9 +10,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -28,11 +23,9 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.cornellappdev.score.R -import com.cornellappdev.score.theme.CrimsonPrimary -import com.cornellappdev.score.theme.GrayStroke +import com.cornellappdev.score.theme.GrayPrimary import com.cornellappdev.score.theme.Style @Composable @@ -59,13 +52,13 @@ fun OnboardingProfileSelectScreen( Text( text = stringResource(R.string.edit_profile), style = Style.heading1, - color = Color(0xFF333333) + color = GrayPrimary ) Spacer(Modifier.height(4.dp)) Text( text = stringResource(R.string.onboarding_profile_subtitle), style = Style.bodyMedium, - color = Color(0xFF333333) + color = GrayPrimary ) Spacer(Modifier.height(40.dp)) @@ -103,62 +96,15 @@ fun OnboardingProfileSelectScreen( } Spacer(Modifier.weight(1f)) - OnboardingProfileFooter( - onNext = { onNext(selectedPicture) } + OnboardingFooter( + buttonText = stringResource(R.string.next), + onClick = { onNext(selectedPicture) }, + activeStep = OnboardingState.PROFILE_SELECT ) } } } -@Composable -private fun OnboardingProfileFooter( - onNext: () -> Unit, -) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding( - start = 24.dp, - end = 24.dp, - top = 24.dp, - bottom = 60.dp - ), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Button( - onClick = onNext, - modifier = Modifier - .fillMaxWidth() - .height(48.dp), - shape = CircleShape, - colors = ButtonDefaults.buttonColors( - containerColor = CrimsonPrimary, - contentColor = Color.White - ) - ) { - Text( - text = stringResource(R.string.next), - style = Style.heading3, - color = Color.White - ) - } - - Spacer(Modifier.height(16.dp)) - RowProgressDots() - } -} - -@Composable -private fun RowProgressDots() { - androidx.compose.foundation.layout.Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box(Modifier.size(8.dp).background(CrimsonPrimary, CircleShape)) - Box(Modifier.size(8.dp).background(GrayStroke, CircleShape)) - } -} - @Preview(showBackground = true) @Composable private fun OnboardingProfileSelectScreenPreview() { diff --git a/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt b/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt index 2caa255..dcae5c4 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/ProfilePictureOptions.kt @@ -10,19 +10,18 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.cornellappdev.score.components.ScorePreview import com.cornellappdev.score.theme.saturatedGreen diff --git a/app/src/main/java/com/cornellappdev/score/theme/Color.kt b/app/src/main/java/com/cornellappdev/score/theme/Color.kt index a4f8fa5..799aaee 100644 --- a/app/src/main/java/com/cornellappdev/score/theme/Color.kt +++ b/app/src/main/java/com/cornellappdev/score/theme/Color.kt @@ -11,6 +11,7 @@ val GrayStroke = Color(0xFFEAEAEA) val GreenAccent = Color(0xFF247211) val RedAccent = Color(0xFFC41616) val GreenLight = Color(0xFF88D598) +val GreenWash = Color(0xFFF6FFF3) val BlueLight = Color(0XFF5AA8D5) val CrimsonPrimary = Color(0xFFA5210D) val PeachPrimary = Color(0xFFE1A69F) diff --git a/app/src/main/res/drawable/ic_light_gray_female_gender.xml b/app/src/main/res/drawable/ic_light_gray_female_gender.xml new file mode 100644 index 0000000..81e066a --- /dev/null +++ b/app/src/main/res/drawable/ic_light_gray_female_gender.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_light_gray_male_gender.xml b/app/src/main/res/drawable/ic_light_gray_male_gender.xml new file mode 100644 index 0000000..3039fdb --- /dev/null +++ b/app/src/main/res/drawable/ic_light_gray_male_gender.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9ef2641..75e707e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,4 +11,13 @@ You can change this later in the profile page. Select profile picture: Next + Select Favorite Sports + You can change your picks at any time! + All + Men’s + Women’s + Finish + Finish with %1$d sports + Finish with 1 sport + Remove favorite sport \ No newline at end of file