diff --git a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/EmailSignInRepository.kt b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/MemberRepository.kt similarity index 61% rename from data/email-sign-in/src/main/java/com/apeun/gidaechi/data/EmailSignInRepository.kt rename to data/email-sign-in/src/main/java/com/apeun/gidaechi/data/MemberRepository.kt index 91604d47..7cc4d36c 100644 --- a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/EmailSignInRepository.kt +++ b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/MemberRepository.kt @@ -5,6 +5,9 @@ import com.apeun.gidaechi.data.model.EmailSignInModel import com.apeun.gidaechi.network.request.EmailSignInRequest import kotlinx.coroutines.flow.Flow -interface EmailSignInRepository { +interface MemberRepository { suspend fun emailSignIn(body: EmailSignInRequest): Flow> + suspend fun getCode(email: String): Flow> + + suspend fun emailSignUp(name: String, email: String, password: String, code: String): Flow> } diff --git a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/EmailSignInRepositoryModule.kt b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/EmailSignInRepositoryModule.kt deleted file mode 100644 index 3687063a..00000000 --- a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/EmailSignInRepositoryModule.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.apeun.gidaechi.data.di - -import com.apeun.gidaechi.data.EmailSignInRepository -import com.apeun.gidaechi.data.repository.EmailSignInRepositoryImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -interface EmailSignInRepositoryModule { - - @Binds - @Singleton - fun provideEmailSignInRepository(emailSignInRepositoryImpl: EmailSignInRepositoryImpl): EmailSignInRepository -} diff --git a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/MemberRepositoryModule.kt b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/MemberRepositoryModule.kt new file mode 100644 index 00000000..1a9cdb0e --- /dev/null +++ b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/di/MemberRepositoryModule.kt @@ -0,0 +1,18 @@ +package com.apeun.gidaechi.data.di + +import com.apeun.gidaechi.data.MemberRepository +import com.apeun.gidaechi.data.repository.MemberRepositoryImpl +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +interface MemberRepositoryModule { + + @Binds + @Singleton + fun provideMemberRepository(memberRepositoryImpl: MemberRepositoryImpl): MemberRepository +} diff --git a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/EmailSignInRepositoryImpl.kt b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/MemberRepositoryImpl.kt similarity index 53% rename from data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/EmailSignInRepositoryImpl.kt rename to data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/MemberRepositoryImpl.kt index 22645e50..1c825745 100644 --- a/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/EmailSignInRepositoryImpl.kt +++ b/data/email-sign-in/src/main/java/com/apeun/gidaechi/data/repository/MemberRepositoryImpl.kt @@ -4,10 +4,10 @@ import com.apeun.gidaechi.common.model.Result import com.apeun.gidaechi.common.model.asResult import com.apeun.gidaechi.common.utiles.DispatcherType import com.apeun.gidaechi.common.utiles.SeugiDispatcher -import com.apeun.gidaechi.data.EmailSignInRepository +import com.apeun.gidaechi.data.MemberRepository import com.apeun.gidaechi.data.mapper.toModel import com.apeun.gidaechi.data.model.EmailSignInModel -import com.apeun.gidaechi.network.EmailSignInDatasource +import com.apeun.gidaechi.network.MemberDatasource import com.apeun.gidaechi.network.core.response.safeResponse import com.apeun.gidaechi.network.request.EmailSignInRequest import javax.inject.Inject @@ -16,10 +16,10 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn -class EmailSignInRepositoryImpl @Inject constructor( - private val datasource: EmailSignInDatasource, +class MemberRepositoryImpl @Inject constructor( + private val datasource: MemberDatasource, @SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher, -) : EmailSignInRepository { +) : MemberRepository { override suspend fun emailSignIn(body: EmailSignInRequest): Flow> { return flow { val e = datasource.emailSignIn(body).safeResponse() @@ -29,4 +29,27 @@ class EmailSignInRepositoryImpl @Inject constructor( .flowOn(dispatcher) .asResult() } + + override suspend fun getCode(email: String): Flow> { + return flow { + val data = datasource.getCode(email).status + emit(data) + } + .flowOn(dispatcher) + .asResult() + } + + override suspend fun emailSignUp(name: String, email: String, password: String, code: String): Flow> { + return flow { + val data = datasource.emailSignUp( + name = name, + email = email, + password = password, + code = code, + ) + emit(data.status) + } + .flowOn(dispatcher) + .asResult() + } } diff --git a/feature-onboarding/join/build.gradle.kts b/feature-onboarding/join/build.gradle.kts index 55115593..fe8b81ef 100644 --- a/feature-onboarding/join/build.gradle.kts +++ b/feature-onboarding/join/build.gradle.kts @@ -8,4 +8,6 @@ android { dependencies { implementation(projects.designsystem) + implementation(projects.data.emailSignIn) + implementation(projects.common) } \ No newline at end of file diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUp.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUpScreen.kt similarity index 80% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUp.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUpScreen.kt index fa5921aa..6815b5f5 100644 --- a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUp.kt +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailSignUpScreen.kt @@ -27,12 +27,12 @@ import com.apeun.gidaechi.designsystem.theme.SeugiTheme @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackStack: () -> Unit) { +internal fun EmailSignUpScreen(navigateToEmailVerification: (name: String, email: String, password: String) -> Unit, popBackStack: () -> Unit) { var nameText by remember { mutableStateOf("") } var emailText by remember { mutableStateOf("") } var pwText by remember { mutableStateOf("") } var pwCheckText by remember { mutableStateOf("") } - var error by remember { mutableStateOf(false) } + var error by remember { mutableStateOf("") } SeugiTheme { Scaffold( modifier = Modifier.fillMaxSize(), @@ -72,7 +72,7 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS placeholder = "이름을 입력해 주세요", modifier = Modifier.padding(vertical = 4.dp), ) - if (error) { + if (error == "blank_name") { Text( text = "이름을 입력해 주세요", style = MaterialTheme.typography.bodyLarge, @@ -101,9 +101,9 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS placeholder = "이메일을 입력해 주세요", modifier = Modifier.padding(vertical = 4.dp), ) - if (error) { + if (error == "blank_email" || error == "email_fomat_is_not") { Text( - text = "이메일을 입력해 주세요", + text = if (error == "blank_email") "이메일을 입력해주세요" else if (error == "email_fomat_is_not")"이메일 형식을 맞춰주세요" else "", style = MaterialTheme.typography.bodyLarge, color = Red500, modifier = Modifier.padding(start = 4.dp), @@ -129,7 +129,7 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS placeholder = "비밀번호를 입력해 주세요", modifier = Modifier.padding(vertical = 4.dp), ) - if (error) { + if (error == "blank_password") { Text( text = "비밀번호를 입력해 주세요", style = MaterialTheme.typography.bodyLarge, @@ -157,9 +157,9 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS placeholder = "비밀번호를 다시 입력해 주세요", modifier = Modifier.padding(vertical = 4.dp), ) - if (error) { + if (error == "different_password") { Text( - text = "비밀번호를 다시 입력해 주세요", + text = "비밀번호가 다릅니다", style = MaterialTheme.typography.bodyLarge, color = Red500, modifier = Modifier.padding(start = 4.dp), @@ -170,7 +170,21 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS Spacer(modifier = Modifier.weight(1f)) SeugiFullWidthButton( - onClick = navigateToEmailVerification, + onClick = { + error = errorCheck( + name = nameText, + email = emailText, + password = pwText, + checkPassword = pwCheckText, + ) + if (error == "success") { + navigateToEmailVerification( + nameText, + emailText, + pwText, + ) + } + }, type = ButtonType.Primary, text = "계속하기", modifier = Modifier @@ -180,3 +194,18 @@ internal fun EmailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackS } } } + +private fun errorCheck(name: String, email: String, password: String, checkPassword: String): String { + if (name.isEmpty()) { + return "blank_name" + } else if (email.isEmpty()) { + return "blank_email" + } else if (!email.contains("@") || email.split("@").size != 2 || email.split("@")[1].isEmpty()) { + return "email_fomat_is_not" + } else if (password.isEmpty()) { + return "blank_password" + } else if (password != checkPassword) { + return "different_password" + } + return "success" +} diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerification.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerificationScreen.kt similarity index 74% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerification.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerificationScreen.kt index 5872dbfe..8a1a8013 100644 --- a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerification.kt +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/EmailVerificationScreen.kt @@ -25,6 +25,8 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.apeun.gidaechi.designsystem.component.ButtonType import com.apeun.gidaechi.designsystem.component.SeugiButton import com.apeun.gidaechi.designsystem.component.SeugiDialog @@ -34,13 +36,27 @@ import com.apeun.gidaechi.designsystem.component.textfield.SeugiCodeTextField import com.apeun.gidaechi.designsystem.theme.Gray600 import com.apeun.gidaechi.designsystem.theme.Red500 import com.apeun.gidaechi.designsystem.theme.SeugiTheme +import com.apeun.gidaechi.model.EmailVerificationSideEffect +import com.apeun.gidaechi.viewModel.EmailVerificationViewModel import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest @OptIn(ExperimentalMaterial3Api::class) @Composable -fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () -> Unit) { +fun EmailVerificationScreen( + navigateToSchoolCode: () -> Unit, + popBackStack: () -> Unit, + viewModel: EmailVerificationViewModel = hiltViewModel(), + name: String, + email: String, + password: String, +) { var timeLeft by remember { mutableStateOf(0) } + val sideEffect: EmailVerificationSideEffect? by viewModel.sideEffect.collectAsStateWithLifecycle( + initialValue = null, + ) + val minutes = timeLeft / 60 val seconds = timeLeft % 60 val formattedTime = "%d분 %02d초 남음".format(minutes, seconds) @@ -50,7 +66,7 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () - } var dialogState by remember { - mutableStateOf(false) + mutableStateOf(Pair("", "")) } SeugiTheme { LaunchedEffect(key1 = timeLeft) { @@ -60,6 +76,28 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () - } verificationClick = false } + LaunchedEffect(key1 = Unit) { + viewModel.sideEffect.collectLatest { + when (it) { + is EmailVerificationSideEffect.SuccessGetCode -> { + dialogState = Pair("인증코드를 전송했어요", "이메일 함을 확인해 보세요") + verificationClick = true + timeLeft = 300 + } + + is EmailVerificationSideEffect.SuccessJoin -> { + } + + is EmailVerificationSideEffect.FiledJoin -> { + dialogState = Pair("인증코드가 올바르지 않습니다", null) + } + + is EmailVerificationSideEffect.Error -> { + dialogState = Pair("오류가 발생했습니다. 다시시도 해주세요", null) + } + } + } + } var verificationCode by remember { mutableStateOf(TextFieldValue()) @@ -84,12 +122,12 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () - ) }, ) { - if (dialogState) { + if (dialogState.first.isNotEmpty()) { SeugiDialog( - title = "인증코드를 전송했어요", - content = "이메일 함을 확인해 보세요", + title = dialogState.first, + content = dialogState.second ?: "", onDismissRequest = { - dialogState = false + dialogState = Pair("", "") }, ) } @@ -144,9 +182,7 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () - if (!verificationClick) { SeugiButton( onClick = { - verificationClick = true - timeLeft = 300 - dialogState = true + viewModel.getCode(email = email) }, type = ButtonType.Primary, text = "인증 코드 전송", @@ -163,8 +199,15 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () - Spacer(modifier = Modifier.weight(1f)) SeugiFullWidthButton( - enabled = if (verificationCode.text.length == 6) true else false, - onClick = navigateToSchoolCode, + enabled = verificationCode.text.length == 6, + onClick = { + viewModel.emailSignUp( + name = name, + email = email, + password = password, + code = verificationCode.text, + ) + }, type = ButtonType.Primary, text = "확인", modifier = Modifier.padding(vertical = 16.dp), diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/JoinSuccess.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/JoinSuccessScreen.kt similarity index 100% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/JoinSuccess.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/JoinSuccessScreen.kt diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/OAuthSignUp.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/OAuthSignUpScreen.kt similarity index 100% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/OAuthSignUp.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/OAuthSignUpScreen.kt diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/SchoolCode.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/SchoolCodeScreen.kt similarity index 100% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/SchoolCode.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/SchoolCodeScreen.kt diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/SelectingJob.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/SelectingJobScreen.kt similarity index 100% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/SelectingJob.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/SelectingJobScreen.kt diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/WaitingJoin.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/WaitingJoinScreen.kt similarity index 100% rename from feature-onboarding/join/src/main/java/com/apeun/gidaechi/WaitingJoin.kt rename to feature-onboarding/join/src/main/java/com/apeun/gidaechi/WaitingJoinScreen.kt diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/model/EmailVerificationSideEffect.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/model/EmailVerificationSideEffect.kt new file mode 100644 index 00000000..b32987ff --- /dev/null +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/model/EmailVerificationSideEffect.kt @@ -0,0 +1,8 @@ +package com.apeun.gidaechi.model + +sealed class EmailVerificationSideEffect { + data object SuccessGetCode : EmailVerificationSideEffect() + data object SuccessJoin : EmailVerificationSideEffect() + data object FiledJoin : EmailVerificationSideEffect() + data object Error : EmailVerificationSideEffect() +} diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailSignUpNavigation.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailSignUpNavigation.kt index 5faf594f..24385df0 100644 --- a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailSignUpNavigation.kt +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailSignUpNavigation.kt @@ -4,14 +4,18 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navigation import com.apeun.gidaechi.EmailSignUpScreen const val EMAIL_SIGN_UP_ROUTE = "emailSignUp" fun NavController.navigateToEmailSignUp(navOptions: NavOptions? = null) = navigate(EMAIL_SIGN_UP_ROUTE, navOptions) -fun NavGraphBuilder.emailSignUpScreen(navigateToEmailVerification: () -> Unit, popBackStack: () -> Unit) { +fun NavGraphBuilder.emailSignUpScreen(navigateToEmailVerification: (name: String, email: String, password: String) -> Unit, popBackStack: () -> Unit) { composable(route = EMAIL_SIGN_UP_ROUTE) { - EmailSignUpScreen(navigateToEmailVerification = navigateToEmailVerification, popBackStack = popBackStack) + EmailSignUpScreen( + navigateToEmailVerification = navigateToEmailVerification, + popBackStack = popBackStack, + ) } } diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailVerificationNavigation.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailVerificationNavigation.kt index 903d2e36..fb9d37b8 100644 --- a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailVerificationNavigation.kt +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/navigation/EmailVerificationNavigation.kt @@ -3,18 +3,31 @@ package com.apeun.gidaechi.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions +import androidx.navigation.NavType import androidx.navigation.compose.composable +import androidx.navigation.navArgument import com.apeun.gidaechi.EmailVerificationScreen const val EMAIL_VERIFICATION_ROUTE = "emailVerification" -fun NavController.navigateToEmailVerification(navOptions: NavOptions? = null) = navigate( - EMAIL_VERIFICATION_ROUTE, - navOptions, -) +fun NavController.navigateToEmailVerification(navOptions: NavOptions? = null, name: String, email: String, password: String) = + navigate("$EMAIL_VERIFICATION_ROUTE/$name/$email/$password", navOptions) fun NavGraphBuilder.emailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () -> Unit) { - composable(route = EMAIL_VERIFICATION_ROUTE) { - EmailVerificationScreen(navigateToSchoolCode = navigateToSchoolCode, popBackStack = popBackStack) + composable( + route = "$EMAIL_VERIFICATION_ROUTE/{name}/{email}/{password}", + arguments = listOf( + navArgument("name") { NavType.StringType }, + navArgument("email") { NavType.StringType }, + navArgument("password") { NavType.StringType }, + ), + ) { + EmailVerificationScreen( + navigateToSchoolCode = navigateToSchoolCode, + popBackStack = popBackStack, + name = it.arguments?.getString("name") ?: "", + email = it.arguments?.getString("email") ?: "", + password = it.arguments?.getString("password") ?: "", + ) } } diff --git a/feature-onboarding/join/src/main/java/com/apeun/gidaechi/viewModel/EmailVerificationViewModel.kt b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/viewModel/EmailVerificationViewModel.kt new file mode 100644 index 00000000..60c3a6c9 --- /dev/null +++ b/feature-onboarding/join/src/main/java/com/apeun/gidaechi/viewModel/EmailVerificationViewModel.kt @@ -0,0 +1,73 @@ +package com.apeun.gidaechi.viewModel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.apeun.gidaechi.common.model.Result +import com.apeun.gidaechi.common.utiles.DispatcherType +import com.apeun.gidaechi.common.utiles.SeugiDispatcher +import com.apeun.gidaechi.data.MemberRepository +import com.apeun.gidaechi.model.EmailVerificationSideEffect +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.launch + +@HiltViewModel +class EmailVerificationViewModel @Inject constructor( + private val memberRepository: MemberRepository, + @SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher, +) : ViewModel() { + private val _sideEffect = Channel() + val sideEffect = _sideEffect.receiveAsFlow() + + fun getCode(email: String) = viewModelScope.launch(dispatcher) { + memberRepository.getCode(email).collectLatest { + when (it) { + is Result.Success -> { + if (it.data == 200) { + _sideEffect.send(EmailVerificationSideEffect.SuccessGetCode) + } else { + _sideEffect.send(EmailVerificationSideEffect.Error) + } + } + + is Result.Error -> { + it.throwable.printStackTrace() + _sideEffect.send(EmailVerificationSideEffect.Error) + } + + is Result.Loading -> { + } + } + } + } + + fun emailSignUp(name: String, email: String, password: String, code: String) = viewModelScope.launch(dispatcher) { + memberRepository.emailSignUp( + name = name, + email = email, + password = password, + code = code, + ).collectLatest { + when (it) { + is Result.Success -> { + if (it.data == 200) { + _sideEffect.send(EmailVerificationSideEffect.SuccessJoin) + } else if (it.data == 400 || it.data == 404 || it.data == 409) { + _sideEffect.send(EmailVerificationSideEffect.FiledJoin) + } else { + _sideEffect.send(EmailVerificationSideEffect.Error) + } + } + is Result.Error -> { + _sideEffect.send(EmailVerificationSideEffect.Error) + } + is Result.Loading -> { + } + } + } + } +} diff --git a/feature-onboarding/login/src/main/java/com/apeun/gidaechi/login/EmailSignInVIewModel.kt b/feature-onboarding/login/src/main/java/com/apeun/gidaechi/login/EmailSignInVIewModel.kt index d74490c8..2a6955ee 100644 --- a/feature-onboarding/login/src/main/java/com/apeun/gidaechi/login/EmailSignInVIewModel.kt +++ b/feature-onboarding/login/src/main/java/com/apeun/gidaechi/login/EmailSignInVIewModel.kt @@ -3,12 +3,15 @@ package com.apeun.gidaechi.login import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.apeun.gidaechi.common.model.Result -import com.apeun.gidaechi.data.repository.EmailSignInRepositoryImpl +import com.apeun.gidaechi.common.utiles.DispatcherType +import com.apeun.gidaechi.common.utiles.SeugiDispatcher +import com.apeun.gidaechi.data.MemberRepository import com.apeun.gidaechi.login.model.EmailSignInSideEffect import com.apeun.gidaechi.login.model.EmailSignInState import com.apeun.gidaechi.network.request.EmailSignInRequest import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -17,7 +20,8 @@ import kotlinx.coroutines.launch @HiltViewModel class EmailSignInVIewModel @Inject constructor( - private val emailSignInRepositoryImpl: EmailSignInRepositoryImpl, + private val emailSignInRepository: MemberRepository, + @SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher, ) : ViewModel() { private val _state = MutableStateFlow(EmailSignInState()) @@ -27,8 +31,8 @@ class EmailSignInVIewModel @Inject constructor( val emailSignInSideEffect = _emailSignInSideEffect.receiveAsFlow() fun emailSignIn(email: String, password: String) { - viewModelScope.launch { - emailSignInRepositoryImpl.emailSignIn( + viewModelScope.launch(dispatcher) { + emailSignInRepository.emailSignIn( body = EmailSignInRequest( email = email, password = password, @@ -54,6 +58,7 @@ class EmailSignInVIewModel @Inject constructor( ), ) } + is Result.Loading -> {} } } diff --git a/feature-onboarding/onabording/src/main/java/com/apeun/gidaechi/OnboardingScreen.kt b/feature-onboarding/onabording/src/main/java/com/apeun/gidaechi/OnboardingScreen.kt index 78ff4bff..10afc33b 100644 --- a/feature-onboarding/onabording/src/main/java/com/apeun/gidaechi/OnboardingScreen.kt +++ b/feature-onboarding/onabording/src/main/java/com/apeun/gidaechi/OnboardingScreen.kt @@ -48,7 +48,13 @@ internal fun OnboardingScreen(navHostController: NavHostController = rememberNav popBackStack = { navHostController.popBackStack() }, ) emailSignUpScreen( - navigateToEmailVerification = { navHostController.navigateToEmailVerification() }, + navigateToEmailVerification = { name, email, password -> + navHostController.navigateToEmailVerification( + name = name, + email = email, + password = password, + ) + }, popBackStack = { navHostController.popBackStack() }, ) emailVerificationScreen( diff --git a/network/core/src/main/java/com/apeun/gidaechi/network/core/SeugiUrl.kt b/network/core/src/main/java/com/apeun/gidaechi/network/core/SeugiUrl.kt index 03c2c1d8..f8f2dca2 100644 --- a/network/core/src/main/java/com/apeun/gidaechi/network/core/SeugiUrl.kt +++ b/network/core/src/main/java/com/apeun/gidaechi/network/core/SeugiUrl.kt @@ -33,5 +33,7 @@ object SeugiUrl { object Auth { const val EMAIL_SIGN_IN = "$BASE_URL/member/login" + const val GET_CODE = "$BASE_URL/email/send?email=" + const val EMAIL_SIGN_UP = "$BASE_URL/member/register" } } diff --git a/network/core/src/main/java/com/apeun/gidaechi/network/core/response/Response.kt b/network/core/src/main/java/com/apeun/gidaechi/network/core/response/Response.kt new file mode 100644 index 00000000..44abc3ea --- /dev/null +++ b/network/core/src/main/java/com/apeun/gidaechi/network/core/response/Response.kt @@ -0,0 +1,11 @@ +package com.apeun.gidaechi.network.core.response + +import kotlinx.serialization.Serializable + +@Serializable +data class Response( + val message: String, + val status: Int, + val state: String, + val success: Boolean, +) diff --git a/network/sign-in/src/main/java/com/apeun/gidaechi/network/EmailSignInDatasource.kt b/network/sign-in/src/main/java/com/apeun/gidaechi/network/MemberDatasource.kt similarity index 57% rename from network/sign-in/src/main/java/com/apeun/gidaechi/network/EmailSignInDatasource.kt rename to network/sign-in/src/main/java/com/apeun/gidaechi/network/MemberDatasource.kt index fc2abcef..3d21bd8c 100644 --- a/network/sign-in/src/main/java/com/apeun/gidaechi/network/EmailSignInDatasource.kt +++ b/network/sign-in/src/main/java/com/apeun/gidaechi/network/MemberDatasource.kt @@ -1,9 +1,13 @@ package com.apeun.gidaechi.network import com.apeun.gidaechi.network.core.response.BaseResponse +import com.apeun.gidaechi.network.core.response.Response import com.apeun.gidaechi.network.request.EmailSignInRequest import com.apeun.gidaechi.network.response.EmailSignInResponse -interface EmailSignInDatasource { +interface MemberDatasource { suspend fun emailSignIn(body: EmailSignInRequest): BaseResponse + + suspend fun getCode(email: String): Response + suspend fun emailSignUp(name: String, email: String, password: String, code: String): Response } diff --git a/network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/EmailSignInDatasourceImpl.kt b/network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/MemberDatasourceImpl.kt similarity index 54% rename from network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/EmailSignInDatasourceImpl.kt rename to network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/MemberDatasourceImpl.kt index 5e57945f..c24c82d3 100644 --- a/network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/EmailSignInDatasourceImpl.kt +++ b/network/sign-in/src/main/java/com/apeun/gidaechi/network/datasource/MemberDatasourceImpl.kt @@ -2,23 +2,42 @@ package com.apeun.gidaechi.network.datasource import com.apeun.gidaechi.common.utiles.DispatcherType import com.apeun.gidaechi.common.utiles.SeugiDispatcher -import com.apeun.gidaechi.network.EmailSignInDatasource +import com.apeun.gidaechi.network.MemberDatasource import com.apeun.gidaechi.network.core.SeugiUrl import com.apeun.gidaechi.network.core.response.BaseResponse +import com.apeun.gidaechi.network.core.response.Response import com.apeun.gidaechi.network.request.EmailSignInRequest +import com.apeun.gidaechi.network.request.EmailSignUpRequest import com.apeun.gidaechi.network.response.EmailSignInResponse import io.ktor.client.HttpClient import io.ktor.client.call.body +import io.ktor.client.request.get import io.ktor.client.request.post import io.ktor.client.request.setBody import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -class EmailSignInDatasourceImpl @Inject constructor( +class MemberDatasourceImpl @Inject constructor( @SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher, private val httpClient: HttpClient, -) : EmailSignInDatasource { +) : MemberDatasource { override suspend fun emailSignIn(body: EmailSignInRequest): BaseResponse = httpClient.post("${SeugiUrl.Auth.EMAIL_SIGN_IN}") { setBody(body = body) }.body>() + + override suspend fun getCode(email: String): Response = httpClient.get("${SeugiUrl.Auth.GET_CODE}$email") { + }.body() + + override suspend fun emailSignUp(name: String, email: String, password: String, code: String): Response = httpClient.post( + "${SeugiUrl.Auth.EMAIL_SIGN_UP}", + ) { + setBody( + body = EmailSignUpRequest( + name = name, + email = email, + password = password, + code = code, + ), + ) + }.body() } diff --git a/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/EmailSignInDataourceModule.kt b/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/EmailSignInDataourceModule.kt deleted file mode 100644 index d9df6de9..00000000 --- a/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/EmailSignInDataourceModule.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.apeun.gidaechi.network.di - -import com.apeun.gidaechi.network.EmailSignInDatasource -import com.apeun.gidaechi.network.datasource.EmailSignInDatasourceImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -interface EmailSignInDataourceModule { - - @Binds - @Singleton - fun provideEmailSignInDataSource(emailSignInDatasourceImpl: EmailSignInDatasourceImpl): EmailSignInDatasource -} diff --git a/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/MemberDatasourceModule.kt b/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/MemberDatasourceModule.kt new file mode 100644 index 00000000..bb2fcf42 --- /dev/null +++ b/network/sign-in/src/main/java/com/apeun/gidaechi/network/di/MemberDatasourceModule.kt @@ -0,0 +1,18 @@ +package com.apeun.gidaechi.network.di + +import com.apeun.gidaechi.network.MemberDatasource +import com.apeun.gidaechi.network.datasource.MemberDatasourceImpl +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +interface MemberDatasourceModule { + + @Binds + @Singleton + fun provideMemberDataSource(memberDatasourceImpl: MemberDatasourceImpl): MemberDatasource +} diff --git a/network/sign-in/src/main/java/com/apeun/gidaechi/network/request/EmailSignUpRequest.kt b/network/sign-in/src/main/java/com/apeun/gidaechi/network/request/EmailSignUpRequest.kt new file mode 100644 index 00000000..d603e2be --- /dev/null +++ b/network/sign-in/src/main/java/com/apeun/gidaechi/network/request/EmailSignUpRequest.kt @@ -0,0 +1,11 @@ +package com.apeun.gidaechi.network.request + +import kotlinx.serialization.Serializable + +@Serializable +data class EmailSignUpRequest( + val name: String, + val email: String, + val password: String, + val code: String, +)