Skip to content

Commit

Permalink
Merge pull request #118 from apeun-gidaechi/feature/109-create-email-…
Browse files Browse the repository at this point in the history
…sign-up

Feature/Create Email SignUp
  • Loading branch information
wnsgur1 authored Jun 20, 2024
2 parents 6cdf393 + 29aa678 commit 91ae93e
Show file tree
Hide file tree
Showing 25 changed files with 335 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<Result<EmailSignInModel>>
suspend fun getCode(email: String): Flow<Result<Int>>

suspend fun emailSignUp(name: String, email: String, password: String, code: String): Flow<Result<Int>>
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Result<EmailSignInModel>> {
return flow {
val e = datasource.emailSignIn(body).safeResponse()
Expand All @@ -29,4 +29,27 @@ class EmailSignInRepositoryImpl @Inject constructor(
.flowOn(dispatcher)
.asResult()
}

override suspend fun getCode(email: String): Flow<Result<Int>> {
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<Result<Int>> {
return flow {
val data = datasource.emailSignUp(
name = name,
email = email,
password = password,
code = code,
)
emit(data.status)
}
.flowOn(dispatcher)
.asResult()
}
}
2 changes: 2 additions & 0 deletions feature-onboarding/join/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ android {

dependencies {
implementation(projects.designsystem)
implementation(projects.data.emailSignIn)
implementation(projects.common)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -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
Expand All @@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -50,7 +66,7 @@ fun EmailVerificationScreen(navigateToSchoolCode: () -> Unit, popBackStack: () -
}

var dialogState by remember {
mutableStateOf(false)
mutableStateOf(Pair<String, String?>("", ""))
}
SeugiTheme {
LaunchedEffect(key1 = timeLeft) {
Expand All @@ -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())
Expand All @@ -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("", "")
},
)
}
Expand Down Expand Up @@ -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 = "인증 코드 전송",
Expand All @@ -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),
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
}
}
Loading

0 comments on commit 91ae93e

Please sign in to comment.