diff --git a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealBottomSheetDialog.kt b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealBottomSheetDialog.kt index 7f828d2d..cc389161 100644 --- a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealBottomSheetDialog.kt +++ b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealBottomSheetDialog.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Surface @@ -21,6 +22,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -29,12 +31,17 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.everymeal.presentation.R -import com.everymeal.presentation.ui.home.CategoryItem +import com.everymeal.presentation.ui.detail.ReportCategoryType import com.everymeal.presentation.ui.home.HomeCategoryList +import com.everymeal.presentation.ui.theme.EveryMealTypography +import com.everymeal.presentation.ui.theme.Gray200 +import com.everymeal.presentation.ui.theme.Gray400 import com.everymeal.presentation.ui.theme.Gray600 +import com.everymeal.presentation.ui.theme.Gray800 import com.everymeal.presentation.ui.theme.Gray900 import com.everymeal.presentation.ui.theme.Grey2 -import com.everymeal.presentation.ui.theme.Grey7 +import com.everymeal.presentation.ui.theme.Main100 +import com.everymeal.presentation.ui.theme.SubMain100 import com.everymeal.presentation.ui.theme.Typography @OptIn(ExperimentalMaterial3Api::class) @@ -86,6 +93,7 @@ fun EveryMealMainBottomSheetDialog( @OptIn(ExperimentalMaterial3Api::class) @Composable fun EveryMealSortCategoryBottomSheetDialog( + title: String, onClick: (String) -> Unit, onDismiss: () -> Unit ) { @@ -98,46 +106,63 @@ fun EveryMealSortCategoryBottomSheetDialog( .fillMaxWidth() .padding(horizontal = 20.dp) ) { - Text( - modifier = Modifier - .fillMaxWidth() - .clickable { onClick("인기순") } - .padding(vertical = 14.dp), - text = stringResource(R.string.popularity_sort), - fontSize = 17.sp, - color = Gray900, - fontWeight = FontWeight.SemiBold, + SortCategoryItem( + title = title, + category = stringResource(R.string.popularity_sort), + onClick = onClick ) Spacer(modifier = Modifier.padding(4.dp)) - Text( - modifier = Modifier - .fillMaxWidth() - .clickable { onClick("거리순") } - .padding(vertical = 14.dp), - text = stringResource(R.string.distance_sort), - fontSize = 17.sp, - color = Gray900, - fontWeight = FontWeight.SemiBold, + SortCategoryItem( + title = title, + category = stringResource(R.string.distance_sort), + onClick = onClick ) Spacer(modifier = Modifier.padding(4.dp)) - Text( - modifier = Modifier - .fillMaxWidth() - .clickable { onClick("최신순") } - .padding(vertical = 14.dp), - text = stringResource(R.string.recent_sort), - fontSize = 17.sp, - color = Gray900, - fontWeight = FontWeight.SemiBold, + SortCategoryItem( + title = title, + category = stringResource(R.string.recent_sort), + onClick = onClick ) Spacer(modifier = Modifier.padding(10.dp)) } } } +@Composable +fun SortCategoryItem( + title: String, + category: String, + onClick: (String) -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { onClick(category) }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.padding(vertical = 14.dp), + text = category, + fontSize = 17.sp, + color = Gray900, + style = EveryMealTypography.displayMedium, + ) + if(title == category) { + Image( + modifier = Modifier.size(24.dp), + imageVector = ImageVector.vectorResource(R.drawable.icon_check_mono), + contentDescription = null, + ) + } + } +} + @OptIn(ExperimentalMaterial3Api::class) @Composable fun EveryMealCategoryRatingBottomSheetDialog( + currentRating: Int, + restaurantCategoryType: String, onClick: () -> Unit, onDismiss: () -> Unit, onCategoryClick: (String) -> Unit, @@ -163,10 +188,15 @@ fun EveryMealCategoryRatingBottomSheetDialog( ) Spacer(modifier = Modifier.padding(4.dp)) HomeCategoryList( - isBottomSheet = true + isBottomSheet = true, + restaurantCategoryType ) { onCategoryClick(it) } + Spacer(modifier = Modifier.padding(14.dp)) + Divider( + color = Gray200, + ) Spacer(modifier = Modifier.padding(4.dp)) Text( modifier = Modifier @@ -181,6 +211,7 @@ fun EveryMealCategoryRatingBottomSheetDialog( LazyRow(content = { items(5) { RatingItem( + currentRating, ratingCount = it + 1, onRatingClick = onRatingClick ) @@ -199,6 +230,7 @@ fun EveryMealCategoryRatingBottomSheetDialog( @Composable fun RatingItem( + currentRating: Int, ratingCount: Int, onRatingClick: (Int) -> Unit ) { @@ -207,7 +239,7 @@ fun RatingItem( indication = null, interactionSource = remember { MutableInteractionSource() } ) { onRatingClick(ratingCount) }, - color = Grey2, + color = if (currentRating == ratingCount) SubMain100 else Grey2, shape = RoundedCornerShape(100.dp), ) { Row( @@ -218,14 +250,146 @@ fun RatingItem( .padding(start = 12.dp) .size(16.dp), imageVector = ImageVector.vectorResource(R.drawable.icon_gray_star_mono), - contentDescription = "rating" + contentDescription = "rating", + colorFilter = if (currentRating == ratingCount) { + ColorFilter.tint(Main100) + } else { + ColorFilter.tint(Gray600) + } ) Text( text = ratingCount.toString(), - color = Grey7, + color = if (currentRating == ratingCount) Main100 else Gray600, style = Typography.bodySmall, modifier = Modifier.padding(start = 4.dp, end = 12.dp, top = 6.dp, bottom = 6.dp) ) } } -} \ No newline at end of file +} +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EveryMealReportBottomSheetDialog( + onClick: () -> Unit, + onDismiss: () -> Unit +) { + ModalBottomSheet( + onDismissRequest = { onDismiss() }, + containerColor = Color.White, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { onClick() }, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + modifier = Modifier.size(24.dp), + imageVector = ImageVector.vectorResource(R.drawable.icon_siren_mono), + contentDescription = null, + ) + Text( + modifier = Modifier.padding(start = 12.dp), + text = stringResource(R.string.report), + fontSize = 17.sp, + color = Gray900, + fontWeight = FontWeight.SemiBold, + ) + } + Spacer(modifier = Modifier.padding(20.dp)) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EveryMealDetailReportBottomSheetDialog( + title: String, + onClick: () -> Unit, + onDismiss: () -> Unit, + onReportCategoryClick: (String) -> Unit +) { + ModalBottomSheet( + onDismissRequest = { onDismiss() }, + containerColor = Color.White, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + ) { + Text( + modifier = Modifier.padding(bottom = 18.dp), + text = stringResource(R.string.select_what_report), + fontSize = 22.sp, + style = EveryMealTypography.titleMedium, + color = Gray900 + ) + ReportCategoryItem( + title = title, + category = stringResource(R.string.restaurant_not_review), + onClick = onReportCategoryClick + ) + Spacer(modifier = Modifier.padding(4.dp)) + ReportCategoryItem( + title = title, + category = stringResource(R.string.dangerous_speak_review), + onClick = onReportCategoryClick + ) + Spacer(modifier = Modifier.padding(4.dp)) + ReportCategoryItem( + title = title, + category = stringResource(R.string.lustful_review), + onClick = onReportCategoryClick + ) + Spacer(modifier = Modifier.padding(4.dp)) + EveryMealMainButton( + text = stringResource(R.string.ok), + enabled = title.ReportCategoryType() != ReportCategoryType.NONE, + onClick = onClick, + ) + Spacer(modifier = Modifier.padding(10.dp)) + } + } +} + +@Composable +fun ReportCategoryItem( + title: String, + category: String, + onClick: (String) -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { onClick(category) }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + modifier = Modifier.padding(vertical = 10.dp), + text = category, + fontSize = 16.sp, + color = Gray800, + fontWeight = FontWeight.Normal, + style = EveryMealTypography.bodySmall + ) + Image( + modifier = Modifier.size(24.dp), + imageVector = ImageVector.vectorResource(R.drawable.icon_check_gray_mono), + contentDescription = null, + colorFilter = if(title == category) { + ColorFilter.tint(Main100) + } else { + ColorFilter.tint(Gray400) + } + ) + } +} 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 d5e43191..75927f96 100644 --- a/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt +++ b/presentation/src/main/java/com/everymeal/presentation/components/EveryMealRestaurantItem.kt @@ -43,10 +43,17 @@ import com.everymeal.presentation.ui.theme.Gray700 fun EveryMealRestaurantItem( restaurant: Restaurant, onLoveClick: () -> Unit, + onDetailClick: () -> Unit, ) { Column( modifier = Modifier .fillMaxSize() + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { + onDetailClick() + } .padding(horizontal = 20.dp) .background(color = Color.White) ) { @@ -254,8 +261,9 @@ fun RestaurantImage(restaurant: Restaurant) { @Composable fun HomeScreenPreview() { EveryMeal_AndroidTheme { - HomeScreen() { - - } + HomeScreen( + onDetailScreenClickType = {}, + onDetailRestaurantClick = {}, + ) } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/bottom/BottomNavigation.kt b/presentation/src/main/java/com/everymeal/presentation/ui/bottom/BottomNavigation.kt index 5085aac9..9c8ef653 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/bottom/BottomNavigation.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/bottom/BottomNavigation.kt @@ -37,4 +37,5 @@ enum class EveryMealRoute(val route: String) { WHAT_FOOD("what-food"), MY_PAGE("my-page"), DETAIL_LIST("detail-list"), + DETAIL_RESTAURANT("detail-restaurant"), } \ No newline at end of file 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 73275c4e..29d4787e 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 @@ -8,18 +8,28 @@ import com.everymeal.presentation.base.ViewState class DetailContract { data class DetailState( val uiState: LoadState = LoadState.SUCCESS, - val detailSortCategoryType: DetailSortCategoryType = DetailSortCategoryType.POPULARITY, val sortBottomSheetState: Boolean = false, val mealRatingBottomSheetState: Boolean = false, + val reportBottomSheetState: Boolean = false, + val detailReportBottomSheetState: Boolean = false, + val detailSortCategoryType: DetailSortCategoryType = DetailSortCategoryType.POPULARITY, + val reportCategoryType: ReportCategoryType = ReportCategoryType.NONE, + val restaurantCategoryType: RestaurantCategoryType = RestaurantCategoryType.NONE, + val rating: Int = 0, ) : ViewState sealed class DetailEvent : ViewEvent { - data class OnClickDetailListCategoryType(val detailSortCategoryType: DetailSortCategoryType) : DetailEvent() data class SortBottomSheetStateChange(val sortBottomSheetState: Boolean) : DetailEvent() data class MealRatingBottomSheetStateChange(val mealRatingBottomSheetState: Boolean) : DetailEvent() + data class ReportBottomSheetStateChange(val reportBottomSheetState: Boolean) : DetailEvent() + data class DetailReportBottomSheetStateChange(val detailReportBottomSheetState: Boolean) : DetailEvent() + data class OnClickDetailListCategoryType(val detailSortCategoryType: DetailSortCategoryType) : DetailEvent() + data class OnClickReportCategoryType(val reportCategoryType: ReportCategoryType) : DetailEvent() + data class OnClickRestaurantCategoryType(val restaurantCategoryType: RestaurantCategoryType) : DetailEvent() + data class OnClickRating(val rating: Int) : DetailEvent() } - sealed class HomeEffect : ViewSideEffect { + sealed class DetailEffect : ViewSideEffect { } } @@ -45,4 +55,57 @@ fun DetailSortCategoryType.title(): String { DetailSortCategoryType.DISTANCE -> "거리순" DetailSortCategoryType.RECENT -> "최신순" } +} + +enum class ReportCategoryType { + IRRELAVANT, + SLANG, + LUSTFUL, + NONE +} + +fun String.ReportCategoryType(): ReportCategoryType { + return when (this) { + "해당 가게와 무관한 리뷰" -> ReportCategoryType.IRRELAVANT + "비속어 및 혐오 발언" -> ReportCategoryType.SLANG + "음란성 게시물" -> ReportCategoryType.LUSTFUL + else -> ReportCategoryType.NONE + } +} + +fun ReportCategoryType.title(): String { + return when (this) { + ReportCategoryType.IRRELAVANT -> "해당 가게와 무관한 리뷰" + ReportCategoryType.SLANG -> "비속어 및 혐오 발언" + ReportCategoryType.LUSTFUL -> "음란성 게시물" + ReportCategoryType.NONE -> "" + } +} + +enum class RestaurantCategoryType { + RECOMMEND, + RICE, + CAFE, + DRINK, + NONE +} + +fun String.RestaurantCategoryType(): RestaurantCategoryType { + return when (this) { + "추천" -> RestaurantCategoryType.RECOMMEND + "밥집" -> RestaurantCategoryType.RICE + "카페" -> RestaurantCategoryType.CAFE + "술집" -> RestaurantCategoryType.DRINK + else -> RestaurantCategoryType.RECOMMEND + } +} + +fun RestaurantCategoryType.title(): String { + return when (this) { + RestaurantCategoryType.RECOMMEND -> "추천" + RestaurantCategoryType.RICE -> "밥집" + RestaurantCategoryType.CAFE -> "카페" + RestaurantCategoryType.DRINK -> "술집" + RestaurantCategoryType.NONE -> "" + } } \ No newline at end of file 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 fa97462e..b19db241 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 @@ -28,6 +28,8 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.everymeal.presentation.R import com.everymeal.presentation.components.EveryMealCategoryRatingBottomSheetDialog +import com.everymeal.presentation.components.EveryMealDetailReportBottomSheetDialog +import com.everymeal.presentation.components.EveryMealReportBottomSheetDialog import com.everymeal.presentation.components.EveryMealSortCategoryBottomSheetDialog import com.everymeal.presentation.ui.save.SaveTopBar import com.everymeal.presentation.ui.theme.Grey2 @@ -44,6 +46,7 @@ fun DetailListScreen( if(detailListViewState.sortBottomSheetState) { EveryMealSortCategoryBottomSheetDialog( + detailListViewState.detailSortCategoryType.title(), onClick = { detailListViewModel.setEvent(DetailContract.DetailEvent.OnClickDetailListCategoryType(it.DetailSortCategoryType())) detailListViewModel.setEvent(DetailContract.DetailEvent.SortBottomSheetStateChange(false)) @@ -56,6 +59,8 @@ fun DetailListScreen( if(detailListViewState.mealRatingBottomSheetState) { EveryMealCategoryRatingBottomSheetDialog( + detailListViewState.rating, + detailListViewState.restaurantCategoryType.title(), onClick = { detailListViewModel.setEvent(DetailContract.DetailEvent.MealRatingBottomSheetStateChange(false)) }, @@ -63,10 +68,37 @@ fun DetailListScreen( detailListViewModel.setEvent(DetailContract.DetailEvent.MealRatingBottomSheetStateChange(false)) }, onCategoryClick = { - + detailListViewModel.setEvent(DetailContract.DetailEvent.OnClickRestaurantCategoryType(it.RestaurantCategoryType())) }, onRatingClick = { + detailListViewModel.setEvent(DetailContract.DetailEvent.OnClickRating(it)) + } + ) + } + + if(detailListViewState.reportBottomSheetState) { + EveryMealReportBottomSheetDialog( + onClick = { + detailListViewModel.setEvent(DetailContract.DetailEvent.ReportBottomSheetStateChange(false)) + detailListViewModel.setEvent(DetailContract.DetailEvent.DetailReportBottomSheetStateChange(true)) + }, + onDismiss = { + detailListViewModel.setEvent(DetailContract.DetailEvent.ReportBottomSheetStateChange(false)) + } + ) + } + if(detailListViewState.detailReportBottomSheetState) { + EveryMealDetailReportBottomSheetDialog( + detailListViewState.reportCategoryType.title(), + onClick = { + detailListViewModel.setEvent(DetailContract.DetailEvent.DetailReportBottomSheetStateChange(false)) + }, + onDismiss = { + detailListViewModel.setEvent(DetailContract.DetailEvent.DetailReportBottomSheetStateChange(false)) + }, + onReportCategoryClick = { + detailListViewModel.setEvent(DetailContract.DetailEvent.OnClickReportCategoryType(it.ReportCategoryType())) } ) } @@ -104,6 +136,13 @@ fun DetailListScreen( detailListViewModel.setEvent(DetailContract.DetailEvent.MealRatingBottomSheetStateChange(true)) } ) + DetailScreenChip( + title = "TEST신고버튼", + isCategory = true, + onChipClicked = { + detailListViewModel.setEvent(DetailContract.DetailEvent.ReportBottomSheetStateChange(true)) + } + ) } } } 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 ad07b7d3..9af0d51e 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 @@ -3,12 +3,12 @@ package com.everymeal.presentation.ui.detail 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.HomeEffect +import com.everymeal.presentation.ui.detail.DetailContract.DetailEffect import javax.inject.Inject class DetailListViewModel @Inject constructor( -): BaseViewModel( +): BaseViewModel( DetailState() ) { @@ -29,6 +29,31 @@ class DetailListViewModel @Inject constructor( mealRatingBottomSheetState = event.mealRatingBottomSheetState ) } + is DetailEvent.ReportBottomSheetStateChange -> { + reflectUpdateState( + reportBottomSheetState = event.reportBottomSheetState + ) + } + is DetailEvent.DetailReportBottomSheetStateChange -> { + reflectUpdateState( + detailReportBottomSheetState = event.detailReportBottomSheetState + ) + } + is DetailEvent.OnClickReportCategoryType -> { + reflectUpdateState( + reportCategoryType = event.reportCategoryType + ) + } + is DetailEvent.OnClickRating -> { + reflectUpdateState( + rating = event.rating + ) + } + is DetailEvent.OnClickRestaurantCategoryType -> { + reflectUpdateState( + restaurantCategoryType = event.restaurantCategoryType + ) + } } } @@ -36,12 +61,22 @@ class DetailListViewModel @Inject constructor( detailSortCategoryType: DetailSortCategoryType = viewState.value.detailSortCategoryType, sortBottomSheetState: Boolean = viewState.value.sortBottomSheetState, mealRatingBottomSheetState: Boolean = viewState.value.mealRatingBottomSheetState, + reportBottomSheetState: Boolean = viewState.value.reportBottomSheetState, + detailReportBottomSheetState: Boolean = viewState.value.detailReportBottomSheetState, + reportCategoryType: ReportCategoryType = viewState.value.reportCategoryType, + rating: Int = viewState.value.rating, + restaurantCategoryType: RestaurantCategoryType = viewState.value.restaurantCategoryType, ) { updateState { copy( detailSortCategoryType = detailSortCategoryType, sortBottomSheetState = sortBottomSheetState, mealRatingBottomSheetState = mealRatingBottomSheetState, + reportBottomSheetState = reportBottomSheetState, + detailReportBottomSheetState = detailReportBottomSheetState, + reportCategoryType = reportCategoryType, + rating = rating, + restaurantCategoryType = restaurantCategoryType, ) } } diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/home/HomeScreen.kt b/presentation/src/main/java/com/everymeal/presentation/ui/home/HomeScreen.kt index abe6bb31..0247ca70 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/home/HomeScreen.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/home/HomeScreen.kt @@ -44,6 +44,7 @@ import com.everymeal.presentation.components.EveryMealLineButton import com.everymeal.presentation.components.EveryMealMainBottomSheetDialog import com.everymeal.presentation.components.EveryMealRestaurantItem import com.everymeal.presentation.components.EveryMealReviewItem +import com.everymeal.presentation.ui.detail.RestaurantCategoryType import com.everymeal.presentation.ui.theme.EveryMealTypography import com.everymeal.presentation.ui.theme.EveryMeal_AndroidTheme import com.everymeal.presentation.ui.theme.Gray100 @@ -56,6 +57,7 @@ import com.everymeal.presentation.ui.theme.Paddings fun HomeScreen( homeViewModel : HomeViewModel = hiltViewModel(), onDetailScreenClickType : (String) -> Unit, + onDetailRestaurantClick : () -> Unit, ) { val items = listOf( Restaurant( @@ -155,9 +157,15 @@ fun HomeScreen( } items(items.size) { index -> val item = items[index] - EveryMealRestaurantItem(item) { + EveryMealRestaurantItem( + item, + onLoveClick = { - } + }, + onDetailClick = { + onDetailRestaurantClick() + } + ) Spacer(modifier = Modifier.padding(10.dp)) if (index != items.size - 1) { Divider( @@ -311,6 +319,7 @@ fun HomeMainTopLayout( @Composable fun HomeCategoryList( isBottomSheet : Boolean = false, + restaurantCategoryType: String = "", onClick: (String) -> Unit ) { val horizotalDp = if (isBottomSheet) 0.dp else 20.dp @@ -322,24 +331,32 @@ fun HomeCategoryList( horizontalArrangement = Arrangement.SpaceBetween ) { CategoryItem( + isBottomSheet, + restaurantCategoryType, R.drawable.ic_homemenu_recommend, R.string.home_top_category_recommend ) { onClick("추천") } CategoryItem( + isBottomSheet, + restaurantCategoryType, R.drawable.ic_homemenu_bap, R.string.home_top_category_rice ) { onClick("밥집") } CategoryItem( + isBottomSheet, + restaurantCategoryType, R.drawable.ic_homemenu_cake, R.string.home_top_category_cafe ) { onClick("카페") } CategoryItem( + isBottomSheet, + restaurantCategoryType, R.drawable.ic_homemenu_beer, R.string.home_top_category_drink ) { @@ -371,6 +388,8 @@ fun LazyColumnTitle(title: String) { @Composable fun CategoryItem( + isBottomSheet: Boolean = false, + restaurantCategoryType: String = "", categoryIcon: Int, categoryText: Int, onClick: () -> Unit, @@ -381,7 +400,13 @@ fun CategoryItem( Column( modifier = Modifier .clickable { onClick() } - .background(Color.White, RoundedCornerShape(12.dp)) + .background( + when { + !isBottomSheet -> Color.White + restaurantCategoryType == stringResource(categoryText) -> Gray100 + else -> Color.White + }, + RoundedCornerShape(12.dp)) .padding(horizontal = 17.dp, vertical = 4.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -402,8 +427,9 @@ fun CategoryItem( @Composable fun HomeScreenPreview() { EveryMeal_AndroidTheme { - HomeScreen() { - - } + HomeScreen( + onDetailScreenClickType = {}, + onDetailRestaurantClick = {}, + ) } } \ No newline at end of file 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 88f314ea..d187555c 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 @@ -23,6 +23,7 @@ import com.everymeal.presentation.ui.bottom.navigateBottomNavigationScreen import com.everymeal.presentation.ui.detail.DetailListScreen import com.everymeal.presentation.ui.home.HomeScreen import com.everymeal.presentation.ui.mypage.MyPageScreen +import com.everymeal.presentation.ui.restaurant.DetailRestaurantScreen import com.everymeal.presentation.ui.univfood.UnivFoodScreen import com.everymeal.presentation.ui.whatfood.WhatFoodScreen @@ -59,6 +60,9 @@ fun MainScreen( HomeScreen( onDetailScreenClickType = { detailScreenType -> navController.navigate(EveryMealRoute.DETAIL_LIST.route.plus("/$detailScreenType")) + }, + onDetailRestaurantClick = { + navController.navigate(EveryMealRoute.DETAIL_RESTAURANT.route) } ) } @@ -78,6 +82,9 @@ fun MainScreen( navigateToPreviousScreen = { navController.popBackStack() } ) } + composable(route = EveryMealRoute.DETAIL_RESTAURANT.route) { + DetailRestaurantScreen() + } } } 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 new file mode 100644 index 00000000..520d8445 --- /dev/null +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantContract.kt @@ -0,0 +1,22 @@ +package com.everymeal.presentation.ui.restaurant + +import com.everymeal.presentation.base.LoadState +import com.everymeal.presentation.base.ViewEvent +import com.everymeal.presentation.base.ViewSideEffect +import com.everymeal.presentation.base.ViewState + + +data class DetailRestaurantState( + val uiState: LoadState = LoadState.SUCCESS, + val selectedTabIndex: Int = 0, + val isFabClicked: Boolean = false, +) : ViewState + +sealed class DetailRestaurantEvent : ViewEvent { + data class OnTabSelectedChanged(val selectedTabIndex: Int) : DetailRestaurantEvent() + data class OnFloatingButtonClick(val isFabClicked: Boolean) : DetailRestaurantEvent() +} + +sealed class DetailRestaurantEffect : ViewSideEffect { + +} \ No newline at end of file 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 new file mode 100644 index 00000000..883628fa --- /dev/null +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantScreen.kt @@ -0,0 +1,488 @@ +package com.everymeal.presentation.ui.restaurant + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +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.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Divider +import androidx.compose.material3.FabPosition +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.font.FontWeight +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.presentation.R +import com.everymeal.presentation.ui.save.SaveTopBar +import com.everymeal.presentation.ui.theme.EveryMealTypography +import com.everymeal.presentation.ui.theme.Gray100 +import com.everymeal.presentation.ui.theme.Gray300 +import com.everymeal.presentation.ui.theme.Gray400 +import com.everymeal.presentation.ui.theme.Gray500 +import com.everymeal.presentation.ui.theme.Gray600 +import com.everymeal.presentation.ui.theme.Gray700 +import com.everymeal.presentation.ui.theme.Gray800 +import com.everymeal.presentation.ui.theme.Gray900 +import com.everymeal.presentation.ui.theme.Main100 +import kotlinx.coroutines.launch + +@Composable +fun DetailRestaurantScreen( + detailRestaurantViewModel: DetailRestaurantViewModel = hiltViewModel(), +) { + 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) + } + } + 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 = EveryMealTypography.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 = EveryMealTypography.bodySmall + ) + } + } + } + } +} + +@Composable +fun DetailRestaurantImage( + +) { + Box( + modifier = Modifier + .fillMaxWidth() + .aspectRatio(9f / 7f) + ) { + Image( + painter = painterResource(id = R.drawable.test_image), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + Text( + modifier = Modifier + .padding(10.dp) + .clip(RoundedCornerShape(20.dp)) + .align(Alignment.BottomStart) + .background(Color.Black.copy(alpha = 0.6f)) + .padding(horizontal = 8.dp, vertical = 2.dp), + text = "1/6", + style = EveryMealTypography.bodySmall, + fontSize = 14.sp, + color = Color.White, + ) + } +} + +@Composable +fun DetailRestaurantMainInfo( + +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp) + .background(color = Color.White) + ) { + Text( + modifier = Modifier + .padding(top = 16.dp) + .clip(RoundedCornerShape(4.dp)) + .background(color = Gray300) + .padding(vertical = 3.dp, horizontal = 6.dp), + text = "술집", + color = Gray600, + fontSize = 12.sp, + style = EveryMealTypography.labelSmall, + ) + Text( + modifier = Modifier.padding(top = 6.dp), + text = "스타벅스 서울대 입구점", + color = Color.Black, + fontSize = 22.sp, + style = EveryMealTypography.titleMedium, + ) + Spacer(modifier = Modifier.padding(5.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_active_star_mono), + contentDescription = stringResource(R.string.icon_star), + ) + Text( + modifier = Modifier.padding(start = 2.dp), + text = "5.0", + color = Gray700, + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + ) + Text( + modifier = Modifier.padding(start = 2.dp), + text = "(100)", + color = Gray700, + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + ) + Spacer(modifier = Modifier.weight(1f)) + } + Spacer(modifier = Modifier.padding(12.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Row( + modifier = Modifier + .background( + color = Color.White, + shape = RoundedCornerShape(12.dp) + ) + .border( + width = 1.dp, + color = Gray300, + shape = RoundedCornerShape(12.dp) + ) + .weight(1f) + .padding(vertical = 12.dp), + horizontalArrangement = Arrangement.Center, + ) { + Image( + modifier = Modifier.size(24.dp), + imageVector = ImageVector.vectorResource(R.drawable.icon_heart_mono), + contentDescription = stringResource(R.string.icon_star), + ) + Text( + modifier = Modifier.padding(start = 4.dp), + text = "89", + color = Gray500, + fontSize = 15.sp, + style = EveryMealTypography.displaySmall + ) + } + Spacer(modifier = Modifier.width(8.dp)) + Row( + modifier = Modifier + .background( + color = Gray100, + shape = RoundedCornerShape(12.dp) + ) + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_download_mono), + contentDescription = "restaurant share", + ) + Text( + modifier = Modifier.padding(start = 6.dp), + text = stringResource(R.string.restaurant_share), + color = Gray600, + fontSize = 15.sp, + style = EveryMealTypography.displaySmall + ) + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun DetailRestaurantTabLayout( + viewModel : DetailRestaurantViewModel +) { + val viewState by viewModel.viewState.collectAsState() + + val pages = listOf("정보", "사진", "리뷰(0)") + + val coroutineScope = rememberCoroutineScope() + + val pagerState = rememberPagerState(pageCount = { + pages.size + }) + + LaunchedEffect(pagerState) { + snapshotFlow { pagerState.currentPage }.collect { page -> + viewModel.setEvent(DetailRestaurantEvent.OnTabSelectedChanged(page)) + } + } + + TabRow( + selectedTabIndex = viewState.selectedTabIndex, + containerColor = Color.White, + indicator = { tabPositions -> + TabRowDefaults.Indicator( + Modifier.tabIndicatorOffset(tabPositions[viewState.selectedTabIndex]), + color = Gray900, + ) + }, + divider = { Divider(color = Gray500) }, + ) { + pages.forEachIndexed { index, title -> + Tab( + text = { Text( + text = title, + style = EveryMealTypography.labelSmall, + ) }, + selected = viewState.selectedTabIndex == index, + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(index) + } + }, + selectedContentColor = Gray900, + unselectedContentColor = Gray500, + ) + } + } + + HorizontalPager(state = pagerState) { page -> + when (page) { + 0 -> DetailRestaurantTabInfo(Modifier.padding(horizontal = 20.dp)) + 1 -> DetailRestaurantTabImage() + 2 -> DetailRestaurantReview() + } + } +} + +@Composable +fun DetailRestaurantTabInfo( + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.padding(top = 20.dp), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + modifier = Modifier.size(20.dp), + imageVector = ImageVector.vectorResource(R.drawable.icon_pin_location_mono), + contentDescription = "location", + colorFilter = ColorFilter.tint(Gray400), + ) + Text( + modifier = Modifier.padding(start = 4.dp), + text = "서울특별시 관악구 관악로 1", + color = Gray800, + fontSize = 14.sp, + style = EveryMealTypography.bodySmall + ) + } + Spacer(modifier = Modifier.padding(6.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_call_mono), + contentDescription = "call", + ) + Text( + modifier = Modifier.padding(start = 4.dp), + text = "1533-2233", + color = Gray800, + fontSize = 14.sp, + style = EveryMealTypography.bodySmall + ) + } + Spacer(modifier = Modifier.padding(6.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.icon_link_mono), + contentDescription = "link", + ) + Text( + modifier = Modifier.padding(start = 4.dp), + text = "카카오맵 이동하기", + color = Gray800, + fontSize = 14.sp, + style = EveryMealTypography.bodySmall + ) + } + Spacer(modifier = Modifier.padding(18.dp)) + } +} + +@Composable +fun DetailRestaurantTabImage() { + // Mock Data + val items = listOf( + R.drawable.food_ex_1, + R.drawable.food_ex_2, + R.drawable.food_ex_3, + R.drawable.food_ex_1, + R.drawable.food_ex_2, + R.drawable.food_ex_3, + R.drawable.food_ex_1, + R.drawable.food_ex_2, + R.drawable.food_ex_3, + ) + + Column { + for (rowItems in items.chunked(3)) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 3.dp), + ) { + for (item in rowItems) { + Image( + painter = painterResource(id = item), + contentDescription = null, + modifier = Modifier + .padding(end = if (rowItems.indexOf(item) != 2) 3.dp else 0.dp) + .weight(1f) + .aspectRatio(1f) + ) + } + } + } + } +} + +@Composable +fun DetailRestaurantReview() { + +} + +@Preview +@Composable +fun PreviewDetailRestaurantScreen() { + DetailRestaurantScreen() +} + +@Preview +@Composable +fun PreviewDetailRestaurantImage() { + DetailRestaurantImage() +} 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 new file mode 100644 index 00000000..cb8b54c7 --- /dev/null +++ b/presentation/src/main/java/com/everymeal/presentation/ui/restaurant/DetailRestaurantViewModel.kt @@ -0,0 +1,40 @@ +package com.everymeal.presentation.ui.restaurant + +import com.everymeal.presentation.base.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class DetailRestaurantViewModel @Inject constructor( + +): BaseViewModel( + DetailRestaurantState() +) { + + override fun handleEvents(event: DetailRestaurantEvent) { + when(event) { + is DetailRestaurantEvent.OnTabSelectedChanged -> { + reflectUpdateState( + selectedTabIndex = event.selectedTabIndex + ) + } + is DetailRestaurantEvent.OnFloatingButtonClick -> { + reflectUpdateState( + isFabClicked = event.isFabClicked + ) + } + } + } + + private fun reflectUpdateState( + selectedTabIndex: Int = viewState.value.selectedTabIndex, + isFabClicked: Boolean = viewState.value.isFabClicked, + ) { + updateState { + copy( + selectedTabIndex = selectedTabIndex, + isFabClicked = isFabClicked, + ) + } + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/everymeal/presentation/ui/theme/Color.kt b/presentation/src/main/java/com/everymeal/presentation/ui/theme/Color.kt index 34ccc1a8..626037d7 100644 --- a/presentation/src/main/java/com/everymeal/presentation/ui/theme/Color.kt +++ b/presentation/src/main/java/com/everymeal/presentation/ui/theme/Color.kt @@ -15,6 +15,7 @@ val MONO_BLACK = Color(0xFF191F28) val Gray100 = Color(0xFFF9FAFB) val Gray200 = Color(0xFFE5E8EB) val Gray300 = Color(0xFFF2F4F6) +val Gray400 = Color(0xFFD1D6DB) val Gray500 = Color(0xFFB0B8C1) val Gray600 = Color(0xFF8B95A1) val Gray700 = Color(0xFF6B7684) @@ -29,3 +30,5 @@ val RED_LIGHT = Color(0xFFFFEDED) val Main100 = Color(0xFFFF4848) val Main800 = Color(0xFFCC3939) + +val SubMain100 = Color(0xFFFFEDED) diff --git a/presentation/src/main/res/drawable/icon_call_mono.xml b/presentation/src/main/res/drawable/icon_call_mono.xml new file mode 100644 index 00000000..c2a371ae --- /dev/null +++ b/presentation/src/main/res/drawable/icon_call_mono.xml @@ -0,0 +1,10 @@ + + + diff --git a/presentation/src/main/res/drawable/icon_camera_mono.xml b/presentation/src/main/res/drawable/icon_camera_mono.xml new file mode 100644 index 00000000..bbe6e048 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_camera_mono.xml @@ -0,0 +1,14 @@ + + + + diff --git a/presentation/src/main/res/drawable/icon_check_gray_mono.xml b/presentation/src/main/res/drawable/icon_check_gray_mono.xml new file mode 100644 index 00000000..f3251ec5 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_check_gray_mono.xml @@ -0,0 +1,9 @@ + + + diff --git a/presentation/src/main/res/drawable/icon_check_mono.xml b/presentation/src/main/res/drawable/icon_check_mono.xml new file mode 100644 index 00000000..b0a31bd1 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_check_mono.xml @@ -0,0 +1,9 @@ + + + diff --git a/presentation/src/main/res/drawable/icon_document_mono.xml b/presentation/src/main/res/drawable/icon_document_mono.xml new file mode 100644 index 00000000..bc1613b0 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_document_mono.xml @@ -0,0 +1,14 @@ + + + + diff --git a/presentation/src/main/res/drawable/icon_download_mono.xml b/presentation/src/main/res/drawable/icon_download_mono.xml new file mode 100644 index 00000000..b499ae0b --- /dev/null +++ b/presentation/src/main/res/drawable/icon_download_mono.xml @@ -0,0 +1,12 @@ + + + + diff --git a/presentation/src/main/res/drawable/icon_link_mono.xml b/presentation/src/main/res/drawable/icon_link_mono.xml new file mode 100644 index 00000000..755997df --- /dev/null +++ b/presentation/src/main/res/drawable/icon_link_mono.xml @@ -0,0 +1,14 @@ + + + + diff --git a/presentation/src/main/res/drawable/icon_pencil_mono.xml b/presentation/src/main/res/drawable/icon_pencil_mono.xml new file mode 100644 index 00000000..d1a1e280 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_pencil_mono.xml @@ -0,0 +1,10 @@ + + + diff --git a/presentation/src/main/res/drawable/icon_siren_mono.xml b/presentation/src/main/res/drawable/icon_siren_mono.xml new file mode 100644 index 00000000..40a69887 --- /dev/null +++ b/presentation/src/main/res/drawable/icon_siren_mono.xml @@ -0,0 +1,14 @@ + + + + diff --git a/presentation/src/main/res/drawable/test_image.png b/presentation/src/main/res/drawable/test_image.png new file mode 100644 index 00000000..be80c10f Binary files /dev/null and b/presentation/src/main/res/drawable/test_image.png differ diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 77fad116..b59b52db 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -3,7 +3,8 @@ 선택하기 - 등록하기기 + 등록하기 + 확인 닫기 나가기 @@ -83,4 +84,17 @@ 음식종류 별점순 적용하기 + + + 신고하기 + 해당 가게와 무관한 리뷰 + 비속어 및 혐오 발언 + 음란성 게시물 + 무엇으로 신고하시나요? + + + 공유하기 + 사진만 올리기 + 리뷰 작성하기 +