diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponseItem.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponseItem.kt index 7189032..b0d0e17 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponseItem.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponseItem.kt @@ -13,6 +13,5 @@ data class RecipeRecommendResponse( val need: List, val servings: Int, val cookingTime: Int, - val isBookmarked: Boolean, val difficulty: String ) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/RepositoryModule.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/RepositoryModule.kt index 323553a..7013ecb 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/RepositoryModule.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/RepositoryModule.kt @@ -1,5 +1,6 @@ package com.sundaegukbap.banchango.core.data.di +import com.sundaegukbap.banchango.core.data.repository.DefaultRecipeRepository import com.sundaegukbap.banchango.core.data.repository.FakeRecipeRepository import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository import dagger.Binds @@ -12,5 +13,5 @@ import dagger.hilt.components.SingletonComponent internal abstract class RepositoryModule { @Binds - abstract fun bindsRecipeRepository(recipeRepository: FakeRecipeRepository): RecipeRepository + abstract fun bindsRecipeRepository(recipeRepository: DefaultRecipeRepository): RecipeRepository } diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/RecipeMapper.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/RecipeMapper.kt index 54be7dd..582323a 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/RecipeMapper.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/RecipeMapper.kt @@ -1,11 +1,20 @@ package com.sundaegukbap.banchango.core.data.mapper import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecipeDifficulty import com.sundaegukbap.banchango.core.data.api.model.RecipeRecommendResponse internal fun List.toData(): List = map { it.toData() } internal fun RecipeRecommendResponse.toData(): Recipe { + val difficulty = when (difficulty) { + "아무나" -> RecipeDifficulty.ANYONE + "초보" -> RecipeDifficulty.BEGINNER + "중급" -> RecipeDifficulty.INTERMEDIATE + "고급" -> RecipeDifficulty.ADVANCED + "신의경지" -> RecipeDifficulty.GODLIKE + else -> RecipeDifficulty.ANYONE + } return Recipe( id = id, name = name, @@ -16,7 +25,6 @@ internal fun RecipeRecommendResponse.toData(): Recipe { need = need, servings = servings, cookingTime = cookingTime, - isBookmarked = isBookmarked, difficulty = difficulty, ) } diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeRecipeRepository.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeRecipeRepository.kt index a81f2e0..925f93d 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeRecipeRepository.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeRecipeRepository.kt @@ -1,6 +1,7 @@ package com.sundaegukbap.banchango.core.data.repository import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecipeDifficulty import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository import javax.inject.Inject @@ -16,10 +17,9 @@ class FakeRecipeRepository @Inject constructor() : RecipeRepository { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf("계란", "간장"), need = listOf("식초", "당근", "감자"), - isBookmarked = false, ) } ) @@ -35,10 +35,9 @@ class FakeRecipeRepository @Inject constructor() : RecipeRepository { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf("계란", "간장"), need = listOf("식초", "당근", "감자"), - isBookmarked = false, ) ) } diff --git a/Android/core/designsystem/src/main/java/com/sundaegukbap/banchango/core/designsystem/theme/Color.kt b/Android/core/designsystem/src/main/java/com/sundaegukbap/banchango/core/designsystem/theme/Color.kt index 4eb5ca2..d3bac00 100644 --- a/Android/core/designsystem/src/main/java/com/sundaegukbap/banchango/core/designsystem/theme/Color.kt +++ b/Android/core/designsystem/src/main/java/com/sundaegukbap/banchango/core/designsystem/theme/Color.kt @@ -11,7 +11,7 @@ val PurpleGrey40 = Color(0xFF625b71) val Pink40 = Color(0xFF7D5260) val Orange = Color(0xFFFF7A00) -val LightBeige = Color(0xFFF5EB) +val LightOrange = Color(0xFFFFC085) val White = Color(0xFFFFFFFF) val Black = Color(0xFF000000) diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailInfo.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailInfo.kt new file mode 100644 index 0000000..6a441af --- /dev/null +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailInfo.kt @@ -0,0 +1,126 @@ +package com.sundaegukbap.banchango.feature.recipe.detail + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight.Companion.Bold +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.sundaegukbap.banchango.RecipeDifficulty +import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme +import com.sundaegukbap.banchango.core.designsystem.theme.LightOrange +import com.sundaegukbap.banchango.core.designsystem.theme.Orange +import com.sundaegukbap.banchango.feature.recipe.difficulty.Stars + +@Composable +fun RecipeDetailInfo( + difficulty: RecipeDifficulty, + serving: Int, + cookingTime: Int, + paddingHorizontal: Int, + modifier: Modifier = Modifier +) { + Row(modifier = modifier.fillMaxWidth()) { + RecipeDetailDifficulty( + modifier = Modifier + .wrapContentSize() + .align(Alignment.CenterVertically) + .padding(horizontal = paddingHorizontal.dp), + difficulty = difficulty + ) + + RecipeLine(alignment = Alignment.CenterVertically) + + DetailText( + modifier = Modifier.align(Alignment.CenterVertically), + text = "${serving}인분", + paddingHorizontal = paddingHorizontal + ) + + RecipeLine(alignment = Alignment.CenterVertically) + + DetailText( + modifier = Modifier.align(Alignment.CenterVertically), + text = "${cookingTime}m", + paddingHorizontal = paddingHorizontal + ) + } +} + +@Composable +private fun RecipeDetailDifficulty( + modifier: Modifier = Modifier, + difficulty: RecipeDifficulty +) { + Column(modifier = modifier) { + Stars( + modifier = Modifier.wrapContentSize(), + starSize = 14, + filledCount = difficulty.level + ) + Text( + modifier = Modifier + .wrapContentSize() + .align(Alignment.CenterHorizontally), + text = difficulty.explain, + fontSize = 12.sp, + fontWeight = Bold, + color = Orange, + ) + } +} + +@Composable +private fun RowScope.RecipeLine(alignment: Alignment.Vertical) { + VerticalDivider( + modifier = Modifier + .height(52.dp) + .align(alignment), + color = LightOrange, + thickness = 2.dp + ) +} + +@Composable +private fun RowScope.DetailText( + modifier: Modifier = Modifier, + paddingHorizontal: Int, + text: String +) { + Text( + modifier = modifier + .wrapContentSize() + .padding(horizontal = paddingHorizontal.dp) + .align(Alignment.CenterVertically), + text = text, + fontSize = 12.sp, + fontWeight = Bold, + color = Orange, + textAlign = TextAlign.Center + ) +} + +@Preview(showBackground = true) +@Composable +fun RecipeDetailInfoPreview() { + BanchangoTheme { + RecipeDetailInfo( + difficulty = RecipeDifficulty.ADVANCED, + serving = 2, + cookingTime = 30, + 20, + ) + } +} + diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailScreen.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailScreen.kt index eeae9e5..d2ae07a 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailScreen.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailScreen.kt @@ -1,6 +1,9 @@ package com.sundaegukbap.banchango.feature.recipe.detail +import android.content.Intent +import android.net.Uri import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -12,8 +15,11 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.BottomSheetScaffold +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.SheetValue import androidx.compose.material3.Text import androidx.compose.material3.rememberBottomSheetScaffoldState @@ -25,14 +31,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext 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.core.content.ContextCompat.startActivity import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecipeDifficulty import com.sundaegukbap.banchango.core.designsystem.component.NetworkImage +import com.sundaegukbap.banchango.core.designsystem.theme.LightOrange +import com.sundaegukbap.banchango.core.designsystem.theme.Orange @Composable fun RecipeDetailRoute( @@ -49,8 +60,8 @@ fun RecipeDetailRoute( RecipeDetailContent( uiState = uiState, - modifier = modifier, onChangeSystemBarsColor = onChangeSystemBarsColor, + modifier = modifier, ) } @@ -78,7 +89,7 @@ fun RecipeDetailContent( } @Composable -fun RecipeDetailLoading() { +private fun RecipeDetailLoading() { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center @@ -90,7 +101,7 @@ fun RecipeDetailLoading() { @OptIn(ExperimentalMaterial3Api::class) @Composable -fun RecipeDetailScreen( +private fun RecipeDetailScreen( recipe: Recipe, modifier: Modifier = Modifier ) { @@ -113,31 +124,59 @@ fun RecipeDetailScreen( BottomSheetScaffold( scaffoldState = scaffoldState, sheetContent = { - RecipeDetailInfo( + RecipeDetailCard( recipe = recipe, modifier = Modifier ) }, - modifier = Modifier.background(Color.White), + sheetContainerColor = Color.White, sheetPeekHeight = screenHeight * 0.7f, ) {} + val context = LocalContext.current + Button( + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 60.dp), + colors = ButtonColors( + containerColor = Orange, + contentColor = Color.White, + disabledContainerColor = LightOrange, + disabledContentColor = Color.White + ), + onClick = { + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(recipe.link))) + }, + ) { + Text(text = "레시피 이동하기") + } } } @Composable -fun RecipeDetailInfo( +private fun RecipeDetailCard( recipe: Recipe, modifier: Modifier = Modifier ) { Box( - modifier = modifier.fillMaxSize() + modifier = modifier + .fillMaxSize() ) { Column( Modifier.padding(horizontal = 16.dp) ) { + RecipeDetailInfo( + difficulty = recipe.difficulty, + serving = recipe.servings, + cookingTime = recipe.cookingTime, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.CenterHorizontally), + paddingHorizontal = 32, + ) Text( + modifier = Modifier.padding(top = 20.dp), text = recipe.name, fontSize = 20.sp, fontWeight = FontWeight.Bold @@ -149,45 +188,61 @@ fun RecipeDetailInfo( modifier = Modifier.padding(top = 12.dp) ) - Text( - text = "식재료", - fontSize = 12.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(top = 24.dp) - ) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp) + ) { + Text( + text = "식재료", + fontSize = 12.sp, + fontWeight = FontWeight.Bold, + ) + Text( + text = "${recipe.have.size}/${recipe.have.size + recipe.need.size}", + color = Color.White, + fontSize = 12.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .background(color = Orange, shape = CircleShape) + .padding(horizontal = 8.dp) + .align(Alignment.CenterEnd) + ) + } + + HorizontalDivider(modifier = Modifier.padding(top = 12.dp), color = Orange) LazyRow( modifier = Modifier.padding(top = 16.dp), - horizontalArrangement = Arrangement.spacedBy(24.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { items(recipe.have) { Box( - modifier = Modifier.background(color = Color.Gray, shape = CircleShape) + modifier = Modifier + .border(1.dp, color = Orange, shape = CircleShape) + .background(color = Color.White, shape = CircleShape) ) { Text(modifier = Modifier.padding(16.dp), text = it) } } - } - - LazyRow( - modifier = Modifier.padding(top = 16.dp), - horizontalArrangement = Arrangement.spacedBy(24.dp), - ) { items(recipe.need) { - Box(modifier = Modifier.background(color = Color.Gray, shape = CircleShape)) { + Box( + modifier = Modifier + .border(1.dp, color = Orange, shape = CircleShape) + .background(color = LightOrange, shape = CircleShape) + ) { Text(modifier = Modifier.padding(16.dp), text = it) } } } - } } } @Preview(showBackground = true) @Composable -fun RecipeDetailInfoPreview() { - RecipeDetailInfo( +fun RecipeDetailCardPreview() { + RecipeDetailCard( recipe = Recipe( id = 1, name = "간장계란볶음밥", @@ -196,10 +251,9 @@ fun RecipeDetailInfoPreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf("계란", "간장"), need = listOf("식초", "당근", "감자"), - isBookmarked = false, ), ) } @@ -216,10 +270,9 @@ fun RecipeDetailScreenPreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf("계란", "간장"), need = listOf("식초", "당근", "감자"), - isBookmarked = false, ), ) } diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeItem.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeItem.kt index d727a25..607081c 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeItem.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeItem.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.util.lerp import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecipeDifficulty import com.sundaegukbap.banchango.core.designsystem.component.NetworkImage import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme import com.sundaegukbap.banchango.feature.reciperecommend.R @@ -120,7 +121,7 @@ private fun RecipeInfo( alpha = 0.8f ) .fillMaxWidth() - .padding(top = 40.dp, bottom = 40.dp), + .padding(vertical = 40.dp, horizontal = 16.dp), ) } } @@ -169,10 +170,9 @@ fun RecipeItemPreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf(""), need = listOf(""), - isBookmarked = false, ), isLiked = true, ), diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipesRecommendScreen.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipesRecommendScreen.kt index 78a57bd..0c4ea4c 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipesRecommendScreen.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipesRecommendScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecipeDifficulty import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme import kotlin.math.absoluteValue @@ -30,7 +31,7 @@ fun RecipeRecommendRoute( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - LaunchedEffect(uiState) { + LaunchedEffect(Unit) { if (uiState is RecipeRecommendUiState.Loading) viewModel.getRecipeRecommendation() } @@ -142,10 +143,9 @@ fun RecipePagePreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf(""), need = listOf(""), - isBookmarked = false, ), isLiked = false ), @@ -158,10 +158,9 @@ fun RecipePagePreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf(""), need = listOf(""), - isBookmarked = false, ), isLiked = false ), @@ -174,10 +173,9 @@ fun RecipePagePreview() { link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, - difficulty = "Easy", + difficulty = RecipeDifficulty.BEGINNER, have = listOf(""), need = listOf(""), - isBookmarked = false, ), isLiked = false ),