Skip to content

Commit

Permalink
Merge pull request #516 from BCSDLab/feature/bus-timetable-detail
Browse files Browse the repository at this point in the history
[Feature] 버스 도메인 리뉴얼
  • Loading branch information
ThirFir authored Dec 25, 2024
2 parents 09e1276 + e26e6c0 commit 37f5ee0
Show file tree
Hide file tree
Showing 129 changed files with 3,954 additions and 1,264 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
*/
@Composable
fun TextChip(
modifier: Modifier = Modifier,
title: String,
modifier: Modifier = Modifier,
isSelected: Boolean = false,
shape: Shape = RoundedCornerShape(50),
showClickRipple: Boolean = true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package `in`.koreatech.koin.core.designsystem.util

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.Dp

/**
* TextStyle에 대한 한글 텍스트 높이를 Dp로 반환
*/
@Composable
fun TextStyle.getMeasuredKoreanHeightDp(): Dp {
return with(rememberTextMeasurer()) {
with(LocalDensity.current) {
measure(
"", this@getMeasuredKoreanHeightDp
).size.height.toDp()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class WebViewActivity : ActivityBase(R.layout.activity_webview) {

@SuppressLint("SetJavaScriptEnabled")
private fun init(title: String?, url: String?) {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setTitle(title)

binding.webView.apply {
Expand Down
45 changes: 45 additions & 0 deletions data/src/main/java/in/koreatech/koin/data/api/BusV2Api.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package `in`.koreatech.koin.data.api

import `in`.koreatech.koin.data.response.bus.v2.BusNoticeResponse
import `in`.koreatech.koin.data.response.bus.v2.BusSearchResultWrapperResponse
import `in`.koreatech.koin.data.response.bus.v2.CityTimetableResponse
import `in`.koreatech.koin.data.response.bus.v2.ExpressTimetableResponse
import `in`.koreatech.koin.data.response.bus.v2.ShuttleCoursesResponse
import `in`.koreatech.koin.data.response.bus.v2.ShuttleTimetableResponse
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface BusV2Api {

@GET("bus/notice")
suspend fun fetchBusNotice(): BusNoticeResponse

@GET("bus/timetable/shuttle/{id}")
suspend fun fetchShuttleTimetable(
@Path("id") id: String
): ShuttleTimetableResponse

@GET("bus/courses/shuttle")
suspend fun fetchShuttleCourses(): ShuttleCoursesResponse

@GET("bus/timetable/v2?bus_type=EXPRESS&region=null")
suspend fun fetchExpressTimetable(
@Query("direction") direction: String,
): ExpressTimetableResponse

@GET("bus/timetable/city")
suspend fun fetchCityTimetable(
@Query("bus_number") busNumber: Int,
@Query("direction") direction: String,
): CityTimetableResponse

@GET("bus/route")
suspend fun fetchBusSearchResult(
@Query("date") date: String,
@Query("time") time: String,
@Query("bus_type") busType: String,
@Query("depart") departure: String,
@Query("arrival") arrival: String
): BusSearchResultWrapperResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import `in`.koreatech.koin.data.source.datastore.ArticleDataStore
import `in`.koreatech.koin.data.source.datastore.BusDataStore
import `in`.koreatech.koin.data.source.datastore.TimetableDataStore
import javax.inject.Singleton

Expand All @@ -25,6 +26,10 @@ object DataStoreModule {
name = "timetables"
)

private val Context.busDataStore: DataStore<Preferences> by preferencesDataStore(
name = "bus.ds"
)

@Provides
@Singleton
fun provideArticleDataStore(
Expand All @@ -40,4 +45,12 @@ object DataStoreModule {
): TimetableDataStore {
return TimetableDataStore(context.timetableDataStore)
}

@Provides
@Singleton
fun provideBusDataStore(
@ApplicationContext context: Context
): BusDataStore {
return BusDataStore(context.busDataStore)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ object NoAuthNetworkModule {
return retrofit.create(BusApi::class.java)
}

@Provides
@Singleton
fun provideBusV2Api(
@NoAuth retrofit: Retrofit
): BusV2Api {
return retrofit.create(BusV2Api::class.java)
}

@Provides
@Singleton
fun provideStoreApi(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import dagger.BindsInstance
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import `in`.koreatech.koin.data.repository.BusV2RepositoryImpl
import `in`.koreatech.koin.data.repository.TimetableRepositoryImpl
import `in`.koreatech.koin.data.repository.firebase.messaging.FirebaseMessagingRepositoryImpl
import `in`.koreatech.koin.domain.repository.BusV2Repository
import `in`.koreatech.koin.domain.repository.TimetableRepository
import `in`.koreatech.koin.domain.repository.firebase.messaging.FirebaseMessagingRepository
import javax.inject.Singleton
Expand All @@ -25,4 +27,10 @@ abstract class BindsRepositoryModule {
abstract fun bindsTimetableRepository(
timetableRepositoryImpl: TimetableRepositoryImpl
): TimetableRepository

@Binds
@Singleton
abstract fun bindsBusV2Repository(
busV2RepositoryImpl: BusV2RepositoryImpl
): BusV2Repository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package `in`.koreatech.koin.data.repository

import `in`.koreatech.koin.data.source.local.BusV2LocalDataSource
import `in`.koreatech.koin.data.source.remote.BusV2RemoteDataSource
import `in`.koreatech.koin.domain.model.bus.v2.BusNotice
import `in`.koreatech.koin.domain.model.bus.v2.BusSearchResult
import `in`.koreatech.koin.domain.model.bus.v2.CityTimetable
import `in`.koreatech.koin.domain.model.bus.v2.ExpressTimetable
import `in`.koreatech.koin.domain.model.bus.v2.ShuttleCourses
import `in`.koreatech.koin.domain.model.bus.v2.ShuttleTimetable
import `in`.koreatech.koin.domain.repository.BusV2Repository
import java.time.LocalDate
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import javax.inject.Inject

class BusV2RepositoryImpl @Inject constructor(
private val busRemoteDataSource: BusV2RemoteDataSource,
private val busLocalDataSource: BusV2LocalDataSource
) : BusV2Repository {

override suspend fun fetchBusNotice(): Result<BusNotice> {
return runCatching {
busRemoteDataSource.fetchBusNotice().toBusNotice()
}
}

override suspend fun fetchShuttleTimetable(id: String): Result<ShuttleTimetable> {
return runCatching {
busRemoteDataSource.fetchShuttleTimetable(id).toShuttleTimetable()
}
}

override suspend fun fetchShuttleCourses(): Result<ShuttleCourses> {
return runCatching {
busRemoteDataSource.fetchShuttleCourses().toShuttleCourses()
}
}

override suspend fun fetchExpressTimetable(direction: String): Result<ExpressTimetable> {
return runCatching {
busRemoteDataSource.fetchExpressTimetable(direction).toExpressTimetable()
}
}

override suspend fun fetchCityTimetable(number: Int, direction: String): Result<CityTimetable> {
return runCatching {
busRemoteDataSource.fetchCityTimetable(number, direction).toCityTimetable()
}
}

override suspend fun fetchBusSearchResult(
date: LocalDate,
time: LocalTime,
busType: String,
departure: String,
arrival: String
): Result<List<BusSearchResult>> {
return runCatching {
busRemoteDataSource.fetchBusSearchResult(
date = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(date),
time = DateTimeFormatter.ofPattern("HH:mm").format(time),
busType = busType,
departure = departure,
arrival = arrival
).schedules?.map { it.toBusSearchResult() }.orEmpty()
}
}

override suspend fun getLastShownNoticeId(): Result<Int> {
return runCatching {
busLocalDataSource.getLastShownNoticeId()
}
}

override suspend fun saveLastShownNoticeId(id: Int): Result<Unit> {
return runCatching {
busLocalDataSource.saveLastShownNoticeId(id)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package `in`.koreatech.koin.data.response.bus

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.CityBusInfoV2

data class CityBusInfoResponseV2(
@SerializedName("number") val number: Int,
@SerializedName("depart_node") val departNode: String,
@SerializedName("arrival_node") val arriveNode: String,
) {

fun toCityBusInfoV2() = CityBusInfoV2(
number = number,
departNode = departNode,
arriveNode = arriveNode,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.BusNotice
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

data class BusNoticeResponse(
@SerializedName("id") val id: Int,
@SerializedName("title") val title: String
) {

fun toBusNotice() = BusNotice(id, title)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.BusSearchResult
import java.time.LocalTime

data class BusSearchResultWrapperResponse(
@SerializedName("depart") val departure: String?,
@SerializedName("arrival") val arrival: String?,
@SerializedName("depart_date") val departDate: String?,
@SerializedName("depart_time") val departTime: String?,
@SerializedName("schedule") val schedules: List<BusSearchResultResponse>?,
)

data class BusSearchResultResponse(
@SerializedName("bus_type") val busType: String?,
@SerializedName("bus_name") val busName: String?,
@SerializedName("depart_time") val departureTime: String?,
) {
fun toBusSearchResult() = BusSearchResult(
busType = busType.orEmpty(),
busName = busName.orEmpty(),
departureTime = LocalTime.parse(departureTime)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.CityTimetableItem

data class CityTimetableItemResponse(
@SerializedName("day_of_week") val dayOfWeek: String?,
@SerializedName("depart_info") val departureTimes: List<String>?
) {
fun toCityTimetableItem() = CityTimetableItem(
dayOfWeek = dayOfWeek.orEmpty(),
departureTimes = departureTimes.orEmpty()
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.data.response.bus.CityBusInfoResponseV2
import `in`.koreatech.koin.domain.model.bus.CityBusInfoV2
import `in`.koreatech.koin.domain.model.bus.v2.CityTimetable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

data class CityTimetableResponse(
@SerializedName("bus_timetables") val timetable: List<CityTimetableItemResponse>?,
@SerializedName("bus_info") val busInfo: CityBusInfoResponseV2?,
@SerializedName("updated_at") val updatedAt: String?,
) {
fun toCityTimetable() = CityTimetable(
timetable = timetable?.map { it.toCityTimetableItem() }.orEmpty(),
busInfo = busInfo?.toCityBusInfoV2() ?: CityBusInfoV2(0, "", ""),
updatedAt = LocalDateTime.parse(updatedAt ?: "1999-04-29 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.ExpressTimetableItem
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

data class ExpressTimetableItemResponse(
@SerializedName("arrival") val arrivalTime: String?,
@SerializedName("departure") val departureTime: String?,
@SerializedName("charge") val charge: Int?,
) {
fun toExpressTimetableItem() = ExpressTimetableItem(
arrivalTime = arrivalTime ?: "",
departureTime = departureTime ?: "",
charge = charge ?: 0,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.ExpressTimetable
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

data class ExpressTimetableResponse(
@SerializedName("bus_timetables") val timetable: List<ExpressTimetableItemResponse>?,
@SerializedName("updated_at") val updatedAt: String?,
) {
fun toExpressTimetable() = ExpressTimetable(
timetable = timetable?.map { it.toExpressTimetableItem() }.orEmpty(),
updatedAt = LocalDateTime.parse(updatedAt ?: "1999-04-29 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package `in`.koreatech.koin.data.response.bus.v2

import com.google.gson.annotations.SerializedName
import `in`.koreatech.koin.domain.model.bus.v2.ShuttleCourse
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

data class ShuttleCourseResponse(
@SerializedName("region") val region: String?,
@SerializedName("routes") val routes: List<ShuttleCourseRouteResponse>?
) {
fun toShuttleCourse() = ShuttleCourse(
region = region.orEmpty(),
routes = routes?.map { it.toShuttleCourseRoute() }.orEmpty()
)
}
Loading

0 comments on commit 37f5ee0

Please sign in to comment.