From f95208aa9d703d0657adb2f1f18e76be26622ab8 Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Thu, 28 May 2026 15:17:57 +0630 Subject: [PATCH] input amount screen responsive screen size --- .../NumericEntryScreen.kt} | 134 +------- .../{amount => input_amount}/AmountRoute.kt | 4 +- .../ui/input_amount/InputAmountScreen.kt | 315 ++++++++++++++++++ .../utsmyanmar/ui/navigation/AppNavGraph.kt | 2 +- .../com/mob/utsmyanmar/ui/preview/Preview.kt | 4 +- .../utsmyanmar/ui/refund_rrn/InputRrnRoute.kt | 2 +- 6 files changed, 324 insertions(+), 137 deletions(-) rename app/src/main/java/com/mob/utsmyanmar/ui/{amount/AmountScreen.kt => components/NumericEntryScreen.kt} (66%) rename app/src/main/java/com/mob/utsmyanmar/ui/{amount => input_amount}/AmountRoute.kt (98%) create mode 100644 app/src/main/java/com/mob/utsmyanmar/ui/input_amount/InputAmountScreen.kt diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt similarity index 66% rename from app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt rename to app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt index 53a434b..93e310d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/components/NumericEntryScreen.kt @@ -1,4 +1,4 @@ -package com.mob.utsmyanmar.ui.amount +package com.mob.utsmyanmar.ui.components import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -15,77 +15,24 @@ 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.automirrored.rounded.Backspace 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 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.preview.P3Preview import com.mob.utsmyanmar.ui.theme.Color -@Composable -fun AmountScreen( - title: String = "Amount", - onBackClick: () -> Unit = {}, - onChargeClick: (String) -> Unit = {} -) { - var amount by remember { mutableStateOf("") } - - 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, @@ -226,7 +173,7 @@ fun NumericEntryScreen( elevation = CardDefaults.cardElevation(defaultElevation = 6.dp) ) { Icon( - imageVector = Icons.Rounded.Backspace, + imageVector = Icons.AutoMirrored.Rounded.Backspace, contentDescription = "Delete", tint = if (canDelete) Color.LegacyRed else Color.Gray, modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) @@ -293,78 +240,3 @@ private fun KeypadButton( ) } } - -private fun formatAmount(value: String): String { - val normalized = value.ifEmpty { "0" } - val wholePart = normalized.substringBefore(".").ifEmpty { "0" } - val groupedWholePart = "%,d".format(wholePart.toLongOrNull() ?: 0L) - - if (!normalized.contains(".")) { - return groupedWholePart - } - - val decimalPart = normalized.substringAfter(".", "") - return if (normalized.endsWith(".")) { - "$groupedWholePart." - } else { - "$groupedWholePart.$decimalPart" - } -} - -private fun appendAmountValue(current: String, value: String): String { - if (value == ".") { - if (current.contains(".")) return current - return if (current.isEmpty()) "0." else "$current." - } - - val decimalIndex = current.indexOf('.') - return if (decimalIndex >= 0) { - val decimalPart = current.substring(decimalIndex + 1) - val remainingDecimalDigits = 2 - decimalPart.length - if (remainingDecimalDigits <= 0) { - current - } else { - current + value.take(remainingDecimalDigits) - } - } else { - val wholeDigitsCount = current.filter(Char::isDigit).length - val remainingWholeDigits = 9 - wholeDigitsCount - if (remainingWholeDigits <= 0) { - current - } else { - current + value.take(remainingWholeDigits) - } - } -} - -@P2Preview -@Composable -fun PreviewAmountScreen2() { - AmountScreen { } -} - -@P3Preview -@Composable -fun PreviewAmountScreen3() { - 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/amount/AmountRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/input_amount/AmountRoute.kt similarity index 98% rename from app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountRoute.kt rename to app/src/main/java/com/mob/utsmyanmar/ui/input_amount/AmountRoute.kt index 6e70e9f..3872e30 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/amount/AmountRoute.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/input_amount/AmountRoute.kt @@ -1,4 +1,4 @@ -package com.mob.utsmyanmar.ui.amount +package com.mob.utsmyanmar.ui.input_amount import androidx.compose.runtime.Composable import com.mob.utsmyanmar.model.ProcessCode @@ -12,7 +12,7 @@ fun AmountRoute( onBack: () -> Unit, onNavigateCardWaiting: () -> Unit ) { - AmountScreen( + InputAmount( title = action.ifBlank { "Amount" }, onBackClick = onBack, onChargeClick = { amount -> diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/input_amount/InputAmountScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/input_amount/InputAmountScreen.kt new file mode 100644 index 0000000..71e2aad --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/input_amount/InputAmountScreen.kt @@ -0,0 +1,315 @@ +package com.mob.utsmyanmar.ui.input_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.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.rounded.Backspace +import androidx.compose.material.icons.rounded.Backspace +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.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 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.components.appbar.AppBar +import com.mob.utsmyanmar.ui.preview.P2Preview +import com.mob.utsmyanmar.ui.preview.P3Preview +import com.mob.utsmyanmar.ui.theme.Color +import kotlin.collections.List + +@Composable +fun InputAmount( + title: String = "Amount", + onBackClick: () -> Unit = {}, + onChargeClick: (String) -> Unit = {} +){ + + var amount by remember { mutableStateOf("") } + val prefixLabel = "MMK" + val supportingText = "Enter the amount to continue" + + Scaffold( + topBar = { AppBar(title = "Amount") }, + containerColor = Color.IvoryBeige + ) {paddingValues -> + + Column( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize() + .padding(16.dp) + ) { + Spacer(Modifier.height(8.dp)) + //first container + Box( + modifier = Modifier + .fillMaxSize() + .weight(1f), + ){ + Card( + modifier = Modifier.align(Alignment.CenterEnd) + .clickable(enabled = true) { + amount = amount.dropLast(1) + }, + shape = RoundedCornerShape(18.dp), + colors = CardDefaults.cardColors(containerColor = Color.White), + elevation = CardDefaults.cardElevation(defaultElevation = 6.dp) + ) { + Icon( + imageVector = Icons.Rounded.Backspace, + contentDescription = "Delete", + tint = Color.LegacyRed, + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp) + ) + } + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Enter Amount", + 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.isNotBlank()) { + Text( + text = prefixLabel, + color = Color.LegacyRed, + fontSize = 13.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier.padding(end = 10.dp, bottom = 6.dp) + ) + } + + Text( + text = formatAmount(amount.ifEmpty { "0" }), + color = Color.LegacyRed, + fontSize = 32.sp, + fontWeight = FontWeight.Bold + ) + } + + Spacer(modifier = Modifier.height(12.dp)) + + Text( + text = supportingText, + color = Color.Gray, + fontSize = 11.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + } + } + + //second container + Column( + modifier = Modifier + .fillMaxWidth() + .weight(3f), + verticalArrangement = Arrangement.Bottom + ){ + NumericKeypad( + onKeyClick = { value -> + amount = appendAmountValue(amount, value) + } + ) + } + + Spacer(Modifier.height(16.dp)) + //third container + Box( + modifier = Modifier + .fillMaxWidth() + .weight(0.5f) + ){ + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Button( + onClick = {}, + modifier = Modifier + .weight(1f) + .height(56.dp), + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.White, + contentColor = Color.LegacyRed + ) + ) { + Text("Cancel") + } + + Button( + onClick = { + if (amount.isNotEmpty()) { + onChargeClick(amount) + } }, + modifier = Modifier + .weight(1f) + .height(56.dp), + enabled = amount.isNotEmpty(), + 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 = "Next", + fontSize = 14.sp, + fontWeight = FontWeight.Medium + ) + } + } + } + + } + } +} + +@Composable +private fun NumericKeypad( + onKeyClick: (String) -> Unit +) { + val keys : List> = listOf( + listOf("1", "2", "3"), + listOf("4", "5", "6"), + listOf("7", "8", "9"), + listOf(".", "0", "00") + ) + 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 appendAmountValue(current: String, value: String): String { + if (value == ".") { + if (current.contains(".")) return current + return if (current.isEmpty()) "0." else "$current." + } + + val decimalIndex = current.indexOf('.') + return if (decimalIndex >= 0) { + val decimalPart = current.substring(decimalIndex + 1) + val remainingDecimalDigits = 2 - decimalPart.length + if (remainingDecimalDigits <= 0) { + current + } else { + current + value.take(remainingDecimalDigits) + } + } else { + val wholeDigitsCount = current.filter(Char::isDigit).length + val remainingWholeDigits = 9 - wholeDigitsCount + if (remainingWholeDigits <= 0) { + current + } else { + current + value.take(remainingWholeDigits) + } + } +} + +private fun formatAmount(value: String): String { + val normalized = value.ifEmpty { "0" } + val wholePart = normalized.substringBefore(".").ifEmpty { "0" } + val groupedWholePart = "%,d".format(wholePart.toLongOrNull() ?: 0L) + + if (!normalized.contains(".")) { + return groupedWholePart + } + + val decimalPart = normalized.substringAfter(".", "") + return if (normalized.endsWith(".")) { + "$groupedWholePart." + } else { + "$groupedWholePart.$decimalPart" + } +} + +@P2Preview +@P3Preview +@Composable +fun PreviewInputAmount(){ + InputAmount(); +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt index 7d70274..e17c5f5 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt @@ -12,7 +12,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument import com.mob.utsmyanmar.model.ProcessCode -import com.mob.utsmyanmar.ui.amount.AmountRoute +import com.mob.utsmyanmar.ui.input_amount.AmountRoute import com.mob.utsmyanmar.ui.cardwaiting.CardWaitingScreen import com.mob.utsmyanmar.ui.cardwaiting.CardWaitingViewModel import com.mob.utsmyanmar.ui.dashboard.DashboardScreen2 diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/preview/Preview.kt b/app/src/main/java/com/mob/utsmyanmar/ui/preview/Preview.kt index 135c3d7..3cf2398 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/preview/Preview.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/preview/Preview.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.tooling.preview.Preview @Preview( name = "P2", - device = "spec:width=720px,height=1440px,dpi=349", + device = "spec:width=720px,height=1440px,dpi=350", showBackground = true, showSystemUi = true ) @@ -13,7 +13,7 @@ annotation class P2Preview @Preview( name = "P3", - device = "spec:width=720px,height=1600px,dpi=320", + device = "spec:width=720px,height=1600px,dpi=300", showBackground = true, showSystemUi = true ) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/refund_rrn/InputRrnRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/refund_rrn/InputRrnRoute.kt index 411e3c9..b618011 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/refund_rrn/InputRrnRoute.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/refund_rrn/InputRrnRoute.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import com.mob.utsmyanmar.ui.amount.NumericEntryScreen +import com.mob.utsmyanmar.ui.components.NumericEntryScreen import com.mob.utsmyanmar.viewmodel.SharedViewModel import com.utsmyanmar.paylibs.utils.POSUtil