Skip to content

Commit

Permalink
[FEAT/#10] 회원가입 서버통신 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyobeen-Park committed Nov 15, 2024
1 parent 064446b commit 9f1c6a1
Show file tree
Hide file tree
Showing 19 changed files with 307 additions and 2 deletions.
11 changes: 11 additions & 0 deletions app/src/main/java/org/sopt/and/data/datasource/AuthDatasource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.and.data.datasource

import org.sopt.and.data.dto.BaseResponse
import org.sopt.and.data.dto.request.SignUpRequest
import org.sopt.and.data.dto.response.SignUpResponse

interface AuthDatasource {
suspend fun postSignUp(
request: SignUpRequest,
): BaseResponse<SignUpResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.and.data.datasourceimpl

import org.sopt.and.data.datasource.AuthDatasource
import org.sopt.and.data.dto.BaseResponse
import org.sopt.and.data.dto.request.SignUpRequest
import org.sopt.and.data.dto.response.SignUpResponse
import org.sopt.and.data.service.AuthService
import javax.inject.Inject

class AuthDatasourceImpl @Inject constructor(
private val authService: AuthService,
) : AuthDatasource {
override suspend fun postSignUp(
request: SignUpRequest
): BaseResponse<SignUpResponse> = authService.postSignUp(request)
}
17 changes: 17 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.and.data.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.datasource.AuthDatasource
import org.sopt.and.data.datasourceimpl.AuthDatasourceImpl
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindAuthDataSource(authDatasourceImpl: AuthDatasourceImpl): AuthDatasource
}
17 changes: 17 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.and.data.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.repositoryimpl.AuthRepositoryImpl
import org.sopt.and.domain.repository.AuthRepository
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository
}
58 changes: 58 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/RetrofitModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.sopt.and.data.di

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.sopt.and.BuildConfig.BASE_URL
import org.sopt.and.data.di.qualifier.Wavve
import retrofit2.Converter
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object RetrofitModule {
@Provides
@Singleton
fun provideJson(): Json = Json {
ignoreUnknownKeys = true
prettyPrint = true
}

@Provides
@Singleton
fun provideJsonConverter(json: Json): Converter.Factory =
json.asConverterFactory("application/json".toMediaType())

@Provides
@Singleton
fun provideLoggingInterceptor() = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}

@Provides
@Singleton
fun provideClient(
loggingInterceptor: HttpLoggingInterceptor,
) = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()

