From b9a5074d07ffdd0d91ed63a520a527c999729bf5 Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 18:16:32 +0900 Subject: [PATCH 01/11] =?UTF-8?q?[add/#23]=20data:search=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle.kts | 1 + shared/data/search/.gitignore | 1 + shared/data/search/build.gradle.kts | 86 +++++++++++++++++++ .../data/search/ExampleInstrumentedTest.kt | 24 ++++++ .../kus/shared/data/search/ExampleUnitTest.kt | 16 ++++ .../src/androidMain/AndroidManifest.xml | 4 + .../shared/data/search/Platform.android.kt | 3 + .../com/kus/shared/data/search/Platform.kt | 3 + .../shared/data/search/Platform.desktop.kt | 3 + .../kus/shared/data/search/Platform.ios.kt | 3 + 10 files changed, 144 insertions(+) create mode 100644 shared/data/search/.gitignore create mode 100644 shared/data/search/build.gradle.kts create mode 100644 shared/data/search/src/androidDeviceTest/kotlin/com/kus/shared/data/search/ExampleInstrumentedTest.kt create mode 100644 shared/data/search/src/androidHostTest/kotlin/com/kus/shared/data/search/ExampleUnitTest.kt create mode 100644 shared/data/search/src/androidMain/AndroidManifest.xml create mode 100644 shared/data/search/src/androidMain/kotlin/com/kus/shared/data/search/Platform.android.kt create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/Platform.kt create mode 100644 shared/data/search/src/desktopMain/kotlin/com/kus/shared/data/search/Platform.desktop.kt create mode 100644 shared/data/search/src/iosMain/kotlin/com/kus/shared/data/search/Platform.ios.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index af34cd9d..33c628c3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -72,3 +72,4 @@ include(":shared:domain:auth") include(":shared:core:serialization") include(":shared:core:presentation") +include(":shared:data:search") diff --git a/shared/data/search/.gitignore b/shared/data/search/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/shared/data/search/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/shared/data/search/build.gradle.kts b/shared/data/search/build.gradle.kts new file mode 100644 index 00000000..291a7e5a --- /dev/null +++ b/shared/data/search/build.gradle.kts @@ -0,0 +1,86 @@ +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidKotlinMultiplatformLibrary) + alias(libs.plugins.androidLint) + alias(libs.plugins.kotlin.serialization) +} + +kotlin { + androidLibrary { + namespace = "com.kus.shared.data.search" + compileSdk = 36 + minSdk = 26 + + withHostTestBuilder { + } + + withDeviceTestBuilder { + sourceSetTreeName = "test" + }.configure { + instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + } + + val xcfName = "shared:data:searchKit" + + iosX64 { + binaries.framework { + baseName = xcfName + } + } + + iosArm64 { + binaries.framework { + baseName = xcfName + } + } + + iosSimulatorArm64 { + binaries.framework { + baseName = xcfName + } + } + + jvm("desktop") + + sourceSets { + commonMain { + dependencies { + implementation(libs.kotlinx.coroutines.core) + + implementation(libs.kotlinx.serialization.json) + implementation(libs.bundles.ktor) + + implementation(project(":shared:domain:model")) + implementation(project(":shared:data:network")) + } + } + + commonTest { + dependencies { + implementation(libs.kotlin.test) + } + } + + androidMain { + dependencies { + implementation(libs.koin.android) + implementation(libs.datastore.preferences) + } + } + + getByName("androidDeviceTest") { + dependencies { + implementation(libs.androidx.runner) + implementation(libs.androidx.core) + implementation(libs.androidx.testExt.junit) + } + } + + iosMain { + dependencies { + } + } + } + +} \ No newline at end of file diff --git a/shared/data/search/src/androidDeviceTest/kotlin/com/kus/shared/data/search/ExampleInstrumentedTest.kt b/shared/data/search/src/androidDeviceTest/kotlin/com/kus/shared/data/search/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..70c9e884 --- /dev/null +++ b/shared/data/search/src/androidDeviceTest/kotlin/com/kus/shared/data/search/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.kus.shared.data.search + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.kus.shared.data.search.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/shared/data/search/src/androidHostTest/kotlin/com/kus/shared/data/search/ExampleUnitTest.kt b/shared/data/search/src/androidHostTest/kotlin/com/kus/shared/data/search/ExampleUnitTest.kt new file mode 100644 index 00000000..3f359462 --- /dev/null +++ b/shared/data/search/src/androidHostTest/kotlin/com/kus/shared/data/search/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.kus.shared.data.search + +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/shared/data/search/src/androidMain/AndroidManifest.xml b/shared/data/search/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/shared/data/search/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/shared/data/search/src/androidMain/kotlin/com/kus/shared/data/search/Platform.android.kt b/shared/data/search/src/androidMain/kotlin/com/kus/shared/data/search/Platform.android.kt new file mode 100644 index 00000000..92cf24b2 --- /dev/null +++ b/shared/data/search/src/androidMain/kotlin/com/kus/shared/data/search/Platform.android.kt @@ -0,0 +1,3 @@ +package com.kus.shared.data.search + +actual fun platform() = "Android" \ No newline at end of file diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/Platform.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/Platform.kt new file mode 100644 index 00000000..862bf666 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/Platform.kt @@ -0,0 +1,3 @@ +package com.kus.shared.data.search + +expect fun platform(): String \ No newline at end of file diff --git a/shared/data/search/src/desktopMain/kotlin/com/kus/shared/data/search/Platform.desktop.kt b/shared/data/search/src/desktopMain/kotlin/com/kus/shared/data/search/Platform.desktop.kt new file mode 100644 index 00000000..d27839a1 --- /dev/null +++ b/shared/data/search/src/desktopMain/kotlin/com/kus/shared/data/search/Platform.desktop.kt @@ -0,0 +1,3 @@ +package com.kus.shared.data.search + +actual fun platform(): String = "Desktop" \ No newline at end of file diff --git a/shared/data/search/src/iosMain/kotlin/com/kus/shared/data/search/Platform.ios.kt b/shared/data/search/src/iosMain/kotlin/com/kus/shared/data/search/Platform.ios.kt new file mode 100644 index 00000000..a2928b80 --- /dev/null +++ b/shared/data/search/src/iosMain/kotlin/com/kus/shared/data/search/Platform.ios.kt @@ -0,0 +1,3 @@ +package com.kus.shared.data.search + +actual fun platform() = "iOS" \ No newline at end of file From 48201b929c4ed8110daa4cd15a41a9f53e54977a Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 19:53:16 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[add/#23]=20domain:search=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=B6=94=EA=B0=80=20-=20repository=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20searchDomainModule=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle.kts | 1 + shared/domain/search/.gitignore | 1 + shared/domain/search/build.gradle.kts | 79 +++++++++++++++++++ .../domain/search/ExampleInstrumentedTest.kt | 24 ++++++ .../shared/domain/search/ExampleUnitTest.kt | 16 ++++ .../src/androidMain/AndroidManifest.xml | 4 + .../shared/domain/search/Platform.android.kt | 3 + .../com/kus/shared/domain/search/Platform.kt | 3 + .../domain/search/di/searchDomainModule.kt | 9 +++ .../search/repository/SearchRepository.kt | 9 +++ .../shared/domain/search/Platform.desktop.kt | 3 + .../kus/shared/domain/search/Platform.ios.kt | 3 + 12 files changed, 155 insertions(+) create mode 100644 shared/domain/search/.gitignore create mode 100644 shared/domain/search/build.gradle.kts create mode 100644 shared/domain/search/src/androidDeviceTest/kotlin/com/kus/shared/domain/search/ExampleInstrumentedTest.kt create mode 100644 shared/domain/search/src/androidHostTest/kotlin/com/kus/shared/domain/search/ExampleUnitTest.kt create mode 100644 shared/domain/search/src/androidMain/AndroidManifest.xml create mode 100644 shared/domain/search/src/androidMain/kotlin/com/kus/shared/domain/search/Platform.android.kt create mode 100644 shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/Platform.kt create mode 100644 shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/di/searchDomainModule.kt create mode 100644 shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/repository/SearchRepository.kt create mode 100644 shared/domain/search/src/desktopMain/kotlin/com/kus/shared/domain/search/Platform.desktop.kt create mode 100644 shared/domain/search/src/iosMain/kotlin/com/kus/shared/domain/search/Platform.ios.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 33c628c3..d898a613 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -73,3 +73,4 @@ include(":shared:domain:auth") include(":shared:core:serialization") include(":shared:core:presentation") include(":shared:data:search") +include(":shared:domain:search") diff --git a/shared/domain/search/.gitignore b/shared/domain/search/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/shared/domain/search/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/shared/domain/search/build.gradle.kts b/shared/domain/search/build.gradle.kts new file mode 100644 index 00000000..976390ce --- /dev/null +++ b/shared/domain/search/build.gradle.kts @@ -0,0 +1,79 @@ +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidKotlinMultiplatformLibrary) + alias(libs.plugins.androidLint) +} + +kotlin { + androidLibrary { + namespace = "com.kus.shared.domain.search" + compileSdk = 36 + minSdk = 26 + + withHostTestBuilder { + } + + withDeviceTestBuilder { + sourceSetTreeName = "test" + }.configure { + instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + } + + val xcfName = "shared:domain:searchKit" + + iosX64 { + binaries.framework { + baseName = xcfName + } + } + + iosArm64 { + binaries.framework { + baseName = xcfName + } + } + + iosSimulatorArm64 { + binaries.framework { + baseName = xcfName + } + } + + jvm("desktop") + + sourceSets { + commonMain { + dependencies { + implementation(libs.kotlinx.coroutines.core) + api(libs.koin.core) + implementation(project(":shared:domain:model")) + } + } + + commonTest { + dependencies { + implementation(libs.kotlin.test) + } + } + + androidMain { + dependencies { + } + } + + getByName("androidDeviceTest") { + dependencies { + implementation(libs.androidx.runner) + implementation(libs.androidx.core) + implementation(libs.androidx.testExt.junit) + } + } + + iosMain { + dependencies { + } + } + } + +} \ No newline at end of file diff --git a/shared/domain/search/src/androidDeviceTest/kotlin/com/kus/shared/domain/search/ExampleInstrumentedTest.kt b/shared/domain/search/src/androidDeviceTest/kotlin/com/kus/shared/domain/search/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..fcc5211e --- /dev/null +++ b/shared/domain/search/src/androidDeviceTest/kotlin/com/kus/shared/domain/search/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.kus.shared.domain.search + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.kus.shared.domain.search.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/shared/domain/search/src/androidHostTest/kotlin/com/kus/shared/domain/search/ExampleUnitTest.kt b/shared/domain/search/src/androidHostTest/kotlin/com/kus/shared/domain/search/ExampleUnitTest.kt new file mode 100644 index 00000000..69971ff3 --- /dev/null +++ b/shared/domain/search/src/androidHostTest/kotlin/com/kus/shared/domain/search/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package com.kus.shared.domain.search + +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/shared/domain/search/src/androidMain/AndroidManifest.xml b/shared/domain/search/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/shared/domain/search/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/shared/domain/search/src/androidMain/kotlin/com/kus/shared/domain/search/Platform.android.kt b/shared/domain/search/src/androidMain/kotlin/com/kus/shared/domain/search/Platform.android.kt new file mode 100644 index 00000000..f8fdedf6 --- /dev/null +++ b/shared/domain/search/src/androidMain/kotlin/com/kus/shared/domain/search/Platform.android.kt @@ -0,0 +1,3 @@ +package com.kus.shared.domain.search + +actual fun platform() = "Android" \ No newline at end of file diff --git a/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/Platform.kt b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/Platform.kt new file mode 100644 index 00000000..4aeb0a9f --- /dev/null +++ b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/Platform.kt @@ -0,0 +1,3 @@ +package com.kus.shared.domain.search + +expect fun platform(): String \ No newline at end of file diff --git a/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/di/searchDomainModule.kt b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/di/searchDomainModule.kt new file mode 100644 index 00000000..eb9b8284 --- /dev/null +++ b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/di/searchDomainModule.kt @@ -0,0 +1,9 @@ +package com.kus.shared.domain.search.di + +import com.kus.shared.domain.search.usecase.GetSearchResultUseCase +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.module + +val searchDomainModule = module { + singleOf(::GetSearchResultUseCase) +} diff --git a/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/repository/SearchRepository.kt b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/repository/SearchRepository.kt new file mode 100644 index 00000000..4ffa2970 --- /dev/null +++ b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/repository/SearchRepository.kt @@ -0,0 +1,9 @@ +package com.kus.shared.domain.search.repository + +import com.kus.shared.domain.model.restaurant.RestaurantItem + +interface SearchRepository { + suspend fun getSearchResult( + searchTerm: String, + ): List +} \ No newline at end of file diff --git a/shared/domain/search/src/desktopMain/kotlin/com/kus/shared/domain/search/Platform.desktop.kt b/shared/domain/search/src/desktopMain/kotlin/com/kus/shared/domain/search/Platform.desktop.kt new file mode 100644 index 00000000..efa21850 --- /dev/null +++ b/shared/domain/search/src/desktopMain/kotlin/com/kus/shared/domain/search/Platform.desktop.kt @@ -0,0 +1,3 @@ +package com.kus.shared.domain.search + +actual fun platform(): String = "Desktop" \ No newline at end of file diff --git a/shared/domain/search/src/iosMain/kotlin/com/kus/shared/domain/search/Platform.ios.kt b/shared/domain/search/src/iosMain/kotlin/com/kus/shared/domain/search/Platform.ios.kt new file mode 100644 index 00000000..dcb95339 --- /dev/null +++ b/shared/domain/search/src/iosMain/kotlin/com/kus/shared/domain/search/Platform.ios.kt @@ -0,0 +1,3 @@ +package com.kus.shared.domain.search + +actual fun platform() = "iOS" \ No newline at end of file From 05c62121e448a3eb006e2f4d78fae4ad7fb04ca5 Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 19:54:04 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[feat/#23]=20usecase=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/model/restaurant/RestaurantItem.kt | 18 ++++++++++++++++++ .../search/usecase/GetSearchResultUseCase.kt | 11 +++++++++++ 2 files changed, 29 insertions(+) create mode 100644 shared/domain/model/src/commonMain/kotlin/com/kus/shared/domain/model/restaurant/RestaurantItem.kt create mode 100644 shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/usecase/GetSearchResultUseCase.kt diff --git a/shared/domain/model/src/commonMain/kotlin/com/kus/shared/domain/model/restaurant/RestaurantItem.kt b/shared/domain/model/src/commonMain/kotlin/com/kus/shared/domain/model/restaurant/RestaurantItem.kt new file mode 100644 index 00000000..dceace0b --- /dev/null +++ b/shared/domain/model/src/commonMain/kotlin/com/kus/shared/domain/model/restaurant/RestaurantItem.kt @@ -0,0 +1,18 @@ +package com.kus.shared.domain.model.restaurant + +data class RestaurantItem( + val restaurantId: Long, + val restaurantRanking: Int, + val restaurantName: String, + val restaurantCuisine: String, + val restaurantPosition: String, + val restaurantImgUrl: String, + val mainTier: Int, + val isTempTier: Boolean, + val longitude: Double, + val latitude: Double, + val partnershipInfo: String, + val restaurantScore: Double, + val isEvaluated: Boolean, + val isFavorite: Boolean, +) diff --git a/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/usecase/GetSearchResultUseCase.kt b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/usecase/GetSearchResultUseCase.kt new file mode 100644 index 00000000..2c0e68b5 --- /dev/null +++ b/shared/domain/search/src/commonMain/kotlin/com/kus/shared/domain/search/usecase/GetSearchResultUseCase.kt @@ -0,0 +1,11 @@ +package com.kus.shared.domain.search.usecase + +import com.kus.shared.domain.model.restaurant.RestaurantItem +import com.kus.shared.domain.search.repository.SearchRepository + +class GetSearchResultUseCase( + private val searchRepository: SearchRepository, +) { + suspend operator fun invoke(searchTerm: String): List = + searchRepository.getSearchResult(searchTerm) +} \ No newline at end of file From 1226b89d5b5ef81eb623dec09fbdace3ac09b38f Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 19:54:27 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[feat/#23]=20api=20=EA=B5=AC=ED=98=84=20-?= =?UTF-8?q?=20api=20=EB=B0=8F=20dataModule=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/data/search/build.gradle.kts | 1 + .../kus/shared/data/search/api/SearchApi.kt | 19 +++++++++++++++ .../shared/data/search/di/searchDataModule.kt | 13 +++++++++++ .../shared/data/search/mapper/searchMapper.kt | 22 ++++++++++++++++++ .../remote/response/SearchResultResponse.kt | 23 +++++++++++++++++++ .../repositoryimpl/SearchRepositoryImpl.kt | 15 ++++++++++++ 6 files changed, 93 insertions(+) create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/api/SearchApi.kt create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/di/searchDataModule.kt create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/remote/response/SearchResultResponse.kt create mode 100644 shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/repositoryimpl/SearchRepositoryImpl.kt diff --git a/shared/data/search/build.gradle.kts b/shared/data/search/build.gradle.kts index 291a7e5a..a2443941 100644 --- a/shared/data/search/build.gradle.kts +++ b/shared/data/search/build.gradle.kts @@ -51,6 +51,7 @@ kotlin { implementation(libs.kotlinx.serialization.json) implementation(libs.bundles.ktor) + implementation(project(":shared:domain:search")) implementation(project(":shared:domain:model")) implementation(project(":shared:data:network")) } diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/api/SearchApi.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/api/SearchApi.kt new file mode 100644 index 00000000..55456be9 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/api/SearchApi.kt @@ -0,0 +1,19 @@ +package com.kus.shared.data.search.api + +import com.kus.shared.data.search.remote.response.RestaurantResponse +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.request.get +import io.ktor.client.request.parameter + +class SearchApi( + private val client: HttpClient, +) { + suspend fun getSearchResult( + searchTerm: String, + ): List { + return client.get("/api/v2/search") { + parameter("kw", searchTerm) + }.body() + } +} \ No newline at end of file diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/di/searchDataModule.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/di/searchDataModule.kt new file mode 100644 index 00000000..ac83f072 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/di/searchDataModule.kt @@ -0,0 +1,13 @@ +package com.kus.shared.data.search.di + +import com.kus.shared.data.search.api.SearchApi +import com.kus.shared.data.search.repositoryimpl.SearchRepositoryImpl +import com.kus.shared.domain.search.repository.SearchRepository +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.bind +import org.koin.dsl.module + +val searchDataModule = module { + singleOf(::SearchApi) + singleOf(::SearchRepositoryImpl) bind SearchRepository::class +} \ No newline at end of file diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt new file mode 100644 index 00000000..d12f6014 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt @@ -0,0 +1,22 @@ +package com.kus.shared.data.search.mapper + +import com.kus.shared.data.search.remote.response.RestaurantResponse +import com.kus.shared.domain.model.restaurant.RestaurantItem + +fun RestaurantResponse.toDomain(): RestaurantItem = + RestaurantItem( + restaurantId = restaurantId, + restaurantRanking = restaurantRanking ?: 0, + restaurantName = restaurantName, + restaurantCuisine = restaurantCuisine, + restaurantPosition = restaurantPosition, + restaurantImgUrl = restaurantImgUrl, + mainTier = mainTier, + isEvaluated = isEvaluated, + isFavorite = isFavorite, + longitude = longitude, + latitude = latitude, + partnershipInfo = partnershipInfo ?: "", + restaurantScore = restaurantScore?.takeIf { s -> !s.isNaN() } ?: 0.0, + isTempTier = isTempTier, + ) diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/remote/response/SearchResultResponse.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/remote/response/SearchResultResponse.kt new file mode 100644 index 00000000..47338b96 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/remote/response/SearchResultResponse.kt @@ -0,0 +1,23 @@ +package com.kus.shared.data.search.remote.response + +import kotlinx.serialization.Serializable + +@Serializable +data class RestaurantResponse( + val restaurantId: Long, + val restaurantRanking: Int? = null, + val restaurantName: String, + val restaurantCuisine: String, + val restaurantPosition: String, + val restaurantImgUrl: String, + val mainTier: Int, + val latitude: Double, + val longitude: Double, + val partnershipInfo: String? = null, + val restaurantScore: Double? = null, + val isEvaluated: Boolean, + val isFavorite: Boolean, + val cuisineImgUrl: String = "", + val tierImgUrl: String? = "", + val isTempTier: Boolean, +) diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/repositoryimpl/SearchRepositoryImpl.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/repositoryimpl/SearchRepositoryImpl.kt new file mode 100644 index 00000000..60563e53 --- /dev/null +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/repositoryimpl/SearchRepositoryImpl.kt @@ -0,0 +1,15 @@ +package com.kus.shared.data.search.repositoryimpl + +import com.kus.shared.data.search.api.SearchApi +import com.kus.shared.data.search.mapper.toDomain +import com.kus.shared.domain.model.restaurant.RestaurantItem +import com.kus.shared.domain.search.repository.SearchRepository + +class SearchRepositoryImpl( + private val api: SearchApi, +): SearchRepository { + override suspend fun getSearchResult(searchTerm: String): List { + return api.getSearchResult(searchTerm).map { it.toDomain() } + } + +} From cea8fd5c09e96b020182447511d3df0e09d681be Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 20:31:02 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[feat/#23]=20api=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EB=B0=8F=20ui=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kus/kustaurant/navigation/KusNavHost.kt | 7 + shared/feature/search/build.gradle.kts | 6 + .../feature/search/di/searchFeatureModule.kt | 9 ++ .../search/navigation/SearchNavGraph.kt | 27 ++++ .../kus/feature/search/state/SearchUiState.kt | 8 ++ .../com/kus/feature/search/ui/SearchScreen.kt | 120 ++++++++++++------ .../kus/feature/search/ui/SearchViewModel.kt | 40 +++++- 7 files changed, 175 insertions(+), 42 deletions(-) create mode 100644 shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/di/searchFeatureModule.kt create mode 100644 shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/navigation/SearchNavGraph.kt create mode 100644 shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/state/SearchUiState.kt diff --git a/composeApp/src/commonMain/kotlin/com/kus/kustaurant/navigation/KusNavHost.kt b/composeApp/src/commonMain/kotlin/com/kus/kustaurant/navigation/KusNavHost.kt index 38fa603d..15d16e11 100644 --- a/composeApp/src/commonMain/kotlin/com/kus/kustaurant/navigation/KusNavHost.kt +++ b/composeApp/src/commonMain/kotlin/com/kus/kustaurant/navigation/KusNavHost.kt @@ -19,6 +19,8 @@ import com.kus.feature.login.navigation.loginNavGraph import com.kus.feature.my.navigation.myNavGraph import com.kus.feature.onboarding.navigatioin.Onboarding import com.kus.feature.onboarding.navigatioin.onboardingNavGraph +import com.kus.feature.search.navigation.navigateToSearch +import com.kus.feature.search.navigation.searchNavGraph import com.kus.feature.splash.navigation.Splash import com.kus.feature.splash.navigation.splashNavGraph import com.kus.feature.tier.navigation.TierCategorySelect @@ -135,5 +137,10 @@ fun KusNavHost( communityNavGraph(onShowMessage = onShowMessage) myNavGraph(onShowMessage = onShowMessage) + + searchNavGraph( + navigateToUp = navController::popBackStack, + navigateToRestDetail = { /* Todo: 상세화면 연결 */ }, + ) } } \ No newline at end of file diff --git a/shared/feature/search/build.gradle.kts b/shared/feature/search/build.gradle.kts index 149230fe..e95f54c2 100644 --- a/shared/feature/search/build.gradle.kts +++ b/shared/feature/search/build.gradle.kts @@ -52,7 +52,13 @@ kotlin { implementation(libs.kotlinx.coroutines.core) implementation(project(":shared:core:designSystem")) + implementation(project(":shared:core:presentation")) + implementation(project(":shared:core:logging")) + implementation(project(":shared:core:serialization")) + implementation(project(":shared:data:network")) + implementation(project(":shared:domain:model")) + implementation(project(":shared:domain:search")) resources.srcDirs("src/commonMain/composeResources") } } diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/di/searchFeatureModule.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/di/searchFeatureModule.kt new file mode 100644 index 00000000..8c722d07 --- /dev/null +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/di/searchFeatureModule.kt @@ -0,0 +1,9 @@ +package com.kus.feature.search.di + +import com.kus.feature.search.ui.SearchViewModel +import org.koin.core.module.dsl.viewModelOf +import org.koin.dsl.module + +val searchFeatureModule = module { + viewModelOf(::SearchViewModel) +} diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/navigation/SearchNavGraph.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/navigation/SearchNavGraph.kt new file mode 100644 index 00000000..9a23326e --- /dev/null +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/navigation/SearchNavGraph.kt @@ -0,0 +1,27 @@ +package com.kus.feature.search.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import com.kus.feature.search.ui.SearchRoute +import kotlinx.serialization.Serializable + +@Serializable +data object Search + +fun NavController.navigateToSearch( + navOptions: NavOptions? = null, +) = navigate(Search, navOptions) + +fun NavGraphBuilder.searchNavGraph( + navigateToUp: () -> Unit, + navigateToRestDetail: (Long) -> Unit, +) { + composable { + SearchRoute( + onBackClick = navigateToUp, + onRestDetailNavigate = navigateToRestDetail, + ) + } +} diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/state/SearchUiState.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/state/SearchUiState.kt new file mode 100644 index 00000000..55bb3c11 --- /dev/null +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/state/SearchUiState.kt @@ -0,0 +1,8 @@ +package com.kus.feature.search.state + +import UiState +import com.kus.shared.domain.model.restaurant.RestaurantItem + +data class SearchUiState( + val results: UiState> = UiState.Idle, +) \ No newline at end of file diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt index c0a9b960..9f45aacf 100644 --- a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt @@ -1,5 +1,6 @@ package com.kus.feature.search.ui +import UiState import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column @@ -24,20 +25,42 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.kus.designsystem.component.KusRestThumbnail import com.kus.designsystem.theme.KusTheme +import com.kus.designsystem.util.noRippleClickable import com.kus.feature.search.component.KusSearchBox +import com.kus.feature.search.state.SearchUiState +import com.kus.shared.domain.model.restaurant.RestaurantItem import kustaurant.shared.feature.search.generated.resources.Res import kustaurant.shared.feature.search.generated.resources.ic_left_chevron import kustaurant.shared.feature.search.generated.resources.img_no_result import org.jetbrains.compose.resources.painterResource +import org.koin.compose.viewmodel.koinViewModel @Composable -fun SearchScreen( +fun SearchRoute( + onBackClick: () -> Unit, onRestDetailNavigate: (Long) -> Unit, - viewModel: SearchViewModel = viewModel(), + viewModel: SearchViewModel = koinViewModel(), ) { val searchTerm by viewModel.searchTerm.collectAsStateWithLifecycle() - val resultItems by viewModel.resultItems.collectAsStateWithLifecycle() + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + SearchScreen( + searchTerm = searchTerm, + uiState = uiState, + onBackClick = onBackClick, + onSearchTermChange = viewModel::updateSearchTerm, + onRestaurantItemClick = onRestDetailNavigate, + ) +} +@Composable +fun SearchScreen( + searchTerm: String, + uiState: SearchUiState, + onBackClick: () -> Unit, + onSearchTermChange: (String) -> Unit, + onRestaurantItemClick: (Long) -> Unit, +) { LazyColumn( modifier = Modifier.fillMaxSize() .background(KusTheme.colors.c_F3F3F3), @@ -52,14 +75,15 @@ fun SearchScreen( Icon( painter = painterResource(Res.drawable.ic_left_chevron), contentDescription = "뒤로가기 버튼", + modifier = Modifier.noRippleClickable(onBackClick), ) Spacer(Modifier.width(8.dp)) KusSearchBox( searchTerm = searchTerm, - onValueChange = viewModel::updateSearchTerm, - onSearchButonClick = { /* 검색 API 연결 */ } + onValueChange = onSearchTermChange, + onSearchButonClick = { /* 기능 없음*/ } ) } } @@ -68,44 +92,64 @@ fun SearchScreen( Spacer(Modifier.background(KusTheme.colors.c_F3F3F3).height(15.dp)) } - if (resultItems.isEmpty() && searchTerm.isNotEmpty()) { - item { - Column( - modifier = Modifier.fillMaxWidth().background(KusTheme.colors.c_F3F3F3) - .padding(top = 60.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Image( - painter = painterResource(Res.drawable.img_no_result), - contentDescription = null, - ) + when (uiState.results) { + is UiState.Loading -> {} + is UiState.Success -> { + val resultItems = uiState.results.data - Spacer(Modifier.height(6.dp)) + if (resultItems.isEmpty() && searchTerm.isNotEmpty()) { + item { + Column( + modifier = Modifier.fillMaxWidth().background(KusTheme.colors.c_F3F3F3) + .padding(top = 60.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image( + painter = painterResource(Res.drawable.img_no_result), + contentDescription = null, + ) - Text( - text = "해당 검색어에 맞는 식당이 없어요", - style = KusTheme.typography.type17sb, - color = KusTheme.colors.c_AAAAAA, - ) + Spacer(Modifier.height(6.dp)) + + Text( + text = "해당 검색어에 맞는 식당이 없어요", + style = KusTheme.typography.type17sb, + color = KusTheme.colors.c_AAAAAA, + ) + } + } + } else { + itemsIndexed(resultItems) { index, item -> + Column( + modifier = Modifier.fillMaxWidth() + .background(KusTheme.colors.c_F3F3F3) + .padding(start = 20.dp, bottom = 8.dp, end = 20.dp), + ) { + KusRestThumbnail( + restName = item.restaurantName, + tier = item.mainTier, + restThumbnail = item.restaurantImgUrl, + restAlliance = item.partnershipInfo, + categories = arrayListOf(item.restaurantCuisine), + location = item.restaurantPosition, + isTempTier = item.isTempTier, + isSaved = item.isFavorite, + isEvaluated = item.isEvaluated, + onClick = { onRestaurantItemClick(item.restaurantId) }, + ) + + if (resultItems.lastIndex == index) { + Spacer(Modifier.height(20.dp)) + } + } + } } } - } else { - itemsIndexed(resultItems) { index, item -> - Column ( - modifier = Modifier.fillMaxWidth() - .background(KusTheme.colors.c_F3F3F3) - .padding(start = 20.dp, bottom = 8.dp, end = 20.dp), - ) { - KusRestThumbnail( - restName = "식당이름입니다.", - isSaved = true, - isEvaluated = false, - onClick = { onRestDetailNavigate(0) }, - ) - if (resultItems.lastIndex == index) { - Spacer(Modifier.height(20.dp)) - } + is UiState.Failure -> {} + is UiState.Idle -> { + item { + Spacer(Modifier.background(KusTheme.colors.c_F3F3F3).fillMaxSize()) } } } diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt index 987759a8..54fd8114 100644 --- a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt @@ -1,16 +1,48 @@ package com.kus.feature.search.ui import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.kus.feature.search.state.SearchUiState +import com.kus.shared.domain.search.usecase.GetSearchResultUseCase +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch -class SearchViewModel: ViewModel() { +class SearchViewModel( + private val getSearchResultUseCase: GetSearchResultUseCase, +) : ViewModel() { private val _searchTerm = MutableStateFlow("") val searchTerm = _searchTerm.asStateFlow() - private val _resultItems = MutableStateFlow>(listOf(1,2,3,4,5,6,7,8,9, 10, 11, 12, 13)) // TODO : 도메인 모델 변경 - val resultItems = _resultItems.asStateFlow() + private val _uiState = MutableStateFlow(SearchUiState()) + val uiState = _uiState.asStateFlow() + + @OptIn(FlowPreview::class) + private fun getResult() = viewModelScope.launch { + _searchTerm + .debounce(DEBOUNCE_DELAY) + .collectLatest { searchTerm -> + runCatching { + getSearchResultUseCase(searchTerm) + }.onSuccess { results -> + _uiState.update { it.copy(results = UiState.Success(results)) } + }.onFailure { + _uiState.update { it.copy(results = UiState.Failure(UiError.Network)) } + } + } + } fun updateSearchTerm(new: String) { _searchTerm.value = new + + if (searchTerm.value.isEmpty()) _uiState.update { it.copy(results = UiState.Idle) } + else getResult() + } + + companion object { + private const val DEBOUNCE_DELAY = 500L } -} \ No newline at end of file +} From efa8403a25f0cad72a5989ae47c8ab5473a5f88f Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 20:33:29 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[feat/#23]=20initKoin=EC=97=90=20search?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=AA=A8=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composeApp/build.gradle.kts | 1 + .../src/commonMain/kotlin/com/kus/kustaurant/di/initKoin.kt | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 9c2f536b..78190866 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -64,6 +64,7 @@ kotlin { implementation(project(":shared:data:firstLaunch")) implementation(project(":shared:data:tier")) implementation(project(":shared:data:auth")) + implementation(project(":shared:data:search")) implementation(project(":shared:feature:community")) implementation(project(":shared:feature:draw")) diff --git a/composeApp/src/commonMain/kotlin/com/kus/kustaurant/di/initKoin.kt b/composeApp/src/commonMain/kotlin/com/kus/kustaurant/di/initKoin.kt index d8652b20..96a3a95b 100644 --- a/composeApp/src/commonMain/kotlin/com/kus/kustaurant/di/initKoin.kt +++ b/composeApp/src/commonMain/kotlin/com/kus/kustaurant/di/initKoin.kt @@ -8,11 +8,14 @@ import com.kus.domain.firstLaunch.di.firstLaunchDomainModule import com.kus.domain.auth.di.authDomainModule import com.kus.feature.login.di.featureLoginModule import com.kus.feature.onboarding.di.onboardingFeatureModule +import com.kus.feature.search.di.searchFeatureModule import com.kus.feature.tier.di.tierFeatureModule import com.kus.shared.data.tier.di.tierDataModule import com.kus.shared.domain.tier.di.tierDomainModule import org.koin.core.KoinApplication import com.kus.feature.splash.di.splashFeatureModule +import com.kus.shared.data.search.di.searchDataModule +import com.kus.shared.domain.search.di.searchDomainModule import org.koin.core.context.startKoin import org.koin.core.module.Module import org.koin.dsl.KoinAppDeclaration @@ -32,18 +35,21 @@ fun initKoin( firstLaunchDomainModule, authDomainModule, tierDomainModule, + searchDomainModule, // data (repository 등 공통) networkModule, firstLaunchDataModule, authDataModule, tierDataModule, + searchDataModule, // feature splashFeatureModule, onboardingFeatureModule, featureLoginModule, tierFeatureModule, + searchFeatureModule, ) modules(additionalModules) From 5db449d7963deb53d6cd3111805e2973681d19ab Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Sun, 22 Feb 2026 20:34:37 +0900 Subject: [PATCH 07/11] =?UTF-8?q?[chore/#23]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt index 9f45aacf..f5688f3a 100644 --- a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchScreen.kt @@ -22,13 +22,11 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import com.kus.designsystem.component.KusRestThumbnail import com.kus.designsystem.theme.KusTheme import com.kus.designsystem.util.noRippleClickable import com.kus.feature.search.component.KusSearchBox import com.kus.feature.search.state.SearchUiState -import com.kus.shared.domain.model.restaurant.RestaurantItem import kustaurant.shared.feature.search.generated.resources.Res import kustaurant.shared.feature.search.generated.resources.ic_left_chevron import kustaurant.shared.feature.search.generated.resources.img_no_result From 0226f97c0e6b0dc7eb9257cad6831764dbce4e2f Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Wed, 25 Feb 2026 22:27:45 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[mod/#23]=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composeApp/build.gradle.kts | 1 + .../kotlin/com/kus/shared/data/search/mapper/searchMapper.kt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 799c6743..45583c8e 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -81,6 +81,7 @@ kotlin { implementation(project(":shared:domain:tier")) implementation(project(":shared:domain:auth")) implementation(project(":shared:domain:home")) + implementation(project(":shared:domain:search")) } commonTest.dependencies { implementation(libs.kotlin.test) diff --git a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt index d12f6014..b7afce0f 100644 --- a/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt +++ b/shared/data/search/src/commonMain/kotlin/com/kus/shared/data/search/mapper/searchMapper.kt @@ -18,5 +18,7 @@ fun RestaurantResponse.toDomain(): RestaurantItem = latitude = latitude, partnershipInfo = partnershipInfo ?: "", restaurantScore = restaurantScore?.takeIf { s -> !s.isNaN() } ?: 0.0, + tierImgUrl = tierImgUrl, + cuisineImgUrl = cuisineImgUrl, isTempTier = isTempTier, ) From 8d189e49853914e9e2a77c3028e9cc738e7ad043 Mon Sep 17 00:00:00 2001 From: Chaerin Kim Date: Wed, 25 Feb 2026 22:51:47 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[mod/#23]=20=EA=B2=80=EC=83=89=EC=96=B4?= =?UTF-8?q?=20=EC=9D=BC=EA=B4=84=20=EC=82=AD=EC=A0=9C=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20tint=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/kus/feature/search/component/KusSearchBox.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/component/KusSearchBox.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/component/KusSearchBox.kt index 567eb04f..92727547 100644 --- a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/component/KusSearchBox.kt +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/component/KusSearchBox.kt @@ -14,6 +14,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.kus.designsystem.theme.KusTheme import com.kus.designsystem.util.noRippleClickable @@ -77,7 +78,7 @@ internal fun KusSearchBox( .padding(start = 13.dp, end = 6.dp) .size(20.dp) .noRippleClickable { onValueChange("") }, - tint = KusTheme.colors.c_AAAAAA, + tint = Color.Unspecified, ) } From 9f3112dbe119a87bc81ac2914653926991de4d86 Mon Sep 17 00:00:00 2001 From: TaejungKim <92737123+imtaejugkim@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:12:31 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[fix/#23]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20prefrence=20dependency=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/data/search/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/data/search/build.gradle.kts b/shared/data/search/build.gradle.kts index a2443941..94c8a4fc 100644 --- a/shared/data/search/build.gradle.kts +++ b/shared/data/search/build.gradle.kts @@ -66,7 +66,6 @@ kotlin { androidMain { dependencies { implementation(libs.koin.android) - implementation(libs.datastore.preferences) } } From 8641d423ca7e312fdacbddac6b768c706d60dc56 Mon Sep 17 00:00:00 2001 From: TaejungKim <92737123+imtaejugkim@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:14:34 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[fix/#23]=20=EA=B2=80=EC=83=89=20api=20?= =?UTF-8?q?=EC=BD=94=EB=A3=A8=ED=8B=B4=20=EC=9E=AC=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kus/feature/search/ui/SearchViewModel.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt index 54fd8114..cf7b336f 100644 --- a/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt +++ b/shared/feature/search/src/commonMain/kotlin/com/kus/feature/search/ui/SearchViewModel.kt @@ -20,11 +20,19 @@ class SearchViewModel( private val _uiState = MutableStateFlow(SearchUiState()) val uiState = _uiState.asStateFlow() + init { + observeSearchTerm() + } + @OptIn(FlowPreview::class) - private fun getResult() = viewModelScope.launch { + private fun observeSearchTerm() = viewModelScope.launch { _searchTerm .debounce(DEBOUNCE_DELAY) .collectLatest { searchTerm -> + if (searchTerm.isEmpty()) { + _uiState.update { it.copy(results = UiState.Idle) } + return@collectLatest + } runCatching { getSearchResultUseCase(searchTerm) }.onSuccess { results -> @@ -37,9 +45,6 @@ class SearchViewModel( fun updateSearchTerm(new: String) { _searchTerm.value = new - - if (searchTerm.value.isEmpty()) _uiState.update { it.copy(results = UiState.Idle) } - else getResult() } companion object {