diff --git a/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/RecipeRepository.kt b/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/RecipeRepository.kt index b42e230..6416ad2 100644 --- a/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/RecipeRepository.kt +++ b/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/RecipeRepository.kt @@ -1,12 +1,11 @@ package com.sundaegukbap.banchango.core.data.repository.api -import com.sundaegukbap.banchango.LikableRecipe -import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecommendedRecipe interface RecipeRepository { - suspend fun getRecipeRecommendation(): Result> + suspend fun getRecipeRecommendation(): Result> - suspend fun getRecipeDetail(id: Long): Result + suspend fun getRecipeDetail(id: Long): Result suspend fun likeRecipe( id: Long, diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/RecipeApi.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/RecipeApi.kt index 25aada2..a9d731a 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/RecipeApi.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/RecipeApi.kt @@ -1,6 +1,7 @@ package com.sundaegukbap.banchango.core.data.api -import com.sundaegukbap.banchango.core.data.api.model.RecipeRecommendResponse +import com.sundaegukbap.banchango.core.data.api.model.RecommendedRecipeResponse +import com.sundaegukbap.banchango.core.data.api.model.RecommendedRecipesResponse import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path @@ -8,12 +9,12 @@ import retrofit2.http.Path internal interface RecipeApi { @GET("api/recipe/recommand/{userId}") suspend fun getRecipeRecommendation( - @Path("userId") userId: Long - ): Response> + @Path("userId") userId: Long, + ): Response @GET("api/recipe/{userId}/{recipeId}") suspend fun getRecipeDetail( @Path("userId") userId: Long, - @Path("recipeId") recipeId: Long - ): Response + @Path("recipeId") recipeId: Long, + ): Response } diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/HaveResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/HaveResponse.kt new file mode 100644 index 0000000..236940d --- /dev/null +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/HaveResponse.kt @@ -0,0 +1,10 @@ +package com.sundaegukbap.banchango.core.data.api.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class HaveResponse( + @SerialName("ingredientDtos") + val ingredients: List, +) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientResponse.kt new file mode 100644 index 0000000..6b243ac --- /dev/null +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientResponse.kt @@ -0,0 +1,11 @@ +package com.sundaegukbap.banchango.core.data.api.model + +import kotlinx.serialization.Serializable + +@Serializable +data class IngredientResponse( + val id: Long, + val name: String, + val kind: String, + val image: String?, +) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/NeedResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/NeedResponse.kt new file mode 100644 index 0000000..da054b3 --- /dev/null +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/NeedResponse.kt @@ -0,0 +1,10 @@ +package com.sundaegukbap.banchango.core.data.api.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class NeedResponse( + @SerialName("ingredientDtos") + val ingredients: List, +) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponse.kt deleted file mode 100644 index 5da78c7..0000000 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.sundaegukbap.banchango.core.data.api.model - -import kotlinx.serialization.Serializable - -@Serializable -data class RecipeRecommendsResponse( - val recipeRecommends: List -) 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/RecipeResponse.kt similarity index 70% rename from Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeRecommendResponseItem.kt rename to Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecipeResponse.kt index b0d0e17..275a9b8 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/RecipeResponse.kt @@ -3,15 +3,13 @@ package com.sundaegukbap.banchango.core.data.api.model import kotlinx.serialization.Serializable @Serializable -data class RecipeRecommendResponse( +data class RecipeResponse( val id: Long, val name: String, val introduction: String, val image: String, val link: String, - val have: List, - val need: List, val servings: Int, val cookingTime: Int, - val difficulty: String + val difficulty: String, ) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipeResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipeResponse.kt new file mode 100644 index 0000000..4ba79d4 --- /dev/null +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipeResponse.kt @@ -0,0 +1,10 @@ +package com.sundaegukbap.banchango.core.data.api.model + +import kotlinx.serialization.Serializable + +@Serializable +data class RecommendedRecipeResponse( + val recipe: RecipeResponse, + val have: HaveResponse, + val need: NeedResponse, +) diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipesResponse.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipesResponse.kt new file mode 100644 index 0000000..86c36b9 --- /dev/null +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/RecommendedRecipesResponse.kt @@ -0,0 +1,10 @@ +package com.sundaegukbap.banchango.core.data.api.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RecommendedRecipesResponse( + @SerialName("recommandedRecipeResponses") + val recommendedRecipeResponses: List, +) 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 358075f..aa00fe5 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,7 +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 import dagger.Module @@ -11,7 +10,6 @@ import dagger.hilt.components.SingletonComponent @InstallIn(SingletonComponent::class) @Module 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 582323a..ef6de41 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,30 +1,58 @@ package com.sundaegukbap.banchango.core.data.mapper +import com.sundaegukbap.banchango.Ingredient +import com.sundaegukbap.banchango.IngredientKind import com.sundaegukbap.banchango.Recipe import com.sundaegukbap.banchango.RecipeDifficulty -import com.sundaegukbap.banchango.core.data.api.model.RecipeRecommendResponse +import com.sundaegukbap.banchango.RecommendedRecipe +import com.sundaegukbap.banchango.core.data.api.model.IngredientResponse +import com.sundaegukbap.banchango.core.data.api.model.RecipeResponse +import com.sundaegukbap.banchango.core.data.api.model.RecommendedRecipeResponse +import com.sundaegukbap.banchango.core.data.api.model.RecommendedRecipesResponse -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 +internal fun List.toData() = + map { + Ingredient( + id = it.id, + name = it.name, + image = it.image ?: "", + kind = + when (it.kind) { + "육류" -> IngredientKind.MEAT + "해산물" -> IngredientKind.SEAFOOD + "채소" -> IngredientKind.VEGETABLE + "과일" -> IngredientKind.FRUIT + "기타" -> IngredientKind.ETC + else -> IngredientKind.ETC + }, + ) } - return Recipe( + +internal fun RecommendedRecipesResponse.toData() = recommendedRecipeResponses.map { it.toData() } + +internal fun RecommendedRecipeResponse.toData() = + RecommendedRecipe( + recipe = recipe.toData(), + hadIngredients = have.ingredients.toData(), + neededIngredients = need.ingredients.toData(), + ) + +internal fun RecipeResponse.toData() = + Recipe( id = id, name = name, introduction = introduction, image = image, link = link, - have = have, - need = need, servings = servings, cookingTime = cookingTime, - difficulty = difficulty, + difficulty = + when (difficulty) { + "아무나" -> RecipeDifficulty.ANYONE + "초보" -> RecipeDifficulty.BEGINNER + "중급" -> RecipeDifficulty.INTERMEDIATE + "고급" -> RecipeDifficulty.ADVANCED + "신의경지" -> RecipeDifficulty.GODLIKE + else -> RecipeDifficulty.ANYONE + }, ) -} diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultRecipeRepository.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultRecipeRepository.kt index 8a734e4..71def4b 100644 --- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultRecipeRepository.kt +++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultRecipeRepository.kt @@ -1,7 +1,6 @@ package com.sundaegukbap.banchango.core.data.repository -import com.sundaegukbap.banchango.LikableRecipe -import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.data.api.RecipeApi import com.sundaegukbap.banchango.core.data.mapper.toData import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository @@ -12,7 +11,7 @@ internal class DefaultRecipeRepository constructor( private val recipeApi: RecipeApi, ) : RecipeRepository { - override suspend fun getRecipeRecommendation(): Result> = + override suspend fun getRecipeRecommendation(): Result> = runCatching { val response = recipeApi.getRecipeRecommendation(1) if (response.isSuccessful) { @@ -25,14 +24,14 @@ internal class DefaultRecipeRepository } } - override suspend fun getRecipeDetail(id: Long): Result = + override suspend fun getRecipeDetail(id: Long): Result = runCatching { val response = recipeApi.getRecipeDetail(1, id) if (response.isSuccessful) { if (response.body() == null) { throw IllegalStateException("Response body is null") } - LikableRecipe(response.body()!!.toData(), false) + response.body()!!.toData() } else { throw IllegalStateException("Response is not successful") } 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 22e81e5..fd1cb76 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,19 +1,45 @@ package com.sundaegukbap.banchango.core.data.repository -import com.sundaegukbap.banchango.LikableRecipe +import com.sundaegukbap.banchango.Ingredient +import com.sundaegukbap.banchango.IngredientKind import com.sundaegukbap.banchango.Recipe import com.sundaegukbap.banchango.RecipeDifficulty +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository import javax.inject.Inject class FakeRecipeRepository @Inject constructor() : RecipeRepository { - override suspend fun getRecipeRecommendation(): Result> = + override suspend fun getRecipeRecommendation(): Result> = Result.success( - List(3) { + List(10) { + RecommendedRecipe( + Recipe( + id = (it + 1).toLong(), + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = + listOf( + Ingredient(1L, "계란", IngredientKind.ETC, ""), + Ingredient(1L, "간장", IngredientKind.ETC, ""), + ), + neededIngredients = listOf(Ingredient(1L, "참기름", IngredientKind.ETC, "")), + ) + }, + ) + + override suspend fun getRecipeDetail(id: Long): Result = + Result.success( + RecommendedRecipe( Recipe( - id = (it + 1).toLong(), + id = 1, name = "간장계란볶음밥", introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", @@ -21,39 +47,13 @@ class FakeRecipeRepository cookingTime = 10, servings = 2, difficulty = RecipeDifficulty.BEGINNER, - have = listOf("계란", "간장"), - need = listOf("식초", "당근", "감자"), - ) - }, - ) - - override suspend fun getRecipeDetail(id: Long): Result = - Result.success( - LikableRecipe( - recipe = - Recipe( - id = id, - name = "간장계란볶음밥", - introduction = - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요." + - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. \n " + - "아이들이 더 좋아할거예요. \n" + - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n" + - " 아이들이 더 좋아할거예요.\n" + - " 아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n 아이들이 더 좋아할거예요.\n " + - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n 아이들이 더 좋아할거예요.\n " + - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n 아이들이 더 좋아할거예요.\n" + - " 아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n 아이들이 더 좋아할거예요.\n " + - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요.\n 아이들이 더 좋아할거예요.\n", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf("계란", "간장"), - need = listOf("식초", "당근", "감자"), + ), + hadIngredients = + listOf( + Ingredient(1L, "계란", IngredientKind.ETC, ""), + Ingredient(1L, "간장", IngredientKind.ETC, ""), ), - isLiked = false, + neededIngredients = listOf(Ingredient(1L, "참기름", IngredientKind.ETC, "")), ), ) 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 d3bac00..e051596 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 @@ -14,6 +14,7 @@ val Orange = Color(0xFFFF7A00) val LightOrange = Color(0xFFFFC085) val White = Color(0xFFFFFFFF) val Black = Color(0xFF000000) +val lightGray = Color(0xFFF5F1EE) // 투명도 50% val SemiTransparentOrange = Color(0x80FF7A00) diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/Ingredient.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Ingredient.kt new file mode 100644 index 0000000..fec7150 --- /dev/null +++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Ingredient.kt @@ -0,0 +1,8 @@ +package com.sundaegukbap.banchango + +data class Ingredient( + val id: Long, + val name: String, + val kind: IngredientKind, + val image: String, +) diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientKind.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientKind.kt new file mode 100644 index 0000000..e9907e6 --- /dev/null +++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientKind.kt @@ -0,0 +1,10 @@ +package com.sundaegukbap.banchango + +enum class IngredientKind { + MEAT, + VEGETABLE, + FRUIT, + SEAFOOD, + SAUCE, + ETC, +} diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/LikableRecipe.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/LikableRecipe.kt index da3a214..2afb97e 100644 --- a/Android/core/model/src/main/java/com/sundaegukbap/banchango/LikableRecipe.kt +++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/LikableRecipe.kt @@ -1,6 +1,6 @@ package com.sundaegukbap.banchango data class LikableRecipe( - val recipe: Recipe, + val recommendedRecipe: RecommendedRecipe, val isLiked: Boolean, ) diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/Recipe.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Recipe.kt index c6a7c43..e530c55 100644 --- a/Android/core/model/src/main/java/com/sundaegukbap/banchango/Recipe.kt +++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Recipe.kt @@ -9,6 +9,4 @@ data class Recipe( val cookingTime: Int, val servings: Int, val difficulty: RecipeDifficulty, - val have: List, - val need: List, ) diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/RecommendedRecipe.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/RecommendedRecipe.kt new file mode 100644 index 0000000..24e941a --- /dev/null +++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/RecommendedRecipe.kt @@ -0,0 +1,7 @@ +package com.sundaegukbap.banchango + +data class RecommendedRecipe( + val recipe: Recipe, + val hadIngredients: List, + val neededIngredients: List, +) diff --git a/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainBottomBar.kt b/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainBottomBar.kt index 3b030cf..a21d390 100644 --- a/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainBottomBar.kt +++ b/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainBottomBar.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable @@ -40,6 +39,7 @@ internal fun MainBottomBar( tabs: PersistentList, currentTab: MainTab?, onTabSelected: (MainTab) -> Unit, + modifier: Modifier = Modifier, ) { AnimatedVisibility( visible = visible, @@ -47,8 +47,7 @@ internal fun MainBottomBar( exit = fadeOut() + slideOut { IntOffset(0, it.height) } ) { Row( - modifier = Modifier - .navigationBarsPadding() + modifier = modifier .fillMaxWidth() .height(56.dp) .background( diff --git a/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainScreen.kt b/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainScreen.kt index ca4bee1..c4b9995 100644 --- a/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainScreen.kt +++ b/Android/feature/main/src/main/java/com/sundaegukbap/banchango/feature/main/MainScreen.kt @@ -3,11 +3,14 @@ package com.sundaegukbap.banchango.feature.main import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp import androidx.navigation.compose.NavHost import com.sundaegukbap.banchango.feature.home.navigation.homeNavGraph import com.sundaegukbap.banchango.feature.recipe.navigation.recipeNavGraph @@ -47,7 +50,9 @@ internal fun MainScreen( visible = navigator.shouldShowBottomBar(), tabs = MainTab.entries.toPersistentList(), currentTab = navigator.currentTab, - onTabSelected = { navigator.navigate(it) } + onTabSelected = { navigator.navigate(it) }, + modifier = Modifier + .navigationBarsPadding() ) } ) diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/LikableHeart.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/LikableHeart.kt new file mode 100644 index 0000000..88d0060 --- /dev/null +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/LikableHeart.kt @@ -0,0 +1,22 @@ +package com.sundaegukbap.banchango.feature.recipe.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import com.sundaegukbap.banchango.feature.reciperecommend.R + +@Composable +fun LikableHeart(isLike: Boolean, onLikeClick: () -> Unit, modifier: Modifier = Modifier) { + val id = if (isLike) { + R.drawable.ic_heart_filled + } else { + R.drawable.ic_heart + } + Image(painterResource(id = id), contentDescription = null, + modifier + .clickable { + onLikeClick() + }) +} 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/component/RecipeExtraInfo.kt similarity index 57% rename from Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailInfo.kt rename to Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/RecipeExtraInfo.kt index 6a441af..c54a560 100644 --- 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/component/RecipeExtraInfo.kt @@ -1,12 +1,11 @@ -package com.sundaegukbap.banchango.feature.recipe.detail +package com.sundaegukbap.banchango.feature.recipe.component 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.foundation.layout.wrapContentHeight import androidx.compose.material3.Text import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable @@ -21,93 +20,107 @@ 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( +fun RecipeExtraInfo( difficulty: RecipeDifficulty, serving: Int, cookingTime: Int, - paddingHorizontal: Int, - modifier: Modifier = Modifier + barHeight: Int, + fontSize: Int, + starSize: Int, + modifier: Modifier = Modifier, ) { - Row(modifier = modifier.fillMaxWidth()) { + Row( + modifier = modifier + .fillMaxWidth() + .wrapContentHeight() + ) { RecipeDetailDifficulty( - modifier = Modifier - .wrapContentSize() - .align(Alignment.CenterVertically) - .padding(horizontal = paddingHorizontal.dp), - difficulty = difficulty + modifier = + Modifier + .weight(1f) + .align(Alignment.CenterVertically), + difficulty = difficulty, + textSize = fontSize, + starSize = starSize, ) - RecipeLine(alignment = Alignment.CenterVertically) + RecipeLine(height = barHeight, alignment = Alignment.CenterVertically) DetailText( - modifier = Modifier.align(Alignment.CenterVertically), + modifier = + Modifier + .weight(1f) + .align(Alignment.CenterVertically), text = "${serving}인분", - paddingHorizontal = paddingHorizontal + fontSize = fontSize, ) - RecipeLine(alignment = Alignment.CenterVertically) + RecipeLine(height = barHeight, alignment = Alignment.CenterVertically) DetailText( modifier = Modifier.align(Alignment.CenterVertically), text = "${cookingTime}m", - paddingHorizontal = paddingHorizontal + fontSize = fontSize, ) } } @Composable private fun RecipeDetailDifficulty( + difficulty: RecipeDifficulty, + textSize: Int, + starSize: Int, modifier: Modifier = Modifier, - difficulty: RecipeDifficulty ) { Column(modifier = modifier) { Stars( - modifier = Modifier.wrapContentSize(), - starSize = 14, - filledCount = difficulty.level - ) - Text( + starSize = starSize, + filledCount = difficulty.level, modifier = Modifier - .wrapContentSize() .align(Alignment.CenterHorizontally), + ) + Text( text = difficulty.explain, - fontSize = 12.sp, + fontSize = textSize.sp, fontWeight = Bold, color = Orange, + modifier = + Modifier + .align(Alignment.CenterHorizontally), ) } } @Composable -private fun RowScope.RecipeLine(alignment: Alignment.Vertical) { +private fun RowScope.RecipeLine(height: Int, alignment: Alignment.Vertical) { VerticalDivider( - modifier = Modifier - .height(52.dp) + modifier = + Modifier + .height(height.dp) .align(alignment), color = LightOrange, - thickness = 2.dp + thickness = 2.dp, ) } @Composable private fun RowScope.DetailText( + text: String, + fontSize: Int, modifier: Modifier = Modifier, - paddingHorizontal: Int, - text: String ) { Text( - modifier = modifier - .wrapContentSize() - .padding(horizontal = paddingHorizontal.dp) - .align(Alignment.CenterVertically), text = text, - fontSize = 12.sp, + fontSize = fontSize.sp, fontWeight = Bold, color = Orange, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, + modifier = + modifier + .weight(1f) + .fillMaxWidth(), ) } @@ -115,12 +128,13 @@ private fun RowScope.DetailText( @Composable fun RecipeDetailInfoPreview() { BanchangoTheme { - RecipeDetailInfo( + RecipeExtraInfo( difficulty = RecipeDifficulty.ADVANCED, serving = 2, cookingTime = 30, - 20, + fontSize = 12, + starSize = 20, + barHeight = 56, ) } } - diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/difficulty/Stars.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/Stars.kt similarity index 74% rename from Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/difficulty/Stars.kt rename to Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/Stars.kt index c4bccd5..28dbdab 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/difficulty/Stars.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/component/Stars.kt @@ -1,4 +1,4 @@ -package com.sundaegukbap.banchango.feature.recipe.difficulty +package com.sundaegukbap.banchango.feature.recipe.component import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Row @@ -20,18 +20,21 @@ fun Stars( ) { Row(modifier = modifier) { repeat(filledCount) { - Star(modifier = Modifier.size(starSize.dp), isFilled = true) + Star(starSize, isFilled = true) } repeat(5 - filledCount) { - Star(modifier = Modifier.size(starSize.dp), isFilled = false) + Star(starSize, isFilled = false) } } } @Composable -fun Star(modifier: Modifier, isFilled: Boolean) { +fun Star( + size: Int, + isFilled: Boolean, +) { Image( - modifier = modifier, + modifier = Modifier.size(size.dp), painter = painterResource(id = if (isFilled) R.drawable.ic_star_filled else R.drawable.ic_star_outline), contentDescription = null, ) @@ -42,8 +45,8 @@ fun Star(modifier: Modifier, isFilled: Boolean) { fun StarPreview() { BanchangoTheme { Row { - Star(modifier = Modifier.size(40.dp), isFilled = true) - Star(modifier = Modifier.size(40.dp), isFilled = false) + Star(size = 40, isFilled = true) + Star(size = 40, isFilled = false) } } } diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailCard.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailCard.kt index 5c7c8b5..d45d6c6 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailCard.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailCard.kt @@ -20,53 +20,62 @@ 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 com.sundaegukbap.banchango.Ingredient +import com.sundaegukbap.banchango.IngredientKind import com.sundaegukbap.banchango.Recipe import com.sundaegukbap.banchango.RecipeDifficulty +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.designsystem.theme.LightOrange import com.sundaegukbap.banchango.core.designsystem.theme.Orange +import com.sundaegukbap.banchango.feature.recipe.component.RecipeExtraInfo @Composable fun RecipeDetailCard( - recipe: Recipe, + recommendRecipe: RecommendedRecipe, modifier: Modifier = Modifier, ) { LazyColumn( modifier = modifier, ) { item { - RecipeDetailInfo( - difficulty = recipe.difficulty, - serving = recipe.servings, - cookingTime = recipe.cookingTime, + RecipeExtraInfo( + difficulty = recommendRecipe.recipe.difficulty, + serving = recommendRecipe.recipe.servings, + cookingTime = recommendRecipe.recipe.cookingTime, modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp), - paddingHorizontal = 32, + Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp), + fontSize = 12, + starSize = 14, + barHeight = 56, ) } item { Text( modifier = Modifier.padding(top = 20.dp, start = 12.dp, end = 12.dp), - text = recipe.name, + text = recommendRecipe.recipe.name, fontSize = 20.sp, fontWeight = FontWeight.Bold, ) } - item { Text( - text = recipe.introduction, + text = recommendRecipe.recipe.introduction, fontSize = 12.sp, modifier = Modifier.padding(top = 12.dp, start = 12.dp, end = 12.dp), ) } item { - Ingredients(title = "핵심 재료", have = recipe.have, need = recipe.need) + Ingredients( + title = "핵심 재료", + have = recommendRecipe.hadIngredients, + need = recommendRecipe.neededIngredients, + ) } item { - Ingredients("식자재", recipe.have, recipe.need) + Ingredients("식자재", recommendRecipe.hadIngredients, recommendRecipe.neededIngredients) } } } @@ -74,14 +83,14 @@ fun RecipeDetailCard( @Composable private fun Ingredients( title: String, - have: List, - need: List, + have: List, + need: List, ) { Box( modifier = - Modifier - .fillMaxWidth() - .padding(top = 20.dp, start = 12.dp, end = 12.dp), + Modifier + .fillMaxWidth() + .padding(top = 20.dp, start = 12.dp, end = 12.dp), ) { Text( text = title, @@ -94,10 +103,10 @@ private fun Ingredients( fontSize = 12.sp, fontWeight = FontWeight.Bold, modifier = - Modifier - .background(color = Orange, shape = CircleShape) - .padding(horizontal = 8.dp) - .align(Alignment.CenterEnd), + Modifier + .background(color = Orange, shape = CircleShape) + .padding(horizontal = 8.dp) + .align(Alignment.CenterEnd), ) } @@ -111,7 +120,7 @@ private fun Ingredients( horizontalArrangement = Arrangement.spacedBy(12.dp), ) { val ingredients = - have.map { ItemIngredient(it, true) } + need.map { ItemIngredient(it, false) } + have.map { ItemIngredient(it.name, true) } + need.map { ItemIngredient(it.name, false) } itemsIndexed(ingredients) { index, it -> if (index == 0) { IngredientCard(it, modifier = Modifier.padding(start = 12.dp)) @@ -129,12 +138,12 @@ private fun IngredientCard( ) { Box( modifier = - modifier - .border(1.dp, color = Orange, shape = CircleShape) - .background( - color = if (itemIngredient.has) Color.White else LightOrange, - shape = CircleShape, - ), + modifier + .border(1.dp, color = Orange, shape = CircleShape) + .background( + color = if (itemIngredient.has) Color.White else LightOrange, + shape = CircleShape, + ), ) { Text(modifier = Modifier.padding(16.dp), text = itemIngredient.name) } @@ -149,20 +158,27 @@ data class ItemIngredient( @Composable fun RecipeDetailCardPreview() { RecipeDetailCard( - recipe = + recommendRecipe = + RecommendedRecipe( + recipe = Recipe( id = 1, name = "간장계란볶음밥", introduction = - "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. \n " + + "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. \n " + "아이들이 더 좋아할거예요. \n", image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", link = "https://www.10000recipe.com/recipe/6889616", cookingTime = 10, servings = 2, difficulty = RecipeDifficulty.BEGINNER, - have = listOf("계란", "간장"), - need = listOf("식초", "당근", "감자", "깨소금", "밥"), ), + hadIngredients = + listOf( + Ingredient(1L, "계란", IngredientKind.ETC, ""), + Ingredient(1L, "간장", IngredientKind.ETC, ""), + ), + neededIngredients = listOf(Ingredient(1L, "참기름", IngredientKind.ETC, "")), + ), ) } 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 b226b83..8fb67c9 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 @@ -32,9 +32,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sundaegukbap.banchango.Ingredient +import com.sundaegukbap.banchango.IngredientKind import com.sundaegukbap.banchango.LikableRecipe import com.sundaegukbap.banchango.Recipe import com.sundaegukbap.banchango.RecipeDifficulty +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.designsystem.component.NetworkImage @Composable @@ -55,7 +58,7 @@ fun RecipeDetailRoute( onChangeSystemBarsColor = onChangeSystemBarsColor, modifier = modifier, ) { likableRecipe -> - viewModel.likeRecipe(likableRecipe.recipe.id, !likableRecipe.isLiked) + viewModel.likeRecipe(likableRecipe.recommendedRecipe.recipe.id, !likableRecipe.isLiked) } } @@ -92,7 +95,7 @@ fun RecipeDetailContent( private fun RecipeDetailLoading() { Box( modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { CircularProgressIndicator() } @@ -134,24 +137,24 @@ private fun RecipeDetailScreen( Box( modifier = - modifier - .windowInsetsPadding(WindowInsets.navigationBars) - .fillMaxSize(), + modifier + .windowInsetsPadding(WindowInsets.navigationBars) + .fillMaxSize(), ) { RecipeImage( - imageUrl = likableRecipe.recipe.image, + imageUrl = likableRecipe.recommendedRecipe.recipe.image, modifier = - Modifier - .fillMaxWidth() - .height(screenHeight * 0.5f) - .align(Alignment.TopCenter), + Modifier + .fillMaxWidth() + .height(screenHeight * 0.5f) + .align(Alignment.TopCenter), ) BottomSheetScaffold( scaffoldState = scaffoldState, sheetContent = { RecipeDetailCard( - likableRecipe.recipe, - Modifier.height(screenHeight * 0.98f), + recommendRecipe = likableRecipe.recommendedRecipe, + modifier = Modifier.height(screenHeight * 0.98f), ) }, sheetContainerColor = Color.White, @@ -167,11 +170,11 @@ private fun RecipeDetailScreen( ) BtnMoveToRecipe( - likableRecipe.recipe.link, + likableRecipe.recommendedRecipe.recipe.link, modifier = Modifier .align(Alignment.BottomCenter) - .padding(bottom = 60.dp), + .padding(bottom = 32.dp), ) } } @@ -191,15 +194,15 @@ private fun RecipeImage( .fillMaxSize() .background( brush = - Brush.verticalGradient( - colors = - listOf( - Color.Black.copy(alpha = 0.3f), - Color.Transparent, + Brush.verticalGradient( + colors = + listOf( + Color.Black.copy(alpha = 0.3f), + Color.Transparent, + ), + startY = 0f, + endY = Float.POSITIVE_INFINITY, ), - startY = 0f, - endY = Float.POSITIVE_INFINITY, - ), ), ) } @@ -211,18 +214,30 @@ fun RecipeDetailScreenPreview() { RecipeDetailScreen( likableRecipe = LikableRecipe( - recipe = - Recipe( - id = 1, - name = "간장계란볶음밥", - introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf("계란", "간장"), - need = listOf("식초", "당근", "감자"), + recommendedRecipe = + RecommendedRecipe( + recipe = + Recipe( + id = 1, + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = + listOf( + Ingredient(1L, "계란", IngredientKind.MEAT, ""), + Ingredient(2L, "간장", IngredientKind.SAUCE, ""), + ), + neededIngredients = + listOf( + Ingredient(1L, "식초", IngredientKind.MEAT, ""), + Ingredient(2L, "당근", IngredientKind.SAUCE, ""), + Ingredient(2L, "감자", IngredientKind.SAUCE, ""), + ), ), isLiked = false, ), diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailViewModel.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailViewModel.kt index 031412e..1bbd901 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailViewModel.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/detail/RecipeDetailViewModel.kt @@ -2,6 +2,7 @@ package com.sundaegukbap.banchango.feature.recipe.detail import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.sundaegukbap.banchango.LikableRecipe import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -24,9 +25,9 @@ class RecipeDetailViewModel viewModelScope.launch { recipeRepository .getRecipeDetail(recipeId) - .onSuccess { likableRecipe -> + .onSuccess { recommendedRecipe -> _uiState.value = - RecipeDetailUiState.Success(likableRecipe) + RecipeDetailUiState.Success(LikableRecipe(recommendedRecipe, false)) }.onFailure { throwable -> _uiState.value = RecipeDetailUiState.Error(throwable) } 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 607081c..b959900 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 @@ -3,216 +3,200 @@ package com.sundaegukbap.banchango.feature.recipe.recommend import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight.Companion.Bold -import androidx.compose.ui.text.style.TextAlign +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.compose.ui.util.lerp +import com.sundaegukbap.banchango.Ingredient +import com.sundaegukbap.banchango.IngredientKind import com.sundaegukbap.banchango.Recipe import com.sundaegukbap.banchango.RecipeDifficulty +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.designsystem.component.NetworkImage import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme +import com.sundaegukbap.banchango.core.designsystem.theme.Orange +import com.sundaegukbap.banchango.core.designsystem.theme.lightGray +import com.sundaegukbap.banchango.feature.recipe.component.LikableHeart +import com.sundaegukbap.banchango.feature.recipe.component.RecipeExtraInfo import com.sundaegukbap.banchango.feature.reciperecommend.R @Composable fun RecipeItem( - recipeItemUiState: RecipeRecommendItemUiState, - pageOffset: Float, - onRecipeClick: (Recipe) -> Unit = {}, - onRecipeLikeClick: (Recipe) -> Unit = {}, + recipeRecommendItemUiState: RecipeRecommendItemUiState, + onRecipeClick: (Recipe) -> Unit, + onRecipeLikeClick: (Recipe) -> Unit, + modifier: Modifier =Modifier ) { - Box( - modifier = Modifier - .fillMaxSize() - .graphicsLayer { - scaleX = lerp( - start = 0.9f, - stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) - ) - scaleY = lerp( - start = 0.9f, - stop = 1f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) - ) - } - .clip(shape = RoundedCornerShape(44.dp)) + Column( + modifier = modifier + .fillMaxWidth() .clickable { - onRecipeClick(recipeItemUiState.recipe) + onRecipeClick(recipeRecommendItemUiState.recommendedRecipe.recipe) } + .shadow(4.dp, RoundedCornerShape(20.dp)) + .background(Color.White, shape = RoundedCornerShape(20.dp)) ) { - NetworkImage( - modifier = Modifier - .fillMaxSize(), - url = recipeItemUiState.recipe.image, - ) - RecipeInfo( - recipeItemUiState.recipe, - modifier = Modifier.fillMaxSize(), - ) + Box { + NetworkImage( + url = recipeRecommendItemUiState.recommendedRecipe.recipe.image, + modifier = + Modifier + .clip(RoundedCornerShape(20.dp)) + .height(128.dp) + .fillMaxWidth(), + ) + Box( + Modifier + .align(Alignment.TopEnd) + .padding(top = 12.dp, end = 12.dp) + .background(Color.White, shape = CircleShape) + ) { + LikableHeart( + modifier = Modifier + .padding(8.dp) + .size(24.dp), + isLike = recipeRecommendItemUiState.isLiked, + onLikeClick = { + onRecipeLikeClick(recipeRecommendItemUiState.recommendedRecipe.recipe) + } + ) - RecipeIngredientCount( - modifier = Modifier - .align(Alignment.BottomStart), - have = recipeItemUiState.recipe.have.count(), - need = recipeItemUiState.recipe.need.count(), - imageSize = 95, - ) + } - RecipeLikeButton( - modifier = Modifier - .align(Alignment.BottomEnd), - isLiked = recipeItemUiState.isLiked, - onLikeClick = { onRecipeLikeClick(recipeItemUiState.recipe) }, + } + Text( + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 12.dp, top = 12.dp), + text = recipeRecommendItemUiState.recommendedRecipe.recipe.name, ) - - Box( - Modifier - .fillMaxSize() - .background( - color = Color.Black.copy( - alpha = lerp( - start = 0.5f, - stop = 0f, - fraction = 1f - pageOffset.coerceIn(0f, 1f) - ) - ), + Row(Modifier.padding(12.dp)) { + Row( + modifier = + Modifier + .weight(1f) + .align(CenterVertically), + ) { + Image( + modifier = + Modifier + .align(CenterVertically) + .weight(1f), + painter = painterResource(R.drawable.ic_fridge), + contentDescription = "", ) - ) - } -} - -@Composable -private fun RecipeInfo( - recipe: Recipe, - modifier: Modifier, -) { - Box(modifier = modifier) { - Text( - text = recipe.name, - color = Color.White, - fontSize = 24.sp, - maxLines = 2, - minLines = 2, - style = TextStyle(fontWeight = Bold), - textAlign = TextAlign.Center, - modifier = Modifier - .background( - brush = Brush.verticalGradient(listOf(Color.Black, Color.Transparent)), - alpha = 0.8f + Text( + modifier = + Modifier + .align(CenterVertically) + .weight(1f), + color = Orange, + fontWeight = FontWeight.Bold, + text = "${recipeRecommendItemUiState.hadCount} / ${recipeRecommendItemUiState.hadCount + recipeRecommendItemUiState.needCount}", ) - .fillMaxWidth() - .padding(vertical = 40.dp, horizontal = 16.dp), - ) + } + RecipeExtraInfoContainer( + cookingTime = recipeRecommendItemUiState.recommendedRecipe.recipe.cookingTime, + serving = recipeRecommendItemUiState.recommendedRecipe.recipe.servings, + difficulty = recipeRecommendItemUiState.recommendedRecipe.recipe.difficulty, + modifier = + Modifier + .weight(2f) + .clip(RoundedCornerShape(20.dp)) + .background(lightGray) + .padding(vertical = 10.dp, horizontal = 6.dp), + ) + } } } @Composable -fun RecipeLikeButton( - modifier: Modifier, - isLiked: Boolean, - onLikeClick: () -> Unit, +private fun RecipeExtraInfoContainer( + difficulty: RecipeDifficulty, + serving: Int, + cookingTime: Int, + modifier: Modifier = Modifier, ) { Box( - modifier = modifier - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - onClick = onLikeClick - ) + modifier = modifier, ) { - Image( - painter = painterResource(id = R.drawable.img_btn_right), - contentDescription = null, - modifier = Modifier.size(95.dp), - ) - Image( - painter = painterResource(id = if (isLiked) R.drawable.ic_heart_filled else R.drawable.ic_heart), - contentDescription = null, - modifier = Modifier - .size(32.dp) - .align(Alignment.Center) - .padding(top = 8.dp), + RecipeExtraInfo( + difficulty = difficulty, + serving = serving, + cookingTime = cookingTime, + fontSize = 10, + starSize = 10, + barHeight = 32 ) } } -@Preview(showBackground = false) @Composable -fun RecipeItemPreview() { +@Preview(showBackground = false) +fun PreviewRecipeItem() { BanchangoTheme { - RecipeItem( - recipeItemUiState = RecipeRecommendItemUiState( - recipe = Recipe( - id = 1, - name = "간장계란볶음밥", - introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf(""), - need = listOf(""), - ), - isLiked = true, - ), - pageOffset = 0f, - ) - } -} - -@Composable -fun RecipeIngredientCount( - modifier: Modifier, - imageSize: Int, - have: Int, - need: Int, -) { - Box(modifier = modifier) { - Image( - modifier = Modifier.size(imageSize.dp), - painter = painterResource(id = R.drawable.img_wave), - contentDescription = null, - ) - Text( - text = "$have / ${need + have}", - modifier = Modifier - .padding(top = 32.dp) - .align(Alignment.Center), - color = Color.White, - style = TextStyle( - letterSpacing = 0.1.sp, - fontWeight = Bold, - fontSize = 20.sp - ), + RecipeExtraInfoContainer( + cookingTime = 10, + serving = 2, + difficulty = RecipeDifficulty.BEGINNER, ) } } @Preview(showBackground = false) @Composable -fun RecipeIngredientCountPreview() { +private fun RecipeItem2Preview() { BanchangoTheme { - RecipeIngredientCount(modifier = Modifier, have = 3, need = 7, imageSize = 120) + RecipeItem( + recipeRecommendItemUiState = + RecipeRecommendItemUiState( + recommendedRecipe = + RecommendedRecipe( + recipe = + Recipe( + id = 1, + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = + listOf( + Ingredient(1L, "계란", IngredientKind.MEAT, ""), + Ingredient(2L, "간장", IngredientKind.SAUCE, ""), + ), + neededIngredients = + listOf( + Ingredient(1L, "식초", IngredientKind.MEAT, ""), + Ingredient(2L, "당근", IngredientKind.SAUCE, ""), + Ingredient(2L, "감자", IngredientKind.SAUCE, ""), + ), + ), + isLiked = false, + ), + onRecipeClick = {}, + onRecipeLikeClick = {}, + ) } } diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendItemUiState.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendItemUiState.kt index dd9f943..cad51de 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendItemUiState.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendItemUiState.kt @@ -1,8 +1,11 @@ package com.sundaegukbap.banchango.feature.recipe.recommend -import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecommendedRecipe data class RecipeRecommendItemUiState( - val recipe: Recipe, + val recommendedRecipe: RecommendedRecipe, val isLiked: Boolean, -) +) { + val hadCount = recommendedRecipe.hadIngredients.count() + val needCount = recommendedRecipe.neededIngredients.count() +} diff --git a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendViewModel.kt b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendViewModel.kt index 9a31afd..30c631f 100644 --- a/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendViewModel.kt +++ b/Android/feature/recipe/src/main/java/com/sundaegukbap/banchango/feature/recipe/recommend/RecipeRecommendViewModel.kt @@ -3,9 +3,9 @@ package com.sundaegukbap.banchango.feature.recipe.recommend import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sundaegukbap.banchango.Recipe +import com.sundaegukbap.banchango.RecommendedRecipe import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -13,24 +13,24 @@ import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class RecipeRecommendViewModel @Inject constructor( +class RecipeRecommendViewModel +@Inject +constructor( private val recipeRepository: RecipeRepository, ) : ViewModel() { - private val _uiState: MutableStateFlow = MutableStateFlow(RecipeRecommendUiState.Loading) val uiState: StateFlow = _uiState.asStateFlow() - fun getRecipeRecommendation() { - val remainRecipes = (_uiState.value as? RecipeRecommendUiState.Success)?.recipes ?: listOf() + _uiState.value = RecipeRecommendUiState.Loading viewModelScope.launch { - recipeRepository.getRecipeRecommendation() + recipeRepository + .getRecipeRecommendation() .onSuccess { recipes -> - _uiState.value = RecipeRecommendUiState.Success( - remainRecipes + recipes.toUiState() - ) + _uiState.value = + RecipeRecommendUiState.Success(recipes.toUiState()) }.onFailure { throwable -> throwable.printStackTrace() } @@ -39,19 +39,19 @@ class RecipeRecommendViewModel @Inject constructor( fun likeRecipe(recipe: Recipe) { val successUiState = _uiState.value as? RecipeRecommendUiState.Success ?: return - val likedRecipeUiStates = successUiState.recipes.map { recipeUiState -> - if (recipeUiState.recipe.id == recipe.id) { - recipeUiState.copy(isLiked = !recipeUiState.isLiked) - } else { - recipeUiState + val likedRecipeUiStates = + successUiState.recipes.map { recipeUiState -> + if (recipeUiState.recommendedRecipe.recipe.id == recipe.id) { + recipeUiState.copy(isLiked = !recipeUiState.isLiked) + } else { + recipeUiState + } } - } _uiState.value = RecipeRecommendUiState.Success(likedRecipeUiStates) } - private fun List.toUiState(): List { - return map { recipe -> - RecipeRecommendItemUiState(recipe = recipe, isLiked = false) + private fun List.toUiState(): List = + map { recipe -> + RecipeRecommendItemUiState(recommendedRecipe = recipe, isLiked = false) } - } } 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 df1b2d3..92c3092 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 @@ -1,26 +1,36 @@ package com.sundaegukbap.banchango.feature.recipe.recommend +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.pager.VerticalPager -import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview 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.RecommendedRecipe import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme -import kotlin.math.absoluteValue +import com.sundaegukbap.banchango.feature.reciperecommend.R @Composable fun RecipeRecommendRoute( @@ -32,17 +42,18 @@ fun RecipeRecommendRoute( val uiState by viewModel.uiState.collectAsStateWithLifecycle() LaunchedEffect(Unit) { - if (uiState is RecipeRecommendUiState.Loading) + if (uiState is RecipeRecommendUiState.Loading) { viewModel.getRecipeRecommendation() + } } RecipeRecommendContent( padding = padding, uiState = uiState, + onRefreshClick = { viewModel.getRecipeRecommendation() }, onLikeClick = { viewModel.likeRecipe(it) }, - onLastPageVisible = { viewModel.getRecipeRecommendation() }, onRecipeClick = onRecipeClick, - onChangeSystemBarsColor = onChangeStatusBarColor + onChangeSystemBarsColor = onChangeStatusBarColor, ) } @@ -50,16 +61,18 @@ fun RecipeRecommendRoute( fun RecipeRecommendContent( padding: PaddingValues, uiState: RecipeRecommendUiState, + onRefreshClick: () -> Unit, onLikeClick: (Recipe) -> Unit, - onLastPageVisible: () -> Unit, onRecipeClick: (Recipe) -> Unit, onChangeSystemBarsColor: (color: Color, darkIcons: Boolean) -> Unit, ) { + onChangeSystemBarsColor(Color.White, true) when (uiState) { is RecipeRecommendUiState.Loading -> { RecipeRecommendLoading( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center + padding = padding, + contentAlignment = Alignment.Center, + onRefreshClick = {}, ) } @@ -68,17 +81,31 @@ fun RecipeRecommendContent( recipeRecommends = uiState.recipes, padding = padding, onLikeClick = onLikeClick, - onLastPageVisible = onLastPageVisible, - onRecipeClick = onRecipeClick + onRecipeClick = onRecipeClick, + onRefreshClick = onRefreshClick, ) } } } @Composable -fun RecipeRecommendLoading(modifier: Modifier, contentAlignment: Alignment) { - Box(modifier = modifier, contentAlignment = contentAlignment) { - CircularProgressIndicator() +fun RecipeRecommendLoading( + padding: PaddingValues, + contentAlignment: Alignment, + onRefreshClick: () -> Unit, +) { + Box( + modifier = Modifier + .padding(padding) + .fillMaxSize() + .padding(horizontal = 16.dp), + contentAlignment = contentAlignment + ) { + RecipeRecommendTopBar(onRefreshClick, Modifier.align(Alignment.TopCenter)) + CircularProgressIndicator( + modifier = Modifier + .align(Alignment.Center) + ) } } @@ -86,101 +113,119 @@ fun RecipeRecommendLoading(modifier: Modifier, contentAlignment: Alignment) { private fun RecipeRecommendScreen( padding: PaddingValues, recipeRecommends: List, + onRefreshClick: () -> Unit, onLikeClick: (Recipe) -> Unit, onRecipeClick: (Recipe) -> Unit, - onLastPageVisible: () -> Unit, ) { - val pagerState = rememberPagerState(pageCount = { recipeRecommends.size + 1 }) - - Box(modifier = Modifier.fillMaxSize()) { - VerticalPager( - modifier = Modifier.padding(padding), - state = pagerState, - contentPadding = PaddingValues(vertical = 136.dp, horizontal = 32.dp), - pageSpacing = 24.dp, - ) { page -> - if (page >= recipeRecommends.size - 2) { - onLastPageVisible() - } - val pageOffset = - (pagerState.currentPage - page + pagerState.currentPageOffsetFraction).absoluteValue - - if (page == pagerState.pageCount - 1) { - RecipeRecommendLoading( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) - } else { - RecipeItem( - recipeItemUiState = recipeRecommends[page], - onRecipeClick = onRecipeClick, - onRecipeLikeClick = onLikeClick, - pageOffset = pageOffset, - ) - } + val listState = rememberLazyListState() + LazyColumn( + state = listState, + contentPadding = padding, + modifier = Modifier.padding(horizontal = 16.dp) + ) { + item { + RecipeRecommendTopBar(onRefreshClick = onRefreshClick) + } + items( + items = recipeRecommends, + key = { it.recommendedRecipe.recipe.id } + ) { item -> + RecipeItem(item, onRecipeClick, onLikeClick) + Spacer(modifier = Modifier.height(20.dp)) } } } -@Preview(showBackground = false) +@Composable +private fun RecipeRecommendTopBar(onRefreshClick: () -> Unit, modifier: Modifier = Modifier) { + Box( + modifier = modifier + .padding(vertical = 20.dp) + .fillMaxWidth() + ) { + Text(text = "AI 레시피 추천", fontWeight = FontWeight.Bold) + Image( + painterResource(id = R.drawable.ic_refresh), + contentDescription = "refresh", + modifier = Modifier + .align(Alignment.CenterEnd) + .clickable { onRefreshClick() } + ) + } +} + +@Preview(showBackground = true) @Composable fun RecipePagePreview() { BanchangoTheme { RecipeRecommendContent( padding = PaddingValues(16.dp), onLikeClick = {}, - onLastPageVisible = {}, onRecipeClick = {}, + onRefreshClick = {}, onChangeSystemBarsColor = { _, _ -> }, - uiState = RecipeRecommendUiState.Success( + uiState = + RecipeRecommendUiState.Success( listOf( RecipeRecommendItemUiState( - recipe = Recipe( - id = 1, - name = "간장계란볶음밥", - introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf(""), - need = listOf(""), + recommendedRecipe = + RecommendedRecipe( + recipe = + Recipe( + id = 1, + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = listOf(), + neededIngredients = listOf(), ), - isLiked = false + isLiked = false, ), RecipeRecommendItemUiState( - recipe = Recipe( - id = 1, - name = "간장계란볶음밥", - introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf(""), - need = listOf(""), + recommendedRecipe = + RecommendedRecipe( + recipe = + Recipe( + id = 1, + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = listOf(), + neededIngredients = listOf(), ), - isLiked = false + isLiked = false, ), RecipeRecommendItemUiState( - recipe = Recipe( - id = 1, - name = "간장계란볶음밥", - introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", - image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", - link = "https://www.10000recipe.com/recipe/6889616", - cookingTime = 10, - servings = 2, - difficulty = RecipeDifficulty.BEGINNER, - have = listOf(""), - need = listOf(""), + recommendedRecipe = + RecommendedRecipe( + recipe = + Recipe( + id = 1, + name = "간장계란볶음밥", + introduction = "아주 간단하면서 맛있는 계란간장볶음밥으로 한끼식사 만들어보세요. 아이들이 더 좋아할거예요.", + image = "https://recipe1.ezmember.co.kr/cache/recipe/2018/05/26/d0c6701bc673ac5c18183b47212a58571.jpg", + link = "https://www.10000recipe.com/recipe/6889616", + cookingTime = 10, + servings = 2, + difficulty = RecipeDifficulty.BEGINNER, + ), + hadIngredients = listOf(), + neededIngredients = listOf(), ), - isLiked = false + isLiked = false, ), - ) - ) + ), + ), ) } } diff --git a/Android/feature/recipe/src/main/res/drawable/ic_fridge.png b/Android/feature/recipe/src/main/res/drawable/ic_fridge.png new file mode 100644 index 0000000..a3adc1f Binary files /dev/null and b/Android/feature/recipe/src/main/res/drawable/ic_fridge.png differ diff --git a/Android/feature/recipe/src/main/res/drawable/ic_refresh.xml b/Android/feature/recipe/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 0000000..86504d0 --- /dev/null +++ b/Android/feature/recipe/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,5 @@ + + + + +