mirror of
https://github.com/AdrianKuta/android-challange-adrian-kuta.git
synced 2025-07-01 20:58:00 +02:00
feat: Implement stations screen with grouped airports
This commit introduces a new "Stations" screen that displays airports grouped by country. Key changes: - Added a new Gradle module: `ui:stations`. - Created `StationsScreen.kt` to display a list of airports grouped by country using `LazyColumn`. Airports within each country are displayed as `AirportInfoItem` and countries as `CountryItem`. - Implemented `StationsScreenViewModel.kt` to fetch and manage the state of airports grouped by country. It uses `ObserveAirportsGroupedByCountry` use case. - Defined `ObserveAirportsGroupedByCountry.kt` use case in `domain:stations` module to provide a flow of airports grouped by country. - Implemented `ObserveAirportsGroupedByCountryImpl.kt` in the repository layer, which fetches data using `AirportService`, stores it in `AirportsDatasource`, and maps it to the domain model. - Added Hilt module `ObserveAirportsGroupedByCountryModule.kt` to provide the use case implementation. - Added `stationsScreen()` and `navigateToStations()` to `FlightsNavGraph.kt` and `TopLevelDestination.kt` for navigation. - Updated `settings.gradle.kts` and `app/build.gradle.kts` to include the new `ui:stations` and `domain:stations` modules. - Updated `CacheObservers.kt` to make `mapToDomain` a suspend function. - Added string resources for the stations screen title.
This commit is contained in:
@ -8,7 +8,9 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.util)
|
||||
implementation(projects.domain.search)
|
||||
implementation(projects.domain.stations)
|
||||
implementation(projects.model.data.api)
|
||||
implementation(projects.model.datasource.airports)
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
package dev.adriankuta.flights.model.repository.di
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dev.adriankuta.flights.domain.stations.ObserveAirportsGroupedByCountry
|
||||
import dev.adriankuta.flights.model.repository.usecases.ObserveAirportsGroupedByCountryImpl
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Suppress("UnnecessaryAbstractClass")
|
||||
internal abstract class ObserveAirportsGroupedByCountryModule {
|
||||
|
||||
@Binds
|
||||
abstract fun bind(
|
||||
observeAirportsGroupedByCountryImpl: ObserveAirportsGroupedByCountryImpl,
|
||||
): ObserveAirportsGroupedByCountry
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package dev.adriankuta.flights.model.repository.usecases
|
||||
|
||||
import dev.adriankuta.flights.core.util.DefaultDispatcher
|
||||
import dev.adriankuta.flights.domain.stations.ObserveAirportsGroupedByCountry
|
||||
import dev.adriankuta.flights.domain.types.AirportInfo
|
||||
import dev.adriankuta.flights.domain.types.Country
|
||||
import dev.adriankuta.flights.model.datasource.airports.AirportsDatasource
|
||||
import dev.adriankuta.flights.model.datasource.airports.entities.AirportInfoModel
|
||||
import dev.adriankuta.flights.model.repository.mappers.toDomain
|
||||
import dev.adriankuta.flights.model.repository.utilities.loadData
|
||||
import dev.adriankuta.model.data.api.AirportService
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class ObserveAirportsGroupedByCountryImpl @Inject constructor(
|
||||
private val airportService: AirportService,
|
||||
private val airportsDatasource: AirportsDatasource,
|
||||
@DefaultDispatcher private val dispatcher: CoroutineDispatcher,
|
||||
) : ObserveAirportsGroupedByCountry {
|
||||
override fun invoke(): Flow<Map<Country, List<AirportInfo>>?> = loadData(
|
||||
onCacheInvalidated = { cacheKey ->
|
||||
val response = airportService.getAirports("pl")
|
||||
airportsDatasource.setAirportsInfo(response, cacheKey)
|
||||
},
|
||||
observeCache = {
|
||||
airportsDatasource.airports
|
||||
},
|
||||
mapToDomain = { model ->
|
||||
withContext(dispatcher) {
|
||||
model.orEmpty().map(AirportInfoModel::toDomain).groupBy { airportInfo ->
|
||||
airportInfo.country
|
||||
}.toSortedMap(compareBy { it.name })
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
@ -9,7 +9,7 @@ import kotlinx.datetime.Clock
|
||||
internal fun <T, R> loadData(
|
||||
onCacheInvalidated: suspend (cacheKey: String) -> Unit,
|
||||
observeCache: () -> Flow<Cache<T>>,
|
||||
mapToDomain: (T?) -> R?,
|
||||
mapToDomain: suspend (T?) -> R?,
|
||||
): Flow<R?> {
|
||||
return observeCache().distinctUntilChanged().map {
|
||||
if (it.cacheKey == null) {
|
||||
|
Reference in New Issue
Block a user