diff --git a/.editorconfig b/.editorconfig
index 5e0bd1f9..b65b2d92 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,5 +11,4 @@ indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
tab_width = 4
-ij_kotlin_allow_trailing_comma = true
-ktlint_standard_function-name = false
+ij_kotlin_allow_trailing_comma = true
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 36aeee14..b881960d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,6 +1,9 @@
plugins {
alias(libs.plugins.com.android.application)
alias(libs.plugins.org.jetbrains.kotlin.android)
+ alias(libs.plugins.hilt)
+ alias(libs.plugins.googleServices)
+ id("kotlin-kapt")
}
android {
@@ -67,5 +70,15 @@ dependencies {
debugImplementation(libs.androidx.ui.test.manifest)
implementation(project(":core:ui"))
+ implementation(project(":data"))
+ implementation(project(":domain"))
implementation(project(":feature:login"))
+
+ // hilt
+ implementation(libs.hilt)
+ kapt(libs.hilt.compiler)
+
+ // firebase
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.auth.ktx)
}
diff --git a/app/google-services.json b/app/google-services.json
index e69de29b..3566f694 100644
--- a/app/google-services.json
+++ b/app/google-services.json
@@ -0,0 +1,62 @@
+{
+ "project_info": {
+ "project_number": "217769178527",
+ "project_id": "pokit-f5c83",
+ "storage_bucket": "pokit-f5c83.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:217769178527:android:5d7efa4ceafe61c37af9aa",
+ "android_client_info": {
+ "package_name": "pokitmons.pokit"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "217769178527-jaa8p8nfmic1j1065qs5a7vfqt18qec0.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "pokitmons.pokit",
+ "certificate_hash": "9ded6dcd446add68f506001f3c1b457cc1c3be9e"
+ }
+ },
+ {
+ "client_id": "217769178527-mmbheg9v5npdhdrbfq78slpsk8lt2nga.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "pokitmons.pokit",
+ "certificate_hash": "b2f3e34f8e02d15beb0d10d3d48a05148e943642"
+ }
+ },
+ {
+ "client_id": "217769178527-tslgsrrr1o8bli4hr4qnas2u9kg80a9h.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyDMh93QvJGUUX8-E-wyJoSS3cFrwfw8Q3w"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "217769178527-l4prj2q9qsuvkodc2cpi84psvul5rth2.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "217769178527-021j3dpbues9rhbkp6cffnn19mdajorq.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.pokitmons.pokit.App"
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 03a2ac03..352408fa 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,7 +5,8 @@
().configureEach {
+ useJUnitPlatform()
+ }
+
namespace = "pokitmons.pokit.data"
compileSdk = 34
@@ -38,6 +45,26 @@ dependencies {
implementation(libs.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
+ testImplementation(project(":feature:login"))
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
+
+ // kotest
+ testImplementation(libs.kotest.runner.junit5)
+ testImplementation(libs.kotlin.reflect)
+
+ // hilt
+ implementation(libs.hilt)
+ kapt(libs.hilt.compiler)
+
+ // serialization
+ implementation(libs.kotlinx.serialization.json)
+
+ // retrofit
+ implementation(libs.retrofit)
+ implementation(libs.retrofit.converter.serialization)
+ implementation(libs.okhttp)
+ implementation(libs.logging.interceptor)
+
+ implementation(project(":domain"))
}
diff --git a/data/src/main/java/pokitmons/pokit/data/api/AuthApi.kt b/data/src/main/java/pokitmons/pokit/data/api/AuthApi.kt
new file mode 100644
index 00000000..22fec397
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/api/AuthApi.kt
@@ -0,0 +1,21 @@
+package pokitmons.pokit.data.api
+
+import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
+import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
+import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.POST
+import retrofit2.http.Path
+
+interface AuthApi {
+ @POST("auth/signin")
+ suspend fun snsLogin(
+ @Body snsLoginRequest: SNSLoginRequest,
+ ): SNSLoginResponse
+
+ @GET("user/duplicate/{nickname}")
+ suspend fun checkDuplicateNickname(
+ @Path(value = "nickname") nickname: String,
+ ): DuplicateNicknameResponse
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/AuthDataSource.kt b/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/AuthDataSource.kt
new file mode 100644
index 00000000..28f411c4
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/AuthDataSource.kt
@@ -0,0 +1,11 @@
+package pokitmons.pokit.data.datasource.remote.auth
+
+import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
+import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
+import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
+
+interface AuthDataSource {
+// suspend fun signUp(signUpRequest: SignUpRequest): PokitResponse
+ suspend fun snsLogin(snsLoginRequest: SNSLoginRequest): SNSLoginResponse
+ suspend fun checkDuplicateNickname(nickname: String): DuplicateNicknameResponse
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/RemoteAuthDataSourceImpl.kt b/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/RemoteAuthDataSourceImpl.kt
new file mode 100644
index 00000000..7b1c521e
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/datasource/remote/auth/RemoteAuthDataSourceImpl.kt
@@ -0,0 +1,17 @@
+package pokitmons.pokit.data.datasource.remote.auth
+
+import pokitmons.pokit.data.api.AuthApi
+import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
+import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
+import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
+import javax.inject.Inject
+
+class RemoteAuthDataSourceImpl @Inject constructor(private val authApi: AuthApi) : AuthDataSource {
+ override suspend fun snsLogin(snsLoginRequest: SNSLoginRequest): SNSLoginResponse {
+ return authApi.snsLogin(snsLoginRequest)
+ }
+
+ override suspend fun checkDuplicateNickname(nickname: String): DuplicateNicknameResponse {
+ return authApi.checkDuplicateNickname(nickname)
+ }
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/di/auth/AuthModule.kt b/data/src/main/java/pokitmons/pokit/data/di/auth/AuthModule.kt
new file mode 100644
index 00000000..62a641bf
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/di/auth/AuthModule.kt
@@ -0,0 +1,23 @@
+package pokitmons.pokit.data.di.auth
+
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import pokitmons.pokit.data.datasource.remote.auth.AuthDataSource
+import pokitmons.pokit.data.datasource.remote.auth.RemoteAuthDataSourceImpl
+import pokitmons.pokit.data.repository.auth.AuthRepositoryImpl
+import pokitmons.pokit.domain.repository.auth.AuthRepository
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+abstract class AuthModule {
+ @Binds
+ @Singleton
+ abstract fun bindAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository
+
+ @Binds
+ @Singleton
+ abstract fun bindAuthDataSource(authDataSourceImpl: RemoteAuthDataSourceImpl): AuthDataSource
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/di/network/BearerTokenInterceptor.kt b/data/src/main/java/pokitmons/pokit/data/di/network/BearerTokenInterceptor.kt
new file mode 100644
index 00000000..769fc857
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/di/network/BearerTokenInterceptor.kt
@@ -0,0 +1,23 @@
+package pokitmons.pokit.data.di.network
+
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+import java.io.IOException
+
+// 토큰 api 수정될 때 까지 사용
+class BearerTokenInterceptor : Interceptor {
+ @Throws(IOException::class)
+ override fun intercept(chain: Interceptor.Chain): Response {
+ val originalRequest: Request = chain.request()
+ val requestWithToken: Request = originalRequest.newBuilder()
+ .header(
+ "Authorization",
+ "Bearer eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzIxNjU4MjUxLCJleHAiOj" +
+ "MwMDE3MjE2NTgyNTF9.gw6LZimKLuZJ2y0UV5cgvk3F7o92pkRIDgx-qlD_S7qEI01QAFt9dZDyHADabftI"
+ )
+ .build()
+
+ return chain.proceed(requestWithToken)
+ }
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/di/network/NetworkModule.kt b/data/src/main/java/pokitmons/pokit/data/di/network/NetworkModule.kt
new file mode 100644
index 00000000..5d5371cf
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/di/network/NetworkModule.kt
@@ -0,0 +1,70 @@
+package pokitmons.pokit.data.di.network
+
+import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import kotlinx.serialization.json.Json
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import pokitmons.pokit.data.api.AuthApi
+import retrofit2.Retrofit
+import java.util.concurrent.TimeUnit
+import javax.inject.Singleton
+
+private const val BASE_URL = "https://pokit.site"
+private const val API = "api"
+private const val VERSION = "v1"
+
+private const val READ_TIME_OUT = 20000L
+private const val WRITE_TIME_OUT = 20000L
+
+@Module
+@InstallIn(SingletonComponent::class)
+object NetworkModule {
+ @Singleton
+ @Provides
+ fun provideOkHttpClient(): OkHttpClient {
+ return OkHttpClient.Builder()
+ .addInterceptor(BearerTokenInterceptor())
+ .addInterceptor(
+ HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ }
+ )
+ .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
+ .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)
+ .build()
+ }
+
+ @Singleton
+ @Provides
+ fun provideJson(): Json {
+ return Json {
+ ignoreUnknownKeys = true
+ coerceInputValues = true
+ prettyPrint = true
+ }
+ }
+
+ @Singleton
+ @Provides
+ fun provideRetrofit(
+ okHttpClient: OkHttpClient,
+ json: Json,
+ ): Retrofit {
+ val converterFactory = json.asConverterFactory("application/json; charset=UTF8".toMediaType())
+ return Retrofit.Builder()
+ .baseUrl("$BASE_URL/$API/$VERSION/")
+ .addConverterFactory(converterFactory)
+ .client(okHttpClient)
+ .build()
+ }
+
+ @Provides
+ fun provideAuthService(retrofit: Retrofit): AuthApi {
+ return retrofit.create(AuthApi::class.java)
+ }
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt b/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt
new file mode 100644
index 00000000..6168b2d5
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt
@@ -0,0 +1,21 @@
+package pokitmons.pokit.data.mapper.auth
+
+import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
+import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
+import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult
+import pokitmons.pokit.domain.model.auth.SNSLoginResult
+
+object AuthMapper {
+ fun mapperToSNSLogin(snsLoginResponse: SNSLoginResponse): SNSLoginResult {
+ return SNSLoginResult(
+ accessToken = snsLoginResponse.accessToken,
+ refreshToken = snsLoginResponse.refreshToken
+ )
+ }
+
+ fun mapperToDuplicateNickname(checkDuplicateNicknameResponse: DuplicateNicknameResponse): DuplicateNicknameResult {
+ return DuplicateNicknameResult(
+ isDuplicate = checkDuplicateNicknameResponse.isDuplicate
+ )
+ }
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/request/SNSLoginRequest.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/request/SNSLoginRequest.kt
new file mode 100644
index 00000000..e52e5e4a
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/auth/request/SNSLoginRequest.kt
@@ -0,0 +1,9 @@
+package pokitmons.pokit.data.model.auth.request
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SNSLoginRequest(
+ val authPlatform: String,
+ val idToken: String,
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/request/SignUpRequest.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/request/SignUpRequest.kt
new file mode 100644
index 00000000..016884a8
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/auth/request/SignUpRequest.kt
@@ -0,0 +1,6 @@
+package pokitmons.pokit.data.model.auth.request
+
+data class SignUpRequest(
+ val nickname: String,
+ val interests: List,
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/response/DuplicateNicknameResponse.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/response/DuplicateNicknameResponse.kt
new file mode 100644
index 00000000..3638dda8
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/auth/response/DuplicateNicknameResponse.kt
@@ -0,0 +1,8 @@
+package pokitmons.pokit.data.model.auth.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class DuplicateNicknameResponse(
+ val isDuplicate: Boolean,
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt
new file mode 100644
index 00000000..64d57407
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt
@@ -0,0 +1,9 @@
+package pokitmons.pokit.data.model.auth.response
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SNSLoginResponse(
+ val accessToken: String,
+ val refreshToken: String,
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/response/SignUpResponse.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SignUpResponse.kt
new file mode 100644
index 00000000..f98bdc98
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SignUpResponse.kt
@@ -0,0 +1,5 @@
+package pokitmons.pokit.data.model.auth.response
+
+data class SignUpResponse(
+ val userId: Int,
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/model/common/ParseErrorResult.kt b/data/src/main/java/pokitmons/pokit/data/model/common/ParseErrorResult.kt
new file mode 100644
index 00000000..878e1220
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/common/ParseErrorResult.kt
@@ -0,0 +1,18 @@
+package pokitmons.pokit.data.model.common
+
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import pokitmons.pokit.domain.commom.PokitError
+import pokitmons.pokit.domain.commom.PokitResult
+
+fun parseErrorResult(throwable: Throwable): PokitResult {
+ return try {
+ val error: PokitErrorResponse = throwable.message?.let { errorBody ->
+ Json.decodeFromString(errorBody)
+ } ?: PokitErrorResponse()
+ val pokitError = PokitError(message = error.message, code = error.code)
+ PokitResult.Error(pokitError)
+ } catch (e: Exception) {
+ PokitResult.Error(PokitError())
+ }
+}
diff --git a/data/src/main/java/pokitmons/pokit/data/model/common/PokitErrorResponse.kt b/data/src/main/java/pokitmons/pokit/data/model/common/PokitErrorResponse.kt
new file mode 100644
index 00000000..93f89d8c
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/model/common/PokitErrorResponse.kt
@@ -0,0 +1,9 @@
+package pokitmons.pokit.data.model.common
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class PokitErrorResponse(
+ val message: String = "그 외",
+ val code: String = "U_0000",
+)
diff --git a/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt b/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt
new file mode 100644
index 00000000..ff31557f
--- /dev/null
+++ b/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt
@@ -0,0 +1,41 @@
+package pokitmons.pokit.data.repository.auth
+
+import pokitmons.pokit.data.datasource.remote.auth.AuthDataSource
+import pokitmons.pokit.data.mapper.auth.AuthMapper
+import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
+import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
+import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
+import pokitmons.pokit.data.model.common.parseErrorResult
+import pokitmons.pokit.domain.commom.PokitResult
+import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult
+import pokitmons.pokit.domain.model.auth.SNSLoginResult
+import pokitmons.pokit.domain.repository.auth.AuthRepository
+import javax.inject.Inject
+
+// TODO getOrElse 반복되는 로직 함수화
+class AuthRepositoryImpl @Inject constructor(
+ private val remoteAuthDataSource: AuthDataSource,
+) : AuthRepository {
+ override suspend fun snsLogin(
+ authPlatform: String,
+ idToken: String,
+ ): PokitResult {
+ return runCatching {
+ val snsLoginResponse: SNSLoginResponse = remoteAuthDataSource.snsLogin(SNSLoginRequest(authPlatform = authPlatform, idToken = idToken))
+ val snsLoginMapper = AuthMapper.mapperToSNSLogin(snsLoginResponse)
+ PokitResult.Success(snsLoginMapper)
+ }.getOrElse { throwable ->
+ parseErrorResult(throwable)
+ }
+ }
+
+ override suspend fun checkDuplicateNickname(nickname: String): PokitResult {
+ return runCatching {
+ val checkDuplicateNicknameResponse: DuplicateNicknameResponse = remoteAuthDataSource.checkDuplicateNickname(nickname)
+ val checkDuplicateMapper = AuthMapper.mapperToDuplicateNickname(checkDuplicateNicknameResponse)
+ PokitResult.Success(checkDuplicateMapper)
+ }.getOrElse { throwable ->
+ parseErrorResult(throwable)
+ }
+ }
+}
diff --git a/data/src/test/java/pokitmons/pokit/data/ExampleUnitTest.kt b/data/src/test/java/pokitmons/pokit/data/ExampleUnitTest.kt
deleted file mode 100644
index c174d0bd..00000000
--- a/data/src/test/java/pokitmons/pokit/data/ExampleUnitTest.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package pokitmons.pokit.data
-
-import junit.framework.TestCase.assertEquals
-import org.junit.Test
-
-/**
- * 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)
- }
-}
diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts
index a64717b1..9f63a980 100644
--- a/domain/build.gradle.kts
+++ b/domain/build.gradle.kts
@@ -7,3 +7,7 @@ java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
+
+dependencies {
+ implementation(libs.javax.inject)
+}
diff --git a/domain/src/main/java/pokitmons/pokit/domain/MyClass.kt b/domain/src/main/java/pokitmons/pokit/domain/MyClass.kt
deleted file mode 100644
index 3a2d8c51..00000000
--- a/domain/src/main/java/pokitmons/pokit/domain/MyClass.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package pokitmons.pokit.domain
-
-class MyClass
diff --git a/domain/src/main/java/pokitmons/pokit/domain/commom/PokitError.kt b/domain/src/main/java/pokitmons/pokit/domain/commom/PokitError.kt
new file mode 100644
index 00000000..79e9632e
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/commom/PokitError.kt
@@ -0,0 +1,6 @@
+package pokitmons.pokit.domain.commom
+
+data class PokitError(
+ val message: String = "그 외",
+ val code: String = "U_0000",
+)
diff --git a/domain/src/main/java/pokitmons/pokit/domain/commom/PokitResult.kt b/domain/src/main/java/pokitmons/pokit/domain/commom/PokitResult.kt
new file mode 100644
index 00000000..25ea983a
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/commom/PokitResult.kt
@@ -0,0 +1,6 @@
+package pokitmons.pokit.domain.commom
+
+sealed interface PokitResult {
+ data class Success(val result: T) : PokitResult
+ data class Error(val error: PokitError) : PokitResult
+}
diff --git a/domain/src/main/java/pokitmons/pokit/domain/model/auth/DuplicateNicknameResult.kt b/domain/src/main/java/pokitmons/pokit/domain/model/auth/DuplicateNicknameResult.kt
new file mode 100644
index 00000000..34c8618c
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/model/auth/DuplicateNicknameResult.kt
@@ -0,0 +1,5 @@
+package pokitmons.pokit.domain.model.auth
+
+data class DuplicateNicknameResult(
+ val isDuplicate: Boolean,
+)
diff --git a/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt b/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt
new file mode 100644
index 00000000..79bd155a
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt
@@ -0,0 +1,6 @@
+package pokitmons.pokit.domain.model.auth
+
+data class SNSLoginResult(
+ val accessToken: String,
+ val refreshToken: String,
+)
diff --git a/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt b/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt
new file mode 100644
index 00000000..f50578d8
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt
@@ -0,0 +1,14 @@
+package pokitmons.pokit.domain.repository.auth
+
+import pokitmons.pokit.domain.commom.PokitResult
+import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult
+import pokitmons.pokit.domain.model.auth.SNSLoginResult
+
+interface AuthRepository {
+ suspend fun snsLogin(
+ authPlatform: String,
+ idToken: String,
+ ): PokitResult
+
+ suspend fun checkDuplicateNickname(nickname: String): PokitResult
+}
diff --git a/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/InputNicknameUseCase.kt b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/InputNicknameUseCase.kt
new file mode 100644
index 00000000..15881f7f
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/InputNicknameUseCase.kt
@@ -0,0 +1,15 @@
+package pokitmons.pokit.domain.usecase.auth
+
+import pokitmons.pokit.domain.commom.PokitResult
+import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult
+import pokitmons.pokit.domain.repository.auth.AuthRepository
+import javax.inject.Inject
+
+class InputNicknameUseCase @Inject constructor(private val authRepository: AuthRepository) {
+ suspend fun checkDuplicateNickname(nickname: String): PokitResult {
+ return when (val duplicateResult = authRepository.checkDuplicateNickname(nickname)) {
+ is PokitResult.Success -> PokitResult.Success(duplicateResult.result)
+ is PokitResult.Error -> PokitResult.Error(duplicateResult.error)
+ }
+ }
+}
diff --git a/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SNSLoginUseCase.kt b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SNSLoginUseCase.kt
new file mode 100644
index 00000000..b16da180
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SNSLoginUseCase.kt
@@ -0,0 +1,15 @@
+package pokitmons.pokit.domain.usecase.auth
+
+import pokitmons.pokit.domain.commom.PokitResult
+import pokitmons.pokit.domain.model.auth.SNSLoginResult
+import pokitmons.pokit.domain.repository.auth.AuthRepository
+import javax.inject.Inject
+
+class SNSLoginUseCase @Inject constructor(private val authRepository: AuthRepository) {
+ suspend fun snsLogin(authPlatform: String, idToken: String): PokitResult {
+ return when (val loginResult = authRepository.snsLogin(authPlatform, idToken)) {
+ is PokitResult.Success -> PokitResult.Success(loginResult.result)
+ is PokitResult.Error -> PokitResult.Error(loginResult.error)
+ }
+ }
+}
diff --git a/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SignUpUseCase.kt b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SignUpUseCase.kt
new file mode 100644
index 00000000..029c6c3f
--- /dev/null
+++ b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/SignUpUseCase.kt
@@ -0,0 +1,3 @@
+package pokitmons.pokit.domain.usecase.auth
+
+class SignUpUseCase
diff --git a/feature/login/build.gradle.kts b/feature/login/build.gradle.kts
index 4188ee20..6ec95ebb 100644
--- a/feature/login/build.gradle.kts
+++ b/feature/login/build.gradle.kts
@@ -4,6 +4,8 @@ import java.util.Properties
plugins {
alias(libs.plugins.com.android.library)
alias(libs.plugins.org.jetbrains.kotlin.android)
+ alias(libs.plugins.hilt)
+ id("kotlin-kapt")
}
val properties = Properties()
@@ -79,9 +81,24 @@ dependencies {
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
+ // google login
implementation(libs.androidx.credentials)
implementation(libs.androidx.credentials.play.services.auth)
implementation(libs.googleid)
+ // hilt
+ implementation(libs.hilt)
+ kapt(libs.hilt.compiler)
+
+ // navigation
+ implementation(libs.androidx.navigation.compose)
+ implementation(libs.hilt.navigation.compose)
+
+ // firebase
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.auth.ktx)
+
+ // module
implementation(project(":core:ui"))
+ implementation(project(":domain"))
}
diff --git a/feature/login/src/main/java/pokitmons/pokit/LoginState.kt b/feature/login/src/main/java/pokitmons/pokit/LoginState.kt
new file mode 100644
index 00000000..687af968
--- /dev/null
+++ b/feature/login/src/main/java/pokitmons/pokit/LoginState.kt
@@ -0,0 +1,9 @@
+package pokitmons.pokit
+
+import pokitmons.pokit.domain.commom.PokitError
+
+sealed class LoginState {
+ data object Init : LoginState()
+ data object Login : LoginState()
+ data class Failed(val error: PokitError) : LoginState()
+}
diff --git a/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt b/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt
new file mode 100644
index 00000000..581c9681
--- /dev/null
+++ b/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt
@@ -0,0 +1,78 @@
+package pokitmons.pokit
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import pokitmons.pokit.domain.commom.PokitResult
+import pokitmons.pokit.domain.usecase.auth.SNSLoginUseCase
+import javax.inject.Inject
+
+@HiltViewModel
+class LoginViewModel @Inject constructor(
+ private val loginUseCase: SNSLoginUseCase,
+) : ViewModel() {
+
+ private var apiRequestJob: Job? = null
+
+ private val _loginState: MutableStateFlow = MutableStateFlow(LoginState.Init)
+ val loginState: StateFlow
+ get() = _loginState.asStateFlow()
+
+ private val _inputNicknameState = MutableStateFlow("")
+ val inputNicknameState: StateFlow
+ get() = _inputNicknameState.asStateFlow()
+
+ fun inputText(text: String) {
+ _inputNicknameState.value = text
+ }
+
+ fun snsLogin(authPlatform: String, idToken: String) {
+ viewModelScope.launch {
+ val loginResult = loginUseCase.snsLogin(
+ authPlatform = authPlatform,
+ idToken = idToken
+ )
+
+ when (loginResult) {
+ is PokitResult.Success -> {
+ accessToken = loginResult.result.accessToken
+ refreshToken = loginResult.result.refreshToken
+ _loginState.emit(LoginState.Login)
+ }
+ is PokitResult.Error -> _loginState.emit(LoginState.Failed(loginResult.error))
+ }
+ }
+ }
+
+ fun checkDuplicateNickname(nickname: String) {
+ apiRequestJob?.cancel()
+ apiRequestJob = viewModelScope.launch {
+ delay(1.second())
+ // TOOD api 연동
+ }
+ }
+
+ val categories: ArrayList = arrayListOf()
+
+ var accessToken: String = ""
+ private set
+
+ var refreshToken: String = ""
+ private set
+
+ var nickname: String = ""
+ private set
+
+ // TODO 확장함수 모듈 생성하기
+ companion object {
+ private fun Int.second(): Long {
+ return (this * 1000L)
+ }
+ }
+}
diff --git a/feature/login/src/main/java/pokitmons/pokit/keyword/KeywordScreen.kt b/feature/login/src/main/java/pokitmons/pokit/keyword/KeywordScreen.kt
index 3a8f2731..2f3e410f 100644
--- a/feature/login/src/main/java/pokitmons/pokit/keyword/KeywordScreen.kt
+++ b/feature/login/src/main/java/pokitmons/pokit/keyword/KeywordScreen.kt
@@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
+import pokitmons.pokit.LoginViewModel
import pokitmons.pokit.core.ui.components.atom.button.PokitButton
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonSize
import pokitmons.pokit.core.ui.components.atom.chip.PokitChip
@@ -26,6 +27,7 @@ import pokitmons.pokit.login.R as Login
@Composable
fun KeywordScreen(
+ loginViewModel: LoginViewModel,
onNavigateToSignUpScreen: () -> Unit,
popBackStack: () -> Unit,
) {
diff --git a/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt b/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt
index f869ed43..88213c07 100644
--- a/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt
+++ b/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt
@@ -1,7 +1,8 @@
package pokitmons.pokit.login
-import android.annotation.SuppressLint
-import android.util.Log
+import android.app.Activity
+import android.content.Context
+import android.widget.Toast
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -9,6 +10,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -19,16 +22,34 @@ import androidx.credentials.CredentialManager
import androidx.credentials.GetCredentialRequest
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
+import com.google.firebase.auth.AuthResult
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.auth.OAuthProvider
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
+import pokitmons.pokit.LoginState
+import pokitmons.pokit.LoginViewModel
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitLoginButtonType
import pokitmons.pokit.core.ui.components.atom.loginbutton.PokitLoginButton
@Composable
fun LoginScreen(
+ loginViewModel: LoginViewModel,
onNavigateToTermsOfServiceScreen: () -> Unit,
- onNavigateToMainScreen: () -> Unit,
) {
- // TODO 서버 api 개발완료 후 viewmodel 연동 및 아키텍처 구축
+ val loginState by loginViewModel.loginState.collectAsState()
+ val context: Context = LocalContext.current
+ val coroutineScope = rememberCoroutineScope()
+
+ when (loginState) {
+ is LoginState.Init -> Unit
+ is LoginState.Login -> onNavigateToTermsOfServiceScreen()
+ is LoginState.Failed -> {
+ // TODO 로그인 실패 바텀시트 렌더링
+ Toast.makeText(context, (loginState as LoginState.Failed).error.toString(), Toast.LENGTH_SHORT).show()
+ }
+ }
+
Box(
modifier = Modifier
.fillMaxSize()
@@ -41,7 +62,12 @@ fun LoginScreen(
PokitLoginButton(
loginType = PokitLoginButtonType.APPLE,
text = stringResource(id = R.string.apple_login),
- onClick = { onNavigateToMainScreen() }
+ onClick = {
+ appleLogin(
+ context = context,
+ snsLogin = loginViewModel::snsLogin
+ )
+ }
)
Spacer(modifier = Modifier.height(8.dp))
@@ -49,18 +75,24 @@ fun LoginScreen(
PokitLoginButton(
loginType = PokitLoginButtonType.GOOGLE,
text = stringResource(id = R.string.google_login),
- onClick = { onNavigateToTermsOfServiceScreen() }
+ onClick = {
+// onNavigateToTermsOfServiceScreen()
+ googleLogin(
+ snsLogin = loginViewModel::snsLogin,
+ coroutineScope = coroutineScope,
+ context = context
+ )
+ }
)
}
}
}
-@SuppressLint("CoroutineCreationDuringComposition")
-@Composable
-private fun googleLogin() {
- val coroutineScope = rememberCoroutineScope()
-
- val context = LocalContext.current
+private fun googleLogin(
+ snsLogin: (String, String) -> Unit,
+ coroutineScope: CoroutineScope,
+ context: Context,
+) {
val credentialManager = CredentialManager.create(context)
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
@@ -81,9 +113,54 @@ private fun googleLogin() {
)
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(result.credential.data)
val googleIdToken = googleIdTokenCredential.idToken
- Log.d("success: ", googleIdToken)
+ snsLogin("구글", googleIdToken)
} catch (e: Exception) {
- Log.d("failed : ", e.message.toString())
+ // TODO 로그인 실패 바텀시트 렌더링
+ }
+ }
+}
+
+private fun appleLogin(
+ context: Context,
+ snsLogin: (String, String) -> Unit,
+) {
+ val provider = OAuthProvider.newBuilder("apple.com").apply {
+ addCustomParameter("locale", "ko")
+ }
+
+ // 이미 응답을 수신 했는지 확인
+ val auth = FirebaseAuth.getInstance()
+ val pending = auth.pendingAuthResult
+ if (pending != null) {
+ pending.addOnSuccessListener { authResult ->
+ handleAuthResult(authResult, snsLogin)
+ }.addOnFailureListener { e ->
+ // TODO 로그인 실패 바텀시트 렌더링
+ }
+ } else {
+ auth.startActivityForSignInWithProvider(context as Activity, provider.build()).addOnSuccessListener { authResult ->
+ handleAuthResult(authResult, snsLogin)
+ }.addOnFailureListener {
+ // TODO 로그인 실패 바텀시트 렌더링
+ }
+ }
+}
+
+private fun handleAuthResult(
+ authResult: AuthResult,
+ snsLogin: (String, String) -> Unit,
+) {
+ val user = authResult.user
+ user?.getIdToken(true)?.addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ val idToken = task.result?.token
+ if (idToken != null) {
+ snsLogin("애플", idToken)
+ } else {
+ // TODO 로그인 실패 바텀시트 렌더링
+ }
+ } else {
+ // TODO 로그인 실패 바텀시트 렌더링
}
}
}
diff --git a/feature/login/src/main/java/pokitmons/pokit/navigation/LoginNavHost.kt b/feature/login/src/main/java/pokitmons/pokit/navigation/LoginNavHost.kt
index a6285297..41a77322 100644
--- a/feature/login/src/main/java/pokitmons/pokit/navigation/LoginNavHost.kt
+++ b/feature/login/src/main/java/pokitmons/pokit/navigation/LoginNavHost.kt
@@ -1,9 +1,11 @@
package pokitmons.pokit.navigation
import androidx.compose.runtime.Composable
+import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
+import pokitmons.pokit.LoginViewModel
import pokitmons.pokit.keyword.KeywordScreen
import pokitmons.pokit.login.LoginScreen
import pokitmons.pokit.nickname.InputNicknameScreen
@@ -13,14 +15,15 @@ import pokitmons.pokit.terms.TermsOfServiceScreen
@Composable
fun LoginNavHost() {
val navController = rememberNavController()
+ val loginViewModel: LoginViewModel = hiltViewModel()
NavHost(
navController = navController,
startDestination = LoginRoute.LoginScreen.name
) {
composable(route = LoginRoute.LoginScreen.name) {
LoginScreen(
- onNavigateToTermsOfServiceScreen = { navController.navigate(route = LoginRoute.TermsOfServiceScreen.name) },
- onNavigateToMainScreen = { } // TODO 메인 화면 구현후 수정
+ loginViewModel = loginViewModel,
+ onNavigateToTermsOfServiceScreen = { navController.navigate(route = LoginRoute.TermsOfServiceScreen.name) }
)
}
@@ -33,6 +36,7 @@ fun LoginNavHost() {
composable(route = LoginRoute.InputNicknameScreen.name) {
InputNicknameScreen(
+ loginViewModel = loginViewModel,
onNavigateToKeywordScreen = { navController.navigate(route = LoginRoute.KeywordScreen.name) },
popBackStack = { navController.popBackStack() }
)
@@ -40,6 +44,7 @@ fun LoginNavHost() {
composable(route = LoginRoute.KeywordScreen.name) {
KeywordScreen(
+ loginViewModel = loginViewModel,
onNavigateToSignUpScreen = { navController.navigate(route = LoginRoute.SignUpSuccessScreen.name) },
popBackStack = { navController.popBackStack() }
)
@@ -47,6 +52,7 @@ fun LoginNavHost() {
composable(route = LoginRoute.SignUpSuccessScreen.name) {
SignUpSuccessScreen(
+ loginViewModel = loginViewModel,
onNavigateToMainScreen = { } // TODO 메인 화면 구현후 수정
)
}
diff --git a/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameScreen.kt b/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameScreen.kt
index 0ae25982..eba8de5c 100644
--- a/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameScreen.kt
+++ b/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameScreen.kt
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
@@ -18,7 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
-import androidx.lifecycle.viewmodel.compose.viewModel
+import pokitmons.pokit.LoginViewModel
import pokitmons.pokit.core.ui.components.atom.button.PokitButton
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonSize
import pokitmons.pokit.core.ui.components.block.labeledinput.LabeledInput
@@ -31,33 +32,31 @@ private const val NICKNAME_MIN_LENGTH = 1 // TODO 매직넘버를 포함하는
@Composable
fun InputNicknameScreen(
+ loginViewModel: LoginViewModel,
onNavigateToKeywordScreen: () -> Unit,
popBackStack: () -> Unit,
) {
- val inputNicknameViewModel: InputNicknameViewModel = viewModel() // TODO hiltViewModel 마이그레이션 예정
- val inputNicknameState by inputNicknameViewModel.inputNicknameState.collectAsState()
+ val inputNicknameState by loginViewModel.inputNicknameState.collectAsState()
Box(
modifier = Modifier
.padding(start = 20.dp, end = 20.dp, top = 20.dp, bottom = 28.dp)
.fillMaxSize()
) {
- Column() {
+ Column {
Icon(
modifier = Modifier.clickable { popBackStack() },
painter = painterResource(id = UI.drawable.icon_24_arrow_left),
contentDescription = "뒤로가기"
)
- Spacer(modifier = Modifier.padding(top = 32.dp))
+ Spacer(modifier = Modifier.height(32.dp))
Text(
style = PokitTheme.typography.title1,
text = stringResource(id = Login.string.input_nickname_title)
)
- Spacer(modifier = Modifier.padding(top = 28.dp))
-
LabeledInput(
modifier = Modifier
.fillMaxWidth()
@@ -74,7 +73,7 @@ fun InputNicknameScreen(
hintText = stringResource(id = Login.string.input_nickname_hint),
onChangeText = { text ->
if (text.length <= NICKNAME_MAX_LENGTH) {
- inputNicknameViewModel.inputText(text)
+ loginViewModel.inputText(text)
}
}
)
diff --git a/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameViewModel.kt b/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameViewModel.kt
deleted file mode 100644
index 0b7678e8..00000000
--- a/feature/login/src/main/java/pokitmons/pokit/nickname/InputNicknameViewModel.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package pokitmons.pokit.nickname
-
-import androidx.lifecycle.ViewModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-class InputNicknameViewModel : ViewModel() {
- private val _inputNicknameState = MutableStateFlow("")
- val inputNicknameState: StateFlow
- get() = _inputNicknameState
-
- fun inputText(text: String) {
- _inputNicknameState.value = text
- }
-}
diff --git a/feature/login/src/main/java/pokitmons/pokit/success/SignUpSuccessScreen.kt b/feature/login/src/main/java/pokitmons/pokit/success/SignUpSuccessScreen.kt
index dd195ddc..ff530988 100644
--- a/feature/login/src/main/java/pokitmons/pokit/success/SignUpSuccessScreen.kt
+++ b/feature/login/src/main/java/pokitmons/pokit/success/SignUpSuccessScreen.kt
@@ -19,6 +19,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
+import pokitmons.pokit.LoginViewModel
import pokitmons.pokit.core.ui.components.atom.button.PokitButton
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonSize
import pokitmons.pokit.core.ui.theme.PokitTheme
@@ -26,6 +27,7 @@ import pokitmons.pokit.login.R
@Composable
fun SignUpSuccessScreen(
+ loginViewModel: LoginViewModel,
onNavigateToMainScreen: () -> Unit,
) {
Box(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ef8751e5..7e65bb1e 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,9 @@
[versions]
agp = "8.3.2"
+javax-inject = "1"
+kotest-runner-junit5 = "5.9.1"
+kotlin-reflect = "1.9.23"
+logging-interceptor = "4.11.0"
org-jetbrains-kotlin-android = "1.9.0"
core-ktx = "1.13.1"
junit = "4.13.2"
@@ -22,11 +26,15 @@ annotation = "1.8.0"
ktlint = "11.3.2"
androidx-credentials = "1.2.2"
androidx-credentials-play-services-auth = "1.2.2"
-googleid = "1.1.0"
+googleid = "1.1.1"
+firebase-bom = "33.1.2"
+firebase-auth = "23.0.0"
+google-services = "4.4.2"
[libraries]
androidx-lifecycle-service = { group = "androidx.lifecycle", name = "lifecycle-service", version.ref = "lifecycle-runtime-ktx"}
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
+javax-inject = { module = "javax.inject:javax.inject", version.ref = "javax-inject" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
@@ -44,9 +52,12 @@ androidx-navigation-compose = { group = "androidx.navigation", name = "navigatio
androidx-credentials = { module = "androidx.credentials:credentials", version.ref = "androidx-credentials" }
androidx-credentials-play-services-auth = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "androidx-credentials-play-services-auth" }
googleid = { module = "com.google.android.libraries.identity.googleid:googleid", version.ref = "googleid" }
-
-
+firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
+firebase-auth-ktx = { module = "com.google.firebase:firebase-auth-ktx", version.ref = "firebase-auth" }
datastore = { module = "androidx.datastore:datastore-preferences", version = "1.1.1" }
+kotest-runner-junit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest-runner-junit5" }
+kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin-reflect" }
+logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "logging-interceptor" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-converter-serialization = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version = "1.0.0"}
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version = "4.12.0"}
@@ -84,6 +95,7 @@ kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "org-jetbrains-k
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "org-jetbrains-kotlin-android"}
com-android-dynamic-feature = { id = "com.android.dynamic-feature", version.ref = "agp" }
ktlint-gradle = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
+googleServices = { id = "com.google.gms.google-services", version.ref = "google-services" }