-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TNT-114] 회원가입 데이터 취합 및 API 연동 #54
Changes from 11 commits
7f245f1
6c0a7e2
071a69f
9c37378
8ff993a
c2d814b
eb79aca
bb6d29e
f942102
e6a14b9
b9d0ba9
f3263f6
a3274b6
6201215
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package co.kr.tnt.ui.util | ||
|
||
import android.content.Context | ||
import android.database.Cursor | ||
import android.net.Uri | ||
import android.provider.MediaStore | ||
import android.util.Log | ||
import okhttp3.MediaType.Companion.toMediaTypeOrNull | ||
import okhttp3.MultipartBody | ||
import okhttp3.RequestBody.Companion.asRequestBody | ||
import java.io.File | ||
|
||
fun Uri.toMultiPart(context: Context, keyName: String = "image"): MultipartBody.Part? { | ||
return getRealPathFromUri(this, context)?.let { filePath -> | ||
val file = File(filePath) | ||
val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull()) | ||
MultipartBody.Part.createFormData(keyName, file.name, requestFile) | ||
} ?: run { | ||
Log.e("toMultipartImagePart", "Error creating multipart image for URI: $this") | ||
null | ||
} | ||
} | ||
|
||
fun getRealPathFromUri(uri: Uri, context: Context): String? { | ||
val projection = arrayOf(MediaStore.Images.Media.DATA) | ||
val cursor: Cursor? = context.contentResolver.query(uri, projection, null, null, null) | ||
cursor?.use { | ||
if (it.moveToFirst()) { | ||
val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) | ||
return it.getString(columnIndex) | ||
} | ||
} | ||
return null | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package co.kr.data.network.model | ||
|
||
import co.kr.tnt.domain.model.UserType | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SignUpRequest( | ||
val socialType: String, | ||
val socialId: String, | ||
val fcmToken: String, | ||
val serviceAgreement: Boolean, | ||
val collectionAgreement: Boolean, | ||
val advertisementAgreement: Boolean, | ||
val socialEmail: String, | ||
val memberType: String, | ||
val name: String, | ||
val birthday: String? = null, | ||
val height: Double? = null, | ||
val weight: Double? = null, | ||
val goalContents: List<String>? = null, | ||
val cautionNote: String? = "", | ||
) | ||
|
||
object SignUpRequestMapper { | ||
fun fromUserType( | ||
userType: UserType, | ||
socialId: String, | ||
socialType: String, | ||
email: String, | ||
fcmToken: String, | ||
): SignUpRequest { | ||
return when (userType) { | ||
is UserType.Trainer -> SignUpRequest( | ||
memberType = "trainer", | ||
name = userType.name, | ||
birthday = null, | ||
height = null, | ||
weight = null, | ||
goalContents = null, | ||
cautionNote = null, | ||
socialType = socialType, | ||
socialId = socialId, | ||
socialEmail = email, | ||
fcmToken = fcmToken, | ||
serviceAgreement = true, | ||
collectionAgreement = true, | ||
advertisementAgreement = true, | ||
) | ||
|
||
is UserType.Trainee -> SignUpRequest( | ||
memberType = "trainee", | ||
name = userType.name, | ||
birthday = userType.birthday?.toString(), | ||
height = userType.height.toDouble(), | ||
weight = userType.weight, | ||
goalContents = userType.ptPurpose, | ||
cautionNote = userType.caution?.ifBlank { null }, | ||
socialType = socialType, | ||
socialId = socialId, | ||
socialEmail = email, | ||
fcmToken = fcmToken, | ||
serviceAgreement = true, | ||
collectionAgreement = true, | ||
advertisementAgreement = true, | ||
) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package co.kr.data.network.model | ||
|
||
import co.kr.tnt.domain.model.SignUpResult | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class SignUpResponse( | ||
val memberType: String, | ||
val sessionId: String, | ||
val name: String, | ||
val profileImageUrl: String, | ||
) | ||
|
||
fun SignUpResponse.toDomain(): SignUpResult { | ||
return SignUpResult( | ||
memberType = memberType, | ||
sessionId = sessionId, | ||
name = name, | ||
profileImageUrl = profileImageUrl, | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,24 @@ package co.kr.data.network.service | |
|
||
import co.kr.data.network.model.LoginRequest | ||
import co.kr.data.network.model.LoginResponse | ||
import co.kr.data.network.model.SignUpResponse | ||
import okhttp3.MultipartBody | ||
import okhttp3.RequestBody | ||
import retrofit2.http.Body | ||
import retrofit2.http.Multipart | ||
import retrofit2.http.POST | ||
import retrofit2.http.Part | ||
|
||
interface ApiService { | ||
@POST("/login") | ||
suspend fun postLogin( | ||
@Body request: LoginRequest, | ||
): LoginResponse | ||
|
||
@Multipart | ||
@POST("/members/sign-up") | ||
suspend fun postSignUp( | ||
@Part profileImage: MultipartBody.Part?, | ||
@Part("request") request: RequestBody, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
): SignUpResponse | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package co.kr.data.network.source | ||
|
||
import co.kr.data.network.model.SignUpResponse | ||
import co.kr.data.network.service.ApiService | ||
import co.kr.data.network.util.networkHandler | ||
import okhttp3.MultipartBody | ||
import okhttp3.RequestBody | ||
import javax.inject.Inject | ||
import javax.inject.Singleton | ||
|
||
@Singleton | ||
class SignUpRemoteDataSource @Inject constructor( | ||
private val apiService: ApiService, | ||
) { | ||
suspend fun postSignUp( | ||
profileImage: MultipartBody.Part?, | ||
request: RequestBody, | ||
): SignUpResponse = networkHandler { | ||
apiService.postSignUp(profileImage, request) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,56 @@ | ||||||||||
package co.kr.data.repository | ||||||||||
|
||||||||||
import co.kr.data.network.model.SignUpRequest | ||||||||||
import co.kr.data.network.model.SignUpRequestMapper | ||||||||||
import co.kr.data.network.model.toDomain | ||||||||||
import co.kr.data.network.source.SignUpRemoteDataSource | ||||||||||
import co.kr.data.storage.source.SessionLocalDataSource | ||||||||||
import co.kr.tnt.domain.model.SignUpResult | ||||||||||
import co.kr.tnt.domain.model.UserType | ||||||||||
import co.kr.tnt.domain.repository.SignUpRepository | ||||||||||
import kotlinx.serialization.encodeToString | ||||||||||
import kotlinx.serialization.json.Json | ||||||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull | ||||||||||
import okhttp3.MultipartBody | ||||||||||
import okhttp3.RequestBody | ||||||||||
import okhttp3.RequestBody.Companion.toRequestBody | ||||||||||
import javax.inject.Inject | ||||||||||
|
||||||||||
class SignUpRepositoryImpl @Inject constructor( | ||||||||||
private val signupRemoteDataSource: SignUpRemoteDataSource, | ||||||||||
private val sessionLocalDataSource: SessionLocalDataSource, | ||||||||||
) : SignUpRepository { | ||||||||||
override suspend fun signUp( | ||||||||||
profileImage: MultipartBody.Part?, | ||||||||||
userType: UserType, | ||||||||||
socialId: String, | ||||||||||
socialType: String, | ||||||||||
email: String, | ||||||||||
): SignUpResult { | ||||||||||
// TODO FCM token | ||||||||||
val signUpRequest = SignUpRequestMapper.fromUserType( | ||||||||||
userType = userType, | ||||||||||
socialId = socialId, | ||||||||||
socialType = socialType, | ||||||||||
email = email, | ||||||||||
fcmToken = "EMPTY", | ||||||||||
) | ||||||||||
val requestBody = prepareJsonRequestBody(signUpRequest) | ||||||||||
|
||||||||||
val response = signupRemoteDataSource.postSignUp( | ||||||||||
profileImage = profileImage, | ||||||||||
request = requestBody, | ||||||||||
) | ||||||||||
|
||||||||||
response.sessionId.let { sessionId -> | ||||||||||
sessionLocalDataSource.updateSessionId(sessionId) | ||||||||||
} | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
return response.toDomain() | ||||||||||
} | ||||||||||
|
||||||||||
private fun prepareJsonRequestBody(signUpRequest: SignUpRequest): RequestBody { | ||||||||||
val jsonString = Json.encodeToString(signUpRequest) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DI Container 에 |
||||||||||
return jsonString.toRequestBody("application/json".toMediaTypeOrNull()) | ||||||||||
} | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,5 +5,6 @@ plugins { | |
|
||
dependencies { | ||
implementation(libs.inject) | ||
implementation(libs.okhttp.logging) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 도메인 영역에서 네트워크 관련 라이브러리를 알고 있어선 안됩니다!! 왜일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 클린 아키텍처 원칙에 따라 도메인 계층은 네트워크와 무관해야 한다는건 알고 있지만 Multipart 때문에 넣었습니다..😿 지금 생각해보니 아래 리뷰처럼 File로 넘기고 심약 이슈였습니다.. 고쳐올게요! |
||
implementation(libs.coroutines.core) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package co.kr.tnt.domain.model | ||
|
||
data class SignUpResult( | ||
val memberType: String, | ||
val sessionId: String, | ||
val name: String, | ||
val profileImageUrl: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package co.kr.tnt.domain.repository | ||
|
||
import co.kr.tnt.domain.model.SignUpResult | ||
import co.kr.tnt.domain.model.UserType | ||
import okhttp3.MultipartBody | ||
|
||
interface SignUpRepository { | ||
suspend fun signUp( | ||
profileImage: MultipartBody.Part?, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
userType: UserType, | ||
socialId: String, | ||
socialType: String, | ||
email: String, | ||
): SignUpResult | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LoginResponse
,SignupResponse
에서 매핑할 때와 같이 통일성 맞춰주는게 좋을 것 같습니다..!