@Provides
@Singleton
@Wavve
fun provideRetrofit(
client: OkHttpClient,
factory: Converter.Factory
): Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(factory)
.build()
}
19 changes: 19 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.sopt.and.data.di

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.di.qualifier.Wavve
import org.sopt.and.data.service.AuthService
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object ServiceModule {
@Provides
@Singleton
fun provideAuthService(@Wavve retrofit: Retrofit): AuthService =
retrofit.create(AuthService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.and.data.di.qualifier

import javax.inject.Qualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Wavve
10 changes: 10 additions & 0 deletions app/src/main/java/org/sopt/and/data/dto/BaseResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.and.data.dto

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

@Serializable
data class BaseResponse<T>(
@SerialName("result")
val result: T,
)
14 changes: 14 additions & 0 deletions app/src/main/java/org/sopt/and/data/dto/request/SignUpRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.dto.request

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

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

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

@Serializable
data class SignUpResponse(
@SerialName("no")
val no: Int? = null,
@SerialName("code")
val code: String? = null,
)
10 changes: 10 additions & 0 deletions app/src/main/java/org/sopt/and/data/mapper/SignUpRequestMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.and.data.mapper

import org.sopt.and.data.dto.request.SignUpRequest
import org.sopt.and.domain.entitiy.signup.SignUpRequestModel

fun SignUpRequestModel.toSignUpRequestDto(): SignUpRequest = SignUpRequest(
username = this.username,
password = this.password,
hobby = this.hobby,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.and.data.mapper

import org.sopt.and.data.dto.response.SignUpResponse
import org.sopt.and.domain.entitiy.signup.SignUpResponseModel

fun SignUpResponse.toSignUpResponseModel(): SignUpResponseModel = SignUpResponseModel(
no = this.no,
code = this.code
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.sopt.and.data.repositoryimpl

import org.sopt.and.data.datasource.AuthDatasource
import org.sopt.and.data.mapper.toSignUpRequestDto
import org.sopt.and.data.mapper.toSignUpResponseModel
import org.sopt.and.domain.entitiy.signup.SignUpRequestModel
import org.sopt.and.domain.entitiy.signup.SignUpResponseModel
import org.sopt.and.domain.repository.AuthRepository
import javax.inject.Inject

class AuthRepositoryImpl @Inject constructor(
private val authDatasource: AuthDatasource
) : AuthRepository {
override suspend fun postSignUp(
username: String,
password: String,
hobby: String
): Result<SignUpResponseModel> =
kotlin.runCatching {
authDatasource.postSignUp(
SignUpRequestModel(
username = username,
password = password,
hobby = hobby,
).toSignUpRequestDto()
).result.toSignUpResponseModel()
}
}
14 changes: 14 additions & 0 deletions app/src/main/java/org/sopt/and/data/service/AuthService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.service

import org.sopt.and.data.dto.BaseResponse
import org.sopt.and.data.dto.request.SignUpRequest
import org.sopt.and.data.dto.response.SignUpResponse
import retrofit2.http.Body
import retrofit2.http.POST

interface AuthService {
@POST("user")
suspend fun postSignUp(
@Body body: SignUpRequest,
): BaseResponse<SignUpResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.and.domain.entitiy.signup

data class SignUpRequestModel(
val username: String,
val password: String,
val hobby: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.sopt.and.domain.entitiy.signup

data class SignUpResponseModel(
val no: Int?,
val code: String?,
)
11 changes: 11 additions & 0 deletions app/src/main/java/org/sopt/and/domain/repository/AuthRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.and.domain.repository

import org.sopt.and.domain.entitiy.signup.SignUpResponseModel

interface AuthRepository {
suspend fun postSignUp(
username: String,
password: String,
hobby: String,
): Result<SignUpResponseModel>
}
41 changes: 39 additions & 2 deletions app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.sopt.and.R
import org.sopt.and.domain.repository.AuthRepository
import javax.inject.Inject

@HiltViewModel
class SignUpViewModel @Inject constructor() : ViewModel() {
class SignUpViewModel @Inject constructor(
private val authRepository: AuthRepository,
) : ViewModel() {
private val _signUpState: MutableStateFlow<SignUpState> = MutableStateFlow(SignUpState())
val signUpState get() = _signUpState.asStateFlow()

Expand All @@ -27,7 +30,41 @@ class SignUpViewModel @Inject constructor() : ViewModel() {
} else if (!isPasswordValid(_signUpState.value.password)) {
_signUpSideEffect.emit(SignUpSideEffect.Toast(R.string.sign_up_not_valid_password))
} else {
_signUpSideEffect.emit(SignUpSideEffect.NavigateToSignIn)
signUp(
username = _signUpState.value.email,
password = _signUpState.value.password,
hobby = _signUpState.value.hobby
)
}
}
}

private fun signUp(
username: String,
password: String,
hobby: String,
) {
viewModelScope.launch {
authRepository.postSignUp(
username = username,
password = password,
hobby = hobby,
).onSuccess { response ->
_signUpSideEffect.emit(
SignUpSideEffect.Toast(
when {
response.no != null -> R.string.sign_up_success
response.code == "00" -> R.string.sign_up_user_exist
response.code == "01" -> R.string.textfield_input_length
else -> R.string.sign_up_failed
}
)
)
if (response.no != null) {
_signUpSideEffect.emit(SignUpSideEffect.NavigateToSignIn)
}
}.onFailure {
_signUpSideEffect.emit(SignUpSideEffect.Toast(R.string.sign_up_failed))
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<string name="sign_up_not_valid_email">이메일 형식으로 입력해주세요.</string>
<string name="sign_up_not_valid_password">비밀번호는 8자 이내로 영문 대소문자, 숫자, 특수문자 중 3가지 이상 혼용하여 입력해 주세요.</string>
<string name="sign_up_success">회원가입을 완료했습니다!</string>
<string name="sign_up_failed">회원가입을 실패했습니다</string>
<string name="sign_up_user_exist">이미 존재하는 회원입니다</string>

<!-- Sign In -->
<string name="sign_in">로그인</string>
Expand Down

0 comments on commit 9f1c6a1

Please sign in to comment.