diff --git a/app/src/main/java/com/couplesconnect/app/core/navigation/AppNavigation.kt b/app/src/main/java/com/couplesconnect/app/core/navigation/AppNavigation.kt index ce86248b..24d71027 100644 --- a/app/src/main/java/com/couplesconnect/app/core/navigation/AppNavigation.kt +++ b/app/src/main/java/com/couplesconnect/app/core/navigation/AppNavigation.kt @@ -74,9 +74,20 @@ fun AppNavigation( val shellTitle = currentRoute ?.takeIf { it in shellBackRoutes } ?.let(AppRoute::titleFor) + val navigateBackOrHome: () -> Unit = { + if (!navController.popBackStack()) { + navController.navigate(AppRoute.HOME) { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + } + } val navigateRoute: (String) -> Unit = { route -> if (route == "back") { - navController.popBackStack() + navigateBackOrHome() } else { navController.navigate(route) } @@ -94,7 +105,7 @@ fun AppNavigation( ) }, navigationIcon = { - IconButton(onClick = { navController.popBackStack() }) { + IconButton(onClick = navigateBackOrHome) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back" @@ -200,7 +211,7 @@ fun AppNavigation( previousQuestionId = it.arguments?.getString("prevId"), nextQuestionId = it.arguments?.getString("nextId"), onNavigate = navigateRoute, - onBack = { navController.popBackStack() } + onBack = navigateBackOrHome ) } diff --git a/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerHistoryScreen.kt b/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerHistoryScreen.kt index 9211207c..82a2524b 100644 --- a/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerHistoryScreen.kt +++ b/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerHistoryScreen.kt @@ -13,15 +13,21 @@ import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush @@ -58,12 +64,43 @@ private fun AnswerHistoryContent( onDailyQuestion: () -> Unit, onDelete: (String) -> Unit ) { + var pendingDelete by remember { mutableStateOf(null) } + + pendingDelete?.let { answer -> + AlertDialog( + onDismissRequest = { pendingDelete = null }, + title = { Text("Remove this answer?") }, + text = { + Text("This removes the saved reflection from this device. The prompt itself will stay available.") + }, + confirmButton = { + Button( + onClick = { + onDelete(answer.questionId) + pendingDelete = null + }, + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF8D2D35), + contentColor = Color.White + ) + ) { + Text("Remove") + } + }, + dismissButton = { + TextButton(onClick = { pendingDelete = null }) { + Text("Keep") + } + } + ) + } + Box( modifier = Modifier .fillMaxSize() .background( Brush.linearGradient( - listOf(Color(0xFFFFFBFA), Color(0xFFF3F7F1), Color(0xFFEAF0F4)), + listOf(Color(0xFFFFFBFE), Color(0xFFF8F1FF), Color(0xFFFFEEF7)), start = Offset.Zero, end = Offset.Infinite ) @@ -109,7 +146,7 @@ private fun AnswerHistoryContent( AnswerHistoryCard( answer = answer, onClick = { onAnswerSelected(answer) }, - onDelete = { onDelete(answer.questionId) } + onDelete = { pendingDelete = answer } ) } } @@ -128,7 +165,7 @@ private fun AnswerHistoryCard( onClick = onClick, modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(24.dp), - colors = CardDefaults.cardColors(containerColor = Color.White.copy(alpha = 0.86f)), + colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 6.dp) ) { Column( @@ -154,12 +191,22 @@ private fun AnswerHistoryCard( maxLines = 2, overflow = TextOverflow.Ellipsis ) - OutlinedButton( - onClick = onDelete, + Row( modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(14.dp) + horizontalArrangement = Arrangement.SpaceBetween ) { - Text("Remove answer") + Text( + text = if (answer.isRevealed) "Opened" else "Private", + style = MaterialTheme.typography.labelMedium, + color = Color(0xFF6B4A86), + fontWeight = FontWeight.SemiBold + ) + TextButton(onClick = onDelete) { + Text( + text = "Remove", + color = Color(0xFF8D2D35) + ) + } } } } diff --git a/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerRevealScreen.kt b/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerRevealScreen.kt index 1bbf22f5..b4aeb4da 100644 --- a/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerRevealScreen.kt +++ b/app/src/main/java/com/couplesconnect/app/ui/answers/AnswerRevealScreen.kt @@ -74,7 +74,7 @@ private fun AnswerRevealContent( .fillMaxSize() .background( Brush.linearGradient( - listOf(Color(0xFFFFFBFA), Color(0xFFF3F7F1), Color(0xFFEAF0F4)), + listOf(Color(0xFFFFFBFE), Color(0xFFF8F1FF), Color(0xFFFFEEF7)), start = Offset.Zero, end = Offset.Infinite ) @@ -89,16 +89,7 @@ private fun AnswerRevealContent( .padding(horizontal = 20.dp, vertical = 20.dp), verticalArrangement = Arrangement.spacedBy(18.dp) ) { - Text( - text = "Reveal together", - style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold), - color = Color(0xFF27211F) - ) - Text( - text = "Open a saved answer when you are ready to look at it together.", - style = MaterialTheme.typography.bodyLarge, - color = Color(0xFF4E4642) - ) + RevealHeader() when { state.isLoading -> RevealMessageCard { @@ -151,15 +142,15 @@ private fun NoAnswerState( Column(verticalArrangement = Arrangement.spacedBy(14.dp)) { RevealPill("No answer yet") Text( - text = question?.text ?: "Question $questionId is ready when you are.", + text = question?.text ?: "This prompt is ready when you are.", style = MaterialTheme.typography.titleMedium, - color = Color(0xFF27211F), + color = Color(0xFF261D2E), fontWeight = FontWeight.SemiBold ) Text( - text = "Answer this prompt first, then come back when you are ready to reveal it.", + text = "Answer privately first. Reveal can wait until there is something worth opening together.", style = MaterialTheme.typography.bodyMedium, - color = Color(0xFF4E4642) + color = Color(0xFF5A5060) ) Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { Button( @@ -167,9 +158,9 @@ private fun NoAnswerState( modifier = Modifier.weight(1f), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors( - containerColor = Color(0xFFB98AF4), - contentColor = Color(0xFF271236) - ) + containerColor = Color(0xFFB98AF4), + contentColor = Color(0xFF24122F) + ) ) { Text("Answer") } @@ -178,7 +169,7 @@ private fun NoAnswerState( modifier = Modifier.weight(1f), shape = RoundedCornerShape(16.dp) ) { - Text("Home") + Text("Not now") } } } @@ -198,13 +189,14 @@ private fun ReadyToRevealState( Text( text = question?.text ?: answer.questionText, style = MaterialTheme.typography.titleLarge, - color = Color(0xFF27211F), + color = Color(0xFF261D2E), fontWeight = FontWeight.SemiBold ) + AnswerPreview(answer = answer, revealed = false) Text( - text = "Your answer is private for now. Reveal it when the moment feels right.", + text = "No rush. Reveal this only when you want the conversation to open.", style = MaterialTheme.typography.bodyMedium, - color = Color(0xFF4E4642) + color = Color(0xFF5A5060) ) Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { Button( @@ -212,18 +204,18 @@ private fun ReadyToRevealState( modifier = Modifier.weight(1f), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors( - containerColor = Color(0xFFB98AF4), - contentColor = Color(0xFF271236) - ) + containerColor = Color(0xFFB98AF4), + contentColor = Color(0xFF24122F) + ) ) { - Text("Reveal") + Text("Reveal answer") } OutlinedButton( onClick = onHistory, modifier = Modifier.weight(1f), shape = RoundedCornerShape(16.dp) ) { - Text("History") + Text("Saved answers") } } } @@ -247,29 +239,21 @@ private fun RevealedState( Text( text = question?.text ?: answer.questionText, style = MaterialTheme.typography.titleLarge, - color = Color(0xFF27211F), + color = Color(0xFF261D2E), fontWeight = FontWeight.SemiBold ) - Surface( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(20.dp), - color = Color(0xFFF8F0FF) - ) { - Text( - text = answer.revealSummary(), - modifier = Modifier.padding(18.dp), - style = MaterialTheme.typography.bodyLarge, - color = Color(0xFF3E3734) - ) - } + AnswerPreview(answer = answer, revealed = true) Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { Button( onClick = onHistory, modifier = Modifier.weight(1f), shape = RoundedCornerShape(16.dp), - colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF81B29A)) + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFFB98AF4), + contentColor = Color(0xFF24122F) + ) ) { - Text("History") + Text("Saved answers") } OutlinedButton( onClick = onHome, @@ -288,7 +272,7 @@ private fun RevealMessageCard(content: @Composable () -> Unit) { Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(28.dp), - colors = CardDefaults.cardColors(containerColor = Color.White.copy(alpha = 0.86f)), + colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 10.dp) ) { Box(modifier = Modifier.padding(20.dp)) { @@ -297,6 +281,51 @@ private fun RevealMessageCard(content: @Composable () -> Unit) { } } +@Composable +private fun RevealHeader() { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + Text( + text = "Reveal together", + style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold), + color = Color(0xFF261D2E) + ) + Text( + text = "A saved answer can stay private, become a shared reflection, or simply wait for the right moment.", + style = MaterialTheme.typography.bodyLarge, + color = Color(0xFF5A5060) + ) + } +} + +@Composable +private fun AnswerPreview( + answer: LocalAnswer, + revealed: Boolean +) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + color = if (revealed) Color(0xFFF4E8FF) else Color(0xFFFFF8FC) + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = if (revealed) "Opened answer" else "Private preview", + style = MaterialTheme.typography.labelMedium, + color = Color(0xFF56306F), + fontWeight = FontWeight.SemiBold + ) + Text( + text = if (revealed) answer.revealSummary() else answer.privatePreview(), + style = MaterialTheme.typography.bodyLarge, + color = Color(0xFF3E3346) + ) + } + } +} + @Composable private fun RevealPill(label: String) { Surface( @@ -323,6 +352,16 @@ fun LocalAnswer.revealSummary(): String { } } +private fun LocalAnswer.privatePreview(): String { + return when (answerType) { + "written" -> writtenText?.takeIf { it.isNotBlank() }?.let { "Your written answer is saved." } + ?: "Your answer is saved." + "scale" -> "Your scale answer is saved." + "single_choice", "multi_choice", "this_or_that" -> "Your choice is saved." + else -> "Your answer is saved." + } +} + @Preview @Composable fun AnswerRevealScreenPreview() { diff --git a/app/src/main/java/com/couplesconnect/app/ui/questions/LocalQuestionContent.kt b/app/src/main/java/com/couplesconnect/app/ui/questions/LocalQuestionContent.kt index 4fd2d121..63b396e9 100644 --- a/app/src/main/java/com/couplesconnect/app/ui/questions/LocalQuestionContent.kt +++ b/app/src/main/java/com/couplesconnect/app/ui/questions/LocalQuestionContent.kt @@ -67,7 +67,7 @@ fun LocalQuestionContent( modifier: Modifier = Modifier ) { val background = Brush.linearGradient( - colors = listOf(Color(0xFFFFFBFA), Color(0xFFF3F7F1), Color(0xFFEAF0F4)), + colors = listOf(Color(0xFFFFFBFE), Color(0xFFF8F1FF), Color(0xFFFFEEF7)), start = Offset.Zero, end = Offset.Infinite ) @@ -135,7 +135,7 @@ fun LocalQuestionContent( shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors( containerColor = Color(0xFFB98AF4), - contentColor = Color(0xFF271236) + contentColor = Color(0xFF24122F) ) ) { Text( @@ -231,44 +231,46 @@ private fun SubmittedAnswerCard( question: Question, state: LocalQuestionUiState ) { - Card( + Surface( modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(24.dp), - colors = CardDefaults.cardColors(containerColor = Color(0xFFFFFFFF).copy(alpha = 0.86f)), - elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) + shape = RoundedCornerShape(22.dp), + color = Color.White.copy(alpha = 0.78f), + shadowElevation = 0.dp ) { - Column( - modifier = Modifier.padding(20.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) + Row( + modifier = Modifier.padding(15.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Box( - modifier = Modifier - .size(34.dp) - .clip(CircleShape) - .background(Color(0xFF81B29A).copy(alpha = 0.22f)), - contentAlignment = Alignment.Center - ) { - Text( - text = "OK", - style = MaterialTheme.typography.labelSmall, - color = Color(0xFF2F5D45), - fontWeight = FontWeight.Bold - ) - } + Box( + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + .background(Color(0xFFB98AF4).copy(alpha = 0.18f)), + contentAlignment = Alignment.Center + ) { Text( - text = "Saved privately", - modifier = Modifier.padding(start = 10.dp), - style = MaterialTheme.typography.titleSmall, - color = Color(0xFF27211F), - fontWeight = FontWeight.SemiBold + text = "OK", + style = MaterialTheme.typography.labelSmall, + color = Color(0xFF56306F), + fontWeight = FontWeight.Bold + ) + } + Column(verticalArrangement = Arrangement.spacedBy(3.dp)) { + Text( + text = "Private answer saved", + style = MaterialTheme.typography.titleSmall, + color = Color(0xFF261D2E), + fontWeight = FontWeight.SemiBold + ) + Text( + text = answerSummary(question, state), + style = MaterialTheme.typography.bodyMedium, + color = Color(0xFF5A5060), + maxLines = 2, + overflow = TextOverflow.Ellipsis ) } - Text( - text = answerSummary(question, state), - style = MaterialTheme.typography.bodyMedium, - color = Color(0xFF4E4642) - ) } } } diff --git a/app/src/main/java/com/couplesconnect/app/ui/questions/QuestionThreadScreen.kt b/app/src/main/java/com/couplesconnect/app/ui/questions/QuestionThreadScreen.kt index ab9840c7..70685430 100644 --- a/app/src/main/java/com/couplesconnect/app/ui/questions/QuestionThreadScreen.kt +++ b/app/src/main/java/com/couplesconnect/app/ui/questions/QuestionThreadScreen.kt @@ -23,8 +23,8 @@ fun QuestionThreadScreen( LocalQuestionContent( state = state, title = "Answer with care", - subtitle = "Take a moment for your own answer. When you are ready, move to the next prompt or revisit what you have saved.", - primaryRouteLabel = nextQuestionId?.let { "Next" } ?: "History", + subtitle = "Save your answer privately first. From there, choose whether to keep moving or revisit what you have opened.", + primaryRouteLabel = nextQuestionId?.let { "Next prompt" } ?: "Saved answers", onPrimaryRoute = { if (nextQuestionId != null) { onNavigate( @@ -73,8 +73,8 @@ fun QuestionThreadScreenPreview() { ) ), title = "Answer with care", - subtitle = "Take a moment for your own answer.", - primaryRouteLabel = "History", + subtitle = "Save your answer privately first.", + primaryRouteLabel = "Saved answers", onPrimaryRoute = {}, onSecondaryRoute = {}, secondaryRouteLabel = "Back", diff --git a/app/src/main/java/com/couplesconnect/app/ui/questions/components/QuestionAnswerInput.kt b/app/src/main/java/com/couplesconnect/app/ui/questions/components/QuestionAnswerInput.kt index 0bd19273..f6cb34d0 100644 --- a/app/src/main/java/com/couplesconnect/app/ui/questions/components/QuestionAnswerInput.kt +++ b/app/src/main/java/com/couplesconnect/app/ui/questions/components/QuestionAnswerInput.kt @@ -92,7 +92,7 @@ fun QuestionAnswerInput( ) ) { Text( - text = if (isSubmitting) "Saving…" else "Submit answer", + text = if (isSubmitting) "Saving…" else "Save privately", style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold )