From 7140ecb7abcbd10bc233b97029e474487600def2 Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Tue, 18 Nov 2025 16:42:18 +0900 Subject: [PATCH 1/7] =?UTF-8?q?chore#155=20google=20credential=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/oauth/build.gradle.kts | 5 +++++ gradle/libs.versions.toml | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/feature/oauth/build.gradle.kts b/feature/oauth/build.gradle.kts index 10e4b72a..de1c1fe8 100644 --- a/feature/oauth/build.gradle.kts +++ b/feature/oauth/build.gradle.kts @@ -1,3 +1,5 @@ +import com.teamsolply.solply.convention.extension.implementation + plugins { alias(libs.plugins.solply.feature) } @@ -8,5 +10,8 @@ android { dependencies { implementation(libs.kakao.login) + implementation(libs.google.id) + implementation(libs.credentials.play.auth) + implementation(libs.credentials) implementation(projects.domain.oauth) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9b8ad48..cc1293c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -90,6 +90,8 @@ coil = "2.7.0" lottie = "6.4.1" jsoup = "1.17.2" kakao-login = "2.19.0" +credentials = "1.6.0-beta03" +googleid = "1.1.1" process-pheonix = "3.0.0" preference = "1.2.1" collapsing-toolbar = "2.3.5" @@ -253,6 +255,11 @@ lottie = { group = "com.airbnb.android", name = "lottie", version.ref = "lottie" lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" } jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoup" } kakao-login = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakao-login" } + +credentials = { module = "androidx.credentials:credentials", version.ref = "credentials" } +credentials-play-auth = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "credentials" } +google-id = { module = "com.google.android.libraries.identity.googleid:googleid", version.ref = "googleid" } + process-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "process-pheonix" } collapsing-toolbar = { group = "me.onebone", name = "toolbar-compose", version.ref = "collapsing-toolbar" } androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" } From acee84e99e0bfe5ac507ce25257197e95cb43231 Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Tue, 18 Nov 2025 22:49:04 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feature#155=20buildconfig=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/teamsolply/solply/convention/BuildConfig.kt | 5 +++++ .../solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt | 2 ++ .../solply/common/buildconfig/BuildConfigFields.kt | 1 + 3 files changed, 8 insertions(+) diff --git a/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt b/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt index ab0598c0..5bb977d6 100644 --- a/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt +++ b/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt @@ -34,6 +34,11 @@ internal fun Project.configureBuildConfig( "NAVER_DEVELOPERS_CLIENT_SECRET", gradleLocalProperties(rootDir, providers).getProperty("naver.developers.client.secret") ) + buildConfigField( + "String", + "GOOGLE_CLIENT_ID", + gradleLocalProperties(rootDir,providers).getProperty("google.client.id") + ) } buildFeatures { diff --git a/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt b/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt index 85469c5b..8b024117 100644 --- a/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt +++ b/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt @@ -1,6 +1,7 @@ package com.teamsolply.solply.buildconfig.impl import com.teamsolply.solply.buildconfig.BuildConfig.BASE_URL +import com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_CLIENT_ID import com.teamsolply.solply.buildconfig.BuildConfig.KAKAO_NATIVE_KEY import com.teamsolply.solply.buildconfig.BuildConfig.NAVER_CLIENT_ID import com.teamsolply.solply.buildconfig.BuildConfig.NAVER_DEVELOPERS_CLIENT_ID @@ -14,6 +15,7 @@ class BuildConfigFieldsProviderImpl @Inject constructor() : BuildConfigFieldProv BuildConfigFields( baseUrl = BASE_URL, kakaoNativeKey = KAKAO_NATIVE_KEY, + googleClientId = GOOGLE_CLIENT_ID, naverClientId = NAVER_CLIENT_ID, naverDevelopersClientId = NAVER_DEVELOPERS_CLIENT_ID, naverDevelopersClientSecret = NAVER_DEVELOPERS_CLIENT_SECRET, diff --git a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt index 16de764e..d23a564f 100644 --- a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt +++ b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt @@ -3,6 +3,7 @@ package com.teamsolply.solply.common.buildconfig data class BuildConfigFields( val baseUrl: String, val kakaoNativeKey: String, + val googleClientId:String, val naverClientId: String, val naverDevelopersClientId: String, val naverDevelopersClientSecret: String, From 64504f4ff5bf0ae74b400df02fa0fd6fe3786a1a Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Thu, 20 Nov 2025 16:03:47 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feature#155=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/drawable/ic_google_logo.xml | 22 +++++ .../solply/oauth/GoogleLoginHelper.kt | 87 +++++++++++++++++++ .../teamsolply/solply/oauth/OauthContract.kt | 4 + .../teamsolply/solply/oauth/OauthScreen.kt | 32 +++++-- .../teamsolply/solply/oauth/OauthViewModel.kt | 11 +++ feature/oauth/src/main/res/values/strings.xml | 1 + 6 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 core/designsystem/src/main/res/drawable/ic_google_logo.xml create mode 100644 feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt diff --git a/core/designsystem/src/main/res/drawable/ic_google_logo.xml b/core/designsystem/src/main/res/drawable/ic_google_logo.xml new file mode 100644 index 00000000..55e2eeaf --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_google_logo.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt new file mode 100644 index 00000000..c4955940 --- /dev/null +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt @@ -0,0 +1,87 @@ +package com.teamsolply.solply.oauth + +import android.content.Context +import androidx.credentials.CredentialManager +import androidx.credentials.CustomCredential +import androidx.credentials.GetCredentialRequest +import androidx.credentials.GetCredentialResponse +import androidx.credentials.exceptions.GetCredentialException +import androidx.multidex.BuildConfig +import com.google.android.libraries.identity.googleid.GetGoogleIdOption +import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential +import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class GoogleLoginHelper( + private val context: Context +) { + + companion object { + const val TAG = "GoogleLogin" + const val WEB_CLIENT_ID = BuildConfig. + //const val SERVER_URL = "" + } + + private val credentialManager: CredentialManager = CredentialManager.create(context) + private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() + .setServerClientId(WEB_CLIENT_ID) // 웹 클라이언트 ID + .setFilterByAuthorizedAccounts(false) // 기존 계정 필터링 해제 + .setAutoSelectEnabled(true) //이전에 선택한 계정을 기억함 + .build() + private val request: GetCredentialRequest = GetCredentialRequest.Builder() + .addCredentialOption(googleIdOption) + .build() + private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main) + + fun requestGoogleLogin( + onSuccess: (String) -> Unit, + onFailure: (String) -> Unit + ) { + coroutineScope.launch { + try { + val result = credentialManager.getCredential( + request = request, + context = context + ) + handleSignInResult(result, onSuccess, onFailure) + } catch (e: GetCredentialException) { + onFailure("Google Sign-in failed: ${e.localizedMessage}") + } + } + } + + private fun handleSignInResult( + result: GetCredentialResponse, + onSuccess: (String) -> Unit, + onFailure: (String) -> Unit + ) { + when (val credential = result.credential) { + is CustomCredential -> { + if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { + try { + val googleIdTokenCredential = + GoogleIdTokenCredential.createFrom(credential.data) + val idToken = googleIdTokenCredential.idToken + //sendTokenToServer(token, onSuccess, onFailure) 서버로 토큰을 전송하고 결과에 따른 처리 +// Log.d(TAG, idToken) //토큰 +// Log.d(TAG, googleIdTokenCredential.id) //이메일 +// googleIdTokenCredential.displayName?.let { Log.d(TAG, it) } //이름 + onSuccess(idToken) //성공 시 처리 함수, 서버 응답 후 실행, 여기서는 테스트를 위해 이곳에서 실행 + } catch (e: GoogleIdTokenParsingException) { +// Log.e(TAG, "Received an invalid google id token response", e) + } + } else { +// Log.e(TAG, "Unexpected type of credential") + onFailure("구글 로그인에 실패하였습니다. 다시 시도해주세요.") + } + } + + else -> { +// Log.e(TAG, "Unexpected type of credential") + onFailure("구글 로그인에 실패하였습니다. 다시 시도해주세요.") + } + } + } +} diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt index 5d6bbc03..60da17d4 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthContract.kt @@ -12,6 +12,9 @@ sealed interface OauthIntent : UiIntent { data object KakaoLoginClick : OauthIntent data class KakaoLoginSuccess(val provider: String, val accessToken: String) : OauthIntent data class KakaoLoginFailure(val error: Throwable) : OauthIntent + data object GoogleLoginClick : OauthIntent + data class GoogleLoginSuccess(val provider: String, val accessToken: String) : OauthIntent + data class GoogleLoginFailure(val error: Throwable) : OauthIntent data class SaveJwtToken( val accessToken: String, val refreshToken: String, @@ -21,6 +24,7 @@ sealed interface OauthIntent : UiIntent { sealed interface OauthSideEffect : SideEffect { data object StartKakaoLogin : OauthSideEffect + data object StartGoogleLogin : OauthSideEffect data object NavigateToOnBoarding : OauthSideEffect data object NavigateToPlace : OauthSideEffect } diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt index 487f8f2d..0d988289 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.Text 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.graphics.Color @@ -46,6 +47,7 @@ fun OauthRoute( viewModel: OauthViewModel = hiltViewModel() ) { val context = LocalContext.current + val googleLoginHelper = remember { GoogleLoginHelper(context = context) } val uiState by viewModel.uiState.collectAsStateWithLifecycle() LaunchedEffectWithLifecycle { @@ -63,6 +65,18 @@ fun OauthRoute( } ) + OauthSideEffect.StartGoogleLogin -> googleLoginHelper.requestGoogleLogin( + onSuccess = { accessToken -> + viewModel.sendIntent( + OauthIntent.GoogleLoginSuccess( + provider = "GOOGLE", + accessToken = accessToken + ) + ) + }, + onFailure = {} + ) + OauthSideEffect.NavigateToOnBoarding -> navigateToOnBoarding() OauthSideEffect.NavigateToPlace -> navigateToPlace() } @@ -70,13 +84,15 @@ fun OauthRoute( } OauthScreen( - kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) } + kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) }, + googleLoginClick = { viewModel.sendIntent(OauthIntent.GoogleLoginClick) } ) } @Composable fun OauthScreen( kakaoLoginClick: () -> Unit, + googleLoginClick: () -> Unit, modifier: Modifier = Modifier ) { Column( @@ -151,28 +167,28 @@ fun OauthScreen( .height(52.dp) .padding(start = 20.dp, end = 20.dp) .background( - color = SolplyTheme.colors.black, + color = SolplyTheme.colors.white, shape = RoundedCornerShape(12.dp) ) .customClickable( rippleEnabled = false ) { - kakaoLoginClick() + googleLoginClick() }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start ) { Icon( - painter = painterResource(R.drawable.ic_apple_logo), - contentDescription = "kakao_logo", + painter = painterResource(R.drawable.ic_google_logo), + contentDescription = "google_logo", tint = Color.Unspecified, modifier = Modifier .padding(start = 16.dp, end = 12.dp, top = 12.dp, bottom = 12.dp) ) Text( - text = stringResource(com.teamsolply.solply.oauth.R.string.apple_login), + text = stringResource(com.teamsolply.solply.oauth.R.string.google_login), style = SolplyTheme.typography.button16M, - color = SolplyTheme.colors.white + color = SolplyTheme.colors.black ) } Spacer(modifier = Modifier.height(48.dp)) @@ -216,4 +232,4 @@ fun startKakaoLogin( } } } -} +} \ No newline at end of file diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt index a728459f..a59c1db8 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthViewModel.kt @@ -25,6 +25,17 @@ class OauthViewModel @Inject constructor( TODO() } + OauthIntent.GoogleLoginClick -> postSideEffect(OauthSideEffect.StartGoogleLogin) + + is OauthIntent.GoogleLoginSuccess -> postSocialLogin( + provider = intent.provider, + oauthAccessToken = intent.accessToken + ) + + is OauthIntent.GoogleLoginFailure -> { + TODO() + } + is OauthIntent.SaveJwtToken -> { viewModelScope.launch { oauthRepository.saveJwtToken( diff --git a/feature/oauth/src/main/res/values/strings.xml b/feature/oauth/src/main/res/values/strings.xml index bec778d5..c686eb09 100644 --- a/feature/oauth/src/main/res/values/strings.xml +++ b/feature/oauth/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ 카카오로 계속하기 + Google로 계속하기 Apple로 계속하기 \ No newline at end of file From c67b7afec76303cc1ccb150ee7859d56bcfa3190 Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Fri, 21 Nov 2025 15:04:38 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feature#155=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/proguard-rules.pro | 5 ++++- .../teamsolply/solply/convention/BuildConfig.kt | 4 ++-- .../impl/BuildConfigFieldsProviderImpl.kt | 4 ++-- .../solply/common/buildconfig/BuildConfigFields.kt | 2 +- feature/oauth/build.gradle.kts | 1 + .../teamsolply/solply/oauth/GoogleLoginHelper.kt | 13 +++++++------ .../com/teamsolply/solply/oauth/OauthScreen.kt | 14 +++++++++++++- 7 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb434..ea1e3875 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,7 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +-keep class * extends com.google.gson.TypeAdapter +-keep class com.google.googlesignin.** { *; } \ No newline at end of file diff --git a/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt b/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt index 5bb977d6..b6528594 100644 --- a/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt +++ b/build-logic/convention/src/main/java/com/teamsolply/solply/convention/BuildConfig.kt @@ -36,8 +36,8 @@ internal fun Project.configureBuildConfig( ) buildConfigField( "String", - "GOOGLE_CLIENT_ID", - gradleLocalProperties(rootDir,providers).getProperty("google.client.id") + "GOOGLE_WEB_CLIENT_ID", + gradleLocalProperties(rootDir, providers).getProperty("google.web.client.id") ) } diff --git a/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt b/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt index 8b024117..d4d765bd 100644 --- a/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt +++ b/core/buildconfig/src/main/java/com/teamsolply/solply/buildconfig/impl/BuildConfigFieldsProviderImpl.kt @@ -1,7 +1,7 @@ package com.teamsolply.solply.buildconfig.impl import com.teamsolply.solply.buildconfig.BuildConfig.BASE_URL -import com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_CLIENT_ID +import com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_WEB_CLIENT_ID import com.teamsolply.solply.buildconfig.BuildConfig.KAKAO_NATIVE_KEY import com.teamsolply.solply.buildconfig.BuildConfig.NAVER_CLIENT_ID import com.teamsolply.solply.buildconfig.BuildConfig.NAVER_DEVELOPERS_CLIENT_ID @@ -15,7 +15,7 @@ class BuildConfigFieldsProviderImpl @Inject constructor() : BuildConfigFieldProv BuildConfigFields( baseUrl = BASE_URL, kakaoNativeKey = KAKAO_NATIVE_KEY, - googleClientId = GOOGLE_CLIENT_ID, + googleWebClientId = GOOGLE_WEB_CLIENT_ID, naverClientId = NAVER_CLIENT_ID, naverDevelopersClientId = NAVER_DEVELOPERS_CLIENT_ID, naverDevelopersClientSecret = NAVER_DEVELOPERS_CLIENT_SECRET, diff --git a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt index d23a564f..f60ef72c 100644 --- a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt +++ b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt @@ -3,7 +3,7 @@ package com.teamsolply.solply.common.buildconfig data class BuildConfigFields( val baseUrl: String, val kakaoNativeKey: String, - val googleClientId:String, + val googleWebClientId:String, val naverClientId: String, val naverDevelopersClientId: String, val naverDevelopersClientSecret: String, diff --git a/feature/oauth/build.gradle.kts b/feature/oauth/build.gradle.kts index de1c1fe8..5630c3b9 100644 --- a/feature/oauth/build.gradle.kts +++ b/feature/oauth/build.gradle.kts @@ -14,4 +14,5 @@ dependencies { implementation(libs.credentials.play.auth) implementation(libs.credentials) implementation(projects.domain.oauth) + implementation(projects.core.buildconfig) } diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt index c4955940..d030028f 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt @@ -1,18 +1,19 @@ package com.teamsolply.solply.oauth import android.content.Context +import android.util.Log import androidx.credentials.CredentialManager import androidx.credentials.CustomCredential import androidx.credentials.GetCredentialRequest import androidx.credentials.GetCredentialResponse import androidx.credentials.exceptions.GetCredentialException -import androidx.multidex.BuildConfig import com.google.android.libraries.identity.googleid.GetGoogleIdOption import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import java.util.UUID class GoogleLoginHelper( private val context: Context @@ -20,15 +21,16 @@ class GoogleLoginHelper( companion object { const val TAG = "GoogleLogin" - const val WEB_CLIENT_ID = BuildConfig. + const val WEB_CLIENT_ID = com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_WEB_CLIENT_ID //const val SERVER_URL = "" } private val credentialManager: CredentialManager = CredentialManager.create(context) + private val nonce = UUID.randomUUID().toString() private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() .setServerClientId(WEB_CLIENT_ID) // 웹 클라이언트 ID - .setFilterByAuthorizedAccounts(false) // 기존 계정 필터링 해제 - .setAutoSelectEnabled(true) //이전에 선택한 계정을 기억함 + .setFilterByAuthorizedAccounts(false) +// .setNonce(nonce) .build() private val request: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) @@ -47,7 +49,7 @@ class GoogleLoginHelper( ) handleSignInResult(result, onSuccess, onFailure) } catch (e: GetCredentialException) { - onFailure("Google Sign-in failed: ${e.localizedMessage}") + Log.e("Google Sign-in failed", " ${e.localizedMessage}") } } } @@ -64,7 +66,6 @@ class GoogleLoginHelper( val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) val idToken = googleIdTokenCredential.idToken - //sendTokenToServer(token, onSuccess, onFailure) 서버로 토큰을 전송하고 결과에 따른 처리 // Log.d(TAG, idToken) //토큰 // Log.d(TAG, googleIdTokenCredential.id) //이메일 // googleIdTokenCredential.displayName?.let { Log.d(TAG, it) } //이름 diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt index 0d988289..e081369a 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt @@ -85,7 +85,19 @@ fun OauthRoute( OauthScreen( kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) }, - googleLoginClick = { viewModel.sendIntent(OauthIntent.GoogleLoginClick) } + googleLoginClick = { + googleLoginHelper.requestGoogleLogin( + onSuccess = { accessToken -> + viewModel.sendIntent( + OauthIntent.GoogleLoginSuccess( + provider = "GOOGLE", + accessToken = accessToken + ) + ) + }, + onFailure = {} + ) + } ) } From 50d9c7ec8b98647e302d3956025e241c315f305d Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Fri, 21 Nov 2025 15:18:27 +0900 Subject: [PATCH 5/7] =?UTF-8?q?fix#155=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=ED=99=94=EB=A9=B4=20=EA=B0=84=EA=B2=A9=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamsolply/solply/mypage/profile/ProfileEditScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt index 8208519a..c9fc23f1 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt @@ -126,7 +126,7 @@ fun ProfileEditScreen( onBackButtonClick = onBackButtonClick ) Spacer( - modifier = Modifier.weight(1f) + modifier = Modifier.height(16.dp) ) Image( painter = painterResource(R.drawable.img_basic_profile), @@ -137,7 +137,7 @@ fun ProfileEditScreen( .clip(CircleShape), contentScale = ContentScale.Fit ) - Spacer(modifier = Modifier.weight(2f)) + Spacer(modifier = Modifier.height(32.dp)) Column( modifier = Modifier.padding(horizontal = 16.dp), verticalArrangement = Arrangement.Top, @@ -165,7 +165,7 @@ fun ProfileEditScreen( modifier = Modifier.padding(top = 12.dp) ) } - Spacer(modifier = Modifier.weight(1.5f)) + Spacer(modifier = Modifier.height(24.dp)) Column( modifier = Modifier.padding(horizontal = 16.dp), verticalArrangement = Arrangement.Top, From efabe6765f0dfd4b9d40689be33ca2b2788d6fe9 Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Fri, 21 Nov 2025 15:18:57 +0900 Subject: [PATCH 6/7] chore#155 apply ktlint --- .../teamsolply/solply/common/buildconfig/BuildConfigFields.kt | 2 +- .../java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt | 4 ++-- .../src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt index f60ef72c..6b8875a1 100644 --- a/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt +++ b/core/common/src/main/java/com/teamsolply/solply/common/buildconfig/BuildConfigFields.kt @@ -3,7 +3,7 @@ package com.teamsolply.solply.common.buildconfig data class BuildConfigFields( val baseUrl: String, val kakaoNativeKey: String, - val googleWebClientId:String, + val googleWebClientId: String, val naverClientId: String, val naverDevelopersClientId: String, val naverDevelopersClientSecret: String, diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt index d030028f..83adb44e 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt @@ -22,7 +22,7 @@ class GoogleLoginHelper( companion object { const val TAG = "GoogleLogin" const val WEB_CLIENT_ID = com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_WEB_CLIENT_ID - //const val SERVER_URL = "" + // const val SERVER_URL = "" } private val credentialManager: CredentialManager = CredentialManager.create(context) @@ -69,7 +69,7 @@ class GoogleLoginHelper( // Log.d(TAG, idToken) //토큰 // Log.d(TAG, googleIdTokenCredential.id) //이메일 // googleIdTokenCredential.displayName?.let { Log.d(TAG, it) } //이름 - onSuccess(idToken) //성공 시 처리 함수, 서버 응답 후 실행, 여기서는 테스트를 위해 이곳에서 실행 + onSuccess(idToken) // 성공 시 처리 함수, 서버 응답 후 실행, 여기서는 테스트를 위해 이곳에서 실행 } catch (e: GoogleIdTokenParsingException) { // Log.e(TAG, "Received an invalid google id token response", e) } diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt index e081369a..12e9c6d4 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt @@ -244,4 +244,4 @@ fun startKakaoLogin( } } } -} \ No newline at end of file +} From 57804bb30c20340321a43a63247d51a6ef147f91 Mon Sep 17 00:00:00 2001 From: ImHyungsuk Date: Fri, 21 Nov 2025 16:30:40 +0900 Subject: [PATCH 7/7] merge#155 resolve conflict --- .../dto/request/PatchUserInfoRequestDto.kt | 8 ++--- .../dto/request/PolicyAgreementInfoDto.kt | 13 +++++++ .../dto/response/GetAllTownResponseDto.kt | 2 ++ .../mapper/PolicyAgreementInfoMapper.kt | 10 ++++++ .../onboarding/mapper/TownEntitiyMapper.kt | 33 ++++++++++++++--- .../repository/OnBoardingRepositoryImpl.kt | 10 +++--- .../model/PolicyAgreementInfoEntity.kt | 6 ++++ .../solply/onboarding/model/TownEntity.kt | 11 ++++-- .../repository/OnBoardingRepository.kt | 5 +-- .../teamsolply/solply/oauth/OauthScreen.kt | 2 +- .../solply/onboarding/OnBoardingContract.kt | 13 +++++-- .../solply/onboarding/OnBoardingViewModel.kt | 23 ++++++++++-- .../onboarding/screen/AllowClauseScreen.kt | 36 +++++++++---------- .../onboarding/screen/SelectTownScreen.kt | 35 +++++++----------- 14 files changed, 142 insertions(+), 65 deletions(-) create mode 100644 data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PolicyAgreementInfoDto.kt create mode 100644 data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PolicyAgreementInfoMapper.kt create mode 100644 domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PolicyAgreementInfoEntity.kt diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PatchUserInfoRequestDto.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PatchUserInfoRequestDto.kt index c06efd1c..99121e84 100644 --- a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PatchUserInfoRequestDto.kt +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PatchUserInfoRequestDto.kt @@ -8,12 +8,12 @@ data class PatchUserInfoRequestDto( @SerialName("selectedTownId") val selectedTownId: Long, - @SerialName("favoriteTownIdList") - val favoriteTownIdList: List, - @SerialName("persona") val persona: String, @SerialName("nickname") - val nickname: String + val nickname: String, + + @SerialName("policyAgreementInfos") + val policyAgreementInfos: List ) diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PolicyAgreementInfoDto.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PolicyAgreementInfoDto.kt new file mode 100644 index 00000000..e22889f2 --- /dev/null +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/request/PolicyAgreementInfoDto.kt @@ -0,0 +1,13 @@ +package com.teamsolply.solply.onboarding.dto.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class PolicyAgreementInfoDto( + @SerialName("policyId") + val policyId: Long, + + @SerialName("isAgree") + val isAgree: Boolean +) diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetAllTownResponseDto.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetAllTownResponseDto.kt index 6d4b84ed..db9d53da 100644 --- a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetAllTownResponseDto.kt +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetAllTownResponseDto.kt @@ -15,6 +15,8 @@ data class TownDto( val townId: Long, @SerialName("townName") val townName: String, + @SerialName("parentTownId") + val parentTownId: Long? = null, @SerialName("subTowns") val subTowns: List? = null ) diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PolicyAgreementInfoMapper.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PolicyAgreementInfoMapper.kt new file mode 100644 index 00000000..ba5145f5 --- /dev/null +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PolicyAgreementInfoMapper.kt @@ -0,0 +1,10 @@ +package com.teamsolply.solply.onboarding.mapper + +import com.teamsolply.solply.onboarding.dto.request.PolicyAgreementInfoDto +import com.teamsolply.solply.onboarding.model.PolicyAgreementInfoEntity + +fun PolicyAgreementInfoEntity.toDto(): PolicyAgreementInfoDto = + PolicyAgreementInfoDto( + policyId = this.policyId, + isAgree = this.isAgree + ) diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/TownEntitiyMapper.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/TownEntitiyMapper.kt index 33388052..c0309801 100644 --- a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/TownEntitiyMapper.kt +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/TownEntitiyMapper.kt @@ -2,19 +2,44 @@ package com.teamsolply.solply.onboarding.mapper import com.teamsolply.solply.onboarding.dto.response.GetAllTownResponseDto import com.teamsolply.solply.onboarding.dto.response.TownDto +import com.teamsolply.solply.onboarding.model.ParentTownEntity import com.teamsolply.solply.onboarding.model.SubTownEntity import com.teamsolply.solply.onboarding.model.TownEntity fun GetAllTownResponseDto.toEntity(): TownEntity { + val parentTowns = towns.filter { it.parentTownId == null } + + val grouped = parentTowns.map { parent -> + ParentTownEntity( + townId = parent.townId, + townName = parent.townName, + subTowns = towns + .filter { it.parentTownId == parent.townId } + .map { dto -> + SubTownEntity( + townId = dto.townId, + townName = dto.townName + ) + } + ) + } + return TownEntity( - towns = towns.map { it.toSubEntity() } + parentTowns = grouped + ) +} + +fun TownDto.toParentEntity(): ParentTownEntity { + return ParentTownEntity( + townId = townId, + townName = townName, + subTowns = subTowns?.map { it.toSubEntity() } ?: emptyList() ) } fun TownDto.toSubEntity(): SubTownEntity { return SubTownEntity( - townId = this.townId, - townName = this.townName, - subTowns = this.subTowns?.map { it.toSubEntity() } + townId = townId, + townName = townName ) } diff --git a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt index 898c0f24..cb48db68 100644 --- a/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt +++ b/data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt @@ -1,8 +1,10 @@ package com.teamsolply.solply.onboarding.repository import com.teamsolply.solply.onboarding.dto.request.PatchUserInfoRequestDto +import com.teamsolply.solply.onboarding.mapper.toDto import com.teamsolply.solply.onboarding.mapper.toEntity import com.teamsolply.solply.onboarding.model.PersonaEntity +import com.teamsolply.solply.onboarding.model.PolicyAgreementInfoEntity import com.teamsolply.solply.onboarding.model.TownEntity import com.teamsolply.solply.onboarding.model.UserInfoEntity import com.teamsolply.solply.onboarding.source.remote.OnBoardingRemoteDataSource @@ -29,16 +31,16 @@ class OnBoardingRepositoryImpl @Inject constructor( override suspend fun patchUserInfo( selectedTownId: Long, - favoriteTownIdList: List, persona: String, - nickname: String + nickname: String, + policyAgreementInfos: List ): Result = runCatching { onBoardingRemoteDataSource.patchUserInfo( PatchUserInfoRequestDto( selectedTownId = selectedTownId, - favoriteTownIdList = favoriteTownIdList, persona = persona, - nickname = nickname + nickname = nickname, + policyAgreementInfos = policyAgreementInfos.map { it.toDto() } ) ) }.mapCatching { diff --git a/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PolicyAgreementInfoEntity.kt b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PolicyAgreementInfoEntity.kt new file mode 100644 index 00000000..f8da33e0 --- /dev/null +++ b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PolicyAgreementInfoEntity.kt @@ -0,0 +1,6 @@ +package com.teamsolply.solply.onboarding.model + +data class PolicyAgreementInfoEntity( + val policyId: Long, + val isAgree: Boolean +) diff --git a/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/TownEntity.kt b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/TownEntity.kt index 91cdeb5d..e5767279 100644 --- a/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/TownEntity.kt +++ b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/TownEntity.kt @@ -1,11 +1,16 @@ package com.teamsolply.solply.onboarding.model data class TownEntity( - val towns: List + val parentTowns: List ) -data class SubTownEntity( +data class ParentTownEntity( val townId: Long, val townName: String, - val subTowns: List? = null + val subTowns: List +) + +data class SubTownEntity( + val townId: Long, + val townName: String ) diff --git a/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt index 8d965d09..b21d6347 100644 --- a/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt +++ b/domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt @@ -1,6 +1,7 @@ package com.teamsolply.solply.onboarding.repository import com.teamsolply.solply.onboarding.model.PersonaEntity +import com.teamsolply.solply.onboarding.model.PolicyAgreementInfoEntity import com.teamsolply.solply.onboarding.model.TownEntity import com.teamsolply.solply.onboarding.model.UserInfoEntity @@ -10,8 +11,8 @@ interface OnBoardingRepository { suspend fun checkNicknameDuplicate(nickname: String): Result suspend fun patchUserInfo( selectedTownId: Long, - favoriteTownIdList: List, persona: String, - nickname: String + nickname: String, + policyAgreementInfos: List ): Result } diff --git a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt index 12e9c6d4..26e5f0f9 100644 --- a/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt +++ b/feature/oauth/src/main/java/com/teamsolply/solply/oauth/OauthScreen.kt @@ -110,7 +110,7 @@ fun OauthScreen( Column( modifier.fillMaxSize() ) { - Spacer(modifier = Modifier.height(115.dp)) + Spacer(modifier = Modifier.height(180.dp)) Image( painter = painterResource(R.drawable.ic_logo_full_vector), contentDescription = "app_logo", diff --git a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt index e6ee1c14..f00aa866 100644 --- a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt +++ b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt @@ -8,21 +8,25 @@ import com.teamsolply.solply.ui.base.UiState data class OnBoardingState( val currentPage: Int = 0, - val totalPageCount: Int = 3, + val totalPageCount: Int = 4, val townList: TownEntity = TownEntity( - towns = emptyList() + parentTowns = emptyList() ), val selectedRegionId: Long? = 1, val selectedTownId: Long? = null, val townBottomSheetShown: Boolean = false, + val personaList: PersonaEntity = PersonaEntity(personaList = emptyList()), val selectedPersona: String? = null, val userNickname: String = "", val isNicknameDuplicate: Boolean = false, val showStartingScreen: Boolean = false, - val isOnBoardingSuccess: Boolean = false + val isOnBoardingSuccess: Boolean = false, + val agree14: Boolean = false, + val agreeService: Boolean = false, + val agreePrivacy: Boolean = false ) : UiState sealed interface OnBoardingIntent : UiIntent { @@ -40,6 +44,9 @@ sealed interface OnBoardingIntent : UiIntent { ) : OnBoardingIntent data object ShowStartingScreen : OnBoardingIntent + data class ChangeAgree14(val isChecked: Boolean) : OnBoardingIntent + data class ChangeAgreeService(val isChecked: Boolean) : OnBoardingIntent + data class ChangeAgreePrivacy(val isChecked: Boolean) : OnBoardingIntent } sealed interface OnBoardingSideEffect : SideEffect { diff --git a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt index c1ebe070..ace2de8e 100644 --- a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt +++ b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt @@ -1,6 +1,7 @@ package com.teamsolply.solply.onboarding import androidx.lifecycle.viewModelScope +import com.teamsolply.solply.onboarding.model.PolicyAgreementInfoEntity import com.teamsolply.solply.onboarding.repository.OnBoardingRepository import com.teamsolply.solply.ui.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel @@ -83,6 +84,17 @@ class OnBoardingViewModel @Inject constructor( is OnBoardingIntent.ShowStartingScreen -> { patchUserInfo() } + is OnBoardingIntent.ChangeAgree14 -> { + reduce { copy(agree14 = intent.isChecked) } + } + + is OnBoardingIntent.ChangeAgreeService -> { + reduce { copy(agreeService = intent.isChecked) } + } + + is OnBoardingIntent.ChangeAgreePrivacy -> { + reduce { copy(agreePrivacy = intent.isChecked) } + } } } @@ -118,11 +130,18 @@ class OnBoardingViewModel @Inject constructor( viewModelScope.launch { uiState.value.selectedTownId?.let { selectedTownId -> uiState.value.selectedPersona?.let { selectedPersona -> + + val policyInfos = listOf( + PolicyAgreementInfoEntity(1, uiState.value.agree14), + PolicyAgreementInfoEntity(2, uiState.value.agreeService), + PolicyAgreementInfoEntity(3, uiState.value.agreePrivacy) + ) + onBoardingRepository.patchUserInfo( selectedTownId = selectedTownId, - favoriteTownIdList = uiState.value.townList.towns.map { it.townId }, persona = selectedPersona, - nickname = uiState.value.userNickname + nickname = uiState.value.userNickname, + policyAgreementInfos = policyInfos ).onSuccess { reduce { copy(showStartingScreen = true) } } diff --git a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/AllowClauseScreen.kt b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/AllowClauseScreen.kt index aa2933b8..b74a2554 100644 --- a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/AllowClauseScreen.kt +++ b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/AllowClauseScreen.kt @@ -17,11 +17,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -38,14 +33,10 @@ fun AllowClauseScreen( onNextClick: () -> Unit, onBoardingIntent: (OnBoardingIntent) -> Unit ) { - var isAllChecked by remember { mutableStateOf(false) } - var agree14 by remember { mutableStateOf(false) } - var agreeService by remember { mutableStateOf(false) } - var agreePrivacy by remember { mutableStateOf(false) } - - LaunchedEffect(agree14, agreeService, agreePrivacy) { - isAllChecked = agree14 && agreeService && agreePrivacy - } + val agree14 = state.agree14 + val agreeService = state.agreeService + val agreePrivacy = state.agreePrivacy + val isAllChecked = agree14 && agreeService && agreePrivacy Column( modifier = Modifier @@ -77,10 +68,9 @@ fun AllowClauseScreen( ) .customClickable(rippleEnabled = false) { val toggle = !isAllChecked - isAllChecked = toggle - agree14 = toggle - agreeService = toggle - agreePrivacy = toggle + onBoardingIntent(OnBoardingIntent.ChangeAgree14(toggle)) + onBoardingIntent(OnBoardingIntent.ChangeAgreeService(toggle)) + onBoardingIntent(OnBoardingIntent.ChangeAgreePrivacy(toggle)) } ) { Row( @@ -114,13 +104,17 @@ fun AllowClauseScreen( AgreementItem( text = "(필수) 만 14세 이상입니다", checked = agree14, - onClick = { agree14 = !agree14 } + onClick = { + onBoardingIntent(OnBoardingIntent.ChangeAgree14(!agree14)) + } ) AgreementItem( text = "(필수) 서비스 이용 약관", checked = agreeService, - onClick = { agreeService = !agreeService }, + onClick = { + onBoardingIntent(OnBoardingIntent.ChangeAgreeService(!agreeService)) + }, showArrow = true, onArrowClick = { // TODO: 서비스 이용 약관 이동 @@ -130,7 +124,9 @@ fun AllowClauseScreen( AgreementItem( text = "(필수) 개인정보 처리방침", checked = agreePrivacy, - onClick = { agreePrivacy = !agreePrivacy }, + onClick = { + onBoardingIntent(OnBoardingIntent.ChangeAgreePrivacy(!agreePrivacy)) + }, showArrow = true, onArrowClick = { // TODO: 개인정보 처리방침 이동 diff --git a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectTownScreen.kt b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectTownScreen.kt index e6a76da3..e6cc50ee 100644 --- a/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectTownScreen.kt +++ b/feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectTownScreen.kt @@ -33,6 +33,7 @@ import com.teamsolply.solply.designsystem.theme.SolplyTheme import com.teamsolply.solply.onboarding.OnBoardingIntent import com.teamsolply.solply.onboarding.OnBoardingState import com.teamsolply.solply.onboarding.component.OnBoardingTownBottomSheet +import com.teamsolply.solply.onboarding.model.ParentTownEntity import com.teamsolply.solply.onboarding.model.SubTownEntity import com.teamsolply.solply.ui.extension.customClickable @@ -77,11 +78,13 @@ fun SelectTownScreen( ) } else { AddLocalAreaButton( - text = townList.towns - .flatMap { it.subTowns ?: emptyList() } + text = townList.parentTowns + .flatMap { it.subTowns } .find { it.townId == state.selectedTownId } ?.townName ?: "", - onClick = {}, + onClick = { + onBoardingIntent(OnBoardingIntent.ChangeTownBottomSheetShown) + }, selected = true ) } @@ -112,15 +115,9 @@ fun SelectTownScreen( ) { LeftRegionPane( borderColor = borderColor, - regions = townList.towns, + regions = townList.parentTowns, selectedRegionId = state.selectedRegionId, - onSelect = { id -> - onBoardingIntent( - OnBoardingIntent.ChangeRegion( - id - ) - ) - } + onSelect = { id -> onBoardingIntent(OnBoardingIntent.ChangeRegion(id)) } ) VerticalDivider( thickness = 1.dp, @@ -128,17 +125,11 @@ fun SelectTownScreen( ) RightTownPane( borderColor = borderColor, - towns = townList.towns + towns = townList.parentTowns .find { it.townId == state.selectedRegionId } ?.subTowns ?: emptyList(), selectedTownId = state.selectedTownId, - onSelect = { id -> - onBoardingIntent( - OnBoardingIntent.OnTownSelected( - id - ) - ) - } + onSelect = { id -> onBoardingIntent(OnBoardingIntent.OnTownSelected(id)) } ) } } @@ -184,7 +175,7 @@ fun SelectTownScreen( @Composable private fun LeftRegionPane( borderColor: Color, - regions: List, + regions: List, selectedRegionId: Long?, onSelect: (Long) -> Unit ) { @@ -194,7 +185,7 @@ private fun LeftRegionPane( .fillMaxHeight() .background(SolplyTheme.colors.gray100) ) { - itemsIndexed(items = regions) { index: Int, item: SubTownEntity -> + itemsIndexed(items = regions) { index: Int, item: ParentTownEntity -> val selected = selectedRegionId == item.townId val bg = if (selected) SolplyTheme.colors.white else SolplyTheme.colors.gray100 val textColor = if (selected) SolplyTheme.colors.black else SolplyTheme.colors.gray600 @@ -233,7 +224,7 @@ private fun LeftRegionPane( ) { Text( text = item.townName, - style = SolplyTheme.typography.body14M.copy(fontWeight = fontWeight), + style = SolplyTheme.typography.body16M.copy(fontWeight = fontWeight), color = textColor ) }