Coverage Summary for Class: CategoryChooserBottomSheetKt (com.georgeci.moneysurfer.feature.category.picker)

Class Class, % Method, % Branch, % Line, % Instruction, %
CategoryChooserBottomSheetKt 0% (0/1) 0% (0/3) 0% (0/56) 0% (0/16) 0% (0/508)


 package com.georgeci.moneysurfer.feature.category.picker
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.georgeci.moneysurfer.domain.primitives.CategoryId
 import com.georgeci.moneysurfer.domain.primitives.CategoryType
 import com.georgeci.moneysurfer.utils.HandleSideEffect
 import org.koin.compose.viewmodel.koinViewModel
 import org.koin.core.parameter.parametersOf
 
 /**
  * Bottom-sheet entry composable for picking a category. Hosted as a navigation entry; the
  * surrounding [androidx.compose.material3.ModalBottomSheet] is provided by
  * [com.georgeci.moneysurfer.navigation.BottomSheetSceneStrategy]. Visual layout lives
  * in [CategoryChooserContent] — this composable just maps the ViewModel's state and effects.
  *
  * [variant] chooses between the two designed layouts, so a caller that knows its user is hunting
  * for one name gets the flat grid, and one browsing a deep tree gets the expandable cards.
  */
 @Composable
 fun CategoryChooserBottomSheet(
     selectedCategoryId: CategoryId?,
     filterType: CategoryType?,
     onDismiss: () -> Unit,
     onNavigateToCategoryCreation: () -> Unit,
     onCategoryPicked: (CategoryId) -> Unit,
     variant: CategoryPickerVariant = CategoryPickerVariant.GRID,
     viewModel: CategoryChooserViewModel = koinViewModel(
         key = "${selectedCategoryId?.value}:${filterType?.name}:${variant.name}",
     ) { parametersOf(selectedCategoryId, filterType, variant) },
 ) {
     val state by viewModel.collectAsStateWithLifecycle()
 
     viewModel.HandleSideEffect { effect ->
         when (effect) {
             CategoryChooserEffect.Dismiss -> onDismiss()
             CategoryChooserEffect.NavigateToCategoryCreation -> onNavigateToCategoryCreation()
             is CategoryChooserEffect.PublishResult -> onCategoryPicked(effect.id)
         }
     }
 
     // Loading is a single frame before the local read lands; drawing the chrome around an empty
     // body would only flash the tab row into place.
     (state as? CategoryChooserState.Content)?.let { content ->
         CategoryChooserContent(state = content, onEvent = viewModel::onEvent)
     }
 }