From 054f0016d40bbc9234a147f3ab2ddd6d48ab2f54 Mon Sep 17 00:00:00 2001 From: Emil Jiang Date: Fri, 19 Sep 2025 15:49:43 -0400 Subject: [PATCH 1/5] git issue fix --- app/build.gradle.kts | 1 + .../com/cornellappdev/score/screen/GameDetailsScreen.kt | 7 ++++++- .../cornellappdev/score/screen/GameScoreSummaryScreen.kt | 3 ++- gradle/libs.versions.toml | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fca0fe5..d6c534f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -71,6 +71,7 @@ dependencies { implementation("androidx.navigation:navigation-compose:2.8.2") implementation(libs.material3) implementation("com.google.dagger:hilt-android:2.51.1") + implementation(libs.androidx.material3) kapt("com.google.dagger:hilt-android-compiler:2.51.1") implementation("androidx.hilt:hilt-navigation-compose:1.0.0") implementation("com.google.accompanist:accompanist-pager:0.24.0-alpha") diff --git a/app/src/main/java/com/cornellappdev/score/screen/GameDetailsScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/GameDetailsScreen.kt index d2f01bf..4062de6 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/GameDetailsScreen.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/GameDetailsScreen.kt @@ -3,6 +3,7 @@ package com.cornellappdev.score.screen import ScoringSummary import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -106,6 +107,7 @@ fun GameDetailsContent( gameCard: DetailsCardData, navigateToGameScoreSummary: (List) -> Unit ) { + val scrollState = rememberScrollState() Column( modifier = Modifier .background(White) @@ -132,7 +134,10 @@ fun GameDetailsContent( ) Text( text = gameCard.title, - style = heading1.copy(color = GrayPrimary) + style = heading1.copy(color = GrayPrimary), + maxLines = 1, + modifier = Modifier + .horizontalScroll(scrollState) ) Spacer(modifier = Modifier.height(13.5.dp)) diff --git a/app/src/main/java/com/cornellappdev/score/screen/GameScoreSummaryScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/GameScoreSummaryScreen.kt index 0c94504..a9514f9 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/GameScoreSummaryScreen.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/GameScoreSummaryScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -43,7 +44,7 @@ fun GameScoreSummaryScreenDetail(scoreEvents: List, onBackArrow: () ) { items(scoreEvents.size) { event -> ScoreEventItemDetailed(event = scoreEvents[event]) - Divider(color = Color.LightGray, thickness = 0.5.dp) + HorizontalDivider(thickness = 0.5.dp, color = Color.LightGray) } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0fa6263..b53ee5a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,7 @@ media3CommonKtx = "1.5.1" # Using alpha version due to bug with pull to refresh in the latest stabel version # See https://stackoverflow.com/a/79126321 material3 = "1.4.0-alpha11" +material3Version = "1.3.2" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -31,6 +32,7 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" } apollo-runtime = { module = "com.apollographql.apollo:apollo-runtime" } androidx-media3-common-ktx = { group = "androidx.media3", name = "media3-common-ktx", version.ref = "media3CommonKtx" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3Version" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } From d1e732c9c340a6e9f509f452bf7e032222fbece1 Mon Sep 17 00:00:00 2001 From: Emil Jiang Date: Tue, 30 Sep 2025 14:04:49 -0400 Subject: [PATCH 2/5] advanced fitler first iteration --- app/build.gradle.kts | 4 +- .../score/components/ButtonPrimary.kt | 11 +- .../score/components/ExpandableSection.kt | 66 ++++++++++++ .../cornellappdev/score/screen/HomeScreen.kt | 102 +++++++++++++++--- app/src/main/res/drawable/advanced_filter.xml | 13 +++ app/src/main/res/drawable/ic_round_minus.xml | 9 ++ app/src/main/res/drawable/ic_round_plus.xml | 9 ++ build.gradle.kts | 3 +- 8 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/cornellappdev/score/components/ExpandableSection.kt create mode 100644 app/src/main/res/drawable/advanced_filter.xml create mode 100644 app/src/main/res/drawable/ic_round_minus.xml create mode 100644 app/src/main/res/drawable/ic_round_plus.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d6c534f..182d1ca 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("com.google.dagger.hilt.android") id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" // this version matches your Kotlin version id("org.jetbrains.kotlin.plugin.serialization") - + id("com.google.gms.google-services") } @@ -94,6 +94,8 @@ dependencies { implementation("io.coil-kt.coil3:coil-compose:3.1.0") implementation("io.coil-kt.coil3:coil-network-okhttp:3.1.0") lintChecks(libs.compose.lint.checks) + implementation(platform("com.google.firebase:firebase-bom:34.3.0")) + implementation("com.google.firebase:firebase-analytics") } apollo { diff --git a/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt b/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt index 6c9b046..0e6e074 100644 --- a/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt +++ b/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt @@ -18,9 +18,16 @@ import com.cornellappdev.score.theme.Style.bodyMedium import com.cornellappdev.score.theme.White @Composable -fun ButtonPrimary(text: String, icon: Painter?, onClick: () -> Unit = {}) { - Button(onClick = onClick, +fun ButtonPrimary( + text: String, + icon: Painter?, + modifier: Modifier = Modifier, + onClick: () -> Unit = {} +) { + Button( + onClick = onClick, colors = ButtonDefaults.buttonColors(containerColor = CrimsonPrimary), + modifier = modifier, contentPadding = PaddingValues(12.dp) ) { if (icon != null) { diff --git a/app/src/main/java/com/cornellappdev/score/components/ExpandableSection.kt b/app/src/main/java/com/cornellappdev/score/components/ExpandableSection.kt new file mode 100644 index 0000000..7c1c671 --- /dev/null +++ b/app/src/main/java/com/cornellappdev/score/components/ExpandableSection.kt @@ -0,0 +1,66 @@ +package com.cornellappdev.score.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.RadioButton +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.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.cornellappdev.score.R + +@Composable +fun ExpandableSection(title: String, options: List) { + var expanded by remember { mutableStateOf(false) } + var selectedOption by remember { mutableStateOf("Under $20") } + + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { expanded = !expanded }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text(title, fontSize = 18.sp) + Icon( + painter = painterResource( + id = if (expanded) R.drawable.ic_round_minus else R.drawable.ic_round_plus + ), + contentDescription = if (expanded) "Collapse" else "Expand" + ) + } + + if (expanded) { + Column { + options.forEach { option -> + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { selectedOption = option } + .padding(vertical = 4.dp) + ) { + RadioButton( + selected = (selectedOption == option), + onClick = { selectedOption = option } + ) + Text(option) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt index 9e42a06..9894e2f 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt @@ -2,10 +2,12 @@ package com.cornellappdev.score.screen import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background +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.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -15,15 +17,23 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState 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.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import com.cornellappdev.score.components.ButtonPrimary import com.cornellappdev.score.components.EmptyStateBox import com.cornellappdev.score.components.ErrorState import com.cornellappdev.score.components.GameCard @@ -45,13 +55,15 @@ import com.cornellappdev.score.util.sportSelectionList import com.cornellappdev.score.viewmodel.HomeUiState import com.cornellappdev.score.viewmodel.HomeViewModel +@OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeScreen( homeViewModel: HomeViewModel = hiltViewModel(), navigateToGameDetails: (String) -> Unit = {} ) { val uiState = homeViewModel.collectUiStateValue() - + var showBottomSheet by remember { mutableStateOf(false) } + val sheetState = rememberModalBottomSheetState() Column( verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Top), modifier = Modifier @@ -72,10 +84,56 @@ fun HomeScreen( onGenderSelected = { homeViewModel.onGenderSelected(it) }, onSportSelected = { homeViewModel.onSportSelected(it) }, navigateToGameDetails = navigateToGameDetails, - onRefresh = { homeViewModel.onRefresh() } + onRefresh = { homeViewModel.onRefresh() }, + onAdvFilterClick = { showBottomSheet = true } ) } } + if (showBottomSheet) { + ModalBottomSheet( + onDismissRequest = { showBottomSheet = false }, + sheetState = sheetState + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp, top = 32.dp, bottom = 12.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + ExpandableSection( + title = "Price", + options = listOf("Unticketed", "Under $20", "Under $50", "Over $50") + ) + ExpandableSection( + title = "Location", + options = listOf("On Campus", "1-2 Hours", "2-4 Hours", "Over 4 Hours") + ) + ExpandableSection( + title = "Date of Game", + options = listOf("Today", "Within 7 Days", "Within a Month", "Over a Month") + ) + ButtonPrimary( + text = "Apply", + icon = null, + modifier = Modifier.fillMaxWidth(), + onClick = { + // TODO: Apply filter logic via ViewModel + showBottomSheet = false + } + ) + Text( + "Reset", + fontSize = 14.sp, + modifier = Modifier + .align(Alignment.CenterHorizontally) + .clickable { + // TODO: Reset filter logic + showBottomSheet = false + } + ) + } + } + } } } @@ -86,10 +144,17 @@ private fun HomeContent( onGenderSelected: (GenderDivision) -> Unit, onSportSelected: (SportSelection) -> Unit, onRefresh: () -> Unit, - navigateToGameDetails: (String) -> Unit = {} + navigateToGameDetails: (String) -> Unit = {}, + onAdvFilterClick: () -> Unit ) { ScorePullToRefreshBox(isRefreshing = uiState.loadedState == ApiResponse.Loading, onRefresh) { - HomeLazyColumn(uiState, onGenderSelected, onSportSelected, navigateToGameDetails) + HomeLazyColumn( + uiState, + onGenderSelected, + onSportSelected, + navigateToGameDetails, + onAdvFilterClick + ) } } @@ -99,7 +164,8 @@ private fun HomeLazyColumn( uiState: HomeUiState, onGenderSelected: (GenderDivision) -> Unit, onSportSelected: (SportSelection) -> Unit, - navigateToGameDetails: (String) -> Unit + navigateToGameDetails: (String) -> Unit, + onAdvFilterClick: () -> Unit ) { LazyColumn(contentPadding = PaddingValues(top = 24.dp)) { if (uiState.filteredGames.isNotEmpty()) { @@ -129,12 +195,22 @@ private fun HomeLazyColumn( .padding(horizontal = 24.dp) ) { Spacer(Modifier.height(24.dp)) - Text( - text = "Game Schedule", - style = title, - modifier = Modifier - .fillMaxWidth() - ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Game Schedule", + style = title, + ) + ButtonPrimary( + "", + painterResource(id = com.cornellappdev.score.R.drawable.advanced_filter) + ) { + onAdvFilterClick() + } + } Spacer(modifier = Modifier.height(8.dp)) SportSelectorHeader( sports = uiState.selectionList, @@ -199,6 +275,7 @@ private fun HomeScreenPreview() = ScorePreview { onGenderSelected = {}, onSportSelected = {}, onRefresh = {}, + onAdvFilterClick = {} ) } } @@ -215,7 +292,8 @@ private fun HomeScreenEmptyStatePreview() = ScorePreview { ), onGenderSelected = {}, onSportSelected = {}, - onRefresh = {} + onRefresh = {}, + onAdvFilterClick = {} ) } diff --git a/app/src/main/res/drawable/advanced_filter.xml b/app/src/main/res/drawable/advanced_filter.xml new file mode 100644 index 0000000..62010d4 --- /dev/null +++ b/app/src/main/res/drawable/advanced_filter.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_minus.xml b/app/src/main/res/drawable/ic_round_minus.xml new file mode 100644 index 0000000..cbca170 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_minus.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_plus.xml b/app/src/main/res/drawable/ic_round_plus.xml new file mode 100644 index 0000000..eb042ed --- /dev/null +++ b/app/src/main/res/drawable/ic_round_plus.xml @@ -0,0 +1,9 @@ + + + diff --git a/build.gradle.kts b/build.gradle.kts index 61d5852..648673c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,9 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { alias(libs.plugins.androidApplication) apply false - alias(libs.plugins.jetbrainsKotlinAndroid)version "1.9.10" apply false + alias(libs.plugins.jetbrainsKotlinAndroid) version "1.9.10" apply false id("com.google.dagger.hilt.android") version "2.51.1" apply false kotlin("jvm") version "2.0.20" kotlin("plugin.serialization") version "2.0.20" + id("com.google.gms.google-services") version "4.4.3" apply false } From bf86fc9294b65dbdd9fddb6f083ef46ee3162a1f Mon Sep 17 00:00:00 2001 From: Emil Jiang Date: Wed, 1 Oct 2025 17:20:05 -0400 Subject: [PATCH 3/5] center icon --- .../java/com/cornellappdev/score/components/ButtonPrimary.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt b/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt index 0e6e074..4aa4108 100644 --- a/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt +++ b/app/src/main/java/com/cornellappdev/score/components/ButtonPrimary.kt @@ -39,7 +39,9 @@ fun ButtonPrimary( .height(24.dp), colorFilter = ColorFilter.tint(White) ) - Spacer(modifier = Modifier.width(8.dp)) + if (text.isNotEmpty()) { + Spacer(modifier = Modifier.width(8.dp)) + } } Text(text = text, style = bodyMedium.copy(color = White)) } From 2f2017ddc0727f58b8633856530750895bde480b Mon Sep 17 00:00:00 2001 From: Emil Jiang Date: Wed, 1 Oct 2025 17:49:14 -0400 Subject: [PATCH 4/5] google-services.json --- app/src/google-services.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 app/src/google-services.json diff --git a/app/src/google-services.json b/app/src/google-services.json new file mode 100644 index 0000000..6d64378 --- /dev/null +++ b/app/src/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "1041954613554", + "project_id": "score-2bbd4", + "storage_bucket": "score-2bbd4.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1041954613554:android:afdaffd5c956622603cf2b", + "android_client_info": { + "package_name": "com.cornellappdev.score" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyCjJpkMnpwSVu270_k6_3UmaHXb_NiCc0I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file From 3cc61b7b8a20b794ee114a683a736bea5ffc001b Mon Sep 17 00:00:00 2001 From: Emil Jiang Date: Thu, 2 Oct 2025 11:56:18 -0400 Subject: [PATCH 5/5] fix scrollable --- .../cornellappdev/score/screen/HomeScreen.kt | 84 ++++++++++++------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt b/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt index 9894e2f..459abb3 100644 --- a/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt +++ b/app/src/main/java/com/cornellappdev/score/screen/HomeScreen.kt @@ -29,6 +29,7 @@ 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.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -36,6 +37,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.cornellappdev.score.components.ButtonPrimary import com.cornellappdev.score.components.EmptyStateBox import com.cornellappdev.score.components.ErrorState +import com.cornellappdev.score.components.ExpandableSection import com.cornellappdev.score.components.GameCard import com.cornellappdev.score.components.GamesCarousel import com.cornellappdev.score.components.LoadingScreen @@ -94,49 +96,69 @@ fun HomeScreen( onDismissRequest = { showBottomSheet = false }, sheetState = sheetState ) { - Column( + LazyColumn( modifier = Modifier .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 32.dp, bottom = 12.dp), + .padding(horizontal = 16.dp), + contentPadding = PaddingValues( + top = 32.dp, + bottom = 24.dp + ), verticalArrangement = Arrangement.spacedBy(20.dp) ) { - ExpandableSection( - title = "Price", - options = listOf("Unticketed", "Under $20", "Under $50", "Over $50") - ) - ExpandableSection( - title = "Location", - options = listOf("On Campus", "1-2 Hours", "2-4 Hours", "Over 4 Hours") - ) - ExpandableSection( - title = "Date of Game", - options = listOf("Today", "Within 7 Days", "Within a Month", "Over a Month") - ) - ButtonPrimary( - text = "Apply", - icon = null, - modifier = Modifier.fillMaxWidth(), - onClick = { - // TODO: Apply filter logic via ViewModel - showBottomSheet = false - } - ) - Text( - "Reset", - fontSize = 14.sp, - modifier = Modifier - .align(Alignment.CenterHorizontally) - .clickable { - // TODO: Reset filter logic + item { + ExpandableSection( + title = "Price", + options = listOf("Unticketed", "Under $20", "Under $50", "Over $50") + ) + } + item { + ExpandableSection( + title = "Location", + options = listOf("On Campus", "1-2 Hours", "2-4 Hours", "Over 4 Hours") + ) + } + item { + ExpandableSection( + title = "Date of Game", + options = listOf( + "Today", + "Within 7 Days", + "Within a Month", + "Over a Month" + ) + ) + } + item { + ButtonPrimary( + text = "Apply", + icon = null, + modifier = Modifier.fillMaxWidth(), + onClick = { + // TODO: Apply filter logic via ViewModel showBottomSheet = false } - ) + ) + } + item { + Text( + "Reset", fontSize = 14.sp, + modifier = Modifier + .fillMaxWidth() + .clickable { + // TODO: Reset filter logic + showBottomSheet = false + }, + textAlign = TextAlign.Center + ) + } } } } } } + @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable private fun HomeContent(