From f2de6ba2099dcb61e64e2390660c84237ab81d55 Mon Sep 17 00:00:00 2001
From: Choi SeongHoon <108349655+SeongHoonC@users.noreply.github.com>
Date: Wed, 18 Sep 2024 10:50:59 +0900
Subject: [PATCH] =?UTF-8?q?[Android]=20feat:=20=EC=9E=AC=EB=A3=8C=20?=
=?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=B3=B4=EA=B8=B0=20=EA=B0=9C=EB=B0=9C(#4?=
=?UTF-8?q?1)=20(#42)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: Data Response model 정의
* feat: 재료 Domain Model 정의
* feat: 재료 요청 Retrofit API 정의
* feat: 재료 DTO 맵퍼 정의
* feat: 재료 저장소 및 냉장고 식자재 가져오기 정의
* feat: Default 재료 저장소 의존성 주입
* feat: 냉장고 재료 화면 보기 개발
* feat: 냉장고 재료 상자 이름 색깔 추가
---
Android/.idea/deploymentTargetSelector.xml | 10 +-
Android/app/build.gradle.kts | 1 +
.../repository/api/IngredientRepository.kt | 7 +
.../banchango/core/data/api/IngredientApi.kt | 13 +
.../core/data/api/model/ContainerDto.kt | 9 +
.../data/api/model/ContainerIngredientDto.kt | 12 +
.../data/api/model/ContainerIngredientDtos.kt | 8 +
.../core/data/api/model/IngredientDto.kt | 11 +
.../banchango/core/data/di/ApiModule.kt | 7 +
.../core/data/di/RepositoryModule.kt | 14 +-
.../core/data/mapper/IngredientMapper.kt | 37 ++
.../repository/DefaultIngredientRepository.kt | 31 ++
.../repository/FakeIngredientRepository.kt | 54 +++
.../core/designsystem/theme/Color.kt | 4 +-
.../com/sundaegukbap/banchango/Container.kt | 6 +
.../banchango/ContainerIngredient.kt | 12 +
.../banchango/IngredientContainer.kt | 7 +
.../banchango/IngredientContainers.kt | 28 ++
.../sundaegukbap/banchango/IngredientKind.kt | 14 +-
.../banchango/KindIngredientContainer.kt | 6 +
Android/feature/home/build.gradle.kts | 1 +
.../banchango/feature/home/HomeScreen.kt | 320 +++++++++++++++++-
.../banchango/feature/home/HomeViewModel.kt | 45 +++
.../feature/home/navigation/HomeNavigator.kt | 5 +-
.../home/src/main/res/drawable/ic_add.xml | 5 +
Android/feature/recipe/build.gradle.kts | 1 -
26 files changed, 646 insertions(+), 22 deletions(-)
create mode 100644 Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/IngredientRepository.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/IngredientApi.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerDto.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDto.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDtos.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientDto.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/IngredientMapper.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultIngredientRepository.kt
create mode 100644 Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeIngredientRepository.kt
create mode 100644 Android/core/model/src/main/java/com/sundaegukbap/banchango/Container.kt
create mode 100644 Android/core/model/src/main/java/com/sundaegukbap/banchango/ContainerIngredient.kt
create mode 100644 Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainer.kt
create mode 100644 Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainers.kt
create mode 100644 Android/core/model/src/main/java/com/sundaegukbap/banchango/KindIngredientContainer.kt
create mode 100644 Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeViewModel.kt
create mode 100644 Android/feature/home/src/main/res/drawable/ic_add.xml
diff --git a/Android/.idea/deploymentTargetSelector.xml b/Android/.idea/deploymentTargetSelector.xml
index da5007a..edb63e4 100644
--- a/Android/.idea/deploymentTargetSelector.xml
+++ b/Android/.idea/deploymentTargetSelector.xml
@@ -4,21 +4,15 @@
-
+
-
+
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Android/app/build.gradle.kts b/Android/app/build.gradle.kts
index 0de2262..3c9df5d 100644
--- a/Android/app/build.gradle.kts
+++ b/Android/app/build.gradle.kts
@@ -55,6 +55,7 @@ dependencies {
// modules
implementation(project(":feature:main"))
+ implementation(project(":core:data"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
diff --git a/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/IngredientRepository.kt b/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/IngredientRepository.kt
new file mode 100644
index 0000000..dfc0ae7
--- /dev/null
+++ b/Android/core/data-api/src/main/java/com/sundaegukbap/banchango/core/data/repository/api/IngredientRepository.kt
@@ -0,0 +1,7 @@
+package com.sundaegukbap.banchango.core.data.repository.api
+
+import com.sundaegukbap.banchango.ContainerIngredient
+
+interface IngredientRepository {
+ suspend fun getIngredientContainers(): Result>
+}
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/IngredientApi.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/IngredientApi.kt
new file mode 100644
index 0000000..ac63973
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/IngredientApi.kt
@@ -0,0 +1,13 @@
+package com.sundaegukbap.banchango.core.data.api
+
+import com.sundaegukbap.banchango.core.data.api.model.ContainerIngredientDtos
+import retrofit2.Response
+import retrofit2.http.GET
+import retrofit2.http.Path
+
+internal interface IngredientApi {
+ @GET("api/ingredients/main/list/{userid}")
+ suspend fun getIngredients(
+ @Path("userid") userId: Long,
+ ): Response
+}
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerDto.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerDto.kt
new file mode 100644
index 0000000..c6f2375
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerDto.kt
@@ -0,0 +1,9 @@
+package com.sundaegukbap.banchango.core.data.api.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ContainerDto(
+ val containerId: Long,
+ val containerName: String
+)
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDto.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDto.kt
new file mode 100644
index 0000000..97b5d19
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDto.kt
@@ -0,0 +1,12 @@
+package com.sundaegukbap.banchango.core.data.api.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ContainerIngredientDto(
+ val containerIngredientId: Long,
+ val containerDto: ContainerDto,
+ val ingredientDto: IngredientDto,
+ val createdAt: String,
+ val expirationDate: String
+)
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDtos.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDtos.kt
new file mode 100644
index 0000000..f2dbaa3
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/ContainerIngredientDtos.kt
@@ -0,0 +1,8 @@
+package com.sundaegukbap.banchango.core.data.api.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class ContainerIngredientDtos(
+ val containerIngredientDtos: List
+)
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientDto.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientDto.kt
new file mode 100644
index 0000000..c581203
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/api/model/IngredientDto.kt
@@ -0,0 +1,11 @@
+package com.sundaegukbap.banchango.core.data.api.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class IngredientDto(
+ val id: Long,
+ val name: String,
+ val kind: String,
+ val image: String?,
+)
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/ApiModule.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/ApiModule.kt
index 9c31690..ca0ed81 100644
--- a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/ApiModule.kt
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/di/ApiModule.kt
@@ -2,6 +2,7 @@ package com.sundaegukbap.banchango.core.data.di
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.sundaegukbap.banchango.core.data.BuildConfig
+import com.sundaegukbap.banchango.core.data.api.IngredientApi
import com.sundaegukbap.banchango.core.data.api.RecipeApi
import dagger.Module
import dagger.Provides
@@ -55,4 +56,10 @@ internal object ApiModule {
fun providesRecipeRecommendApi(
@DefaultRetrofitQualifier retrofit: Retrofit
): RecipeApi = retrofit.create(RecipeApi::class.java)
+
+ @Provides
+ @Singleton
+ fun providesIngredientApi(
+ @DefaultRetrofitQualifier retrofit: Retrofit
+ ): IngredientApi = retrofit.create(IngredientApi::class.java)
}
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 aa00fe5..fdeb08e 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,15 +1,25 @@
package com.sundaegukbap.banchango.core.data.di
+import com.sundaegukbap.banchango.core.data.repository.DefaultIngredientRepository
import com.sundaegukbap.banchango.core.data.repository.DefaultRecipeRepository
+import com.sundaegukbap.banchango.core.data.repository.FakeIngredientRepository
+import com.sundaegukbap.banchango.core.data.repository.FakeRecipeRepository
+import com.sundaegukbap.banchango.core.data.repository.api.IngredientRepository
import com.sundaegukbap.banchango.core.data.repository.api.RecipeRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
-internal abstract class RepositoryModule {
+internal interface RepositoryModule {
+ @Singleton
@Binds
- abstract fun bindsRecipeRepository(recipeRepository: DefaultRecipeRepository): RecipeRepository
+ fun bindsRecipeRepository(recipeRepository: FakeRecipeRepository): RecipeRepository
+
+ @Singleton
+ @Binds
+ fun bindsIngredientRepository(ingredientRepository: FakeIngredientRepository): IngredientRepository
}
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/IngredientMapper.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/IngredientMapper.kt
new file mode 100644
index 0000000..55209a4
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/mapper/IngredientMapper.kt
@@ -0,0 +1,37 @@
+package com.sundaegukbap.banchango.core.data.mapper
+
+import com.sundaegukbap.banchango.Container
+import com.sundaegukbap.banchango.Ingredient
+import com.sundaegukbap.banchango.ContainerIngredient
+import com.sundaegukbap.banchango.IngredientKind
+import com.sundaegukbap.banchango.core.data.api.model.ContainerDto
+import com.sundaegukbap.banchango.core.data.api.model.ContainerIngredientDto
+import com.sundaegukbap.banchango.core.data.api.model.IngredientDto
+import java.time.LocalDateTime
+
+internal fun ContainerIngredientDto.toData() = ContainerIngredient(
+ id = containerIngredientId,
+ container = containerDto.toData(),
+ ingredient = ingredientDto.toData(),
+ createdAt = LocalDateTime.parse(createdAt),
+ expirationDate = LocalDateTime.parse(expirationDate)
+)
+
+internal fun ContainerDto.toData() = Container(
+ id = containerId,
+ name = containerName
+)
+
+internal fun IngredientDto.toData() = Ingredient(
+ id = id,
+ name = name,
+ kind = when (kind) {
+ "육류" -> IngredientKind.MEAT
+ "해산물" -> IngredientKind.SEAFOOD
+ "채소" -> IngredientKind.VEGETABLE
+ "과일" -> IngredientKind.FRUIT
+ "기타" -> IngredientKind.ETC
+ else -> IngredientKind.ETC
+ },
+ image = image ?: ""
+)
\ No newline at end of file
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultIngredientRepository.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultIngredientRepository.kt
new file mode 100644
index 0000000..21dc54e
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/DefaultIngredientRepository.kt
@@ -0,0 +1,31 @@
+package com.sundaegukbap.banchango.core.data.repository
+
+import android.util.Log
+import com.sundaegukbap.banchango.Container
+import com.sundaegukbap.banchango.ContainerIngredient
+import com.sundaegukbap.banchango.Ingredient
+import com.sundaegukbap.banchango.IngredientKind
+import com.sundaegukbap.banchango.core.data.api.IngredientApi
+import com.sundaegukbap.banchango.core.data.mapper.toData
+import com.sundaegukbap.banchango.core.data.repository.api.IngredientRepository
+import java.time.LocalDateTime
+import javax.inject.Inject
+
+internal class DefaultIngredientRepository @Inject constructor(
+ private val ingredientApi: IngredientApi,
+) : IngredientRepository {
+ override suspend fun getIngredientContainers(): Result> {
+ return runCatching {
+ val response = ingredientApi.getIngredients(1)
+ Log.d("asdf", "response: $response")
+ if (response.isSuccessful) {
+ if (response.body() == null) {
+ throw IllegalStateException("Response body is null")
+ }
+ response.body()!!.containerIngredientDtos.map { it.toData() }
+ } else {
+ throw IllegalStateException("Response is not successful")
+ }
+ }
+ }
+}
diff --git a/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeIngredientRepository.kt b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeIngredientRepository.kt
new file mode 100644
index 0000000..4f0200f
--- /dev/null
+++ b/Android/core/data/src/main/java/com/sundaegukbap/banchango/core/data/repository/FakeIngredientRepository.kt
@@ -0,0 +1,54 @@
+package com.sundaegukbap.banchango.core.data.repository
+
+import com.sundaegukbap.banchango.Container
+import com.sundaegukbap.banchango.ContainerIngredient
+import com.sundaegukbap.banchango.Ingredient
+import com.sundaegukbap.banchango.IngredientKind
+import com.sundaegukbap.banchango.core.data.repository.api.IngredientRepository
+import java.time.LocalDateTime
+import javax.inject.Inject
+
+internal class FakeIngredientRepository @Inject constructor() : IngredientRepository {
+ override suspend fun getIngredientContainers(): Result> {
+ return Result.success(
+ listOf(
+ ContainerIngredient(
+ 1,
+ Container(1, "Container 1"),
+ Ingredient(1, "Ingredient 1", IngredientKind.SAUCE, "Ingredient 1 Image"),
+ LocalDateTime.now(),
+ LocalDateTime.now().plusDays(1)
+ ),
+ ContainerIngredient(
+ 2,
+ Container(2, "Container 2"),
+ Ingredient(2, "Ingredient 2", IngredientKind.VEGETABLE, "Ingredient 2 Image"),
+ LocalDateTime.now(),
+ LocalDateTime.now().plusDays(2)
+ ),
+ ContainerIngredient(
+ 3,
+ Container(2, "Container 2"),
+ Ingredient(3, "Ingredient 3", IngredientKind.MEAT, "Ingredient 3 Image"),
+ LocalDateTime.now(),
+ LocalDateTime.now().plusDays(3)
+ ),
+ ContainerIngredient(
+ 4,
+ Container(2, "Container 2"),
+ Ingredient(4, "Ingredient 4", IngredientKind.VEGETABLE, "Ingredient 4 Image"),
+ LocalDateTime.now(),
+ LocalDateTime.now().plusDays(4)
+ ),
+ ContainerIngredient(
+ 5,
+ Container(1, "Container 1"),
+ Ingredient(5, "Ingredient 5", IngredientKind.SAUCE, "Ingredient 5 Image"),
+ LocalDateTime.now(),
+ LocalDateTime.now().plusDays(5)
+ ),
+ )
+ )
+ }
+
+}
\ No newline at end of file
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 e051596..39fbb96 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,10 +11,12 @@ val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
val Orange = Color(0xFFFF7A00)
-val LightOrange = Color(0xFFFFC085)
+val LightOrange = Color(0xFFFFA857)
val White = Color(0xFFFFFFFF)
val Black = Color(0xFF000000)
val lightGray = Color(0xFFF5F1EE)
+val Gray = Color(0xFFF5F1EE)
+
// 투명도 50%
val SemiTransparentOrange = Color(0x80FF7A00)
diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/Container.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Container.kt
new file mode 100644
index 0000000..6674df4
--- /dev/null
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/Container.kt
@@ -0,0 +1,6 @@
+package com.sundaegukbap.banchango
+
+data class Container(
+ val id: Long,
+ val name: String
+)
diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/ContainerIngredient.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/ContainerIngredient.kt
new file mode 100644
index 0000000..93f88a5
--- /dev/null
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/ContainerIngredient.kt
@@ -0,0 +1,12 @@
+package com.sundaegukbap.banchango
+
+import java.time.LocalDateTime
+
+data class ContainerIngredient(
+ val id: Long,
+ val container: Container,
+ val ingredient: Ingredient,
+ val createdAt: LocalDateTime,
+ val expirationDate: LocalDateTime
+)
+
diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainer.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainer.kt
new file mode 100644
index 0000000..3ac9e5d
--- /dev/null
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainer.kt
@@ -0,0 +1,7 @@
+package com.sundaegukbap.banchango
+
+data class IngredientContainer(
+ val container: Container,
+ val kindIngredientContainers: List
+)
+
diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainers.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainers.kt
new file mode 100644
index 0000000..69627c5
--- /dev/null
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientContainers.kt
@@ -0,0 +1,28 @@
+package com.sundaegukbap.banchango
+
+class ContainerIngredients(
+ containerIngredients: List
+) {
+ private val _value: MutableList = containerIngredients.toMutableList()
+ val value: List get() = _value.toList()
+
+ fun getIngredientContainers(): List {
+ return _value.groupBy { it.container }
+ .map { (container, containerIngredients) ->
+ IngredientContainer(
+ container = container,
+ kindIngredientContainers = containerIngredients.toKindIngredientContainers()
+ )
+ }
+ }
+
+ private fun List.toKindIngredientContainers(): List {
+ return groupBy { it.ingredient.kind }
+ .map { (kind, ingredients) ->
+ KindIngredientContainer(
+ kind = kind,
+ ingredients = ingredients
+ )
+ }
+ }
+}
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
index e9907e6..bda73bb 100644
--- a/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientKind.kt
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/IngredientKind.kt
@@ -1,10 +1,10 @@
package com.sundaegukbap.banchango
-enum class IngredientKind {
- MEAT,
- VEGETABLE,
- FRUIT,
- SEAFOOD,
- SAUCE,
- ETC,
+enum class IngredientKind(val label: String) {
+ MEAT("육류"),
+ VEGETABLE("채소"),
+ FRUIT("과일"),
+ SEAFOOD("해산물"),
+ SAUCE("소스"),
+ ETC("기타"),
}
diff --git a/Android/core/model/src/main/java/com/sundaegukbap/banchango/KindIngredientContainer.kt b/Android/core/model/src/main/java/com/sundaegukbap/banchango/KindIngredientContainer.kt
new file mode 100644
index 0000000..b5007f2
--- /dev/null
+++ b/Android/core/model/src/main/java/com/sundaegukbap/banchango/KindIngredientContainer.kt
@@ -0,0 +1,6 @@
+package com.sundaegukbap.banchango
+
+data class KindIngredientContainer(
+ val kind: IngredientKind,
+ val ingredients: List
+)
\ No newline at end of file
diff --git a/Android/feature/home/build.gradle.kts b/Android/feature/home/build.gradle.kts
index 44bbac8..5316d0c 100644
--- a/Android/feature/home/build.gradle.kts
+++ b/Android/feature/home/build.gradle.kts
@@ -42,6 +42,7 @@ android {
dependencies {
implementation(project(":core:model"))
+ implementation(project(":core:data-api"))
implementation(project(":core:designsystem"))
implementation(project(":core:navigation"))
implementation(libs.androidx.core.ktx)
diff --git a/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeScreen.kt b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeScreen.kt
index 0e4b374..40fed40 100644
--- a/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeScreen.kt
+++ b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeScreen.kt
@@ -1,12 +1,330 @@
package com.sundaegukbap.banchango.feature.home
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+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.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.ElevatedCard
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Label
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Paint
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.drawscope.Stroke
+import androidx.compose.ui.res.colorResource
+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.compose.ui.unit.sp
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.sundaegukbap.banchango.Container
+import com.sundaegukbap.banchango.ContainerIngredient
+import com.sundaegukbap.banchango.Ingredient
+import com.sundaegukbap.banchango.IngredientContainer
+import com.sundaegukbap.banchango.IngredientKind
+import com.sundaegukbap.banchango.KindIngredientContainer
+import com.sundaegukbap.banchango.core.designsystem.theme.BanchangoTheme
+import com.sundaegukbap.banchango.core.designsystem.theme.Gray
+import com.sundaegukbap.banchango.core.designsystem.theme.LightOrange
+import com.sundaegukbap.banchango.core.designsystem.theme.Orange
+import com.sundaegukbap.banchango.core.designsystem.theme.White
+import com.sundaegukbap.banchango.core.designsystem.theme.lightGray
+import java.time.LocalDateTime
+import java.time.temporal.ChronoUnit
@Composable
-fun HomeScreen(
+fun HomeRoute(
padding: PaddingValues,
onChangeStatusBarColor: (color: Color, darkIcons: Boolean) -> Unit,
+ viewModel: HomeViewModel = hiltViewModel()
) {
+ val ingredientContainers by viewModel.ingredientContainers.collectAsStateWithLifecycle()
+
+ HomeScreen(
+ padding = padding,
+ ingredientContainers = ingredientContainers,
+ onChangeStatusBarColor = onChangeStatusBarColor
+ )
+}
+
+@Composable
+private fun HomeScreen(
+ padding: PaddingValues,
+ ingredientContainers: List,
+ onChangeStatusBarColor: (color: Color, darkIcons: Boolean) -> Unit
+) {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(padding)
+ .padding(16.dp)
+ ) {
+ items(ingredientContainers) { ingredientContainer ->
+ val isEven = ingredientContainers.indexOf(ingredientContainer) % 2 == 0
+ val containerColor = if (isEven) LightOrange else Gray
+ val itemColor = if (isEven) Gray else White
+ val buttonColor = if (isEven) White else Gray
+ val ingredientContainerNameColor = if (isEven) White else LightOrange
+
+ ElevatedCard(
+ colors = CardDefaults.elevatedCardColors().copy(containerColor = containerColor),
+ elevation = CardDefaults.elevatedCardElevation(2.dp),
+ modifier = Modifier
+ .fillMaxSize()
+ ) {
+ Row(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(vertical = 8.dp, horizontal = 8.dp)
+ ) {
+ Text(
+ modifier = Modifier.weight(0.4f),
+ fontWeight = FontWeight.Bold,
+ style = MaterialTheme.typography.titleMedium,
+ color = ingredientContainerNameColor,
+ text = ingredientContainer.container.name
+ )
+ Spacer(modifier = Modifier.weight(0.5f))
+ Icon(
+ modifier = Modifier.weight(0.1f),
+ tint = ingredientContainerNameColor,
+ painter = painterResource(id = R.drawable.ic_add),
+ contentDescription = null
+ )
+ }
+ val kindIngredients = ingredientContainer.kindIngredientContainers
+ val totalIngredients = kindIngredients.size
+
+
+ // Creating rows of two IngredientItems
+ for (index in 0 until totalIngredients step 2) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 16.dp),
+ horizontalArrangement = Arrangement.SpaceBetween // Distributes items evenly
+ ) {
+ // First IngredientItem
+ IngredientItem(
+ containerColor = itemColor,
+ kindIngredientContainer = kindIngredients[index],
+ buttonColor = buttonColor,
+ modifier = Modifier.weight(0.4f) // Fixed width for consistent size
+ )
+ Spacer(modifier = Modifier.width(20.dp))
+ // Check for the second item
+ if (index + 1 < totalIngredients) {
+ IngredientItem(
+ kindIngredientContainer = kindIngredients[index + 1],
+ modifier = Modifier.weight(0.4f), // Fixed width for consistent size
+ containerColor = itemColor,
+ buttonColor = buttonColor,
+ )
+ } else {
+ // If the second item does not exist, add a spacer for alignment
+ Spacer(modifier = Modifier.weight(0.4f)) // Takes remaining space
+ }
+ }
+ }
+ }
+ Spacer(modifier = Modifier.height(20.dp))
+ }
+ item { AddContainerButton(if (ingredientContainers.size % 2 == 0) LightOrange else Gray) }
+ }
+}
+
+@Composable
+private fun AddContainerButton(
+ containerColor: Color,
+) {
+ ElevatedCard(
+ colors = CardDefaults.elevatedCardColors(containerColor = containerColor),
+ modifier = Modifier
+ ) {
+ Column(
+ modifier = Modifier
+ .padding(8.dp)
+ .fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_add),
+ contentDescription = null
+ )
+ }
+ }
}
+
+@Composable
+private fun IngredientItem(
+ containerColor: Color,
+ buttonColor: Color,
+ kindIngredientContainer: KindIngredientContainer,
+ modifier: Modifier = Modifier
+) {
+ Card(
+ colors = CardDefaults.cardColors(containerColor = containerColor),
+ modifier = modifier
+ .height(106.dp)
+ ) {
+ Column(Modifier.padding(8.dp)) {
+ val ingredients = kindIngredientContainer.ingredients
+ Row {
+ Text(
+ text = kindIngredientContainer.kind.label,
+ style = MaterialTheme.typography.bodyLarge,
+ fontWeight = FontWeight.Bold,
+ )
+ Spacer(modifier = Modifier.weight(0.3f))
+ Text(
+ modifier = Modifier
+ .background(
+ color = buttonColor,
+ shape = RoundedCornerShape(20.dp)
+ )
+ .padding(horizontal = 16.dp, vertical = 4.dp),
+ text = ingredients.size.toString() + "개",
+ style = MaterialTheme.typography.bodySmall,
+ fontWeight = FontWeight.Bold,
+ color = Orange
+ )
+ }
+
+ // 2개까지만 표시하고, 2개 이상일 경우 ... 표시
+ ingredients.subList(0, minOf(ingredients.size, 2)).forEach { ingredient ->
+ val dDay = ChronoUnit.DAYS.between(
+ LocalDateTime.now(),
+ ingredient.expirationDate,
+ )
+ Row {
+ Text(
+ text = ingredient.ingredient.name,
+ style = MaterialTheme.typography.bodySmall,
+ fontSize = 12.sp
+ )
+ Spacer(modifier = Modifier.width(10.dp))
+ Text(text = "D - $dDay", style = MaterialTheme.typography.bodySmall)
+ }
+ }
+ if (ingredients.size > 2) {
+ Spacer(modifier = Modifier.height(4.dp))
+ Text(
+ text = "...",
+ style = MaterialTheme.typography.bodySmall,
+ fontSize = 12.sp
+ )
+ }
+ }
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewIngredientItem() {
+ BanchangoTheme {
+ IngredientItem(
+ containerColor = White,
+ buttonColor = Gray,
+ kindIngredientContainer = KindIngredientContainer(
+ IngredientKind.VEGETABLE,
+ listOf(
+ ContainerIngredient(
+ 1,
+ Container(1, "냉장 1"),
+ Ingredient(1, "상추", IngredientKind.VEGETABLE, ""),
+ LocalDateTime.now(),
+ LocalDateTime.now()
+ ),
+ ContainerIngredient(
+ 1,
+ Container(1, "냉장 1"),
+ Ingredient(1, "상추", IngredientKind.VEGETABLE, ""),
+ LocalDateTime.now(),
+ LocalDateTime.now()
+ )
+ )
+ )
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewHomeScreen() {
+ BanchangoTheme {
+ HomeScreen(
+ padding = PaddingValues(0.dp),
+ onChangeStatusBarColor = { _, _ -> },
+ ingredientContainers = listOf(
+ IngredientContainer(
+ Container(1, "냉장 1"),
+ listOf(
+ KindIngredientContainer(
+ IngredientKind.VEGETABLE, listOf(
+ ContainerIngredient(
+ 1,
+ Container(1, "냉장 1"),
+ Ingredient(1, "상추", IngredientKind.VEGETABLE, ""),
+ LocalDateTime.now(),
+ LocalDateTime.now()
+ ),
+ ContainerIngredient(
+ 1,
+ Container(1, "냉장 1"),
+ Ingredient(1, "상추", IngredientKind.VEGETABLE, ""),
+ LocalDateTime.now(),
+ LocalDateTime.now()
+ )
+ )
+ )
+ )
+ ),
+ IngredientContainer(
+ Container(1, "냉장 1"),
+ listOf(
+ KindIngredientContainer(
+ IngredientKind.VEGETABLE, listOf(
+ ContainerIngredient(
+ 1,
+ Container(1, "냉장 1"),
+ Ingredient(1, "상추", IngredientKind.VEGETABLE, ""),
+ LocalDateTime.now(),
+ LocalDateTime.now()
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ }
+}
+
diff --git a/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeViewModel.kt b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeViewModel.kt
new file mode 100644
index 0000000..823696f
--- /dev/null
+++ b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/HomeViewModel.kt
@@ -0,0 +1,45 @@
+package com.sundaegukbap.banchango.feature.home
+
+import android.util.Log
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.sundaegukbap.banchango.ContainerIngredients
+import com.sundaegukbap.banchango.IngredientContainer
+import com.sundaegukbap.banchango.core.data.repository.api.IngredientRepository
+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
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class HomeViewModel @Inject constructor(
+ private val ingredientRepository: IngredientRepository
+) : ViewModel() {
+
+ private var containerIngredients: ContainerIngredients = ContainerIngredients(emptyList())
+
+ private val _ingredientContainers: MutableStateFlow> =
+ MutableStateFlow(emptyList())
+ val ingredientContainers: StateFlow> =
+ _ingredientContainers.asStateFlow()
+
+ init {
+ viewModelScope.launch {
+ ingredientRepository.getIngredientContainers()
+ .onSuccess {
+ containerIngredients = ContainerIngredients(it)
+ _ingredientContainers.value = containerIngredients.getIngredientContainers()
+ Log.d(
+ "asdf",
+ "containerIngredients: ${containerIngredients.getIngredientContainers()}"
+ )
+ }.onFailure {
+ Log.e("asdf", "Failed to get ingredient containers", it)
+ }
+ }
+ }
+}
+
diff --git a/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/navigation/HomeNavigator.kt b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/navigation/HomeNavigator.kt
index 9b3f838..5d3f52b 100644
--- a/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/navigation/HomeNavigator.kt
+++ b/Android/feature/home/src/main/java/com/sundaegukbap/banchango/feature/home/navigation/HomeNavigator.kt
@@ -6,8 +6,9 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
-import com.sundaegukbap.banchango.feature.home.HomeScreen
+import com.sundaegukbap.banchango.feature.home.HomeRoute
import com.sundaegukbap.banchango.navigation.MainTabRoute
+import com.sundaegukbap.banchango.navigation.Route
fun NavController.navigateHome(navOptions: NavOptions) {
navigate(MainTabRoute.Home, navOptions)
@@ -18,6 +19,6 @@ fun NavGraphBuilder.homeNavGraph(
onChangeStatusBarColor: (color: Color, darkIcons: Boolean) -> Unit,
) {
composable {
- HomeScreen(padding, onChangeStatusBarColor)
+ HomeRoute(padding, onChangeStatusBarColor)
}
}
diff --git a/Android/feature/home/src/main/res/drawable/ic_add.xml b/Android/feature/home/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000..9f83b8f
--- /dev/null
+++ b/Android/feature/home/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/Android/feature/recipe/build.gradle.kts b/Android/feature/recipe/build.gradle.kts
index e90a9eb..5ea806a 100644
--- a/Android/feature/recipe/build.gradle.kts
+++ b/Android/feature/recipe/build.gradle.kts
@@ -45,7 +45,6 @@ dependencies {
implementation(project(":core:designsystem"))
implementation(project(":core:navigation"))
implementation(project(":core:data-api"))
- implementation(project(":core:data"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)