From 639fb814b5ca6cab38aba3fcf7f6cb333b1c5dfb Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Sat, 4 Nov 2023 17:55:32 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20?= =?UTF-8?q?=EB=8C=80=ED=95=99=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20=EC=97=B0=EA=B2=B0=20=EB=B0=8F=20=ED=81=B4=EB=A6=B0?= =?UTF-8?q?=EC=95=84=ED=82=A4=ED=85=8D=EC=B2=98=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../everymeal_android/di/NetworkModule.kt | 9 +- .../everymeal_android/di/RepositoryModule.kt | 16 ++ .../remote/onboarding/OnboardingDataSource.kt | 7 + .../onboarding/OnboardingDataSourceImpl.kt | 14 ++ .../model/onboarding/GetUniversityData.kt | 34 +++ .../onboarding/OnboardingRepositoryImpl.kt | 16 ++ .../data/service/onboarding/OnboardingApi.kt | 11 + .../model/onboarding/GetUniversityEntity.kt | 12 + .../onboarding/OnboardingRepository.kt | 7 + .../onboarding/GetUniversityUseCase.kt | 10 + .../ui/signup/UnivSelectContract.kt | 7 +- .../ui/signup/UnivSelectScreen.kt | 212 +++++++++--------- .../ui/signup/UnivSelectViewModel.kt | 31 ++- 13 files changed, 275 insertions(+), 111 deletions(-) create mode 100644 data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt create mode 100644 data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt create mode 100644 data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt create mode 100644 data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt create mode 100644 data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt create mode 100644 domain/src/main/java/com/everymeal/domain/model/onboarding/GetUniversityEntity.kt create mode 100644 domain/src/main/java/com/everymeal/domain/repository/onboarding/OnboardingRepository.kt create mode 100644 domain/src/main/java/com/everymeal/domain/usecase/onboarding/GetUniversityUseCase.kt diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt index 8e9d3ec0..196aba02 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt @@ -1,6 +1,7 @@ package com.everymeal.everymeal_android.di import com.everymeal.data.service.ExampleApi +import com.everymeal.data.service.onboarding.OnboardingApi import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module import dagger.Provides @@ -19,7 +20,7 @@ object NetworkModule { private val contentType = "application/json".toMediaType() private val json = Json { ignoreUnknownKeys = true } - private const val BASE_URL = "https://api.github.com/" + private const val BASE_URL = "http://dev.everymeal.shop:8085" @Provides @Singleton @@ -45,4 +46,10 @@ object NetworkModule { fun provideApi(retrofit: Retrofit): ExampleApi { return retrofit.create(ExampleApi::class.java) } + + @Provides + @Singleton + fun provideOnboardingApi(retrofit: Retrofit): OnboardingApi { + return retrofit.create(OnboardingApi::class.java) + } } \ No newline at end of file diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt index 86014ebb..689b9992 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt @@ -2,8 +2,12 @@ package com.everymeal.everymeal_android.di import com.everymeal.data.datasource.FoodDataSource import com.everymeal.data.datasource.FoodDataSourceImpl +import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSource +import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSourceImpl import com.everymeal.data.repository.FoodRepositoryImpl +import com.everymeal.data.repository.onboarding.OnboardingRepositoryImpl import com.everymeal.domain.repository.FoodRepository +import com.everymeal.domain.repository.onboarding.OnboardingRepository import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -25,4 +29,16 @@ abstract class RepositoryModule { abstract fun bindFoodV2DataSource( foodDataSourceImpl: FoodDataSourceImpl ): FoodDataSource + + @Singleton + @Binds + abstract fun bindOnboardingRepository( + onboardingRepositoryImpl: OnboardingRepositoryImpl + ): OnboardingRepository + + @Singleton + @Binds + abstract fun bindOnboardingDataSource( + onboardingDataSourceImpl: OnboardingDataSourceImpl + ): OnboardingDataSource } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt new file mode 100644 index 00000000..f2207ec5 --- /dev/null +++ b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt @@ -0,0 +1,7 @@ +package com.everymeal.data.datasource.remote.onboarding + +import com.everymeal.data.model.onboarding.GetUniversityData + +interface OnboardingDataSource { + suspend fun getUniversity(): Result +} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt new file mode 100644 index 00000000..0d62d44b --- /dev/null +++ b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt @@ -0,0 +1,14 @@ +package com.everymeal.data.datasource.remote.onboarding + +import com.everymeal.data.model.onboarding.GetUniversityData +import com.everymeal.data.service.onboarding.OnboardingApi +import javax.inject.Inject + +class OnboardingDataSourceImpl @Inject constructor( + private val onboardingApi: OnboardingApi +) : OnboardingDataSource { + + override suspend fun getUniversity(): Result { + return runCatching { onboardingApi.getUniversity() } + } +} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt b/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt new file mode 100644 index 00000000..0bd4386c --- /dev/null +++ b/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt @@ -0,0 +1,34 @@ +package com.everymeal.data.model.onboarding + +import com.everymeal.domain.model.onboarding.GetUniversityEntity +import kotlinx.serialization.Serializable + +@Serializable +data class GetUniversityData( + val localDateTime: String, + val message: String, + val data: List +) { + @Serializable + data class UniversityData( + val idx: Int, + val universityName: String, + val campusName: String, + val universityShortName: String + ) +} + +fun GetUniversityData.toUniversityEntity(): GetUniversityEntity { + val universityDataList = this.data.map { result -> + GetUniversityEntity.UniversityData( + idx = result.idx, + universityName = result.universityName, + campusName = result.campusName, + universityShortName = result.universityShortName + ) + } + + return GetUniversityEntity( + data = universityDataList + ) +} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt b/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt new file mode 100644 index 00000000..1d586497 --- /dev/null +++ b/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.everymeal.data.repository.onboarding + +import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSource +import com.everymeal.data.model.onboarding.toUniversityEntity +import com.everymeal.domain.model.onboarding.GetUniversityEntity +import com.everymeal.domain.repository.onboarding.OnboardingRepository +import javax.inject.Inject + +class OnboardingRepositoryImpl @Inject constructor( + private val onboardingDataSource: OnboardingDataSource +): OnboardingRepository { + + override suspend fun getUniversity(): Result { + return onboardingDataSource.getUniversity().map { it.toUniversityEntity() } + } +} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt b/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt new file mode 100644 index 00000000..11fabcca --- /dev/null +++ b/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt @@ -0,0 +1,11 @@ +package com.everymeal.data.service.onboarding + +import com.everymeal.data.model.onboarding.GetUniversityData +import retrofit2.Response +import retrofit2.http.GET + +interface OnboardingApi { + + @GET("/api/v1/universities") + suspend fun getUniversity(): GetUniversityData +} \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/model/onboarding/GetUniversityEntity.kt b/domain/src/main/java/com/everymeal/domain/model/onboarding/GetUniversityEntity.kt new file mode 100644 index 00000000..19bf2443 --- /dev/null +++ b/domain/src/main/java/com/everymeal/domain/model/onboarding/GetUniversityEntity.kt @@ -0,0 +1,12 @@ +package com.everymeal.domain.model.onboarding + +data class GetUniversityEntity( + val data: List +) { + data class UniversityData( + val idx: Int, + val universityName: String, + val campusName: String, + val universityShortName: String + ) +} diff --git a/domain/src/main/java/com/everymeal/domain/repository/onboarding/OnboardingRepository.kt b/domain/src/main/java/com/everymeal/domain/repository/onboarding/OnboardingRepository.kt new file mode 100644 index 00000000..012171e5 --- /dev/null +++ b/domain/src/main/java/com/everymeal/domain/repository/onboarding/OnboardingRepository.kt @@ -0,0 +1,7 @@ +package com.everymeal.domain.repository.onboarding + +import com.everymeal.domain.model.onboarding.GetUniversityEntity + +interface OnboardingRepository { + suspend fun getUniversity(): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/usecase/onboarding/GetUniversityUseCase.kt b/domain/src/main/java/com/everymeal/domain/usecase/onboarding/GetUniversityUseCase.kt new file mode 100644 index 00000000..66bed9f5 --- /dev/null +++ b/domain/src/main/java/com/everymeal/domain/usecase/onboarding/GetUniversityUseCase.kt @@ -0,0 +1,10 @@ +package com.everymeal.domain.usecase.onboarding + +import com.everymeal.domain.repository.onboarding.OnboardingRepository +import javax.inject.Inject + +class GetUniversityUseCase @Inject constructor( + private val onboardingRepository: OnboardingRepository +) { + suspend operator fun invoke() = onboardingRepository.getUniversity() +} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt index 0945b13f..70339f96 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt @@ -1,5 +1,6 @@ package com.everymeal.presentation.ui.signup +import com.everymeal.domain.model.onboarding.GetUniversityEntity.UniversityData import com.everymeal.presentation.base.LoadState import com.everymeal.presentation.base.ViewEvent import com.everymeal.presentation.base.ViewSideEffect @@ -12,8 +13,9 @@ class UnivSelectContract { 대학교 선택하기 State Hoisting */ data class UnivSelectState( - val univSelectLoadState: LoadState = LoadState.SUCCESS, - val selectedUniv: String = "" + val univSelectLoadState: LoadState = LoadState.LOADING, + val selectedUniv: String = "", + val universities: List = emptyList() ) : ViewState /* @@ -21,6 +23,7 @@ class UnivSelectContract { 대학교 선택하기 ViewEvent */ sealed class UnivSelectEvent : ViewEvent { + object InitUnivSelectScreen : UnivSelectEvent() object SelectButtonClicked : UnivSelectEvent() data class SelectedUniv( val selectedUniv: String diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt index e76779f8..cf77712d 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt @@ -1,6 +1,7 @@ package com.everymeal.presentation.ui.signup import android.annotation.SuppressLint +import android.util.Log import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -38,7 +39,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import com.everymeal.domain.model.onboarding.GetUniversityEntity import com.everymeal.presentation.R +import com.everymeal.presentation.base.LoadState import com.everymeal.presentation.components.EveryMealMainButton import com.everymeal.presentation.ui.theme.EveryMeal_AndroidTheme import com.everymeal.presentation.ui.theme.Gray100 @@ -48,11 +51,6 @@ import com.everymeal.presentation.ui.theme.Gray600 import com.everymeal.presentation.ui.theme.Gray800 import com.everymeal.presentation.ui.theme.Paddings -data class Item( - val univName: String, - val campusName: String? = null -) - @Composable fun UnivSelectScreen( viewModel: UnivSelectViewModel = hiltViewModel(), @@ -60,113 +58,121 @@ fun UnivSelectScreen( ) { val viewState by viewModel.viewState.collectAsState() - val items = listOf( - Item(univName = "명지대", campusName = "자연캠퍼스"), - Item(univName = "명지대", campusName = "인문캠퍼스"), - Item(univName = "성신여대", campusName = "수정캠퍼스"), - Item(univName = "성신여대", campusName = "운정캠퍼스"), - Item(univName = "서울여대"), - Item(univName = "연세대학교", campusName = "서울캠퍼스"), - ) + LaunchedEffect(key1 = true) { + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.InitUnivSelectScreen) + } - Box( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = Paddings.extra) - ) { - Spacer(modifier = Modifier.padding(40.dp)) - Image( - painter = painterResource(id = R.drawable.icon_school), - contentDescription = stringResource(R.string.icon_univ), - modifier = Modifier.size(64.dp) - ) - Spacer(modifier = Modifier.padding(10.dp)) - Text( - text = stringResource(R.string.univ_select_title), - style = TextStyle( - fontSize = 24.sp, - fontWeight = FontWeight.Bold - ), - ) - Spacer(modifier = Modifier.padding(10.dp)) - LazyVerticalGrid( - columns = GridCells.Fixed(2), - modifier = Modifier.weight(1f), - ) { - items(items.size) { index -> - val item = items[index] - val isSelected = viewState.selectedUniv == "${item.univName}+${item.campusName}" - UnivSelectItem( - item = item, - isSelected = isSelected, - index = index - ) { - viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectedUniv( - "${item.univName}+${item.campusName}") - ) - } + LaunchedEffect(key1 = viewModel.effect) { + viewModel.effect.collect { effect -> + when(effect) { + UnivSelectContract.UnivSelectEffect.MoveToMain -> { + onUnivSelectClick() } } - Row( + } + } + + when(viewState.univSelectLoadState) { + LoadState.LOADING -> { + //Todo 로딩 UI 구현 필요 + Log.d("UnivSelectScreen", "Loading") + } + LoadState.SUCCESS -> { + Log.d("UnivSelectScreen", "Success") + Box( modifier = Modifier - .fillMaxWidth() - .background(Gray300, RoundedCornerShape(100.dp)) - .padding(horizontal = Paddings.extra, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, + .fillMaxSize() + .background(Color.White) ) { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.icon_chat), - contentDescription = stringResource(id = R.string.icon_chat_description), - tint = Gray500 - ) - Spacer(modifier = Modifier.padding(14.dp)) - Column { - Text( - text = stringResource(id = R.string.univ_select_not_univ), - fontSize = 15.sp, - color = Gray800 + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = Paddings.extra) + ) { + Spacer(modifier = Modifier.padding(40.dp)) + Image( + painter = painterResource(id = R.drawable.icon_school), + contentDescription = stringResource(R.string.icon_univ), + modifier = Modifier.size(64.dp) ) + Spacer(modifier = Modifier.padding(10.dp)) Text( - text = stringResource(id = R.string.univ_select_apply), - fontSize = 14.sp, - color = Gray500 + text = stringResource(R.string.univ_select_title), + style = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Bold + ), ) + Spacer(modifier = Modifier.padding(10.dp)) + LazyVerticalGrid( + columns = GridCells.Fixed(2), + modifier = Modifier.weight(1f), + ) { + items(viewState.universities.size) { index -> + val item = viewState.universities[index] + val isSelected = viewState.selectedUniv == "${item.universityShortName}+${item.campusName}" + UnivSelectItem( + item = item, + isSelected = isSelected, + index = index + ) { + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectedUniv( + "${item.universityShortName}+${item.campusName}") + ) + } + } + } + Row( + modifier = Modifier + .fillMaxWidth() + .background(Gray300, RoundedCornerShape(100.dp)) + .padding(horizontal = Paddings.extra, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.icon_chat), + contentDescription = stringResource(id = R.string.icon_chat_description), + tint = Gray500 + ) + Spacer(modifier = Modifier.padding(14.dp)) + Column { + Text( + text = stringResource(id = R.string.univ_select_not_univ), + fontSize = 15.sp, + color = Gray800 + ) + Text( + text = stringResource(id = R.string.univ_select_apply), + fontSize = 14.sp, + color = Gray500 + ) + } + Spacer(modifier = Modifier.weight(1f)) + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.icon_arrow_right), + contentDescription = stringResource(id = R.string.icon_arrow_right), + tint = Gray500 + ) + } + EveryMealMainButton( + text = stringResource(R.string.select), + enabled = viewState.selectedUniv.isNotEmpty(), + ) { + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectButtonClicked) + } } - Spacer(modifier = Modifier.weight(1f)) - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.icon_arrow_right), - contentDescription = stringResource(id = R.string.icon_arrow_right), - tint = Gray500 - ) - } - EveryMealMainButton( - text = stringResource(R.string.select), - enabled = viewState.selectedUniv.isNotEmpty(), - ) { - viewModel.setEvent(UnivSelectContract.UnivSelectEvent.SelectButtonClicked) } } - } - - LaunchedEffect(key1 = viewModel.effect) { - viewModel.effect.collect { effect -> - when(effect) { - UnivSelectContract.UnivSelectEffect.MoveToMain -> { - onUnivSelectClick() - } - } + LoadState.ERROR -> { + //Todo 네트워크 에러 다이얼로그 구현 필요 + Log.d("UnivSelectScreen", "Error") } } } @SuppressLint("RememberReturnType") @Composable -fun UnivSelectItem(item: Item, isSelected: Boolean, index: Int, onSelectClick: (Item) -> Unit) { +fun UnivSelectItem(item: GetUniversityEntity.UniversityData, isSelected: Boolean, index: Int, onSelectClick: (GetUniversityEntity.UniversityData) -> Unit) { Column( modifier = Modifier .clickable( @@ -180,18 +186,18 @@ fun UnivSelectItem(item: Item, isSelected: Boolean, index: Int, onSelectClick: ( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - val spacerSize = if (item.campusName == null) 17.dp else 10.dp + val spacerSize = if (item.campusName.isEmpty()) 17.dp else 10.dp Spacer(modifier = Modifier.padding(spacerSize)) Text( - text = item.univName, + text = item.universityShortName, fontSize = 13.sp, fontWeight = FontWeight.Bold, color = Gray800 ) - item.campusName?.let { campusName -> + if (item.campusName.isNotEmpty()) { Spacer(modifier = Modifier.padding(4.dp)) Text( - text = campusName, + text = item.campusName, fontSize = 13.sp, color = Gray600, ) @@ -214,14 +220,6 @@ fun UnivSelectScreenPreview() { @Composable fun UnivSelectScreenItemPreview() { EveryMeal_AndroidTheme { - UnivSelectItem(item = Item( - univName = "명지대", - campusName = "용인캠퍼스" - ), - false, - index = 0 - ) { - } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt index 9f42ff2d..71b660f8 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt @@ -1,21 +1,31 @@ package com.everymeal.presentation.ui.signup +import android.util.Log +import androidx.lifecycle.viewModelScope +import com.everymeal.domain.usecase.onboarding.GetUniversityUseCase import com.everymeal.presentation.base.BaseViewModel +import com.everymeal.presentation.base.LoadState import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectEffect import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectEvent import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class UnivSelectViewModel @Inject constructor( - + private val getUniversityUseCase: GetUniversityUseCase ) : BaseViewModel( UnivSelectState() ) { override fun handleEvents(event: UnivSelectEvent) { when (event) { + is UnivSelectEvent.InitUnivSelectScreen -> { + updateState { copy(univSelectLoadState = LoadState.LOADING) } + getUniversity() + } + is UnivSelectEvent.SelectButtonClicked -> { sendEffect({ UnivSelectEffect.MoveToMain }) } @@ -29,4 +39,23 @@ class UnivSelectViewModel @Inject constructor( } } } + + private fun getUniversity() { + viewModelScope.launch { + getUniversityUseCase().onSuccess { + updateState { + copy( + univSelectLoadState = LoadState.SUCCESS, + universities = it.data + ) + } + }.onFailure { + updateState { + copy( + univSelectLoadState = LoadState.ERROR, + ) + } + } + } + } } \ No newline at end of file From 7f2c3253c78a41974df5bebebd3302a169238e68 Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Mon, 6 Nov 2023 21:56:10 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20?= =?UTF-8?q?=EB=A1=9C=EB=94=A9,=20=EC=97=90=EB=9F=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EC=96=BC=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/EveryMealDialog.kt | 17 +++++++++ .../ui/onboarding/OnboardingActivity.kt | 1 - .../ui/signup/UnivSelectActivity.kt | 15 ++++++-- .../ui/signup/UnivSelectScreen.kt | 38 +++++++++++++++---- .../ui/signup/UnivSelectViewModel.kt | 1 + presentation/src/main/res/values/strings.xml | 6 +++ 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealDialog.kt b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealDialog.kt index 6d676c16..068f7a19 100644 --- a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealDialog.kt +++ b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealDialog.kt @@ -1,20 +1,25 @@ package com.everymeal.presentation.components +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.everymeal.presentation.ui.theme.EveryMealTypo import com.everymeal.presentation.ui.theme.Grey7 import com.everymeal.presentation.ui.theme.MONO_BLACK +import com.everymeal.presentation.ui.theme.Main100 @Composable fun EveryMealDialog( @@ -72,3 +77,15 @@ fun EveryMealDialog( } ) } + +@Composable +fun EveryMealLoadingDialog( + modifier: Modifier = Modifier.fillMaxSize(), +) { + Box(modifier = modifier) { + CircularProgressIndicator( + modifier = Modifier.align(Alignment.Center), + color = Main100 + ) + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/onboarding/OnboardingActivity.kt b/presentation/src/main/java/com/everymeal/presentation/ui/onboarding/OnboardingActivity.kt index 9d60ae48..cf1322da 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/onboarding/OnboardingActivity.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/onboarding/OnboardingActivity.kt @@ -24,7 +24,6 @@ class OnboardingActivity : ComponentActivity() { EveryMeal_AndroidTheme { OnboardingScreen{ UnivSelectActivity.startActivity(this) - finish() } } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectActivity.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectActivity.kt index cc3f76f2..b1949fca 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectActivity.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import com.everymeal.presentation.ui.main.MainActivity +import com.everymeal.presentation.ui.onboarding.OnboardingActivity import com.everymeal.presentation.ui.theme.EveryMeal_AndroidTheme import dagger.hilt.android.AndroidEntryPoint @@ -21,10 +22,16 @@ class UnivSelectActivity : ComponentActivity() { private fun setUnivSelectScreen() { setContent { EveryMeal_AndroidTheme { - UnivSelectScreen{ - MainActivity.startActivity(this) - finish() - } + UnivSelectScreen( + onUnivSelectClick = { + MainActivity.startActivity(this) + finish() + }, + onNetWorkErrorCancelClick = { + OnboardingActivity.startActivity(this) + finish() + } + ) } } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt index cf77712d..2fb9893b 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -42,7 +43,10 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.everymeal.domain.model.onboarding.GetUniversityEntity import com.everymeal.presentation.R import com.everymeal.presentation.base.LoadState +import com.everymeal.presentation.components.EveryMealDialog +import com.everymeal.presentation.components.EveryMealLoadingDialog import com.everymeal.presentation.components.EveryMealMainButton +import com.everymeal.presentation.ui.onboarding.OnboardingActivity import com.everymeal.presentation.ui.theme.EveryMeal_AndroidTheme import com.everymeal.presentation.ui.theme.Gray100 import com.everymeal.presentation.ui.theme.Gray300 @@ -55,6 +59,7 @@ import com.everymeal.presentation.ui.theme.Paddings fun UnivSelectScreen( viewModel: UnivSelectViewModel = hiltViewModel(), onUnivSelectClick : () -> Unit, + onNetWorkErrorCancelClick : () -> Unit ) { val viewState by viewModel.viewState.collectAsState() @@ -71,14 +76,13 @@ fun UnivSelectScreen( } } } + val showDialog = remember { mutableStateOf(true) } when(viewState.univSelectLoadState) { LoadState.LOADING -> { - //Todo 로딩 UI 구현 필요 - Log.d("UnivSelectScreen", "Loading") + EveryMealLoadingDialog() } LoadState.SUCCESS -> { - Log.d("UnivSelectScreen", "Success") Box( modifier = Modifier .fillMaxSize() @@ -164,8 +168,25 @@ fun UnivSelectScreen( } } LoadState.ERROR -> { - //Todo 네트워크 에러 다이얼로그 구현 필요 - Log.d("UnivSelectScreen", "Error") + if(showDialog.value) { + EveryMealDialog( + modifier = Modifier.fillMaxWidth(), + title = stringResource(R.string.error_dialog_title), + message = stringResource(R.string.error_dialog_content), + confirmButtonText = stringResource(R.string.retry), + dismissButtonText = stringResource(R.string.cancel), + onDismissRequest = { }, + onConfirmClick = { + showDialog.value = false + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.InitUnivSelectScreen) + showDialog.value = true + }, + onDisMissClicked = { + showDialog.value = false + onNetWorkErrorCancelClick() + } + ) + } } } } @@ -210,9 +231,10 @@ fun UnivSelectItem(item: GetUniversityEntity.UniversityData, isSelected: Boolean @Composable fun UnivSelectScreenPreview() { EveryMeal_AndroidTheme { - UnivSelectScreen { - - } + UnivSelectScreen( + onUnivSelectClick = { }, + onNetWorkErrorCancelClick = { } + ) } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt index 71b660f8..727a85ec 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt @@ -9,6 +9,7 @@ import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectEffect import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectEvent import com.everymeal.presentation.ui.signup.UnivSelectContract.UnivSelectState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import javax.inject.Inject diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index bdb1c24f..f3922d54 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -115,4 +115,10 @@ 학교를 인증하면 리뷰 작성, 사진 등록 등 에브리밀을 다양하게 이용할 수 있어요! 나의 활동 설정 + + + 네트워크에 연결할 수 없어요 + 네트워크 연결 상태 확인 후 다시 시도해주세요 + 취소 + 다시 시도 From 48ebc8893da9dc384df168312d47b06dbd9057b8 Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Mon, 6 Nov 2023 22:09:45 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20?= =?UTF-8?q?=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20=EC=97=90=EB=9F=AC=20Sta?= =?UTF-8?q?te=20ViewModel=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/signup/UnivSelectContract.kt | 6 +++++- .../presentation/ui/signup/UnivSelectScreen.kt | 18 +++++++++++------- .../ui/signup/UnivSelectViewModel.kt | 8 ++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt index 70339f96..a0fc1109 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectContract.kt @@ -15,7 +15,8 @@ class UnivSelectContract { data class UnivSelectState( val univSelectLoadState: LoadState = LoadState.LOADING, val selectedUniv: String = "", - val universities: List = emptyList() + val universities: List = emptyList(), + val networkErrorDialog: Boolean = true ) : ViewState /* @@ -28,6 +29,9 @@ class UnivSelectContract { data class SelectedUniv( val selectedUniv: String ) : UnivSelectEvent() + data class NetworkErrorDialogClicked( + val dialogStateChange: Boolean + ) : UnivSelectEvent() } /* diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt index 2fb9893b..52885016 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectScreen.kt @@ -76,7 +76,6 @@ fun UnivSelectScreen( } } } - val showDialog = remember { mutableStateOf(true) } when(viewState.univSelectLoadState) { LoadState.LOADING -> { @@ -168,7 +167,7 @@ fun UnivSelectScreen( } } LoadState.ERROR -> { - if(showDialog.value) { + if(viewState.networkErrorDialog) { EveryMealDialog( modifier = Modifier.fillMaxWidth(), title = stringResource(R.string.error_dialog_title), @@ -177,12 +176,12 @@ fun UnivSelectScreen( dismissButtonText = stringResource(R.string.cancel), onDismissRequest = { }, onConfirmClick = { - showDialog.value = false + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.NetworkErrorDialogClicked(false)) viewModel.setEvent(UnivSelectContract.UnivSelectEvent.InitUnivSelectScreen) - showDialog.value = true + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.NetworkErrorDialogClicked(true)) }, onDisMissClicked = { - showDialog.value = false + viewModel.setEvent(UnivSelectContract.UnivSelectEvent.NetworkErrorDialogClicked(false)) onNetWorkErrorCancelClick() } ) @@ -193,14 +192,19 @@ fun UnivSelectScreen( @SuppressLint("RememberReturnType") @Composable -fun UnivSelectItem(item: GetUniversityEntity.UniversityData, isSelected: Boolean, index: Int, onSelectClick: (GetUniversityEntity.UniversityData) -> Unit) { +fun UnivSelectItem( + item: GetUniversityEntity.UniversityData, + isSelected: Boolean, + index: Int, + onSelectClick: (GetUniversityEntity.UniversityData) -> Unit +) { Column( modifier = Modifier .clickable( indication = null, interactionSource = remember { MutableInteractionSource() } ) { onSelectClick(item) } - .padding(bottom = Paddings.medium, end = if(index%2==0) Paddings.medium else 0.dp) + .padding(bottom = Paddings.medium, end = if (index % 2 == 0) Paddings.medium else 0.dp) .clip(RoundedCornerShape(Paddings.medium)) .background(if (isSelected) Gray500 else Gray100) .fillMaxSize(), diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt index 727a85ec..f4480720 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/signup/UnivSelectViewModel.kt @@ -38,6 +38,14 @@ class UnivSelectViewModel @Inject constructor( ) } } + + is UnivSelectEvent.NetworkErrorDialogClicked -> { + updateState { + copy( + networkErrorDialog = event.dialogStateChange + ) + } + } } } From 99b0f7bc3761a158ee2ad207d1904a726b95f4c6 Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Mon, 6 Nov 2023 22:47:06 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20BaseResp?= =?UTF-8?q?onse=20=EC=A0=81=EC=9A=A9=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../remote/onboarding/OnboardingDataSource.kt | 4 ++-- .../onboarding/OnboardingDataSourceImpl.kt | 7 +++--- .../com/everymeal/data/model/BaseResponse.kt | 14 +++++++++++ .../model/onboarding/GetUniversityData.kt | 23 +++++++------------ .../data/service/onboarding/OnboardingApi.kt | 6 ++--- 5 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 data/src/main/java/com/everymeal/data/model/BaseResponse.kt diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt index f2207ec5..aadb1bb7 100644 --- a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt +++ b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt @@ -1,7 +1,7 @@ package com.everymeal.data.datasource.remote.onboarding -import com.everymeal.data.model.onboarding.GetUniversityData +import com.everymeal.data.model.onboarding.UniversityData interface OnboardingDataSource { - suspend fun getUniversity(): Result + suspend fun getUniversity(): Result> } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt index 0d62d44b..5cdafcc5 100644 --- a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt +++ b/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt @@ -1,6 +1,7 @@ package com.everymeal.data.datasource.remote.onboarding -import com.everymeal.data.model.onboarding.GetUniversityData +import com.everymeal.data.model.onboarding.UniversityData +import com.everymeal.data.model.unwrapData import com.everymeal.data.service.onboarding.OnboardingApi import javax.inject.Inject @@ -8,7 +9,7 @@ class OnboardingDataSourceImpl @Inject constructor( private val onboardingApi: OnboardingApi ) : OnboardingDataSource { - override suspend fun getUniversity(): Result { - return runCatching { onboardingApi.getUniversity() } + override suspend fun getUniversity(): Result> { + return runCatching { onboardingApi.getUniversity() }.unwrapData() } } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/model/BaseResponse.kt b/data/src/main/java/com/everymeal/data/model/BaseResponse.kt new file mode 100644 index 00000000..ba187ad5 --- /dev/null +++ b/data/src/main/java/com/everymeal/data/model/BaseResponse.kt @@ -0,0 +1,14 @@ +package com.everymeal.data.model + +import kotlinx.serialization.Serializable + +@Serializable +data class BaseResponse( + val localDateTime: String, + val message: String, + val data: T, +) + +fun Result>.unwrapData(): Result { + return this.map { it.data } +} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt b/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt index 0bd4386c..86e6779e 100644 --- a/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt +++ b/data/src/main/java/com/everymeal/data/model/onboarding/GetUniversityData.kt @@ -4,22 +4,15 @@ import com.everymeal.domain.model.onboarding.GetUniversityEntity import kotlinx.serialization.Serializable @Serializable -data class GetUniversityData( - val localDateTime: String, - val message: String, - val data: List -) { - @Serializable - data class UniversityData( - val idx: Int, - val universityName: String, - val campusName: String, - val universityShortName: String - ) -} +data class UniversityData( + val idx: Int, + val universityName: String, + val campusName: String, + val universityShortName: String +) -fun GetUniversityData.toUniversityEntity(): GetUniversityEntity { - val universityDataList = this.data.map { result -> +fun List.toUniversityEntity(): GetUniversityEntity { + val universityDataList = this.map { result -> GetUniversityEntity.UniversityData( idx = result.idx, universityName = result.universityName, diff --git a/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt b/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt index 11fabcca..e76d1a0a 100644 --- a/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt +++ b/data/src/main/java/com/everymeal/data/service/onboarding/OnboardingApi.kt @@ -1,11 +1,11 @@ package com.everymeal.data.service.onboarding -import com.everymeal.data.model.onboarding.GetUniversityData -import retrofit2.Response +import com.everymeal.data.model.BaseResponse +import com.everymeal.data.model.onboarding.UniversityData import retrofit2.http.GET interface OnboardingApi { @GET("/api/v1/universities") - suspend fun getUniversity(): GetUniversityData + suspend fun getUniversity(): BaseResponse> } \ No newline at end of file From dea22be27c80a0907e0b2fd816f81bd2f5d3fc78 Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Mon, 6 Nov 2023 22:56:37 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20DataSour?= =?UTF-8?q?ce=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/everymeal/everymeal_android/di/RepositoryModule.kt | 4 ++-- .../{remote => }/onboarding/OnboardingDataSource.kt | 2 +- .../{remote => }/onboarding/OnboardingDataSourceImpl.kt | 2 +- .../data/repository/onboarding/OnboardingRepositoryImpl.kt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename data/src/main/java/com/everymeal/data/datasource/{remote => }/onboarding/OnboardingDataSource.kt (73%) rename data/src/main/java/com/everymeal/data/datasource/{remote => }/onboarding/OnboardingDataSourceImpl.kt (89%) diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt index 689b9992..903accbe 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt @@ -2,8 +2,8 @@ package com.everymeal.everymeal_android.di import com.everymeal.data.datasource.FoodDataSource import com.everymeal.data.datasource.FoodDataSourceImpl -import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSource -import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSourceImpl +import com.everymeal.data.datasource.onboarding.OnboardingDataSource +import com.everymeal.data.datasource.onboarding.OnboardingDataSourceImpl import com.everymeal.data.repository.FoodRepositoryImpl import com.everymeal.data.repository.onboarding.OnboardingRepositoryImpl import com.everymeal.domain.repository.FoodRepository diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt b/data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSource.kt similarity index 73% rename from data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt rename to data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSource.kt index aadb1bb7..f4978af4 100644 --- a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSource.kt +++ b/data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSource.kt @@ -1,4 +1,4 @@ -package com.everymeal.data.datasource.remote.onboarding +package com.everymeal.data.datasource.onboarding import com.everymeal.data.model.onboarding.UniversityData diff --git a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt b/data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSourceImpl.kt similarity index 89% rename from data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt rename to data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSourceImpl.kt index 5cdafcc5..2f447e78 100644 --- a/data/src/main/java/com/everymeal/data/datasource/remote/onboarding/OnboardingDataSourceImpl.kt +++ b/data/src/main/java/com/everymeal/data/datasource/onboarding/OnboardingDataSourceImpl.kt @@ -1,4 +1,4 @@ -package com.everymeal.data.datasource.remote.onboarding +package com.everymeal.data.datasource.onboarding import com.everymeal.data.model.onboarding.UniversityData import com.everymeal.data.model.unwrapData diff --git a/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt b/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt index 1d586497..ef0e7ce9 100644 --- a/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt +++ b/data/src/main/java/com/everymeal/data/repository/onboarding/OnboardingRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.everymeal.data.repository.onboarding -import com.everymeal.data.datasource.remote.onboarding.OnboardingDataSource +import com.everymeal.data.datasource.onboarding.OnboardingDataSource import com.everymeal.data.model.onboarding.toUniversityEntity import com.everymeal.domain.model.onboarding.GetUniversityEntity import com.everymeal.domain.repository.onboarding.OnboardingRepository From 76ca1bcda741f2f1588be067c9b6f4d03c66a87b Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Wed, 8 Nov 2023 23:33:56 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20API=20Mo?= =?UTF-8?q?ck=20Data=20=EC=A0=9C=EA=B1=B0=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../everymeal_android/di/NetworkModule.kt | 7 --- .../everymeal_android/di/RepositoryModule.kt | 16 ------- .../data/datasource/FoodDataSource.kt | 9 ---- .../data/datasource/FoodDataSourceImpl.kt | 26 ----------- .../com/everymeal/data/model/GetWeekFood.kt | 44 ------------------- .../data/repository/FoodRepositoryImpl.kt | 16 ------- .../com/everymeal/data/service/ExampleApi.kt | 14 ------ .../domain/model/ResponseWeekFoodEntity.kt | 18 -------- .../java/com/everymeal/domain/model/Result.kt | 7 --- .../domain/repository/FoodRepository.kt | 8 ---- .../domain/usecase/GetWeekFoodUseCase.kt | 10 ----- .../presentation/ExampleFoodState.kt | 13 ------ .../presentation/ExampleViewModel.kt | 34 -------------- .../presentation/ui/splash/SplashScreen.kt | 32 -------------- 14 files changed, 254 deletions(-) delete mode 100644 data/src/main/java/com/everymeal/data/datasource/FoodDataSource.kt delete mode 100644 data/src/main/java/com/everymeal/data/datasource/FoodDataSourceImpl.kt delete mode 100644 data/src/main/java/com/everymeal/data/model/GetWeekFood.kt delete mode 100644 data/src/main/java/com/everymeal/data/repository/FoodRepositoryImpl.kt delete mode 100644 data/src/main/java/com/everymeal/data/service/ExampleApi.kt delete mode 100644 domain/src/main/java/com/everymeal/domain/model/ResponseWeekFoodEntity.kt delete mode 100644 domain/src/main/java/com/everymeal/domain/model/Result.kt delete mode 100644 domain/src/main/java/com/everymeal/domain/repository/FoodRepository.kt delete mode 100644 domain/src/main/java/com/everymeal/domain/usecase/GetWeekFoodUseCase.kt delete mode 100644 presentation/src/main/java/com/everymeal/presentation/ExampleFoodState.kt delete mode 100644 presentation/src/main/java/com/everymeal/presentation/ExampleViewModel.kt diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt index 196aba02..ea5b1669 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt @@ -1,6 +1,5 @@ package com.everymeal.everymeal_android.di -import com.everymeal.data.service.ExampleApi import com.everymeal.data.service.onboarding.OnboardingApi import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module @@ -41,12 +40,6 @@ object NetworkModule { .build() } - @Provides - @Singleton - fun provideApi(retrofit: Retrofit): ExampleApi { - return retrofit.create(ExampleApi::class.java) - } - @Provides @Singleton fun provideOnboardingApi(retrofit: Retrofit): OnboardingApi { diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt index 903accbe..da5bacce 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/RepositoryModule.kt @@ -1,12 +1,8 @@ package com.everymeal.everymeal_android.di -import com.everymeal.data.datasource.FoodDataSource -import com.everymeal.data.datasource.FoodDataSourceImpl import com.everymeal.data.datasource.onboarding.OnboardingDataSource import com.everymeal.data.datasource.onboarding.OnboardingDataSourceImpl -import com.everymeal.data.repository.FoodRepositoryImpl import com.everymeal.data.repository.onboarding.OnboardingRepositoryImpl -import com.everymeal.domain.repository.FoodRepository import com.everymeal.domain.repository.onboarding.OnboardingRepository import dagger.Binds import dagger.Module @@ -18,18 +14,6 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) abstract class RepositoryModule { - @Singleton - @Binds - abstract fun bindFoodRepository( - foodRepositoryImpl: FoodRepositoryImpl, - ) : FoodRepository - - @Singleton - @Binds - abstract fun bindFoodV2DataSource( - foodDataSourceImpl: FoodDataSourceImpl - ): FoodDataSource - @Singleton @Binds abstract fun bindOnboardingRepository( diff --git a/data/src/main/java/com/everymeal/data/datasource/FoodDataSource.kt b/data/src/main/java/com/everymeal/data/datasource/FoodDataSource.kt deleted file mode 100644 index 9e66b20e..00000000 --- a/data/src/main/java/com/everymeal/data/datasource/FoodDataSource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.everymeal.data.datasource - -import com.everymeal.domain.model.ResponseWeekFoodEntity -import com.everymeal.domain.model.Result - -interface FoodDataSource { - - suspend fun weekGetFoodArea(s: String): Result -} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/datasource/FoodDataSourceImpl.kt b/data/src/main/java/com/everymeal/data/datasource/FoodDataSourceImpl.kt deleted file mode 100644 index 0909e510..00000000 --- a/data/src/main/java/com/everymeal/data/datasource/FoodDataSourceImpl.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.everymeal.data.datasource - -import com.everymeal.data.model.toWeekFoodEntity -import com.everymeal.data.service.ExampleApi -import com.everymeal.domain.model.ResponseWeekFoodEntity -import javax.inject.Inject -import com.everymeal.domain.model.Result - -class FoodDataSourceImpl @Inject constructor( - private val exampleApi: ExampleApi -) : FoodDataSource { - override suspend fun weekGetFoodArea(s: String): Result { - val response = exampleApi.weekGetFoodArea(s) - return try { - if (response.isSuccessful) { - response.body()?.let { data -> - return Result.Success(data.toWeekFoodEntity()) - } ?: Result.Error(404) - } else { - Result.Error(response.code()) - } - } catch (e: Exception) { - Result.Error(response.code()) - } - } -} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/model/GetWeekFood.kt b/data/src/main/java/com/everymeal/data/model/GetWeekFood.kt deleted file mode 100644 index d1d8c395..00000000 --- a/data/src/main/java/com/everymeal/data/model/GetWeekFood.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.everymeal.data.model - -import com.everymeal.domain.model.ResponseWeekFoodEntity -import kotlinx.serialization.Serializable - -@Serializable -data class WeekFoodResponse( - val success : Boolean, - val message : String, - val localDateTime : String, - val httpStatus : String, - val httpCode : Int, - val data : List, -) { - @Serializable - data class WeekFoodResult( - val mealId: Int, - val toDay: String, - val mealType : String, - val statusType : String, - val meals : List - ) -} - -fun WeekFoodResponse.toWeekFoodEntity(): ResponseWeekFoodEntity { - val weekFoodResultEntityList = this.data.map { result -> - ResponseWeekFoodEntity.WeekFoodResultEntity( - mealId = result.mealId, - toDay = result.toDay, - mealType = result.mealType, - statusType = result.statusType, - meals = result.meals - ) - } - - return ResponseWeekFoodEntity( - success = this.success, - message = this.message, - localDateTime = this.localDateTime, - httpStatus = this.httpStatus, - httpCode = this.httpCode, - data = weekFoodResultEntityList - ) -} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/repository/FoodRepositoryImpl.kt b/data/src/main/java/com/everymeal/data/repository/FoodRepositoryImpl.kt deleted file mode 100644 index 3def471f..00000000 --- a/data/src/main/java/com/everymeal/data/repository/FoodRepositoryImpl.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.everymeal.data.repository - -import com.everymeal.data.datasource.FoodDataSource -import com.everymeal.domain.model.ResponseWeekFoodEntity -import com.everymeal.domain.model.Result -import com.everymeal.domain.repository.FoodRepository -import javax.inject.Inject - -class FoodRepositoryImpl @Inject constructor( - private val foodDataSource: FoodDataSource -) : FoodRepository { - - override suspend fun weekFood(area: String): Result { - return foodDataSource.weekGetFoodArea(area) - } -} \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/service/ExampleApi.kt b/data/src/main/java/com/everymeal/data/service/ExampleApi.kt deleted file mode 100644 index 8157944a..00000000 --- a/data/src/main/java/com/everymeal/data/service/ExampleApi.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.everymeal.data.service - -import com.everymeal.data.model.WeekFoodResponse -import retrofit2.Response -import retrofit2.http.GET -import retrofit2.http.Path - -interface ExampleApi { - - @GET("/api/v2/meals/week/{area}") - suspend fun weekGetFoodArea( - @Path("area") area: String - ): Response -} \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/model/ResponseWeekFoodEntity.kt b/domain/src/main/java/com/everymeal/domain/model/ResponseWeekFoodEntity.kt deleted file mode 100644 index 2e280d77..00000000 --- a/domain/src/main/java/com/everymeal/domain/model/ResponseWeekFoodEntity.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.everymeal.domain.model - -data class ResponseWeekFoodEntity( - val success : Boolean, - val message : String, - val localDateTime : String, - val httpStatus : String, - val httpCode : Int, - val data : List, -){ - data class WeekFoodResultEntity( - val mealId: Int, - val toDay: String, - val mealType : String, - val statusType : String, - val meals : List - ) -} diff --git a/domain/src/main/java/com/everymeal/domain/model/Result.kt b/domain/src/main/java/com/everymeal/domain/model/Result.kt deleted file mode 100644 index 1d15d382..00000000 --- a/domain/src/main/java/com/everymeal/domain/model/Result.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.everymeal.domain.model - -sealed class Result { - data class Success(val data: T) : Result() - - data class Error(val exception: Int) : Result() -} \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/repository/FoodRepository.kt b/domain/src/main/java/com/everymeal/domain/repository/FoodRepository.kt deleted file mode 100644 index 4c57b7f2..00000000 --- a/domain/src/main/java/com/everymeal/domain/repository/FoodRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.everymeal.domain.repository - -import com.everymeal.domain.model.ResponseWeekFoodEntity -import com.everymeal.domain.model.Result - -interface FoodRepository { - suspend fun weekFood(area: String): Result -} \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/usecase/GetWeekFoodUseCase.kt b/domain/src/main/java/com/everymeal/domain/usecase/GetWeekFoodUseCase.kt deleted file mode 100644 index 107d0d58..00000000 --- a/domain/src/main/java/com/everymeal/domain/usecase/GetWeekFoodUseCase.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.everymeal.domain.usecase - -import com.everymeal.domain.repository.FoodRepository -import javax.inject.Inject - -class GetWeekFoodUseCase @Inject constructor( - private val foodRepository: FoodRepository -) { - suspend operator fun invoke(s : String) = foodRepository.weekFood(s) -} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ExampleFoodState.kt b/presentation/src/main/java/com/everymeal/presentation/ExampleFoodState.kt deleted file mode 100644 index ffcad981..00000000 --- a/presentation/src/main/java/com/everymeal/presentation/ExampleFoodState.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.everymeal.presentation - -import com.everymeal.domain.model.ResponseWeekFoodEntity - -sealed class ExampleFoodState { - object UnInitialized : ExampleFoodState() - - object Loading : ExampleFoodState() - - data class SuccessWeekFoodGetData(val getWeekFoodData: ResponseWeekFoodEntity) : ExampleFoodState() - - data class Error(val errorCode: Int) : ExampleFoodState() -} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ExampleViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ExampleViewModel.kt deleted file mode 100644 index fe12186c..00000000 --- a/presentation/src/main/java/com/everymeal/presentation/ExampleViewModel.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.everymeal.presentation - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.everymeal.domain.model.Result -import com.everymeal.domain.usecase.GetWeekFoodUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class ExampleViewModel @Inject constructor( - private val getWeekFoodUseCase: GetWeekFoodUseCase -) : ViewModel() { - - private val _weekGetFoodArea = MutableStateFlow(ExampleFoodState.UnInitialized) - val weekGetFoodArea: StateFlow = _weekGetFoodArea.asStateFlow() - - fun getWeekFood(area: String) { - viewModelScope.launch { - when(val result = getWeekFoodUseCase(area)) { - is Result.Success -> { - _weekGetFoodArea.value = ExampleFoodState.SuccessWeekFoodGetData(result.data) - } - is Result.Error -> { - _weekGetFoodArea.value = ExampleFoodState.Error(result.exception) - } - } - } - } -} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/splash/SplashScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/splash/SplashScreen.kt index 63fd72ab..8d001f41 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/splash/SplashScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/splash/SplashScreen.kt @@ -1,59 +1,27 @@ package com.everymeal.presentation.ui.splash import android.annotation.SuppressLint -import android.util.Log import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import com.airbnb.lottie.compose.LottieAnimation import com.airbnb.lottie.compose.LottieCompositionSpec import com.airbnb.lottie.compose.animateLottieCompositionAsState import com.airbnb.lottie.compose.rememberLottieComposition -import com.everymeal.presentation.ExampleFoodState -import com.everymeal.presentation.ExampleViewModel import com.everymeal.presentation.ui.theme.EveryMeal_AndroidTheme @SuppressLint("CoroutineCreationDuringComposition") @Composable fun SplashScreen( onFinishSplash: () -> Unit, - viewModel: ExampleViewModel = hiltViewModel(), ) { - LaunchedEffect(Unit) { - viewModel.getWeekFood("MCC식당") - } - val weekFoodState by viewModel.weekGetFoodArea.collectAsState() - - when (weekFoodState) { - is ExampleFoodState.UnInitialized -> { - - } - - is ExampleFoodState.Loading -> { - - } - - is ExampleFoodState.SuccessWeekFoodGetData -> { - val data = - (weekFoodState as ExampleFoodState.SuccessWeekFoodGetData).getWeekFoodData - Log.d("clean architecture test url success", "$data") - } - - is ExampleFoodState.Error -> { - - } - } - val composition by rememberLottieComposition(LottieCompositionSpec.Asset("everymeal_splash.json")) val progress by animateLottieCompositionAsState(composition) From 4c620439de5ac2647541e0107b254152c59ac18f Mon Sep 17 00:00:00 2001 From: sgsk88 Date: Wed, 8 Nov 2023 23:55:48 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[feature/api=5Fget=5Funiversity]=20BuildCon?= =?UTF-8?q?fig=20=EC=A0=81=EC=9A=A9=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 9 +++++++++ .../com/everymeal/everymeal_android/di/NetworkModule.kt | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 67a5e01e..4f4cd357 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.konan.properties.Properties @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { id("com.android.application") @@ -23,6 +24,10 @@ android { } } + val localPropertiesFile = rootProject.file("local.properties") + val localProperties = Properties() + localProperties.load(localPropertiesFile.inputStream()) + buildTypes { release { isMinifyEnabled = false @@ -31,6 +36,9 @@ android { "proguard-rules.pro" ) } + debug { + buildConfigField("String", "BASE_URL", "\"${localProperties.getProperty("BASE_URL")}\"") + } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 @@ -41,6 +49,7 @@ android { } buildFeatures { compose = true + buildConfig = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.7" diff --git a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt index ea5b1669..207c5046 100644 --- a/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt +++ b/app/src/main/java/com/everymeal/everymeal_android/di/NetworkModule.kt @@ -1,6 +1,7 @@ package com.everymeal.everymeal_android.di import com.everymeal.data.service.onboarding.OnboardingApi +import com.everymeal.everymeal_android.BuildConfig import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Module import dagger.Provides @@ -19,7 +20,7 @@ object NetworkModule { private val contentType = "application/json".toMediaType() private val json = Json { ignoreUnknownKeys = true } - private const val BASE_URL = "http://dev.everymeal.shop:8085" + private const val BASE_URL = BuildConfig.BASE_URL @Provides @Singleton From ce485fa79ea7df2c2ab6eae780b234ee3cccf233 Mon Sep 17 00:00:00 2001 From: KwakEuiJin Date: Thu, 9 Nov 2023 11:51:53 +0900 Subject: [PATCH 8/9] Fix PR Builder --- .github/workflows/EveryMeal_PR_Builder.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/EveryMeal_PR_Builder.yml b/.github/workflows/EveryMeal_PR_Builder.yml index 024098d1..d95414a8 100644 --- a/.github/workflows/EveryMeal_PR_Builder.yml +++ b/.github/workflows/EveryMeal_PR_Builder.yml @@ -38,6 +38,12 @@ jobs: - name: Change gradlew permissions run: chmod +x ./gradlew + - name: Add Local Properties + env: + BASE_URL: ${{ secrets.BASE_URL }} + run: | + echo pophoryBaseUrl=BASE_URL >> ./local.properties + - name: Build debug APK run: ./gradlew assembleDebug --stacktrace From 174232d6bd867219df4367b4941206e0c5371167 Mon Sep 17 00:00:00 2001 From: KwakEuiJin Date: Thu, 9 Nov 2023 11:58:14 +0900 Subject: [PATCH 9/9] Fix PR Builder --- .github/workflows/EveryMeal_PR_Builder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/EveryMeal_PR_Builder.yml b/.github/workflows/EveryMeal_PR_Builder.yml index d95414a8..aec748e2 100644 --- a/.github/workflows/EveryMeal_PR_Builder.yml +++ b/.github/workflows/EveryMeal_PR_Builder.yml @@ -42,7 +42,7 @@ jobs: env: BASE_URL: ${{ secrets.BASE_URL }} run: | - echo pophoryBaseUrl=BASE_URL >> ./local.properties + echo baseUrl=BASE_URL >> ./local.properties - name: Build debug APK run: ./gradlew assembleDebug --stacktrace