diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/components/task/TaskCard.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/components/task/TaskCard.kt index 91fd476..fe15320 100644 --- a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/components/task/TaskCard.kt +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/components/task/TaskCard.kt @@ -1,6 +1,8 @@ package com.mycrib.android.ui.components.task +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* @@ -8,8 +10,11 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.mycrib.android.ui.theme.AppColors import com.mycrib.shared.models.TaskDetail import com.mycrib.shared.models.TaskCategory import com.mycrib.shared.models.TaskPriority @@ -32,10 +37,10 @@ fun TaskCard( ) { Card( modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), + shape = MaterialTheme.shapes.large, + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerLowest + containerColor = MaterialTheme.colorScheme.surface ) ) { Column( @@ -51,54 +56,75 @@ fun TaskCard( Column(modifier = Modifier.weight(1f)) { Text( text = task.title, - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface ) - Spacer(modifier = Modifier.height(4.dp)) + Spacer(modifier = Modifier.height(8.dp)) + // Pill-style category badge Surface( - color = MaterialTheme.colorScheme.secondaryContainer, - shape = RoundedCornerShape(8.dp) + color = MaterialTheme.colorScheme.surfaceVariant, + shape = RoundedCornerShape(12.dp) ) { Text( - text = task.category.name, - modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSecondaryContainer + text = task.category.name.uppercase(), + modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } } Column( horizontalAlignment = Alignment.End, - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Surface( - color = when (task.priority.name.lowercase()) { - "urgent" -> MaterialTheme.colorScheme.error - "high" -> MaterialTheme.colorScheme.errorContainer - "medium" -> MaterialTheme.colorScheme.primaryContainer - else -> MaterialTheme.colorScheme.surfaceVariant - }, - shape = RoundedCornerShape(10.dp) + // Priority badge with semantic colors + val priorityColor = when (task.priority.name.lowercase()) { + "urgent", "high" -> Color(0xFFEF4444) // Error/Red + "medium" -> Color(0xFFF59E0B) // Warning/Orange + else -> Color(0xFF10B981) // Success/Green + } + Row( + modifier = Modifier + .background( + priorityColor.copy(alpha = 0.15f), + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 12.dp, vertical = 6.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically ) { + Box( + modifier = Modifier + .size(6.dp) + .clip(CircleShape) + .background(priorityColor) + ) Text( text = task.priority.name.uppercase(), - modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.labelSmall, + color = priorityColor ) } + // Status badge with semantic colors if (task.status != null) { + val statusColor = when (task.status.name.lowercase()) { + "completed" -> AppColors.taskCompleted + "in_progress" -> AppColors.taskInProgress + "pending" -> Color(0xFFF59E0B) + "cancelled" -> AppColors.taskCanceled + else -> Color(0xFF9CA3AF) + } Surface( - color = MaterialTheme.colorScheme.tertiaryContainer, - shape = RoundedCornerShape(10.dp) + color = statusColor.copy(alpha = 0.15f), + shape = RoundedCornerShape(12.dp) ) { Text( - text = task.status.name.uppercase(), - modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onTertiaryContainer + text = task.status.name.replace("_", " ").uppercase(), + modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), + style = MaterialTheme.typography.labelSmall, + color = statusColor ) } } @@ -114,42 +140,61 @@ fun TaskCard( ) } - Spacer(modifier = Modifier.height(12.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(16.dp)) + HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) + Spacer(modifier = Modifier.height(16.dp)) + // Metadata pills Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically) { + // Date pill + Row( + modifier = Modifier + .background( + MaterialTheme.colorScheme.surfaceVariant, + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 12.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { Icon( Icons.Default.CalendarToday, contentDescription = null, - modifier = Modifier.size(16.dp), - tint = MaterialTheme.colorScheme.primary + modifier = Modifier.size(14.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant ) - Spacer(modifier = Modifier.width(4.dp)) Text( text = task.nextScheduledDate ?: task.dueDate ?: "N/A", - style = MaterialTheme.typography.bodySmall, - fontWeight = FontWeight.SemiBold + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } + + // Cost pill task.estimatedCost?.let { - Row(verticalAlignment = Alignment.CenterVertically) { + Row( + modifier = Modifier + .background( + MaterialTheme.colorScheme.surfaceVariant, + RoundedCornerShape(12.dp) + ) + .padding(horizontal = 12.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { Icon( Icons.Default.AttachMoney, contentDescription = null, - modifier = Modifier.size(16.dp), - tint = MaterialTheme.colorScheme.tertiary + modifier = Modifier.size(14.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant ) - Spacer(modifier = Modifier.width(4.dp)) Text( text = "$$it", - style = MaterialTheme.typography.bodySmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.tertiary + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } } @@ -282,7 +327,8 @@ fun CompletionCard(completion: TaskCompletion) { colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.surfaceVariant ), - shape = RoundedCornerShape(12.dp) + shape = MaterialTheme.shapes.medium, + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) ) { Column( modifier = Modifier diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/HomeScreen.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/HomeScreen.kt index 4d9f66b..00bdfdf 100644 --- a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/HomeScreen.kt @@ -1,15 +1,22 @@ package com.mycrib.android.ui.screens +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape 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.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +import com.mycrib.android.ui.theme.AppColors +import com.mycrib.android.ui.theme.AppRadius import com.mycrib.android.viewmodel.ResidenceViewModel import com.mycrib.shared.network.ApiResult @@ -30,10 +37,17 @@ fun HomeScreen( Scaffold( topBar = { TopAppBar( - title = { Text("myCrib") }, + title = { Text("myCrib", style = MaterialTheme.typography.headlineSmall) }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ), actions = { IconButton(onClick = onLogout) { - Icon(Icons.Default.ExitToApp, contentDescription = "Logout") + Icon( + Icons.Default.ExitToApp, + contentDescription = "Logout", + tint = MaterialTheme.colorScheme.primary + ) } } ) @@ -42,71 +56,116 @@ fun HomeScreen( Column( modifier = Modifier .fillMaxSize() + .background(MaterialTheme.colorScheme.background) .padding(paddingValues) - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) ) { + // Personalized Greeting + Column( + modifier = Modifier.padding(vertical = 8.dp) + ) { + Text( + text = "Welcome back", + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Text( + text = "Manage your properties", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } // Summary Card when (summaryState) { is ApiResult.Success -> { val summary = (summaryState as ApiResult.Success).data Card( modifier = Modifier.fillMaxWidth(), + shape = MaterialTheme.shapes.large, colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer - ) + containerColor = MaterialTheme.colorScheme.surface + ), + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) ) { Column( modifier = Modifier .fillMaxWidth() - .padding(16.dp) + .padding(20.dp) ) { - Text( - text = "Overview", - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - Spacer(modifier = Modifier.height(8.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + // Gradient circular icon + Box( + modifier = Modifier + .size(44.dp) + .clip(CircleShape) + .background( + Brush.linearGradient( + listOf( + Color(0xFF2563EB), + Color(0xFF8B5CF6) + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.Default.Home, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(24.dp) + ) + } + Column { + Text( + text = "Overview", + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface + ) + Text( + text = "Your property stats", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + + Spacer(modifier = Modifier.height(20.dp)) + Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = "${summary.residences.size}", - style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - Text( - text = "Properties", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - } - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = "${summary.summary.totalTasks}", - style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - Text( - text = "Total Tasks", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - } - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text( - text = "${summary.summary.totalPending}", - style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - Text( - text = "Pending", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onPrimaryContainer - ) - } + StatItem( + value = "${summary.residences.size}", + label = "Properties", + color = Color(0xFF3B82F6) + ) + Divider( + modifier = Modifier + .height(48.dp) + .width(1.dp), + color = MaterialTheme.colorScheme.outlineVariant + ) + StatItem( + value = "${summary.summary.totalTasks}", + label = "Total Tasks", + color = Color(0xFF8B5CF6) + ) + Divider( + modifier = Modifier + .height(48.dp) + .width(1.dp), + color = MaterialTheme.colorScheme.outlineVariant + ) + StatItem( + value = "${summary.summary.totalPending}", + label = "Pending", + color = Color(0xFFF59E0B) + ) } } } @@ -131,66 +190,126 @@ fun HomeScreen( } // Residences Card - Card( - modifier = Modifier - .fillMaxWidth() - .clickable { onNavigateToResidences() } - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(24.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.Home, - contentDescription = null, - modifier = Modifier.size(48.dp) - ) - Spacer(modifier = Modifier.width(16.dp)) - Column { - Text( - text = "Residences", - style = MaterialTheme.typography.titleLarge - ) - Text( - text = "Manage your properties", - style = MaterialTheme.typography.bodyMedium - ) - } - } - } + NavigationCard( + title = "Properties", + subtitle = "Manage your residences", + icon = Icons.Default.Home, + iconColor = Color(0xFF3B82F6), + onClick = onNavigateToResidences + ) // Tasks Card - Card( - modifier = Modifier - .fillMaxWidth() - .clickable { onNavigateToTasks() } - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(24.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.CheckCircle, - contentDescription = null, - modifier = Modifier.size(48.dp) - ) - Spacer(modifier = Modifier.width(16.dp)) - Column { - Text( - text = "Tasks", - style = MaterialTheme.typography.titleLarge - ) - Text( - text = "View and manage tasks", - style = MaterialTheme.typography.bodyMedium - ) - } - } - } + NavigationCard( + title = "Tasks", + subtitle = "View and manage tasks", + icon = Icons.Default.CheckCircle, + iconColor = Color(0xFF10B981), + onClick = onNavigateToTasks + ) + } + } +} + +@Composable +private fun StatItem( + value: String, + label: String, + color: Color +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Box( + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .background(color.copy(alpha = 0.1f)), + contentAlignment = Alignment.Center + ) { + Text( + text = value, + style = MaterialTheme.typography.titleLarge, + color = color + ) + } + Text( + text = label, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } +} + +@Composable +private fun NavigationCard( + title: String, + subtitle: String, + icon: androidx.compose.ui.graphics.vector.ImageVector, + iconColor: Color, + onClick: () -> Unit +) { + Card( + modifier = Modifier + .fillMaxWidth() + .clickable { onClick() }, + shape = MaterialTheme.shapes.large, + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + // Gradient circular icon + Box( + modifier = Modifier + .size(56.dp) + .clip(CircleShape) + .background( + Brush.linearGradient( + listOf( + iconColor, + iconColor.copy(alpha = 0.7f) + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Icon( + icon, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(28.dp) + ) + } + + Column( + modifier = Modifier.weight(1f) + ) { + Text( + text = title, + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = subtitle, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + Icon( + Icons.Default.KeyboardArrowRight, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) } } } diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/LoginScreen.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/LoginScreen.kt index b64545a..0af22fc 100644 --- a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/LoginScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/LoginScreen.kt @@ -2,6 +2,7 @@ package com.mycrib.android.ui.screens import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* @@ -11,6 +12,8 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType @@ -63,11 +66,11 @@ fun LoginScreen( modifier = Modifier .fillMaxWidth(0.9f) .wrapContentHeight(), - shape = RoundedCornerShape(24.dp), + shape = MaterialTheme.shapes.extraLarge, colors = CardDefaults.cardColors( containerColor = MaterialTheme.colorScheme.surface ), - elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) + elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) { Column( modifier = Modifier @@ -123,28 +126,54 @@ fun LoginScreen( ErrorCard(message = errorMessage) - Button( - onClick = { - viewModel.login(username, password) - }, + // Gradient button + Box( modifier = Modifier .fillMaxWidth() - .height(56.dp), - enabled = username.isNotEmpty() && password.isNotEmpty(), - shape = RoundedCornerShape(12.dp) + .height(56.dp) + .clip(MaterialTheme.shapes.medium) + .then( + if (username.isNotEmpty() && password.isNotEmpty() && !isLoading) { + Modifier.background( + Brush.linearGradient( + listOf( + Color(0xFF2563EB), + Color(0xFF8B5CF6) + ) + ) + ) + } else { + Modifier.background(MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.3f)) + } + ), + contentAlignment = Alignment.Center ) { - if (isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(24.dp), - color = MaterialTheme.colorScheme.onPrimary, - strokeWidth = 2.dp - ) - } else { - Text( - "Sign In", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold + Button( + onClick = { + viewModel.login(username, password) + }, + modifier = Modifier.fillMaxSize(), + enabled = username.isNotEmpty() && password.isNotEmpty(), + shape = MaterialTheme.shapes.medium, + colors = ButtonDefaults.buttonColors( + containerColor = Color.Transparent, + disabledContainerColor = Color.Transparent ) + ) { + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + color = Color.White, + strokeWidth = 2.dp + ) + } else { + Text( + "Sign In", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + color = Color.White + ) + } } } diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/ResidencesScreen.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/ResidencesScreen.kt index c1113ef..e21a0a8 100644 --- a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/ResidencesScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/screens/ResidencesScreen.kt @@ -1,9 +1,11 @@ package com.mycrib.android.ui.screens +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* @@ -11,6 +13,9 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel @@ -315,8 +320,11 @@ fun ResidencesScreen( modifier = Modifier .fillMaxWidth() .clickable { onResidenceClick(residence.id) }, - shape = RoundedCornerShape(16.dp), - elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) + shape = MaterialTheme.shapes.large, + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ) ) { Column( modifier = Modifier @@ -325,32 +333,67 @@ fun ResidencesScreen( ) { Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, + horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically ) { + // Gradient circular house icon + Box( + modifier = Modifier + .size(56.dp) + .clip(CircleShape) + .background( + Brush.linearGradient( + listOf( + Color(0xFF2563EB), + Color(0xFF8B5CF6) + ) + ) + ), + contentAlignment = Alignment.Center + ) { + Icon( + Icons.Default.Home, + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(28.dp) + ) + } + Column(modifier = Modifier.weight(1f)) { Text( text = residence.name, - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface ) Spacer(modifier = Modifier.height(4.dp)) - Text( - text = "${residence.streetAddress}", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Text( - text = "${residence.city}, ${residence.stateProvince}", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Icon( + Icons.Default.LocationOn, + contentDescription = null, + modifier = Modifier.size(14.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + Text( + text = "${residence.city}, ${residence.stateProvince}", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } } + + Icon( + Icons.Default.KeyboardArrowRight, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) } Spacer(modifier = Modifier.height(16.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(12.dp)) + HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) + Spacer(modifier = Modifier.height(16.dp)) Row( modifier = Modifier.fillMaxWidth(), @@ -360,19 +403,19 @@ fun ResidencesScreen( icon = Icons.Default.Assignment, value = "${residence.taskSummary.total}", label = "Tasks", - color = MaterialTheme.colorScheme.primary + color = Color(0xFF3B82F6) ) TaskStatChip( icon = Icons.Default.CheckCircle, value = "${residence.taskSummary.completed}", label = "Done", - color = MaterialTheme.colorScheme.tertiary + color = Color(0xFF10B981) ) TaskStatChip( icon = Icons.Default.Schedule, value = "${residence.taskSummary.pending}", label = "Pending", - color = MaterialTheme.colorScheme.error + color = Color(0xFFF59E0B) ) } } diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Shape.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Shape.kt new file mode 100644 index 0000000..c8386ab --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Shape.kt @@ -0,0 +1,28 @@ +package com.mycrib.android.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.ui.unit.dp + +// Modern Shape System - Matching iOS Design System +object AppRadius { + val xs = 4.dp + val sm = 8.dp + val md = 12.dp + val lg = 16.dp + val xl = 20.dp + val xxl = 24.dp +} + +val AppShapes = Shapes( + // Small components (buttons, chips, badges) + extraSmall = RoundedCornerShape(AppRadius.xs), + small = RoundedCornerShape(AppRadius.sm), + + // Medium components (cards, inputs) + medium = RoundedCornerShape(AppRadius.md), + + // Large components (dialogs, sheets) + large = RoundedCornerShape(AppRadius.lg), + extraLarge = RoundedCornerShape(AppRadius.xl) +) diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Theme.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Theme.kt index ed8042b..dd23c44 100644 --- a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Theme.kt +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Theme.kt @@ -5,51 +5,73 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -// Bright color palette -private val BrightBlue = Color(0xFF007AFF) -private val BrightGreen = Color(0xFF34C759) -private val BrightOrange = Color(0xFFFF9500) -private val BrightRed = Color(0xFFFF3B30) -private val BrightPurple = Color(0xFFAF52DE) -private val BrightTeal = Color(0xFF5AC8FA) +// Modern Color Palette - Matching iOS Design System +// Primary Colors - Modern blue gradient +private val Primary = Color(0xFF2563EB) +private val PrimaryLight = Color(0xFF3B82F6) +private val PrimaryDark = Color(0xFF1E40AF) -// Light variations for containers -private val LightBlue = Color(0xFFE3F2FD) -private val LightGreen = Color(0xFFE8F5E9) -private val LightOrange = Color(0xFFFFF3E0) +// Accent Colors +private val Accent = Color(0xFF8B5CF6) +private val AccentLight = Color(0xFFA78BFA) -// Dark variations -private val DarkBlue = Color(0xFF0A84FF) -private val DarkGreen = Color(0xFF30D158) -private val DarkOrange = Color(0xFFFF9F0A) +// Semantic Colors +private val Success = Color(0xFF10B981) +private val Warning = Color(0xFFF59E0B) +private val Error = Color(0xFFEF4444) +private val Info = Color(0xFF3B82F6) + +// Neutral Colors - Modern grays +private val Background = Color(0xFFF9FAFB) +private val Surface = Color.White +private val SurfaceSecondary = Color(0xFFF3F4F6) + +private val TextPrimary = Color(0xFF111827) +private val TextSecondary = Color(0xFF6B7280) +private val TextTertiary = Color(0xFF9CA3AF) + +private val Border = Color(0xFFE5E7EB) +private val BorderLight = Color(0xFFF3F4F6) + +// Task Status Colors +private val TaskUpcoming = Color(0xFF3B82F6) +private val TaskInProgress = Color(0xFFF59E0B) +private val TaskCompleted = Color(0xFF10B981) +private val TaskCanceled = Color(0xFF6B7280) +private val TaskArchived = Color(0xFF9CA3AF) + +// Dark mode variations +private val DarkBackground = Color(0xFF1C1B1F) +private val DarkSurface = Color(0xFF2B2930) +private val DarkSurfaceSecondary = Color(0xFF3B3842) private val DarkColorScheme = darkColorScheme( - primary = DarkBlue, + primary = PrimaryLight, onPrimary = Color.White, - primaryContainer = Color(0xFF003D75), + primaryContainer = PrimaryDark, onPrimaryContainer = Color(0xFFD0E4FF), - secondary = DarkGreen, + secondary = Success, onSecondary = Color.White, secondaryContainer = Color(0xFF1B5E20), onSecondaryContainer = Color(0xFFB9F6CA), - tertiary = DarkOrange, + tertiary = Warning, onTertiary = Color.White, tertiaryContainer = Color(0xFF663C00), onTertiaryContainer = Color(0xFFFFE0B2), - error = BrightRed, + error = Error, onError = Color.White, errorContainer = Color(0xFF93000A), onErrorContainer = Color(0xFFFFDAD6), - background = Color(0xFF1C1B1F), + background = DarkBackground, onBackground = Color(0xFFE6E1E5), - surface = Color(0xFF1C1B1F), + surface = DarkSurface, onSurface = Color(0xFFE6E1E5), - surfaceVariant = Color(0xFF49454F), + surfaceVariant = DarkSurfaceSecondary, onSurfaceVariant = Color(0xFFCAC4D0), outline = Color(0xFF938F99), @@ -57,36 +79,36 @@ private val DarkColorScheme = darkColorScheme( ) private val LightColorScheme = lightColorScheme( - primary = BrightBlue, + primary = Primary, onPrimary = Color.White, - primaryContainer = LightBlue, - onPrimaryContainer = Color(0xFF001D35), + primaryContainer = Color(0xFFEBF2FF), + onPrimaryContainer = PrimaryDark, - secondary = BrightGreen, + secondary = Success, onSecondary = Color.White, - secondaryContainer = LightGreen, - onSecondaryContainer = Color(0xFF002106), + secondaryContainer = Color(0xFFD1FAE5), + onSecondaryContainer = Color(0xFF064E3B), - tertiary = BrightOrange, + tertiary = Warning, onTertiary = Color.White, - tertiaryContainer = LightOrange, - onTertiaryContainer = Color(0xFF2B1700), + tertiaryContainer = Color(0xFFFEF3C7), + onTertiaryContainer = Color(0xFF78350F), - error = BrightRed, + error = Error, onError = Color.White, - errorContainer = Color(0xFFFFDAD6), - onErrorContainer = Color(0xFF410002), + errorContainer = Color(0xFFFEE2E2), + onErrorContainer = Color(0xFF7F1D1D), - background = Color(0xFFFFFBFE), - onBackground = Color(0xFF1C1B1F), + background = Background, + onBackground = TextPrimary, - surface = Color(0xFFFFFBFE), - onSurface = Color(0xFF1C1B1F), - surfaceVariant = Color(0xFFE7E0EC), - onSurfaceVariant = Color(0xFF49454F), + surface = Surface, + onSurface = TextPrimary, + surfaceVariant = SurfaceSecondary, + onSurfaceVariant = TextSecondary, - outline = Color(0xFF79747E), - outlineVariant = Color(0xFFCAC4D0) + outline = Border, + outlineVariant = BorderLight ) @Composable @@ -98,6 +120,20 @@ fun MyCribTheme( MaterialTheme( colorScheme = colorScheme, + typography = AppTypography, + shapes = AppShapes, content = content ) } + +// Extended colors for semantic states (not part of Material3 ColorScheme) +object AppColors { + val accent = Accent + val accentLight = AccentLight + val info = Info + val taskUpcoming = TaskUpcoming + val taskInProgress = TaskInProgress + val taskCompleted = TaskCompleted + val taskCanceled = TaskCanceled + val taskArchived = TaskArchived +} diff --git a/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Type.kt b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Type.kt new file mode 100644 index 0000000..24bc7d5 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/example/mycrib/ui/theme/Type.kt @@ -0,0 +1,94 @@ +package com.mycrib.android.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Modern Typography Scale - Matching iOS Design System +val AppTypography = Typography( + // Display - For hero sections + displayLarge = TextStyle( + fontSize = 57.sp, + fontWeight = FontWeight.Bold, + lineHeight = 64.sp + ), + displayMedium = TextStyle( + fontSize = 45.sp, + fontWeight = FontWeight.Bold, + lineHeight = 52.sp + ), + displaySmall = TextStyle( + fontSize = 36.sp, + fontWeight = FontWeight.Bold, + lineHeight = 44.sp + ), + + // Headline - For section headers + headlineLarge = TextStyle( + fontSize = 32.sp, + fontWeight = FontWeight.Bold, + lineHeight = 40.sp + ), + headlineMedium = TextStyle( + fontSize = 28.sp, + fontWeight = FontWeight.SemiBold, + lineHeight = 36.sp + ), + headlineSmall = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.SemiBold, + lineHeight = 32.sp + ), + + // Title - For card titles + titleLarge = TextStyle( + fontSize = 22.sp, + fontWeight = FontWeight.SemiBold, + lineHeight = 28.sp + ), + titleMedium = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.SemiBold, + lineHeight = 24.sp + ), + titleSmall = TextStyle( + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + lineHeight = 20.sp + ), + + // Body - For main content + bodyLarge = TextStyle( + fontSize = 17.sp, + fontWeight = FontWeight.Normal, + lineHeight = 24.sp + ), + bodyMedium = TextStyle( + fontSize = 15.sp, + fontWeight = FontWeight.Normal, + lineHeight = 20.sp + ), + bodySmall = TextStyle( + fontSize = 13.sp, + fontWeight = FontWeight.Normal, + lineHeight = 16.sp + ), + + // Label - For labels and captions + labelLarge = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + lineHeight = 20.sp + ), + labelMedium = TextStyle( + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + lineHeight = 16.sp + ), + labelSmall = TextStyle( + fontSize = 11.sp, + fontWeight = FontWeight.Medium, + lineHeight = 16.sp + ) +)