From ba24c6005898c1ab7221e3e6ff8294f25ace485c Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Fri, 22 May 2026 22:32:07 +0630 Subject: [PATCH] merge AmountScreen --- .../main/java/com/mob/utsmyanmar/AGENTS.md | 3 + .../mob/utsmyanmar/ui/amount/AmountScreen.kt | 318 ++++++++++++++++-- .../ui/components/NumericEntryScreen.kt | 270 --------------- 3 files changed, 298 insertions(+), 293 deletions(-) create mode 100644 app/src/main/java/com/mob/utsmyanmar/AGENTS.md delete mode 100644 app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt diff --git a/app/src/main/java/com/mob/utsmyanmar/AGENTS.md b/app/src/main/java/com/mob/utsmyanmar/AGENTS.md new file mode 100644 index 0000000..c0ef129 --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/AGENTS.md @@ -0,0 +1,3 @@ +## Working agreements + +- use Scaffold and AppBar() in every main Screen \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt index a11c65e..0e52d9b 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt @@ -1,12 +1,48 @@ package com.mob.utsmyanmar.ui.amount +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBackIosNew +import androidx.compose.material.icons.rounded.Backspace +import androidx.compose.material.icons.rounded.KeyboardArrowLeft +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import com.mob.utsmyanmar.ui.components.NumericEntryScreen +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mob.utsmyanmar.ui.components.appbar.AppBar import com.mob.utsmyanmar.ui.preview.P2Preview +import com.mob.utsmyanmar.ui.theme.Color @Composable fun AmountScreen( @@ -16,29 +52,245 @@ fun AmountScreen( ) { var amount by remember { mutableStateOf("") } - NumericEntryScreen( - title = title, - prompt = "Enter $title", - displayValue = formatAmount(amount.ifEmpty { "0" }), - supportingText = "Enter the amount to continue", - confirmText = "Next", - prefixLabel = "MMK", - onBackClick = onBackClick, - onCancelClick = onBackClick, - onConfirmClick = { - if (amount.isNotEmpty()) { - onChargeClick(amount) - } - }, - onKeyClick = { value -> - amount = appendAmountValue(amount, value) - }, - onDeleteClick = { - amount = amount.dropLast(1) - }, - confirmEnabled = amount.isNotEmpty(), - canDelete = amount.isNotEmpty() + Scaffold( + topBar = { + AppBar(title = title, icon = Icons.Default.ArrowBackIosNew, onIconClick = onBackClick) + } + ) { paddingValues -> + + NumericEntryScreen( + modifier = Modifier.padding(paddingValues), + title = title, + prompt = "Enter $title", + displayValue = formatAmount(amount.ifEmpty { "0" }), + supportingText = "Enter the amount to continue", + confirmText = "Next", + prefixLabel = "MMK", + onBackClick = onBackClick, + onCancelClick = onBackClick, + onConfirmClick = { + if (amount.isNotEmpty()) { + onChargeClick(amount) + } + }, + onKeyClick = { value -> + amount = appendAmountValue(amount, value) + }, + onDeleteClick = { + amount = amount.dropLast(1) + }, + confirmEnabled = amount.isNotEmpty(), + canDelete = amount.isNotEmpty() + ) + } +} + +@Composable +fun NumericEntryScreen( + title: String, + prompt: String, + displayValue: String, + supportingText: String, + confirmText: String, + onBackClick: () -> Unit, + onCancelClick: () -> Unit, + onConfirmClick: () -> Unit, + onKeyClick: (String) -> Unit, + onDeleteClick: () -> Unit, + modifier: Modifier = Modifier, + prefixLabel: String? = null, + errorMessage: String? = null, + confirmEnabled: Boolean = true, + canDelete: Boolean = true, + keys: List> = listOf( + listOf("1", "2", "3"), + listOf("4", "5", "6"), + listOf("7", "8", "9"), + listOf(".", "0", "00") ) +) { + Box( + modifier = modifier + .fillMaxSize() + .background(Color.IvoryBeige) + .navigationBarsPadding() + .statusBarsPadding() + ) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp) + ) { + Text( + text = prompt, + color = Color.Gray, + fontSize = 11.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Row( + modifier = Modifier.align(Alignment.CenterHorizontally), + verticalAlignment = Alignment.Bottom + ) { + if (!prefixLabel.isNullOrBlank()) { + Text( + text = prefixLabel, + color = Color.LegacyRed, + fontSize = 13.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier.padding(end = 10.dp, bottom = 6.dp) + ) + } + + Text( + text = displayValue, + color = Color.LegacyRed, + fontSize = 32.sp, + fontWeight = FontWeight.Bold + ) + } + + Spacer(modifier = Modifier.height(12.dp)) + + Text( + text = supportingText, + color = if (errorMessage == null) Color.Gray else Color.Error, + fontSize = 11.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + Spacer(modifier = Modifier.height(80.dp)) + + NumericKeypad( + keys = keys, + onKeyClick = onKeyClick + ) + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Button( + onClick = onCancelClick, + modifier = Modifier + .weight(1f) + .height(56.dp), + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = Color.LegacyRed + ) + ) { + Text("Cancel") + } + + Button( + onClick = onConfirmClick, + modifier = Modifier + .weight(1f) + .height(56.dp), + enabled = confirmEnabled, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.LegacyRed, + contentColor = Color.White, + disabledContainerColor = Color.LegacyRed.copy(alpha = 0.5f), + disabledContentColor = Color.White + ) + ) { + Text( + text = confirmText, + fontSize = 14.sp, + fontWeight = FontWeight.Medium + ) + } + } + + Spacer(modifier = Modifier.height(18.dp)) + } + + Card( + modifier = Modifier + .align(Alignment.TopEnd) + .padding(top = 25.dp, end = 20.dp) + .clickable(enabled = canDelete) { + onDeleteClick() + }, + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.cardColors(containerColor = Color.White), + elevation = CardDefaults.cardElevation(defaultElevation = 6.dp) + ) { + Icon( + imageVector = Icons.Rounded.Backspace, + contentDescription = "Delete", + tint = if (canDelete) Color.LegacyRed else Color.Gray, + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) + ) + } + } +} + +@Composable +private fun NumericKeypad( + keys: List>, + onKeyClick: (String) -> Unit +) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + keys.forEach { row -> + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + row.forEach { key -> + KeypadButton( + text = key, + modifier = Modifier.weight(1f), + onClick = { onKeyClick(key) } + ) + } + } + } + } +} + +@Composable +private fun KeypadButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit +) { + val enabled = text.isNotBlank() + + Box( + modifier = modifier + .height(66.dp) + .shadow( + elevation = 2.dp, + shape = RoundedCornerShape(8.dp), + clip = false + ) + .background( + color = Color.White, + shape = RoundedCornerShape(8.dp) + ) + .clickable(enabled = enabled) { onClick() }, + contentAlignment = Alignment.Center + ) { + Text( + text = text, + color = if (enabled) Color.LegacyRed else Color.White, + fontSize = 24.sp, + fontWeight = FontWeight.Normal, + textAlign = TextAlign.Center + ) + } } private fun formatAmount(value: String): String { @@ -89,3 +341,23 @@ private fun appendAmountValue(current: String, value: String): String { fun PreviewAmountScreen() { AmountScreen { } } + +@Preview(showBackground = true) +@Composable +private fun PreviewNumericEntryScreen() { + NumericEntryScreen( + title = "Amount", + prompt = "Enter Amount", + displayValue = "12,500", + supportingText = "Enter the amount to continue", + confirmText = "Next", + onBackClick = {}, + onCancelClick = {}, + onConfirmClick = {}, + onKeyClick = {}, + onDeleteClick = {}, + prefixLabel = "MMK", + confirmEnabled = true, + canDelete = true + ) +} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt deleted file mode 100644 index e460022..0000000 --- a/app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt +++ /dev/null @@ -1,270 +0,0 @@ -package com.mob.utsmyanmar.ui.components - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -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.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Backspace -import androidx.compose.material.icons.rounded.KeyboardArrowLeft -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.shadow -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.mob.utsmyanmar.ui.theme.Color - -@Composable -fun NumericEntryScreen( - title: String, - prompt: String, - displayValue: String, - supportingText: String, - confirmText: String, - onBackClick: () -> Unit, - onCancelClick: () -> Unit, - onConfirmClick: () -> Unit, - onKeyClick: (String) -> Unit, - onDeleteClick: () -> Unit, - modifier: Modifier = Modifier, - prefixLabel: String? = null, - errorMessage: String? = null, - confirmEnabled: Boolean = true, - canDelete: Boolean = true, - keys: List> = listOf( - listOf("1", "2", "3"), - listOf("4", "5", "6"), - listOf("7", "8", "9"), - listOf(".", "0", "00") - ) -) { - Box( - modifier = modifier - .fillMaxSize() - .background(Color.IvoryBeige) - .navigationBarsPadding() - .statusBarsPadding() - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 20.dp) - ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - contentAlignment = Alignment.Center - ) { - IconButton( - onClick = onBackClick, - modifier = Modifier.align(Alignment.CenterStart) - ) { - Icon( - imageVector = Icons.Rounded.KeyboardArrowLeft, - contentDescription = "Back", - tint = Color.LegacyRed - ) - } - - Text( - text = title, - color = Color.LegacyRed, - fontSize = 14.sp, - fontWeight = FontWeight.Bold - ) - } - - Spacer(modifier = Modifier.height(36.dp)) - - Text( - text = prompt, - color = Color.Gray, - fontSize = 11.sp, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - - Spacer(modifier = Modifier.height(8.dp)) - - Row( - modifier = Modifier.align(Alignment.CenterHorizontally), - verticalAlignment = Alignment.Bottom - ) { - if (!prefixLabel.isNullOrBlank()) { - Text( - text = prefixLabel, - color = Color.LegacyRed, - fontSize = 13.sp, - fontWeight = FontWeight.Medium, - modifier = Modifier.padding(end = 10.dp, bottom = 6.dp) - ) - } - - Text( - text = displayValue, - color = Color.LegacyRed, - fontSize = 32.sp, - fontWeight = FontWeight.Bold - ) - } - - Spacer(modifier = Modifier.height(12.dp)) - - Text( - text = supportingText, - color = if (errorMessage == null) Color.Gray else Color.Error, - fontSize = 11.sp, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - - Spacer(modifier = Modifier.height(28.dp)) - - NumericKeypad( - keys = keys, - onKeyClick = onKeyClick - ) - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - Button( - onClick = onCancelClick, - modifier = Modifier - .weight(1f) - .height(56.dp), - shape = RoundedCornerShape(8.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.White, - contentColor = Color.LegacyRed - ) - ) { - Text("Cancel") - } - - Button( - onClick = onConfirmClick, - modifier = Modifier - .weight(1f) - .height(56.dp), - enabled = confirmEnabled, - shape = RoundedCornerShape(8.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.LegacyRed, - contentColor = Color.White, - disabledContainerColor = Color.LegacyRed.copy(alpha = 0.5f), - disabledContentColor = Color.White - ) - ) { - Text( - text = confirmText, - fontSize = 14.sp, - fontWeight = FontWeight.Medium - ) - } - } - - Spacer(modifier = Modifier.height(18.dp)) - } - - Card( - modifier = Modifier - .align(Alignment.TopEnd) - .padding(top = 110.dp, end = 20.dp) - .clickable(enabled = canDelete) { - onDeleteClick() - }, - shape = RoundedCornerShape(18.dp), - colors = CardDefaults.cardColors(containerColor = Color.White), - elevation = CardDefaults.cardElevation(defaultElevation = 6.dp) - ) { - Icon( - imageVector = Icons.Rounded.Backspace, - contentDescription = "Delete", - tint = if (canDelete) Color.LegacyRed else Color.Gray, - modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) - ) - } - } -} - -@Composable -private fun NumericKeypad( - keys: List>, - onKeyClick: (String) -> Unit -) { - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(6.dp) - ) { - keys.forEach { row -> - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(6.dp) - ) { - row.forEach { key -> - KeypadButton( - text = key, - modifier = Modifier.weight(1f), - onClick = { onKeyClick(key) } - ) - } - } - } - } -} - -@Composable -private fun KeypadButton( - text: String, - modifier: Modifier = Modifier, - onClick: () -> Unit -) { - val enabled = text.isNotBlank() - - Box( - modifier = modifier - .height(66.dp) - .shadow( - elevation = 2.dp, - shape = RoundedCornerShape(8.dp), - clip = false - ) - .background( - color = Color.White, - shape = RoundedCornerShape(8.dp) - ) - .clickable(enabled = enabled) { onClick() }, - contentAlignment = Alignment.Center - ) { - Text( - text = text, - color = if (enabled) Color.LegacyRed else Color.White, - fontSize = 24.sp, - fontWeight = FontWeight.Normal, - textAlign = TextAlign.Center - ) - } -}