feat: integrate MatchesScreen.kt with viewmodel and match cards

This commit is contained in:
Leonardo Murça 2025-07-18 16:08:30 -03:00
parent 29a2985294
commit 15707753fc
5 changed files with 132 additions and 8 deletions

View file

@ -64,6 +64,7 @@ dependencies {
implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3) implementation(libs.androidx.material3)
implementation(libs.hilt.android) implementation(libs.hilt.android)
implementation(libs.hilt.navigation.compose)
implementation(libs.androidx.navigation.compose) implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.core.splashscreen)
implementation(libs.retrofit2) implementation(libs.retrofit2)

View file

@ -0,0 +1,20 @@
package xyz.leomurca.csgomatches.ui.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun LoadingIndicator() {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize()
) {
CircularProgressIndicator()
}
}

View file

@ -1,23 +1,82 @@
package xyz.leomurca.csgomatches.ui.screens.matches package xyz.leomurca.csgomatches.ui.screens.matches
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import xyz.leomurca.csgomatches.domain.model.Match
import xyz.leomurca.csgomatches.ui.components.LoadingIndicator
import xyz.leomurca.csgomatches.ui.components.MatchCard
import xyz.leomurca.csgomatches.ui.screens.matches.MatchesViewModel.MatchesUiState
import xyz.leomurca.csgomatches.ui.theme.White
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MatchesScreen() { fun MatchesScreen(viewModel: MatchesViewModel = hiltViewModel()) {
Box( val uiState = viewModel.uiState.collectAsState()
modifier = Modifier val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
.fillMaxSize()
.background(MaterialTheme.colorScheme.background), Scaffold(
contentAlignment = Alignment.Center modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = {
) { TopAppBar(
Text("Main Screen", fontSize = 24.sp) title = {
Text(
"Partidas",
style = MaterialTheme.typography.titleLarge,
color = White,
modifier = Modifier.padding(top = 24.dp, start = 24.dp)
)
},
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.topAppBarColors().copy(
containerColor = MaterialTheme.colorScheme.background,
scrolledContainerColor = MaterialTheme.colorScheme.background
)
)
}) { innerPadding ->
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.background(MaterialTheme.colorScheme.background),
contentAlignment = Alignment.Center
) {
when (val value = uiState.value) {
is MatchesUiState.Loading -> LoadingIndicator()
is MatchesUiState.Success -> MatchesList(value.matches)
is MatchesUiState.Error -> Text(value.message)
}
}
}
}
@Composable
private fun MatchesList(matches: List<Match>) {
LazyColumn(
Modifier
.padding(horizontal = 24.dp),
verticalArrangement = Arrangement.spacedBy(24.dp),
contentPadding = PaddingValues(vertical = 24.dp)
) {
items(matches) {
MatchCard(it.opponents, it.league, it.serie.name)
}
} }
} }

View file

@ -0,0 +1,42 @@
package xyz.leomurca.csgomatches.ui.screens.matches
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import xyz.leomurca.csgomatches.domain.model.Match
import xyz.leomurca.csgomatches.domain.model.Resource
import xyz.leomurca.csgomatches.domain.repository.MatchRepository
import javax.inject.Inject
@HiltViewModel
class MatchesViewModel @Inject constructor(
private val matchRepository: MatchRepository
) : ViewModel() {
private val _uiState = MutableStateFlow<MatchesUiState>(MatchesUiState.Loading)
val uiState: StateFlow<MatchesUiState> = _uiState.asStateFlow()
init {
loadUpcomingMatches()
}
fun loadUpcomingMatches() {
viewModelScope.launch {
_uiState.value = MatchesUiState.Loading
_uiState.value = when (val result = matchRepository.upcomingMatches()) {
is Resource.Success -> MatchesUiState.Success(result.data)
is Resource.Error -> MatchesUiState.Error(result.message)
}
}
}
sealed class MatchesUiState {
object Loading : MatchesUiState()
data class Success(val matches: List<Match>) : MatchesUiState()
data class Error(val message: String) : MatchesUiState()
}
}

View file

@ -17,6 +17,7 @@ retrofit2 = "2.11.0"
kotlinxSerializationJson = "1.8.1" kotlinxSerializationJson = "1.8.1"
okhttp = "4.12.0" okhttp = "4.12.0"
coil = "3.2.0" coil = "3.2.0"
hiltNavigation = "1.2.0"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -35,6 +36,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit
androidx-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigation" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashScreen" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashScreen" }
retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit2" } retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit2" }