diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt deleted file mode 100644 index fde1201..0000000 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt +++ /dev/null @@ -1,928 +0,0 @@ -package com.mob.utsmyanmar.ui.dashboard - -import android.os.Handler -import android.os.Looper -import androidx.compose.animation.core.tween -import androidx.compose.foundation.Image -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.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountBalanceWallet -import androidx.compose.material.icons.filled.BarChart -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.ChevronRight -import androidx.compose.material.icons.filled.CreditCard -import androidx.compose.material.icons.filled.Lock -import androidx.compose.material.icons.filled.LockOpen -import androidx.compose.material.icons.filled.Menu -import androidx.compose.material.icons.filled.Notifications -import androidx.compose.material.icons.filled.Replay -import androidx.compose.material.icons.filled.SwapHoriz -import androidx.compose.material.icons.filled.Sync -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.DrawerValue -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalDrawerSheet -import androidx.compose.material3.ModalNavigationDrawer -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.VerticalDivider -import androidx.compose.material3.rememberDrawerState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import coil3.compose.AsyncImage -import com.mob.utsmyanmar.R -import com.mob.utsmyanmar.ui.components.appbar.AppBar -import com.mob.utsmyanmar.ui.device_info.DeviceInfoUiState -import com.mob.utsmyanmar.ui.preview.P2Preview -import com.mob.utsmyanmar.ui.preview.P3Preview -import com.mob.utsmyanmar.ui.theme.Color -import com.utsmyanmar.paylibs.sign_on.EchoTestProcess -import com.utsmyanmar.paylibs.sign_on.SignOnListener -import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlin.time.Duration.Companion.milliseconds - -@Composable -fun DashboardScreen2( - onNavigateAmount: (String) -> Unit = {}, - onNavigateSignOn: () -> Unit = {}, - onNavigateSettlement: () -> Unit = {}, - onNavigateVersion: () -> Unit = {}, - onNavigateFunctions: () -> Unit = {}, - onNavigateAction: (String) -> Unit = {}, - onNavigateNotifications: () -> Unit = {}, - dashboardUiState: DashboardUiState = DashboardUiState(), - deviceInfo: DeviceInfoUiState = DeviceInfoUiState() -) { - - val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) - val scope = rememberCoroutineScope() - val mainHandler = remember { Handler(Looper.getMainLooper()) } - var showHostActionDialog by remember { mutableStateOf(false) } - var activeHostAction by remember { mutableStateOf("Log-On") } - var isHostActionRunning by remember { mutableStateOf(false) } - var dialogMessage by remember { mutableStateOf("") } - var reversalEnabled by remember { mutableStateOf(runCatching { SystemParamsOperation.getInstance().isReversalOn }.getOrDefault(false)) } - - val isOnline = true - - fun confirmationMessage(action: String) = "Do you want to start ${action.lowercase()}?" - fun processingMessage(action: String) = "Sending ${action.lowercase()} request to host..." - fun successMessage(action: String) = "$action success." - fun failureMessage(action: String, resultCode: Int?) = - "$action failed. Response code: ${resultCode ?: -1}" - - fun networkFailureMessage(action: String) = "Network error during $action." - fun openHostActionDialog(action: String) { - activeHostAction = action - isHostActionRunning = false - dialogMessage = confirmationMessage(action) - showHostActionDialog = true - } - - if (showHostActionDialog) { - AlertDialog( - onDismissRequest = { - if (!isHostActionRunning) { - showHostActionDialog = false - } - }, title = { - Text( - text = activeHostAction, color = Color.LegacyRed, fontWeight = FontWeight.Bold - ) - }, text = { - Text(text = dialogMessage) - }, confirmButton = { - TextButton( - onClick = { - if (isHostActionRunning) return@TextButton - - if (dialogMessage != confirmationMessage(activeHostAction)) { - showHostActionDialog = false - dialogMessage = confirmationMessage(activeHostAction) - return@TextButton - } - - isHostActionRunning = true - dialogMessage = processingMessage(activeHostAction) - - val signOnProcess = EchoTestProcess.getInstance() - val request = when (activeHostAction) { - "Echo Test" -> signOnProcess.enqueue(false) - "Log-Off" -> signOnProcess.enqueueLogOff() - else -> signOnProcess.enqueueLogOn() - } - - request.startSignOn(object : SignOnListener { - override fun onSuccessSignOn() { - mainHandler.post { - isHostActionRunning = false - dialogMessage = successMessage(activeHostAction) - } - } - - override fun onFailureSignOn(resultCode: Int?) { - mainHandler.post { - isHostActionRunning = false - mainHandler.post { - isHostActionRunning = false - dialogMessage = failureMessage(activeHostAction, resultCode) - } - } - } - - - override fun onNetworkFailSignOn(message: String?) { - mainHandler.post { - isHostActionRunning = false - dialogMessage = message?.takeIf { it.isNotBlank() } - ?: networkFailureMessage(activeHostAction) - } - } - }) - }) { - Text( - text = when { - isHostActionRunning -> "Processing" - dialogMessage == confirmationMessage(activeHostAction) -> "Start" - else -> "Close" - }, color = Color.LegacyRed - ) - } - }, dismissButton = { - if (!isHostActionRunning) { - TextButton( - onClick = { - showHostActionDialog = false - dialogMessage = confirmationMessage(activeHostAction) - }) { - Text(text = "Cancel", color = Color.Gray) - } - } - }, containerColor = Color.White - ) - } - - ModalNavigationDrawer( - drawerState = drawerState, drawerContent = { - ModalDrawerSheet( - modifier = Modifier.fillMaxWidth(0.78f), - drawerContainerColor = Color.White, - drawerShape = RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .background(Color.IvoryBeige) - .padding(horizontal = 20.dp, vertical = 28.dp) - ) { - Row { - Box( - modifier = Modifier - .size(80.dp) - .clip(CircleShape) - .background(Color.White), contentAlignment = Alignment.Center - ) { - Image( - painter = painterResource(R.drawable.logo_mob), - contentDescription = "mob logo", - modifier = Modifier - .size(100.dp) - .padding(16.dp), - contentScale = ContentScale.Fit - ) - } - - Column { - Text( - text = "MOB Merchant", - color = Color.CrimsonRed, - fontSize = 12.sp, - fontWeight = FontWeight.Bold - ) - Text( - text = "S/N:${deviceInfo.serialNumber}", - color = Color.Black, - fontSize = 12.sp, - fontWeight = FontWeight.Bold - ) - Text( - text = if (isOnline) "Online" else "Offline", - color = if (isOnline) Color.Success else Color.Error, - fontSize = 12.sp, - fontWeight = FontWeight.Bold - ) - } - } - } - - Spacer(modifier = Modifier.height(10.dp)) - Text( - text = "Connection Settings", - fontWeight = FontWeight.Medium, - modifier = Modifier.padding(horizontal = 16.dp) - ) - - Item( - title = "Echo Test", subTitle = "Test Connection Status", - onClick = { - scope.launch { drawerState.close() } - openHostActionDialog("Echo Test") - }, - leadingIcon = { - Icon( - painterResource(R.drawable.ic_up_down_arrow), - contentDescription = "icon", - tint = Color.LegacyRed - ) - }, - trailingIcon = {}, - ) - Item( - title = "Log-On", subTitle = "Log on to System", - onClick = { - scope.launch { drawerState.close() } - openHostActionDialog("Log-On") - }, - leadingIcon = { - Icon( - painterResource(R.drawable.ic_lock), - contentDescription = "icon", - tint = Color.LegacyRed - ) - }, - trailingIcon = {}, - ) - Item( - title = "Log-Off", subTitle = "Log off from System", - onClick = { - scope.launch { drawerState.close() } - openHostActionDialog("Log-Off") - }, - leadingIcon = { - Icon( - painterResource(R.drawable.ic_cancel_circle), - contentDescription = "icon", - tint = Color.LegacyRed - ) - }, - trailingIcon = {}, - ) - Item( - title = "Reversal", subTitle = "Enable / Disable Reversal", - onClick = { - reversalEnabled = !reversalEnabled - runCatching { SystemParamsOperation.getInstance().setReversalFlag(reversalEnabled) } - }, - leadingIcon = { - Icon( - Icons.Default.Sync, - contentDescription = "icon", - tint = Color.LegacyRed - ) - }, - trailingIcon = { - Switch( - checked = reversalEnabled, - onCheckedChange = { isChecked -> - reversalEnabled = isChecked - runCatching { SystemParamsOperation.getInstance().setReversalFlag(isChecked) } - } - ) - }, - ) - - Text( - text = "System Management", - fontWeight = FontWeight.Medium, - modifier = Modifier.padding(horizontal = 16.dp) - ) - - Item( - title = "Functions", subTitle = "System Function Settings", - onClick = { - scope.launch { drawerState.close() } - onNavigateFunctions() - }, - leadingIcon = { - Icon( - painterResource(R.drawable.ic_four_boxes), - contentDescription = "icon", - tint = Color.LegacyRed, - modifier = Modifier.size(16.dp) - ) - }, - trailingIcon = {}, - ) - Item( - title = "Version", subTitle = "View App Version Info", - onClick = { - scope.launch { drawerState.close() } - onNavigateVersion() - }, - leadingIcon = { - Icon( - painterResource(R.drawable.ic_version), - contentDescription = "icon", - tint = Color.LegacyRed - ) - }, - trailingIcon = {}, - ) - - } - }) { -//body start - Scaffold( - containerColor = Color.IvoryBeige, topBar = { - AppBar( - title = "Dashboard", - icon = Icons.Default.Menu, - onIconClick = { scope.launch { drawerState.open() } }, - actions = { - IconButton(onClick = onNavigateNotifications) { - Box { - Icon( - imageVector = Icons.Default.Notifications, - contentDescription = "Notifications", - tint = Color.White - ) - Box( - modifier = Modifier - .size(8.dp) - .background(Color.GoldenGlow, CircleShape) - .align(Alignment.TopEnd) - .offset(x = 2.dp, y = (-2).dp) - ) - } - } - } - ) - }) { paddingValues -> - Column( - modifier = Modifier - .padding(paddingValues) - .fillMaxSize() - ) { - //top section - Box( - modifier = Modifier - .weight(1f) - .fillMaxWidth(), - ) { - AdvertisingArea() - } - //center section - Box( - modifier = Modifier - .weight(1f) - .fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - SummaryCard() - } - //pager section - Box( - modifier = Modifier - .weight(1.3f) - .fillMaxWidth(), - ) { - MenuPager( - items = buildMenuItems( - onNavigateAmount = onNavigateAmount, - onNavigateSignOn = onNavigateSignOn, - onNavigateSettlement = onNavigateSettlement, - onNavigateAction = onNavigateAction - ), - modifier = Modifier.fillMaxSize() - ) - } - //transactions section - RecentTransactions( - transactions = dashboardUiState.recentTransactions, - modifier = Modifier - .weight(1.2f) - .fillMaxWidth() - ) - } - } - } -} - -@Composable -private fun AdvertisingArea() { - - val imageArray = listOf( - "https://i.ytimg.com/vi/eRUVxGRp1Ms/maxresdefault.jpg", - "https://i.ytimg.com/vi/AwvmgTPd7qw/maxresdefault.jpg", - "https://mma.prnewswire.com/media/2080956/SUNMI_3rd_generation_products_T3_PRO_series_V3_MIX.jpg?p=facebook" - ) - val pageState = rememberPagerState(pageCount = { imageArray.size }) - - LaunchedEffect(pageState) { - while (true) { - delay(10000.milliseconds) - val nextPage = (pageState.currentPage + 1) % imageArray.size - - pageState.animateScrollToPage( - page = nextPage, animationSpec = tween(durationMillis = 700) - ) - } - } - - Card( - modifier = Modifier.fillMaxSize(), - shape = RoundedCornerShape(0.dp), - colors = CardDefaults.cardColors(containerColor = Color.White), - ) { - HorizontalPager( - state = pageState, modifier = Modifier.fillMaxSize() - ) { page -> - AsyncImage( - model = imageArray[page], - contentDescription = "ads images", - modifier = Modifier.fillMaxSize(), - contentScale = ContentScale.Crop - ) - } - } -} - -@Composable -private fun SummaryCard() { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = Color.White), - elevation = CardDefaults.cardElevation(4.dp) - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Column(modifier = Modifier.weight(1f)) { - SummaryItem( - title = "Sales Today", - value = "MMK 2,000,000", - subtitle = "47 Transactions", - icon = Icons.Default.BarChart, - iconBg = Color.CrimsonRed - ) - - HorizontalDivider( - color = Color.Gray, - modifier = Modifier.padding(vertical = 6.dp, horizontal = 6.dp) - ) - - SummaryItem( - title = "Settlement", - value = "Completed", - subtitle = "Today 11:00 PM", - icon = Icons.Default.Check, - iconBg = Color.CrimsonRed - ) - } - - VerticalDivider(color = Color.Gray, modifier = Modifier.height(160.dp)) - - Column( - modifier = Modifier - .weight(0.75f) - .padding(start = 18.dp), - horizontalAlignment = Alignment.Start - ) { - Row(verticalAlignment = Alignment.Bottom) { - Text( - text = "Last Sync", fontSize = 12.sp - ) - IconCircle(Icons.Default.Sync, Color.CrimsonRed) - } - - Spacer(Modifier.height(6.dp)) - - Text( - text = "5 mins ago", - fontSize = 18.sp, - color = Color.LegacyRed, - fontWeight = FontWeight.SemiBold - ) - } - } - } -} - -@Composable -private fun SummaryItem( - title: String, - value: String, - subtitle: String, - icon: ImageVector, - iconBg: androidx.compose.ui.graphics.Color -) { - Row( - verticalAlignment = Alignment.Top, modifier = Modifier.padding(6.dp) - ) { - Column(modifier = Modifier.weight(1f)) { - Text(title, fontSize = 12.sp) - Text( - value, fontSize = 14.sp, color = Color.LegacyRed, fontWeight = FontWeight.Bold - ) - Text(subtitle, fontSize = 12.sp) - } - IconCircle(icon, iconBg) - } -} - -@Composable -private fun IconCircle( - icon: ImageVector, color: androidx.compose.ui.graphics.Color -) { - Box( - modifier = Modifier - .size(38.dp) - .clip(CircleShape) - .background(color.copy(alpha = 0.1f)), - contentAlignment = Alignment.Center - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = color, - modifier = Modifier.size(22.dp) - ) - } -} - -private class DashboardMenuItem( - val title: String, - val iconContent: @Composable () -> Unit, - val onClick: () -> Unit -) - -@Composable -private fun buildMenuItems( - onNavigateAmount: (String) -> Unit, - onNavigateSignOn: () -> Unit, - onNavigateSettlement: () -> Unit, - onNavigateAction: (String) -> Unit -): List = listOf( - DashboardMenuItem("Sale", { Icon(painterResource(R.drawable.ic_terminal), contentDescription = null, modifier = Modifier.size(40.dp), tint = Color.LegacyRed) }) { onNavigateAmount("Sale") }, - DashboardMenuItem("MMQR", { Image(painter = painterResource(R.drawable.ic_mmqr_logo), contentDescription = null, modifier = Modifier.height(48.dp)) }) { }, - DashboardMenuItem("History", { Icon(painterResource(R.drawable.ic_history), contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { }, - DashboardMenuItem("Sign On", { Icon(painterResource(R.drawable.ic_sign_on), contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateSignOn() }, - DashboardMenuItem("Settlement", { Icon(painterResource(R.drawable.ic_settlement), contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateSettlement() }, - DashboardMenuItem("Void", { Icon(Icons.Default.Lock, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Void") }, - DashboardMenuItem("Refund", { Icon(Icons.Default.Replay, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Refund") }, - DashboardMenuItem("Pre-Auth", { Icon(Icons.Default.Lock, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Pre-Auth") }, - DashboardMenuItem("Pre-Auth Void", { Icon(Icons.Default.LockOpen, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Pre-Auth Void") }, - DashboardMenuItem("Pre-Auth Complete", { Icon(Icons.Default.CreditCard, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Pre-Auth Complete") }, - DashboardMenuItem("Pre-Auth Complete Void", { Icon(Icons.Default.SwapHoriz, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Pre-Auth Complete Void") }, - DashboardMenuItem("Cash Out", { Icon(Icons.Default.AccountBalanceWallet, contentDescription = null, modifier = Modifier.size(32.dp), tint = Color.LegacyRed) }) { onNavigateAction("Cash Out") }, -) - -@Composable -private fun MenuPager( - items: List, - modifier: Modifier = Modifier -) { - val pages = items.chunked(6) - val pagerState = rememberPagerState(pageCount = { pages.size }) - - Column(modifier = modifier) { - HorizontalPager( - state = pagerState, - modifier = Modifier.weight(1f) - ) { pageIndex -> - MenuPage(items = pages[pageIndex]) - } - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - repeat(pages.size) { index -> - val selected = pagerState.currentPage == index - Box( - modifier = Modifier - .padding(horizontal = 4.dp) - .size(if (selected) 8.dp else 6.dp) - .background( - color = if (selected) Color.LegacyRed else Color.Gray.copy(alpha = 0.4f), - shape = CircleShape - ) - ) - } - } - } -} - -@Composable -private fun MenuPage(items: List) { - Column( - verticalArrangement = Arrangement.spacedBy(10.dp), - modifier = Modifier.padding(horizontal = 16.dp) - ) { - Spacer(Modifier.height(8.dp)) - items.chunked(3).forEach { rowItems -> - Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { - rowItems.forEach { item -> - MenuCard( - title = item.title, - icon = item.iconContent, - modifier = Modifier.weight(1f), - onClick = item.onClick - ) - } - repeat(3 - rowItems.size) { - Spacer(modifier = Modifier.weight(1f)) - } - } - } - } -} - -@Composable -private fun MenuCard( - title: String, - icon: @Composable () -> Unit, - modifier: Modifier = Modifier, - onClick: (() -> Unit)? = null -) { - Card( - modifier = modifier - .height(100.dp) - .then( - if (onClick != null) { - Modifier.clickable(onClick = onClick) - } else { - Modifier - } - ), - shape = RoundedCornerShape(14.dp), - colors = CardDefaults.cardColors(containerColor = Color.White), - elevation = CardDefaults.cardElevation(5.dp) - ) { - Box( - modifier = Modifier - .fillMaxSize() - .padding(6.dp) - ) { - Column { - icon() - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = title, - fontSize = 12.sp, - color = Color.Black, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - modifier = Modifier.weight(1f) - ) - Icon( - imageVector = Icons.Default.ChevronRight, - contentDescription = null, - tint = Color.LegacyRed, - modifier = Modifier.size(28.dp) - ) - } - } - } - } -} - -@Composable -private fun RecentTransactions( - transactions: List, - modifier: Modifier = Modifier -) { - Column(modifier = modifier) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "Recent Transactions", - fontWeight = FontWeight.SemiBold, - fontSize = 14.sp - ) - } - HorizontalDivider( - modifier = Modifier.padding(horizontal = 16.dp), - color = Color.Gray.copy(alpha = 0.2f) - ) - LazyColumn(modifier = Modifier.fillMaxSize()) { - if (transactions.isEmpty()) { - item { - Text( - text = "No recent transactions", - color = Color.Gray, - fontSize = 13.sp, - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 24.dp) - ) - } - } else { - items(items = transactions, key = { it.pid }) { record -> - TrnxRow(record = record) - } - } - } - } -} - -@Composable -private fun TrnxRow(record: TrnxRecord) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 4.dp) - .clip(RoundedCornerShape(10.dp)) - .background(Color.White) - .padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier - .size(36.dp) - .background(Color.LegacyRed.copy(alpha = 0.1f), CircleShape), - contentAlignment = Alignment.Center - ) { - Text( - text = record.typeLabel.take(1), - color = Color.LegacyRed, - fontWeight = FontWeight.Bold, - fontSize = 15.sp - ) - } - - Spacer(Modifier.width(10.dp)) - - Column(modifier = Modifier.weight(1f)) { - Text( - text = if (record.isVoided) "${record.typeLabel} (Voided)" else record.typeLabel, - fontSize = 13.sp, - fontWeight = FontWeight.SemiBold, - color = if (record.isVoided) Color.Gray else Color.Black - ) - Text( - text = record.maskedCard, - fontSize = 11.sp, - color = Color.Gray - ) - } - - Column(horizontalAlignment = Alignment.End) { - Text( - text = record.amountDisplay, - fontSize = 13.sp, - fontWeight = FontWeight.Bold, - color = if (record.isVoided) Color.Gray else Color.LegacyRed - ) - Text( - text = record.dateTime, - fontSize = 10.sp, - color = Color.Gray - ) - } - } -} - -private val previewTransactions = listOf( - TrnxRecord(1L, "Sale", "MMK 10,000", "**** 1234", "06/10 14:32", isVoided = false, isApproved = true), - TrnxRecord(2L, "Void", "MMK 5,500", "**** 5678", "06/10 13:10", isVoided = true, isApproved = false), - TrnxRecord(3L, "Refund", "MMK 2,000", "**** 9012", "06/09 09:45", isVoided = false, isApproved = true), - TrnxRecord(4L, "Sale", "MMK 30,000", "**** 3456", "06/09 08:00", isVoided = false, isApproved = true), - TrnxRecord(5L, "Settlement", "MMK 0", "----", "06/08 18:00", isVoided = false, isApproved = true), -) - -@P3Preview -@P2Preview -@Composable -fun PreviewDashboardScreen2() { - DashboardScreen2(dashboardUiState = DashboardUiState(previewTransactions)) -} - -@Preview -@Composable -fun PreviewItem() { - Item( - onClick = {}, - title = "title", - subTitle = "sub-title" - ) -} - - -@Composable -fun Item( - onClick: () -> Unit, - title: String, - subTitle: String, - leadingIcon: (@Composable () -> Unit)? = null, - trailingIcon: (@Composable () -> Unit)? = null, -) { - Button( - onClick = onClick, - colors = ButtonDefaults.buttonColors( - containerColor = Color.White, - contentColor = Color.Black - ), - modifier = Modifier.fillMaxWidth() - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - ) { - // Square icon background - leadingIcon?.let { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .size(40.dp) - .clip(RoundedCornerShape(16.dp)) // change to RectangleShape for sharp corners - .background(Color.LegacyRed.copy(alpha = 0.1f)) - .padding(8.dp) - ) { - it() - } - } - - Spacer(modifier = Modifier.width(12.dp)) - - Column( - modifier = Modifier - .weight(1f) - .padding(horizontal = 8.dp) - ) { - Text(text = title) - Text( - text = subTitle, - style = MaterialTheme.typography.bodySmall, - color = Color.Gray - ) - } - - trailingIcon?.invoke() - } - } -} \ 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 8d83545..8a77c6d 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 @@ -1,13 +1,10 @@ package com.mob.utsmyanmar.ui.navigation import android.annotation.SuppressLint -import android.net.Uri import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -18,18 +15,10 @@ import com.mob.utsmyanmar.model.ProcessCode import com.mob.utsmyanmar.ui.cardwaiting.CardWaitingScreen import com.mob.utsmyanmar.ui.cardwaiting.CardWaitingViewModel import com.mob.utsmyanmar.ui.dashboard.DashboardScreen2 -import com.mob.utsmyanmar.ui.dashboard.DashboardViewModel +import com.mob.utsmyanmar.ui.dashboard.SeeMoreScreen import com.mob.utsmyanmar.ui.device_info.DeviceInfoViewModel -import com.mob.utsmyanmar.ui.disable.DisableScreen import com.mob.utsmyanmar.ui.functions.FunctionsScreen -import com.mob.utsmyanmar.ui.history_functions.HistoryRoute import com.mob.utsmyanmar.ui.input_amount.AmountRoute -import com.mob.utsmyanmar.ui.manual_entry.InputManualCardRoute -import com.mob.utsmyanmar.ui.notification.NotificationDetailScreen -import com.mob.utsmyanmar.ui.notification.NotificationListScreen -import com.mob.utsmyanmar.ui.notification.NotificationViewModel -import com.mob.utsmyanmar.ui.password_input.InputPassword -import com.mob.utsmyanmar.ui.password_input.PasswordType import com.mob.utsmyanmar.ui.pinpad.PinPadRoute import com.mob.utsmyanmar.ui.pinpad.PinPadViewModel import com.mob.utsmyanmar.ui.print_receipt.PrintReceiptScreen @@ -57,7 +46,6 @@ import com.mob.utsmyanmar.viewmodel.SharedViewModel import com.mob.utsmyanmar.viewmodel.TransProcessViewModel import com.utsmyanmar.paylibs.model.TradeData import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType -import sunmi.sunmiui.utils.LogUtil @SuppressLint("ContextCastToActivity") @Composable @@ -76,64 +64,22 @@ fun AppNavGraph( viewModel = tmsSetupViewModel, onNavigateDashboard = { navController.navigate(Routes.Dashboard.route) { - popUpTo(Routes.TmsSetup.route) { inclusive = true } + popUpTo(Routes.TmsSetup.route) { + inclusive = true + } launchSingleTop = true } }, - onNavigateDisable = { message -> - navController.navigate(Routes.Disable.createRoute(message)) { - popUpTo(Routes.TmsSetup.route) { inclusive = true } - launchSingleTop = true - } - } - ) - } - - composable( - route = Routes.Disable.route, - arguments = listOf( - navArgument("message") { type = NavType.StringType } - ) - ) { backStackEntry -> - val message = Uri.decode(backStackEntry.arguments?.getString("message").orEmpty()) - DisableScreen( - message = message, - onRetry = { - navController.navigate(Routes.TmsSetup.route) { - popUpTo(Routes.Disable.route) { inclusive = true } - launchSingleTop = true - } - } + onNavigateDisable = {} ) } composable(Routes.Dashboard.route) { val sharedViewModel: SharedViewModel = hiltViewModel(activity) - val dashboardViewModel: DashboardViewModel = hiltViewModel() - val dashboardUiState by dashboardViewModel.uiState.collectAsStateWithLifecycle() - val deviceInfoViewModel: DeviceInfoViewModel = hiltViewModel() - val deviceInfo by deviceInfoViewModel.uiState.collectAsStateWithLifecycle() - val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel() - androidx.compose.runtime.LaunchedEffect(Unit) { deviceInfoViewModel.loadDeviceInfo() } - androidx.compose.runtime.LaunchedEffect(tmsSetupViewModel) { - tmsSetupViewModel.onSyncCompleted.collect { - dashboardViewModel.refreshLastSyncTime() - dashboardViewModel.loadCarouselUrls() - } - } - androidx.compose.runtime.LaunchedEffect(tmsSetupViewModel) { - tmsSetupViewModel.navigateToDisable.collect { message -> - navController.navigate(Routes.Disable.createRoute(message)) { - launchSingleTop = true - } - } - } val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) transProcessViewModel.resetTransactionStatus() DashboardScreen2( - dashboardUiState = dashboardUiState, - deviceInfo = deviceInfo, onNavigateAmount = { action -> if(action == "Sale"){ sharedViewModel.transactionsType.value = TransactionsType.SALE; @@ -143,12 +89,14 @@ fun AppNavGraph( navController.navigate(Routes.Amount.createRoute(action)) { launchSingleTop = true } + }, onNavigateSignOn = { navController.navigate(Routes.SignOn.route) { launchSingleTop = true } }, + onNavigateSettlement = { navController.navigate(Routes.Settlement.route) { launchSingleTop = true @@ -158,47 +106,41 @@ fun AppNavGraph( navController.navigate(Routes.Version.route) }, onNavigateFunctions = { - navController.navigate(Routes.Password.createRoute(Routes.Functions.route, PasswordType.SETTING)) { + navController.navigate(Routes.Functions.route) { launchSingleTop = true } - }, - onNavigateHistory = { - navController.navigate(Routes.Password.createRoute(Routes.History.route, PasswordType.SYSTEM)) { - launchSingleTop = true - } - }, - onNavigateAction = { action -> - when (action) { - "Void" -> { - sharedViewModel.transactionsType.value = TransactionsType.VOID - navController.navigate(Routes.Password.createRoute(Routes.VoidTrace.route, PasswordType.SYSTEM)) { - launchSingleTop = true - } - } - "Pre-Auth Void" -> navController.navigate(Routes.Password.createRoute(Routes.Amount.createRoute(action), PasswordType.SYSTEM)) { - launchSingleTop = true - } - "Pre-Auth Complete Void" -> { - sharedViewModel.transactionsType.value = TransactionsType.PRE_AUTH_COMPLETE_VOID - navController.navigate(Routes.Password.createRoute(Routes.VoidTrace.route, PasswordType.SYSTEM)) { - launchSingleTop = true - } - } - "Refund" -> navController.navigate(Routes.Password.createRoute(Routes.Amount.createRoute(action), PasswordType.SYSTEM)) { - launchSingleTop = true - } - else -> navController.navigate(Routes.Amount.createRoute(action)) { launchSingleTop = true } - } - }, - onNavigateNotifications = { - navController.navigate(Routes.NotificationList.route) { launchSingleTop = true } - }, - onClickLastSync = { - tmsSetupViewModel.downloadConfigs() } ) } + composable(Routes.SeeMore.route) { + val sharedViewModel: SharedViewModel = hiltViewModel(activity) + SeeMoreScreen( + onBack = { navController.popBackStack() }, + onNavigateAmount = { action -> + when (action) { + "Void" -> { + sharedViewModel.transactionsType.value = TransactionsType.VOID + navController.navigate(Routes.VoidTrace.route) { + launchSingleTop = true + } + } + "Pre-Auth Complete Void" -> { + sharedViewModel.transactionsType.value = TransactionsType.PRE_AUTH_COMPLETE_VOID + navController.navigate(Routes.VoidTrace.route) { + launchSingleTop = true + } + } + else -> { + navController.navigate(Routes.Amount.createRoute(action)) { + launchSingleTop = true + } + } + } + } + ) + } + composable(Routes.Version.route){ val deviceInfoViewModel: DeviceInfoViewModel = hiltViewModel(); VersionScreen( @@ -207,57 +149,18 @@ fun AppNavGraph( ) } - composable( - route = Routes.Password.route, - arguments = listOf( - navArgument("destination") { type = NavType.StringType }, - navArgument("passwordType") { type = NavType.StringType } - ) - ) { backStackEntry -> - val destination = Uri.decode(backStackEntry.arguments?.getString("destination").orEmpty()) - val passwordType = backStackEntry.arguments?.getString("passwordType").orEmpty() - InputPassword( - passwordType = passwordType, - onBack = { navController.popBackStack() }, - onPasswordCorrect = { - navController.navigate(destination) { - popUpTo(Routes.Password.route) { inclusive = true } - launchSingleTop = true - } - } - ) - } - composable(Routes.Functions.route) { FunctionsScreen( onBack = { navController.popBackStack() } ) } - composable(Routes.History.route) { - val sharedViewModel: SharedViewModel = hiltViewModel(activity) - val transResultViewModel: TransactionResultViewModel = hiltViewModel(activity) - HistoryRoute( - sharedViewModel = sharedViewModel, - onBack = { navController.popBackStack() }, - onNavigatePrintReceipt = { - transResultViewModel.onEvent( - TransactionResultEvent.Start, - sharedViewModel - ) - navController.navigate(Routes.PrintReceipt.route) { - launchSingleTop = true - } - } - ) - } - composable(Routes.VoidTrace.route) { val voidViewModel: VoidViewModel = hiltViewModel() val sharedViewModel: SharedViewModel = hiltViewModel(activity) VoidTraceScreen( - voidViewModel = voidViewModel, sharedViewModel = sharedViewModel, + voidViewModel = voidViewModel, onNavigateTranDetail = { trace -> navController.navigate(Routes.VoidTranDetail.createRoute(trace)) { launchSingleTop = true @@ -314,6 +217,7 @@ fun AppNavGraph( payDetail.transType = TransactionsType.PRE_AUTH_COMPLETE_VOID.name payDetail.transactionType = TransactionsType.PRE_AUTH_COMPLETE_VOID.value } + val tradeData = TradeData() tradeData.payDetail = payDetail transProcessViewModel.setTradeData(tradeData) @@ -417,14 +321,7 @@ fun AppNavGraph( CardWaitingScreen( viewModel = cardWaitingViewModel, amount = formatAmountForDisplay(sharedViewModel.amount.value), - onManualEntry = { - navController.navigate(Routes.ManualEntry.route) { - popUpTo(Routes.CardWaiting.route) { - inclusive = true - } - launchSingleTop = true - } - }, + onManualEntry = {}, onProcessingCard = { navController.navigate(Routes.ProcessingCard.route) { popUpTo(Routes.CardWaiting.route) { @@ -520,11 +417,11 @@ fun AppNavGraph( composable(Routes.InputRrn.route) { val sharedViewModel: SharedViewModel = hiltViewModel(activity) - val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) val rrnViewModel: RRNViewModel = hiltViewModel(activity) + val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) InputRrnRoute( - rrnViewModel = rrnViewModel, transProcessViewModel = transProcessViewModel, + rrnViewModel = rrnViewModel, sharedViewModel = sharedViewModel, onBack = { navController.popBackStack() }, onNavigateProcessing = { @@ -538,27 +435,6 @@ fun AppNavGraph( ) } - composable(Routes.ManualEntry.route) { - val sharedViewModel: SharedViewModel = hiltViewModel(activity) - val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) - val pinPadViewModel: PinPadViewModel = hiltViewModel(activity) - InputManualCardRoute( - transProcessViewModel = transProcessViewModel, - sharedViewModel = sharedViewModel, - pinPadViewModel = pinPadViewModel, - onBack = { navController.popBackStack() }, - onNavigatePinPad = { - pinPadViewModel.resetSessionState() - navController.navigate(Routes.PinPad.route) { - popUpTo(Routes.ProcessingCard.route) { - inclusive = true - } - launchSingleTop = true - } - }, - ) - } - composable(Routes.Processing.route) { val sharedViewModel: SharedViewModel = hiltViewModel(activity) val transProcessViewModel: TransProcessViewModel = hiltViewModel(activity) @@ -636,34 +512,6 @@ fun AppNavGraph( } ) } - - composable(Routes.NotificationList.route) { - val notificationViewModel: NotificationViewModel = hiltViewModel() - NotificationListScreen( - viewModel = notificationViewModel, - onBack = { navController.popBackStack() }, - onNavigateDetail = { id -> - navController.navigate(Routes.NotificationDetail.createRoute(id)) { - launchSingleTop = true - } - } - ) - } - - composable( - route = Routes.NotificationDetail.route, - arguments = listOf( - navArgument("notificationId") { type = NavType.IntType } - ) - ) { backStackEntry -> - val notificationViewModel: NotificationViewModel = hiltViewModel() - val id = backStackEntry.arguments?.getInt("notificationId") ?: return@composable - NotificationDetailScreen( - viewModel = notificationViewModel, - notificationId = id, - onBack = { navController.popBackStack() } - ) - } } } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt b/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt index f3ce5a9..ff5d20e 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/sending_to_host/SendingToHostRoute.kt @@ -8,12 +8,15 @@ import com.mob.utsmyanmar.viewmodel.SharedViewModel import com.mob.utsmyanmar.viewmodel.TransProcessViewModel import kotlinx.coroutines.delay import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.runtime.saveable.rememberSaveable +import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState +import com.mob.utsmyanmar.viewmodel.ProcessingTransaction +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import androidx.compose.runtime.collectAsState import com.mob.utsmyanmar.model.TransactionStatus import com.mob.utsmyanmar.ui.settlement.SettlementViewModel import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType +import kotlinx.coroutines.channels.Channel private const val MOCK_HOST_DELAY_MS = 2000L @@ -32,7 +35,6 @@ fun ProcessingRoute( val settlementStatus by settlementViewModel.uiState.collectAsStateWithLifecycle() - if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) { LaunchedEffect(Unit) { settlementViewModel.startSettlementProcess() @@ -50,6 +52,7 @@ fun ProcessingRoute( } } else { LaunchedEffect(Unit) { +// transProcessViewModel.resetTransactionStatus() transProcessViewModel.startOnlineProcess() } @@ -64,15 +67,10 @@ fun ProcessingRoute( sharedViewModel.payDetail.value = transProcessViewModel.payDetailResult.value onNavigateTransactionResult() } - TransResultStatus.REVERSAL_SUCCESS , - TransResultStatus.REVERSAL_FAIL -> { - delay(2500) - onNavigateMain() - } + TransResultStatus.REVERSAL_SUCCESS -> onNavigateMain() + TransResultStatus.REVERSAL_FAIL -> onNavigateMain() else -> {} } - - } } @@ -81,6 +79,7 @@ fun ProcessingRoute( + if(sharedViewModel.transactionsType.value == TransactionsType.SETTLEMENT) { ProcessingScreen(settlementStatus.processingState) } else {