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 index e91ba3f..c4a6185 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen2.kt @@ -3,70 +3,78 @@ 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.padding - import androidx.compose.foundation.layout.size +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.layout.size 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.BarChart - import androidx.compose.material.icons.filled.Check - import androidx.compose.material.icons.filled.ChevronRight - import androidx.compose.material.icons.filled.Dashboard - import androidx.compose.material.icons.filled.GridView - import androidx.compose.material.icons.filled.History - import androidx.compose.material.icons.filled.Link - import androidx.compose.material.icons.filled.Menu - import androidx.compose.material.icons.filled.PointOfSale - import androidx.compose.material.icons.filled.QrCode +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +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.Dashboard +import androidx.compose.material.icons.filled.GridView +import androidx.compose.material.icons.filled.History +import androidx.compose.material.icons.filled.Link +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.PointOfSale +import androidx.compose.material.icons.filled.QrCode import androidx.compose.material.icons.filled.Sync import androidx.compose.material.icons.filled.Wallet - import androidx.compose.material3.Card - import androidx.compose.material3.CardDefaults - import androidx.compose.material3.HorizontalDivider - import androidx.compose.material3.Icon - import androidx.compose.material3.AlertDialog - import androidx.compose.material3.ModalDrawerSheet - import androidx.compose.material3.ModalNavigationDrawer - import androidx.compose.material3.NavigationDrawerItem - import androidx.compose.material3.NavigationDrawerItemDefaults - import androidx.compose.material3.Scaffold - 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.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ModalDrawerSheet +import androidx.compose.material3.ModalNavigationDrawer +import androidx.compose.material3.NavigationDrawerItem +import androidx.compose.material3.NavigationDrawerItemDefaults +import androidx.compose.material3.Scaffold +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.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.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight - import androidx.compose.ui.text.style.TextOverflow - import androidx.compose.ui.unit.dp - import androidx.compose.ui.unit.sp +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel import coil3.compose.AsyncImage +import com.mob.utsmyanmar.R import com.mob.utsmyanmar.ui.components.appbar.AppBar +import com.mob.utsmyanmar.ui.device_info.DeviceInfoViewModel import com.mob.utsmyanmar.ui.preview.P2Preview import com.mob.utsmyanmar.ui.theme.Color +import com.sunmi.pay.hardware.aidl.AidlConstants +import com.utsmyanmar.baselib.BaseApplication import com.utsmyanmar.paylibs.sign_on.EchoTestProcess import com.utsmyanmar.paylibs.sign_on.SignOnListener import kotlinx.coroutines.delay @@ -75,20 +83,31 @@ import kotlinx.coroutines.launch @Composable fun DashboardScreen2( onNavigateAmount: (String) -> Unit = {}, - onNavigateSignOn: () -> Unit = {} + onNavigateSignOn: () -> Unit = {}, + deviceInfoViewModel: DeviceInfoViewModel = viewModel() ) { - val drawerState = rememberDrawerState(initialValue = androidx.compose.material3.DrawerValue.Closed) + val deviceInfo by deviceInfoViewModel.uiState.collectAsState() + + LaunchedEffect(Unit) { + deviceInfoViewModel.loadDeviceInfo(); + } + val drawerState = rememberDrawerState(initialValue = androidx.compose.material3.DrawerValue.Open) //for preview +// val drawerState = rememberDrawerState(initialValue = androidx.compose.material3.DrawerValue.Closed) //for normal usage 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("") } + + 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 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 @@ -149,7 +168,8 @@ fun DashboardScreen2( isHostActionRunning = false mainHandler.post { isHostActionRunning = false - dialogMessage = failureMessage(activeHostAction, resultCode) + dialogMessage = + failureMessage(activeHostAction, resultCode) } } } @@ -190,365 +210,382 @@ fun DashboardScreen2( 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.LegacyRed) - .padding(horizontal = 20.dp, vertical = 28.dp) - ) { - Text( - text = "MOBPOS", - color = Color.White, - fontSize = 22.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(6.dp)) - Text( - text = "Quick navigation", - color = Color.White.copy(alpha = 0.85f), - fontSize = 13.sp - ) - } - - Spacer(modifier = Modifier.height(10.dp)) - DrawerItem("Log-On", Icons.Default.Dashboard) { - scope.launch { drawerState.close() } - openHostActionDialog("Log-On") - } - DrawerItem("Log-Off", Icons.Default.Dashboard) { - scope.launch { drawerState.close() } - openHostActionDialog("Log-Off") - } - DrawerItem("Sale", Icons.Default.PointOfSale) { - scope.launch { drawerState.close() } - onNavigateAmount("Sale") - } - DrawerItem("Sign On", Icons.Default.Link) { - scope.launch { drawerState.close() } - onNavigateSignOn() - } - DrawerItem("Settlement", Icons.Default.Wallet) { - scope.launch { drawerState.close() } - } - DrawerItem("History", Icons.Default.History) { - scope.launch { drawerState.close() } - } - } - } - ) { - Scaffold( - containerColor = Color.IvoryBeige, - topBar = { - AppBar( - title = "Dashboard", - icon = Icons.Default.Menu, - onIconClick = { scope.launch { drawerState.open() } } - ) - } - ) { paddingValues -> + ModalNavigationDrawer( + drawerState = drawerState, + drawerContent = { + ModalDrawerSheet( + modifier = Modifier.fillMaxWidth(0.78f), + drawerContainerColor = Color.White, + drawerShape = RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) + ) { Column( modifier = Modifier - .padding(paddingValues) - .fillMaxSize() -// .padding(horizontal = 16.dp) + .fillMaxWidth() + .background(Color.IvoryBeige) + .padding(horizontal = 20.dp, vertical = 28.dp) ) { - AdvertisingArea() - SummaryCard() - Spacer(modifier = Modifier.height(16.dp)) - MenuGrid( - onNavigateAmount = onNavigateAmount, - onNavigateSignOn = onNavigateSignOn - ) + 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)) + + DrawerItem("Log-On", Icons.Default.Dashboard) { + scope.launch { drawerState.close() } + openHostActionDialog("Log-On") + } + DrawerItem("Log-Off", Icons.Default.Dashboard) { + scope.launch { drawerState.close() } + openHostActionDialog("Log-Off") } } } - } - - @Composable - private fun DrawerItem( - title: String, - icon: ImageVector, - onClick: () -> Unit ) { - NavigationDrawerItem( - label = { - Text( - text = title, - fontWeight = FontWeight.Medium + Scaffold( + containerColor = Color.IvoryBeige, + topBar = { + AppBar( + title = "Dashboard", + icon = Icons.Default.Menu, + onIconClick = { scope.launch { drawerState.open() } } ) - }, - selected = false, - onClick = onClick, - icon = { - Icon( - imageVector = icon, - contentDescription = title + } + ) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize() +// .padding(horizontal = 16.dp) + ) { + AdvertisingArea() + SummaryCard() + Spacer(modifier = Modifier.height(16.dp)) + MenuGrid( + onNavigateAmount = onNavigateAmount, + onNavigateSignOn = onNavigateSignOn ) - }, - modifier = Modifier.padding(horizontal = 12.dp, vertical = 2.dp), - colors = NavigationDrawerItemDefaults.colors( - unselectedContainerColor = androidx.compose.ui.graphics.Color.Transparent, - unselectedIconColor = Color.LegacyRed, - unselectedTextColor = Color.Black + } + } + } +} + +@Composable +private fun DrawerItem( + title: String, + icon: ImageVector, + onClick: () -> Unit +) { + NavigationDrawerItem( + label = { + Text( + text = title, + fontWeight = FontWeight.Medium ) + }, + selected = false, + onClick = onClick, + icon = { + Icon( + imageVector = icon, + contentDescription = title + ) + }, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 2.dp), + colors = NavigationDrawerItemDefaults.colors( + unselectedContainerColor = androidx.compose.ui.graphics.Color.Transparent, + unselectedIconColor = Color.LegacyRed, + unselectedTextColor = Color.Black + ) + ) +} + +@Composable +private fun AdvertisingArea() { + + val imageArray = listOf( + "https://i.ytimg.com/vi/eRUVxGRp1Ms/maxresdefault.jpg", + "https://sunmi.ua/wp-content/themes/yootheme/cache/04/p6-3-en-04a68bb5.jpeg", + "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) + val nextPage = (pageState.currentPage + 1) % imageArray.size; + + pageState.animateScrollToPage( + page = nextPage, + animationSpec = tween(durationMillis = 700) + ) + } + } + + Card( + modifier = Modifier + .fillMaxWidth() + .height(170.dp), + 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) ) } - - @Composable - private fun AdvertisingArea() { - - val imageArray = listOf( - "https://i.ytimg.com/vi/eRUVxGRp1Ms/maxresdefault.jpg", - "https://sunmi.ua/wp-content/themes/yootheme/cache/04/p6-3-en-04a68bb5.jpeg", - "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) - val nextPage = (pageState.currentPage + 1) % imageArray.size; - - pageState.animateScrollToPage( - page = nextPage, - animationSpec = tween(durationMillis = 700) - ) - } - } - - Card( - modifier = Modifier.fillMaxWidth().height(170.dp), - 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 +@Composable +private fun MenuGrid( + onNavigateAmount: (String) -> Unit, + onNavigateSignOn: () -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(10.dp), + modifier = Modifier.padding(horizontal = 16.dp) ) { - 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) + Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { + MenuCard( + title = "Sale", + icon = Icons.Default.PointOfSale, + modifier = Modifier.weight(1f), + onClick = { onNavigateAmount("Sale") } + ) + MenuCard("MMQR", Icons.Default.QrCode, Modifier.weight(1f)) + MenuCard("History", Icons.Default.History, Modifier.weight(1f)) + } + + Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { + MenuCard( + "Sign On", + Icons.Default.Link, + Modifier.weight(1f), + onClick = onNavigateSignOn + ) + MenuCard("Settlement", Icons.Default.Wallet, Modifier.weight(1f)) + MenuCard("See More", Icons.Default.GridView, Modifier.weight(1f)) } } +} - @Composable - private fun IconCircle( - icon: ImageVector, - color: androidx.compose.ui.graphics.Color +@Composable +private fun MenuCard( + title: String, + icon: ImageVector, + 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 - .size(38.dp) - .clip(CircleShape) - .background(color.copy(alpha = 0.1f)), - contentAlignment = Alignment.Center + .fillMaxSize() + .padding(6.dp) ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = color, - modifier = Modifier.size(22.dp) - ) - } - } + Column { + Icon( + imageVector = icon, + contentDescription = title, + tint = Color.LegacyRed, + modifier = Modifier.size(50.dp) + ) - @Composable - private fun MenuGrid( - onNavigateAmount: (String) -> Unit, - onNavigateSignOn: () -> Unit - ) { - Column( - verticalArrangement = Arrangement.spacedBy(10.dp), - modifier = Modifier.padding(horizontal = 16.dp) - ) { - Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { - MenuCard( - title = "Sale", - icon = Icons.Default.PointOfSale, - modifier = Modifier.weight(1f), - onClick = { onNavigateAmount("Sale") } - ) - MenuCard("MMQR", Icons.Default.QrCode, Modifier.weight(1f)) - MenuCard("History", Icons.Default.History, Modifier.weight(1f)) - } - - Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { - MenuCard( - "Sign On", - Icons.Default.Link, - Modifier.weight(1f), - onClick = onNavigateSignOn - ) - MenuCard("Settlement", Icons.Default.Wallet, Modifier.weight(1f)) - MenuCard("See More", Icons.Default.GridView, Modifier.weight(1f)) - } - } - } - - @Composable - private fun MenuCard( - title: String, - icon: ImageVector, - 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( - imageVector = icon, - contentDescription = title, - tint = Color.LegacyRed, - modifier = Modifier.size(50.dp) + 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) ) - - 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) - ) - } } } } } - - @P2Preview - @Composable - fun PreviewDashboardScreen2() { - DashboardScreen2() - } +} + +@P2Preview +@Composable +fun PreviewDashboardScreen2() { + DashboardScreen2() +} diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoUiState.kt b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoUiState.kt new file mode 100644 index 0000000..42e7e5e --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoUiState.kt @@ -0,0 +1,11 @@ +package com.mob.utsmyanmar.ui.device_info + +data class DeviceInfoUiState( + val hardwareVersion: String = "", + val firmwareVersion: String = "", + val serialNumber: String = "", + val deviceModel: String = "", + val finalVersion: String = "", + val isLoading: Boolean = false, + val errorMessage: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt new file mode 100644 index 0000000..1ce39ed --- /dev/null +++ b/app/src/main/java/com/mob/utsmyanmar/ui/device_info/DeviceInfoViewModel.kt @@ -0,0 +1,52 @@ +package com.mob.utsmyanmar.ui.device_info + +import androidx.lifecycle.ViewModel +import com.sunmi.pay.hardware.aidl.AidlConstants +import com.utsmyanmar.baselib.BaseApplication +import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class DeviceInfoViewModel : ViewModel() { + + private val _uiState = MutableStateFlow(DeviceInfoUiState()) + val uiState = _uiState.asStateFlow() + + fun loadDeviceInfo() { + _uiState.value = _uiState.value.copy(isLoading = true) + + try { + val hardwareVersion = getParams(AidlConstants.SysParam.HARDWARE_VERSION) + val firmwareVersion = getParams(AidlConstants.SysParam.FIRMWARE_VERSION) + val serialNo = getParams(AidlConstants.SysParam.SN) + val deviceModel = getParams(AidlConstants.SysParam.DEVICE_MODEL) + val finalVersion = SystemParamsOperation.getInstance().finalVersion ?: "" + + _uiState.value = DeviceInfoUiState( + hardwareVersion = hardwareVersion, + firmwareVersion = firmwareVersion, + serialNumber = serialNo, + deviceModel = deviceModel, + finalVersion = finalVersion, + isLoading = false + ) + + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + isLoading = false, + errorMessage = e.message ?: "Failed to load device info" + ) + } + } + + private fun getParams(name: String): String { + return try { + BaseApplication.getInstance() + .basicOptBinder + ?.getSysParam(name) + ?: "" + } catch (e: Exception) { + "" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/theme/Color.kt b/app/src/main/java/com/mob/utsmyanmar/ui/theme/Color.kt index ddfdb0e..d9611f1 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/theme/Color.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/theme/Color.kt @@ -22,4 +22,5 @@ object Color { val Black = Color(0xFF000000) val Gray = Color(0xFF898989) val Success = Color(0xFF007E33) + val Error = Color(0xFFCD2029) } \ No newline at end of file