개발 일지/Nutri Capture

Nutri Capture 프론트엔드 - NutrientBottomSheet 부분 구현

interfacer_han 2025. 3. 26. 21:51

#1 개요

 

Nutri Capture 프론트엔드 - '피자' 아이콘 임시 적용

#1 커스텀 아이콘 임시 적용#1-1 커스텀 아이콘 Nutri Capture 프론트엔드 - '피자' 아이콘 구현#1 개요#1-1 지금까지의 여정 Nutri Capture 프론트엔드 - 커스텀 BottomSheetScaffold 개발 유예#1 개요#1-1 개발 이

kenel.tistory.com

위 게시글에서 못다한 부분을 구현했다. 

 

#2 코드 스니펫

#2-1 NutritionBottomSheet.kt

...

@Composable
fun NutrientBottomSheet(
    viewModel: NutrientViewModel = hiltViewModel()
) {
    val inputtedDayMeal = viewModel.nutrientScreenState.collectAsState().value.inputtedDayMeal
    val nutritionInfo = inputtedDayMeal.nutritionInfo
    val maxLevel = 5

    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 100.dp),
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        items(
            nutritionInfo.toMutableMap().toList()
        ) { nutritionDetailMap ->
            val nutritionKey = nutritionDetailMap.first
            val nutritionDetail = nutritionDetailMap.second

            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .border(width = 1.dp, color = Color.Black),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                ResponsiveArcSurroundedIconButton(
                    imageVector = ImageVector.vectorResource(id = nutritionDetail.iconId),
                    contentDescription = nutritionDetail.name,
                    currentLevel = nutritionDetail.value,
                    maxLevel = maxLevel,
                    arcColor = Color.Yellow,
                    arcWidth = 15
                ) {
                    viewModel.onEvent(
                        NutrientViewModelEvent.UpdateInputtedDayMeal(
                            inputtedDayMeal.copy(
                                nutritionInfo = nutritionInfo.updateNutritionDetail(nutritionKey) {
                                    if (nutritionDetail.value < maxLevel) {
                                        nutritionDetail.value + 1
                                    } else {
                                        0
                                    }
                                }
                            )
                        )
                    )
                }

                Spacer(modifier = Modifier.height(4.dp))

                Text(
                    text = nutritionDetail.name,
                    style = MaterialTheme.typography.labelLarge
                )
            }
        }
    }
}

여기에서 리팩토링한 NutritionInfo의 getter 및 setter를 활용했다.

 

#2-2 작동 확인 - 스크린샷

 

#2-3 작동 확인 - App Inspection

DB에 잘 저장된 모습이다.

 

#3 다음 방향

더 예쁘게 만들고 싶지만, 그건 최종적으로 다듬을 때 하면 된다. 다음 작업은, BottomSheet를 동적으로 내리거나 올리게 만들 것이다. 간단한 유스케이스는 아래와 같다.

 

  1. 사용자는 원래 쓰던 소프트 키보드로 식단의 이름을 적음
  2. '다음' 버튼 클릭 시 소프트 키보드는 내려가고 #2-2에 있는 'NutritionBottomSheet'가 올라옴
  3. 'NutritionBottomSheet'를 통해 영양 정보를 입력
  4. '제출' 버튼 클릭 시 DB에 식단이 저장됨

'다음' 버튼이나 '제출' 버튼은 따로 구분된 2개의 버튼이 아닌 하나의 버튼이다. 버튼은 그대로 두고 유스케이스 단계 별로 아이콘만 바뀌게 만들 것이다.

 

#4 완성된 앱

#4-1 이 게시글 시점의 Commit

 

GitHub - Kanmanemone/nutri-capture-new

Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.

github.com

 

#4-2 본 프로젝트의 가장 최신 Commit

 

GitHub - Kanmanemone/nutri-capture-new

Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.

github.com