diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index c9353ed6..8ca125d6 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -27,7 +27,7 @@
-
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 5afd8a76..3a48b45a 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -3,6 +3,7 @@ plugins {
id("com.wap.wapp.firebase")
id("com.wap.wapp.compose")
id("com.wap.wapp.hilt")
+ id("com.wap.wapp.navigation")
}
android {
diff --git a/app/src/main/java/com/wap/wapp/MainActivity.kt b/app/src/main/java/com/wap/wapp/MainActivity.kt
index 377a3485..07324139 100644
--- a/app/src/main/java/com/wap/wapp/MainActivity.kt
+++ b/app/src/main/java/com/wap/wapp/MainActivity.kt
@@ -1,8 +1,6 @@
package com.wap.wapp
import android.os.Bundle
-import android.util.Log
-import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.navigation.NavController
@@ -39,7 +37,7 @@ class MainActivity : AppCompatActivity() {
val typedArray = resources.obtainTypedArray(R.array.hide_bottomNavigation_fragments)
for (index in 0..typedArray.length()) {
- hideBottomNavigationFragments.add(typedArray.getResourceId(index, 0,))
+ hideBottomNavigationFragments.add(typedArray.getResourceId(index, 0))
}
typedArray.recycle()
diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml
index 165becc3..3640d92b 100644
--- a/app/src/main/res/navigation/nav_main.xml
+++ b/app/src/main/res/navigation/nav_main.xml
@@ -4,6 +4,7 @@
android:id="@+id/main_nav"
app:startDestination="@id/nav_splash">
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index b99edf07..5d93a1ca 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -2,5 +2,7 @@
- @id/splashFragment
+ - @id/signInFragment
+ - @id/signUpFragment
diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts
index d544c6a7..c83f7dc9 100644
--- a/build-logic/convention/build.gradle.kts
+++ b/build-logic/convention/build.gradle.kts
@@ -2,10 +2,6 @@ plugins{
`kotlin-dsl`
}
-kotlin {
- jvmToolchain(17)
-}
-
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
@@ -42,5 +38,9 @@ gradlePlugin {
id = "com.wap.wapp.hilt"
implementationClass = "com.wap.wapp.plugin.AndroidHiltPlugin"
}
+ create("androidNavigation") {
+ id = "com.wap.wapp.navigation"
+ implementationClass = "com.wap.wapp.plugin.AndroidNavigationPlugin"
+ }
}
}
diff --git a/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidFeatureConventionPlugin.kt
index 0351a4eb..afe4669f 100644
--- a/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidFeatureConventionPlugin.kt
+++ b/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidFeatureConventionPlugin.kt
@@ -11,8 +11,9 @@ class AndroidFeatureConventionPlugin: Plugin{
apply("com.wap.wapp.library")
apply("com.wap.wapp.compose")
apply("com.wap.wapp.hilt")
+ apply("com.wap.wapp.navigation")
}
configureBinding()
}
}
-}
\ No newline at end of file
+}
diff --git a/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidNavigationPlugin.kt b/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidNavigationPlugin.kt
new file mode 100644
index 00000000..e201c6e1
--- /dev/null
+++ b/build-logic/convention/src/main/java/com/wap/wapp/plugin/AndroidNavigationPlugin.kt
@@ -0,0 +1,25 @@
+package com.wap.wapp.plugin
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.VersionCatalogsExtension
+import org.gradle.kotlin.dsl.dependencies
+import org.gradle.kotlin.dsl.getByType
+
+class AndroidNavigationPlugin: Plugin {
+ override fun apply(target: Project) {
+ with(target) {
+ with(pluginManager) {
+ apply("androidx.navigation.safeargs")
+ }
+
+ val libs = extensions.getByType().named("libs")
+
+ dependencies{
+ "implementation"(libs.findLibrary("androidx-navigation-fragment-ktx").get())
+ "implementation"(libs.findLibrary("androidx-navigation-ui-ktx").get())
+ "implementation"(libs.findLibrary("androidx-navigation-compose").get())
+ }
+ }
+ }
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 3376c53a..87f25852 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,6 +6,7 @@ buildscript {
dependencies {
classpath(libs.android.build)
classpath(libs.kotlin.gradle)
+ classpath(libs.androidx.navigation.safeargs)
classpath(libs.hilt.gradle)
classpath(libs.google.services.gradle)
classpath(libs.firebase.crashlytics.gradle)
@@ -16,6 +17,7 @@ plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
+ alias(libs.plugins.androidx.navigation.safeargs) apply false
alias(libs.plugins.dagger.hilt) apply false
alias(libs.plugins.google.services) apply false
alias(libs.plugins.firebase.crashlytics) apply false
diff --git a/core/base/.gitignore b/core/common/.gitignore
similarity index 100%
rename from core/base/.gitignore
rename to core/common/.gitignore
diff --git a/core/base/build.gradle.kts b/core/common/build.gradle.kts
similarity index 84%
rename from core/base/build.gradle.kts
rename to core/common/build.gradle.kts
index c1fd5690..b0380e5f 100644
--- a/core/base/build.gradle.kts
+++ b/core/common/build.gradle.kts
@@ -23,6 +23,9 @@ android {
dependencies {
implementation(libs.bundles.androidx)
+ implementation(platform(libs.firebase.bom))
+ implementation(libs.firebase.auth)
+ implementation(libs.firebase.firestore)
implementation(libs.material)
testImplementation(libs.junit)
diff --git a/core/base/consumer-rules.pro b/core/common/consumer-rules.pro
similarity index 100%
rename from core/base/consumer-rules.pro
rename to core/common/consumer-rules.pro
diff --git a/core/base/proguard-rules.pro b/core/common/proguard-rules.pro
similarity index 100%
rename from core/base/proguard-rules.pro
rename to core/common/proguard-rules.pro
diff --git a/core/base/src/androidTest/java/com/wap/wapp/core/base/ExampleInstrumentedTest.kt b/core/common/src/androidTest/java/com/wap/wapp/core/base/ExampleInstrumentedTest.kt
similarity index 100%
rename from core/base/src/androidTest/java/com/wap/wapp/core/base/ExampleInstrumentedTest.kt
rename to core/common/src/androidTest/java/com/wap/wapp/core/base/ExampleInstrumentedTest.kt
diff --git a/core/base/src/main/AndroidManifest.xml b/core/common/src/main/AndroidManifest.xml
similarity index 100%
rename from core/base/src/main/AndroidManifest.xml
rename to core/common/src/main/AndroidManifest.xml
diff --git a/core/base/src/main/java/com/wap/wapp/core/base/BaseFragment.kt b/core/common/src/main/java/com/wap/wapp/core/commmon/base/BaseFragment.kt
similarity index 96%
rename from core/base/src/main/java/com/wap/wapp/core/base/BaseFragment.kt
rename to core/common/src/main/java/com/wap/wapp/core/commmon/base/BaseFragment.kt
index 3f7bd808..941581e1 100644
--- a/core/base/src/main/java/com/wap/wapp/core/base/BaseFragment.kt
+++ b/core/common/src/main/java/com/wap/wapp/core/commmon/base/BaseFragment.kt
@@ -1,4 +1,4 @@
-package com.android.mediproject.core.ui.base
+package com.wap.wapp.core.commmon.base
import android.os.Bundle
import android.util.Log
diff --git a/core/base/src/main/java/com/wap/wapp/core/base/util/RepeatOnLifecycle.kt b/core/common/src/main/java/com/wap/wapp/core/commmon/extensions/CoroutinesExtension.kt
similarity index 90%
rename from core/base/src/main/java/com/wap/wapp/core/base/util/RepeatOnLifecycle.kt
rename to core/common/src/main/java/com/wap/wapp/core/commmon/extensions/CoroutinesExtension.kt
index 1f615a95..0d79ada7 100644
--- a/core/base/src/main/java/com/wap/wapp/core/base/util/RepeatOnLifecycle.kt
+++ b/core/common/src/main/java/com/wap/wapp/core/commmon/extensions/CoroutinesExtension.kt
@@ -1,4 +1,4 @@
-package com.wap.wapp.core.base.util
+package com.wap.wapp.core.commmon.extensions
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
diff --git a/core/common/src/main/java/com/wap/wapp/core/commmon/extensions/ThrowableExtensions.kt b/core/common/src/main/java/com/wap/wapp/core/commmon/extensions/ThrowableExtensions.kt
new file mode 100644
index 00000000..717bf502
--- /dev/null
+++ b/core/common/src/main/java/com/wap/wapp/core/commmon/extensions/ThrowableExtensions.kt
@@ -0,0 +1,47 @@
+package com.wap.wapp.core.commmon.extensions
+
+import com.google.firebase.auth.FirebaseAuthException
+import com.google.firebase.firestore.FirebaseFirestoreException
+import java.net.UnknownHostException
+
+fun Throwable.toSupportingText(): String {
+ return when (this) {
+ is UnknownHostException -> {
+ "네트워크 연결이 원활하지 않습니다."
+ }
+ is FirebaseAuthException -> {
+ this.toSupportingText()
+ }
+ is FirebaseFirestoreException -> {
+ this.toSupportingText()
+ }
+ else -> {
+ "알 수 없는 오류가 발생하였습니다."
+ }
+ }
+}
+
+fun FirebaseAuthException.toSupportingText(): String {
+ return when (this.errorCode) {
+ "ERROR_WEB_CONTEXT_CANCELED", "ERROR_USER_CANCELLED" -> {
+ "다시 시도해 주세요."
+ }
+ else -> {
+ "알 수 없는 오류가 발생하였습니다."
+ }
+ }
+}
+
+fun FirebaseFirestoreException.toSupportingText(): String {
+ return when (this.code.value()) {
+ 7 -> {
+ "접근 권한이 없습니다."
+ }
+ 16 -> {
+ "회원이 만료되었습니다. 다시 로그인 해주세요."
+ }
+ else -> {
+ "알 수 없는 오류가 발생하였습니다."
+ }
+ }
+}
diff --git a/core/base/src/test/java/com/wap/wapp/core/base/ExampleUnitTest.kt b/core/common/src/test/java/com/wap/wapp/core/base/ExampleUnitTest.kt
similarity index 100%
rename from core/base/src/test/java/com/wap/wapp/core/base/ExampleUnitTest.kt
rename to core/common/src/test/java/com/wap/wapp/core/base/ExampleUnitTest.kt
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/di/AuthRepositoryModule.kt b/core/data/src/main/java/com/wap/wapp/core/data/di/AuthRepositoryModule.kt
index 4b8f157e..68331bb2 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/di/AuthRepositoryModule.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/di/AuthRepositoryModule.kt
@@ -13,7 +13,7 @@ import dagger.hilt.android.scopes.ActivityScoped
abstract class AuthRepositoryModule {
@Binds
@ActivityScoped
- abstract fun providesAuthRepository(
+ abstract fun bindsAuthRepository(
authRepositoryImpl: AuthRepositoryImpl,
): AuthRepository
}
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/di/DataModule.kt b/core/data/src/main/java/com/wap/wapp/core/data/di/DataModule.kt
index 2ebbd53d..7191e64a 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/di/DataModule.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/di/DataModule.kt
@@ -13,7 +13,7 @@ import javax.inject.Singleton
abstract class DataModule {
@Binds
@Singleton
- abstract fun providesUserRepository(
+ abstract fun bindsUserRepository(
userRepositoryImpl: UserRepositoryImpl,
): UserRepository
}
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepository.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepository.kt
index f5039061..1c4e3b76 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepository.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepository.kt
@@ -5,6 +5,8 @@ import com.wap.wapp.core.model.user.UserProfile
interface UserRepository {
suspend fun getUserProfile(userId: String): Result
+ suspend fun getUserId(): Result
+
suspend fun postUserProfile(
userId: String,
userName: String,
diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepositoryImpl.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepositoryImpl.kt
index 0490832c..efa25af4 100644
--- a/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepositoryImpl.kt
+++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/user/UserRepositoryImpl.kt
@@ -14,6 +14,10 @@ class UserRepositoryImpl @Inject constructor(
}
}
+ override suspend fun getUserId(): Result {
+ return userDataSource.getUserId()
+ }
+
override suspend fun postUserProfile(
userId: String,
userName: String,
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/SignInUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/SignInUseCase.kt
index 04df5309..4eaeb957 100644
--- a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/SignInUseCase.kt
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/SignInUseCase.kt
@@ -6,6 +6,7 @@ import com.wap.wapp.core.domain.model.AuthState
import com.wap.wapp.core.domain.model.AuthState.SIGN_IN
import com.wap.wapp.core.domain.model.AuthState.SIGN_UP
import dagger.hilt.android.scopes.ActivityScoped
+import java.lang.IllegalStateException
import javax.inject.Inject
@ActivityScoped
@@ -21,13 +22,15 @@ class SignInUseCase @Inject constructor(
userRepository.getUserProfile(userId)
.fold(
onFailure = { exception ->
- // 사용자를 조회할 수 없는 예외인 경우
- val userNotFoundException = IllegalStateException()
- if (exception == userNotFoundException) {
- SIGN_UP
+ when (exception) {
+ // 사용자를 조회할 수 없는 예외인 경우
+ is IllegalStateException -> {
+ SIGN_UP
+ }
+ else -> {
+ throw (exception)
+ }
}
- // 이외의 예외라면,
- throw (exception)
},
onSuccess = {
SIGN_IN
diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/PostUserProfileUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/PostUserProfileUseCase.kt
index 136b9ddc..b72ade90 100644
--- a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/PostUserProfileUseCase.kt
+++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/user/PostUserProfileUseCase.kt
@@ -9,16 +9,19 @@ class PostUserProfileUseCase @Inject constructor(
private val userRepository: UserRepository,
) {
suspend operator fun invoke(
- userId: String,
userName: String,
studentId: String,
registeredAt: String,
): Result {
- return userRepository.postUserProfile(
- userId = userId,
- userName = userName,
- studentId = studentId,
- registeredAt = registeredAt,
- )
+ return runCatching {
+ val userId = userRepository.getUserId().getOrThrow()
+
+ userRepository.postUserProfile(
+ userId = userId,
+ userName = userName,
+ studentId = studentId,
+ registeredAt = registeredAt,
+ )
+ }
}
}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/di/AuthDataSourceModule.kt b/core/network/src/main/java/com/wap/wapp/core/network/di/AuthDataSourceModule.kt
index 6116ef9c..a00ca9d4 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/di/AuthDataSourceModule.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/di/AuthDataSourceModule.kt
@@ -13,7 +13,7 @@ import dagger.hilt.android.scopes.ActivityScoped
abstract class AuthDataSourceModule {
@Binds
@ActivityScoped
- abstract fun providesAuthDataSource(
+ abstract fun bindsAuthDataSource(
authDataSourceImpl: AuthDataSourceImpl,
): AuthDataSource
}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/di/FirebaseModule.kt b/core/network/src/main/java/com/wap/wapp/core/network/di/FirebaseModule.kt
new file mode 100644
index 00000000..d47105c5
--- /dev/null
+++ b/core/network/src/main/java/com/wap/wapp/core/network/di/FirebaseModule.kt
@@ -0,0 +1,24 @@
+package com.wap.wapp.core.network.di
+
+import com.google.firebase.auth.FirebaseAuth
+import com.google.firebase.auth.ktx.auth
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.ktx.firestore
+import com.google.firebase.ktx.Firebase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object FirebaseModule {
+ @Provides
+ @Singleton
+ fun providesFirebaseAuth(): FirebaseAuth = Firebase.auth
+
+ @Provides
+ @Singleton
+ fun providesFirestore(): FirebaseFirestore = Firebase.firestore
+}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/di/NetworkModule.kt b/core/network/src/main/java/com/wap/wapp/core/network/di/NetworkModule.kt
index 85df137d..d36b8a79 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/di/NetworkModule.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/di/NetworkModule.kt
@@ -1,24 +1,20 @@
package com.wap.wapp.core.network.di
-import com.google.firebase.auth.FirebaseAuth
-import com.google.firebase.auth.ktx.auth
-import com.google.firebase.firestore.FirebaseFirestore
-import com.google.firebase.firestore.ktx.firestore
-import com.google.firebase.ktx.Firebase
+import com.wap.wapp.core.network.source.user.UserDataSource
+import com.wap.wapp.core.network.source.user.UserDataSourceImpl
+import dagger.Binds
import dagger.Module
-import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
-object NetworkModule {
- @Provides
- @Singleton
- fun providesFirebaseAuth(): FirebaseAuth = Firebase.auth
+abstract class NetworkModule {
- @Provides
+ @Binds
@Singleton
- fun providesFirestore(): FirebaseFirestore = Firebase.firestore
+ abstract fun bindsUserDataSource(
+ userDataSourceImpl: UserDataSourceImpl,
+ ): UserDataSource
}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSource.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSource.kt
index 4b261118..e13b3020 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSource.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSource.kt
@@ -7,4 +7,6 @@ interface UserDataSource {
suspend fun postUserProfile(userProfileRequest: UserProfileRequest): Result
suspend fun getUserProfile(userId: String): Result
+
+ suspend fun getUserId(): Result
}
diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSourceImpl.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSourceImpl.kt
index 093318d1..d242636b 100644
--- a/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSourceImpl.kt
+++ b/core/network/src/main/java/com/wap/wapp/core/network/source/user/UserDataSourceImpl.kt
@@ -1,5 +1,6 @@
package com.wap.wapp.core.network.source.user
+import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.SetOptions
import com.wap.wapp.core.network.constant.USER_COLLECTION
@@ -10,6 +11,7 @@ import javax.inject.Inject
class UserDataSourceImpl @Inject constructor(
private val firebaseFirestore: FirebaseFirestore,
+ private val firebaseAuth: FirebaseAuth,
) : UserDataSource {
override suspend fun postUserProfile(
userProfileRequest: UserProfileRequest,
@@ -28,6 +30,12 @@ class UserDataSourceImpl @Inject constructor(
}
}
+ override suspend fun getUserId(): Result {
+ return runCatching {
+ checkNotNull(firebaseAuth.uid)
+ }
+ }
+
override suspend fun getUserProfile(
userId: String,
): Result {
diff --git a/feature/auth/build.gradle.kts b/feature/auth/build.gradle.kts
index b063bee6..d2f266d2 100644
--- a/feature/auth/build.gradle.kts
+++ b/feature/auth/build.gradle.kts
@@ -28,6 +28,7 @@ dependencies {
implementation(project(":core:model"))
implementation(project(":core:designsystem"))
implementation(project(":core:designresource"))
+ implementation(project(":core:common"))
implementation(libs.bundles.androidx)
implementation(libs.material)
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInBottomSheet.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInBottomSheet.kt
deleted file mode 100644
index 5185c068..00000000
--- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInBottomSheet.kt
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.wap.wapp.feature.auth.signin
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material3.Button
-import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.Divider
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.ModalBottomSheet
-import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Text
-import androidx.compose.material3.rememberModalBottomSheetState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import com.wap.designsystem.WappTheme
-import com.wap.wapp.feature.auth.R
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-fun signInBottomSheet() {
- val sheetState = rememberModalBottomSheetState()
- var isSheetOpen by rememberSaveable {
- mutableStateOf(false)
- }
-
- if (isSheetOpen) {
- ModalBottomSheet(
- sheetState = sheetState,
- onDismissRequest = { isSheetOpen = false },
- ) {
- Column(
- modifier = Modifier.padding(16.dp),
- ) {
- Text(
- modifier = Modifier.align(Alignment.CenterHorizontally),
- text = stringResource(id = R.string.sign_in),
- style = WappTheme.typography.contentMedium,
- color = WappTheme.colors.white,
- )
-
- Spacer(modifier = Modifier.height(16.dp))
-
- Text(
- text = stringResource(id = R.string.sign_in_email),
- color = WappTheme.colors.white,
- style = WappTheme.typography.labelRegular,
- )
- var filledText = ""
- OutlinedTextField(
- modifier = Modifier.fillMaxWidth(),
- value = filledText,
- onValueChange = { filledText = it },
- placeholder = {
- Text(
- text = stringResource(id = R.string.sign_in_email_hint),
- )
- },
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Email,
- ),
- )
-
- Spacer(modifier = Modifier.height(16.dp))
-
- Button(
- onClick = { },
- modifier = Modifier.fillMaxWidth(),
- colors = ButtonDefaults.buttonColors(
- contentColor = WappTheme.colors.white,
- containerColor = WappTheme.colors.gray1,
- ),
- shape = RoundedCornerShape(10.dp),
- ) {
- Text(
- text = stringResource(id = R.string.done),
- style = WappTheme.typography.contentMedium,
- )
- }
-
- Spacer(modifier = Modifier.height(16.dp))
-
- Divider(
- color = WappTheme.colors.white,
- thickness = 1.dp,
- )
- Text(
- modifier = Modifier.fillMaxWidth(),
- textAlign = TextAlign.Center,
- text = stringResource(id = R.string.sign_in_find_email),
- style = WappTheme.typography.captionMedium,
- color = WappTheme.colors.yellow,
- )
- }
- }
- }
-}
-
-@Preview
-@Composable
-fun previewSignUpScreen() {
- WappTheme {
- signInBottomSheet()
- }
-}
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt
new file mode 100644
index 00000000..20f08de5
--- /dev/null
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt
@@ -0,0 +1,135 @@
+package com.wap.wapp.feature.auth.signin
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+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.material.Text
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.ElevatedButton
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+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.compose.ui.unit.sp
+import com.wap.designsystem.WappTheme
+import com.wap.wapp.core.designresource.R
+import com.wap.wapp.feature.auth.R.string
+
+@Composable
+internal fun SignInContent(
+ openSignInSheet: () -> Unit,
+ navigateToNotice: () -> Unit,
+) {
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ verticalArrangement = Arrangement.spacedBy(32.dp),
+ ) {
+ Spacer(modifier = Modifier.height(32.dp))
+ Image(
+ painter = painterResource(id = R.drawable.img_white_cat),
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally)
+ .size(width = 230.dp, height = 230.dp),
+ contentDescription = "WAPP ICON",
+ )
+
+ Row(
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ ) {
+ Column {
+ Spacer(modifier = Modifier.height(40.dp))
+ Text(
+ text = stringResource(id = string.application_name),
+ style = WappTheme.typography.titleBold,
+ fontSize = 48.sp,
+ color = WappTheme.colors.white,
+ )
+ }
+ Text(
+ text = stringResource(id = string.application_name),
+ fontSize = 48.sp,
+ style = WappTheme.typography.titleBold,
+ color = WappTheme.colors.yellow,
+ )
+ }
+
+ Column {
+ ElevatedButton(
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally)
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ onClick = {
+ openSignInSheet()
+ },
+ shape = RoundedCornerShape(10.dp),
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_github),
+ contentDescription = stringResource(
+ id = string.sign_in_github_description,
+ ),
+ modifier = Modifier.size(40.dp),
+ tint = WappTheme.colors.black,
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(
+ text = stringResource(id = string.sign_in_github_content),
+ style = WappTheme.typography.contentMedium,
+ )
+ }
+
+ Spacer(modifier = Modifier.height(12.dp))
+
+ ElevatedButton(
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally)
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ onClick = {
+ navigateToNotice()
+ },
+ colors = ButtonDefaults.elevatedButtonColors(
+ containerColor = WappTheme.colors.yellow,
+ contentColor = WappTheme.colors.white,
+ ),
+ shape = RoundedCornerShape(10.dp),
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_balloon),
+ contentDescription = stringResource(
+ id = string.sign_in_non_member_description,
+ ),
+ modifier = Modifier.size(40.dp),
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(
+ text = stringResource(id = string.sign_in_non_member_content),
+ style = WappTheme.typography.contentMedium,
+ color = WappTheme.colors.white,
+ )
+ }
+ }
+ }
+}
+
+/*@Preview
+@Composable
+fun previewSignInScreen() {
+ SignInScreen(
+
+ navigateToSignUp = { },
+ navigateToNotice = { },
+ )
+}*/
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInFragment.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInFragment.kt
new file mode 100644
index 00000000..f13922a5
--- /dev/null
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInFragment.kt
@@ -0,0 +1,63 @@
+package com.wap.wapp.feature.auth.signin
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.core.net.toUri
+import androidx.fragment.app.Fragment
+import androidx.navigation.NavOptions
+import androidx.navigation.fragment.findNavController
+import com.wap.designsystem.WappTheme
+import com.wap.wapp.core.domain.usecase.auth.SignInUseCase
+import com.wap.wapp.feature.auth.R
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class SignInFragment : Fragment() {
+
+ @Inject
+ lateinit var signInUseCase: SignInUseCase
+
+ private lateinit var composeView: ComposeView
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View {
+ return ComposeView(requireContext()).also {
+ composeView = it
+ }
+ }
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ composeView.setContent {
+ WappTheme {
+ SignInScreen(
+ signInUseCase = signInUseCase,
+ navigateToSignUp = { navigateToSignUp() },
+ navigateToNotice = { navigateToNotice() },
+ )
+ }
+ }
+ }
+
+ private fun navigateToSignUp() {
+ findNavController().navigate(
+ SignInFragmentDirections.actionSignInFragmentToSignUpFragment(),
+ )
+ }
+
+ private fun navigateToNotice() {
+ findNavController().navigate(
+ "wapp://feature/nav_notice".toUri(),
+ NavOptions.Builder()
+ .setPopUpTo(R.id.signUpFragment, true)
+ .build(),
+ )
+ }
+}
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt
index d4de7fcc..81b69cbb 100644
--- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt
@@ -1,144 +1,162 @@
package com.wap.wapp.feature.auth.signin
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
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.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.BottomSheetScaffold
+import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.ElevatedButton
-import androidx.compose.material3.Icon
+import androidx.compose.material3.Divider
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
+import androidx.compose.material3.Text
+import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.wap.designsystem.WappTheme
-import com.wap.wapp.core.designresource.R
-import com.wap.wapp.feature.auth.R.string
+import com.wap.wapp.core.commmon.extensions.toSupportingText
+import com.wap.wapp.core.domain.model.AuthState
+import com.wap.wapp.core.domain.usecase.auth.SignInUseCase
+import com.wap.wapp.feature.auth.R
+import kotlinx.coroutines.launch
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SignInScreen(
- navigateToSignUp: () -> Unit,
+internal fun SignInScreen(
+ signInUseCase: SignInUseCase,
navigateToNotice: () -> Unit,
+ navigateToSignUp: () -> Unit,
) {
- WappTheme {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = WappTheme.colors.backgroundBlack,
- ) {
+ val coroutineScope = rememberCoroutineScope()
+ val scaffoldState = rememberBottomSheetScaffoldState()
+ val snackBarHostState = remember { SnackbarHostState() }
+ var email by rememberSaveable { mutableStateOf("") }
+
+ BottomSheetScaffold(
+ scaffoldState = scaffoldState,
+ snackbarHost = { SnackbarHost(snackBarHostState) },
+ sheetContainerColor = WappTheme.colors.backgroundBlack,
+ containerColor = WappTheme.colors.backgroundBlack,
+ sheetPeekHeight = 0.dp,
+ modifier = Modifier.fillMaxSize(),
+ sheetContent = {
Column(
- modifier = Modifier.fillMaxWidth(),
- verticalArrangement = Arrangement.spacedBy(32.dp),
+ modifier = Modifier.padding(16.dp),
) {
- Spacer(modifier = Modifier.height(32.dp))
- Image(
- painter = painterResource(id = R.drawable.img_white_cat),
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .size(width = 230.dp, height = 230.dp),
- contentDescription = "WAPP ICON",
+ Text(
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ text = stringResource(id = R.string.sign_in),
+ style = WappTheme.typography.contentBold,
+ color = WappTheme.colors.white,
+ fontSize = 18.sp,
)
+ Spacer(modifier = Modifier.height(16.dp))
- Row(
- modifier = Modifier.align(Alignment.CenterHorizontally),
- ) {
- Column {
- Spacer(modifier = Modifier.height(40.dp))
+ Text(
+ text = stringResource(id = R.string.sign_in_email),
+ color = WappTheme.colors.white,
+ style = WappTheme.typography.labelRegular,
+ )
+ Spacer(modifier = Modifier.height(4.dp))
+
+ OutlinedTextField(
+ modifier = Modifier.fillMaxWidth(),
+ value = email,
+ onValueChange = { email = it },
+ placeholder = {
Text(
- text = stringResource(id = string.application_name),
- style = WappTheme.typography.titleBold,
- fontSize = 48.sp,
- color = WappTheme.colors.white,
+ text = stringResource(id = R.string.sign_in_email_hint),
)
- }
+ },
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Email,
+ ),
+ colors = OutlinedTextFieldDefaults.colors(
+ focusedTextColor = WappTheme.colors.white,
+ focusedBorderColor = WappTheme.colors.yellow,
+ ),
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+
+ Button(
+ onClick = {
+ coroutineScope.launch {
+ signInUseCase(email = email)
+ .onSuccess {
+ when (it) {
+ AuthState.SIGN_IN -> { navigateToNotice() }
+ AuthState.SIGN_UP -> { navigateToSignUp() }
+ }
+ }
+ .onFailure { throwable ->
+ snackBarHostState.showSnackbar(
+ throwable.toSupportingText(),
+ )
+ }
+ }
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(48.dp),
+ enabled = email.isNotBlank(),
+ colors = ButtonDefaults.buttonColors(
+ contentColor = WappTheme.colors.white,
+ containerColor = WappTheme.colors.yellow,
+ disabledContentColor = WappTheme.colors.white,
+ disabledContainerColor = WappTheme.colors.gray1,
+ ),
+ shape = RoundedCornerShape(10.dp),
+ ) {
Text(
- text = stringResource(id = string.application_name),
- fontSize = 48.sp,
- style = WappTheme.typography.titleBold,
- color = WappTheme.colors.yellow,
+ text = stringResource(id = R.string.done),
+ style = WappTheme.typography.contentMedium,
)
}
+ Spacer(modifier = Modifier.height(16.dp))
- Column {
- ElevatedButton(
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .fillMaxWidth()
- .padding(horizontal = 16.dp),
- onClick = {
- navigateToSignUp()
- },
- shape = RoundedCornerShape(10.dp),
- ) {
- Icon(
- painter = painterResource(id = R.drawable.ic_github),
- contentDescription = stringResource(
- id = string.sign_in_github_description,
- ),
- modifier = Modifier.size(40.dp),
- tint = WappTheme.colors.black,
- )
- Spacer(modifier = Modifier.width(16.dp))
- Text(
- text = stringResource(id = string.sign_in_github_content),
- style = WappTheme.typography.contentMedium,
- )
- }
-
- Spacer(modifier = Modifier.height(12.dp))
-
- ElevatedButton(
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .fillMaxWidth()
- .padding(horizontal = 16.dp),
- onClick = {
- navigateToNotice()
- },
- colors = ButtonDefaults.elevatedButtonColors(
- containerColor = WappTheme.colors.yellow,
- contentColor = WappTheme.colors.white,
- ),
- shape = RoundedCornerShape(10.dp),
- ) {
- Icon(
- painter = painterResource(id = R.drawable.ic_balloon),
- contentDescription = stringResource(
- id = string.sign_in_non_member_description,
- ),
- modifier = Modifier.size(40.dp),
- )
- Spacer(modifier = Modifier.width(16.dp))
- Text(
- text = stringResource(id = string.sign_in_non_member_content),
- style = WappTheme.typography.contentMedium,
- color = WappTheme.colors.white,
- )
- }
- }
+ Divider(
+ color = WappTheme.colors.white,
+ thickness = 1.dp,
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center,
+ text = stringResource(id = R.string.sign_in_find_email),
+ style = WappTheme.typography.captionMedium,
+ color = WappTheme.colors.yellow,
+ )
+ Spacer(modifier = Modifier.height(32.dp))
}
- }
+ },
+ ) {
+ SignInContent(
+ openSignInSheet = {
+ coroutineScope.launch {
+ scaffoldState.bottomSheetState.expand()
+ }
+ },
+ navigateToNotice = { navigateToNotice() },
+ )
}
}
-
-@Preview
-@Composable
-fun previewSignInScreen() {
- SignInScreen(
- navigateToSignUp = { },
- navigateToNotice = { },
- )
-}
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChipGroup.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChip.kt
similarity index 76%
rename from feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChipGroup.kt
rename to feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChip.kt
index ed9afb92..1e5a30d7 100644
--- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChipGroup.kt
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpChip.kt
@@ -9,32 +9,29 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.wap.designsystem.WappTheme
+import com.wap.wapp.feature.auth.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SignUpChipGroup() {
- val itemsList = listOf("1학기", "2학기")
-
- var selectedItem by remember {
- mutableStateOf(itemsList[0]) // initially, first item is selected
- }
-
+internal fun SignUpChip(
+ selectedItem: String,
+ onSelected: (String) -> Unit,
+) {
+ val itemsList = listOf(
+ stringResource(id = R.string.first_semester),
+ stringResource(id = R.string.second_semester),
+ )
LazyRow(modifier = Modifier.fillMaxWidth()) {
items(itemsList) { item ->
FilterChip(
modifier = Modifier.padding(horizontal = 6.dp),
selected = (item == selectedItem),
- onClick = {
- selectedItem = item
- },
+ onClick = { onSelected(item) },
label = {
Text(
text = item,
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpFragment.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpFragment.kt
new file mode 100644
index 00000000..095b4cef
--- /dev/null
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpFragment.kt
@@ -0,0 +1,59 @@
+package com.wap.wapp.feature.auth.signup
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.core.net.toUri
+import androidx.fragment.app.Fragment
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.navigation.NavOptions
+import androidx.navigation.fragment.findNavController
+import com.wap.designsystem.WappTheme
+import com.wap.wapp.feature.auth.R
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class SignUpFragment : Fragment() {
+
+ private lateinit var composeView: ComposeView
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View {
+ return ComposeView(requireContext()).also {
+ composeView = it
+ }
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ composeView.setContent {
+ WappTheme {
+ SignUpScreen(
+ viewModel = hiltViewModel(),
+ navigateToNotice = { navigateToNotice() },
+ navigateToSignIn = { navigateToSignIn() },
+ )
+ }
+ }
+ }
+
+ private fun navigateToNotice() {
+ findNavController().navigate(
+ "wapp://feature/nav_notice".toUri(),
+ NavOptions.Builder()
+ .setPopUpTo(R.id.signUpFragment, true)
+ .build(),
+ )
+ }
+
+ private fun navigateToSignIn() {
+ findNavController().navigate(
+ SignUpFragmentDirections.actionSignUpFragmentToSignInFragment(),
+ )
+ }
+}
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt
index b7e85827..64f671dd 100644
--- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt
@@ -1,6 +1,7 @@
package com.wap.wapp.feature.auth.signup
import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -14,184 +15,186 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material.Icon
-import androidx.compose.material.Surface
import androidx.compose.material.Text
-import androidx.compose.material.TextField
-import androidx.compose.material.TextFieldDefaults
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.hilt.navigation.compose.hiltViewModel
import com.wap.designsystem.WappTheme
+import com.wap.wapp.core.commmon.extensions.toSupportingText
import com.wap.wapp.core.designresource.R
import com.wap.wapp.feature.auth.R.drawable.ic_card
import com.wap.wapp.feature.auth.R.drawable.ic_door
import com.wap.wapp.feature.auth.R.string
+import com.wap.wapp.feature.auth.signup.SignUpViewModel.SignUpEvent
+import kotlinx.coroutines.flow.collectLatest
@Composable
-fun SignUpScreen() {
- WappTheme {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = WappTheme.colors.backgroundBlack,
- ) {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(horizontal = 16.dp),
- ) {
- Box(
- modifier = Modifier.fillMaxWidth(),
- ) {
- Image(
- painterResource(id = R.drawable.ic_back_btn),
- contentDescription = stringResource(id = string.back_button_description),
- modifier = Modifier
- .padding(vertical = 16.dp)
- .size(20.dp),
- )
- Text(
- text = stringResource(id = string.sign_up),
- style = WappTheme.typography.titleBold,
- color = WappTheme.colors.white,
- fontSize = 20.sp,
- modifier = Modifier
- .fillMaxWidth()
- .padding(vertical = 16.dp),
- textAlign = TextAlign.Center,
+internal fun SignUpScreen(
+ navigateToNotice: () -> Unit,
+ navigateToSignIn: () -> Unit,
+ viewModel: SignUpViewModel = hiltViewModel(),
+) {
+ val snackBarHostState = remember { SnackbarHostState() }
+
+ LaunchedEffect(true) {
+ viewModel.signUpEventFlow.collectLatest {
+ when (it) {
+ is SignUpEvent.Success -> {
+ navigateToNotice()
+ }
+ is SignUpEvent.Failure -> {
+ snackBarHostState.showSnackbar(
+ message = it.throwable.toSupportingText(),
)
}
+ }
+ }
+ }
- Spacer(modifier = Modifier.height(32.dp))
-
+ Scaffold(
+ modifier = Modifier.fillMaxSize(),
+ containerColor = WappTheme.colors.backgroundBlack,
+ snackbarHost = { SnackbarHost(snackBarHostState) },
+ ) { padding ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp),
+ ) {
+ Box(
+ modifier = Modifier.fillMaxWidth(),
+ ) {
+ Image(
+ painterResource(id = R.drawable.ic_back_btn),
+ contentDescription = stringResource(id = string.back_button_description),
+ modifier = Modifier
+ .padding(vertical = 16.dp)
+ .size(20.dp)
+ .clickable { navigateToSignIn() },
+ )
Text(
- text = stringResource(id = string.sign_up_title),
+ text = stringResource(id = string.sign_up),
style = WappTheme.typography.titleBold,
color = WappTheme.colors.white,
+ fontSize = 20.sp,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 16.dp),
+ textAlign = TextAlign.Center,
)
- Text(
- text = stringResource(id = string.sign_up_content),
- style = WappTheme.typography.contentMedium,
- color = WappTheme.colors.gray1,
+ }
+
+ Spacer(modifier = Modifier.height(32.dp))
+
+ Text(
+ text = stringResource(id = string.sign_up_title),
+ style = WappTheme.typography.titleBold,
+ color = WappTheme.colors.white,
+ )
+ Text(
+ text = stringResource(id = string.sign_up_content),
+ style = WappTheme.typography.contentMedium,
+ color = WappTheme.colors.gray1,
+ )
+
+ Spacer(modifier = Modifier.height(32.dp))
+
+ Column(
+ verticalArrangement = Arrangement.spacedBy(32.dp),
+ ) {
+ SignUpTextField(
+ iconDescription = stringResource(id = string.sign_up_name_description),
+ text = viewModel.signUpName.collectAsState().value,
+ title = stringResource(id = string.sign_up_name_title),
+ onValueChanged = { name -> viewModel.setName(name) },
+ hint = stringResource(id = string.sign_up_name_hint),
+ supportingText = stringResource(id = string.sign_up_name_caption),
+ icon = R.drawable.ic_profile,
+ modifier = Modifier.fillMaxWidth(),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
)
- Spacer(modifier = Modifier.height(32.dp))
+ SignUpTextField(
+ iconDescription = stringResource(
+ id = string.sign_up_student_id_description,
+ ),
+ text = viewModel.signUpStudentId.collectAsState().value,
+ title = stringResource(id = string.sign_up_student_id_title),
+ onValueChanged = { name -> viewModel.setStudentId(name) },
+ hint = stringResource(id = string.sign_up_student_id_hint),
+ supportingText = stringResource(id = string.sign_up_student_id_caption),
+ icon = ic_card,
+ modifier = Modifier.fillMaxWidth(),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
+ )
- Column(
- verticalArrangement = Arrangement.spacedBy(32.dp),
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
) {
- SignUpTextField(
- iconDescription = stringResource(id = string.sign_up_name_description),
- fieldName = stringResource(id = string.sign_up_name_title),
- fieldHint = stringResource(id = string.sign_up_name_hint),
- fieldSupportingText = stringResource(id = string.sign_up_name_caption),
- fieldIcon = R.drawable.ic_profile,
- )
-
SignUpTextField(
iconDescription = stringResource(
- id = string.sign_up_student_id_description,
+ id = string.sign_up_registered_at_description,
),
- fieldName = stringResource(id = string.sign_up_student_id_title),
- fieldHint = stringResource(id = string.sign_up_student_id_hint),
- fieldSupportingText = stringResource(
- id = string.sign_up_student_id_caption,
+ text = viewModel.signUpYear.collectAsState().value,
+ title = stringResource(id = string.sign_up_registered_at_title),
+ onValueChanged = { name -> viewModel.setYear(name) },
+ hint = stringResource(id = string.sign_up_registered_at_hint),
+ supportingText = stringResource(
+ id = string.sign_up_registered_at_caption,
),
- fieldIcon = ic_card,
+ icon = ic_door,
+ modifier = Modifier.width(150.dp),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
)
- var dummyText = ""
- Column {
- Row(
- verticalAlignment = Alignment.CenterVertically,
- ) {
- Icon(
- painter = painterResource(id = ic_door),
- contentDescription = stringResource(
- id = string.sign_up_registered_at_description,
- ),
- tint = WappTheme.colors.white,
- modifier = Modifier.size(20.dp),
- )
- Spacer(modifier = Modifier.width(8.dp))
- Text(
- text = stringResource(id = string.sign_up_registered_at_title),
- color = WappTheme.colors.white,
- style = WappTheme.typography.contentBold,
- )
- }
-
- Row(
- modifier = Modifier.fillMaxWidth(),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- TextField(
- value = dummyText,
- onValueChange = { dummyText = it },
- modifier = Modifier.width(150.dp),
- colors = TextFieldDefaults.textFieldColors(
- textColor = WappTheme.colors.white,
- backgroundColor = WappTheme.colors.backgroundBlack,
- focusedIndicatorColor = WappTheme.colors.white,
- unfocusedIndicatorColor = WappTheme.colors.white,
- ),
- placeholder = {
- Text(
- text = stringResource(
- id = string.sign_up_registered_at_hint,
- ),
- color = WappTheme.colors.gray1,
- )
- },
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Number,
- ),
- )
-
- Spacer(modifier = Modifier.width(16.dp))
-
- SignUpChipGroup()
- }
-
- Spacer(modifier = Modifier.height(8.dp))
- Text(
- text = stringResource(id = string.sign_up_registered_at_caption),
- color = WappTheme.colors.yellow,
- style = WappTheme.typography.captionRegular,
- )
- }
+ SignUpChip(
+ selectedItem = viewModel.signUpSemester.collectAsState().value,
+ onSelected = { semester -> viewModel.setSemester(semester) },
+ )
+ }
- Button(
- onClick = { },
- modifier = Modifier.fillMaxWidth(),
- colors = ButtonDefaults.buttonColors(
- containerColor = WappTheme.colors.yellow,
- ),
- shape = RoundedCornerShape(10.dp),
- ) {
- Text(
- text = stringResource(id = string.done),
- style = WappTheme.typography.contentMedium,
- color = WappTheme.colors.white,
- )
- }
+ Button(
+ onClick = { viewModel.postUserProfile() },
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(48.dp),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = WappTheme.colors.yellow,
+ ),
+ shape = RoundedCornerShape(10.dp),
+ ) {
+ Text(
+ text = stringResource(id = string.done),
+ style = WappTheme.typography.contentMedium,
+ color = WappTheme.colors.white,
+ )
}
}
}
}
}
-@Preview
+/*@Preview
@Composable
fun previewSignUpScreen() {
- SignUpScreen()
-}
+ SignUpScreen(
+ "",
+ navigateToNotice = { }
+ )
+}*/
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpTextField.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpTextField.kt
index f3a0e122..e82b3199 100644
--- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpTextField.kt
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpTextField.kt
@@ -3,10 +3,10 @@ package com.wap.wapp.feature.auth.signup
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.TextField
@@ -19,36 +19,38 @@ import androidx.compose.ui.unit.dp
import com.wap.designsystem.WappTheme
@Composable
-fun SignUpTextField(
+internal fun SignUpTextField(
iconDescription: String,
- fieldName: String,
- fieldHint: String,
- fieldSupportingText: String,
- fieldIcon: Int,
+ title: String,
+ text: String,
+ onValueChanged: (String) -> Unit,
+ hint: String,
+ supportingText: String,
+ icon: Int,
+ keyboardOptions: KeyboardOptions,
+ modifier: Modifier,
) {
- var dummyText = ""
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
- painter = painterResource(id = fieldIcon),
+ painter = painterResource(id = icon),
contentDescription = iconDescription,
tint = WappTheme.colors.white,
modifier = Modifier.size(20.dp),
)
Spacer(modifier = Modifier.width(8.dp))
Text(
- text = fieldName,
+ text = title,
color = WappTheme.colors.white,
style = WappTheme.typography.contentBold,
)
}
TextField(
- value = dummyText,
- onValueChange = { dummyText = it },
- modifier = Modifier
- .fillMaxWidth(),
+ value = text,
+ onValueChange = onValueChanged,
+ modifier = modifier,
colors = TextFieldDefaults.textFieldColors(
textColor = WappTheme.colors.white,
backgroundColor = WappTheme.colors.backgroundBlack,
@@ -56,15 +58,13 @@ fun SignUpTextField(
unfocusedIndicatorColor = WappTheme.colors.white,
),
placeholder = {
- Text(
- text = fieldHint,
- color = WappTheme.colors.gray1,
- )
+ Text(text = hint, color = WappTheme.colors.gray1)
},
+ keyboardOptions = keyboardOptions,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
- text = fieldSupportingText,
+ text = supportingText,
color = WappTheme.colors.yellow,
style = WappTheme.typography.captionRegular,
)
diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt
new file mode 100644
index 00000000..e067b7ec
--- /dev/null
+++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt
@@ -0,0 +1,72 @@
+package com.wap.wapp.feature.auth.signup
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.wap.wapp.core.domain.usecase.user.PostUserProfileUseCase
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+@HiltViewModel
+class SignUpViewModel @Inject constructor(
+ private val postUserProfileUseCase: PostUserProfileUseCase,
+) : ViewModel() {
+
+ private val _signUpEventFlow = MutableSharedFlow()
+ val signUpEventFlow: SharedFlow get() = _signUpEventFlow
+
+ private val _signUpName: MutableStateFlow = MutableStateFlow("")
+ val signUpName: StateFlow get() = _signUpName
+
+ private val _signUpStudentId: MutableStateFlow = MutableStateFlow("")
+ val signUpStudentId: StateFlow get() = _signUpStudentId
+
+ private val _signUpYear: MutableStateFlow = MutableStateFlow("")
+ val signUpYear: StateFlow get() = _signUpYear
+
+ private val _signUpSemester: MutableStateFlow = MutableStateFlow(FIRST_SEMESTER)
+ val signUpSemester: StateFlow get() = _signUpSemester
+
+ fun postUserProfile() {
+ viewModelScope.launch {
+ postUserProfileUseCase(
+ userName = _signUpName.value,
+ studentId = _signUpStudentId.value,
+ registeredAt = "${_signUpYear.value} ${_signUpSemester.value}",
+ ).onSuccess {
+ _signUpEventFlow.emit(SignUpEvent.Success)
+ }.onFailure { throwable ->
+ _signUpEventFlow.emit(SignUpEvent.Failure(throwable))
+ }
+ }
+ }
+
+ fun setName(name: String) {
+ _signUpName.value = name
+ }
+
+ fun setStudentId(studentId: String) {
+ _signUpStudentId.value = studentId
+ }
+
+ fun setYear(year: String) {
+ _signUpYear.value = year
+ }
+
+ fun setSemester(semester: String) {
+ _signUpSemester.value = semester
+ }
+
+ companion object {
+ const val FIRST_SEMESTER = "1학기"
+ }
+
+ sealed class SignUpEvent {
+ data object Success : SignUpEvent()
+ data class Failure(val throwable: Throwable) : SignUpEvent()
+ }
+}
diff --git a/feature/auth/src/main/res/navigation/nav_auth.xml b/feature/auth/src/main/res/navigation/nav_auth.xml
new file mode 100644
index 00000000..2bd099c7
--- /dev/null
+++ b/feature/auth/src/main/res/navigation/nav_auth.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/feature/auth/src/main/res/values/strings.xml b/feature/auth/src/main/res/values/strings.xml
index 2426c642..9fb757db 100644
--- a/feature/auth/src/main/res/values/strings.xml
+++ b/feature/auth/src/main/res/values/strings.xml
@@ -26,5 +26,7 @@
입부년도 입력
회원님의 기수 정보를 알려드릴게요!
Door Icon
+ 1학기
+ 2학기
완료
diff --git a/feature/splash/build.gradle.kts b/feature/splash/build.gradle.kts
index f494e209..26404c74 100644
--- a/feature/splash/build.gradle.kts
+++ b/feature/splash/build.gradle.kts
@@ -25,7 +25,7 @@ android {
dependencies {
implementation(project(":core:designresource"))
implementation(project(":core:designsystem"))
- implementation(project(":core:base"))
+ implementation(project(":core:common"))
implementation(libs.bundles.androidx)
implementation(libs.material)
diff --git a/feature/splash/src/main/java/com/wap/wapp/feature/splash/SplashFragment.kt b/feature/splash/src/main/java/com/wap/wapp/feature/splash/SplashFragment.kt
index ee668f33..8fe255f5 100644
--- a/feature/splash/src/main/java/com/wap/wapp/feature/splash/SplashFragment.kt
+++ b/feature/splash/src/main/java/com/wap/wapp/feature/splash/SplashFragment.kt
@@ -6,8 +6,8 @@ import androidx.core.net.toUri
import androidx.fragment.app.viewModels
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
-import com.android.mediproject.core.ui.base.BaseFragment
-import com.wap.wapp.core.base.util.repeatOnStarted
+import com.wap.wapp.core.commmon.base.BaseFragment
+import com.wap.wapp.core.commmon.extensions.repeatOnStarted
import com.wap.wapp.feature.splash.databinding.FragmentSplashBinding
import dagger.hilt.android.AndroidEntryPoint
@@ -27,13 +27,15 @@ class SplashFragment :
}
private fun handleEvent(event: SplashViewModel.SplashEvent) = when (event) {
- is SplashViewModel.SplashEvent.TimerDone -> navigateToNotice()
+ is SplashViewModel.SplashEvent.TimerDone -> navigateToAuth()
}
- private fun navigateToNotice() {
+ private fun navigateToAuth() {
findNavController().navigate(
- "wapp://feature/nav_notice".toUri(),
- NavOptions.Builder().setPopUpTo(R.id.splashFragment, true).build(),
+ "wapp://feature/nav_auth".toUri(),
+ NavOptions.Builder()
+ .setPopUpTo(R.id.splashFragment, true)
+ .build(),
)
}
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7f57b3c9..2dad5f47 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -15,6 +15,7 @@ androidx-appcompat = "1.6.1"
androidx-fragment = "1.6.1"
androidx-activity = "1.7.2"
androidx-lifecycle = "2.6.2"
+androidx-compose-hilt = "1.0.0"
androidx-contstraintlayout = "2.1.4"
androidx-test-junit = "1.1.5"
androidx-test-espresso = "3.5.1"
@@ -42,6 +43,7 @@ hilt = "2.48"
android-build = { module = "com.android.tools.build:gradle", version.ref = "gradleplugin" }
kotlin-gradle = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
hilt-gradle = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "hilt" }
+androidx-navigation-safeargs = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref="androidx-navigation"}
kotlin = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
@@ -53,7 +55,7 @@ androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-kt
androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "androidx-fragment" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "androidx-navigation" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "androidx-navigation" }
-
+androidx-navigation-compose = { group = "androidx.navigation", name ="navigation-compose", version.ref = "androidx-navigation" }
compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
@@ -67,6 +69,7 @@ compose-material3-windowSizeClass = { module = "androidx.compose.material3:mater
compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" }
compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "compose" }
compose-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
+compose-hilt = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidx-compose-hilt" }
compose-activity = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
google-services-gradle = { group = "com.google.gms", name = "google-services", version.ref = "google-services-plugin" }
@@ -94,8 +97,6 @@ androidx = [
"androidx-lifecycle-viewmodel",
"androidx-fragment",
"androidx-lifecycle-runtime",
- "androidx-navigation-fragment-ktx",
- "androidx-navigation-ui-ktx",
]
compose = [
@@ -109,12 +110,14 @@ compose = [
"compose-material3-windowSizeClass",
"compose-ui-tooling-preview",
"compose-viewmodel",
- "compose-activity"
+ "compose-activity",
+ "compose-hilt"
]
[plugins]
android-application = { id = "com.android.application", version.ref = "gradleplugin" }
android-library = { id = "com.android.library", version.ref = "gradleplugin" }
+androidx-navigation-safeargs= { id = "androidx.navigation.safeargs", version.ref = "androidx-navigation"}
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
google-services = { id = "com.google.gms.google-services", version.ref = "google-services-plugin" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5ad1f456..28664dda 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,7 +21,7 @@ include(":core:domain")
include(":core:network")
include(":core:designsystem")
include(":core:designresource")
-include(":core:base")
+include(":core:common")
include(":core:model")
include(":feature")
include(":feature:auth")