From b02e0f9f553fbf3934dbda095b434448dd43a745 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Tue, 3 Dec 2024 20:32:45 +0900 Subject: [PATCH 01/14] =?UTF-8?q?#10=20[refactor]=20:=20clean=20architectu?= =?UTF-8?q?re=20=EA=B5=AC=EC=A1=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../mapper/todata/UserLoginModelMapper.kt | 7 ++++++ .../mapper/todata/UserSignUpModelMapper.kt | 7 ++++++ .../todomain/UserHobbyResponseDtoMapper.kt | 7 ++++++ .../data/remote/datasource/UserDataSource.kt | 7 ++++++ .../datasourceimpl/UserDataSourceImpl.kt | 11 ++++++++++ .../service/UserService.kt | 2 +- .../repositoryimpl/UserHobbyRepositoryImpl.kt | 10 +++++++++ .../org/sopt/and/{data => di}/ApiFactory.kt | 4 ++-- .../domain/model/request/UserLoginModel.kt | 6 +++++ .../domain/model/request/UserSignUpModel.kt | 7 ++++++ .../sopt/and/domain/model/response/Hobby.kt | 5 +++++ .../sopt/and/domain/model/response/Token.kt | 5 +++++ .../and/domain/model/response/UserNumber.kt | 5 +++++ .../domain/repository/UserHobbyRepository.kt | 4 ++++ .../core}/component/Banner.kt | 2 +- .../core}/component/CustomBox.kt | 2 +- .../core}/component/CustomButton.kt | 2 +- .../core}/component/CustomDialog.kt | 2 +- .../core}/component/CustomTabBar.kt | 2 +- .../core}/component/CustomTextField.kt | 2 +- .../core}/component/SocialLoginButton.kt | 2 +- .../home/HomeScreen.kt | 10 ++++----- .../home/HomeViewModel.kt | 2 +- .../login/LoginScreen.kt | 10 ++++----- .../login/LoginViewModel.kt | 4 ++-- .../main/BottomNavigationBar.kt | 2 +- .../main/MainActivity.kt | 2 +- .../main/NavGraph.kt | 22 +++++++++---------- .../{feature => presentation}/main/Routes.kt | 2 +- .../mypage/MyScreen.kt | 8 +++---- .../mypage/MyViewModel.kt | 4 ++-- .../search/SearchScreen.kt | 2 +- .../search/SearchViewModel.kt | 2 +- .../signup/SignUpScreen.kt | 8 +++---- .../signup/SignUpViewModel.kt | 4 ++-- 36 files changed, 133 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt create mode 100644 app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt create mode 100644 app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt create mode 100644 app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt create mode 100644 app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt rename app/src/main/java/org/sopt/and/data/{network => remote}/service/UserService.kt (95%) create mode 100644 app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt rename app/src/main/java/org/sopt/and/{data => di}/ApiFactory.kt (92%) create mode 100644 app/src/main/java/org/sopt/and/domain/model/request/UserLoginModel.kt create mode 100644 app/src/main/java/org/sopt/and/domain/model/request/UserSignUpModel.kt create mode 100644 app/src/main/java/org/sopt/and/domain/model/response/Hobby.kt create mode 100644 app/src/main/java/org/sopt/and/domain/model/response/Token.kt create mode 100644 app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt create mode 100644 app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/Banner.kt (98%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/CustomBox.kt (99%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/CustomButton.kt (98%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/CustomDialog.kt (98%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/CustomTabBar.kt (96%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/CustomTextField.kt (97%) rename app/src/main/java/org/sopt/and/{core/designsystem => presentation/core}/component/SocialLoginButton.kt (98%) rename app/src/main/java/org/sopt/and/{feature => presentation}/home/HomeScreen.kt (95%) rename app/src/main/java/org/sopt/and/{feature => presentation}/home/HomeViewModel.kt (95%) rename app/src/main/java/org/sopt/and/{feature => presentation}/login/LoginScreen.kt (97%) rename app/src/main/java/org/sopt/and/{feature => presentation}/login/LoginViewModel.kt (96%) rename app/src/main/java/org/sopt/and/{feature => presentation}/main/BottomNavigationBar.kt (98%) rename app/src/main/java/org/sopt/and/{feature => presentation}/main/MainActivity.kt (97%) rename app/src/main/java/org/sopt/and/{feature => presentation}/main/NavGraph.kt (80%) rename app/src/main/java/org/sopt/and/{feature => presentation}/main/Routes.kt (84%) rename app/src/main/java/org/sopt/and/{feature => presentation}/mypage/MyScreen.kt (91%) rename app/src/main/java/org/sopt/and/{feature => presentation}/mypage/MyViewModel.kt (93%) rename app/src/main/java/org/sopt/and/{feature => presentation}/search/SearchScreen.kt (96%) rename app/src/main/java/org/sopt/and/{feature => presentation}/search/SearchViewModel.kt (65%) rename app/src/main/java/org/sopt/and/{feature => presentation}/signup/SignUpScreen.kt (98%) rename app/src/main/java/org/sopt/and/{feature => presentation}/signup/SignUpViewModel.kt (98%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7dcf9b7..6c0a596 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,7 @@ android:usesCleartextTraffic="true" tools:targetApi="31"> diff --git a/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt new file mode 100644 index 0000000..bd3d906 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt @@ -0,0 +1,7 @@ +package org.sopt.and.data.mapper.todata + +import org.sopt.and.domain.model.request.UserLoginModel + +fun UserLoginModel.toData() : UserLoginRequestDto = UserLoginRequestDto( + +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt new file mode 100644 index 0000000..15ff091 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt @@ -0,0 +1,7 @@ +package org.sopt.and.data.mapper.todata + +import org.sopt.and.domain.model.request.UserSignUpModel + +fun UserSignUpModel.toData() : UserSignUpRequestDto = UserSignUpRequestDto( + +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt new file mode 100644 index 0000000..c28ab8d --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt @@ -0,0 +1,7 @@ +package org.sopt.and.data.mapper.todomain + +import org.sopt.and.domain.model.response.Hobby + +fun UserHobbyResponseDto.toDomain(): Hobby = Hobby( + hobby = this.hobby +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt b/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt new file mode 100644 index 0000000..53b8167 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt @@ -0,0 +1,7 @@ +package org.sopt.and.data.remote.datasource + +interface UserDataSource { + suspend fun postUserSignUp() : ApiResponse + suspend fun postUserLogin() : ApiResponse + suspend fun getUserHobby() : ApiResponse +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt new file mode 100644 index 0000000..790cae2 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt @@ -0,0 +1,11 @@ +package org.sopt.and.data.remote.datasourceimpl + +import org.sopt.and.data.remote.datasource.UserDataSource + +class UserDataSourceImpl @Inject constructor( + // private val +) : UserDataSource { + override suspend fun getUserHobby(): ApiResponse { + userService. + } +} \ 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/remote/service/UserService.kt similarity index 95% rename from app/src/main/java/org/sopt/and/data/network/service/UserService.kt rename to app/src/main/java/org/sopt/and/data/remote/service/UserService.kt index 7f5013a..18cbf9b 100644 --- a/app/src/main/java/org/sopt/and/data/network/service/UserService.kt +++ b/app/src/main/java/org/sopt/and/data/remote/service/UserService.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.network.service +package org.sopt.and.data.remote.service import org.sopt.and.data.remote.model.base.ApiResponse import org.sopt.and.data.remote.model.request.UserLoginRequestDto diff --git a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt new file mode 100644 index 0000000..79ffd88 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt @@ -0,0 +1,10 @@ +package org.sopt.and.data.repositoryimpl + +import org.sopt.and.data.remote.datasource.UserDataSource +import org.sopt.and.domain.repository.UserHobbyRepository + +class UserHobbyRepositoryImpl @Inject constructor( + private val userHobbyDataSource: UserDataSource +) : UserHobbyRepository { + +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/ApiFactory.kt b/app/src/main/java/org/sopt/and/di/ApiFactory.kt similarity index 92% rename from app/src/main/java/org/sopt/and/data/ApiFactory.kt rename to app/src/main/java/org/sopt/and/di/ApiFactory.kt index 4ad4168..f13afbd 100644 --- a/app/src/main/java/org/sopt/and/data/ApiFactory.kt +++ b/app/src/main/java/org/sopt/and/di/ApiFactory.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data +package org.sopt.and.di import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import kotlinx.serialization.json.Json @@ -6,7 +6,7 @@ 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 org.sopt.and.data.remote.service.UserService import retrofit2.Retrofit object ApiFactory { diff --git a/app/src/main/java/org/sopt/and/domain/model/request/UserLoginModel.kt b/app/src/main/java/org/sopt/and/domain/model/request/UserLoginModel.kt new file mode 100644 index 0000000..fe142ba --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/model/request/UserLoginModel.kt @@ -0,0 +1,6 @@ +package org.sopt.and.domain.model.request + +data class UserLoginModel( + val username: String, + val password: String +) diff --git a/app/src/main/java/org/sopt/and/domain/model/request/UserSignUpModel.kt b/app/src/main/java/org/sopt/and/domain/model/request/UserSignUpModel.kt new file mode 100644 index 0000000..e725d98 --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/model/request/UserSignUpModel.kt @@ -0,0 +1,7 @@ +package org.sopt.and.domain.model.request + +data class UserSignUpModel( + val username: String, + val password: String, + val hobby: String +) diff --git a/app/src/main/java/org/sopt/and/domain/model/response/Hobby.kt b/app/src/main/java/org/sopt/and/domain/model/response/Hobby.kt new file mode 100644 index 0000000..a9972da --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/model/response/Hobby.kt @@ -0,0 +1,5 @@ +package org.sopt.and.domain.model.response + +data class Hobby( + val hobby: String +) diff --git a/app/src/main/java/org/sopt/and/domain/model/response/Token.kt b/app/src/main/java/org/sopt/and/domain/model/response/Token.kt new file mode 100644 index 0000000..46abcc2 --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/model/response/Token.kt @@ -0,0 +1,5 @@ +package org.sopt.and.domain.model.response + +data class Token( + val token: String +) diff --git a/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt b/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt new file mode 100644 index 0000000..e6a2381 --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt @@ -0,0 +1,5 @@ +package org.sopt.and.domain.model.response + +data class UserNumber( + val no: Int +) diff --git a/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt b/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt new file mode 100644 index 0000000..aee0063 --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt @@ -0,0 +1,4 @@ +package org.sopt.and.domain.repository + +interface UserHobbyRepository { +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/Banner.kt b/app/src/main/java/org/sopt/and/presentation/core/component/Banner.kt similarity index 98% rename from app/src/main/java/org/sopt/and/core/designsystem/component/Banner.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/Banner.kt index 7bac48d..d123010 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/Banner.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/Banner.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.foundation.Image import androidx.compose.foundation.background diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt similarity index 99% rename from app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt index 27c81ee..6d7a91d 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomBox.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.foundation.Image import androidx.compose.foundation.background diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomButton.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomButton.kt similarity index 98% rename from app/src/main/java/org/sopt/and/core/designsystem/component/CustomButton.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/CustomButton.kt index ddb9d7f..8a5d964 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomButton.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomButton.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomDialog.kt similarity index 98% rename from app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/CustomDialog.kt index e1337ca..47eb3a0 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomDialog.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomDialog.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomTabBar.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt similarity index 96% rename from app/src/main/java/org/sopt/and/core/designsystem/component/CustomTabBar.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt index c71ae50..2bce3e3 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomTabBar.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.material3.ScrollableTabRow import androidx.compose.material3.Tab diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomTextField.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTextField.kt similarity index 97% rename from app/src/main/java/org/sopt/and/core/designsystem/component/CustomTextField.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/CustomTextField.kt index a97cfd6..6cb7c28 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/CustomTextField.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTextField.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions diff --git a/app/src/main/java/org/sopt/and/core/designsystem/component/SocialLoginButton.kt b/app/src/main/java/org/sopt/and/presentation/core/component/SocialLoginButton.kt similarity index 98% rename from app/src/main/java/org/sopt/and/core/designsystem/component/SocialLoginButton.kt rename to app/src/main/java/org/sopt/and/presentation/core/component/SocialLoginButton.kt index 5be59c4..14a178b 100644 --- a/app/src/main/java/org/sopt/and/core/designsystem/component/SocialLoginButton.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/SocialLoginButton.kt @@ -1,4 +1,4 @@ -package org.sopt.and.core.designsystem.component +package org.sopt.and.presentation.core.component import androidx.annotation.DrawableRes import androidx.compose.foundation.Image diff --git a/app/src/main/java/org/sopt/and/feature/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt similarity index 95% rename from app/src/main/java/org/sopt/and/feature/home/HomeScreen.kt rename to app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt index bf4962d..087fdca 100644 --- a/app/src/main/java/org/sopt/and/feature/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.home +package org.sopt.and.presentation.home import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -39,10 +39,10 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import org.sopt.and.R -import org.sopt.and.core.designsystem.component.Banner -import org.sopt.and.core.designsystem.component.EditorRecommendBox -import org.sopt.and.core.designsystem.component.TodayTop20Box -import org.sopt.and.core.designsystem.component.WavveTabBar +import org.sopt.and.presentation.core.component.Banner +import org.sopt.and.presentation.core.component.EditorRecommendBox +import org.sopt.and.presentation.core.component.TodayTop20Box +import org.sopt.and.presentation.core.component.WavveTabBar import org.sopt.and.ui.theme.WavveTheme @OptIn(ExperimentalMaterial3Api::class) diff --git a/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt similarity index 95% rename from app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt rename to app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt index caa788f..4dc454f 100644 --- a/app/src/main/java/org/sopt/and/feature/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.home +package org.sopt.and.presentation.home import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt similarity index 97% rename from app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt rename to app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt index bd3a0b3..868be7c 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.login +package org.sopt.and.presentation.login import android.content.Context import androidx.activity.compose.LocalOnBackPressedDispatcherOwner @@ -50,11 +50,11 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController 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.presentation.core.component.AuthTextField +import org.sopt.and.presentation.core.component.SocialLoginButtonGroup +import org.sopt.and.presentation.core.component.WavveLoginButton import org.sopt.and.data.remote.model.request.UserLoginRequestDto -import org.sopt.and.feature.main.Routes +import org.sopt.and.presentation.main.Routes import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable diff --git a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt similarity index 96% rename from app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt rename to app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt index a6b3f4f..e179a3f 100644 --- a/app/src/main/java/org/sopt/and/feature/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.login +package org.sopt.and.presentation.login import android.content.Context import android.util.Log @@ -9,7 +9,7 @@ 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.di.ServicePool import org.sopt.and.data.remote.model.request.UserLoginRequestDto import org.sopt.and.utils.toast import retrofit2.HttpException diff --git a/app/src/main/java/org/sopt/and/feature/main/BottomNavigationBar.kt b/app/src/main/java/org/sopt/and/presentation/main/BottomNavigationBar.kt similarity index 98% rename from app/src/main/java/org/sopt/and/feature/main/BottomNavigationBar.kt rename to app/src/main/java/org/sopt/and/presentation/main/BottomNavigationBar.kt index 1d4c79a..e21c435 100644 --- a/app/src/main/java/org/sopt/and/feature/main/BottomNavigationBar.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/BottomNavigationBar.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.main +package org.sopt.and.presentation.main import androidx.compose.foundation.Image import androidx.compose.foundation.layout.height diff --git a/app/src/main/java/org/sopt/and/feature/main/MainActivity.kt b/app/src/main/java/org/sopt/and/presentation/main/MainActivity.kt similarity index 97% rename from app/src/main/java/org/sopt/and/feature/main/MainActivity.kt rename to app/src/main/java/org/sopt/and/presentation/main/MainActivity.kt index a600584..0ac815d 100644 --- a/app/src/main/java/org/sopt/and/feature/main/MainActivity.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/MainActivity.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.main +package org.sopt.and.presentation.main import android.annotation.SuppressLint import android.os.Bundle diff --git a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt similarity index 80% rename from app/src/main/java/org/sopt/and/feature/main/NavGraph.kt rename to app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt index a2ae220..cb03183 100644 --- a/app/src/main/java/org/sopt/and/feature/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.main +package org.sopt.and.presentation.main import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -12,16 +12,16 @@ 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 -import org.sopt.and.feature.login.LoginViewModel -import org.sopt.and.feature.mypage.MyScreen -import org.sopt.and.feature.mypage.MyViewModel -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.presentation.home.HomeScreen +import org.sopt.and.presentation.home.HomeViewModel +import org.sopt.and.presentation.login.LoginScreen +import org.sopt.and.presentation.login.LoginViewModel +import org.sopt.and.presentation.mypage.MyScreen +import org.sopt.and.presentation.mypage.MyViewModel +import org.sopt.and.presentation.search.SearchScreen +import org.sopt.and.presentation.search.SearchViewModel +import org.sopt.and.presentation.signup.SignUpScreen +import org.sopt.and.presentation.signup.SignUpViewModel import org.sopt.and.utils.toast @Composable diff --git a/app/src/main/java/org/sopt/and/feature/main/Routes.kt b/app/src/main/java/org/sopt/and/presentation/main/Routes.kt similarity index 84% rename from app/src/main/java/org/sopt/and/feature/main/Routes.kt rename to app/src/main/java/org/sopt/and/presentation/main/Routes.kt index d235d93..ee8123e 100644 --- a/app/src/main/java/org/sopt/and/feature/main/Routes.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/Routes.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.main +package org.sopt.and.presentation.main sealed class Routes (val screen: String){ object SignUp: Routes("signup") diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt similarity index 91% rename from app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt rename to app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt index 2b30da0..1e1203a 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.mypage +package org.sopt.and.presentation.mypage import android.content.Context import androidx.compose.foundation.background @@ -19,9 +19,9 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import org.sopt.and.R -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.presentation.core.component.EmptyBox +import org.sopt.and.presentation.core.component.ProfileBox +import org.sopt.and.presentation.core.component.TicketBox import org.sopt.and.ui.theme.WavveTheme @Composable diff --git a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt similarity index 93% rename from app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt rename to app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt index d9f1ea5..cf13a12 100644 --- a/app/src/main/java/org/sopt/and/feature/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.mypage +package org.sopt.and.presentation.mypage import android.util.Log import androidx.compose.runtime.State @@ -8,7 +8,7 @@ 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.di.ServicePool import org.sopt.and.data.remote.model.response.UserHobbyResponseDto class MyViewModel : ViewModel() { diff --git a/app/src/main/java/org/sopt/and/feature/search/SearchScreen.kt b/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt similarity index 96% rename from app/src/main/java/org/sopt/and/feature/search/SearchScreen.kt rename to app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt index 17179b5..314b492 100644 --- a/app/src/main/java/org/sopt/and/feature/search/SearchScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.search +package org.sopt.and.presentation.search import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/app/src/main/java/org/sopt/and/feature/search/SearchViewModel.kt b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt similarity index 65% rename from app/src/main/java/org/sopt/and/feature/search/SearchViewModel.kt rename to app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt index f3cb802..bf42189 100644 --- a/app/src/main/java/org/sopt/and/feature/search/SearchViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.search +package org.sopt.and.presentation.search import androidx.lifecycle.ViewModel diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt similarity index 98% rename from app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt rename to app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt index a1da24a..3aebd6f 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.signup +package org.sopt.and.presentation.signup import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.compose.foundation.background @@ -49,9 +49,9 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel 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.WavveSignUpButton +import org.sopt.and.presentation.core.component.AuthTextField +import org.sopt.and.presentation.core.component.ErrorDialog +import org.sopt.and.presentation.core.component.WavveSignUpButton import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable diff --git a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt similarity index 98% rename from app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt rename to app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt index c46883f..9b19cbe 100644 --- a/app/src/main/java/org/sopt/and/feature/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt @@ -1,4 +1,4 @@ -package org.sopt.and.feature.signup +package org.sopt.and.presentation.signup import android.content.Context import android.util.Log @@ -12,7 +12,7 @@ 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.di.ServicePool 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 From b808a91391e72de05addd98661b88c9d53584d62 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 15:08:40 +0900 Subject: [PATCH 02/14] =?UTF-8?q?#10=20[feat]=20:=20api=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{remote/model => local}/TodayTopData.kt | 2 +- .../mapper/todata/UserLoginModelMapper.kt | 4 +- .../mapper/todata/UserSignUpModelMapper.kt | 5 +- .../todomain/UserHobbyResponseDtoMapper.kt | 1 + .../todomain/UserSignUpResponseDtoMapper.kt | 8 +++ .../todomain/UserTokenResponseDtoMapper.kt | 8 +++ .../remote/datasource/UserDataRemoteSource.kt | 14 +++++ .../data/remote/datasource/UserDataSource.kt | 7 --- .../UserDataRemoteSourceImpl.kt | 26 +++++++++ .../datasourceimpl/UserDataSourceImpl.kt | 11 ---- .../data/remote/utils/ApiResponseHandler.kt | 11 ++++ .../repositoryimpl/UserHobbyRepositoryImpl.kt | 10 ---- .../data/repositoryimpl/UserRepositoryImpl.kt | 35 ++++++++++++ .../domain/repository/UserHobbyRepository.kt | 4 -- .../and/domain/repository/UserRepository.kt | 13 +++++ .../presentation/core/component/CustomBox.kt | 2 +- .../and/presentation/home/HomeViewModel.kt | 2 +- .../and/presentation/login/LoginScreen.kt | 9 ++- .../sopt/and/presentation/login/LoginState.kt | 10 ++++ .../and/presentation/login/LoginViewModel.kt | 56 +++++++++++-------- .../sopt/and/presentation/main/NavGraph.kt | 1 - 21 files changed, 178 insertions(+), 61 deletions(-) rename app/src/main/java/org/sopt/and/data/{remote/model => local}/TodayTopData.kt (64%) create mode 100644 app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt create mode 100644 app/src/main/java/org/sopt/and/data/mapper/todomain/UserTokenResponseDtoMapper.kt create mode 100644 app/src/main/java/org/sopt/and/data/remote/datasource/UserDataRemoteSource.kt delete mode 100644 app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt create mode 100644 app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt delete mode 100644 app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt create mode 100644 app/src/main/java/org/sopt/and/data/remote/utils/ApiResponseHandler.kt delete mode 100644 app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt create mode 100644 app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt delete mode 100644 app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt create mode 100644 app/src/main/java/org/sopt/and/domain/repository/UserRepository.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/login/LoginState.kt diff --git a/app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt b/app/src/main/java/org/sopt/and/data/local/TodayTopData.kt similarity index 64% rename from app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt rename to app/src/main/java/org/sopt/and/data/local/TodayTopData.kt index 8ad0d84..dafa5c2 100644 --- a/app/src/main/java/org/sopt/and/data/remote/model/TodayTopData.kt +++ b/app/src/main/java/org/sopt/and/data/local/TodayTopData.kt @@ -1,4 +1,4 @@ -package org.sopt.and.data.remote.model +package org.sopt.and.data.local data class TodayTopData( val painterId: Int, diff --git a/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt index bd3d906..47e6be0 100644 --- a/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt +++ b/app/src/main/java/org/sopt/and/data/mapper/todata/UserLoginModelMapper.kt @@ -1,7 +1,9 @@ package org.sopt.and.data.mapper.todata +import org.sopt.and.data.remote.model.request.UserLoginRequestDto import org.sopt.and.domain.model.request.UserLoginModel fun UserLoginModel.toData() : UserLoginRequestDto = UserLoginRequestDto( - + username = this.username, + password = this.password ) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt index 15ff091..e5e58f9 100644 --- a/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt +++ b/app/src/main/java/org/sopt/and/data/mapper/todata/UserSignUpModelMapper.kt @@ -1,7 +1,10 @@ package org.sopt.and.data.mapper.todata +import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.domain.model.request.UserSignUpModel fun UserSignUpModel.toData() : UserSignUpRequestDto = UserSignUpRequestDto( - + username = this.username, + password = this.password, + hobby = this.hobby ) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt index c28ab8d..6311a29 100644 --- a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt +++ b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserHobbyResponseDtoMapper.kt @@ -1,5 +1,6 @@ package org.sopt.and.data.mapper.todomain +import org.sopt.and.data.remote.model.response.UserHobbyResponseDto import org.sopt.and.domain.model.response.Hobby fun UserHobbyResponseDto.toDomain(): Hobby = Hobby( diff --git a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt new file mode 100644 index 0000000..6e8bf61 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt @@ -0,0 +1,8 @@ +package org.sopt.and.data.mapper.todomain + +import org.sopt.and.data.remote.model.response.UserSignUpResponseDto +import org.sopt.and.domain.model.response.UserNumber + +fun UserSignUpResponseDto.toDomain(): UserNumber = UserNumber( + no = this.no +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserTokenResponseDtoMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserTokenResponseDtoMapper.kt new file mode 100644 index 0000000..51df841 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserTokenResponseDtoMapper.kt @@ -0,0 +1,8 @@ +package org.sopt.and.data.mapper.todomain + +import org.sopt.and.data.remote.model.response.UserTokenResponseDto +import org.sopt.and.domain.model.response.Token + +fun UserTokenResponseDto.toDomain(): Token = Token( + token = this.token +) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataRemoteSource.kt b/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataRemoteSource.kt new file mode 100644 index 0000000..6d49afc --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataRemoteSource.kt @@ -0,0 +1,14 @@ +package org.sopt.and.data.remote.datasource + +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 + +interface UserDataRemoteSource { + suspend fun postUserSignUp(userSignUpRequestDto: UserSignUpRequestDto): ApiResponse + suspend fun postUserLogin(userLoginRequestDto: UserLoginRequestDto): ApiResponse + suspend fun getUserHobby(token: String): ApiResponse +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt b/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt deleted file mode 100644 index 53b8167..0000000 --- a/app/src/main/java/org/sopt/and/data/remote/datasource/UserDataSource.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.sopt.and.data.remote.datasource - -interface UserDataSource { - suspend fun postUserSignUp() : ApiResponse - suspend fun postUserLogin() : ApiResponse - suspend fun getUserHobby() : ApiResponse -} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt new file mode 100644 index 0000000..f40597a --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt @@ -0,0 +1,26 @@ +package org.sopt.and.data.remote.datasourceimpl + +import org.sopt.and.data.remote.datasource.UserDataRemoteSource +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.service.UserService +import org.sopt.and.di.ServicePool + +class UserDataRemoteSourceImpl( + private val userService: UserService +) : UserDataRemoteSource { + + override suspend fun postUserSignUp(userSignUpRequestDto: UserSignUpRequestDto): ApiResponse = + userService.postUserSignUp(body = userSignUpRequestDto) + + override suspend fun postUserLogin(userLoginRequestDto: UserLoginRequestDto): ApiResponse = + userService.postUserLogin(body = userLoginRequestDto) + + + override suspend fun getUserHobby(token: String): ApiResponse = + userService.getUserHobby(token = token) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt deleted file mode 100644 index 790cae2..0000000 --- a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataSourceImpl.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.sopt.and.data.remote.datasourceimpl - -import org.sopt.and.data.remote.datasource.UserDataSource - -class UserDataSourceImpl @Inject constructor( - // private val -) : UserDataSource { - override suspend fun getUserHobby(): ApiResponse { - userService. - } -} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/remote/utils/ApiResponseHandler.kt b/app/src/main/java/org/sopt/and/data/remote/utils/ApiResponseHandler.kt new file mode 100644 index 0000000..f6f19d3 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/remote/utils/ApiResponseHandler.kt @@ -0,0 +1,11 @@ +package org.sopt.and.data.remote.utils + +import org.sopt.and.data.remote.model.base.ApiResponse + +fun ApiResponse.handleApiResponse(): Result { + return try { + Result.success(this.result) + } catch (e: Exception) { + Result.failure(e) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt deleted file mode 100644 index 79ffd88..0000000 --- a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserHobbyRepositoryImpl.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.sopt.and.data.repositoryimpl - -import org.sopt.and.data.remote.datasource.UserDataSource -import org.sopt.and.domain.repository.UserHobbyRepository - -class UserHobbyRepositoryImpl @Inject constructor( - private val userHobbyDataSource: UserDataSource -) : UserHobbyRepository { - -} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt new file mode 100644 index 0000000..845f1f9 --- /dev/null +++ b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt @@ -0,0 +1,35 @@ +package org.sopt.and.data.repositoryimpl + +import org.sopt.and.data.mapper.todata.toData +import org.sopt.and.data.mapper.todomain.toDomain +import org.sopt.and.data.remote.datasource.UserDataRemoteSource +import org.sopt.and.data.remote.utils.handleApiResponse +import org.sopt.and.domain.model.request.UserLoginModel +import org.sopt.and.domain.model.request.UserSignUpModel +import org.sopt.and.domain.model.response.Hobby +import org.sopt.and.domain.model.response.Token +import org.sopt.and.domain.model.response.UserNumber +import org.sopt.and.domain.repository.UserRepository + +class UserRepositoryImpl ( + private val userDataRemoteSource: UserDataRemoteSource +) : UserRepository { + + override suspend fun postUserSignUp(userSignUpModel: UserSignUpModel): Result { + return runCatching { + userDataRemoteSource.postUserSignUp(userSignUpModel.toData()).handleApiResponse().getOrThrow().toDomain() + } + } + + override suspend fun postUserLogin(userLoginModel: UserLoginModel): Result { + return runCatching { + userDataRemoteSource.postUserLogin(userLoginModel.toData()).handleApiResponse().getOrThrow().toDomain() + } + } + + override suspend fun getUserHobby(token: String): Result { + return runCatching { + userDataRemoteSource.getUserHobby(token = token).handleApiResponse().getOrThrow().toDomain() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt b/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt deleted file mode 100644 index aee0063..0000000 --- a/app/src/main/java/org/sopt/and/domain/repository/UserHobbyRepository.kt +++ /dev/null @@ -1,4 +0,0 @@ -package org.sopt.and.domain.repository - -interface UserHobbyRepository { -} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/domain/repository/UserRepository.kt b/app/src/main/java/org/sopt/and/domain/repository/UserRepository.kt new file mode 100644 index 0000000..d18fd2e --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/repository/UserRepository.kt @@ -0,0 +1,13 @@ +package org.sopt.and.domain.repository + +import org.sopt.and.domain.model.request.UserLoginModel +import org.sopt.and.domain.model.request.UserSignUpModel +import org.sopt.and.domain.model.response.Hobby +import org.sopt.and.domain.model.response.Token +import org.sopt.and.domain.model.response.UserNumber + +interface UserRepository { + suspend fun postUserSignUp(userSignUpModel: UserSignUpModel): Result + suspend fun postUserLogin(userLoginModel: UserLoginModel): Result + suspend fun getUserHobby(token: String): Result +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt index 6d7a91d..297d41e 100644 --- a/app/src/main/java/org/sopt/and/presentation/core/component/CustomBox.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/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.remote.model.TodayTopData +import org.sopt.and.data.local.TodayTopData import org.sopt.and.ui.theme.WavveTheme @Composable diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt index 4dc454f..95a446a 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/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.remote.model.TodayTopData +import org.sopt.and.data.local.TodayTopData class HomeViewModel : ViewModel() { private val _homeTabText = listOf( diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt index 868be7c..6c76042 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt @@ -29,6 +29,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -50,10 +51,15 @@ import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import org.sopt.and.R +import org.sopt.and.data.remote.datasourceimpl.UserDataRemoteSourceImpl import org.sopt.and.presentation.core.component.AuthTextField import org.sopt.and.presentation.core.component.SocialLoginButtonGroup import org.sopt.and.presentation.core.component.WavveLoginButton import org.sopt.and.data.remote.model.request.UserLoginRequestDto +import org.sopt.and.data.repositoryimpl.UserRepositoryImpl +import org.sopt.and.di.ServicePool +import org.sopt.and.domain.model.request.UserLoginModel +import org.sopt.and.domain.repository.UserRepository import org.sopt.and.presentation.main.Routes import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -72,6 +78,7 @@ fun LoginScreen( val editor = sharedPreferences.edit() + val loginState by viewModel.loginState.collectAsState() val token by viewModel.token.observeAsState("") val userName by viewModel.userName.observeAsState("") val password by viewModel.password.observeAsState("") @@ -178,7 +185,7 @@ fun LoginScreen( onClick = { viewModel.postUserLogin( context = context, - body = UserLoginRequestDto( + body = UserLoginModel( username = userName, password = password ), diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginState.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginState.kt new file mode 100644 index 0000000..e1b246f --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginState.kt @@ -0,0 +1,10 @@ +package org.sopt.and.presentation.login + +import org.sopt.and.domain.model.response.Token + +sealed class LoginState { + data object Idle: LoginState() + data object Loading: LoginState() + data class Success(val result: Token): LoginState() + data class Failure(val message: String): LoginState() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt index e179a3f..dfc0483 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt @@ -6,48 +6,60 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import okio.IOException import org.sopt.and.R import org.sopt.and.di.ServicePool -import org.sopt.and.data.remote.model.request.UserLoginRequestDto +import org.sopt.and.domain.model.request.UserLoginModel +import org.sopt.and.domain.repository.UserRepository import org.sopt.and.utils.toast import retrofit2.HttpException -class LoginViewModel : ViewModel() { - private val userService by lazy { ServicePool.userService } +class LoginViewModel( + private val userRepository: UserRepository +) : ViewModel() { + private val _loginState = MutableStateFlow(LoginState.Idle) + val loginState: StateFlow = _loginState private val _token = MutableLiveData(null) val token: LiveData get() = _token fun postUserLogin( context: Context, - body: UserLoginRequestDto, + body: UserLoginModel, ) { + _loginState.value = LoginState.Loading 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)) + val result = userRepository.postUserLogin( + userLoginModel = body + ) + _loginState.value = result.fold( + onSuccess = { response -> + _token.value = response.token + LoginState.Success(response) + }, + 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)) + } } - } - is IOException -> { - context.toast(context.getString(R.string.fail_to_network)) - } + is IOException -> { + context.toast(context.getString(R.string.fail_to_network)) + } - else -> { - context.toast(context.getString(R.string.fail_to_login)) + else -> { + context.toast(context.getString(R.string.fail_to_login)) + } } + LoginState.Failure(error.message.orEmpty()) } - Log.e("postUserLoginError", error.toString()) - } + ) } } diff --git a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt index cb03183..263a2aa 100644 --- a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt @@ -54,7 +54,6 @@ fun NavGraph( popUpTo(Routes.Home.screen) { inclusive = true } } }, - viewModel = LoginViewModel() ) } composable(Routes.SignUp.screen) { From 9c4ccf4caf548389d261b7071b67beb44d73defa Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 15:24:17 +0900 Subject: [PATCH 03/14] =?UTF-8?q?#10=20[add]=20:=20hilt=20dependencies=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/build.gradle.kts | 7 +++++++ gradle/libs.versions.toml | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a18a009..3e9b79d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,6 +5,8 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.hilt.android) + id("kotlin-kapt") } val properties = Properties().apply { @@ -49,6 +51,11 @@ android { } dependencies { + // Hilt + implementation(libs.hilt.android) + implementation(libs.hilt.navigation.compose) + implementation(libs.androidx.appcompat) + kapt(libs.hilt.compiler) // Network implementation(platform(libs.okhttp.bom)) implementation(libs.okhttp) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2737244..a5697db 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,9 @@ okhttp = "4.11.0" retrofit = "2.9.0" retrofitKotlinSerializationConverter = "1.0.0" kotlinxSerializationJson = "1.6.3" +# hilt +androidx-hilt-navigation-compose = "1.2.0" +hilt = "2.51.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -46,9 +49,14 @@ okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-i retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } retrofit-kotlin-serialization-converter = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "retrofitKotlinSerializationConverter" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +# hilt +hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } +hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } +hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidx-hilt-navigation-compose" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } \ No newline at end of file From 9baff1bfa1ed675f13ffd6c98262cba7e7086480 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 15:28:38 +0900 Subject: [PATCH 04/14] =?UTF-8?q?#10=20[feat]=20:=20hilt=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/org/sopt/and/WavveApp.kt | 17 +++++++++++++++++ .../sopt/and/presentation/main/MainActivity.kt | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/WavveApp.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6c0a596..b5a93b8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ Date: Wed, 4 Dec 2024 17:09:28 +0900 Subject: [PATCH 05/14] =?UTF-8?q?#10=20[feat]=20:=20module=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20LoginViewModel=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 + .../UserDataRemoteSourceImpl.kt | 4 +- .../data/repositoryimpl/UserRepositoryImpl.kt | 3 +- .../java/org/sopt/and/di/DataSourceModule.kt | 19 ++++ .../java/org/sopt/and/di/NetworkModule.kt | 90 +++++++++++++++++++ .../java/org/sopt/and/di/RepositoryModule.kt | 20 +++++ .../java/org/sopt/and/di/ServiceModule.kt | 18 ++++ .../and/presentation/login/LoginScreen.kt | 26 +++--- .../and/presentation/login/LoginViewModel.kt | 10 ++- 9 files changed, 174 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/di/DataSourceModule.kt create mode 100644 app/src/main/java/org/sopt/and/di/NetworkModule.kt create mode 100644 app/src/main/java/org/sopt/and/di/RepositoryModule.kt create mode 100644 app/src/main/java/org/sopt/and/di/ServiceModule.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3e9b79d..3b85493 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -48,6 +48,10 @@ android { compose = true buildConfig = true } + + hilt { + enableAggregatingTask = false + } } dependencies { diff --git a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt index f40597a..9415dd2 100644 --- a/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt +++ b/app/src/main/java/org/sopt/and/data/remote/datasourceimpl/UserDataRemoteSourceImpl.kt @@ -8,9 +8,9 @@ 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.service.UserService -import org.sopt.and.di.ServicePool +import javax.inject.Inject -class UserDataRemoteSourceImpl( +class UserDataRemoteSourceImpl @Inject constructor( private val userService: UserService ) : UserDataRemoteSource { diff --git a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt index 845f1f9..989aeb2 100644 --- a/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt +++ b/app/src/main/java/org/sopt/and/data/repositoryimpl/UserRepositoryImpl.kt @@ -10,8 +10,9 @@ import org.sopt.and.domain.model.response.Hobby import org.sopt.and.domain.model.response.Token import org.sopt.and.domain.model.response.UserNumber import org.sopt.and.domain.repository.UserRepository +import javax.inject.Inject -class UserRepositoryImpl ( +class UserRepositoryImpl @Inject constructor( private val userDataRemoteSource: UserDataRemoteSource ) : UserRepository { diff --git a/app/src/main/java/org/sopt/and/di/DataSourceModule.kt b/app/src/main/java/org/sopt/and/di/DataSourceModule.kt new file mode 100644 index 0000000..ed50f7f --- /dev/null +++ b/app/src/main/java/org/sopt/and/di/DataSourceModule.kt @@ -0,0 +1,19 @@ +package org.sopt.and.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import org.sopt.and.data.remote.datasource.UserDataRemoteSource +import org.sopt.and.data.remote.datasourceimpl.UserDataRemoteSourceImpl +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class DataSourceModule { + @Binds + @Singleton + abstract fun bindUserDataRemoteSource( + userDataRemoteSourceImpl: UserDataRemoteSourceImpl + ): UserDataRemoteSource +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/di/NetworkModule.kt b/app/src/main/java/org/sopt/and/di/NetworkModule.kt new file mode 100644 index 0000000..388eed2 --- /dev/null +++ b/app/src/main/java/org/sopt/and/di/NetworkModule.kt @@ -0,0 +1,90 @@ +package org.sopt.and.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.Interceptor +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.sopt.and.BuildConfig +import retrofit2.Retrofit +import java.util.concurrent.TimeUnit +import javax.inject.Qualifier +import javax.inject.Singleton + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class Wavve + +@Module +@InstallIn(SingletonComponent::class) +object NetworkModule { + @Provides + @Singleton + fun providesOkHttpClient( + loggingInterceptor: HttpLoggingInterceptor, + authInterceptor: Interceptor + ): OkHttpClient = + OkHttpClient.Builder().apply { + connectTimeout(10, TimeUnit.SECONDS) + writeTimeout(10, TimeUnit.SECONDS) + readTimeout(10, TimeUnit.SECONDS) + addInterceptor(authInterceptor) + }.build() + + @Provides + @Singleton + fun providesJson(): Json = + Json { + isLenient = true + prettyPrint = true + explicitNulls = false + ignoreUnknownKeys = true + } + + @Provides + @Singleton + fun provideLoggingInterceptor(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + + @Provides + @Singleton + fun provideAuthInterceptor(): Interceptor = Interceptor { chain -> + val request = chain.request().newBuilder() + .addHeader("Authorization", "Bearer ") + .build() + chain.proceed(request) + } + + @Provides + @Singleton + fun provideRetrofit( + okHttpClient: OkHttpClient, + json: Json + ): Retrofit { + return Retrofit.Builder() + .baseUrl(BuildConfig.BASE_URL) + .client(okHttpClient) + .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) + .build() + } + + @Provides + @Singleton + @Wavve + fun provideWavveRetrofit( + okHttpClient: OkHttpClient, + json: Json + ): Retrofit { + return Retrofit.Builder() + .baseUrl(BuildConfig.BASE_URL) + .client(okHttpClient) + .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) + .build() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/di/RepositoryModule.kt b/app/src/main/java/org/sopt/and/di/RepositoryModule.kt new file mode 100644 index 0000000..398f170 --- /dev/null +++ b/app/src/main/java/org/sopt/and/di/RepositoryModule.kt @@ -0,0 +1,20 @@ +package org.sopt.and.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import org.sopt.and.data.repositoryimpl.UserRepositoryImpl +import org.sopt.and.domain.repository.UserRepository +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class RepositoryModule { + @Binds + @Singleton + abstract fun bindUserRepository( + userRepositoryImpl: UserRepositoryImpl + ): UserRepository + +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/di/ServiceModule.kt b/app/src/main/java/org/sopt/and/di/ServiceModule.kt new file mode 100644 index 0000000..48ef2c5 --- /dev/null +++ b/app/src/main/java/org/sopt/and/di/ServiceModule.kt @@ -0,0 +1,18 @@ +package org.sopt.and.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import org.sopt.and.data.remote.service.UserService +import retrofit2.Retrofit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object ServiceModule { + @Provides + @Singleton + fun provideUserService(@Wavve retrofit: Retrofit): UserService = + retrofit.create(UserService::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt index 6c76042..05e4b23 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginScreen.kt @@ -48,18 +48,13 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import org.sopt.and.R -import org.sopt.and.data.remote.datasourceimpl.UserDataRemoteSourceImpl +import org.sopt.and.domain.model.request.UserLoginModel import org.sopt.and.presentation.core.component.AuthTextField import org.sopt.and.presentation.core.component.SocialLoginButtonGroup import org.sopt.and.presentation.core.component.WavveLoginButton -import org.sopt.and.data.remote.model.request.UserLoginRequestDto -import org.sopt.and.data.repositoryimpl.UserRepositoryImpl -import org.sopt.and.di.ServicePool -import org.sopt.and.domain.model.request.UserLoginModel -import org.sopt.and.domain.repository.UserRepository import org.sopt.and.presentation.main.Routes import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -69,7 +64,7 @@ import org.sopt.and.utils.noRippleClickable fun LoginScreen( navController: NavController, onLoginSuccess: (String, String) -> Unit, - viewModel: LoginViewModel = viewModel() + viewModel: LoginViewModel = hiltViewModel() ) { val context = LocalContext.current val focusManager = LocalFocusManager.current @@ -187,15 +182,16 @@ fun LoginScreen( context = context, body = UserLoginModel( username = userName, - password = password + password = password, ), + onSuccess = { + editor.putString(context.getString(R.string.login_token), token) + editor.apply() + onLoginSuccess(userName, password) + //키보드 내리기 + focusManager.clearFocus() + } ) - - 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/presentation/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt index dfc0483..37e4201 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt @@ -6,18 +6,20 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import okio.IOException import org.sopt.and.R -import org.sopt.and.di.ServicePool import org.sopt.and.domain.model.request.UserLoginModel import org.sopt.and.domain.repository.UserRepository import org.sopt.and.utils.toast import retrofit2.HttpException +import javax.inject.Inject -class LoginViewModel( +@HiltViewModel +class LoginViewModel @Inject constructor( private val userRepository: UserRepository ) : ViewModel() { private val _loginState = MutableStateFlow(LoginState.Idle) @@ -29,6 +31,7 @@ class LoginViewModel( fun postUserLogin( context: Context, body: UserLoginModel, + onSuccess: () -> Unit ) { _loginState.value = LoginState.Loading viewModelScope.launch { @@ -37,7 +40,9 @@ class LoginViewModel( ) _loginState.value = result.fold( onSuccess = { response -> + Log.d("LoginSuccess", response.token) _token.value = response.token + onSuccess() LoginState.Success(response) }, onFailure = { error -> @@ -50,6 +55,7 @@ class LoginViewModel( } is IOException -> { + Log.e("NetworkError", "IOException occurred: ${error.message}") context.toast(context.getString(R.string.fail_to_network)) } From 2ef04499f9adbb7b78ab1d8840a4bb1d50145a47 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 17:22:13 +0900 Subject: [PATCH 06/14] =?UTF-8?q?#10=20[feat]=20:=20SignUpApi=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/and/presentation/main/NavGraph.kt | 5 -- .../and/presentation/signup/SignUpScreen.kt | 8 +-- .../and/presentation/signup/SignUpState.kt | 10 +++ .../presentation/signup/SignUpViewModel.kt | 62 +++++++++++-------- 4 files changed, 49 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/signup/SignUpState.kt diff --git a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt index 263a2aa..8efc202 100644 --- a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt @@ -15,13 +15,10 @@ import org.sopt.and.R import org.sopt.and.presentation.home.HomeScreen import org.sopt.and.presentation.home.HomeViewModel import org.sopt.and.presentation.login.LoginScreen -import org.sopt.and.presentation.login.LoginViewModel import org.sopt.and.presentation.mypage.MyScreen -import org.sopt.and.presentation.mypage.MyViewModel import org.sopt.and.presentation.search.SearchScreen import org.sopt.and.presentation.search.SearchViewModel import org.sopt.and.presentation.signup.SignUpScreen -import org.sopt.and.presentation.signup.SignUpViewModel import org.sopt.and.utils.toast @Composable @@ -64,7 +61,6 @@ fun NavGraph( popUpTo(Routes.Login.screen) { inclusive = true } } }, - viewModel = SignUpViewModel() ) } composable(Routes.Home.screen) { @@ -77,7 +73,6 @@ fun NavGraph( composable(Routes.My.screen) { MyScreen( navController = navController, - viewModel = MyViewModel() ) } } diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt index 3aebd6f..eaf270c 100644 --- a/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpScreen.kt @@ -46,13 +46,13 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import org.sopt.and.R +import org.sopt.and.domain.model.request.UserSignUpModel import org.sopt.and.presentation.core.component.AuthTextField import org.sopt.and.presentation.core.component.ErrorDialog import org.sopt.and.presentation.core.component.WavveSignUpButton -import org.sopt.and.data.remote.model.request.UserSignUpRequestDto import org.sopt.and.ui.theme.WavveTheme import org.sopt.and.utils.noRippleClickable @@ -61,7 +61,7 @@ import org.sopt.and.utils.noRippleClickable fun SignUpScreen( navController: NavController, onSignUpSuccess: (String, String) -> Unit, - viewModel: SignUpViewModel = viewModel() + viewModel: SignUpViewModel = hiltViewModel() ) { val focusManager = LocalFocusManager.current val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher @@ -243,7 +243,7 @@ fun SignUpScreen( onSuccess = { userName, password, hobby -> viewModel.postUserSignUp( context = context, - body = UserSignUpRequestDto( + body = UserSignUpModel( username = userName, password = password, hobby = hobby diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpState.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpState.kt new file mode 100644 index 0000000..d4d0863 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpState.kt @@ -0,0 +1,10 @@ +package org.sopt.and.presentation.signup + +import org.sopt.and.domain.model.response.UserNumber + +sealed class SignUpState { + data object Idle : SignUpState() + data object Loading : SignUpState() + data class Success(val result: UserNumber) : SignUpState() + data class Failure(val message: String) : SignUpState() +} diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt index 9b19cbe..d36e47e 100644 --- a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt @@ -10,47 +10,55 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import org.sopt.and.R -import org.sopt.and.di.ServicePool -import org.sopt.and.data.remote.model.request.UserSignUpRequestDto -import org.sopt.and.data.remote.model.response.UserSignUpResponseDto +import org.sopt.and.domain.model.request.UserSignUpModel +import org.sopt.and.domain.repository.UserRepository import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN import org.sopt.and.utils.toast import retrofit2.HttpException import java.io.IOException +import javax.inject.Inject -class SignUpViewModel : ViewModel() { - private val userService by lazy { ServicePool.userService } +@HiltViewModel +class SignUpViewModel @Inject constructor( + private val userRepository: UserRepository +) : ViewModel() { + private val _signUpState = mutableStateOf(SignUpState.Idle) + val signUpState: State get() = _signUpState - private val _userState = mutableStateOf(null) - val userState: State get() = _userState - - fun postUserSignUp(context: Context, body: UserSignUpRequestDto) { + fun postUserSignUp(context: Context, body: UserSignUpModel) { + _signUpState.value = SignUpState.Loading 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)) + val result = userRepository.postUserSignUp( + userSignUpModel = body + ) + _signUpState.value = result.fold( + onSuccess = { response -> + Log.d("SignUpSuccess", response.no.toString()) + SignUpState.Success(response) + }, + 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)) - } + is IOException -> { + context.toast(context.getString(R.string.fail_to_network)) + } - else -> { - context.toast(context.getString(R.string.fail_to_signup)) + else -> { + context.toast(context.getString(R.string.fail_to_signup)) + } } + SignUpState.Failure(error.message.orEmpty()) } - Log.e("postUserSignUpError", error.toString()) - } + ) } } From 6753a6f4023793da0488108c01f463fbe26dee4a Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 17:36:33 +0900 Subject: [PATCH 07/14] =?UTF-8?q?#10=20[feat]=20:=20Hobby=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/and/presentation/mypage/MyScreen.kt | 9 ++-- .../sopt/and/presentation/mypage/MyState.kt | 10 +++++ .../and/presentation/mypage/MyViewModel.kt | 41 +++++++++++-------- 3 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/mypage/MyState.kt diff --git a/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt index 1e1203a..1d7ba00 100644 --- a/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyScreen.kt @@ -10,13 +10,14 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import org.sopt.and.R import org.sopt.and.presentation.core.component.EmptyBox @@ -27,13 +28,15 @@ import org.sopt.and.ui.theme.WavveTheme @Composable fun MyScreen( navController: NavController, - viewModel: MyViewModel = viewModel() + viewModel: MyViewModel = hiltViewModel() ) { val context = LocalContext.current val sharedPreferences = context.getSharedPreferences("token", Context.MODE_PRIVATE) val token = sharedPreferences.getString("loginToken", "").orEmpty() - viewModel.getUserHobby(token = token) + LaunchedEffect(Unit) { + viewModel.getUserHobby(token = token) + } val hobby by viewModel.hobby.observeAsState("") diff --git a/app/src/main/java/org/sopt/and/presentation/mypage/MyState.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyState.kt new file mode 100644 index 0000000..03dba23 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyState.kt @@ -0,0 +1,10 @@ +package org.sopt.and.presentation.mypage + +import org.sopt.and.domain.model.response.Hobby + +sealed class MyState { + data object Idle : MyState() + data object Loading : MyState() + data class Success(val result: Hobby) : MyState() + data class Failure(val message: String) : MyState() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt index cf13a12..f3991c4 100644 --- a/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt @@ -1,35 +1,42 @@ package org.sopt.and.presentation.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 androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import org.sopt.and.di.ServicePool -import org.sopt.and.data.remote.model.response.UserHobbyResponseDto +import org.sopt.and.domain.repository.UserRepository +import javax.inject.Inject -class MyViewModel : ViewModel() { - private val userService by lazy { ServicePool.userService } - - private val _userState = mutableStateOf(null) - val userState: State get() = _userState +@HiltViewModel +class MyViewModel @Inject constructor( + private val userRepository: UserRepository +) : ViewModel() { + private val _myState = MutableStateFlow(MyState.Idle) + val myState: StateFlow get() = _myState private val _hobby = MutableLiveData("") val hobby: LiveData get() = _hobby fun getUserHobby(token: String) { + _myState.value = MyState.Loading 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()) - } + val result = userRepository.getUserHobby(token = token) + _myState.value = result.fold( + onSuccess = { response -> + Log.d("HobbySuccess", response.hobby) + _hobby.value = response.hobby + MyState.Success(response) + }, + onFailure = { error -> + Log.e("getUserHobbyError", error.toString()) + MyState.Failure(error.message.toString()) + } + ) } } } \ No newline at end of file From 577186a7d7d8d856fabc3d89d170080d1ce3e3c0 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 17:48:52 +0900 Subject: [PATCH 08/14] =?UTF-8?q?#10=20[feat]=20:=20HomeTabType=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/domain/type/HomeTabType.kt | 24 +++++++++++++++++++ .../core/component/CustomTabBar.kt | 5 ++-- .../sopt/and/presentation/home/HomeScreen.kt | 2 +- .../and/presentation/home/HomeViewModel.kt | 16 ++----------- 4 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/domain/type/HomeTabType.kt diff --git a/app/src/main/java/org/sopt/and/domain/type/HomeTabType.kt b/app/src/main/java/org/sopt/and/domain/type/HomeTabType.kt new file mode 100644 index 0000000..29a92c0 --- /dev/null +++ b/app/src/main/java/org/sopt/and/domain/type/HomeTabType.kt @@ -0,0 +1,24 @@ +package org.sopt.and.domain.type + +enum class HomeTabType( + val text: String, +) { + NEW_CLASSIC( + text = "뉴클래식" + ), + DRAMA( + text = "드라마" + ), + VARIETY_SHOW( + text = "예능" + ), + MOVIE( + text = "영화" + ), + ANIMATION( + text = "애니" + ), + OVERSEAS_SERIES( + text = "해외시리즈" + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt index 2bce3e3..c7700c6 100644 --- a/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt +++ b/app/src/main/java/org/sopt/and/presentation/core/component/CustomTabBar.kt @@ -12,12 +12,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import org.sopt.and.domain.type.HomeTabType import org.sopt.and.ui.theme.WavveTheme @Composable fun WavveTabBar( - tabTitles: List, modifier: Modifier = Modifier + tabTitles: Array, modifier: Modifier = Modifier ) { var selectedTabIndex by remember { mutableIntStateOf(0) } @@ -35,7 +36,7 @@ fun WavveTabBar( onClick = { selectedTabIndex = index }, text = { Text( - text = tab, + text = tab.text, fontSize = 18.sp, color = if (selectedTabIndex == index) Color.White else Color.Gray ) diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt index 087fdca..9111b8d 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt @@ -93,7 +93,7 @@ fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewMode .fillMaxSize() .verticalScroll(scrollState) ) { - WavveTabBar(viewModel.homeTabText) + WavveTabBar(tabTitles = viewModel.homeTabText) HorizontalPager( modifier = Modifier diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt index 95a446a..225ffd7 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt @@ -1,24 +1,12 @@ package org.sopt.and.presentation.home -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.local.TodayTopData +import org.sopt.and.domain.type.HomeTabType class HomeViewModel : ViewModel() { - private val _homeTabText = listOf( - R.string.new_classic, - R.string.drama, - R.string.variety_show, - R.string.movie, - R.string.animation, - R.string.overseas_series - ) - - val homeTabText: List - @Composable - get() = _homeTabText.map { stringResource(it) } + val homeTabText = HomeTabType.entries.toTypedArray() val editorDummy = List(20) { TodayTopData( From 3275b4e3eca7d1385bc38308114d483e40e88157 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Wed, 4 Dec 2024 17:49:44 +0900 Subject: [PATCH 09/14] =?UTF-8?q?#10=20[del]=20:=20ApiFactory=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/di/ApiFactory.kt | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 app/src/main/java/org/sopt/and/di/ApiFactory.kt diff --git a/app/src/main/java/org/sopt/and/di/ApiFactory.kt b/app/src/main/java/org/sopt/and/di/ApiFactory.kt deleted file mode 100644 index f13afbd..0000000 --- a/app/src/main/java/org/sopt/and/di/ApiFactory.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.sopt.and.di - -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.remote.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 From d379fb7d8d9417d8eec69efa0a8c9befb50f1e94 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 9 Dec 2024 12:54:01 +0900 Subject: [PATCH 10/14] =?UTF-8?q?#10=20[chore]=20:=20signup=20response=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt | 2 +- .../and/data/remote/model/response/UserSignUpResponseDto.kt | 2 +- .../main/java/org/sopt/and/domain/model/response/UserNumber.kt | 2 +- .../java/org/sopt/and/presentation/signup/SignUpViewModel.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt index 6e8bf61..5ed6022 100644 --- a/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt +++ b/app/src/main/java/org/sopt/and/data/mapper/todomain/UserSignUpResponseDtoMapper.kt @@ -4,5 +4,5 @@ import org.sopt.and.data.remote.model.response.UserSignUpResponseDto import org.sopt.and.domain.model.response.UserNumber fun UserSignUpResponseDto.toDomain(): UserNumber = UserNumber( - no = this.no + userId = this.userId ) \ 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 6609fd9..42aa942 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 @@ -7,5 +7,5 @@ import kotlinx.serialization.Serializable @Serializable data class UserSignUpResponseDto( @SerialName("no") - val no: Int + val userId: Int ) \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt b/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt index e6a2381..c951271 100644 --- a/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt +++ b/app/src/main/java/org/sopt/and/domain/model/response/UserNumber.kt @@ -1,5 +1,5 @@ package org.sopt.and.domain.model.response data class UserNumber( - val no: Int + val userId: Int ) diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt index d36e47e..a0fba29 100644 --- a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt @@ -36,7 +36,7 @@ class SignUpViewModel @Inject constructor( ) _signUpState.value = result.fold( onSuccess = { response -> - Log.d("SignUpSuccess", response.no.toString()) + Log.d("SignUpSuccess", response.userId.toString()) SignUpState.Success(response) }, onFailure = { error -> From 76bab7abb156f6ee2aa26d04e91dd0a061c5c2b7 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 9 Dec 2024 13:04:39 +0900 Subject: [PATCH 11/14] =?UTF-8?q?#10=20[del]=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20Qualifier=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/di/NetworkModule.kt | 18 ------------------ .../main/java/org/sopt/and/di/ServiceModule.kt | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/app/src/main/java/org/sopt/and/di/NetworkModule.kt b/app/src/main/java/org/sopt/and/di/NetworkModule.kt index 388eed2..22ed31f 100644 --- a/app/src/main/java/org/sopt/and/di/NetworkModule.kt +++ b/app/src/main/java/org/sopt/and/di/NetworkModule.kt @@ -13,12 +13,8 @@ import okhttp3.logging.HttpLoggingInterceptor import org.sopt.and.BuildConfig import retrofit2.Retrofit import java.util.concurrent.TimeUnit -import javax.inject.Qualifier import javax.inject.Singleton -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class Wavve @Module @InstallIn(SingletonComponent::class) @@ -63,20 +59,6 @@ object NetworkModule { @Provides @Singleton - fun provideRetrofit( - okHttpClient: OkHttpClient, - json: Json - ): Retrofit { - return Retrofit.Builder() - .baseUrl(BuildConfig.BASE_URL) - .client(okHttpClient) - .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) - .build() - } - - @Provides - @Singleton - @Wavve fun provideWavveRetrofit( okHttpClient: OkHttpClient, json: Json diff --git a/app/src/main/java/org/sopt/and/di/ServiceModule.kt b/app/src/main/java/org/sopt/and/di/ServiceModule.kt index 48ef2c5..6afb689 100644 --- a/app/src/main/java/org/sopt/and/di/ServiceModule.kt +++ b/app/src/main/java/org/sopt/and/di/ServiceModule.kt @@ -13,6 +13,6 @@ import javax.inject.Singleton object ServiceModule { @Provides @Singleton - fun provideUserService(@Wavve retrofit: Retrofit): UserService = + fun provideUserService(retrofit: Retrofit): UserService = retrofit.create(UserService::class.java) } \ No newline at end of file From 930e91745b826ac1ffbbe1994d4b3f30c2b35f7c Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 9 Dec 2024 13:09:58 +0900 Subject: [PATCH 12/14] =?UTF-8?q?#10=20[chore]=20:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=B0=20hiltViewModel=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/presentation/home/HomeScreen.kt | 4 ++-- .../java/org/sopt/and/presentation/home/HomeViewModel.kt | 2 ++ .../main/java/org/sopt/and/presentation/main/NavGraph.kt | 6 ++---- .../java/org/sopt/and/presentation/search/SearchScreen.kt | 4 ++-- .../org/sopt/and/presentation/search/SearchViewModel.kt | 2 ++ 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt index 9111b8d..7ae8d31 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt @@ -36,7 +36,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import org.sopt.and.R import org.sopt.and.presentation.core.component.Banner @@ -47,7 +47,7 @@ import org.sopt.and.ui.theme.WavveTheme @OptIn(ExperimentalMaterial3Api::class) @Composable -fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewModel()) { +fun HomeScreen(navController: NavController, viewModel: HomeViewModel = hiltViewModel()) { val scrollState = rememberScrollState() val pagerState = rememberPagerState( pageCount = { 6 } diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt index 225ffd7..6cf631d 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt @@ -1,10 +1,12 @@ package org.sopt.and.presentation.home import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel import org.sopt.and.R import org.sopt.and.data.local.TodayTopData import org.sopt.and.domain.type.HomeTabType +@HiltViewModel class HomeViewModel : ViewModel() { val homeTabText = HomeTabType.entries.toTypedArray() diff --git a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt index 8efc202..dcafde9 100644 --- a/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt +++ b/app/src/main/java/org/sopt/and/presentation/main/NavGraph.kt @@ -13,11 +13,9 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import org.sopt.and.R import org.sopt.and.presentation.home.HomeScreen -import org.sopt.and.presentation.home.HomeViewModel import org.sopt.and.presentation.login.LoginScreen import org.sopt.and.presentation.mypage.MyScreen import org.sopt.and.presentation.search.SearchScreen -import org.sopt.and.presentation.search.SearchViewModel import org.sopt.and.presentation.signup.SignUpScreen import org.sopt.and.utils.toast @@ -65,10 +63,10 @@ fun NavGraph( } composable(Routes.Home.screen) { isLoggedIn = true - HomeScreen(navController = navController, viewModel = HomeViewModel()) + HomeScreen(navController = navController) } composable(Routes.Search.screen) { - SearchScreen(navController = navController, viewModel = SearchViewModel()) + SearchScreen(navController = navController) } composable(Routes.My.screen) { MyScreen( diff --git a/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt b/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt index 314b492..29ceea7 100644 --- a/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/search/SearchScreen.kt @@ -9,12 +9,12 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import org.sopt.and.ui.theme.WavveTheme @Composable -fun SearchScreen(navController: NavController, viewModel: SearchViewModel = viewModel()) { +fun SearchScreen(navController: NavController, viewModel: SearchViewModel = hiltViewModel()) { Scaffold( modifier = Modifier.fillMaxSize(), ) { innerPadding -> diff --git a/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt index bf42189..fd8c436 100644 --- a/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt @@ -1,6 +1,8 @@ package org.sopt.and.presentation.search import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +@HiltViewModel class SearchViewModel : ViewModel() { } \ No newline at end of file From 388764e98c9a0f81817f8d0a56b764f9fbed8942 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 9 Dec 2024 13:11:13 +0900 Subject: [PATCH 13/14] =?UTF-8?q?#10=20[del]=20:=20log=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/sopt/and/presentation/login/LoginViewModel.kt | 2 -- .../main/java/org/sopt/and/presentation/mypage/MyViewModel.kt | 2 -- .../java/org/sopt/and/presentation/signup/SignUpViewModel.kt | 1 - 3 files changed, 5 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt index 37e4201..6fe6ead 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt @@ -40,7 +40,6 @@ class LoginViewModel @Inject constructor( ) _loginState.value = result.fold( onSuccess = { response -> - Log.d("LoginSuccess", response.token) _token.value = response.token onSuccess() LoginState.Success(response) @@ -55,7 +54,6 @@ class LoginViewModel @Inject constructor( } is IOException -> { - Log.e("NetworkError", "IOException occurred: ${error.message}") context.toast(context.getString(R.string.fail_to_network)) } diff --git a/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt index f3991c4..86d36ee 100644 --- a/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/mypage/MyViewModel.kt @@ -28,12 +28,10 @@ class MyViewModel @Inject constructor( val result = userRepository.getUserHobby(token = token) _myState.value = result.fold( onSuccess = { response -> - Log.d("HobbySuccess", response.hobby) _hobby.value = response.hobby MyState.Success(response) }, onFailure = { error -> - Log.e("getUserHobbyError", error.toString()) MyState.Failure(error.message.toString()) } ) diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt index a0fba29..51c33c7 100644 --- a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt @@ -36,7 +36,6 @@ class SignUpViewModel @Inject constructor( ) _signUpState.value = result.fold( onSuccess = { response -> - Log.d("SignUpSuccess", response.userId.toString()) SignUpState.Success(response) }, onFailure = { error -> From e8f5d4db1a70c3a0d6f6135a81563f5848240917 Mon Sep 17 00:00:00 2001 From: gitsuhyun Date: Mon, 9 Dec 2024 13:51:43 +0900 Subject: [PATCH 14/14] =?UTF-8?q?#10=20[feat]=20:=20ErrorHandler=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/home/HomeViewModel.kt | 4 ++- .../and/presentation/login/LoginViewModel.kt | 27 +++++----------- .../presentation/search/SearchViewModel.kt | 4 ++- .../presentation/signup/SignUpViewModel.kt | 27 +++++----------- .../java/org/sopt/and/utils/ErrorHandler.kt | 31 +++++++++++++++++++ 5 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/utils/ErrorHandler.kt diff --git a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt index 6cf631d..9d8f829 100644 --- a/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt @@ -5,9 +5,11 @@ import dagger.hilt.android.lifecycle.HiltViewModel import org.sopt.and.R import org.sopt.and.data.local.TodayTopData import org.sopt.and.domain.type.HomeTabType +import javax.inject.Inject @HiltViewModel -class HomeViewModel : ViewModel() { +class HomeViewModel @Inject constructor( +) : ViewModel() { val homeTabText = HomeTabType.entries.toTypedArray() val editorDummy = List(20) { diff --git a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt index 6fe6ead..0d55dd9 100644 --- a/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/login/LoginViewModel.kt @@ -1,7 +1,6 @@ package org.sopt.and.presentation.login import android.content.Context -import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -10,12 +9,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import okio.IOException import org.sopt.and.R import org.sopt.and.domain.model.request.UserLoginModel import org.sopt.and.domain.repository.UserRepository -import org.sopt.and.utils.toast -import retrofit2.HttpException +import org.sopt.and.utils.handleErrorToast import javax.inject.Inject @HiltViewModel @@ -45,22 +42,12 @@ class LoginViewModel @Inject constructor( LoginState.Success(response) }, 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)) - } - } - - is IOException -> { - context.toast(context.getString(R.string.fail_to_network)) - } - - else -> { - context.toast(context.getString(R.string.fail_to_login)) - } - } + handleErrorToast( + exception = error, + is400Error = R.string.fail_to_login, + is403Error = R.string.fail_to_login_invalid_password, + context = context + ) LoginState.Failure(error.message.orEmpty()) } ) diff --git a/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt index fd8c436..d789ce7 100644 --- a/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/search/SearchViewModel.kt @@ -2,7 +2,9 @@ package org.sopt.and.presentation.search import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject @HiltViewModel -class SearchViewModel : ViewModel() { +class SearchViewModel @Inject constructor( +) : ViewModel() { } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt index 51c33c7..38e3020 100644 --- a/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/signup/SignUpViewModel.kt @@ -1,7 +1,6 @@ package org.sopt.and.presentation.signup import android.content.Context -import android.util.Log import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -16,9 +15,7 @@ import org.sopt.and.R import org.sopt.and.domain.model.request.UserSignUpModel import org.sopt.and.domain.repository.UserRepository import org.sopt.and.utils.AuthKey.PASSWORD_PATTERN -import org.sopt.and.utils.toast -import retrofit2.HttpException -import java.io.IOException +import org.sopt.and.utils.handleErrorToast import javax.inject.Inject @HiltViewModel @@ -39,22 +36,12 @@ class SignUpViewModel @Inject constructor( SignUpState.Success(response) }, 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)) - } - } + handleErrorToast( + exception = error, + is400Error = R.string.fail_to_signup_maximum_length, + is409Error = R.string.fail_to_signup_duplicate_name, + context = context + ) SignUpState.Failure(error.message.orEmpty()) } ) diff --git a/app/src/main/java/org/sopt/and/utils/ErrorHandler.kt b/app/src/main/java/org/sopt/and/utils/ErrorHandler.kt new file mode 100644 index 0000000..551501a --- /dev/null +++ b/app/src/main/java/org/sopt/and/utils/ErrorHandler.kt @@ -0,0 +1,31 @@ +package org.sopt.and.utils + +import android.content.Context +import org.sopt.and.R +import retrofit2.HttpException +import java.io.IOException + +fun handleErrorToast( + exception: Throwable?, + is400Error: Int, + context: Context, + is403Error: Int = R.string.fail_to_network, + is409Error: Int = R.string.fail_to_network, +) { + return when (exception) { + is HttpException -> when (exception.code()) { + 400 -> context.toast(context.getString(is400Error)) + 403 -> context.toast(context.getString(is403Error)) + 409 -> context.toast(context.getString(is409Error)) + else -> context.toast(context.getString(R.string.fail_to_network)) + } + + is IOException -> { + context.toast(context.getString(R.string.fail_to_network)) + } + + else -> { + context.toast(context.getString(R.string.fail_to_login)) + } + } +} \ No newline at end of file