From 8f15e93c8a92f26fd76acb56624ad5b529fd11d3 Mon Sep 17 00:00:00 2001 From: starshape77 <111961655+starshape7@users.noreply.github.com> Date: Sun, 11 Jan 2026 05:22:54 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix=20:=20=EC=8B=9C=EA=B5=B0=EA=B5=AC=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=8B=9C/=EB=8F=99?= =?UTF-8?q?=20=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ConsultationCenterScreen.kt | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/feature/src/main/java/com/example/feature/ui/consultationCenter/ConsultationCenterScreen.kt b/feature/src/main/java/com/example/feature/ui/consultationCenter/ConsultationCenterScreen.kt index a94b6b2..7fcdbcb 100644 --- a/feature/src/main/java/com/example/feature/ui/consultationCenter/ConsultationCenterScreen.kt +++ b/feature/src/main/java/com/example/feature/ui/consultationCenter/ConsultationCenterScreen.kt @@ -98,8 +98,11 @@ fun ConsultationCenterScreen( // 위치 → 행정구역명 갱신 LaunchedEffect(userLocation) { userLocation?.let { ll -> - reverseGeocodeToSidoGu(context, ll)?.let { sidoGu -> - locationTitle = sidoGu + val sidoGu = reverseGeocodeToSidoGu(context, ll) + Log.d("LOCATION_DEBUG", "📍 reverseGeocode result = $sidoGu (lat=${ll.latitude}, lng=${ll.longitude})") + + sidoGu?.let { + locationTitle = it } } } @@ -457,22 +460,66 @@ suspend fun reverseGeocodeToSidoGu( return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { suspendCancellableCoroutine { cont -> geocoder.getFromLocation(lat, lng, 1) { list -> + Log.d("GEOCODER_DEBUG", "getFromLocation size=${list.size}, lat=$lat, lng=$lng") + val a = list.firstOrNull() - val sido = normalizeSido(a?.adminArea) - val gu = a?.locality ?: a?.subLocality ?: a?.subAdminArea - cont.resume( - if (!sido.isNullOrBlank() && !gu.isNullOrBlank()) - "$sido $gu" else null + if (a == null) { + Log.w("GEOCODER_DEBUG", "Address is null (empty list)") + cont.resume(null) + return@getFromLocation + } + + Log.d( + "GEOCODER_DEBUG", + """ + adminArea=${a.adminArea} + subAdminArea=${a.subAdminArea} + locality=${a.locality} + subLocality=${a.subLocality} + thoroughfare=${a.thoroughfare} + featureName=${a.featureName} + """.trimIndent() ) + + val sido = normalizeSido(a.adminArea) + // 🔥 여기 추가 / 교체 + val guOrDong = + a.subAdminArea + ?: a.locality + ?: a.subLocality + ?: a.thoroughfare // ✅ 역삼동 + ?: a.subThoroughfare + ?: a.featureName + + val result = + if (!sido.isNullOrBlank() && !guOrDong.isNullOrBlank()) + "$sido $guOrDong" + else null + + Log.d("GEOCODER_DEBUG", "result=$result (sido=$sido, gu=$guOrDong)") + + cont.resume(result) } } } else { withContext(Dispatchers.IO) { try { val a = geocoder.getFromLocation(lat, lng, 1)?.firstOrNull() - val sido = normalizeSido(a?.adminArea) - val gu = a?.locality ?: a?.subLocality ?: a?.subAdminArea - if (!sido.isNullOrBlank() && !gu.isNullOrBlank()) "$sido $gu" else null + if (a == null) return@withContext null + + val sido = normalizeSido(a.adminArea) + + val guOrDong = + a.subAdminArea + ?: a.locality + ?: a.subLocality + ?: a.thoroughfare + ?: a.subThoroughfare + ?: a.featureName + + if (!sido.isNullOrBlank() && !guOrDong.isNullOrBlank()) + "$sido $guOrDong" + else null } catch (_: Exception) { null } From 0136cd65120e7296e8cd06a3dca550b7a86c02b7 Mon Sep 17 00:00:00 2001 From: yeonwoo Date: Mon, 12 Jan 2026 09:24:01 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix=20:=20AICHAT=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/feature/ui/aichat/chatting/ChattingScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/src/main/java/com/example/feature/ui/aichat/chatting/ChattingScreen.kt b/feature/src/main/java/com/example/feature/ui/aichat/chatting/ChattingScreen.kt index cac6238..a1af1b9 100644 --- a/feature/src/main/java/com/example/feature/ui/aichat/chatting/ChattingScreen.kt +++ b/feature/src/main/java/com/example/feature/ui/aichat/chatting/ChattingScreen.kt @@ -195,7 +195,7 @@ internal fun RecentChattingScreen( painter = painterResource(id = R.drawable.ic_arrow_up), contentDescription = "Send", modifier = Modifier - .align(Alignment.CenterEnd) + .align(Alignment.TopEnd) .padding(6.dp) .clickable( enabled = userInput.isNotBlank(), From 6c2c99be3c70a3ceeb6731c449c7dccb9e3a2f11 Mon Sep 17 00:00:00 2001 From: yeonwoo Date: Mon, 12 Jan 2026 11:22:49 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix=20:=20UI=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/feature/MainScreen.kt | 121 +++++++++++++----- .../feature/ui/home/header/LogoHeader.kt | 2 +- .../feature/ui/home/screen/HomeScreen.kt | 58 ++++++--- 3 files changed, 127 insertions(+), 54 deletions(-) diff --git a/feature/src/main/java/com/example/feature/MainScreen.kt b/feature/src/main/java/com/example/feature/MainScreen.kt index c3ae715..dcb9c22 100644 --- a/feature/src/main/java/com/example/feature/MainScreen.kt +++ b/feature/src/main/java/com/example/feature/MainScreen.kt @@ -1,16 +1,33 @@ package com.example.feature +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview @@ -52,7 +69,6 @@ import com.example.feature.ui.onboarding.screen.LanguageScreen import com.example.feature.ui.onboarding.screen.LoginScreen import com.example.feature.ui.splash.screen.SplashScreen -// 아이콘 리소스 구성 (기본 / 클릭) data class NavItem( val route: String, val iconResId: Int, @@ -68,55 +84,90 @@ val items = listOf( NavItem("커뮤니티", R.drawable.ic_community, R.drawable.ic_community_click) ) +@Preview +@Composable +private fun preview() { + MyBottomNavigation(rememberNavController()) +} + @Composable fun MyBottomNavigation(navController: NavHostController) { val currentDestination = navController.currentBackStackEntryAsState().value?.destination + val currentRoute = currentDestination?.route - NavigationBar( - containerColor = Color.White, - tonalElevation = 0.dp + // 바 전체 컨테이너 (둥글게 + 그림자 + 패딩) + Box( + modifier = Modifier + .fillMaxWidth() + .background(Color.White) + .navigationBarsPadding() + .height(60.dp) ) { - items.forEach { item -> - val isSelected = currentDestination?.route == item.route - val iconRes = if (isSelected) item.iconClickResId else item.iconResId + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 15.dp, end = 15.dp, bottom = 15.dp), + verticalAlignment = Alignment.CenterVertically + ) { + items.forEach { item -> + val isSelected = currentRoute == item.route + val iconRes = if (isSelected) item.iconClickResId else item.iconResId - NavigationBarItem( - selected = isSelected, - onClick = { - if (!isSelected) { - if (item.route == "홈") { - // ✅ 홈으로 갈 때마다 전체 스택 초기화 - navController.navigate("홈") { - popUpTo(0) { inclusive = true } - launchSingleTop = true - } - } else { - // 나머지 탭은 기존처럼 동작 - navController.navigate(item.route) { - popUpTo(navController.graph.startDestinationId) { - saveState = true + BottomBarItem( + modifier = Modifier.weight(1f), // ✅ 균등 분배 + selected = isSelected, + iconRes = iconRes, + contentDescription = item.route, + onClick = { + if (!isSelected) { + if (item.route == "홈") { + navController.navigate("홈") { + popUpTo(0) { inclusive = true } + launchSingleTop = true + } + } else { + navController.navigate(item.route) { + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + launchSingleTop = true + restoreState = true } - launchSingleTop = true - restoreState = true } } } - }, - icon = { - Icon( - painter = painterResource(id = iconRes), - contentDescription = item.route, - tint = Color.Unspecified // 아이콘 색상 유지 - ) - }, - colors = NavigationBarItemDefaults.colors( - indicatorColor = Color.Transparent ) - ) + } } } } +@Composable +private fun BottomBarItem( + modifier: Modifier = Modifier, + selected: Boolean, + iconRes: Int, + contentDescription: String, + onClick: () -> Unit, +) { + Box( + modifier = modifier + .fillMaxHeight() + .clickable( + onClick = onClick + ), + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = iconRes), + contentDescription = contentDescription, + tint = Color.Unspecified, + modifier = Modifier.size(66.dp) // 아이콘 크기 + ) + } +} + + // 메인 네비게이션 호스트 @Composable fun MyNavigationHost(navController: NavHostController) { diff --git a/feature/src/main/java/com/example/feature/ui/home/header/LogoHeader.kt b/feature/src/main/java/com/example/feature/ui/home/header/LogoHeader.kt index 7834710..66cb095 100644 --- a/feature/src/main/java/com/example/feature/ui/home/header/LogoHeader.kt +++ b/feature/src/main/java/com/example/feature/ui/home/header/LogoHeader.kt @@ -20,7 +20,7 @@ fun LogoHeader( modifier = Modifier .fillMaxWidth() .height(56.dp) - .padding(start = 20.dp, top = 16.dp), + .padding(horizontal = 24.dp, vertical = 18.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start ) { diff --git a/feature/src/main/java/com/example/feature/ui/home/screen/HomeScreen.kt b/feature/src/main/java/com/example/feature/ui/home/screen/HomeScreen.kt index e8e6491..9247c61 100644 --- a/feature/src/main/java/com/example/feature/ui/home/screen/HomeScreen.kt +++ b/feature/src/main/java/com/example/feature/ui/home/screen/HomeScreen.kt @@ -5,9 +5,11 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -15,6 +17,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer @@ -35,6 +38,9 @@ import com.example.core.ui.R as languageR import com.example.feature.ui.mypage.navigation.navigateToMyPage import com.example.feature.ui.home.viewmodel.HomeViewModel import com.example.core.data.network.RetrofitInstance +import com.example.core.ui.theme.HelloWorldGoogleBorder +import com.example.core.ui.theme.HelloWorldMain100 +import com.example.core.ui.theme.HelloWorldMain300 import com.example.feature.ui.aichat.navigation.navigateToAIChat import com.example.feature.ui.aichat.navigation.navigateToAIChatDetail import com.example.feature.ui.community.navigation.navigateToCommunity @@ -73,9 +79,9 @@ fun HomeScreen( // 상단 사용자 정보 영역 Row( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp), - horizontalArrangement = Arrangement.SpaceBetween, + .wrapContentSize() + .padding(horizontal = 34.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically ) { Column { @@ -97,7 +103,13 @@ fun HomeScreen( style = AppTypography.heading01, color = HelloWorldGrayScale500 ) - Spacer(modifier = Modifier.height(4.dp)) + Spacer(modifier = Modifier.height(8.dp)) + HorizontalDivider( + modifier = Modifier.width(115.dp), + thickness = 1.dp, + color = HelloWorldMain300 + ) + Spacer(modifier = Modifier.height(8.dp)) Text( text = stringResource(languageR.string.home_go_mypage) + " →", style = AppTypography.label02, @@ -109,18 +121,18 @@ fun HomeScreen( ) } + Spacer(modifier = Modifier.width(37.dp)) + Image( painter = painterResource(id = R.drawable.avatar_character), contentDescription = "사용자 아바타", - modifier = Modifier.size(140.dp) + modifier = Modifier + .width(140.dp) + .height(164.dp) ) } - - Spacer(modifier = Modifier.height(12.dp)) - // 서비스 카드 목록 Column( - verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier .background(Color.White, shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp)) .padding(24.dp, 30.dp, 24.dp, 19.dp) @@ -131,9 +143,11 @@ fun HomeScreen( color = HelloWorldGrayScale500 ) + Spacer(modifier = Modifier.height(16.dp)) + Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) + horizontalArrangement = Arrangement.spacedBy(18.dp) ) { HomeServiceCard( title = stringResource(languageR.string.home_chatbot_title), @@ -153,9 +167,11 @@ fun HomeScreen( ) } + Spacer(modifier = Modifier.height(16.dp)) + Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) + horizontalArrangement = Arrangement.spacedBy(18.dp) ) { HomeServiceCard( title = stringResource(languageR.string.home_nearby_center_title), @@ -175,6 +191,15 @@ fun HomeScreen( ) } + Spacer(modifier = Modifier.height(12.dp)) + + HorizontalDivider( + modifier = Modifier.fillMaxWidth(), + thickness = 1.dp, + color = HelloWorldMain100 + ) + Spacer(modifier = Modifier.height(12.dp)) + Image( painter = painterResource(id = R.drawable.banner_helloworld), contentDescription = "HelloWorld 배너", @@ -194,16 +219,13 @@ fun HomeServiceCard( modifier: Modifier, onClick: () -> Unit, ) { - val shadowColor = Color(0x665E8DC5) + + val shadowColor = Color(0xFF0b458a) Box( modifier = modifier - .aspectRatio(1.3f) - .graphicsLayer { - shadowElevation = 4.dp.toPx() - shape = RoundedCornerShape(8.dp) - } + .shadow(elevation = 2.dp, ambientColor = shadowColor, spotColor = shadowColor, shape = RoundedCornerShape(8.dp)) .background(color = backgroundColor, shape = RoundedCornerShape(8.dp)) - .shadow(elevation = 1.dp, ambientColor = shadowColor, spotColor = shadowColor) + .clip(shape = RoundedCornerShape(8.dp)) .clickable(onClick = onClick) .padding(12.dp, 16.dp, 12.dp, 8.dp)