Skip to content

Commit

Permalink
Merge pull request #348 from BCSDLab/feature/dining-notice
Browse files Browse the repository at this point in the history
[Feature] 학식당 운영시간 구현
  • Loading branch information
wateralsie authored Aug 13, 2024
2 parents bc2a80a + fcdc6be commit 92d23be
Show file tree
Hide file tree
Showing 51 changed files with 904 additions and 65 deletions.
5 changes: 5 additions & 0 deletions core/src/main/res/drawable/line_gray15_1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="1dp" />
<solid android:color="@color/gray15" />
</shape>
14 changes: 14 additions & 0 deletions data/src/main/java/in/koreatech/koin/data/api/CoopShopApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package `in`.koreatech.koin.data.api

import `in`.koreatech.koin.data.constant.URLConstant
import `in`.koreatech.koin.data.response.coopshop.CoopShopResponse
import retrofit2.http.GET
import retrofit2.http.Path

interface CoopShopApi {
@GET(URLConstant.COOPSHOP)
suspend fun getCoopShopAll(): List<CoopShopResponse>

@GET("${URLConstant.COOPSHOP}/{coopShopId}")
suspend fun getCoopShopById(@Path("coopShopId") id: Int): CoopShopResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object URLConstant {
const val SEMESTERS = "semesters"
const val LAND = "lands"
const val TERM = "term"
const val COOPSHOP = "coopshop"

object DINING {
const val DINING = "dining"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import `in`.koreatech.koin.data.error.CoopShopErrorHandlerImpl
import `in`.koreatech.koin.data.error.OwnerErrorHandlerImpl
import `in`.koreatech.koin.domain.error.coopshop.CoopShopErrorHandler
import `in`.koreatech.koin.domain.error.owner.OwnerErrorHandler
import javax.inject.Singleton

Expand Down Expand Up @@ -51,4 +53,10 @@ object ErrorHandlerModule {
fun provideOwnerErrorHandler(
@ApplicationContext applicationContext: Context
): OwnerErrorHandler = OwnerErrorHandlerImpl(applicationContext)

@Provides
@Singleton
fun provideCoopShopErrorHandler(
@ApplicationContext applicationContext: Context
): CoopShopErrorHandler = CoopShopErrorHandlerImpl(applicationContext)
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,12 @@ object NoAuthNetworkModule {
): LandApi {
return retrofit.create(LandApi::class.java)
}

@Provides
@Singleton
fun provideCoopShopApi(
@NoAuth retrofit: Retrofit
): CoopShopApi {
return retrofit.create(CoopShopApi::class.java)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,12 @@ object RepositoryModule {
): OnBoardingRepository {
return OnBoardingRepositoryImpl(onBoardingLocalDataSource)
}

@Provides
@Singleton
fun provideCoopShopRepository(
coopShopRemoteDataSource: CoopShopRemoteDataSource
): CoopShopRepository {
return CoopShopRepositoryImpl(coopShopRemoteDataSource)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,12 @@ object RemoteDataSourceModule {
): PreSignedUrlRemoteDataSource {
return PreSignedUrlRemoteDataSource(preSignedUrlApi)
}

@Provides
@Singleton
fun provideCoopShopRemoteDataSource(
coopShopApi: CoopShopApi,
): CoopShopRemoteDataSource {
return CoopShopRemoteDataSource(coopShopApi)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package `in`.koreatech.koin.data.error

import android.content.Context
import retrofit2.HttpException
import dagger.hilt.android.qualifiers.ApplicationContext
import `in`.koreatech.koin.data.R
import `in`.koreatech.koin.data.util.handleCommonError
import `in`.koreatech.koin.data.util.unknownErrorHandler
import `in`.koreatech.koin.data.util.withUnknown
import `in`.koreatech.koin.domain.error.coopshop.CoopShopErrorHandler
import `in`.koreatech.koin.domain.model.error.ErrorHandler
import javax.inject.Inject

class CoopShopErrorHandlerImpl @Inject constructor(
@ApplicationContext private val context: Context
): CoopShopErrorHandler {
override fun handleGetCoopShopAllError(throwable: Throwable): ErrorHandler =
throwable.handleCommonError(context) {
unknownErrorHandler(context)
}

override fun handleGetCoopShopError(throwable: Throwable): ErrorHandler =
throwable.handleCommonError(context) {
when (it) {
is HttpException -> {
when (it.code()) {
404 -> ErrorHandler(it.message())
else -> ErrorHandler(context.getString(R.string.error_network))
}
}
else -> ErrorHandler(context.getString(R.string.error_network_unknown))
}.withUnknown(context)
}
}
36 changes: 36 additions & 0 deletions data/src/main/java/in/koreatech/koin/data/mapper/CoopShopMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package `in`.koreatech.koin.data.mapper

import `in`.koreatech.koin.data.response.coopshop.CoopShopResponse
import `in`.koreatech.koin.data.response.coopshop.OpenCloseInfoResponse
import `in`.koreatech.koin.domain.model.coopshop.CoopShop
import `in`.koreatech.koin.domain.model.coopshop.OpenCloseInfo
import `in`.koreatech.koin.domain.model.coopshop.OpenCloseTimeInfo
import `in`.koreatech.koin.domain.model.coopshop.checkIfNotOpen
import `in`.koreatech.koin.domain.model.coopshop.toCoopShopDayType

fun CoopShopResponse.toCoopShop(): CoopShop {
return CoopShop(
id = id,
name = name,
semester = semester,
opens = opens.groupByDayOfWeek(),
phone = phone.orEmpty(),
location = location,
remarks = remarks.orEmpty(),
updatedAt = updatedAt
)
}

fun List<OpenCloseInfoResponse>.groupByDayOfWeek(): List<OpenCloseInfo> =
this.groupBy { it.dayOfWeek }.map { (day, infoList) ->
OpenCloseInfo(
dayOfWeek = day.toCoopShopDayType,
opensByDayType = infoList.map { info ->
OpenCloseTimeInfo(
type = info.type.orEmpty(),
openTime = info.openTime.orEmpty().checkIfNotOpen,
closeTime = info.closeTime.orEmpty().checkIfNotOpen
)
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package `in`.koreatech.koin.data.repository

import `in`.koreatech.koin.data.mapper.toCoopShop
import `in`.koreatech.koin.data.response.coopshop.CoopShopResponse
import `in`.koreatech.koin.data.source.remote.CoopShopRemoteDataSource
import `in`.koreatech.koin.domain.model.coopshop.CoopShop
import `in`.koreatech.koin.domain.repository.CoopShopRepository
import javax.inject.Inject

class CoopShopRepositoryImpl @Inject constructor(
private val coopShopRemoteDataSource: CoopShopRemoteDataSource
): CoopShopRepository {
override suspend fun getCoopShopAll(): List<CoopShop> {
return coopShopRemoteDataSource.getCoopShopAll().map(CoopShopResponse::toCoopShop)
}

override suspend fun getCoopShopById(id: Int): CoopShop {
return coopShopRemoteDataSource.getCoopShopById(id).toCoopShop()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package `in`.koreatech.koin.data.response.coopshop

import com.google.gson.annotations.SerializedName
import java.time.LocalDateTime

data class CoopShopResponse(
@SerializedName("id") val id: Int,
@SerializedName("name") val name: String,
@SerializedName("semester") val semester: String,
@SerializedName("opens") val opens: List<OpenCloseInfoResponse>,
@SerializedName("phone") val phone: String?,
@SerializedName("location") val location: String,
@SerializedName("remarks") val remarks: String?,
@SerializedName("updated_at") val updatedAt: String
)

data class OpenCloseInfoResponse(
@SerializedName("day_of_week") val dayOfWeek: String,
@SerializedName("type") val type: String?,
@SerializedName("open_time") val openTime: String?,
@SerializedName("close_time") val closeTime: String?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package `in`.koreatech.koin.data.source.remote

import `in`.koreatech.koin.data.api.CoopShopApi
import `in`.koreatech.koin.data.response.coopshop.CoopShopResponse
import javax.inject.Inject

class CoopShopRemoteDataSource @Inject constructor(
private val coopShopApi: CoopShopApi
) {
suspend fun getCoopShopAll(): List<CoopShopResponse> {
return coopShopApi.getCoopShopAll()
}

suspend fun getCoopShopById(id: Int): CoopShopResponse {
return coopShopApi.getCoopShopById(id)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package `in`.koreatech.koin.domain.error.coopshop

import `in`.koreatech.koin.domain.model.error.ErrorHandler

interface CoopShopErrorHandler {
fun handleGetCoopShopAllError(throwable: Throwable) : ErrorHandler
fun handleGetCoopShopError(throwable: Throwable) : ErrorHandler
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package `in`.koreatech.koin.domain.model.coopshop

data class CoopShop(
val id: Int,
val name: String,
val semester: String,
val opens: List<OpenCloseInfo>,
val phone: String,
val location: String,
val remarks: String,
val updatedAt: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package `in`.koreatech.koin.domain.model.coopshop

enum class CoopShopDayType(
val value: String
) {
Weekday("평일"),
Weekend("주말")
}

val String.toCoopShopDayType
get() = when (this) {
"평일" -> CoopShopDayType.Weekday
"주말" -> CoopShopDayType.Weekend
else -> throw IllegalArgumentException("Invalid day type")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package `in`.koreatech.koin.domain.model.coopshop

enum class CoopShopType(
val id: Int
) {
Dining(1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package `in`.koreatech.koin.domain.model.coopshop

data class OpenCloseInfo(
val dayOfWeek: CoopShopDayType,
val opensByDayType: List<OpenCloseTimeInfo>
)

data class OpenCloseTimeInfo(
val type: String,
val openTime: String,
val closeTime: String
)

val String.checkIfNotOpen get() =
if (this == "휴점(예약)") "미운영" else this
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package `in`.koreatech.koin.domain.repository

import `in`.koreatech.koin.domain.model.coopshop.CoopShop

interface CoopShopRepository {
suspend fun getCoopShopAll(): List<CoopShop>
suspend fun getCoopShopById(id: Int): CoopShop
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package `in`.koreatech.koin.domain.usecase.coopshop

import `in`.koreatech.koin.domain.error.coopshop.CoopShopErrorHandler
import `in`.koreatech.koin.domain.model.coopshop.CoopShop
import `in`.koreatech.koin.domain.model.error.ErrorHandler
import `in`.koreatech.koin.domain.repository.CoopShopRepository
import javax.inject.Inject

class GetCoopShopAllUseCase @Inject constructor(
private val coopShopRepository: CoopShopRepository,
private val coopShopErrorHandler: CoopShopErrorHandler
) {
suspend operator fun invoke(): Pair<List<CoopShop>?, ErrorHandler?> {
return try {
coopShopRepository.getCoopShopAll() to null
} catch (t: Throwable) {
null to coopShopErrorHandler.handleGetCoopShopAllError(t)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package `in`.koreatech.koin.domain.usecase.coopshop

import `in`.koreatech.koin.domain.error.coopshop.CoopShopErrorHandler
import `in`.koreatech.koin.domain.model.coopshop.CoopShop
import `in`.koreatech.koin.domain.model.coopshop.CoopShopType
import `in`.koreatech.koin.domain.model.error.ErrorHandler
import `in`.koreatech.koin.domain.repository.CoopShopRepository
import javax.inject.Inject

class GetCoopShopUseCase @Inject constructor(
private val coopShopRepository: CoopShopRepository,
private val coopShopErrorHandler: CoopShopErrorHandler
) {
suspend operator fun invoke(type: CoopShopType): Pair<CoopShop?, ErrorHandler?> {
return try {
coopShopRepository.getCoopShopById(type.id) to null
} catch (t: Throwable) {
null to coopShopErrorHandler.handleGetCoopShopError(t)
}
}
}
1 change: 1 addition & 0 deletions koin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ android {
}
buildFeatures {
dataBinding = true
viewBinding = true
}
}

Expand Down
10 changes: 6 additions & 4 deletions koin/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@
android:usesCleartextTraffic="true"
tools:replace="android:name">


<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/logo_color_horizontal_300x168"
/>

android:resource="@drawable/logo_color_horizontal_300x168" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/black" />
Expand Down Expand Up @@ -181,6 +178,11 @@
android:host="@string/kakaolink_host" />
</intent-filter>
</activity>
<activity
android:name=".ui.dining.DiningNoticeActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/KAPTheme.NoActionBar"/>
<activity
android:name=".ui.bus.BusActivity"
android:exported="false"
Expand Down
Loading

0 comments on commit 92d23be

Please sign in to comment.