Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#11] HotelScreen 구현 #12

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ dependencies {
// coil
implementation(libs.coil.compose)

// paging
implementation(libs.paging.runtime)
implementation(libs.paging.compose)

// test
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package kr.ksw.visitkorea.data.paging.source

import androidx.paging.PagingSource
import androidx.paging.PagingState
import kr.ksw.visitkorea.data.mapper.toItems
import kr.ksw.visitkorea.data.remote.api.LocationBasedListApi
import kr.ksw.visitkorea.data.remote.dto.LocationBasedDTO

class LocationBasedPagingSource (
private val locationBasedListApi: LocationBasedListApi,
private val contentTypeId: String,
private val mapX: String,
private val mapY: String
) : PagingSource<Int, LocationBasedDTO>() {

override fun getRefreshKey(state: PagingState<Int, LocationBasedDTO>): Int? {
return state.anchorPosition?.let { anchor ->
val anchorPage = state.closestPageToPosition(anchor)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LocationBasedDTO> {
val page = params.key ?: 1
val loadSize = params.loadSize
val response = locationBasedListApi.getLocationBasedListByContentType(
numOfRows = loadSize,
pageNo = page,
mapX = mapX,
mapY = mapY,
contentTypeId = contentTypeId
)
val data = response.toItems()
return LoadResult.Page(
data = data,
prevKey = if(page == 1) null else page - 1,
nextKey = if(data.size == loadSize) page + 1 else null
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ data class LocationBasedDTO(
val mapX: String,
@SerializedName("mapy")
val mapY: String,
val cat3: String,
@SerializedName("cat3")
val category: String,
val tel: String,
val title: String,
)
17 changes: 17 additions & 0 deletions app/src/main/java/kr/ksw/visitkorea/domain/di/HotelModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package kr.ksw.visitkorea.domain.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent
import kr.ksw.visitkorea.domain.usecase.hotel.GetHotelListUseCase
import kr.ksw.visitkorea.domain.usecase.hotel.GetHotelListUseCaseImpl

@Module
@InstallIn(ActivityRetainedComponent::class)
abstract class HotelModule {
@Binds
abstract fun bindGetHotelListUseCase(
getHotelListUseCase: GetHotelListUseCaseImpl
): GetHotelListUseCase
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package kr.ksw.visitkorea.domain.usecase.home

import kr.ksw.visitkorea.domain.usecase.model.CultureCenter
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel

interface GetCultureCenterForHomeUseCase {
suspend operator fun invoke(
mapX: String,
mapY: String,
): Result<List<CultureCenter>>
mapY: String
): Result<List<CommonCardModel>>
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
package kr.ksw.visitkorea.domain.usecase.home

import kr.ksw.visitkorea.data.repository.LocationBasedListRepository
import kr.ksw.visitkorea.domain.usecase.mapper.toCultureCenterModel
import kr.ksw.visitkorea.domain.usecase.model.CultureCenter
import kr.ksw.visitkorea.domain.usecase.mapper.toCommonCardModel
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel
import javax.inject.Inject

class GetCultureCenterForHomeUseCaseImpl @Inject constructor(
private val locationBasedListRepository: LocationBasedListRepository
) : GetCultureCenterForHomeUseCase {
override suspend fun invoke(
mapX: String,
mapY: String,
): Result<List<CultureCenter>> {
mapY: String,): Result<List<CommonCardModel>> {
return locationBasedListRepository.getLocationBasedListByContentType(
10, 1, mapX, mapY, "14"
).map { list ->
list.map { dto ->
dto.toCultureCenterModel()
dto.toCommonCardModel()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package kr.ksw.visitkorea.domain.usecase.home

import kr.ksw.visitkorea.domain.usecase.model.LeisureSports
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel

interface GetLeisureSportsForHomeUseCase {
suspend operator fun invoke(
mapX: String,
mapY: String,
): Result<List<LeisureSports>>
): Result<List<CommonCardModel>>
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package kr.ksw.visitkorea.domain.usecase.home

import kr.ksw.visitkorea.data.repository.LocationBasedListRepository
import kr.ksw.visitkorea.domain.usecase.mapper.toLeisureSportsModel
import kr.ksw.visitkorea.domain.usecase.model.LeisureSports
import kr.ksw.visitkorea.domain.usecase.mapper.toCommonCardModel
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel
import javax.inject.Inject

class GetLeisureSportsForHomeUseCaseImpl @Inject constructor(
Expand All @@ -11,12 +11,12 @@ class GetLeisureSportsForHomeUseCaseImpl @Inject constructor(
override suspend fun invoke(
mapX: String,
mapY: String,
): Result<List<LeisureSports>> {
): Result<List<CommonCardModel>> {
return locationBasedListRepository.getLocationBasedListByContentType(
10, 1, mapX, mapY, "28"
).map { list ->
list.map { dto ->
dto.toLeisureSportsModel()
dto.toCommonCardModel()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package kr.ksw.visitkorea.domain.usecase.hotel

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import kr.ksw.visitkorea.data.remote.dto.LocationBasedDTO

interface GetHotelListUseCase {
suspend operator fun invoke(
forceFetch: Boolean,
mapX: String,
mapY: String
): Result<Flow<PagingData<LocationBasedDTO>>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package kr.ksw.visitkorea.domain.usecase.hotel

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import kotlinx.coroutines.flow.Flow
import kr.ksw.visitkorea.data.paging.source.LocationBasedPagingSource
import kr.ksw.visitkorea.data.remote.api.LocationBasedListApi
import kr.ksw.visitkorea.data.remote.dto.LocationBasedDTO
import javax.inject.Inject

class GetHotelListUseCaseImpl @Inject constructor(
private val locationBasedListApi: LocationBasedListApi
): GetHotelListUseCase {
private var pagingSource: PagingSource<Int, LocationBasedDTO>? = null

override suspend fun invoke(
forceFetch: Boolean,
mapX: String,
mapY: String
): Result<Flow<PagingData<LocationBasedDTO>>> = runCatching {
if(forceFetch &&
pagingSource != null &&
pagingSource?.invalid != true) {
pagingSource?.invalidate()
}
Pager(
config = PagingConfig(
pageSize = 10,
initialLoadSize = 10
),
pagingSourceFactory = {
LocationBasedPagingSource(
locationBasedListApi,
"32",
mapX,
mapY
).also {
pagingSource = it
}
}
).flow
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package kr.ksw.visitkorea.domain.usecase.mapper

import kr.ksw.visitkorea.data.remote.dto.LocationBasedDTO
import kr.ksw.visitkorea.domain.usecase.model.CultureCenter
import kr.ksw.visitkorea.domain.usecase.model.LeisureSports
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel
import kr.ksw.visitkorea.domain.usecase.model.Restaurant
import kr.ksw.visitkorea.domain.usecase.model.TouristSpot
import kr.ksw.visitkorea.domain.usecase.util.toDistForUi
Expand All @@ -17,16 +16,11 @@ fun LocationBasedDTO.toTouristSpotModel(): TouristSpot = TouristSpot(
title
)

fun LocationBasedDTO.toCultureCenterModel(): CultureCenter = CultureCenter(
fun LocationBasedDTO.toCommonCardModel(): CommonCardModel = CommonCardModel(
address,
firstImage.toImageUrl(),
title
)

fun LocationBasedDTO.toLeisureSportsModel(): LeisureSports = LeisureSports(
address,
firstImage.toImageUrl(),
title
title,
contentId
)

val restaurantMap = mapOf(
Expand All @@ -44,5 +38,5 @@ fun LocationBasedDTO.toRestaurantModel(): Restaurant = Restaurant(
dist.toDistForUi(),
firstImage.toImageUrl(),
title,
restaurantMap[cat3] ?: ""
restaurantMap[category] ?: ""
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package kr.ksw.visitkorea.domain.usecase.model

data class LeisureSports(
data class CommonCardModel(
val address: String = "",
val firstImage: String = "",
val title: String = "",
val contentId: String = "",
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ import kr.ksw.visitkorea.presentation.ui.theme.VisitKoreaTheme

@Composable
fun CultureCard(
modifier: Modifier = Modifier,
ratio: Float = 0.7f,
title: String,
address: String,
image: String,
) {
Card (
modifier = Modifier
.width(160.dp)
.aspectRatio(0.78f),
modifier = modifier
.aspectRatio(ratio),
shape = RoundedCornerShape(24.dp),
elevation = CardDefaults.elevatedCardElevation(
defaultElevation = 4.dp
Expand All @@ -53,7 +54,7 @@ fun CultureCard(
AsyncImage(
modifier = Modifier
.fillMaxWidth()
.height(144.dp)
.aspectRatio(1f)
.background(color = Color.LightGray),
model = ImageRequest
.Builder(LocalContext.current)
Expand Down Expand Up @@ -104,9 +105,9 @@ fun CultureCardPreview() {
.padding(20.dp)
) {
CultureCard(
"문화시설",
"문화시설 주소",
"https://ksw"
title = "문화시설",
address = "문화시설 주소",
image = "https://ksw"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ fun HomeScreen(
) { index ->
val cultureCenter = homeState.cultureCenterList[index]
CultureCard(
cultureCenter.title,
cultureCenter.address,
cultureCenter.firstImage
Modifier.fillParentMaxWidth(0.5f),
title = cultureCenter.title,
address = cultureCenter.address,
image = cultureCenter.firstImage
)
}
}
Expand Down Expand Up @@ -202,9 +203,10 @@ fun HomeScreen(
) { index ->
val leisureSports = homeState.leisureSportsList[index]
CultureCard(
leisureSports.title,
leisureSports.address,
leisureSports.firstImage
Modifier.fillParentMaxWidth(0.5f),
title = leisureSports.title,
address = leisureSports.address,
image = leisureSports.firstImage
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package kr.ksw.visitkorea.presentation.home.viewmodel

import androidx.compose.runtime.Immutable
import kr.ksw.visitkorea.domain.usecase.model.CultureCenter
import kr.ksw.visitkorea.domain.usecase.model.LeisureSports
import kr.ksw.visitkorea.domain.usecase.model.CommonCardModel
import kr.ksw.visitkorea.domain.usecase.model.Restaurant
import kr.ksw.visitkorea.domain.usecase.model.TouristSpot

@Immutable
data class HomeState(
val mainImage: String = "",
val touristSpotList: List<TouristSpot> = emptyList(),
val cultureCenterList: List<CultureCenter> = emptyList(),
val leisureSportsList: List<LeisureSports> = emptyList(),
val cultureCenterList: List<CommonCardModel> = emptyList(),
val leisureSportsList: List<CommonCardModel> = emptyList(),
val restaurantList: List<Restaurant> = emptyList(),
)
Loading
Loading