mirror of
https://github.com/AdrianKuta/android-challange-adrian-kuta.git
synced 2025-07-02 05:28:00 +02:00
feat: Implement airport data fetching and display
This commit introduces the functionality to fetch airport data from the Ryanair API and display it in the UI. Key changes: - Added `AirportInfoModel` interface and its implementation `AirportInfoModelImpl` to represent airport data in the data layer. - Created `AirportInfoModelMapper` to map `AirportResponse` to `AirportInfoModel`. - Set the base URL for Retrofit in `NetworkModule` to `https://services-api.ryanair.com`. - Added new Gradle modules: `model:data:shared`, `model:datasource:airports`, `model:datasource:shared`, and `domain:search`. - Implemented `CacheImpl` in `model:data:shared` for generic caching. - Defined `ObserveAirportsUseCase` interface in `domain:search` to observe airport data. - Added Detekt configuration for the `domain:search` and `model:datasource:shared` modules. - Created `AirportsDatasource` interface and its implementation `AirportsDatasourceImpl` to manage airport data. - Implemented `AirportInfoDomainMapper` to map `AirportInfoModel` to the domain `AirportInfo`. - Updated `HomeScreen` to display a list of airports using `LazyColumn`. - Updated `HomeScreenViewModel` to fetch and expose airport data via `ObserveAirportsUseCase`. - Added `ObserveAirportsUseCaseModule` to provide the `ObserveAirportsUseCase` implementation. - Implemented `ObserveAirportsUseCaseImpl` in the repository layer to fetch data from the API and update the datasource. - Added `kotlinx-datetime` dependency. - Created `AirportsDatasourceModule` to provide `AirportsDatasource` and its implementation. - Added `CacheObservers.kt` with a utility function `loadData` to handle cache observation and data loading logic. - Updated dependencies in `model:data:simple`, `model:repository`, and `ui:home` build files. - Updated `settings.gradle.kts` to include new modules. - Defined `Cache` interface in `model:datasource:shared`.
This commit is contained in:
@ -10,6 +10,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation(projects.ui.designsystem)
|
||||
implementation(projects.domain.search)
|
||||
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
implementation(libs.timber)
|
||||
|
@ -1,7 +1,14 @@
|
||||
package dev.adriankuta.flights.ui.home
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import dev.adriankuta.flights.domain.types.AirportInfo
|
||||
import dev.adriankuta.flights.ui.designsystem.theme.FlightsTheme
|
||||
import dev.adriankuta.flights.ui.designsystem.theme.PreviewDevices
|
||||
|
||||
@ -9,12 +16,31 @@ import dev.adriankuta.flights.ui.designsystem.theme.PreviewDevices
|
||||
internal fun HomeScreen(
|
||||
viewModel: HomeScreenViewModel = hiltViewModel(),
|
||||
) {
|
||||
val homeUiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
HomeScreen(
|
||||
airports = homeUiState.airports
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HomeScreen(
|
||||
airports: List<AirportInfo>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LazyColumn {
|
||||
items(airports) { airport ->
|
||||
Text(airport.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewDevices
|
||||
@Composable
|
||||
private fun HomeScreenPreview() {
|
||||
FlightsTheme {
|
||||
HomeScreen()
|
||||
HomeScreen(
|
||||
airports = listOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,47 @@
|
||||
package dev.adriankuta.flights.ui.home
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dev.adriankuta.flights.domain.search.ObserveAirportsUseCase
|
||||
import dev.adriankuta.flights.domain.types.AirportInfo
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@HiltViewModel
|
||||
class HomeScreenViewModel @Inject constructor() : ViewModel()
|
||||
class HomeScreenViewModel @Inject constructor(
|
||||
private val observeAirportsUseCase: ObserveAirportsUseCase
|
||||
) : ViewModel() {
|
||||
|
||||
internal val uiState = homeUiState(
|
||||
useCase = observeAirportsUseCase
|
||||
)
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = HomeUiState(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun homeUiState(
|
||||
useCase: ObserveAirportsUseCase
|
||||
): Flow<HomeUiState> {
|
||||
|
||||
return flow {
|
||||
delay(15.seconds)
|
||||
emit("")
|
||||
}.flatMapLatest { useCase() }.map {
|
||||
HomeUiState(it.orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
internal data class HomeUiState(
|
||||
val airports: List<AirportInfo> = emptyList()
|
||||
)
|
||||
|
Reference in New Issue
Block a user