package com.craigvg.lichun_android.ui.screens.home.components import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing import com.craigvg.lichun_android.ui.theme.AppTypography import com.craigvg.lichun_android.viewmodel.GameStateViewModel import com.craigvg.lichun_android.viewmodel.PlayerViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle /** * Profile navigation menu with card grid for all player features. * Ported from iOS ProfileMenuView.swift */ @Composable fun ProfileMenuView( gameStateViewModel: GameStateViewModel = hiltViewModel(), playerViewModel: PlayerViewModel = hiltViewModel(), onDismiss: () -> Unit = {}, onCharacters: () -> Unit = {}, onStore: () -> Unit = {}, onDailyRewards: () -> Unit = {}, onDailyQuests: () -> Unit = {}, onAchievements: () -> Unit = {}, onTimeSkip: () -> Unit = {}, onSettings: () -> Unit = {} ) { val person by playerViewModel.person.collectAsStateWithLifecycle() val dailyRewardState by gameStateViewModel.dailyRewardState.collectAsStateWithLifecycle() val dailyQuestsState by gameStateViewModel.dailyQuestsState.collectAsStateWithLifecycle() val hasDailyRewardAvailable = dailyRewardState?.let { it.canClaim && !it.todaysClaimed } ?: false val dailyQuestsClaimableCount = dailyQuestsState?.quests?.count { it.canClaim } ?: 0 Box( modifier = Modifier .fillMaxWidth() .background(AppColors.background) ) { Column( modifier = Modifier .fillMaxWidth() .padding(AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(AppSpacing.xl)) // Header Text(person.firstname, style = AppTypography.displayTitle, color = AppColors.primaryText) Text("Level ${person.ageYears}", style = AppTypography.body, color = AppColors.secondaryText) Spacer(modifier = Modifier.height(AppSpacing.lg)) // Menu cards grid val cards = listOf( MenuCardData(Icons.Default.People, "Characters", AppColors.friend, false, null, onCharacters), MenuCardData(Icons.Default.ShoppingBag, "Store", AppColors.accent, false, null, onStore), MenuCardData(Icons.Default.CalendarMonth, "Daily Rewards", AppColors.happiness, hasDailyRewardAvailable, dailyRewardState?.let { if (it.currentStreak > 0) "${it.currentStreak} day streak" else null }, onDailyRewards), MenuCardData(Icons.Default.Checklist, "Daily Quests", AppColors.intelligence, dailyQuestsClaimableCount > 0, if (dailyQuestsClaimableCount > 0) "$dailyQuestsClaimableCount ready" else null, onDailyQuests), MenuCardData(Icons.Default.EmojiEvents, "Achievements", AppColors.prestige, false, null, onAchievements), MenuCardData(Icons.Default.FastForward, "Time Skip", AppColors.primary, false, null, onTimeSkip), ) LazyVerticalGrid( columns = GridCells.Fixed(2), horizontalArrangement = Arrangement.spacedBy(AppSpacing.sm), verticalArrangement = Arrangement.spacedBy(AppSpacing.sm), modifier = Modifier.height(((cards.size + 1) / 2 * 130).dp) ) { items(cards.size) { index -> val card = cards[index] ProfileMenuCard( icon = card.icon, title = card.title, color = card.color, hasBadge = card.hasBadge, subtitle = card.subtitle, onClick = card.onClick ) } } Spacer(modifier = Modifier.height(AppSpacing.xl)) } // Close button IconButton( onClick = onDismiss, modifier = Modifier .align(Alignment.TopEnd) .padding(AppSpacing.md) ) { Box( modifier = Modifier .size(36.dp) .background(AppColors.surfaceElevated, CircleShape), contentAlignment = Alignment.Center ) { Icon(Icons.Default.Close, "Close", tint = AppColors.secondaryText, modifier = Modifier.size(14.dp)) } } } } private data class MenuCardData( val icon: ImageVector, val title: String, val color: Color, val hasBadge: Boolean, val subtitle: String?, val onClick: () -> Unit ) @Composable private fun ProfileMenuCard( icon: ImageVector, title: String, color: Color, hasBadge: Boolean, subtitle: String?, onClick: () -> Unit ) { Card( onClick = onClick, modifier = Modifier .fillMaxWidth() .height(120.dp), shape = RoundedCornerShape(AppSpacing.cornerRadius), colors = CardDefaults.cardColors(containerColor = AppColors.surfaceElevated), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Column( modifier = Modifier .fillMaxSize() .padding(AppSpacing.md), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Box(contentAlignment = Alignment.Center) { Box( modifier = Modifier .size(56.dp) .background(color.copy(alpha = 0.15f), CircleShape), contentAlignment = Alignment.Center ) { Icon(icon, contentDescription = null, tint = color, modifier = Modifier.size(26.dp)) } if (hasBadge) { Box( modifier = Modifier .size(10.dp) .background(AppColors.error, CircleShape) .align(Alignment.TopEnd) ) } } Spacer(modifier = Modifier.height(AppSpacing.xs)) Text(title, style = AppTypography.bodyBold, color = AppColors.primaryText, textAlign = TextAlign.Center) subtitle?.let { Text(it, style = AppTypography.caption, color = AppColors.secondaryText, maxLines = 1) } } } }