Skip to content

Commit

Permalink
#7 서버연동 - 유저등록
Browse files Browse the repository at this point in the history
  • Loading branch information
MinseoSONG committed Nov 13, 2024
1 parent f1f4111 commit a531a0f
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 35 deletions.
36 changes: 36 additions & 0 deletions app/src/main/java/org/sopt/and/api/ApiFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.sopt.and.api

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.sopt.and.BuildConfig
import org.sopt.and.api.service.UserService
import retrofit2.Retrofit

object ApiFactory {
private const val BASE_URL: String = BuildConfig.BASE_URL

private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}

private val client = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()

val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
}

inline fun <reified T> create(): T = retrofit.create(T::class.java)
}

object ServicePool {
val userService = ApiFactory.create<UserService>()
}
10 changes: 10 additions & 0 deletions app/src/main/java/org/sopt/and/api/dto/ErrorDTO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.and.api.dto

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseErrorDto(
@SerialName("code")
val code: String
)
26 changes: 26 additions & 0 deletions app/src/main/java/org/sopt/and/api/dto/UserDTO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.sopt.and.api.dto

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseUserSuccessDto(
@SerialName("result")
val result: UserData
)

@Serializable
data class UserData(
@SerialName("no")
val no: Int
)

@Serializable
data class RequestUserDto(
@SerialName("username")
val username: String,
@SerialName("password")
val password: String,
@SerialName("hobby")
val hobby: String
)
14 changes: 14 additions & 0 deletions app/src/main/java/org/sopt/and/api/service/UserService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.api.service

import okhttp3.ResponseBody
import org.sopt.and.api.dto.RequestUserDto
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST

interface UserService {
@POST("/user")
fun postUser(
@Body requestUser: RequestUserDto
): Call<ResponseBody>
}
42 changes: 29 additions & 13 deletions app/src/main/java/org/sopt/and/ui/signup/SignUpScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ 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.material.MaterialTheme.colors
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
Expand Down Expand Up @@ -43,8 +44,11 @@ fun SignUpScreen(
var userPassWord by remember {
mutableStateOf("")
}
var userHobby by remember {
mutableStateOf("")
}
val context = LocalContext.current
signUpViewModel.initializePreferences(context)
// signUpViewModel.initializePreferences(context)

Column(
modifier = modifier
Expand Down Expand Up @@ -88,6 +92,13 @@ fun SignUpScreen(
InfoTextWithIcon(
text = stringResource(R.string.signup_password_explain)
)

IDTextField(
value = userHobby,
onValueChange = { userHobby = it },
modifier = Modifier.fillMaxWidth(),
placeholder = context.getString(R.string.signup_hobby)
)
}


Expand All @@ -98,18 +109,23 @@ fun SignUpScreen(
) {
Button(
onClick = {
if (signUpViewModel.isAbleEmail(userId) && signUpViewModel.isAblePassword(
userPassWord
)
) {
signUpViewModel.saveUserInfo(userId, userPassWord)
navController.popBackStack()
Toast.makeText(context, (R.string.signup_success), Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(context, (R.string.signup_fail), Toast.LENGTH_SHORT)
.show()
}
signUpViewModel.signUpUser(
username = userId,
password = userPassWord,
hobby = userHobby,
onSuccess = {
navController.popBackStack()
Toast.makeText(
context,
R.string.signup_success,
Toast.LENGTH_SHORT
).show()
},
onFailure = { errorMessage ->
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
}
)

},
modifier = Modifier
.fillMaxWidth()
Expand Down
97 changes: 75 additions & 22 deletions app/src/main/java/org/sopt/and/ui/signup/SignUpViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,34 +1,87 @@
package org.sopt.and.ui.signup

import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.ViewModel
import kotlinx.serialization.json.Json
import okhttp3.ResponseBody
import org.sopt.and.api.ServicePool
import org.sopt.and.api.dto.RequestUserDto
import org.sopt.and.api.dto.ResponseErrorDto
import org.sopt.and.api.dto.ResponseUserSuccessDto
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class SignUpViewModel: ViewModel() {
val PASSWORD_MIN_LENGTH = 8
val PASSWORD_MAX_LENGTH = 20
val PASSWORD_REGEX = Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@\$!%*?&])[A-Za-z\\d@\$!%*?&]{$PASSWORD_MIN_LENGTH,$PASSWORD_MAX_LENGTH}\$")
class SignUpViewModel : ViewModel() {
private val userService by lazy { ServicePool.userService }

var sharedPreferences: SharedPreferences? = null
// val PASSWORD_MIN_LENGTH = 8
// val PASSWORD_MAX_LENGTH = 20
// val PASSWORD_REGEX =
// Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@\$!%*?&])[A-Za-z\\d@\$!%*?&]{$PASSWORD_MIN_LENGTH,$PASSWORD_MAX_LENGTH}\$")

fun initializePreferences(context: Context){
sharedPreferences = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE)
}
// var sharedPreferences: SharedPreferences? = null
//
// fun initializePreferences(context: Context) {
// sharedPreferences = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE)
// }
//
// fun saveUserInfo(id: String, password: String) {
// sharedPreferences?.edit()?.apply() {
// putString("userId", id)
// putString("userPassWord", password)
// apply()
// }
// }

fun saveUserInfo(id: String, password: String){
sharedPreferences?.edit()?.apply(){
putString("userId", id)
putString("userPassWord", password)
apply()
}
}
// fun isAbleEmail(email: String): Boolean {
// return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()
// }
//
// fun isAblePassword(password: String): Boolean {
// return PASSWORD_REGEX.matches(password)
// }

fun isAbleEmail(email: String): Boolean{
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()
}
fun signUpUser(
username: String,
password: String,
hobby: String,
onSuccess: () -> Unit,
onFailure: (String) -> Unit
) {
val requestUserDto = RequestUserDto(username = username, password = password, hobby = hobby)

userService.postUser(requestUserDto).enqueue(object : Callback<ResponseBody> {
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
if (response.isSuccessful) {
val successBody = response.body()?.string()
val successDto = Json.decodeFromString<ResponseUserSuccessDto>(successBody ?: "")
onSuccess()
} else {
val errorBody = response.errorBody()?.string()
val errorDto = errorBody?.let { Json.decodeFromString<ResponseErrorDto>(it) }
val errorMessage = when (response.code()) {
400 -> when (errorDto?.code) {
"01" -> "닉네임, 비밀번호, 취미가 8자를 넘기면 안됩니다."
else -> "잘못된 요청입니다."
}
409 -> when (errorDto?.code) {
"00" -> "닉네임이 중복됩니다."
else -> "충돌이 발생했습니다."
}
else -> "알 수 없는 오류가 발생했습니다."
}
onFailure(errorMessage)
}
}

fun isAblePassword(password: String): Boolean{
return PASSWORD_REGEX.matches(password)
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
Log.e("SignUpViewModel", "Failure: ${t.message}")
}
})
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<string name="signup_id">[email protected]</string>
<string name="signup_id_explain">로그인, 비밀번호 찾기, 알림에 사용되니 정확한 이메일을 입력해주세요.</string>
<string name="signup_password">Wavve 비밀번호 설정</string>
<string name="signup_hobby">취미 설정</string>
<string name="signup_password_explain">비밀번호는 8-20자 이내로 영문 대소문자, 숫자, 특수문자 중 3가지 이상 혼용하여 입력해 주세요.</string>
<string name="signup_button">Wavve 회원가입</string>
<string name="signup_success">회원가입 성공</string>
Expand Down

0 comments on commit a531a0f

Please sign in to comment.