-
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
[Feat/#8] 4주차 필수 과제 #9
Changes from all commits
8cd667e
543087b
d582891
5d1a2b7
d032403
55a8047
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. [2] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,51 @@ | ||
package org.sopt.and | ||
|
||
import android.app.Application | ||
import android.os.Bundle | ||
import androidx.activity.ComponentActivity | ||
import androidx.activity.compose.setContent | ||
import androidx.activity.enableEdgeToEdge | ||
import androidx.compose.runtime.Composable | ||
import androidx.lifecycle.viewmodel.compose.viewModel | ||
import androidx.navigation.compose.NavHost | ||
import androidx.navigation.compose.composable | ||
import androidx.navigation.compose.rememberNavController | ||
import dagger.hilt.android.AndroidEntryPoint | ||
import dagger.hilt.android.HiltAndroidApp | ||
import org.sopt.and.navigation.AuthNavItem | ||
import org.sopt.and.presentation.ui.auth.SignInScreen | ||
import org.sopt.and.presentation.ui.auth.SignUpScreen | ||
import org.sopt.and.presentation.ui.main.MainScreen | ||
import org.sopt.and.presentation.viewmodel.SignUpViewModel | ||
import org.sopt.and.ui.theme.ANDANDROIDTheme | ||
|
||
@AndroidEntryPoint | ||
class MainActivity : ComponentActivity() { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
enableEdgeToEdge() | ||
setContent { | ||
ANDANDROIDTheme { | ||
val signUpViewModel: SignUpViewModel = viewModel() | ||
MyApp(signUpViewModel) | ||
MyAppScreen() | ||
} | ||
} | ||
} | ||
} | ||
|
||
@HiltAndroidApp | ||
class MyApp : Application() | ||
|
||
@Composable | ||
fun MyApp(signUpViewModel: SignUpViewModel) { | ||
fun MyAppScreen() { | ||
val navController = rememberNavController() | ||
|
||
NavHost(navController, startDestination = AuthNavItem.SignUp.route) { | ||
composable(AuthNavItem.SignUp.route) { | ||
SignUpScreen(signUpViewModel = signUpViewModel, navController = navController) | ||
SignUpScreen(navController = navController) | ||
} | ||
|
||
composable(AuthNavItem.SignIn.route) { | ||
SignInScreen(signUpViewModel = signUpViewModel, navController = navController) | ||
SignInScreen(navController = navController) | ||
} | ||
|
||
composable(AuthNavItem.Main.route) { | ||
MainScreen(signUpViewModel = signUpViewModel) | ||
MainScreen() | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.sopt.and.data.api | ||
|
||
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 | ||
import retrofit2.Retrofit | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object ApiFactory { | ||
private const val BASE_URL: String = BuildConfig.BASE_URL | ||
|
||
@Provides | ||
@Singleton | ||
fun provideOkHttpClient(): OkHttpClient { | ||
val loggingInterceptor = HttpLoggingInterceptor().apply { | ||
level = HttpLoggingInterceptor.Level.BODY | ||
} | ||
return OkHttpClient.Builder() | ||
.addInterceptor(loggingInterceptor) | ||
.build() | ||
} | ||
|
||
@Provides | ||
@Singleton | ||
fun provideRetrofit(client: OkHttpClient): Retrofit { | ||
return Retrofit.Builder() | ||
.baseUrl(BASE_URL) | ||
.client(client) | ||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) | ||
.build() | ||
} | ||
|
||
@Provides | ||
@Singleton | ||
fun provideUserRegistrationService(retrofit: Retrofit): UserRegistrationService { | ||
return retrofit.create(UserRegistrationService::class.java) | ||
} | ||
|
||
@Provides | ||
@Singleton | ||
fun provideLoginService(retrofit: Retrofit): LoginService { | ||
return retrofit.create(LoginService::class.java) | ||
} | ||
Comment on lines
+42
to
+52
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. [2] |
||
|
||
@Provides | ||
@Singleton | ||
fun provideHobbyService(retrofit: Retrofit): HobbyService { | ||
return retrofit.create(HobbyService::class.java) | ||
} | ||
|
||
} |
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. [3] |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
package org.sopt.and.data.api | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.sopt.and.data.dto.RequestLoginData | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.sopt.and.data.dto.RequestUserRegistrationData | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.sopt.and.data.dto.ResponseLogin | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import org.sopt.and.data.dto.ResponseUserRegistration | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import retrofit2.Response | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import retrofit2.http.Body | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import retrofit2.http.POST | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
interface UserRegistrationService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
@POST("/user") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
suspend fun postUserRegistration( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
@Body userRequest: RequestUserRegistrationData | ||||||||||||||||||||||||||||||||||||||||||||||||||||
): Response<ResponseUserRegistration> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
interface LoginService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
@POST("/login") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
suspend fun postLogin( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
@Body loginRequeset: RequestLoginData | ||||||||||||||||||||||||||||||||||||||||||||||||||||
): Response<ResponseLogin> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+12
to
+24
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. AuthService 라는 이름에 맞춰서 다음처럼 하나의 인터페이스로 구현하는 건 어떤가요?
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.sopt.and.data.api | ||
|
||
import org.sopt.and.data.dto.ResponseMyHobbyData | ||
import retrofit2.Response | ||
import retrofit2.http.GET | ||
import retrofit2.http.Header | ||
|
||
interface HobbyService { | ||
@GET("/user/my-hobby") | ||
Comment on lines
+8
to
+9
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. "/user/my-hobby"는 하드코딩되어 있는데, 변경 시 유지보수성이 떨어질 수 있다고 합니다! 이를 상수화하면 관리가 더 편리할 수 있습니다! |
||
suspend fun getHobby( | ||
@Header("token") token: String? | ||
): Response<ResponseMyHobbyData> | ||
} |
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. [2] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.sopt.and.data.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
/* 유저 등록 */ | ||
@Serializable | ||
data class RequestUserRegistrationData( | ||
@SerialName("username") | ||
val userName: String, | ||
@SerialName("password") | ||
val password: String, | ||
@SerialName("hobby") | ||
val hobby: String | ||
) | ||
|
||
@Serializable | ||
data class ResponseUserRegistration( | ||
@SerialName("result") | ||
val result: ResultUserNo | ||
) | ||
|
||
@Serializable | ||
data class ResultUserNo( | ||
@SerialName("no") | ||
val no: Int | ||
) | ||
|
||
/* 로그인 */ | ||
@Serializable | ||
data class RequestLoginData( | ||
@SerialName("username") | ||
val userName: String, | ||
@SerialName("password") | ||
val password: String | ||
) | ||
|
||
@Serializable | ||
data class ResponseLogin( | ||
@SerialName("result") | ||
val result: ResultToken | ||
) | ||
Comment on lines
+38
to
+42
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. 공통되는 부분에 대해 BaseResponse를 만든 후 사용하시면 가독성이 더 좋아질 것 같아요! |
||
|
||
@Serializable | ||
data class ResultToken( | ||
@SerialName("token") | ||
val token: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.sopt.and.data.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
/* 내 취미 조회 */ | ||
@Serializable | ||
data class ResponseMyHobbyData( | ||
@SerialName("result") | ||
val result: ResponseMyHobbyDataResult | ||
) | ||
|
||
@Serializable | ||
data class ResponseMyHobbyDataResult( | ||
@SerialName("hobby") | ||
val hobby: String | ||
) |
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. [3] 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. [3] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.sopt.and.data.repository.Auth | ||
|
||
import org.sopt.and.data.api.LoginService | ||
import org.sopt.and.data.dto.RequestLoginData | ||
import org.sopt.and.data.dto.ResponseLogin | ||
import javax.inject.Inject | ||
|
||
class LoginRepository @Inject constructor( | ||
private val apiService: LoginService | ||
) { | ||
suspend fun postLogin(requestData: RequestLoginData): Result<ResponseLogin> { | ||
return try { | ||
val response = apiService.postLogin(requestData) | ||
if (response.isSuccessful) { | ||
Result.success(response.body()!!) | ||
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. !! 사용은 지양합시다. NPE가 발생할 수 있어요. |
||
} else { | ||
val errorCode = response.errorBody()?.string() ?: "알수없슴" | ||
Result.failure(Exception("Error code : ${response.code()}, 에러 코드 : $errorCode")) | ||
} | ||
} catch (e: Exception) { | ||
Result.failure(e) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.sopt.and.data.repository.Auth | ||
|
||
import org.sopt.and.data.api.UserRegistrationService | ||
import org.sopt.and.data.dto.RequestUserRegistrationData | ||
import org.sopt.and.data.dto.ResponseUserRegistration | ||
import javax.inject.Inject | ||
|
||
class UserRegistrationRepository @Inject constructor( | ||
private val apiService: UserRegistrationService | ||
) { | ||
suspend fun postUserRegistration(requestData: RequestUserRegistrationData): Result<ResponseUserRegistration> { | ||
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. 저는 서버 통신하는 부분은 return 문이 없는게 보기 좋더라구요 suspend fun postUserRegistration(
requestData: RequestUserRegistrationData
): Result<ResponseUserRegistration> = try {
val response = apiService.postUserRegistration(requestData)
if (response.isSuccessful) {
Result.success(response.body()!!)
} else {
val errorCode = response.errorBody()?.string() ?: "알수없슴"
Result.failure(Exception("Error code : ${response.code()}, 에러 코드 : $errorCode"))
}
} catch (e: Exception) {
Result.failure(e)
}
|
||
return try { | ||
val response = apiService.postUserRegistration(requestData) | ||
if (response.isSuccessful) { | ||
Result.success(response.body()!!) | ||
} else { | ||
val errorCode = response.errorBody()?.string() ?: "알수없슴" | ||
Result.failure(Exception("Error code : ${response.code()}, 에러 코드 : $errorCode")) | ||
} | ||
} catch (e: Exception) { | ||
Result.failure(e) | ||
} | ||
} | ||
} |
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.
버전 카탈로그를 이용해주셔도 좋을 것 같네요 ~ 그리고 id와 alias의 차이는 뭘까요?