From cee8105bf7d8b8d0fe7d660a0c9ea9f10623e0fe Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 11 Nov 2024 20:53:34 +0900 Subject: [PATCH 01/20] =?UTF-8?q?#8=20[feat]=20:=20AndroidManifest=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=EB=84=B7=20=EA=B6=8C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e827a15..866f860 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + Date: Mon, 11 Nov 2024 21:01:27 +0900 Subject: [PATCH 02/20] =?UTF-8?q?#8=20[feat]=20:=20plugins=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 16 ++++++++++++++++ app/src/main/AndroidManifest.xml | 1 + gradle/libs.versions.toml | 12 +++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 537845c..a18a009 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,14 @@ +import java.util.Properties + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) +} + +val properties = Properties().apply { + load(project.rootProject.file("local.properties").inputStream()) } android { @@ -16,6 +23,7 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + buildConfigField("String", "BASE_URL", properties["base.url"].toString()) } buildTypes { @@ -36,10 +44,18 @@ android { } buildFeatures { compose = true + buildConfig = true } } dependencies { + // Network + implementation(platform(libs.okhttp.bom)) + implementation(libs.okhttp) + implementation(libs.okhttp.logging.interceptor) + implementation(libs.retrofit) + implementation(libs.retrofit.kotlin.serialization.converter) + implementation(libs.kotlinx.serialization.json) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 866f860..7dcf9b7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.ANDANDROID" + android:usesCleartextTraffic="true" tools:targetApi="31"> Date: Mon, 11 Nov 2024 21:54:12 +0900 Subject: [PATCH 03/20] =?UTF-8?q?#8=20[feat]=20:=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/data/ApiFactory.kt | 36 +++++++++++++++++++ .../data/model/dto/ResponseUserHobbyDto.kt | 17 +++++++++ .../data/model/dto/ResponseUserSignUpDto.kt | 17 +++++++++ .../data/model/dto/ResponseUserTokenDto.kt | 17 +++++++++ .../data/model/request/UserLoginRequest.kt | 13 +++++++ .../data/model/request/UserSignUpRequest.kt | 15 ++++++++ .../and/data/network/service/UserService.kt | 29 +++++++++++++++ 7 files changed, 144 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/data/ApiFactory.kt create mode 100644 app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt create mode 100644 app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt create mode 100644 app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt create mode 100644 app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt create mode 100644 app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt create mode 100644 app/src/main/java/org/sopt/and/data/network/service/UserService.kt diff --git a/app/src/main/java/org/sopt/and/data/ApiFactory.kt b/app/src/main/java/org/sopt/and/data/ApiFactory.kt new file mode 100644 index 0000000..4ad4168 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/ApiFactory.kt @@ -0,0 +1,36 @@ +package org.sopt.and.data + +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.data.network.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 create(): T = retrofit.create(T::class.java) +} + +object ServicePool { + val userService = ApiFactory.create() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt new file mode 100644 index 0000000..0d960e3 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt @@ -0,0 +1,17 @@ +package org.sopt.and.data.model.dto + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseUserHobbyDto( + @SerialName("result") + val result: Result +) { + @Serializable + data class Result( + @SerialName("hobby") + val hobby: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt new file mode 100644 index 0000000..142aaed --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt @@ -0,0 +1,17 @@ +package org.sopt.and.data.model.dto + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseUserSignUpDto( + @SerialName("result") + val result: Result +) { + @Serializable + data class Result( + @SerialName("no") + val no: Int + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt new file mode 100644 index 0000000..6735b18 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt @@ -0,0 +1,17 @@ +package org.sopt.and.data.model.dto + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseUserTokenDto( + @SerialName("result") + val result: Result +) { + @Serializable + data class Result( + @SerialName("token") + val token: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt b/app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt new file mode 100644 index 0000000..1c31bab --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt @@ -0,0 +1,13 @@ +package org.sopt.and.data.model.request + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserLoginRequest( + @SerialName("username") + val username: String, + @SerialName("password") + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt b/app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt new file mode 100644 index 0000000..fbe48f6 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt @@ -0,0 +1,15 @@ +package org.sopt.and.data.model.request + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserSignUpRequest( + @SerialName("username") + val username: String, + @SerialName("password") + val password: String, + @SerialName("hobby") + val hobby: String +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt new file mode 100644 index 0000000..33d76fd --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt @@ -0,0 +1,29 @@ +package org.sopt.and.data.network.service + +import org.sopt.and.data.model.dto.ResponseUserHobbyDto +import org.sopt.and.data.model.dto.ResponseUserSignUpDto +import org.sopt.and.data.model.dto.ResponseUserTokenDto +import org.sopt.and.data.model.request.UserLoginRequest +import org.sopt.and.data.model.request.UserSignUpRequest +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST + +interface UserService { + @POST("/user") + fun postUserSignUp( + @Body body: UserSignUpRequest + ): Call + + @POST("/login") + fun postUserLogin( + @Body body: UserLoginRequest + ): Call + + @GET("/user/my-hobby") + fun getUserHobby( + @Header("token") token: String, + ): Call +} \ No newline at end of file From ef08fbdd0cc174ec78a71f38e09ce41b2f2f36d9 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 00:31:19 +0900 Subject: [PATCH 04/20] =?UTF-8?q?#8=20[feat]=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/and/feature/signup/SignUpScreen.kt | 8 +++++ .../and/feature/signup/SignUpViewModel.kt | 36 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt index 06f78d4..f390b03 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt @@ -53,6 +53,7 @@ import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.ErrorDialog import org.sopt.and.core.designsystem.component.SocialLoginButtonGroup import org.sopt.and.core.designsystem.component.WavveSignUpButton +import org.sopt.and.data.model.request.UserSignUpRequest import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -220,6 +221,13 @@ fun SignUpScreen( localEmail = email, localPassword = password, onSuccess = { email, password -> + viewModel.postUserSignUp( + body = UserSignUpRequest( + username = "email", + password = "password", + hobby = "hobby" + ) + ) onSignUpSuccess(email, password) }, onFailure = { diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index 677cde5..486ad7a 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -1,7 +1,9 @@ package org.sopt.and.feature.signup import android.content.Context +import android.util.Log import android.util.Patterns +import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue @@ -11,9 +13,43 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R +import org.sopt.and.data.ServicePool +import org.sopt.and.data.model.dto.ResponseUserSignUpDto +import org.sopt.and.data.model.request.UserSignUpRequest import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class SignUpViewModel : ViewModel() { + private val userService by lazy { ServicePool.userService } + + private val _userState = mutableStateOf(null) + val userState: State get() = _userState + + fun postUserSignUp(body: UserSignUpRequest) { + userService.postUserSignUp( + body = body + ).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + _userState.value = response.body() + Log.d("postUserSignUp", response.body().toString()) + + } else { + val error = response.message() + Log.e("error", error.toString()) + } + } + override fun onFailure(call: Call, t: Throwable) { + Log.e("failure", t.message.toString()) + } + }) + } + private val _email = MutableLiveData("") val email: LiveData get() = _email From 1445650101047a4714674ad33b5e1d33ebece409 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 00:41:45 +0900 Subject: [PATCH 05/20] =?UTF-8?q?#8=20[feat]=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/feature/login/LoginScreen.kt | 7 ++++ .../sopt/and/feature/login/LoginViewModel.kt | 38 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index a150828..a039768 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -56,6 +56,7 @@ import org.sopt.and.R import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.SocialLoginButtonGroup import org.sopt.and.core.designsystem.component.WavveLoginButton +import org.sopt.and.data.model.request.UserLoginRequest import org.sopt.and.feature.main.Routes import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -187,6 +188,12 @@ fun LoginScreen( localEmail = localEmail, localPassword = localPassword, onSuccess = { email, password -> + viewModel.postUserLogin( + body = UserLoginRequest( + username = "email", + password = "password" + ) + ) onLoginSuccess(email, password) }, onFailure = { diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index 118dbb4..eb411d8 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -1,12 +1,50 @@ package org.sopt.and.feature.login +import android.util.Log +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch +import org.sopt.and.data.ServicePool +import org.sopt.and.data.model.dto.ResponseUserTokenDto +import org.sopt.and.data.model.request.UserLoginRequest +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class LoginViewModel : ViewModel() { + private val userService by lazy { ServicePool.userService } + + private val _userState = mutableStateOf(null) + val userState: State get() = _userState + + fun postUserLogin(body: UserLoginRequest) { + userService.postUserLogin( + body = body + ).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + _userState.value = response.body() + Log.d("postUserLogin", response.body().toString()) + + } else { + val error = response.message() + Log.e("error", error.toString()) + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("failure", t.message.toString()) + } + }) + } + private val _email = MutableLiveData("") val email: LiveData get() = _email From ac5a610c29defcc59e6b3481855e4c305cdd1675 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 01:28:35 +0900 Subject: [PATCH 06/20] =?UTF-8?q?#8=20[feat]=20:=20=EC=B7=A8=EB=AF=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/feature/login/LoginScreen.kt | 8 ++++- .../sopt/and/feature/login/LoginViewModel.kt | 6 ++-- .../org/sopt/and/feature/mypage/MyScreen.kt | 7 +++- .../sopt/and/feature/mypage/MyViewModel.kt | 36 +++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index a039768..ffc1848 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -1,5 +1,6 @@ package org.sopt.and.feature.login +import android.content.Context import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -73,6 +74,8 @@ fun LoginScreen( val context = LocalContext.current val focusManager = LocalFocusManager.current val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher + val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) + val editor = sharedPreferences.edit() val scope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } @@ -193,7 +196,10 @@ fun LoginScreen( username = "email", password = "password" ) - ) + ) { body -> + editor.putString("loginToken", body!!.result.token) + editor.apply() + } onLoginSuccess(email, password) }, onFailure = { diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index eb411d8..4ef6d34 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -21,7 +21,7 @@ class LoginViewModel : ViewModel() { private val _userState = mutableStateOf(null) val userState: State get() = _userState - fun postUserLogin(body: UserLoginRequest) { + fun postUserLogin(body: UserLoginRequest, callback: (ResponseUserTokenDto?) -> Unit) { userService.postUserLogin( body = body ).enqueue(object : Callback { @@ -31,16 +31,18 @@ class LoginViewModel : ViewModel() { ) { if (response.isSuccessful) { _userState.value = response.body() - Log.d("postUserLogin", response.body().toString()) + callback(response.body()) } else { val error = response.message() Log.e("error", error.toString()) + callback(null) } } override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) + callback(null) } }) } diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt index e7b38f7..1ce4151 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt @@ -1,5 +1,6 @@ package org.sopt.and.feature.mypage +import android.content.Context import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -33,10 +34,14 @@ fun MyScreen( viewModel: MyViewModel = viewModel() ) { val context = LocalContext.current + val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) + val token = sharedPreferences.getString("loginToken", "none") ?: "none" + val snackbarHostState = remember { SnackbarHostState() } LaunchedEffect(Unit) { snackbarHostState.showSnackbar(context.getString(R.string.welcome)) + viewModel.getUserHobby(token = token) } Scaffold( @@ -56,7 +61,7 @@ fun MyScreen( Column { //프로필 박스 ProfileBox( - userEmail = localEmail.ifEmpty { DEFAULT_NAME }, + userEmail = viewModel.userState.value?.result?.hobby ?: DEFAULT_NAME, modifier = Modifier ) diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index bc7b9ce..1819462 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -1,10 +1,46 @@ package org.sopt.and.feature.mypage +import android.util.Log +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import org.sopt.and.data.ServicePool +import org.sopt.and.data.model.dto.ResponseUserHobbyDto +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class MyViewModel : ViewModel() { + private val userService by lazy { ServicePool.userService } + + private val _userState = mutableStateOf(null) + val userState: State get() = _userState + + fun getUserHobby(token: String) { + userService.getUserHobby(token = token) + .enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + _userState.value = response.body() + Log.d("getUserHobby", response.body().toString()) + + } else { + val error = response.message() + Log.e("error", error.toString()) + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("failure", t.message.toString()) + } + }) + } + private var _userEmail = MutableLiveData("") val userEmail: LiveData get() = _userEmail From 381a434c3c220c54fd8b7e1fa9f4bec73731a51e Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 16:38:27 +0900 Subject: [PATCH 07/20] =?UTF-8?q?#8=20[feat]=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=B7=A8=EB=AF=B8=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../designsystem/component/CustomDialog.kt | 1 + .../sopt/and/feature/signup/SignUpScreen.kt | 69 ++++++++++++------- .../and/feature/signup/SignUpViewModel.kt | 54 ++++++++++----- app/src/main/res/values/strings.xml | 14 ++-- 4 files changed, 92 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt index 198c05b..bb5ea7c 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt +++ b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt @@ -23,6 +23,7 @@ fun ErrorDialog( onClick: () -> Unit, isEmailError: String, isPasswordError: String, + isHobbyError: String, modifier: Modifier = Modifier ) { Dialog( diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt index f390b03..665627e 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt @@ -51,7 +51,6 @@ import androidx.navigation.NavController import org.sopt.and.R import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.ErrorDialog -import org.sopt.and.core.designsystem.component.SocialLoginButtonGroup import org.sopt.and.core.designsystem.component.WavveSignUpButton import org.sopt.and.data.model.request.UserSignUpRequest import org.sopt.and.ui.theme.WavveTheme @@ -68,8 +67,10 @@ fun SignUpScreen( val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher val context = LocalContext.current - val email by viewModel.email.observeAsState("") + val userName by viewModel.userName.observeAsState("") val password by viewModel.password.observeAsState("") + val hobby by viewModel.hobby.observeAsState("") + val showPassword = remember { mutableStateOf(false) } val showDialog by viewModel.showDialog.observeAsState(false) @@ -141,17 +142,16 @@ fun SignUpScreen( Spacer(modifier = Modifier.height(20.dp)) - //이메일 AuthTextField( modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp), - value = email, + value = userName, onValueChange = { - viewModel.setEmail(it) - viewModel.validateInputs(email, password, context) //검증 + viewModel.setUserName(it) + viewModel.validateInputs(userName, password, hobby, context) //검증 }, - placeholder = stringResource(R.string.placeholder_email), + placeholder = stringResource(R.string.placeholder_user_name), keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Email, imeAction = ImeAction.Next @@ -159,12 +159,12 @@ fun SignUpScreen( keyboardActions = KeyboardActions( onNext = { focusManager.moveFocus(FocusDirection.Next) } ), - isError = viewModel.emailErrorMsg.isNotEmpty(), + isError = viewModel.nameErrorMsg.isNotEmpty(), ) Spacer(modifier = Modifier.height(10.dp)) - WavveToolTip(stringResource(R.string.helper_text_email)) + WavveToolTip(stringResource(R.string.helper_text_user_name)) Spacer(modifier = Modifier.height(20.dp)) @@ -175,7 +175,7 @@ fun SignUpScreen( value = password, onValueChange = { viewModel.setPassword(it) - viewModel.validateInputs(email, password, context) //검증 + viewModel.validateInputs(userName, password, hobby, context) //검증 }, placeholder = stringResource(R.string.placeholder_password), suffix = { @@ -191,12 +191,10 @@ fun SignUpScreen( }, keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Password, - imeAction = ImeAction.Done + imeAction = ImeAction.Next ), keyboardActions = KeyboardActions( - onDone = { - focusManager.clearFocus() - } + onNext = { focusManager.moveFocus(FocusDirection.Next) } ), visualTransformation = if (showPassword.value) VisualTransformation.None else PasswordVisualTransformation(), isError = viewModel.passwordErrorMsg.isNotEmpty() @@ -206,29 +204,49 @@ fun SignUpScreen( WavveToolTip(stringResource(R.string.helper_text_password)) - Spacer(modifier = Modifier.height(50.dp)) + Spacer(modifier = Modifier.height(20.dp)) - SocialLoginButtonGroup( - stringResource(R.string.social_description_2), - modifier = Modifier.padding(horizontal = 20.dp) + AuthTextField( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp), + value = hobby, + onValueChange = { + viewModel.setHobby(it) + }, + placeholder = stringResource(R.string.placeholder_hobby), + keyboardOptions = KeyboardOptions.Default.copy( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Done + ), + keyboardActions = KeyboardActions( + onDone = { + focusManager.clearFocus() + } + ), ) + Spacer(modifier = Modifier.height(10.dp)) + + WavveToolTip(stringResource(R.string.helper_text_hobby)) + Spacer(modifier = Modifier.weight(1f)) WavveSignUpButton( onClick = { viewModel.onSignUpClick( - localEmail = email, + localName = userName, localPassword = password, - onSuccess = { email, password -> + localHobby = hobby, + onSuccess = { userName, password, hobby -> viewModel.postUserSignUp( body = UserSignUpRequest( - username = "email", - password = "password", - hobby = "hobby" + username = userName, + password = password, + hobby = hobby ) ) - onSignUpSuccess(email, password) + onSignUpSuccess(userName, password) }, onFailure = { viewModel.setDialogState(true) @@ -246,8 +264,9 @@ fun SignUpScreen( onClick = { viewModel.setDialogState(false) }, - isEmailError = viewModel.emailErrorMsg, + isEmailError = viewModel.nameErrorMsg, isPasswordError = viewModel.passwordErrorMsg, + isHobbyError = viewModel.hobbyErrorMsg, modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(20.dp)) diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index 486ad7a..d8fed0c 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -2,7 +2,6 @@ package org.sopt.and.feature.signup import android.content.Context import android.util.Log -import android.util.Patterns import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -44,55 +43,72 @@ class SignUpViewModel : ViewModel() { Log.e("error", error.toString()) } } + override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) } }) } - private val _email = MutableLiveData("") - val email: LiveData get() = _email + private val _userName = MutableLiveData("") + val userName: LiveData get() = _userName private val _password = MutableLiveData("") val password: LiveData get() = _password - var emailErrorMsg by mutableStateOf("") + private val _hobby = MutableLiveData("") + val hobby: LiveData get() = _hobby + + var nameErrorMsg by mutableStateOf("") var passwordErrorMsg by mutableStateOf("") + var hobbyErrorMsg by mutableStateOf("") + private val _showDialog = MutableLiveData(false) val showDialog: LiveData get() = _showDialog private val regex = Regex(PASSWORD_PATTERN) - fun setEmail(newEmail: String) { - _email.value = newEmail + fun setUserName(newName: String) { + _userName.value = newName } fun setPassword(newPassword: String) { _password.value = newPassword } + fun setHobby(newHobby: String) { + _hobby.value = newHobby + } + fun setDialogState(dialogState: Boolean) { _showDialog.value = dialogState } fun onSignUpClick( - localEmail: String, + localName: String, localPassword: String, - onSuccess: (String, String) -> Unit, + localHobby: String, + onSuccess: (String, String, String) -> Unit, onFailure: () -> Unit, context: Context ) { viewModelScope.launch { - validateInputs(email = localEmail, password = localPassword, context = context) //검증 - if (emailErrorMsg.isEmpty() && passwordErrorMsg.isEmpty()) { + validateInputs( + name = localName, + password = localPassword, + hobby = localHobby, + context = context + ) //검증 + if (nameErrorMsg.isEmpty() && passwordErrorMsg.isEmpty() && hobbyErrorMsg.isEmpty()) { setDialogState(false) //회원가입 정보 저장 - setEmail(localEmail) + setUserName(localName) setPassword(localPassword) - onSuccess(email.value!!, password.value!!) + setHobby(localHobby) + onSuccess(userName.value!!, password.value!!, hobby.value!!) } else { onFailure() } @@ -100,18 +116,24 @@ class SignUpViewModel : ViewModel() { } // 이메일 및 비밀번호 검증 함수 - fun validateInputs(email: String, password: String, context: Context) { - emailErrorMsg = if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) { - context.getString(R.string.invalid_email_address) + fun validateInputs(name: String, password: String, hobby: String, context: Context) { + nameErrorMsg = if (name.length > 8) { + context.getString(R.string.invalid_user_name) } else { "" } - passwordErrorMsg = if (!isValidPassword(password)) { + passwordErrorMsg = if (password.length > 8) { context.getString(R.string.invalid_password) } else { "" } + + hobbyErrorMsg = if (hobby.length > 8) { + context.getString(R.string.invalid_hobby) + } else { + "" + } } //비밀번호 검증 함수 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9d622eb..12abd1b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,18 +20,22 @@ 비밀번호 재설정 또는 다른 서비스 계정으로 로그인 SNS계정으로 간편하게 가입하여 서비스를 이용하실 수 있습니다.\n기존 POOQ 계정 또는 Wavve 계정과는 연동되지 않으니 이용에 참고하세요 - wavve@example.com + Wavve 사용자 이름 설정 Wavve 비밀번호 설정 - 비밀번호는 8~20자 이내로 영문 대소문자, 숫자, 특수문자 중 3가지 이상 혼용하여 입력해 주세요. - 로그인, 비밀번호 찾기, 알림에 사용되니 정확한 이메일을 입력해주세요. + 비밀번호는 8자 이하로 입력해 주세요. + 사용자 이름은 8자 이하로 입력해 주세요. 또는 다른 서비스 계정으로 가입 이메일과 비밀번호 만으로 Wavve를 즐길 수 있어요! 로그인에 실패했습니다. - 유효한 이메일 형식이 아닙니다. - 비밀번호는 8~20자 이내로 영문 대소문자, 숫자, 특수문자 중 3가지 이상 혼용해야 합니다. + 사용자 이름은 8자 이하여야 합니다. + 비밀번호는 8자 이하여야 합니다. + 취미는 8자 이하여야 합니다. + 취미는 8자 이하로 입력해 주세요. + Wavve 사용자 취미 설정 + 환영합니다! From d1497cd455e5048c128f238963b863b3db37b818 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 16:47:44 +0900 Subject: [PATCH 08/20] =?UTF-8?q?#8=20[chore]=20:=20ErrorDialog=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/designsystem/component/CustomDialog.kt | 14 +++++++++++++- .../org/sopt/and/feature/signup/SignUpScreen.kt | 6 ++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt index bb5ea7c..e1337ca 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt +++ b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt @@ -41,9 +41,21 @@ fun ErrorDialog( textAlign = TextAlign.Center, color = Color.Black, text = when { - isEmailError.isNotEmpty() && isPasswordError.isNotEmpty() -> "$isEmailError\n$isPasswordError" + isEmailError.isNotEmpty() && isPasswordError.isNotEmpty() && isHobbyError.isNotEmpty() -> + "$isEmailError\n$isPasswordError\n$isHobbyError" + + isEmailError.isNotEmpty() && isPasswordError.isNotEmpty() -> + "$isEmailError\n$isPasswordError" + + isEmailError.isNotEmpty() && isHobbyError.isNotEmpty() -> + "$isEmailError\n$isHobbyError" + + isPasswordError.isNotEmpty() && isHobbyError.isNotEmpty() -> + "$isPasswordError\n$isHobbyError" + isEmailError.isNotEmpty() -> isEmailError isPasswordError.isNotEmpty() -> isPasswordError + isHobbyError.isNotEmpty() -> isHobbyError else -> "" } ) diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt index 665627e..c7e4c38 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt @@ -149,7 +149,7 @@ fun SignUpScreen( value = userName, onValueChange = { viewModel.setUserName(it) - viewModel.validateInputs(userName, password, hobby, context) //검증 + viewModel.validateInputs(userName, password, hobby, context) }, placeholder = stringResource(R.string.placeholder_user_name), keyboardOptions = KeyboardOptions.Default.copy( @@ -175,7 +175,7 @@ fun SignUpScreen( value = password, onValueChange = { viewModel.setPassword(it) - viewModel.validateInputs(userName, password, hobby, context) //검증 + viewModel.validateInputs(userName, password, hobby, context) }, placeholder = stringResource(R.string.placeholder_password), suffix = { @@ -213,6 +213,7 @@ fun SignUpScreen( value = hobby, onValueChange = { viewModel.setHobby(it) + viewModel.validateInputs(userName, password, hobby, context) }, placeholder = stringResource(R.string.placeholder_hobby), keyboardOptions = KeyboardOptions.Default.copy( @@ -224,6 +225,7 @@ fun SignUpScreen( focusManager.clearFocus() } ), + isError = viewModel.hobbyErrorMsg.isNotEmpty(), ) Spacer(modifier = Modifier.height(10.dp)) From 1ed9d9630941536833b2a7729b0730ca3926f9a4 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 16:57:29 +0900 Subject: [PATCH 09/20] =?UTF-8?q?#8=20[chore]=20:=20email=20->=20userName?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/feature/login/LoginScreen.kt | 18 +++++++++--------- .../sopt/and/feature/login/LoginViewModel.kt | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index ffc1848..cd11a46 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -80,7 +80,7 @@ fun LoginScreen( val scope = rememberCoroutineScope() val snackbarHostState = remember { SnackbarHostState() } - val email by viewModel.email.observeAsState("") + val userName by viewModel.userName.observeAsState("") val password by viewModel.password.observeAsState("") val showPassword = remember { mutableStateOf(false) } @@ -135,11 +135,11 @@ fun LoginScreen( AuthTextField( modifier = Modifier .fillMaxWidth(), - value = email, + value = userName, onValueChange = { - viewModel.setEmail(it) + viewModel.setUserName(it) }, - placeholder = stringResource(R.string.email_or_id), + placeholder = stringResource(R.string.placeholder_user_name), keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Email, imeAction = ImeAction.Next @@ -188,19 +188,19 @@ fun LoginScreen( WavveLoginButton( onClick = { viewModel.onLoginClick( - localEmail = localEmail, + localName = localEmail, localPassword = localPassword, - onSuccess = { email, password -> + onSuccess = { userName, password -> viewModel.postUserLogin( body = UserLoginRequest( - username = "email", - password = "password" + username = userName, + password = password ) ) { body -> editor.putString("loginToken", body!!.result.token) editor.apply() } - onLoginSuccess(email, password) + onLoginSuccess(userName, password) }, onFailure = { scope.launch { diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index 4ef6d34..4d5301e 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -47,15 +47,15 @@ class LoginViewModel : ViewModel() { }) } - private val _email = MutableLiveData("") - val email: LiveData get() = _email + private val _userName = MutableLiveData("") + val userName: LiveData get() = _userName private val _password = MutableLiveData("") val password: LiveData get() = _password - fun setEmail(newEmail: String) { - _email.value = newEmail + fun setUserName(newName: String) { + _userName.value = newName } fun setPassword(newPassword: String) { @@ -63,15 +63,15 @@ class LoginViewModel : ViewModel() { } fun onLoginClick( - localEmail: String, + localName: String, localPassword: String, onSuccess: (String, String) -> Unit, onFailure: () -> Unit ) { viewModelScope.launch { - if (email.value == localEmail && password.value == localPassword) { + if (userName.value == localName && password.value == localPassword) { //로그인 성공 - onSuccess(email.value!!, password.value!!) + onSuccess(userName.value!!, password.value!!) } else { onFailure() } From e087cb2141b670a1008aec2d0aa08b7acdc05b76 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 17:18:54 +0900 Subject: [PATCH 10/20] =?UTF-8?q?#8=20[del]=20:=20local=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/sopt/and/feature/login/LoginScreen.kt | 11 +---------- .../org/sopt/and/feature/login/LoginViewModel.kt | 8 -------- .../main/java/org/sopt/and/feature/main/NavGraph.kt | 12 ++---------- .../java/org/sopt/and/feature/mypage/MyScreen.kt | 1 - 4 files changed, 3 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index cd11a46..de6351f 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -65,8 +65,6 @@ import org.sopt.and.utils.noRippleClickable @OptIn(ExperimentalMaterial3Api::class) @Composable fun LoginScreen( - localEmail: String, - localPassword: String, navController: NavController, onLoginSuccess: (String, String) -> Unit, viewModel: LoginViewModel = viewModel() @@ -188,25 +186,18 @@ fun LoginScreen( WavveLoginButton( onClick = { viewModel.onLoginClick( - localName = localEmail, - localPassword = localPassword, onSuccess = { userName, password -> viewModel.postUserLogin( body = UserLoginRequest( username = userName, password = password - ) + ), ) { body -> editor.putString("loginToken", body!!.result.token) editor.apply() } onLoginSuccess(userName, password) }, - onFailure = { - scope.launch { - snackbarHostState.showSnackbar(context.getString(R.string.fail_to_login)) - } - } ) //키보드 내리기 diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index 4d5301e..58136c0 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -63,18 +63,10 @@ class LoginViewModel : ViewModel() { } fun onLoginClick( - localName: String, - localPassword: String, onSuccess: (String, String) -> Unit, - onFailure: () -> Unit ) { viewModelScope.launch { - if (userName.value == localName && password.value == localPassword) { - //로그인 성공 onSuccess(userName.value!!, password.value!!) - } else { - onFailure() - } } } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt index caaf3dd..8b44d76 100644 --- a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt @@ -25,9 +25,6 @@ fun NavGraph( navController: NavHostController, modifier: Modifier = Modifier, ) { - var localEmail by remember { mutableStateOf("") } - var localPassword by remember { mutableStateOf("") } - NavHost( navController = navController, startDestination = Routes.Login.screen, @@ -35,10 +32,8 @@ fun NavGraph( ) { composable(Routes.Login.screen) { LoginScreen( - localEmail = localEmail, - localPassword = localPassword, navController = navController, - onLoginSuccess = { email, password -> + onLoginSuccess = { name, password -> navController.navigate(Routes.Home.screen) { popUpTo(Routes.Home.screen) { inclusive = true } } @@ -49,9 +44,7 @@ fun NavGraph( composable(Routes.SignUp.screen) { SignUpScreen( navController = navController, - onSignUpSuccess = { email, password -> - localEmail = email - localPassword = password + onSignUpSuccess = { name, password -> navController.navigate(Routes.Login.screen) { popUpTo(Routes.Login.screen) { inclusive = true } } @@ -68,7 +61,6 @@ fun NavGraph( composable(Routes.My.screen) { MyScreen( navController = navController, - localEmail = localEmail, viewModel = MyViewModel() ) } diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt index 1ce4151..e7dda2b 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt @@ -30,7 +30,6 @@ import org.sopt.and.utils.AuthKey.DEFAULT_NAME @Composable fun MyScreen( navController: NavController, - localEmail: String, viewModel: MyViewModel = viewModel() ) { val context = LocalContext.current From 09cb79217b4a22673cb914d8b89e47d1abb0af09 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 12 Nov 2024 18:48:21 +0900 Subject: [PATCH 11/20] =?UTF-8?q?#8=20[feat]=20:=20toast=20util=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/org/sopt/and/utils/ContextExt.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/utils/ContextExt.kt diff --git a/app/src/main/java/org/sopt/and/utils/ContextExt.kt b/app/src/main/java/org/sopt/and/utils/ContextExt.kt new file mode 100644 index 0000000..03e60c6 --- /dev/null +++ b/app/src/main/java/org/sopt/and/utils/ContextExt.kt @@ -0,0 +1,8 @@ +package org.sopt.and.utils + +import android.content.Context +import android.widget.Toast + +fun Context.toast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() +} \ No newline at end of file From a61fc26539f1c2ca778354a67d8d39fe730f7135 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Thu, 14 Nov 2024 21:00:08 +0900 Subject: [PATCH 12/20] =?UTF-8?q?#8=20[feat]=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=B7=A8=EB=AF=B8=20=EB=9D=84=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/feature/mypage/MyScreen.kt | 10 +++++++--- .../java/org/sopt/and/feature/mypage/MyViewModel.kt | 10 ++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt index e7dda2b..c63337f 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt @@ -13,6 +13,8 @@ import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -25,7 +27,6 @@ import org.sopt.and.core.designsystem.component.EmptyBox import org.sopt.and.core.designsystem.component.ProfileBox import org.sopt.and.core.designsystem.component.TicketBox import org.sopt.and.ui.theme.WavveTheme -import org.sopt.and.utils.AuthKey.DEFAULT_NAME @Composable fun MyScreen( @@ -36,11 +37,14 @@ fun MyScreen( val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) val token = sharedPreferences.getString("loginToken", "none") ?: "none" + viewModel.getUserHobby(token = token) + + val hobby by viewModel.hobby.observeAsState("") + val snackbarHostState = remember { SnackbarHostState() } LaunchedEffect(Unit) { snackbarHostState.showSnackbar(context.getString(R.string.welcome)) - viewModel.getUserHobby(token = token) } Scaffold( @@ -60,7 +64,7 @@ fun MyScreen( Column { //프로필 박스 ProfileBox( - userEmail = viewModel.userState.value?.result?.hobby ?: DEFAULT_NAME, + userEmail = hobby, modifier = Modifier ) diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index 1819462..ff8679a 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -18,6 +18,9 @@ class MyViewModel : ViewModel() { private val _userState = mutableStateOf(null) val userState: State get() = _userState + private val _hobby = MutableLiveData("") + val hobby: LiveData get() = _hobby + fun getUserHobby(token: String) { userService.getUserHobby(token = token) .enqueue(object : Callback { @@ -27,6 +30,7 @@ class MyViewModel : ViewModel() { ) { if (response.isSuccessful) { _userState.value = response.body() + _hobby.value = response.body()?.result?.hobby Log.d("getUserHobby", response.body().toString()) } else { @@ -41,10 +45,4 @@ class MyViewModel : ViewModel() { }) } - private var _userEmail = MutableLiveData("") - val userEmail: LiveData get() = _userEmail - - fun setUserEmail(userEmail: String) { - _userEmail.value = userEmail - } } \ No newline at end of file From a29a3e11448a80af521398e66782b63b48933f18 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Thu, 14 Nov 2024 21:45:47 +0900 Subject: [PATCH 13/20] =?UTF-8?q?#8=20[feat]=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20=EC=95=88=EB=82=B4?= =?UTF-8?q?=20=ED=86=A0=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/sopt/and/feature/main/NavGraph.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt index 8b44d76..20e4861 100644 --- a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt @@ -1,14 +1,17 @@ package org.sopt.and.feature.main import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect 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.platform.LocalContext import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import org.sopt.and.R import org.sopt.and.feature.home.HomeScreen import org.sopt.and.feature.home.HomeViewModel import org.sopt.and.feature.login.LoginScreen @@ -19,17 +22,29 @@ import org.sopt.and.feature.search.SearchScreen import org.sopt.and.feature.search.SearchViewModel import org.sopt.and.feature.signup.SignUpScreen import org.sopt.and.feature.signup.SignUpViewModel +import org.sopt.and.utils.toast @Composable fun NavGraph( navController: NavHostController, modifier: Modifier = Modifier, ) { + val context = LocalContext.current + var isLoggedIn by remember { mutableStateOf(false) } + + LaunchedEffect(key1 = isLoggedIn) { + if (isLoggedIn) { + context.toast(context.getString(R.string.welcome)) + } + } + NavHost( navController = navController, startDestination = Routes.Login.screen, modifier = Modifier ) { + + composable(Routes.Login.screen) { LoginScreen( navController = navController, @@ -53,6 +68,7 @@ fun NavGraph( ) } composable(Routes.Home.screen) { + isLoggedIn = true HomeScreen(navController = navController, viewModel = HomeViewModel()) } composable(Routes.Search.screen) { From 07beb20e0ca6328584ee2bac8da240f1c2b4ef0f Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Thu, 14 Nov 2024 22:03:30 +0900 Subject: [PATCH 14/20] =?UTF-8?q?#8=20[feat]=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20=EC=95=88=EB=82=B4?= =?UTF-8?q?=20=ED=86=A0=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/sopt/and/feature/login/LoginScreen.kt | 4 ++-- .../org/sopt/and/feature/login/LoginViewModel.kt | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index de6351f..1a00739 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -52,7 +52,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController -import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.SocialLoginButtonGroup @@ -188,6 +187,7 @@ fun LoginScreen( viewModel.onLoginClick( onSuccess = { userName, password -> viewModel.postUserLogin( + context = context, body = UserLoginRequest( username = userName, password = password @@ -195,8 +195,8 @@ fun LoginScreen( ) { body -> editor.putString("loginToken", body!!.result.token) editor.apply() + onLoginSuccess(userName, password) } - onLoginSuccess(userName, password) }, ) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index 58136c0..0459796 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -1,5 +1,6 @@ package org.sopt.and.feature.login +import android.content.Context import android.util.Log import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf @@ -11,6 +12,7 @@ import kotlinx.coroutines.launch import org.sopt.and.data.ServicePool import org.sopt.and.data.model.dto.ResponseUserTokenDto import org.sopt.and.data.model.request.UserLoginRequest +import org.sopt.and.utils.toast import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -21,7 +23,11 @@ class LoginViewModel : ViewModel() { private val _userState = mutableStateOf(null) val userState: State get() = _userState - fun postUserLogin(body: UserLoginRequest, callback: (ResponseUserTokenDto?) -> Unit) { + fun postUserLogin( + context: Context, + body: UserLoginRequest, + callback: (ResponseUserTokenDto?) -> Unit + ) { userService.postUserLogin( body = body ).enqueue(object : Callback { @@ -36,13 +42,13 @@ class LoginViewModel : ViewModel() { } else { val error = response.message() Log.e("error", error.toString()) - callback(null) + context.toast("로그인에 실패했습니다.") } } override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) - callback(null) + context.toast("로그인에 실패했습니다.") } }) } @@ -66,7 +72,7 @@ class LoginViewModel : ViewModel() { onSuccess: (String, String) -> Unit, ) { viewModelScope.launch { - onSuccess(userName.value!!, password.value!!) + onSuccess(userName.value!!, password.value!!) } } } \ No newline at end of file From 0c77d443e53575c013a384277eb35d7fa793e0bd Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Thu, 14 Nov 2024 22:35:49 +0900 Subject: [PATCH 15/20] =?UTF-8?q?#8=20[del]=20:=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/feature/login/LoginScreen.kt | 13 ++----------- .../sopt/and/feature/login/LoginViewModel.kt | 5 +++-- .../org/sopt/and/feature/main/NavGraph.kt | 1 + .../org/sopt/and/feature/mypage/MyScreen.kt | 19 ------------------- 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index 1a00739..b54f4c1 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -25,8 +25,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.VerticalDivider @@ -35,7 +33,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection @@ -74,14 +71,13 @@ fun LoginScreen( val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) val editor = sharedPreferences.edit() - val scope = rememberCoroutineScope() - val snackbarHostState = remember { SnackbarHostState() } val userName by viewModel.userName.observeAsState("") val password by viewModel.password.observeAsState("") val showPassword = remember { mutableStateOf(false) } - Scaffold(modifier = Modifier.fillMaxSize(), + Scaffold( + modifier = Modifier.fillMaxSize(), topBar = { CenterAlignedTopAppBar( title = { @@ -110,11 +106,6 @@ fun LoginScreen( colors = TopAppBarDefaults.mediumTopAppBarColors(containerColor = WavveTheme.colors.BackgroundGray) ) }, - snackbarHost = { - SnackbarHost( - hostState = snackbarHostState - ) - } ) { innerPadding -> Box( modifier = Modifier diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index 0459796..a466bf7 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch +import org.sopt.and.R import org.sopt.and.data.ServicePool import org.sopt.and.data.model.dto.ResponseUserTokenDto import org.sopt.and.data.model.request.UserLoginRequest @@ -42,13 +43,13 @@ class LoginViewModel : ViewModel() { } else { val error = response.message() Log.e("error", error.toString()) - context.toast("로그인에 실패했습니다.") + context.toast(context.getString(R.string.fail_to_login)) } } override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) - context.toast("로그인에 실패했습니다.") + context.toast(context.getString(R.string.fail_to_login)) } }) } diff --git a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt index 20e4861..a2ae220 100644 --- a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt @@ -46,6 +46,7 @@ fun NavGraph( composable(Routes.Login.screen) { + isLoggedIn = false LoginScreen( navController = navController, onLoginSuccess = { name, password -> diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt index c63337f..1ddccc7 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt @@ -9,13 +9,9 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding 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.getValue import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -41,19 +37,8 @@ fun MyScreen( val hobby by viewModel.hobby.observeAsState("") - val snackbarHostState = remember { SnackbarHostState() } - - LaunchedEffect(Unit) { - snackbarHostState.showSnackbar(context.getString(R.string.welcome)) - } - Scaffold( modifier = Modifier.fillMaxSize(), - snackbarHost = { - SnackbarHost( - hostState = snackbarHostState - ) - } ) { innerPadding -> Box( modifier = Modifier @@ -62,7 +47,6 @@ fun MyScreen( .padding(innerPadding) ) { Column { - //프로필 박스 ProfileBox( userEmail = hobby, modifier = Modifier @@ -70,12 +54,10 @@ fun MyScreen( Spacer(modifier = Modifier.height(1.dp)) - //이용권 박스 TicketBox() Spacer(modifier = Modifier.height(20.dp)) - //전체 시청 내역 EmptyBox( stringResource(R.string.viewing_history), stringResource(R.string.no_viewing_history), @@ -83,7 +65,6 @@ fun MyScreen( Spacer(modifier = Modifier.height(30.dp)) - //관심 프로그램 EmptyBox( stringResource(R.string.interested_program), stringResource(R.string.no_interested_program), From c8b5b52b6fad42fb6a26a7e5cd65102e90b4fd6e Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Thu, 14 Nov 2024 23:04:02 +0900 Subject: [PATCH 16/20] #8 [refactor] : rename dto -> response --- .../data/model/{dto => response}/ResponseUserHobbyDto.kt | 2 +- .../data/model/{dto => response}/ResponseUserSignUpDto.kt | 2 +- .../data/model/{dto => response}/ResponseUserTokenDto.kt | 2 +- .../java/org/sopt/and/data/network/service/UserService.kt | 6 +++--- .../main/java/org/sopt/and/feature/login/LoginViewModel.kt | 2 +- app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt | 2 +- .../main/java/org/sopt/and/feature/mypage/MyViewModel.kt | 2 +- .../java/org/sopt/and/feature/signup/SignUpViewModel.kt | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) rename app/src/main/java/org/sopt/and/data/model/{dto => response}/ResponseUserHobbyDto.kt (87%) rename app/src/main/java/org/sopt/and/data/model/{dto => response}/ResponseUserSignUpDto.kt (87%) rename app/src/main/java/org/sopt/and/data/model/{dto => response}/ResponseUserTokenDto.kt (87%) diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt similarity index 87% rename from app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt rename to app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt index 0d960e3..2c2803a 100644 --- a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserHobbyDto.kt +++ b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.model.dto +package org.sopt.and.data.model.response import kotlinx.serialization.SerialName diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt similarity index 87% rename from app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt rename to app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt index 142aaed..470a3e4 100644 --- a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserSignUpDto.kt +++ b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.model.dto +package org.sopt.and.data.model.response import kotlinx.serialization.SerialName diff --git a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt similarity index 87% rename from app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt rename to app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt index 6735b18..b435385 100644 --- a/app/src/main/java/org/sopt/and/data/model/dto/ResponseUserTokenDto.kt +++ b/app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.model.dto +package org.sopt.and.data.model.response import kotlinx.serialization.SerialName diff --git a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt index 33d76fd..570fad9 100644 --- a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt +++ b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt @@ -1,8 +1,8 @@ package org.sopt.and.data.network.service -import org.sopt.and.data.model.dto.ResponseUserHobbyDto -import org.sopt.and.data.model.dto.ResponseUserSignUpDto -import org.sopt.and.data.model.dto.ResponseUserTokenDto +import org.sopt.and.data.model.response.ResponseUserHobbyDto +import org.sopt.and.data.model.response.ResponseUserSignUpDto +import org.sopt.and.data.model.response.ResponseUserTokenDto import org.sopt.and.data.model.request.UserLoginRequest import org.sopt.and.data.model.request.UserSignUpRequest import retrofit2.Call diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index a466bf7..bc5dd88 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -11,7 +11,7 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.dto.ResponseUserTokenDto +import org.sopt.and.data.model.response.ResponseUserTokenDto import org.sopt.and.data.model.request.UserLoginRequest import org.sopt.and.utils.toast import retrofit2.Call diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt index 1ddccc7..2b30da0 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt @@ -31,7 +31,7 @@ fun MyScreen( ) { val context = LocalContext.current val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) - val token = sharedPreferences.getString("loginToken", "none") ?: "none" + val token = sharedPreferences.getString("loginToken", "").orEmpty() viewModel.getUserHobby(token = token) diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index ff8679a..c90ff2b 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -7,7 +7,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.dto.ResponseUserHobbyDto +import org.sopt.and.data.model.response.ResponseUserHobbyDto import retrofit2.Call import retrofit2.Callback import retrofit2.Response diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index d8fed0c..5c61645 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -13,7 +13,7 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.dto.ResponseUserSignUpDto +import org.sopt.and.data.model.response.ResponseUserSignUpDto import org.sopt.and.data.model.request.UserSignUpRequest import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN import retrofit2.Call From d7b49fa27297d9452dfc3aee34cd82c023faa5d7 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 2 Dec 2024 13:55:33 +0900 Subject: [PATCH 17/20] #8 [refactor] : refactor dto naming --- .../core/designsystem/component/CustomBox.kt | 2 +- .../and/data/network/service/UserService.kt | 20 +++++++++---------- .../data/{ => remote}/model/TodayTopData.kt | 2 +- .../model/request/UserLoginRequestDto.kt} | 4 ++-- .../model/request/UserSignUpRequestDto.kt} | 4 ++-- .../model/response/UserHobbyResponseDto.kt} | 4 ++-- .../model/response/UserSignUpResponseDto.kt} | 4 ++-- .../model/response/UserTokenResponseDto.kt} | 4 ++-- .../sopt/and/feature/home/HomeViewModel.kt | 2 +- .../org/sopt/and/feature/login/LoginScreen.kt | 4 ++-- .../sopt/and/feature/login/LoginViewModel.kt | 20 +++++++++---------- .../sopt/and/feature/mypage/MyViewModel.kt | 14 ++++++------- .../sopt/and/feature/signup/SignUpScreen.kt | 4 ++-- .../and/feature/signup/SignUpViewModel.kt | 18 ++++++++--------- 14 files changed, 53 insertions(+), 53 deletions(-) rename app/src/main/java/org/sopt/and/data/{ => remote}/model/TodayTopData.kt (64%) rename app/src/main/java/org/sopt/and/data/{model/request/UserLoginRequest.kt => remote/model/request/UserLoginRequestDto.kt} (72%) rename app/src/main/java/org/sopt/and/data/{model/request/UserSignUpRequest.kt => remote/model/request/UserSignUpRequestDto.kt} (76%) rename app/src/main/java/org/sopt/and/data/{model/response/ResponseUserHobbyDto.kt => remote/model/response/UserHobbyResponseDto.kt} (75%) rename app/src/main/java/org/sopt/and/data/{model/response/ResponseUserSignUpDto.kt => remote/model/response/UserSignUpResponseDto.kt} (75%) rename app/src/main/java/org/sopt/and/data/{model/response/ResponseUserTokenDto.kt => remote/model/response/UserTokenResponseDto.kt} (75%) diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt index c5eb0cd..27c81ee 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt +++ b/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt @@ -36,7 +36,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.sopt.and.R -import org.sopt.and.data.model.TodayTopData +import org.sopt.and.data.remote.model.TodayTopData import org.sopt.and.ui.theme.WavveTheme @Composable diff --git a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt index 570fad9..b2604bd 100644 --- a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt +++ b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt @@ -1,10 +1,10 @@ package org.sopt.and.data.network.service -import org.sopt.and.data.model.response.ResponseUserHobbyDto -import org.sopt.and.data.model.response.ResponseUserSignUpDto -import org.sopt.and.data.model.response.ResponseUserTokenDto -import org.sopt.and.data.model.request.UserLoginRequest -import org.sopt.and.data.model.request.UserSignUpRequest +import org.sopt.and.data.remote.model.response.UserHobbyResponseDto +import org.sopt.and.data.remote.model.response.UserSignUpResponseDto +import org.sopt.and.data.remote.model.response.UserTokenResponseDto +import org.sopt.and.data.remote.model.request.UserLoginRequestDto +import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import retrofit2.Call import retrofit2.http.Body import retrofit2.http.GET @@ -14,16 +14,16 @@ import retrofit2.http.POST interface UserService { @POST("/user") fun postUserSignUp( - @Body body: UserSignUpRequest - ): Call + @Body body: UserSignUpRequestDto + ): Call @POST("/login") fun postUserLogin( - @Body body: UserLoginRequest - ): Call + @Body body: UserLoginRequestDto + ): Call @GET("/user/my-hobby") fun getUserHobby( @Header("token") token: String, - ): Call + ): Call } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/model/TodayTopData.kt b/app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt similarity index 64% rename from app/src/main/java/org/sopt/and/data/model/TodayTopData.kt rename to app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt index 821de81..8ad0d84 100644 --- a/app/src/main/java/org/sopt/and/data/model/TodayTopData.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.model +package org.sopt.and.data.remote.model data class TodayTopData( val painterId: Int, diff --git a/app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt b/app/src/main/java/org/sopt/and/data/remote/model/request/UserLoginRequestDto.kt similarity index 72% rename from app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt rename to app/src/main/java/org/sopt/and/data/remote/model/request/UserLoginRequestDto.kt index 1c31bab..df54844 100644 --- a/app/src/main/java/org/sopt/and/data/model/request/UserLoginRequest.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/request/UserLoginRequestDto.kt @@ -1,11 +1,11 @@ -package org.sopt.and.data.model.request +package org.sopt.and.data.remote.model.request import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class UserLoginRequest( +data class UserLoginRequestDto( @SerialName("username") val username: String, @SerialName("password") diff --git a/app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt b/app/src/main/java/org/sopt/and/data/remote/model/request/UserSignUpRequestDto.kt similarity index 76% rename from app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt rename to app/src/main/java/org/sopt/and/data/remote/model/request/UserSignUpRequestDto.kt index fbe48f6..feff169 100644 --- a/app/src/main/java/org/sopt/and/data/model/request/UserSignUpRequest.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/request/UserSignUpRequestDto.kt @@ -1,11 +1,11 @@ -package org.sopt.and.data.model.request +package org.sopt.and.data.remote.model.request import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class UserSignUpRequest( +data class UserSignUpRequestDto( @SerialName("username") val username: String, @SerialName("password") diff --git a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt similarity index 75% rename from app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt rename to app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt index 2c2803a..b9f2b5f 100644 --- a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserHobbyDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt @@ -1,11 +1,11 @@ -package org.sopt.and.data.model.response +package org.sopt.and.data.remote.model.response import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ResponseUserHobbyDto( +data class UserHobbyResponseDto( @SerialName("result") val result: Result ) { diff --git a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt similarity index 75% rename from app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt rename to app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt index 470a3e4..a2a2116 100644 --- a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserSignUpDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt @@ -1,11 +1,11 @@ -package org.sopt.and.data.model.response +package org.sopt.and.data.remote.model.response import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ResponseUserSignUpDto( +data class UserSignUpResponseDto( @SerialName("result") val result: Result ) { diff --git a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt similarity index 75% rename from app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt rename to app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt index b435385..37ba662 100644 --- a/app/src/main/java/org/sopt/and/data/model/response/ResponseUserTokenDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt @@ -1,11 +1,11 @@ -package org.sopt.and.data.model.response +package org.sopt.and.data.remote.model.response import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ResponseUserTokenDto( +data class UserTokenResponseDto( @SerialName("result") val result: Result ) { diff --git a/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt index a9f67fa..caa788f 100644 --- a/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.lifecycle.ViewModel import org.sopt.and.R -import org.sopt.and.data.model.TodayTopData +import org.sopt.and.data.remote.model.TodayTopData class HomeViewModel : ViewModel() { private val _homeTabText = listOf( diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index b54f4c1..c01edfc 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -53,7 +53,7 @@ import org.sopt.and.R import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.SocialLoginButtonGroup import org.sopt.and.core.designsystem.component.WavveLoginButton -import org.sopt.and.data.model.request.UserLoginRequest +import org.sopt.and.data.remote.model.request.UserLoginRequestDto import org.sopt.and.feature.main.Routes import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -179,7 +179,7 @@ fun LoginScreen( onSuccess = { userName, password -> viewModel.postUserLogin( context = context, - body = UserLoginRequest( + body = UserLoginRequestDto( username = userName, password = password ), diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index bc5dd88..a7b4c76 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -11,8 +11,8 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.response.ResponseUserTokenDto -import org.sopt.and.data.model.request.UserLoginRequest +import org.sopt.and.data.remote.model.response.UserTokenResponseDto +import org.sopt.and.data.remote.model.request.UserLoginRequestDto import org.sopt.and.utils.toast import retrofit2.Call import retrofit2.Callback @@ -21,20 +21,20 @@ import retrofit2.Response class LoginViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } - private val _userState = mutableStateOf(null) - val userState: State get() = _userState + private val _userState = mutableStateOf(null) + val userState: State get() = _userState fun postUserLogin( context: Context, - body: UserLoginRequest, - callback: (ResponseUserTokenDto?) -> Unit + body: UserLoginRequestDto, + callback: (UserTokenResponseDto?) -> Unit ) { userService.postUserLogin( body = body - ).enqueue(object : Callback { + ).enqueue(object : Callback { override fun onResponse( - call: Call, - response: Response + call: Call, + response: Response ) { if (response.isSuccessful) { _userState.value = response.body() @@ -47,7 +47,7 @@ class LoginViewModel : ViewModel() { } } - override fun onFailure(call: Call, t: Throwable) { + override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) context.toast(context.getString(R.string.fail_to_login)) } diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index c90ff2b..ec6acca 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -7,7 +7,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.response.ResponseUserHobbyDto +import org.sopt.and.data.remote.model.response.UserHobbyResponseDto import retrofit2.Call import retrofit2.Callback import retrofit2.Response @@ -15,18 +15,18 @@ import retrofit2.Response class MyViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } - private val _userState = mutableStateOf(null) - val userState: State get() = _userState + private val _userState = mutableStateOf(null) + val userState: State get() = _userState private val _hobby = MutableLiveData("") val hobby: LiveData get() = _hobby fun getUserHobby(token: String) { userService.getUserHobby(token = token) - .enqueue(object : Callback { + .enqueue(object : Callback { override fun onResponse( - call: Call, - response: Response + call: Call, + response: Response ) { if (response.isSuccessful) { _userState.value = response.body() @@ -39,7 +39,7 @@ class MyViewModel : ViewModel() { } } - override fun onFailure(call: Call, t: Throwable) { + override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) } }) diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt index c7e4c38..f2418de 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt @@ -52,7 +52,7 @@ import org.sopt.and.R import org.sopt.and.core.designsystem.component.AuthTextField import org.sopt.and.core.designsystem.component.ErrorDialog import org.sopt.and.core.designsystem.component.WavveSignUpButton -import org.sopt.and.data.model.request.UserSignUpRequest +import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -242,7 +242,7 @@ fun SignUpScreen( localHobby = hobby, onSuccess = { userName, password, hobby -> viewModel.postUserSignUp( - body = UserSignUpRequest( + body = UserSignUpRequestDto( username = userName, password = password, hobby = hobby diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index 5c61645..f569f39 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -13,8 +13,8 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.model.response.ResponseUserSignUpDto -import org.sopt.and.data.model.request.UserSignUpRequest +import org.sopt.and.data.remote.model.response.UserSignUpResponseDto +import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN import retrofit2.Call import retrofit2.Callback @@ -23,16 +23,16 @@ import retrofit2.Response class SignUpViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } - private val _userState = mutableStateOf(null) - val userState: State get() = _userState + private val _userState = mutableStateOf(null) + val userState: State get() = _userState - fun postUserSignUp(body: UserSignUpRequest) { + fun postUserSignUp(body: UserSignUpRequestDto) { userService.postUserSignUp( body = body - ).enqueue(object : Callback { + ).enqueue(object : Callback { override fun onResponse( - call: Call, - response: Response + call: Call, + response: Response ) { if (response.isSuccessful) { _userState.value = response.body() @@ -44,7 +44,7 @@ class SignUpViewModel : ViewModel() { } } - override fun onFailure(call: Call, t: Throwable) { + override fun onFailure(call: Call, t: Throwable) { Log.e("failure", t.message.toString()) } }) From 04baad4298811aee7f9f491ed72274c199e37452 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 2 Dec 2024 13:59:38 +0900 Subject: [PATCH 18/20] =?UTF-8?q?#8=20[del]=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20log=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt | 2 +- app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt | 2 -- .../main/java/org/sopt/and/feature/signup/SignUpViewModel.kt | 2 -- app/src/main/res/values/strings.xml | 1 + 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index c01edfc..25c6b91 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -184,7 +184,7 @@ fun LoginScreen( password = password ), ) { body -> - editor.putString("loginToken", body!!.result.token) + editor.putString(context.getString(R.string.login_token), body!!.result.token) editor.apply() onLoginSuccess(userName, password) } diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index ec6acca..59344a5 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -31,8 +31,6 @@ class MyViewModel : ViewModel() { if (response.isSuccessful) { _userState.value = response.body() _hobby.value = response.body()?.result?.hobby - Log.d("getUserHobby", response.body().toString()) - } else { val error = response.message() Log.e("error", error.toString()) diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index f569f39..528a5d3 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -36,8 +36,6 @@ class SignUpViewModel : ViewModel() { ) { if (response.isSuccessful) { _userState.value = response.body() - Log.d("postUserSignUp", response.body().toString()) - } else { val error = response.message() Log.e("error", error.toString()) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 12abd1b..4485abd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ 확인 도움말 더보기 + loginToken 회원가입 From c4adfaedeb9b3c9141c1ed662bf98d155e88922c Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 2 Dec 2024 14:05:51 +0900 Subject: [PATCH 19/20] =?UTF-8?q?#8=20[feat]=20:=20base=20response=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/data/network/service/UserService.kt | 12 ++++++------ .../sopt/and/data/remote/model/base/ApiResponse.kt | 10 ++++++++++ .../remote/model/response/UserHobbyResponseDto.kt | 12 +++--------- .../remote/model/response/UserSignUpResponseDto.kt | 12 +++--------- .../remote/model/response/UserTokenResponseDto.kt | 12 +++--------- 5 files changed, 25 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/data/remote/model/base/ApiResponse.kt diff --git a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt index b2604bd..db74d50 100644 --- a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt +++ b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt @@ -1,11 +1,11 @@ package org.sopt.and.data.network.service +import org.sopt.and.data.remote.model.base.ApiResponse +import org.sopt.and.data.remote.model.request.UserLoginRequestDto +import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.data.remote.model.response.UserHobbyResponseDto import org.sopt.and.data.remote.model.response.UserSignUpResponseDto import org.sopt.and.data.remote.model.response.UserTokenResponseDto -import org.sopt.and.data.remote.model.request.UserLoginRequestDto -import org.sopt.and.data.remote.model.request.UserSignUpRequestDto -import retrofit2.Call import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header @@ -15,15 +15,15 @@ interface UserService { @POST("/user") fun postUserSignUp( @Body body: UserSignUpRequestDto - ): Call + ): ApiResponse @POST("/login") fun postUserLogin( @Body body: UserLoginRequestDto - ): Call + ): ApiResponse @GET("/user/my-hobby") fun getUserHobby( @Header("token") token: String, - ): Call + ): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/model/base/ApiResponse.kt b/app/src/main/java/org/sopt/and/data/remote/model/base/ApiResponse.kt new file mode 100644 index 0000000..8adfd8f --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/model/base/ApiResponse.kt @@ -0,0 +1,10 @@ +package org.sopt.and.data.remote.model.base + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ApiResponse( + @SerialName("result") + val result: T +) diff --git a/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt index b9f2b5f..f654c04 100644 --- a/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserHobbyResponseDto.kt @@ -6,12 +6,6 @@ import kotlinx.serialization.Serializable @Serializable data class UserHobbyResponseDto( - @SerialName("result") - val result: Result -) { - @Serializable - data class Result( - @SerialName("hobby") - val hobby: String - ) -} \ No newline at end of file + @SerialName("hobby") + val hobby: String +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt index a2a2116..6609fd9 100644 --- a/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserSignUpResponseDto.kt @@ -6,12 +6,6 @@ import kotlinx.serialization.Serializable @Serializable data class UserSignUpResponseDto( - @SerialName("result") - val result: Result -) { - @Serializable - data class Result( - @SerialName("no") - val no: Int - ) -} \ No newline at end of file + @SerialName("no") + val no: Int +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt b/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt index 37ba662..98a2f43 100644 --- a/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt +++ b/app/src/main/java/org/sopt/and/data/remote/model/response/UserTokenResponseDto.kt @@ -6,12 +6,6 @@ import kotlinx.serialization.Serializable @Serializable data class UserTokenResponseDto( - @SerialName("result") - val result: Result -) { - @Serializable - data class Result( - @SerialName("token") - val token: String - ) -} \ No newline at end of file + @SerialName("token") + val token: String +) \ No newline at end of file From 6912a999ecc9b13834297c1c33c0bd108ca67313 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 3 Dec 2024 19:03:53 +0900 Subject: [PATCH 20/20] =?UTF-8?q?#8=20[refactor]=20:=20code=20review=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/data/network/service/UserService.kt | 6 +- .../org/sopt/and/feature/login/LoginScreen.kt | 26 ++++---- .../sopt/and/feature/login/LoginViewModel.kt | 63 ++++++++----------- .../sopt/and/feature/mypage/MyViewModel.kt | 35 ++++------- .../sopt/and/feature/signup/SignUpScreen.kt | 1 + .../and/feature/signup/SignUpViewModel.kt | 50 ++++++++------- app/src/main/res/values/strings.xml | 5 ++ 7 files changed, 86 insertions(+), 100 deletions(-) diff --git a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt index db74d50..7f5013a 100644 --- a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt +++ b/app/src/main/java/org/sopt/and/data/network/service/UserService.kt @@ -13,17 +13,17 @@ import retrofit2.http.POST interface UserService { @POST("/user") - fun postUserSignUp( + suspend fun postUserSignUp( @Body body: UserSignUpRequestDto ): ApiResponse @POST("/login") - fun postUserLogin( + suspend fun postUserLogin( @Body body: UserLoginRequestDto ): ApiResponse @GET("/user/my-hobby") - fun getUserHobby( + suspend fun getUserHobby( @Header("token") token: String, ): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt index 25c6b91..bd3a0b3 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt @@ -67,11 +67,12 @@ fun LoginScreen( ) { val context = LocalContext.current val focusManager = LocalFocusManager.current - val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher + val dispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher ?: return val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) val editor = sharedPreferences.edit() + val token by viewModel.token.observeAsState("") val userName by viewModel.userName.observeAsState("") val password by viewModel.password.observeAsState("") val showPassword = remember { mutableStateOf(false) } @@ -175,22 +176,17 @@ fun LoginScreen( //기본 로그인 버튼 WavveLoginButton( onClick = { - viewModel.onLoginClick( - onSuccess = { userName, password -> - viewModel.postUserLogin( - context = context, - body = UserLoginRequestDto( - username = userName, - password = password - ), - ) { body -> - editor.putString(context.getString(R.string.login_token), body!!.result.token) - editor.apply() - onLoginSuccess(userName, password) - } - }, + viewModel.postUserLogin( + context = context, + body = UserLoginRequestDto( + username = userName, + password = password + ), ) + editor.putString(context.getString(R.string.login_token), token) + editor.apply() + onLoginSuccess(userName, password) //키보드 내리기 focusManager.clearFocus() } diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt index a7b4c76..a6b3f4f 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt @@ -2,56 +2,53 @@ package org.sopt.and.feature.login import android.content.Context import android.util.Log -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch +import okio.IOException import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.remote.model.response.UserTokenResponseDto import org.sopt.and.data.remote.model.request.UserLoginRequestDto import org.sopt.and.utils.toast -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import retrofit2.HttpException class LoginViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } - private val _userState = mutableStateOf(null) - val userState: State get() = _userState + private val _token = MutableLiveData(null) + val token: LiveData get() = _token fun postUserLogin( context: Context, body: UserLoginRequestDto, - callback: (UserTokenResponseDto?) -> Unit ) { - userService.postUserLogin( - body = body - ).enqueue(object : Callback { - override fun onResponse( - call: Call, - response: Response - ) { - if (response.isSuccessful) { - _userState.value = response.body() - callback(response.body()) + viewModelScope.launch { + runCatching { + userService.postUserLogin(body = body) + }.onSuccess { response -> + _token.value = response.result.token + }.onFailure { error -> + when (error) { + is HttpException -> { + when (error.code()) { + 400 -> context.toast(context.getString(R.string.fail_to_login)) + 403 -> context.toast(context.getString(R.string.fail_to_login_invalid_password)) + } + } - } else { - val error = response.message() - Log.e("error", error.toString()) - context.toast(context.getString(R.string.fail_to_login)) - } - } + is IOException -> { + context.toast(context.getString(R.string.fail_to_network)) + } - override fun onFailure(call: Call, t: Throwable) { - Log.e("failure", t.message.toString()) - context.toast(context.getString(R.string.fail_to_login)) + else -> { + context.toast(context.getString(R.string.fail_to_login)) + } + } + Log.e("postUserLoginError", error.toString()) } - }) + } } private val _userName = MutableLiveData("") @@ -68,12 +65,4 @@ class LoginViewModel : ViewModel() { fun setPassword(newPassword: String) { _password.value = newPassword } - - fun onLoginClick( - onSuccess: (String, String) -> Unit, - ) { - viewModelScope.launch { - onSuccess(userName.value!!, password.value!!) - } - } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt index 59344a5..d9f1ea5 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt @@ -6,11 +6,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch import org.sopt.and.data.ServicePool import org.sopt.and.data.remote.model.response.UserHobbyResponseDto -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response class MyViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } @@ -22,25 +21,15 @@ class MyViewModel : ViewModel() { val hobby: LiveData get() = _hobby fun getUserHobby(token: String) { - userService.getUserHobby(token = token) - .enqueue(object : Callback { - override fun onResponse( - call: Call, - response: Response - ) { - if (response.isSuccessful) { - _userState.value = response.body() - _hobby.value = response.body()?.result?.hobby - } else { - val error = response.message() - Log.e("error", error.toString()) - } - } - - override fun onFailure(call: Call, t: Throwable) { - Log.e("failure", t.message.toString()) - } - }) + viewModelScope.launch { + runCatching { + userService.getUserHobby(token = token) + }.onSuccess { response -> + _userState.value = response.result + _hobby.value = response.result.hobby + }.onFailure { error -> + Log.e("getUserHobbyError", error.toString()) + } + } } - } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt index f2418de..a1da24a 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt @@ -242,6 +242,7 @@ fun SignUpScreen( localHobby = hobby, onSuccess = { userName, password, hobby -> viewModel.postUserSignUp( + context = context, body = UserSignUpRequestDto( username = userName, password = password, diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt index 528a5d3..c46883f 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt @@ -13,12 +13,12 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import org.sopt.and.R import org.sopt.and.data.ServicePool -import org.sopt.and.data.remote.model.response.UserSignUpResponseDto import org.sopt.and.data.remote.model.request.UserSignUpRequestDto +import org.sopt.and.data.remote.model.response.UserSignUpResponseDto import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import org.sopt.and.utils.toast +import retrofit2.HttpException +import java.io.IOException class SignUpViewModel : ViewModel() { private val userService by lazy { ServicePool.userService } @@ -26,26 +26,32 @@ class SignUpViewModel : ViewModel() { private val _userState = mutableStateOf(null) val userState: State get() = _userState - fun postUserSignUp(body: UserSignUpRequestDto) { - userService.postUserSignUp( - body = body - ).enqueue(object : Callback { - override fun onResponse( - call: Call, - response: Response - ) { - if (response.isSuccessful) { - _userState.value = response.body() - } else { - val error = response.message() - Log.e("error", error.toString()) + fun postUserSignUp(context: Context, body: UserSignUpRequestDto) { + viewModelScope.launch { + runCatching { + userService.postUserSignUp(body = body) + }.onSuccess { response -> + _userState.value = response.result + }.onFailure { error -> + when (error) { + is HttpException -> { + when (error.code()) { + 400 -> context.toast(context.getString(R.string.fail_to_signup_maximum_length)) + 409 -> context.toast(context.getString(R.string.fail_to_signup_duplicate_name)) + } + } + + is IOException -> { + context.toast(context.getString(R.string.fail_to_network)) + } + + else -> { + context.toast(context.getString(R.string.fail_to_signup)) + } } + Log.e("postUserSignUpError", error.toString()) } - - override fun onFailure(call: Call, t: Throwable) { - Log.e("failure", t.message.toString()) - } - }) + } } private val _userName = MutableLiveData("") diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4485abd..9108ad0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,6 +36,11 @@ 취미는 8자 이하여야 합니다. 취미는 8자 이하로 입력해 주세요. Wavve 사용자 취미 설정 + 올바르지 않은 password입니다. + 각 필드는 8자 이하여야 합니다. + 이미 존재하는 user name입니다. + 네트워크 상태를 확인해주세요 + 회원가입에 실패했습니다.