diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index b344de908..da7da4f5e 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -40,12 +40,15 @@ android { dependencies { implementation(project(":core:model")) + implementation(project(":core:util")) kapt(libs.hilt.compiler) implementation(libs.hilt.android) implementation(libs.retrofit.core) implementation(libs.retrofit.kotlin.serialization) + implementation(libs.retrofit.converter.moshi) + implementation(libs.moshi.kotlin) implementation(libs.okhttp.logging) implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.datetime) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt index 27eac8498..2f2e6b5b7 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt @@ -1,9 +1,34 @@ package com.kusitms.connectdog.core.data.api -import com.kusitms.connectdog.core.data.api.model.ExampleResponse +import com.kusitms.connectdog.core.data.api.model.AnnouncementHomeResponseItem +import com.kusitms.connectdog.core.data.api.model.AnnouncementSearchResponseItem +import com.kusitms.connectdog.core.data.api.model.ReviewResponseItem import retrofit2.http.GET +import retrofit2.http.Query internal interface ApiService { - @GET("/droidknights/DroidKnights2023_App/main/core/data/src/main/assets/sponsors.json") - suspend fun getExample(): List + + @GET("/volunteers/posts/home") + suspend fun getAnnouncementPostsHome(): List + + @GET("/volunteers/posts") + suspend fun getAnnouncementFilterPosts( + @Query("postStatus") postStatus: String?, + @Query("departureLoc") departureLoc: String?, + @Query("arrivalLoc") arrivalLoc: String?, + @Query("startDate") startDate: String?, + @Query("endDate") endDate: String?, + @Query("dogSize") dogSize: String?, + @Query("isKennel") isKennel: Boolean?, + @Query("intermediaryName") intermediaryName: String?, + @Query("orderCondition") orderCondition: String?, + @Query("page") page: Int, + @Query("size") size: Int + ): List + + @GET("/volunteers/reviews") + suspend fun getReviewsHome( + @Query("page") page: Int, + @Query("size") size: Int + ): List } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementHomeResponseItem.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementHomeResponseItem.kt new file mode 100644 index 000000000..64547d558 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementHomeResponseItem.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.core.data.api.model + +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class AnnouncementHomeResponseItem( + val arrivalLoc: String, + val departureLoc: String, + val endDate: String, + val intermediaryName: String, + val isKennel: Boolean, + val mainImage: String, + val postId: Int, + val startDate: String +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementSearchResponseItem.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementSearchResponseItem.kt new file mode 100644 index 000000000..8ff82578d --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AnnouncementSearchResponseItem.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.core.data.api.model + +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class AnnouncementSearchResponseItem( + val postId: Int, + val departureLoc: String, + val arrivalLoc: String, + val startDate: String, + val endDate: String, + val intermediaryName: String, + val isKennel: Boolean, + val mainImage: String +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ExampleResponse.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ExampleResponse.kt deleted file mode 100644 index a1da50188..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ExampleResponse.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -internal data class ExampleResponse( - @SerialName("name") val name: String, - @SerialName("imageUrl") val imageUrl: String, - @SerialName("homepage") val homepage: String, - @SerialName("grade") val grade: Grade -) { - enum class Grade { - @SerialName("platinum") - PLATINUM, - - @SerialName("gold") - GOLD - } -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ReviewResponseItem.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ReviewResponseItem.kt new file mode 100644 index 000000000..855bdb997 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/ReviewResponseItem.kt @@ -0,0 +1,17 @@ +package com.kusitms.connectdog.core.data.api.model + +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class ReviewResponseItem( + val arrivalLoc: String, + val content: String, + val departureLoc: String, + val dogName: String, + val endDate: String, + val images: List, + val intermediaryName: String, + val mainImage: String, + val startDate: String, + val volunteerNickname: String +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt index f5d8e1596..55a1462fe 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt @@ -1,24 +1,51 @@ package com.kusitms.connectdog.core.data.di -import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.kusitms.connectdog.core.data.api.ApiService +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import kotlinx.serialization.json.Json -import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Interceptor import okhttp3.OkHttpClient +import okhttp3.Protocol +import okhttp3.Response +import okhttp3.ResponseBody import okhttp3.logging.HttpLoggingInterceptor -import retrofit2.Converter import retrofit2.Retrofit +import retrofit2.converter.moshi.MoshiConverterFactory import java.util.concurrent.TimeUnit import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) internal object ApiModule { - private const val BASE_URL = "https://raw.githubusercontent.com" + private const val BASE_URL = "https://dev-api.connectdog.site" + + private val networkInterceptor: Interceptor = Interceptor { chain -> + val request = chain.request() + val jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJBY2Nlc3NUb2tlbiIsInJvbGVOYW1lIjoiVk9MVU5URUVSIiwiaWQiOjEsImV4cCI6MTcwMDQyMTc2NH0.sn-XWVtZEp4gI_yq4D9-UCXCJpxOcdqBdnlIW_n2PMcI_KSWWfYiLboZG3RE4uwyReo90_XjcLSUA4a2MPyHZA" + try { + chain.proceed( + request.newBuilder() + .addHeader( + "Authorization", + "Bearer $jwt" + ) // todo + .build() + ) + } catch (e: Exception) { + Response.Builder() + .request(request) + .protocol(Protocol.HTTP_2) + .code(1001) + .message(e.message ?: "") + .body(ResponseBody.create(null, e.message ?: "")) + .build() + } + } @Provides @Singleton @@ -28,6 +55,7 @@ internal object ApiModule { level = HttpLoggingInterceptor.Level.BODY } return OkHttpClient.Builder() + .addInterceptor(networkInterceptor) .addNetworkInterceptor(httpLoggingInterceptor) .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) @@ -37,19 +65,21 @@ internal object ApiModule { @Provides @Singleton - fun provideConverterFactory(json: Json): Converter.Factory { - return json.asConverterFactory("application/json".toMediaType()) + fun provideMoshi(): Moshi { + return Moshi.Builder() + .addLast(KotlinJsonAdapterFactory()) + .build() } @Provides @Singleton fun provideApiService( okHttpClient: OkHttpClient, - converterFactory: Converter.Factory + moshi: Moshi ): ApiService { return Retrofit.Builder() .baseUrl(BASE_URL) - .addConverterFactory(converterFactory) + .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient).build() .create(ApiService::class.java) } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataModule.kt index 8b1654067..6f59c6f44 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataModule.kt @@ -1,26 +1,26 @@ package com.kusitms.connectdog.core.data.di import android.content.Context -import com.kusitms.connectdog.core.data.repository.DefaultExampleRepository -import com.kusitms.connectdog.core.data.repository.ExampleRepository +import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.repository.HomeRepository import com.kusitms.connectdog.core.data.repository.HomeRepositoryImpl import com.kusitms.connectdog.core.data.repository.LoginRepository -import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module -internal abstract class DataModule { - @Binds - abstract fun bindsExampleRepository(repository: DefaultExampleRepository): ExampleRepository +internal class DataModule { - @Binds - abstract fun bindsHomeRepository(repository: HomeRepositoryImpl): HomeRepository + @Provides + @Singleton + fun provideHomeRepository(apiService: ApiService): HomeRepository { + return HomeRepositoryImpl(apiService) + } companion object { @Provides diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/AnnouncementMapper.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/AnnouncementMapper.kt new file mode 100644 index 000000000..0ccb026cc --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/AnnouncementMapper.kt @@ -0,0 +1,35 @@ +package com.kusitms.connectdog.core.data.mapper + +import com.kusitms.connectdog.core.data.api.model.AnnouncementHomeResponseItem +import com.kusitms.connectdog.core.data.api.model.AnnouncementSearchResponseItem +import com.kusitms.connectdog.core.model.Announcement +import com.kusitms.connectdog.core.util.dateFormat +import com.kusitms.connectdog.core.util.toLocalDate + +internal fun AnnouncementHomeResponseItem.toData(): Announcement { + val datePattern = "yyyy-MM-dd" + val uiPattern = "YY.MM.dd(E)" + val start = this.startDate.toLocalDate(datePattern).dateFormat(uiPattern) + val end = this.endDate.toLocalDate(datePattern).dateFormat(uiPattern) + return Announcement( + imageUrl = this.mainImage, + location = "${this.departureLoc} → ${this.arrivalLoc}", + date = "$start-$end", + organization = this.intermediaryName, + hasKennel = this.isKennel + ) +} + +internal fun AnnouncementSearchResponseItem.toData(): Announcement { + val datePattern = "yyyy-MM-dd" + val uiPattern = "YY.MM.dd(E)" + val start = this.startDate.toLocalDate(datePattern).dateFormat(uiPattern) + val end = this.endDate.toLocalDate(datePattern).dateFormat(uiPattern) + return Announcement( + imageUrl = this.mainImage, + location = "${this.departureLoc} → ${this.arrivalLoc}", + date = "$start-$end", + organization = this.intermediaryName, + hasKennel = this.isKennel + ) +} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ExampleMapper.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ExampleMapper.kt deleted file mode 100644 index 033ddebce..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ExampleMapper.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.kusitms.connectdog.core.data.mapper - -import com.kusitms.connectdog.core.data.api.model.ExampleResponse -import com.kusitms.connectdog.core.model.Example - -internal fun ExampleResponse.toData(): Example = - Example( - name = name, - imageUrl = imageUrl, - homepage = homepage, - grade = - when (grade) { - ExampleResponse.Grade.PLATINUM -> Example.Grade.PLATINUM - ExampleResponse.Grade.GOLD -> Example.Grade.GOLD - } - ) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ReviewMapper.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ReviewMapper.kt new file mode 100644 index 000000000..7c21fbfdd --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/mapper/ReviewMapper.kt @@ -0,0 +1,21 @@ +package com.kusitms.connectdog.core.data.mapper + +import com.kusitms.connectdog.core.data.api.model.ReviewResponseItem +import com.kusitms.connectdog.core.model.Review +import com.kusitms.connectdog.core.util.toLocalDate + +internal fun ReviewResponseItem.toData(): Review { + val datePattern = "yyyy-MM-dd" + val start = startDate.toLocalDate(datePattern) + val end = endDate.toLocalDate(datePattern) + return Review( + profileUrl = mainImage, // todo profileUrl로 바뀔 예정 + dogName = dogName, + userName = volunteerNickname, + contentUrl = mainImage, + date = "$start-$end", + location = "$departureLoc->$arrivalLoc", + organization = intermediaryName, + content = content + ) +} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DefaultExampleRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DefaultExampleRepository.kt deleted file mode 100644 index 2350b7117..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DefaultExampleRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import com.kusitms.connectdog.core.data.api.ApiService -import com.kusitms.connectdog.core.data.mapper.toData -import com.kusitms.connectdog.core.model.Example -import javax.inject.Inject - -internal class DefaultExampleRepository -@Inject -constructor( - private val api: ApiService -) : ExampleRepository { - override suspend fun getExample(): List { - return api.getExample().map { it.toData() } - } -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/ExampleRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/ExampleRepository.kt deleted file mode 100644 index ae5e0c6db..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/ExampleRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import com.kusitms.connectdog.core.model.Example - -interface ExampleRepository { - suspend fun getExample(): List -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepository.kt index 7cb5fc0fb..3b6524dee 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepository.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepository.kt @@ -6,7 +6,19 @@ import com.kusitms.connectdog.core.model.Review interface HomeRepository { suspend fun getAnnouncementList(): List - suspend fun getAnnouncementListWithFilter(): List + suspend fun getAnnouncementListWithFilter( + postStatus: String? = null, + departureLoc: String? = null, + arrivalLoc: String? = null, + startDate: String? = "", + endDate: String? = "", + dogSize: String? = null, + isKennel: Boolean? = null, + intermediaryName: String? = null, + orderCondition: String? = null, + page: Int? = 0, + size: Int? = 50 + ): List - suspend fun getReviewList(): List + suspend fun getReviewList(page: Int? = 0, size: Int? = 5): List } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepositoryImpl.kt index 700e573b9..785b6195c 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/HomeRepositoryImpl.kt @@ -1,6 +1,7 @@ package com.kusitms.connectdog.core.data.repository import com.kusitms.connectdog.core.data.api.ApiService +import com.kusitms.connectdog.core.data.mapper.toData import com.kusitms.connectdog.core.model.Announcement import com.kusitms.connectdog.core.model.Review import javax.inject.Inject @@ -9,14 +10,33 @@ internal class HomeRepositoryImpl @Inject constructor( private val api: ApiService ) : HomeRepository { override suspend fun getAnnouncementList(): List { - TODO("Not yet implemented") + return api.getAnnouncementPostsHome().map { it.toData() } } - override suspend fun getAnnouncementListWithFilter(): List { - TODO("Not yet implemented") + override suspend fun getAnnouncementListWithFilter( + postStatus: String?, + departureLoc: String?, + arrivalLoc: String?, + startDate: String?, + endDate: String?, + dogSize: String?, + isKennel: Boolean?, + intermediaryName: String?, + orderCondition: String?, + page: Int?, + size: Int? + ): List { + return api.getAnnouncementFilterPosts( + postStatus, + departureLoc, arrivalLoc, + startDate, endDate, + dogSize, isKennel, intermediaryName, + orderCondition, + page ?: 0, size ?: 50 + ).map { it.toData() } } - override suspend fun getReviewList(): List { - TODO("Not yet implemented") + override suspend fun getReviewList(page: Int?, size: Int?): List { + return api.getReviewsHome(page ?: 0, size ?: 5).map { it.toData() } } } diff --git a/core/util/src/main/java/com/kusitms/connectdog/core/util/Formatter.kt b/core/util/src/main/java/com/kusitms/connectdog/core/util/Formatter.kt index c8b8be8dc..03b9c7b92 100644 --- a/core/util/src/main/java/com/kusitms/connectdog/core/util/Formatter.kt +++ b/core/util/src/main/java/com/kusitms/connectdog/core/util/Formatter.kt @@ -4,4 +4,9 @@ import java.time.LocalDate import java.time.format.DateTimeFormatter fun LocalDate.dateFormat(pattern: String) = - this.format(DateTimeFormatter.ofPattern(pattern)) \ No newline at end of file + this.format(DateTimeFormatter.ofPattern(pattern)) + +fun String.toLocalDate(pattern: String): LocalDate { + val formatter = DateTimeFormatter.ofPattern(pattern) + return LocalDate.parse(this, formatter) +} \ No newline at end of file diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt index 7e4fd543f..558489d67 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt @@ -1,11 +1,10 @@ package com.kusitms.connectdog.feature.home +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.ExampleRepository import com.kusitms.connectdog.core.data.repository.HomeRepository import com.kusitms.connectdog.feature.home.state.AnnouncementUiState -import com.kusitms.connectdog.feature.home.state.ExampleUiState import com.kusitms.connectdog.feature.home.state.ReviewUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -18,37 +17,22 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import javax.inject.Inject +private val TAG = "HomeViewModel" + @HiltViewModel class HomeViewModel @Inject constructor( - exampleRepository: ExampleRepository, homeRepository: HomeRepository ) : ViewModel() { private val _errorFlow = MutableSharedFlow() val errorFlow: SharedFlow get() = _errorFlow - val exampleUiState: StateFlow = - flow { - emit(exampleRepository.getExample()) - }.map { examples -> - if (examples.isNotEmpty()) { - ExampleUiState.Examples(examples) - } else { - ExampleUiState.Empty - } - }.catch { - _errorFlow.emit(it) - }.stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), - initialValue = ExampleUiState.Loading - ) - val announcementUiState: StateFlow = flow { emit(homeRepository.getAnnouncementList()) }.map { + Log.d(TAG, "announcementUiState = ${it.size}") if (it.isNotEmpty()) { AnnouncementUiState.Announcements(it) } else { @@ -66,6 +50,7 @@ constructor( flow { emit(homeRepository.getReviewList()) }.map { + Log.d(TAG, "reviewUiState = ${it.size}") if (it.isNotEmpty()) { ReviewUiState.Reviews(it) } else { diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/SearchViewModel.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/SearchViewModel.kt index 9544718a3..afaefa5c8 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/SearchViewModel.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/SearchViewModel.kt @@ -15,30 +15,29 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch import java.time.LocalDate import javax.inject.Inject +private val TAG = "SearchViewModel" + @HiltViewModel class SearchViewModel @Inject constructor( - homeRepository: HomeRepository + val homeRepository: HomeRepository ) : ViewModel() { private var _filter = MutableStateFlow(Filter()) val filter: StateFlow get() = _filter + private var _isDeadlineOrder = MutableStateFlow(true) + val isDeadlineOrder: StateFlow get() = _isDeadlineOrder + private val _errorFlow = MutableSharedFlow() val errorFlow: SharedFlow get() = _errorFlow val announcementUiState: StateFlow = flow { - emit(homeRepository.getAnnouncementListWithFilter()) - }.map { - if (it.isNotEmpty()) { - AnnouncementUiState.Announcements(it) - } else { - AnnouncementUiState.Empty - } + emit(loadAnnouncementList()) }.catch { _errorFlow.emit(it) }.stateIn( @@ -69,4 +68,35 @@ class SearchViewModel @Inject constructor( fun clearFilter() { _filter.value = Filter() } + + fun changeOrderCondition() { + _isDeadlineOrder.value = !_isDeadlineOrder.value + viewModelScope.launch { + loadAnnouncementList() + } + } + + /** + * Network Communication + */ + private suspend fun loadAnnouncementList(): AnnouncementUiState { + val orderCondition = if (isDeadlineOrder.value) "마감순" else "최신순" + + val announcementList = homeRepository.getAnnouncementListWithFilter( + departureLoc = filter.value.departure, + arrivalLoc = filter.value.arrival, + startDate = filter.value.startDate?.toString(), + endDate = filter.value.endDate?.toString(), + dogSize = filter.value.detail.dogSize?.toDisplayName(), + isKennel = filter.value.detail.hasKennel, + intermediaryName = filter.value.detail.organization, + orderCondition = orderCondition + ) + + return if (announcementList.isNotEmpty()) { + AnnouncementUiState.Announcements(announcementList) + } else { + AnnouncementUiState.Empty + } + } } diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/SearchScreen.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/SearchScreen.kt index 5496dc17f..862f474aa 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/SearchScreen.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/SearchScreen.kt @@ -62,6 +62,7 @@ internal fun SearchScreen( Log.d(TAG, "filter = $filter") val announcementUiState by viewModel.announcementUiState.collectAsStateWithLifecycle() + val isByDeadline by viewModel.isDeadlineOrder.collectAsStateWithLifecycle() Column { TopAppBar { onBackClick() } @@ -83,8 +84,8 @@ internal fun SearchScreen( modifier = Modifier .padding(top = 20.dp, end = 20.dp) .fillMaxWidth(), - isByDeadline = true - ) { /*todo sort*/ } + isByDeadline = isByDeadline + ) { viewModel.changeOrderCondition() } } } } @@ -204,26 +205,29 @@ private fun SortButton( isByDeadline: Boolean = true, onClick: () -> Unit ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End, - modifier = modifier.clickable { onClick() } - ) { - Text( - text = if (isByDeadline) { - stringResource(id = R.string.search_sort_end) - } else { - stringResource(id = R.string.search_sort_recent) - }, - style = MaterialTheme.typography.bodyMedium, - color = Gray2 - ) - Spacer(modifier = Modifier.width(4.dp)) - Icon( - painter = painterResource(id = R.drawable.ic_sort), - contentDescription = "정렬", - tint = Gray2 - ) + Row(modifier = modifier.fillMaxWidth()) { + Spacer(modifier = Modifier.weight(1f)) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End, + modifier = Modifier.clickable { onClick() } + ) { + Text( + text = if (isByDeadline) { + stringResource(id = R.string.search_sort_end) + } else { + stringResource(id = R.string.search_sort_recent) + }, + style = MaterialTheme.typography.bodyMedium, + color = Gray2 + ) + Spacer(modifier = Modifier.width(4.dp)) + Icon( + painter = painterResource(id = R.drawable.ic_sort), + contentDescription = "정렬", + tint = Gray2 + ) + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e62db791c..6b648da59 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,6 +25,7 @@ kakaoOauth = "2.17.0" okhttp = "4.11.0" retrofit = "2.9.0" +moshiKotlin = "1.15.0" retrofitKotlinxSerializationJson = "1.0.0" kotlinxSerializationJson = "1.5.1" kotlinxDatetime = "0.4.1" @@ -79,6 +80,8 @@ hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-com okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" } retrofit-core = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } +retrofit-converter-moshi = {group = "com.squareup.retrofit2", name = "converter-moshi", version.ref = "retrofit"} +moshi-kotlin = { group = "com.squareup.moshi", name = "moshi-kotlin", version.ref = "moshiKotlin"} retrofit-kotlin-serialization = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "retrofitKotlinxSerializationJson" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" }