mirror of
https://github.com/AdrianKuta/android-challange-adrian-kuta.git
synced 2025-07-02 05:47:59 +02:00
feat: Implement flight search functionality
This commit introduces the ability to search for flights based on user-defined criteria. Key changes: - Added `GetFlightsSearchContentUseCase` interface in the domain layer and its implementation `GetFlightsSearchContentUseCaseImpl` in the repository layer to handle flight search logic. - Implemented `FlightDomainMapper` to map `FlightResponse` from the API to the domain `Flight` model. - Updated `NetworkModule`: - Introduced `ServicesAPI` and `NativeAppsAPI` qualifiers to differentiate between Retrofit instances for different Ryanair APIs. - Configured a new Retrofit instance for the `nativeapps.ryanair.com` base URL. - Modified `FlightService` to use the `nativeapps.ryanair.com` base URL. - Updated `FlightService` endpoint to `api/v4/en-gb/Availability`. - Integrated `GetFlightsSearchContentUseCase` into `HomeScreenViewModel` to trigger flight searches. - Created `SearchOptions` data class in the domain layer to encapsulate search parameters. - Added `GetFlightsSearchContentUseCaseModule` to provide the use case implementation via Hilt.
This commit is contained in:
@ -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.search.GetFlightsSearchContentUseCase
|
||||
import dev.adriankuta.flights.model.repository.usecases.GetFlightsSearchContentUseCaseImpl
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Suppress("UnnecessaryAbstractClass")
|
||||
internal abstract class GetFlightsSearchContentUseCaseModule {
|
||||
|
||||
@Binds
|
||||
abstract fun bind(
|
||||
getFlightsSearchContentUseCaseImpl: GetFlightsSearchContentUseCaseImpl,
|
||||
): GetFlightsSearchContentUseCase
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package dev.adriankuta.flights.model.repository.mappers
|
||||
|
||||
import dev.adriankuta.flights.domain.types.Flight
|
||||
import dev.adriankuta.flights.domain.types.RegularFare
|
||||
import dev.adriankuta.flights.domain.types.Segment
|
||||
import dev.adriankuta.flights.domain.types.Trip
|
||||
import dev.adriankuta.flights.domain.types.TripDate
|
||||
import dev.adriankuta.flights.domain.types.TripFare
|
||||
import dev.adriankuta.flights.domain.types.TripFlight
|
||||
import dev.adriankuta.model.data.api.entities.FlightResponse
|
||||
import dev.adriankuta.model.data.api.entities.RegularFare as ApiRegularFare
|
||||
import dev.adriankuta.model.data.api.entities.Segment as ApiSegment
|
||||
import dev.adriankuta.model.data.api.entities.Trip as ApiTrip
|
||||
import dev.adriankuta.model.data.api.entities.TripDate as ApiTripDate
|
||||
import dev.adriankuta.model.data.api.entities.TripFare as ApiTripFare
|
||||
import dev.adriankuta.model.data.api.entities.TripFlight as ApiTripFlight
|
||||
|
||||
internal fun FlightResponse.toDomain(): Flight {
|
||||
return Flight(
|
||||
currency = currency ?: "",
|
||||
currPrecision = currPrecision ?: 0,
|
||||
trips = trips.orEmpty().map { it.toDomain() },
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiTrip.toDomain(): Trip {
|
||||
return Trip(
|
||||
dates = dates.orEmpty().map { it.toDomain() },
|
||||
origin = origin ?: "",
|
||||
destination = destination ?: "",
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiTripDate.toDomain(): TripDate {
|
||||
return TripDate(
|
||||
dateOut = dateOut ?: "",
|
||||
flights = flights.orEmpty().map { it.toDomain() },
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiTripFlight.toDomain(): TripFlight {
|
||||
return TripFlight(
|
||||
faresLeft = faresLeft ?: 0,
|
||||
regularFare = regularFare?.toDomain() ?: RegularFare(emptyList()),
|
||||
flightNumber = flightNumber ?: "",
|
||||
dateTimes = dateTimes.orEmpty(),
|
||||
duration = duration ?: "",
|
||||
segments = segments.orEmpty().map { it.toDomain() },
|
||||
operatedBy = operatedBy ?: "",
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiRegularFare.toDomain(): RegularFare {
|
||||
return RegularFare(
|
||||
fares = fares.orEmpty().map { it.toDomain() },
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiTripFare.toDomain(): TripFare {
|
||||
return TripFare(
|
||||
type = type ?: "",
|
||||
amount = amount ?: 0.0,
|
||||
count = count ?: 0,
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ApiSegment.toDomain(): Segment {
|
||||
return Segment(
|
||||
origin = origin ?: "",
|
||||
destination = destination ?: "",
|
||||
flightNumber = flightNumber ?: "",
|
||||
dateTimes = dateTimes.orEmpty(),
|
||||
duration = duration ?: "",
|
||||
)
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package dev.adriankuta.flights.model.repository.usecases
|
||||
|
||||
import dev.adriankuta.flights.domain.search.GetFlightsSearchContentUseCase
|
||||
import dev.adriankuta.flights.domain.search.entities.SearchOptions
|
||||
import dev.adriankuta.flights.domain.types.Flight
|
||||
import dev.adriankuta.flights.model.repository.mappers.toDomain
|
||||
import dev.adriankuta.model.data.api.FlightService
|
||||
import java.time.format.DateTimeFormatter
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class GetFlightsSearchContentUseCaseImpl @Inject constructor(
|
||||
private val flightService: FlightService,
|
||||
) : GetFlightsSearchContentUseCase {
|
||||
|
||||
override suspend fun invoke(searchOptions: SearchOptions): Flight {
|
||||
val result = flightService.getFlights(
|
||||
origin = searchOptions.origin.code,
|
||||
destination = searchOptions.destination.code,
|
||||
date = searchOptions.date.format(DateTimeFormatter.ISO_DATE),
|
||||
adult = searchOptions.adults,
|
||||
teen = searchOptions.teens,
|
||||
child = searchOptions.children,
|
||||
)
|
||||
|
||||
return result.toDomain()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user