diff --git a/app/src/main/java/com/ti/mobpo/ui/PokeSearchViewModel.kt b/app/src/main/java/com/ti/mobpo/ui/PokeSearchViewModel.kt index 86cea18..9bb19f5 100644 --- a/app/src/main/java/com/ti/mobpo/ui/PokeSearchViewModel.kt +++ b/app/src/main/java/com/ti/mobpo/ui/PokeSearchViewModel.kt @@ -1,60 +1,68 @@ package com.ti.mobpo.ui import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.google.gson.annotations.SerializedName import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import retrofit2.Call +import kotlinx.coroutines.launch import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET +import java.io.IOException -// Data class to hold Pokemon species information +private const val BASE_URL = "https://pokeapi.co/api/v2/"; data class PokemonSpecies( @SerializedName("name") val name: String, @SerializedName("url") val url: String ) -// Data class to hold the response from the Pokemon species API data class PokemonSpeciesResponse( @SerializedName("results") val results: List ) interface PokeApiService { @GET("pokemon-species/?offset=0&limit=1025") - fun getPokemonSpecies(): Call + suspend fun getPokemonSpecies(): PokemonSpeciesResponse } class PokeSearchViewModel : ViewModel() { private val retrofit = Retrofit.Builder() - .baseUrl("https://pokeapi.co/api/v2/") + .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() private val service = retrofit.create(PokeApiService::class.java) - private val _uiState = MutableStateFlow(PokeSearchUiState()) - val uiState: StateFlow = _uiState.asStateFlow() + private val _initialPokemonList = MutableStateFlow?>(null) + private val _filteredPokemonList = MutableStateFlow?>(null) - private var pokemonList: List? = null + val pokemonList: StateFlow?> = _filteredPokemonList.asStateFlow() init { fetchPokemonSpecies() } private fun fetchPokemonSpecies() { - service.getPokemonSpecies().enqueue(object : retrofit2.Callback { - override fun onResponse(call: Call, response: retrofit2.Response) { - if (response.isSuccessful) { - val speciesResponse = response.body() - pokemonList = speciesResponse?.results - } - } - - override fun onFailure(call: Call, t: Throwable) { + viewModelScope.launch { + try { + val response = service.getPokemonSpecies() + _initialPokemonList.value = response.results + _filteredPokemonList.value = response.results + } catch (e: IOException) { /*TODO*/ } - }) + } } -} + + fun search(query: String) { + val initialPokemonList = _initialPokemonList.value + if (query.isNotBlank() && initialPokemonList != null) { + val filteredList = initialPokemonList.filter { it.name.contains(query, ignoreCase = true) } + _filteredPokemonList.value = filteredList + } else { + _filteredPokemonList.value = initialPokemonList + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ti/mobpo/ui/screens/PokeSearch.kt b/app/src/main/java/com/ti/mobpo/ui/screens/PokeSearch.kt index c79f9a1..e4f4d8e 100644 --- a/app/src/main/java/com/ti/mobpo/ui/screens/PokeSearch.kt +++ b/app/src/main/java/com/ti/mobpo/ui/screens/PokeSearch.kt @@ -1,9 +1,13 @@ package com.ti.mobpo.ui.screens +import com.ti.mobpo.ui.PokeSearchViewModel import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -15,30 +19,41 @@ import androidx.compose.ui.unit.dp import com.ti.mobpo.R import com.ti.mobpo.ui.SearchBar import androidx.lifecycle.viewmodel.compose.viewModel -import com.ti.mobpo.ui.PokeSearchViewModel @Composable -fun PokeSearchScreen(pokesearchViewModel: PokeSearchViewModel = viewModel()){ - val pokesearchUiState by pokesearchViewModel.uiState.collectAsState() - PokeSearch() +fun PokeSearchScreen(pokeSearchViewModel: PokeSearchViewModel = viewModel()) { + PokeSearch(pokeSearchViewModel) } @Composable -fun PokeSearch() { - Column ( +fun PokeSearch(pokeSearchViewModel: PokeSearchViewModel = viewModel()) { + val searchResults by pokeSearchViewModel.pokemonList.collectAsState() + + Column( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxSize() .padding(20.dp) ) { - SearchBar(stringResource(R.string.input_field_label)){ value -> - run { - println(value) + SearchBar(stringResource(R.string.input_field_label)) { value -> + pokeSearchViewModel.search(value) + } + + Spacer(modifier = Modifier.height(16.dp)) + + searchResults?.let { results -> + if (results.isNotEmpty()) { + results.forEach { pokemon -> + Text(text = pokemon.name) + } + } else { + Text("No results found") } } } } + @Preview(showBackground = true) @Composable fun PokeSearchApp(){