diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c5db018..b498ea6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -64,6 +64,7 @@ dependencies { implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.hilt.android) + implementation(libs.hilt.navigation.compose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.core.splashscreen) implementation(libs.retrofit2) diff --git a/app/src/main/java/xyz/leomurca/csgomatches/ui/components/LoadingIndicator.kt b/app/src/main/java/xyz/leomurca/csgomatches/ui/components/LoadingIndicator.kt new file mode 100644 index 0000000..4a58048 --- /dev/null +++ b/app/src/main/java/xyz/leomurca/csgomatches/ui/components/LoadingIndicator.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesScreen.kt b/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesScreen.kt index c691d4d..2b3c902 100644 --- a/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesScreen.kt +++ b/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesScreen.kt @@ -1,23 +1,82 @@ package xyz.leomurca.csgomatches.ui.screens.matches import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues 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.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment 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 +fun MatchesScreen(viewModel: MatchesViewModel = hiltViewModel()) { + val uiState = viewModel.uiState.collectAsState() + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { + TopAppBar( + 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 -fun MatchesScreen() { - Box( - modifier = Modifier - .fillMaxSize() - .background(MaterialTheme.colorScheme.background), - contentAlignment = Alignment.Center +private fun MatchesList(matches: List) { + LazyColumn( + Modifier + .padding(horizontal = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp), + contentPadding = PaddingValues(vertical = 24.dp) ) { - Text("Main Screen", fontSize = 24.sp) + items(matches) { + MatchCard(it.opponents, it.league, it.serie.name) + } } } \ No newline at end of file diff --git a/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesViewModel.kt b/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesViewModel.kt new file mode 100644 index 0000000..c5c7e13 --- /dev/null +++ b/app/src/main/java/xyz/leomurca/csgomatches/ui/screens/matches/MatchesViewModel.kt @@ -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.Loading) + val uiState: StateFlow = _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) : MatchesUiState() + data class Error(val message: String) : MatchesUiState() + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a6e83c..4d468cd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,7 @@ retrofit2 = "2.11.0" kotlinxSerializationJson = "1.8.1" okhttp = "4.12.0" coil = "3.2.0" +hiltNavigation = "1.2.0" [libraries] 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" } 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-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-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashScreen" } retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit2" }