refactor(home): extract category preview -> components/HomeCategoryPreview.kt

Step 3/9. Verbatim move (grid public, mini-card private). compileDebugKotlin green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
null 2026-07-11 19:29:06 -05:00
parent 18ad31506e
commit 07c810c9a1
2 changed files with 116 additions and 87 deletions

View File

@ -87,6 +87,7 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import app.closer.R import app.closer.R
import app.closer.ui.home.components.CategoryPreviewGrid
import app.closer.ui.home.components.EmptyHomeContent import app.closer.ui.home.components.EmptyHomeContent
import app.closer.ui.home.components.ErrorHomeCard import app.closer.ui.home.components.ErrorHomeCard
import app.closer.ui.home.components.HomeActionColors import app.closer.ui.home.components.HomeActionColors
@ -1313,93 +1314,6 @@ private fun MomentCueCard() {
} }
} }
@Composable
private fun CategoryPreviewGrid(
categories: List<HomeCategorySummary>,
onCategory: (String) -> Unit,
onPacks: () -> Unit
) {
val featuredCategories = categories.take(2)
if (featuredCategories.isEmpty()) return
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "More doorways",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold
)
CloserActionButton(
label = "All packs",
onClick = onPacks,
style = CloserButtonStyle.Secondary
)
}
featuredCategories.chunked(2).forEach { rowItems ->
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
rowItems.forEach { item ->
CategoryMiniCard(
item = item,
modifier = Modifier.weight(1f),
onClick = { onCategory(item.category.id) }
)
}
if (rowItems.size == 1) {
Box(modifier = Modifier.weight(1f))
}
}
}
}
}
@Composable
private fun CategoryMiniCard(
item: HomeCategorySummary,
modifier: Modifier,
onClick: () -> Unit
) {
CloserClickableCard(
onClick = onClick,
modifier = modifier,
containerColor = closerCardColor(alpha = 0.82f),
shape = RoundedCornerShape(CloserRadii.Card),
elevation = CloserElevations.Card
) {
Column(
modifier = Modifier.padding(15.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
CategoryGlyph(
categoryId = item.category.id,
iconName = item.category.iconName,
size = 42.dp,
iconSize = 20.dp
)
Text(
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${item.questionCount} questions",
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
@Composable @Composable
private fun WaitingForYouSection( private fun WaitingForYouSection(
actions: List<PendingActionCard>, actions: List<PendingActionCard>,

View File

@ -0,0 +1,115 @@
package app.closer.ui.home.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import app.closer.ui.components.CategoryGlyph
import app.closer.ui.components.CloserActionButton
import app.closer.ui.components.CloserButtonStyle
import app.closer.ui.components.CloserClickableCard
import app.closer.ui.components.CloserElevations
import app.closer.ui.components.CloserRadii
import app.closer.ui.home.HomeCategorySummary
import app.closer.ui.questions.displayCategoryName
import app.closer.ui.theme.closerCardColor
/** Home's "More doorways" category preview grid. Extracted from HomeScreen.kt. */
@Composable
fun CategoryPreviewGrid(
categories: List<HomeCategorySummary>,
onCategory: (String) -> Unit,
onPacks: () -> Unit
) {
val featuredCategories = categories.take(2)
if (featuredCategories.isEmpty()) return
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "More doorways",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold
)
CloserActionButton(
label = "All packs",
onClick = onPacks,
style = CloserButtonStyle.Secondary
)
}
featuredCategories.chunked(2).forEach { rowItems ->
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
rowItems.forEach { item ->
CategoryMiniCard(
item = item,
modifier = Modifier.weight(1f),
onClick = { onCategory(item.category.id) }
)
}
if (rowItems.size == 1) {
Box(modifier = Modifier.weight(1f))
}
}
}
}
}
@Composable
private fun CategoryMiniCard(
item: HomeCategorySummary,
modifier: Modifier,
onClick: () -> Unit
) {
CloserClickableCard(
onClick = onClick,
modifier = modifier,
containerColor = closerCardColor(alpha = 0.82f),
shape = RoundedCornerShape(CloserRadii.Card),
elevation = CloserElevations.Card
) {
Column(
modifier = Modifier.padding(15.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
CategoryGlyph(
categoryId = item.category.id,
iconName = item.category.iconName,
size = 42.dp,
iconSize = 20.dp
)
Text(
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Text(
text = "${item.questionCount} questions",
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}