Skip to content

Commit f4759ba

Browse files
authored
HomeViewModel/ScoreRepositoryRefactor (#27)
* Date functions refactor * Add Result.kt * functioning refactored HomeViewModel * Reformat code * Gradle + Library updates * Having RootNavigation Hilt/injection issues? Commented them out since they currently aren't being used * Added Result checks to ScoreRepository * Updated to display all games in LazyColumn and first 3 games in upcomingGamesHeader * small fixes * PR fixes checkpoint * HomeContent abstraction * Temp update * Date fixes * Refactored HomeViewModel with map and toGameCardData * Cleanup * Documentation + cleanup * formatColor relocation * Revisions * Revert agp version
1 parent c8de9f7 commit f4759ba

11 files changed

Lines changed: 256 additions & 205 deletions

File tree

app/src/main/java/com/cornellappdev/score/components/SportCard.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.cornellappdev.score.components
22

3-
import android.icu.text.SimpleDateFormat
43
import androidx.compose.animation.core.RepeatMode
54
import androidx.compose.animation.core.animateFloat
65
import androidx.compose.animation.core.infiniteRepeatable
@@ -9,7 +8,14 @@ import androidx.compose.animation.core.tween
98
import androidx.compose.foundation.Image
109
import androidx.compose.foundation.background
1110
import androidx.compose.foundation.border
12-
import androidx.compose.foundation.layout.*
11+
import androidx.compose.foundation.layout.Arrangement
12+
import androidx.compose.foundation.layout.Box
13+
import androidx.compose.foundation.layout.Column
14+
import androidx.compose.foundation.layout.Row
15+
import androidx.compose.foundation.layout.fillMaxWidth
16+
import androidx.compose.foundation.layout.height
17+
import androidx.compose.foundation.layout.padding
18+
import androidx.compose.foundation.layout.width
1319
import androidx.compose.foundation.shape.CircleShape
1420
import androidx.compose.foundation.shape.RoundedCornerShape
1521
import androidx.compose.material3.Card
@@ -40,8 +46,6 @@ import com.cornellappdev.score.theme.Style.labelsNormal
4046
import com.cornellappdev.score.theme.Style.teamName
4147
import com.cornellappdev.score.theme.Style.universityText
4248
import com.cornellappdev.score.theme.saturatedGreen
43-
import java.util.Date
44-
import java.util.Locale
4549

4650
@Composable
4751
fun SportCard(
@@ -101,7 +105,9 @@ fun SportCard(
101105
) {
102106
AsyncImage(
103107
model = teamLogo,
104-
modifier = Modifier.height(20.dp).padding(start = 4.dp, end = 4.dp),
108+
modifier = Modifier
109+
.height(20.dp)
110+
.padding(horizontal = 4.dp),
105111
contentDescription = ""
106112
)
107113

app/src/main/java/com/cornellappdev/score/components/UpcomingGamesCarousel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ fun UpcomingGamesCarousel(games: List<GameCardData>) {
8787
location = game.location,
8888
modifier = Modifier,
8989
headerModifier = Modifier,
90-
gradientColor1 = CornellRed, //TODO: is it okay if this is hardcoded
91-
gradientColor2 = Color(game.teamColor)
90+
gradientColor1 = CornellRed,
91+
gradientColor2 = game.teamColor
9292
)
9393
}
9494

app/src/main/java/com/cornellappdev/score/model/Game.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package com.cornellappdev.score.model
22

3-
import androidx.compose.ui.graphics.painter.Painter
3+
import androidx.compose.ui.graphics.Color
4+
import com.cornellappdev.score.R
5+
import com.cornellappdev.score.util.outputFormatter
6+
import com.cornellappdev.score.util.parseDateOrNull
47
import java.time.LocalDate
58

69
// TODO Refactor to make easier to filter... actual gender, etc.
710

811
data class Game(
912
val teamName: String,
1013
val teamLogo: String,
11-
val teamColor: String,
14+
val teamColor: Color,
1215
val gender: String,
1316
val sport: String,
1417
val date: String,
@@ -19,7 +22,7 @@ data class Game(
1922
data class GameCardData(
2023
val teamLogo: String,
2124
val team: String,
22-
val teamColor: Int,
25+
val teamColor: Color,
2326
val date: LocalDate?,
2427
val dateString: String,
2528
val isLive: Boolean,
@@ -98,4 +101,22 @@ enum class GameStatus {
98101
NOT_STARTED,
99102
IN_PROGRESS,
100103
COMPLETED
104+
}
105+
106+
fun Game.toGameCardData(): GameCardData{
107+
return GameCardData(
108+
teamLogo = teamLogo,
109+
team = teamName,
110+
teamColor = teamColor,
111+
date = parseDateOrNull(date),
112+
dateString = parseDateOrNull(date)?.format(outputFormatter)
113+
?: date,
114+
isLive = (LocalDate.now() == parseDateOrNull(date)),
115+
location = city,
116+
gender = gender,
117+
genderIcon = if (gender == "Mens") R.drawable.ic_gender_men else R.drawable.ic_gender_women,
118+
sport = sport,
119+
sportIcon = Sport.fromDisplayName(sport)?.emptyIcon
120+
?: R.drawable.ic_empty_placeholder
121+
)
101122
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.cornellappdev.score.model
2+
3+
import com.apollographql.apollo.api.ApolloResponse
4+
import com.apollographql.apollo.api.Operation
5+
import com.apollographql.apollo.exception.NoDataException
6+
7+
/**
8+
* Maps an ApolloResponse to a generic Kotlin result. It either provides the data with no errors, or
9+
* a failure response containing the error message in the throwable.
10+
*/
11+
fun <T : Operation.Data> ApolloResponse<T>.toResult(): Result<T> {
12+
if (hasErrors() || exception != null) {
13+
return Result.failure(
14+
exception?.cause ?: RuntimeException(
15+
errors?.firstOrNull()?.message ?: "Unknown error occurred"
16+
)
17+
)
18+
}
19+
return try {
20+
Result.success(dataOrThrow())
21+
} catch (e: NoDataException) {
22+
Result.failure(e)
23+
}
24+
}

app/src/main/java/com/cornellappdev/score/model/ScoreRepository.kt

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.asStateFlow
99
import kotlinx.coroutines.launch
1010
import javax.inject.Inject
1111
import javax.inject.Singleton
12+
import com.cornellappdev.score.util.parseColor
1213

1314
/**
1415
* This is a singleton responsible for fetching and caching all data for Score.
@@ -19,7 +20,6 @@ import javax.inject.Singleton
1920
@Singleton
2021
class ScoreRepository @Inject constructor(
2122
private val apolloClient: ApolloClient,
22-
// TODO use this to launch queries
2323
private val appScope: CoroutineScope,
2424
) {
2525
private val _upcomingGamesFlow =
@@ -34,28 +34,33 @@ class ScoreRepository @Inject constructor(
3434
fun fetchGames() = appScope.launch {
3535
_upcomingGamesFlow.value = ApiResponse.Loading
3636
try {
37-
val response = (apolloClient.query(GamesQuery()).execute())
38-
val games = response.data?.games ?: emptyList()
39-
Log.d("ScoreRepository", "response fetched successfully")
37+
val result = (apolloClient.query(GamesQuery()).execute()).toResult()
4038

41-
val list: List<Game> = games.mapNotNull { game ->
42-
game?.team?.image?.let {
43-
Game(
44-
teamLogo = it,//game.team.image,
45-
teamName = game.team.name,
46-
teamColor = game.team.color,
47-
gender = game.gender,
48-
sport = game.sport,
49-
date = game.date,
50-
city = game.city
51-
)
52-
}
39+
if (result.isSuccess) {
40+
val games = result.getOrNull()
41+
42+
val upcomingGameslist: List<Game> =
43+
games?.games?.mapNotNull { game ->
44+
game?.team?.image?.let {
45+
Game(
46+
teamLogo = it,
47+
teamName = game.team.name,
48+
teamColor = parseColor(game.team.color).copy(alpha = 0.4f*255),
49+
gender = game.gender,
50+
sport = game.sport,
51+
date = game.date,
52+
city = game.city
53+
)
54+
}
55+
} ?: emptyList()
56+
_upcomingGamesFlow.value = ApiResponse.Success(upcomingGameslist)
57+
} else {
58+
_upcomingGamesFlow.value = ApiResponse.Error
5359
}
54-
Log.d("ScoreRepository", "#games: ${list.size}")
55-
_upcomingGamesFlow.value = ApiResponse.Success(list.toList())
60+
5661
} catch (e: Exception) {
5762
Log.e("ScoreRepository", "Error fetching posts: ", e)
5863
_upcomingGamesFlow.value = ApiResponse.Error
5964
}
6065
}
61-
}
66+
}

app/src/main/java/com/cornellappdev/score/nav/root/RootNavigation.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.cornellappdev.score.nav.root
22

3-
import android.os.Build
4-
import androidx.annotation.RequiresApi
53
import androidx.compose.runtime.Composable
64
import androidx.compose.runtime.LaunchedEffect
75
import androidx.hilt.navigation.compose.hiltViewModel
@@ -11,7 +9,6 @@ import androidx.navigation.compose.rememberNavController
119
import com.cornellappdev.score.screen.HomeScreen
1210
import kotlinx.serialization.Serializable
1311

14-
@RequiresApi(Build.VERSION_CODES.O)
1512
@Composable
1613
fun RootNavigation(
1714
rootNavigationViewModel: RootNavigationViewModel = hiltViewModel(),

0 commit comments

Comments
 (0)