diff --git a/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSource.kt b/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSource.kt index 54c51f59..246455e0 100644 --- a/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSource.kt +++ b/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSource.kt @@ -11,4 +11,6 @@ interface RestaurantDataSource { group: String? = null, grade: String? = null, ): Flow> + + suspend fun getRestaurantDetail(index: Int): Result } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSourceImpl.kt b/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSourceImpl.kt index dc76f05d..1656037e 100644 --- a/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSourceImpl.kt +++ b/data/src/main/java/com/everymeal/data/datasource/restaurant/RestaurantDataSourceImpl.kt @@ -4,6 +4,7 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData import com.everymeal.data.model.restaruant.RestaurantResponse +import com.everymeal.data.model.unwrapData import com.everymeal.data.service.restaurant.RestaurantApi import kotlinx.coroutines.flow.Flow import javax.inject.Inject @@ -30,4 +31,8 @@ class RestaurantDataSourceImpl @Inject constructor( pagingSourceFactory = pagingSourceFactory ).flow } + + override suspend fun getRestaurantDetail(index: Int): Result { + return runCatching { restaurantApi.getRestaurantDetail(index) }.unwrapData() + } } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/repository/restaurant/RestaurantRepositoryImpl.kt b/data/src/main/java/com/everymeal/data/repository/restaurant/RestaurantRepositoryImpl.kt index 56366a2e..606d149e 100644 --- a/data/src/main/java/com/everymeal/data/repository/restaurant/RestaurantRepositoryImpl.kt +++ b/data/src/main/java/com/everymeal/data/repository/restaurant/RestaurantRepositoryImpl.kt @@ -24,4 +24,8 @@ class RestaurantRepositoryImpl @Inject constructor( pagingData.map { it.toEntity() } } } + + override suspend fun getRestaurantDetail(index: Int): Result { + return restaurantDataSource.getRestaurantDetail(index).map { it.toEntity() } + } } \ No newline at end of file diff --git a/data/src/main/java/com/everymeal/data/service/restaurant/RestaurantApi.kt b/data/src/main/java/com/everymeal/data/service/restaurant/RestaurantApi.kt index f961741f..e3cd541c 100644 --- a/data/src/main/java/com/everymeal/data/service/restaurant/RestaurantApi.kt +++ b/data/src/main/java/com/everymeal/data/service/restaurant/RestaurantApi.kt @@ -2,6 +2,7 @@ package com.everymeal.data.service.restaurant import com.everymeal.data.model.BaseResponse import com.everymeal.data.model.restaruant.GetUnivRestaurantResponse +import com.everymeal.data.model.restaruant.RestaurantResponse import retrofit2.http.GET import retrofit2.http.Path import retrofit2.http.Query @@ -17,4 +18,9 @@ interface RestaurantApi { @Query("group") group: String? = null, @Query("grade") grade: String? = null, ): BaseResponse + + @GET("/api/v1/stores/{index}") + suspend fun getRestaurantDetail( + @Path("index") index: Int + ): BaseResponse } \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/repository/restaurant/RestaurantRepository.kt b/domain/src/main/java/com/everymeal/domain/repository/restaurant/RestaurantRepository.kt index 9038d73e..627951bd 100644 --- a/domain/src/main/java/com/everymeal/domain/repository/restaurant/RestaurantRepository.kt +++ b/domain/src/main/java/com/everymeal/domain/repository/restaurant/RestaurantRepository.kt @@ -12,4 +12,8 @@ interface RestaurantRepository { group: String? = null, grade: String? = null, ) : Flow> + + suspend fun getRestaurantDetail( + index: Int + ) : Result } \ No newline at end of file diff --git a/domain/src/main/java/com/everymeal/domain/usecase/restaurant/GetDetailRestaurantUseCase.kt b/domain/src/main/java/com/everymeal/domain/usecase/restaurant/GetDetailRestaurantUseCase.kt new file mode 100644 index 00000000..a6536bde --- /dev/null +++ b/domain/src/main/java/com/everymeal/domain/usecase/restaurant/GetDetailRestaurantUseCase.kt @@ -0,0 +1,15 @@ +package com.everymeal.domain.usecase.restaurant + +import com.everymeal.domain.model.restaurant.RestaurantDataEntity +import com.everymeal.domain.repository.restaurant.RestaurantRepository +import javax.inject.Inject + +class GetDetailRestaurantUseCase @Inject constructor( + private val restaurantRepository: RestaurantRepository +) { + suspend operator fun invoke( + restaurantIdx: Int, + ) : Result { + return restaurantRepository.getRestaurantDetail(restaurantIdx) + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt index 796496e1..ff0415f8 100644 --- a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt +++ b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt @@ -43,7 +43,7 @@ import com.everymeal.presentation.ui.theme.Gray700 fun EveryMealRestaurantItem( restaurant: RestaurantDataEntity, onLoveClick: () -> Unit = {}, - onDetailClick: () -> Unit = {}, + onDetailClick: (Int) -> Unit = {}, ) { Column( modifier = Modifier @@ -52,7 +52,7 @@ fun EveryMealRestaurantItem( indication = null, interactionSource = remember { MutableInteractionSource() } ) { - onDetailClick() + onDetailClick(restaurant.idx) } .padding(horizontal = 20.dp) .background(color = Color.White) diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListContract.kt b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListContract.kt index 34ae6b26..c9b606d0 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListContract.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListContract.kt @@ -30,10 +30,11 @@ class DetailContract { data class OnClickRating(val rating: Int) : DetailEvent() object OnDeleteClickRestaurantCategoryType : DetailEvent() object OnDeleteClickRating : DetailEvent() + data class OnRestaurantDetailClick(val restaurantId: Int) : DetailEvent() } sealed class DetailEffect : ViewSideEffect { - + data class OnRestaurantClickEffect(val restaurantId: Int) : DetailEffect() } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListScreen.kt index 6c516a5f..e670cad4 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListScreen.kt @@ -41,6 +41,7 @@ import com.everymeal.presentation.components.EveryMealReportBottomSheetDialog import com.everymeal.presentation.components.EveryMealRestaurantItem import com.everymeal.presentation.components.EveryMealSortCategoryBottomSheetDialog import com.everymeal.presentation.ui.save.SaveTopBar +import com.everymeal.presentation.ui.signup.UnivSelectContract import com.everymeal.presentation.ui.theme.Grey2 import com.everymeal.presentation.ui.theme.Grey7 import com.everymeal.presentation.ui.theme.Main100 @@ -52,6 +53,7 @@ fun DetailListScreen( detailListViewModel: DetailListViewModel = hiltViewModel(), title: String, navigateToPreviousScreen: () -> Unit, + onDetailRestaurantClick: (Int) -> Unit = {} ) { val detailListViewState by detailListViewModel.viewState.collectAsState() @@ -61,6 +63,16 @@ fun DetailListScreen( detailListViewModel.setEvent(DetailContract.DetailEvent.InitDetailScreen) } + LaunchedEffect(key1 = detailListViewModel.effect) { + detailListViewModel.effect.collect { effect -> + when(effect) { + is DetailContract.DetailEffect.OnRestaurantClickEffect -> { + onDetailRestaurantClick(effect.restaurantId) + } + } + } + } + if(detailListViewState.sortBottomSheetState) { EveryMealSortCategoryBottomSheetDialog( detailListViewState.detailSortCategoryType.title(), @@ -190,6 +202,9 @@ fun DetailListScreen( item?.let { EveryMealRestaurantItem( restaurant = it, + onDetailClick = { restaurantIdx -> + detailListViewModel.setEvent(DetailContract.DetailEvent.OnRestaurantDetailClick(restaurantIdx)) + } ) Spacer(modifier = Modifier.padding(16.dp)) } @@ -275,7 +290,12 @@ fun DetailScreenChip( @Preview @Composable fun PreviewDetailListScreen() { - DetailListScreen(title = "맛집") { + DetailListScreen( + title = "맛집", + navigateToPreviousScreen = { + + }, + ) { } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListViewModel.kt index efd423fe..f07ac298 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListViewModel.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/detail/DetailListViewModel.kt @@ -10,6 +10,7 @@ import com.everymeal.presentation.base.BaseViewModel import com.everymeal.presentation.ui.detail.DetailContract.DetailEvent import com.everymeal.presentation.ui.detail.DetailContract.DetailState import com.everymeal.presentation.ui.detail.DetailContract.DetailEffect +import com.everymeal.presentation.ui.signup.UnivSelectContract import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -87,6 +88,9 @@ class DetailListViewModel @Inject constructor( ) getRestaurantList() } + is DetailEvent.OnRestaurantDetailClick -> { + sendEffect({ DetailEffect.OnRestaurantClickEffect(event.restaurantId) }) + } } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/main/MainScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/main/MainScreen.kt index c7e25d83..dec1db19 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/main/MainScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/main/MainScreen.kt @@ -26,6 +26,7 @@ import com.everymeal.presentation.ui.univfood.UnivFoodScreen import com.everymeal.presentation.ui.whatfood.WhatFoodScreen const val DETAIL_SCREEN_TYPE = "detailScreenType" +const val DETAIL_RESTAURANT_IDX = "detailRestaurantIdx" @Composable fun MainScreen( @@ -78,11 +79,17 @@ fun MainScreen( val detailScreenType = it.arguments?.getString(DETAIL_SCREEN_TYPE) ?: "" DetailListScreen( title = detailScreenType, - navigateToPreviousScreen = { navController.popBackStack() } + navigateToPreviousScreen = { navController.popBackStack() }, + onDetailRestaurantClick = { detailRestaurantIdx -> + navController.navigate(EveryMealRoute.DETAIL_RESTAURANT.route.plus("/$detailRestaurantIdx")) + } ) } - composable(route = EveryMealRoute.DETAIL_RESTAURANT.route) { - DetailRestaurantScreen() + composable(route = EveryMealRoute.DETAIL_RESTAURANT.route.plus("/{$DETAIL_RESTAURANT_IDX}")) { + val detailRestaurantIdx = it.arguments?.getString(DETAIL_RESTAURANT_IDX) ?: "" + DetailRestaurantScreen(detailRestaurantIdx.toInt()) { + navController.popBackStack() + } } composable(route = EveryMealRoute.SCHOOL_AUTH.route) { SchoolAuthScreen( diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantContract.kt b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantContract.kt index 520d8445..5b13177f 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantContract.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantContract.kt @@ -1,20 +1,39 @@ package com.everymeal.presentation.ui.restaurant +import com.everymeal.domain.model.restaurant.RestaurantDataEntity import com.everymeal.presentation.base.LoadState import com.everymeal.presentation.base.ViewEvent import com.everymeal.presentation.base.ViewSideEffect import com.everymeal.presentation.base.ViewState +import com.everymeal.presentation.ui.signup.UnivSelectContract data class DetailRestaurantState( val uiState: LoadState = LoadState.SUCCESS, val selectedTabIndex: Int = 0, val isFabClicked: Boolean = false, + val getDetailRestaurantState: LoadState = LoadState.LOADING, + val restaurantInfo: RestaurantDataEntity = RestaurantDataEntity( + idx = 0, + name = "", + address = "", + phoneNumber = "", + categoryDetail = "", + distance = 0, + grade = 0f, + reviewCount = 0, + recommendedCount = 0, + images = null, + isLiked = false + ), + val networkErrorDialog: Boolean = true, ) : ViewState sealed class DetailRestaurantEvent : ViewEvent { data class OnTabSelectedChanged(val selectedTabIndex: Int) : DetailRestaurantEvent() data class OnFloatingButtonClick(val isFabClicked: Boolean) : DetailRestaurantEvent() + data class InitDetailRestaurantScreen(val restaurantId: Int) : DetailRestaurantEvent() + data class NetworkErrorDialogClicked(val dialogStateChange: Boolean) : DetailRestaurantEvent() } sealed class DetailRestaurantEffect : ViewSideEffect { diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantScreen.kt index 4ed51639..1d012fb7 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantScreen.kt @@ -49,8 +49,13 @@ 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.restaurant.RestaurantDataEntity 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.ui.save.SaveTopBar +import com.everymeal.presentation.ui.signup.UnivSelectContract import com.everymeal.presentation.ui.theme.EveryMealTypo import com.everymeal.presentation.ui.theme.Gray100 import com.everymeal.presentation.ui.theme.Gray300 @@ -65,110 +70,154 @@ import kotlinx.coroutines.launch @Composable fun DetailRestaurantScreen( + restaurantId: Int, detailRestaurantViewModel: DetailRestaurantViewModel = hiltViewModel(), + onNetWorkErrorCancelClick: () -> Unit = {} ) { val viewState by detailRestaurantViewModel.viewState.collectAsState() - Scaffold( - topBar = { - SaveTopBar(title = "") - }, - floatingActionButton = { - Row( - modifier = Modifier - .padding(bottom = 20.dp) - .clip(RoundedCornerShape(100.dp)) - .background(if (viewState.isFabClicked) Gray100 else Main100) - .padding(12.dp) - .clickable { - detailRestaurantViewModel.setEvent( - DetailRestaurantEvent.OnFloatingButtonClick( - !viewState.isFabClicked - ) - ) - }, - verticalAlignment = Alignment.CenterVertically, - ) { - Image( - imageVector = - if(viewState.isFabClicked) - ImageVector.vectorResource(R.drawable.icon_x_mono) - else - ImageVector.vectorResource(R.drawable.icon_pencil_mono), - contentDescription = "floating", - colorFilter = ColorFilter.tint(if(viewState.isFabClicked) Gray800 else Color.White), - ) - } - }, - floatingActionButtonPosition = FabPosition.End, - ) { innerPadding -> - LazyColumn( - modifier = Modifier.padding(innerPadding), - ) { - item { - DetailRestaurantImage() - } - item { - DetailRestaurantMainInfo() - } - item { - DetailRestaurantTabLayout(detailRestaurantViewModel) - } + val restaurantInfo = viewState.restaurantInfo + + LaunchedEffect(Unit) { + detailRestaurantViewModel.setEvent(DetailRestaurantEvent.InitDetailRestaurantScreen(restaurantId)) + } + + when(viewState.getDetailRestaurantState) { + LoadState.LOADING -> { + EveryMealLoadingDialog() } - if (viewState.isFabClicked) { - Box( - modifier = Modifier - .fillMaxSize() - .background(Color.Black.copy(alpha = 0.5f)) - .clickable { - detailRestaurantViewModel.setEvent( - DetailRestaurantEvent.OnFloatingButtonClick( - false - ) + LoadState.SUCCESS -> { + Scaffold( + topBar = { + SaveTopBar(title = "") + }, + floatingActionButton = { + Row( + modifier = Modifier + .padding(bottom = 20.dp) + .clip(RoundedCornerShape(100.dp)) + .background(if (viewState.isFabClicked) Gray100 else Main100) + .padding(12.dp) + .clickable { + detailRestaurantViewModel.setEvent( + DetailRestaurantEvent.OnFloatingButtonClick( + !viewState.isFabClicked + ) + ) + }, + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = + if(viewState.isFabClicked) + ImageVector.vectorResource(R.drawable.icon_x_mono) + else + ImageVector.vectorResource(R.drawable.icon_pencil_mono), + contentDescription = "floating", + colorFilter = ColorFilter.tint(if(viewState.isFabClicked) Gray800 else Color.White), ) - }, - contentAlignment=Alignment.BottomEnd - ) { - Row( - modifier = Modifier - .padding(end = 20.dp, bottom = 160.dp) - .clip(RoundedCornerShape(6.dp)) - .background(color = Gray100) - .padding(vertical = 7.dp, horizontal = 12.dp), - verticalAlignment = Alignment.CenterVertically, + } + }, + floatingActionButtonPosition = FabPosition.End, + ) { innerPadding -> + LazyColumn( + modifier = Modifier.padding(innerPadding), ) { - Image( - imageVector = ImageVector.vectorResource(R.drawable.icon_camera_mono), - contentDescription = "camera", - ) - Text( - modifier = Modifier.padding(start = 2.dp), - text = stringResource(R.string.restaurant_only_picture), - color = Gray900, - style = EveryMealTypo.bodySmall - ) + // Todo Test 필요 + if(!restaurantInfo.images.isNullOrEmpty()) { + item { + DetailRestaurantImage() + } + } + item { + DetailRestaurantMainInfo( + restaurantInfo = restaurantInfo + ) + } + item { + DetailRestaurantTabLayout( + restaurantInfo = restaurantInfo, + viewModel = detailRestaurantViewModel + ) + } } - Row( - modifier = Modifier - .padding(end = 20.dp, bottom = 100.dp) - .clip(RoundedCornerShape(6.dp)) - .background(color = Gray100) - .padding(vertical = 7.dp, horizontal = 12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Image( - imageVector = ImageVector.vectorResource(R.drawable.icon_document_mono), - contentDescription = "review", - ) - Text( - modifier = Modifier.padding(start = 2.dp), - text = stringResource(R.string.restaurant_review), - color = Gray900, - style = EveryMealTypo.bodySmall - ) + if (viewState.isFabClicked) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.5f)) + .clickable { + detailRestaurantViewModel.setEvent( + DetailRestaurantEvent.OnFloatingButtonClick( + false + ) + ) + }, + contentAlignment=Alignment.BottomEnd + ) { + Row( + modifier = Modifier + .padding(end = 20.dp, bottom = 160.dp) + .clip(RoundedCornerShape(6.dp)) + .background(color = Gray100) + .padding(vertical = 7.dp, horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_camera_mono), + contentDescription = "camera", + ) + Text( + modifier = Modifier.padding(start = 2.dp), + text = stringResource(R.string.restaurant_only_picture), + color = Gray900, + style = EveryMealTypo.bodySmall + ) + } + Row( + modifier = Modifier + .padding(end = 20.dp, bottom = 100.dp) + .clip(RoundedCornerShape(6.dp)) + .background(color = Gray100) + .padding(vertical = 7.dp, horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_document_mono), + contentDescription = "review", + ) + Text( + modifier = Modifier.padding(start = 2.dp), + text = stringResource(R.string.restaurant_review), + color = Gray900, + style = EveryMealTypo.bodySmall + ) + } + } } } } + LoadState.ERROR -> { + if(viewState.networkErrorDialog) { + 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 = { + detailRestaurantViewModel.setEvent(DetailRestaurantEvent.NetworkErrorDialogClicked(false)) + detailRestaurantViewModel.setEvent(DetailRestaurantEvent.InitDetailRestaurantScreen(restaurantId)) + detailRestaurantViewModel.setEvent(DetailRestaurantEvent.NetworkErrorDialogClicked(true)) + }, + onDisMissClicked = { + detailRestaurantViewModel.setEvent(DetailRestaurantEvent.NetworkErrorDialogClicked(false)) + onNetWorkErrorCancelClick() + } + ) + } + } } } @@ -204,7 +253,7 @@ fun DetailRestaurantImage( @Composable fun DetailRestaurantMainInfo( - + restaurantInfo : RestaurantDataEntity ) { Column( modifier = Modifier @@ -218,14 +267,14 @@ fun DetailRestaurantMainInfo( .clip(RoundedCornerShape(4.dp)) .background(color = Gray300) .padding(vertical = 3.dp, horizontal = 6.dp), - text = "술집", + text = restaurantInfo.categoryDetail, color = Gray600, fontSize = 12.sp, style = EveryMealTypo.labelSmall, ) Text( modifier = Modifier.padding(top = 6.dp), - text = "스타벅스 서울대 입구점", + text = restaurantInfo.name, color = Color.Black, fontSize = 22.sp, style = EveryMealTypo.titleMedium, @@ -240,14 +289,14 @@ fun DetailRestaurantMainInfo( ) Text( modifier = Modifier.padding(start = 2.dp), - text = "5.0", + text = restaurantInfo.grade.toString(), color = Gray700, fontSize = 12.sp, fontWeight = FontWeight.Medium, ) Text( modifier = Modifier.padding(start = 2.dp), - text = "(100)", + text = "(${restaurantInfo.reviewCount})", color = Gray700, fontSize = 12.sp, fontWeight = FontWeight.Medium, @@ -281,7 +330,7 @@ fun DetailRestaurantMainInfo( ) Text( modifier = Modifier.padding(start = 4.dp), - text = "89", + text = restaurantInfo.recommendedCount.toString(), color = Gray500, fontSize = 15.sp, style = EveryMealTypo.displaySmall @@ -316,11 +365,12 @@ fun DetailRestaurantMainInfo( @OptIn(ExperimentalFoundationApi::class) @Composable fun DetailRestaurantTabLayout( + restaurantInfo : RestaurantDataEntity, viewModel : DetailRestaurantViewModel ) { val viewState by viewModel.viewState.collectAsState() - val pages = listOf("정보", "사진", "리뷰(0)") + val pages = listOf("정보", "사진", "리뷰(${restaurantInfo.reviewCount})") val coroutineScope = rememberCoroutineScope() @@ -365,7 +415,10 @@ fun DetailRestaurantTabLayout( HorizontalPager(state = pagerState) { page -> when (page) { - 0 -> DetailRestaurantTabInfo(Modifier.padding(horizontal = 20.dp)) + 0 -> DetailRestaurantTabInfo( + restaurantInfo = restaurantInfo, + modifier = Modifier.padding(horizontal = 20.dp) + ) 1 -> DetailRestaurantTabImage() 2 -> DetailRestaurantReview() } @@ -374,6 +427,7 @@ fun DetailRestaurantTabLayout( @Composable fun DetailRestaurantTabInfo( + restaurantInfo : RestaurantDataEntity, modifier: Modifier = Modifier, ) { Column( @@ -390,7 +444,7 @@ fun DetailRestaurantTabInfo( ) Text( modifier = Modifier.padding(start = 4.dp), - text = "서울특별시 관악구 관악로 1", + text = restaurantInfo.address, color = Gray800, fontSize = 14.sp, style = EveryMealTypo.bodySmall @@ -406,7 +460,7 @@ fun DetailRestaurantTabInfo( ) Text( modifier = Modifier.padding(start = 4.dp), - text = "1533-2233", + text = restaurantInfo.phoneNumber, color = Gray800, fontSize = 14.sp, style = EveryMealTypo.bodySmall @@ -420,13 +474,14 @@ fun DetailRestaurantTabInfo( imageVector = ImageVector.vectorResource(R.drawable.icon_link_mono), contentDescription = "link", ) - Text( - modifier = Modifier.padding(start = 4.dp), - text = "카카오맵 이동하기", - color = Gray800, - fontSize = 14.sp, - style = EveryMealTypo.bodySmall - ) +// Version2 KakaoMap +// Text( +// modifier = Modifier.padding(start = 4.dp), +// text = "카카오맵 이동하기", +// color = Gray800, +// fontSize = 14.sp, +// style = EveryMealTypo.bodySmall +// ) } Spacer(modifier = Modifier.padding(18.dp)) } @@ -477,7 +532,7 @@ fun DetailRestaurantReview() { @Preview @Composable fun PreviewDetailRestaurantScreen() { - DetailRestaurantScreen() + DetailRestaurantScreen(0) } @Preview diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantViewModel.kt b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantViewModel.kt index cb8b54c7..b00753c2 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantViewModel.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantViewModel.kt @@ -1,18 +1,26 @@ package com.everymeal.presentation.ui.restaurant +import androidx.lifecycle.viewModelScope +import com.everymeal.domain.model.restaurant.RestaurantDataEntity +import com.everymeal.domain.usecase.restaurant.GetDetailRestaurantUseCase import com.everymeal.presentation.base.BaseViewModel +import com.everymeal.presentation.base.LoadState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DetailRestaurantViewModel @Inject constructor( - + private val getDetailRestaurantUseCase: GetDetailRestaurantUseCase ): BaseViewModel( DetailRestaurantState() ) { - override fun handleEvents(event: DetailRestaurantEvent) { when(event) { + is DetailRestaurantEvent.InitDetailRestaurantScreen -> { + getDetailRestaurant(event.restaurantId) + } is DetailRestaurantEvent.OnTabSelectedChanged -> { reflectUpdateState( selectedTabIndex = event.selectedTabIndex @@ -23,17 +31,43 @@ class DetailRestaurantViewModel @Inject constructor( isFabClicked = event.isFabClicked ) } + is DetailRestaurantEvent.NetworkErrorDialogClicked -> { + reflectUpdateState( + networkErrorDialog = event.dialogStateChange + ) + } + } + } + + private fun getDetailRestaurant(restaurantIdx: Int) { + viewModelScope.launch { + getDetailRestaurantUseCase(restaurantIdx).onSuccess { + reflectUpdateState( + getDetailRestaurantState = LoadState.SUCCESS, + restaurantInfo = it + ) + }.onFailure { + reflectUpdateState( + getDetailRestaurantState = LoadState.ERROR + ) + } } } private fun reflectUpdateState( selectedTabIndex: Int = viewState.value.selectedTabIndex, isFabClicked: Boolean = viewState.value.isFabClicked, + restaurantInfo: RestaurantDataEntity = viewState.value.restaurantInfo, + getDetailRestaurantState: LoadState = viewState.value.getDetailRestaurantState, + networkErrorDialog: Boolean = viewState.value.networkErrorDialog ) { updateState { copy( selectedTabIndex = selectedTabIndex, isFabClicked = isFabClicked, + restaurantInfo = restaurantInfo, + getDetailRestaurantState = getDetailRestaurantState, + networkErrorDialog = networkErrorDialog ) } }