Skip to content

Commit

Permalink
[Feat] SignUp API 구현 (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
arinming committed May 3, 2024
1 parent bf28c1f commit 3094e49
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 71 deletions.
3 changes: 2 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization'
}

Properties properties = new Properties()
Expand Down Expand Up @@ -43,7 +44,7 @@ android {
buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.1'
kotlinCompilerExtensionVersion '1.5.5'
}
packagingOptions {
resources {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sopt.now.compose.data.model

data class SignInState(
val isSuccess: Boolean,
val message: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.sopt.now.compose.data.model

data class SignUpState(
val isSuccess: Boolean,
val message: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.sopt.now.compose.data.module

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.sopt.now.compose.BuildConfig
import com.sopt.now.compose.data.network.AuthService
import com.sopt.now.compose.data.network.FollowerService
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
Expand Down
30 changes: 3 additions & 27 deletions app/src/main/java/com/sopt/now/compose/ui/base/SoptAppNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,11 @@ import com.sopt.now.compose.ui.signUp.SignUpScreen
fun SoptAppNavHost() {
val navController: NavHostController = rememberNavController()

NavHost(navController = navController, startDestination = "login") {
composable(
"login?id={id}&pw={pw}&nickname={nickname}&mbti={mbti}", arguments = listOf(
navArgument("id") {
type = NavType.StringType
defaultValue = ""
},
navArgument("pw") {
type = NavType.StringType
defaultValue = ""
},
navArgument("nickname") {
type = NavType.StringType
defaultValue = ""
},
navArgument("mbti") {
type = NavType.StringType
defaultValue = ""
},
)
) { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
val pw = backStackEntry.arguments?.getString("pw")
val nickname = backStackEntry.arguments?.getString("nickname")
val mbti = backStackEntry.arguments?.getString("mbti")
NavHost(navController = navController, startDestination = "sign_in") {
composable("sign_in") {
LoginScreen(
onNavigateToHome = navController,
onNavigateToSignUp = { navController.navigate("signup") },
id.toString(), pw.toString(), nickname.toString(), mbti.toString()
)
}

Expand Down Expand Up @@ -75,7 +51,7 @@ fun SoptAppNavHost() {
MainScreen(id.toString(), pw.toString(), nickname.toString(), mbti.toString())
}
composable("signup") {
SignUpScreen(onNavigateToLogin = navController)
SignUpScreen(onNavigateToSignIn = navController)
}
}
}
10 changes: 1 addition & 9 deletions app/src/main/java/com/sopt/now/compose/ui/login/LoginScreen.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.sopt.now.compose.ui.login

import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -27,10 +26,6 @@ import com.sopt.now.compose.ui.base.SoptPasswordTextField
fun LoginScreen(
onNavigateToHome: NavHostController,
onNavigateToSignUp: () -> Unit,
id: String,
pw: String,
nickname: String,
mbti: String,
) {
Column(
modifier = Modifier.fillMaxSize(),
Expand Down Expand Up @@ -70,10 +65,7 @@ fun LoginScreen(
SoptOutlinedButton(
text = R.string.btn_login,
onClick = {
Log.d("Login", "$textId, $id")
if (textId == id && textPw == pw && isLoginButtonEnabled) {
onNavigateToHome.navigate("main?id=$textId&pw=$textPw&nickname=$nickname&mbti=$mbti")
}

},
enabled = true
)
Expand Down
73 changes: 41 additions & 32 deletions app/src/main/java/com/sopt/now/compose/ui/signUp/SignUpScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -26,18 +27,36 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.sopt.now.compose.R
import com.sopt.now.compose.data.model.RequestSignUpDto
import com.sopt.now.compose.ui.base.SoptInputTextField
import com.sopt.now.compose.ui.base.SoptOutlinedButton
import com.sopt.now.compose.ui.base.SoptPasswordTextField
import kotlinx.coroutines.launch

@Composable
fun SignUpScreen(
onNavigateToLogin: NavHostController,
onNavigateToSignIn: NavHostController,
signUpViewModel: SignUpViewModel = viewModel(),
) {
val context = LocalContext.current
val signUpState by signUpViewModel.signUpState.collectAsState()

var id by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var nickname by remember { mutableStateOf("") }
var phone by remember { mutableStateOf("") }

LaunchedEffect(signUpState) {
if (signUpState.isSuccess) {
Toast.makeText(context, signUpState.message, Toast.LENGTH_SHORT).show()
onNavigateToSignIn.navigate("sign_in")
} else if (signUpState.message.isNotBlank()) {
Toast.makeText(context, signUpState.message, Toast.LENGTH_SHORT).show()
}
}

Column(
modifier = Modifier.fillMaxSize(),
Expand All @@ -54,24 +73,11 @@ fun SignUpScreen(
}
}

var textId by remember {
mutableStateOf("")
}
var textPw by remember {
mutableStateOf("")
}
var textNickname by remember {
mutableStateOf("")
}
var textMbti by remember {
mutableStateOf("")
}

val isSignUpButtonEnabled by remember(textId, textPw, textNickname, textMbti) {
val isSignUpButtonEnabled by remember(id, password, nickname, phone) {
mutableStateOf(
textId.length in 6..10 && textPw.length in 8..12 && textNickname.isNotEmpty() && !textNickname.contains(
id.length in 6..10 && password.length in 8..12 && nickname.isNotEmpty() && !nickname.contains(
" "
) && textMbti.length == 4
) && phone.matches(Regex("^010-\\d{4}-\\d{4}\$"))
)
}

Expand All @@ -85,30 +91,33 @@ fun SignUpScreen(
item {
SoptInputTextField(
text = R.string.hint_id,
value = textId,
onValueChange = { textId = it })
value = id,
onValueChange = { id = it })
SoptPasswordTextField(
text = R.string.hint_pw,
value = textPw,
onValueChange = { textPw = it })
value = password,
onValueChange = { password = it })
SoptInputTextField(
text = R.string.hint_nickname,
value = textNickname,
onValueChange = { textNickname = it })
value = nickname,
onValueChange = { nickname = it })
SoptInputTextField(
text = R.string.hint_mbti,
value = textMbti,
onValueChange = { textMbti = it })
text = R.string.hint_phone,
value = phone,
onValueChange = { phone = it })
}
}
SoptOutlinedButton(text = R.string.btn_sign_up, onClick = {
if (isSignUpButtonEnabled) {
Toast.makeText(
context,
"회원가입 성공",
Toast.LENGTH_SHORT
).show()
onNavigateToLogin.navigate("login?id=$textId&pw=$textPw&nickname=$textNickname&mbti=$textMbti")
signUpViewModel.signUp(
RequestSignUpDto(
authenticationId = id,
password = password,
nickname = nickname,
phone = phone
)
)
onNavigateToSignIn.navigate("sign_in")
} else {
Toast.makeText(
context,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.sopt.now.compose.ui.signUp

import android.util.Log
import androidx.lifecycle.ViewModel
import com.sopt.now.compose.data.model.RequestSignUpDto
import com.sopt.now.compose.data.model.ResponseSignUpDto
import com.sopt.now.compose.data.model.SignUpState
import com.sopt.now.compose.data.module.ServicePool
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class SignUpViewModel : ViewModel() {
private val authService by lazy { ServicePool.authService }

private val _signUpState = MutableStateFlow(SignUpState(isSuccess = false, message = ""))
val signUpState = _signUpState.asStateFlow()

fun signUp(request: RequestSignUpDto) {
authService.signUp(request).enqueue(
object : Callback<ResponseSignUpDto> {
override fun onResponse(
call: Call<ResponseSignUpDto>,
response: Response<ResponseSignUpDto>,
) {
if (response.isSuccessful) {
val userId = response.headers()["location"]
_signUpState.update {
SignUpState(
isSuccess = true,
message = "가입된 유저 아이디는 $userId"
)
}
} else {
val error = response.code()
_signUpState.update {
SignUpState(
isSuccess = false,
message = "회원가입 실패 : $error"
)
}
}
}

override fun onFailure(call: Call<ResponseSignUpDto>, t: Throwable) {
_signUpState.update {
SignUpState(isSuccess = false, message = "서버 에러")
}
Log.d("SignUp", "${t.message}")
}
},
)
}
}
4 changes: 2 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<string name="label_id">ID</string>
<string name="label_pw">Password</string>
<string name="label_nickname">Nickname</string>
<string name="label_mbti">MBTI</string>
<string name="label_phone">전화번호</string>
<string name="btn_login">로그인</string>
<string name="btn_sign_up">회원가입</string>

Expand All @@ -15,7 +15,7 @@
<string name="hint_id">아이디를 입력해주세요.</string>
<string name="hint_pw">비밀번호를 입력해주세요.</string>
<string name="hint_nickname">닉네임을 입력해주세요.</string>
<string name="hint_mbti">MBTI를 입력해주세요.</string>
<string name="hint_phone">전화번호를 입력해주세요.</string>

<!-- Screen-->
<string name="screen_home">홈</string>
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ plugins {
id 'com.android.application' version '8.3.1' apply false
id 'com.android.library' version '8.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
id("org.jetbrains.kotlin.plugin.serialization") version "1.9.20" apply false
}

0 comments on commit 3094e49

Please sign in to comment.