Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d704106
[add/#31] 평가하기 관련 의존성 추가
imtaejugkim Mar 8, 2026
427e63b
[feat/#31] 평가하기 api data 모듈 추가
imtaejugkim Mar 8, 2026
6cfb0e4
[feat/#31] 평가하기 api domain 모듈 추가
imtaejugkim Mar 8, 2026
0f4964f
[feat/#31] 평가하기 api viewmodel 연동 및 UIState 적용
imtaejugkim Mar 8, 2026
deeda14
[feat/#31] 평가하기 api koin 연동 및 상태에 따른 ui 로직 변경
imtaejugkim Mar 8, 2026
7d381e5
[feat/#31] 이전 평가 가져오기 api data 모듈 추가
imtaejugkim Mar 8, 2026
edf965a
[feat/#31] 이젼 평가 가져오기 api domain 모듈 추가
imtaejugkim Mar 8, 2026
7f7cd90
[mod/#31] 평가 데이터 초기화 데이터 수정 및 UiState, 모델 분리
imtaejugkim Mar 8, 2026
67d22a9
[feat/#31] 이전 평가 가져오기 api viewmodel 연동
imtaejugkim Mar 8, 2026
4f571d6
[feat/#31] 이전 평가 전달 navigation 및 데이터 수정
imtaejugkim Mar 8, 2026
c550e7e
[feat/#31] 이전 평가 전달 api 상태에 따른 ui 로직 변경
imtaejugkim Mar 8, 2026
b38f775
[fix/#31] 평가 제출 multi-part 분리 로직으로 변경
imtaejugkim Mar 8, 2026
e6c51d5
[feat/#31] 티어 화면 식당 id 전달 로직 추가
imtaejugkim Mar 8, 2026
3fb681c
[add/#31] koin 의존성 추가
imtaejugkim Mar 10, 2026
91b6de2
[fix/#31] 식당 id Long형으로 변경
imtaejugkim Mar 10, 2026
263b3ad
[ui/#31] 로딩 시 배경 흰색으로 변경
imtaejugkim Mar 10, 2026
4f9aa9a
[ui/#31] kusbutton 비활성화 인 경우 border 컬러 로직 추가
imtaejugkim Mar 10, 2026
1bac56d
[merge/#31] pulled develop
imtaejugkim Mar 10, 2026
17772f0
[fix/#31] 머지 과정 오류 수정
imtaejugkim Mar 10, 2026
ec45b52
[ui/#31] 로딩 및 실패 시도 상단 바 출력되도록 변경
imtaejugkim Mar 10, 2026
16abd92
[chore/#31] 자간 수정
imtaejugkim Mar 10, 2026
18576a6
Merge branch 'develop' into feat/#31-evaluate-api
imtaejugkim Mar 10, 2026
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
3 changes: 3 additions & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ kotlin {
implementation(project(":shared:data:home"))
implementation(project(":shared:data:community"))
implementation(project(":shared:data:detail"))
implementation(project(":shared:data:evaluate"))

implementation(project(":shared:feature:community"))
implementation(project(":shared:feature:draw"))
Expand All @@ -88,6 +89,8 @@ kotlin {
implementation(project(":shared:domain:home"))
implementation(project(":shared:domain:model"))
implementation(project(":shared:domain:detail"))
implementation(project(":shared:domain:evaluate"))
implementation(project(":shared:domain:model"))
}
commonTest.dependencies {
implementation(libs.kotlin.test)
Expand Down
6 changes: 3 additions & 3 deletions composeApp/src/commonMain/kotlin/com/kus/kustaurant/App.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.kus.kustaurant

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
Expand Down Expand Up @@ -118,7 +117,7 @@ fun SetNavigation() {
val showBottomBar = shouldShowBottomBar(destination)
val currentRoute = destination?.route
val selectedKey = BottomTab.fromRoute(currentRoute).key

val applySystemBarsPadding = !isEdgeToEdgeScreen(currentRoute)
val isWriter =
navBackStackEntry?.destination?.hasRoute<CommunityWrite>() == true ||
Expand All @@ -136,7 +135,7 @@ fun SetNavigation() {
navController = navController,
)
},
modifier = if (applySystemBarsPadding) Modifier.systemBarsPadding() else Modifier,
modifier = if (applySystemBarsPadding) Modifier.systemBarsPadding() else Modifier,
contentWindowInsets = WindowInsets.systemBars,
) { padding ->
Box(
Expand Down Expand Up @@ -170,6 +169,7 @@ fun SetNavigation() {
}
}
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.kus.domain.auth.di.authDomainModule
import com.kus.domain.community.di.communityDomainModule
import com.kus.feature.community.di.communityFeatureModule
import com.kus.feature.detail.di.detailFeatureModule
import com.kus.feature.evaluate.di.evaluateFeatureModule
import com.kus.feature.home.di.homeFeatureModule
import com.kus.feature.login.di.featureLoginModule
import com.kus.feature.onboarding.di.onboardingFeatureModule
Expand All @@ -19,8 +20,10 @@ import com.kus.shared.domain.tier.di.tierDomainModule
import org.koin.core.KoinApplication
import com.kus.feature.splash.di.splashFeatureModule
import com.kus.kustaurant.detail.di.detailDataModule
import com.kus.kustaurant.evaluate.di.evaluateDataModule
import com.kus.kustaurant.home.di.homeDataModule
import com.kus.shared.domain.detail.di.detailDomainModule
import com.kus.shared.domain.evaluate.di.evaluateDomainModule
import com.kus.shared.domain.home.di.homeDomainModule
import org.koin.core.context.startKoin
import org.koin.core.module.Module
Expand All @@ -44,6 +47,7 @@ fun initKoin(
homeDomainModule,
communityDomainModule,
detailDomainModule,
evaluateDomainModule,

// data (repository 등 공통)
networkModule,
Expand All @@ -53,15 +57,17 @@ fun initKoin(
homeDataModule,
communityDataModule,
detailDataModule,
evaluateDataModule,

// feature
splashFeatureModule,
onboardingFeatureModule,
featureLoginModule,
tierFeatureModule,
homeFeatureModule,
communityFeatureModule
detailFeatureModule
communityFeatureModule,
detailFeatureModule,
evaluateFeatureModule
)

modules(additionalModules)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fun KusNavHost(

navController.navigate(TierCategorySelect)
},
navigateToDetail = { navController.navigate(Detail) },
navigateToDetail = { restaurantId -> navController.navigate(Detail(restaurantId)) },
popBackStackWithResult = { result ->
val json = KusJson.json.encodeToString(result)
navController.previousBackStackEntry
Expand Down Expand Up @@ -228,7 +228,21 @@ fun KusNavHost(

detailNavGraph(
navigateToUp = navController::popBackStack,
navigateToEvaluate = { navController.navigate(Evaluate) },
navigateToEvaluate = { restaurant ->
navController.navigate(
Evaluate(
restaurantId = restaurant.restaurantId,
restaurantName = restaurant.restaurantName,
mainTier = restaurant.mainTier,
restaurantCuisine = restaurant.restaurantCuisine,
restaurantCuisineImgUrl = restaurant.restaurantCuisineImgUrl,
restaurantPosition = restaurant.restaurantPosition,
restaurantAddress = restaurant.restaurantAddress,
situationList = restaurant.situationList,
partnershipInfo = restaurant.partnershipInfo,
)
)
},
Comment on lines +231 to +245
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

평가 완료 후 이전 화면을 갱신할 결과 전달 경로가 없습니다.

여기서는 Evaluate로 이동만 하고, 이 파일의 evaluate 흐름은 onBackClick만 연결돼 있어서 제출 성공 여부나 갱신 신호가 Detail/Tier로 돌아오지 않습니다. 같은 파일의 tierNavGraph/communityNavGraph처럼 savedStateHandle이나 명시적 result callback을 붙이지 않으면, 사용자는 방금 평가한 내용이 즉시 반영되지 않은 화면을 보게 됩니다.

원하시면 savedStateHandle 기반 결과 전달 키 설계까지 같이 정리해드릴게요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composeApp/src/commonMain/kotlin/com/kus/kustaurant/navigation/KusNavHost.kt`
around lines 231 - 245, navigateToEvaluate currently only navigates to Evaluate
and never wires a result back, so you must send a refresh/result via the
NavController savedStateHandle (or an explicit result callback) when the
evaluation completes; update the navigateToEvaluate lambda to set a known
result-key (e.g., "evaluate_result") on the originating
backStackEntry.savedStateHandle before navigating or attach a callback to the
destination so Evaluate can write to
navController.previousBackStackEntry?.savedStateHandle on success, and update
the Detail/Tier screens to observe that key (in their composables or in
tierNavGraph/communityNavGraph) and refresh when it changes; reference
navigateToEvaluate, Evaluate, onBackClick and the destination
backStackEntry.savedStateHandle so the reviewer can locate the spots to add the
set/get logic.

)

evaluateNavGraph(
Expand Down
8 changes: 5 additions & 3 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ include(
":shared:data:tier",
":shared:data:auth",
":shared:data:home",
":shared:data:community"
":shared:data:detail"
":shared:data:community",
":shared:data:detail",
":shared:data:evaluate"
)

include(
Expand All @@ -65,7 +66,8 @@ include(
":shared:domain:auth",
":shared:domain:home",
":shared:domain:community",
":shared:domain:detail"
":shared:domain:detail",
":shared:domain:evaluate"
)

include(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ fun KusButton(
isShadowVisible: Boolean = false,
onClick: () -> Unit,
) {
val resolvedBorderColor = if (enabled) borderColor else KusTheme.colors.c_E0E0E0

Box(
modifier = modifier
) {
Expand All @@ -84,7 +86,7 @@ fun KusButton(
disabledContainerColor = KusTheme.colors.c_E0E0E0,
disabledContentColor = KusTheme.colors.c_AAAAAA,
),
border = BorderStroke(1.dp, borderColor),
border = BorderStroke(1.dp, resolvedBorderColor),
contentPadding = contentPadding,
) {
Row(
Expand Down
88 changes: 88 additions & 0 deletions shared/data/evaluate/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
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.evaluate"
compileSdk = 36
minSdk = 26

withHostTestBuilder {
}

withDeviceTestBuilder {
sourceSetTreeName = "test"
}.configure {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}

val xcfName = "shared:data:evaluateKit"

iosX64 {
binaries.framework {
baseName = xcfName
}
}

iosArm64 {
binaries.framework {
baseName = xcfName
}
}

iosSimulatorArm64 {
binaries.framework {
baseName = xcfName
}
}

jvm("desktop")

sourceSets {
commonMain {
dependencies {
implementation(libs.koin.core)
implementation(libs.kotlinx.coroutines.core)

implementation(libs.kotlinx.serialization.json)
implementation(libs.bundles.ktor)

implementation(project(":shared:domain:model"))
implementation(project(":shared:domain:evaluate"))
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 {
}
}
}

}
4 changes: 4 additions & 0 deletions shared/data/evaluate/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.kus.kustaurant.evaluate.api

import com.kus.kustaurant.evaluate.remote.request.EvaluationRequest
import com.kus.kustaurant.evaluate.remote.response.EvaluationResponse
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData
import io.ktor.client.request.get
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders

class EvaluateApi(
private val client: HttpClient,
) {
suspend fun getEvaluation(restaurantId: Long): EvaluationResponse {
return client.get("/api/v2/auth/restaurants/$restaurantId/evaluation").body()
}

suspend fun postEvaluation(
restaurantId: Long,
request: EvaluationRequest,
imageBytes: ByteArray?,
) {
client.post("/api/v2/auth/restaurants/$restaurantId/evaluation") {
setBody(
MultiPartFormDataContent(
formData {
append("evaluationScore", request.evaluationScore.toString())

request.evaluationSituations?.forEach { situation ->
append("evaluationSituations", situation.toString())
}

request.evaluationComment?.let {
append("evaluationComment", it)
}

imageBytes?.let {
append(
key = "newImage",
value = it,
headers = Headers.build {
append(HttpHeaders.ContentType, "image/jpeg")
append(HttpHeaders.ContentDisposition, "filename=evaluation.jpg")
}
)
}
}
)
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.kus.kustaurant.evaluate.di

import com.kus.kustaurant.evaluate.api.EvaluateApi
import com.kus.kustaurant.evaluate.repositoryimpl.EvaluateRepositoryImpl
import com.kus.shared.domain.evaluate.repository.EvaluateRepository
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.bind
import org.koin.dsl.module

val evaluateDataModule = module {
singleOf(::EvaluateApi)
singleOf(::EvaluateRepositoryImpl) bind EvaluateRepository::class
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.kus.kustaurant.evaluate.remote.mapper

import com.kus.kustaurant.evaluate.remote.response.EvaluationResponse
import com.kus.kustaurant.evaluate.remote.response.StarCommentResponse
import com.kus.shared.domain.model.evaluate.PreviousEvaluation
import com.kus.shared.domain.model.evaluate.PreviousStarComment

fun EvaluationResponse.toDomain(): PreviousEvaluation =
PreviousEvaluation(
evaluationScore = evaluationScore,
evaluationSituations = evaluationSituations ?: emptyList(),
evaluationImgUrl = evaluationImgUrl,
evaluationComment = evaluationComment,
starComments = starComments.map { it.toDomain() },
)

fun StarCommentResponse.toDomain(): PreviousStarComment =
PreviousStarComment(
star = star,
comment = comment,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.kus.kustaurant.evaluate.remote.request

import kotlinx.serialization.Serializable

@Serializable
data class EvaluationRequest(
val evaluationScore: Double,
val evaluationSituations: List<Int>? = null,
val evaluationComment: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.kus.kustaurant.evaluate.remote.response

import kotlinx.serialization.Serializable

@Serializable
data class EvaluationResponse(
val evaluationScore: Double? = null,
val evaluationSituations: List<Int>? = null,
val evaluationImgUrl: String? = null,
val evaluationComment: String? = null,
val starComments: List<StarCommentResponse> = emptyList(),
val newImage: String? = null,
)

@Serializable
data class StarCommentResponse(
val star: Double,
val comment: String,
)
Loading