sidebar profile added

This commit is contained in:
moon 2026-05-21 21:27:13 +06:30
parent 57dcd13c34
commit 675e398aaf
4 changed files with 486 additions and 385 deletions

View File

@ -3,70 +3,78 @@ package com.mob.utsmyanmar.ui.dashboard
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BarChart import androidx.compose.material.icons.filled.BarChart
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.ChevronRight import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.Dashboard import androidx.compose.material.icons.filled.Dashboard
import androidx.compose.material.icons.filled.GridView import androidx.compose.material.icons.filled.GridView
import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.filled.Link import androidx.compose.material.icons.filled.Link
import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.PointOfSale import androidx.compose.material.icons.filled.PointOfSale
import androidx.compose.material.icons.filled.QrCode import androidx.compose.material.icons.filled.QrCode
import androidx.compose.material.icons.filled.Sync import androidx.compose.material.icons.filled.Sync
import androidx.compose.material.icons.filled.Wallet import androidx.compose.material.icons.filled.Wallet
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ModalDrawerSheet import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.NavigationDrawerItemDefaults import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.VerticalDivider import androidx.compose.material3.VerticalDivider
import androidx.compose.material3.rememberDrawerState import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.mob.utsmyanmar.R
import com.mob.utsmyanmar.ui.components.appbar.AppBar 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.preview.P2Preview
import com.mob.utsmyanmar.ui.theme.Color 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.EchoTestProcess
import com.utsmyanmar.paylibs.sign_on.SignOnListener import com.utsmyanmar.paylibs.sign_on.SignOnListener
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -75,9 +83,16 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun DashboardScreen2( fun DashboardScreen2(
onNavigateAmount: (String) -> Unit = {}, 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 scope = rememberCoroutineScope()
val mainHandler = remember { Handler(Looper.getMainLooper()) } val mainHandler = remember { Handler(Looper.getMainLooper()) }
var showHostActionDialog by remember { mutableStateOf(false) } var showHostActionDialog by remember { mutableStateOf(false) }
@ -85,10 +100,14 @@ fun DashboardScreen2(
var isHostActionRunning by remember { mutableStateOf(false) } var isHostActionRunning by remember { mutableStateOf(false) }
var dialogMessage by remember { mutableStateOf("") } var dialogMessage by remember { mutableStateOf("") }
val isOnline = true;
fun confirmationMessage(action: String) = "Do you want to start ${action.lowercase()}?" fun confirmationMessage(action: String) = "Do you want to start ${action.lowercase()}?"
fun processingMessage(action: String) = "Sending ${action.lowercase()} request to host..." fun processingMessage(action: String) = "Sending ${action.lowercase()} request to host..."
fun successMessage(action: String) = "$action success." 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 networkFailureMessage(action: String) = "Network error during $action."
fun openHostActionDialog(action: String) { fun openHostActionDialog(action: String) {
activeHostAction = action activeHostAction = action
@ -149,7 +168,8 @@ fun DashboardScreen2(
isHostActionRunning = false isHostActionRunning = false
mainHandler.post { mainHandler.post {
isHostActionRunning = false isHostActionRunning = false
dialogMessage = failureMessage(activeHostAction, resultCode) dialogMessage =
failureMessage(activeHostAction, resultCode)
} }
} }
} }
@ -191,364 +211,381 @@ fun DashboardScreen2(
) )
} }
ModalNavigationDrawer( ModalNavigationDrawer(
drawerState = drawerState, drawerState = drawerState,
drawerContent = { drawerContent = {
ModalDrawerSheet( ModalDrawerSheet(
modifier = Modifier.fillMaxWidth(0.78f), modifier = Modifier.fillMaxWidth(0.78f),
drawerContainerColor = Color.White, drawerContainerColor = Color.White,
drawerShape = RoundedCornerShape(topEnd = 24.dp, bottomEnd = 24.dp) 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 ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(paddingValues) .fillMaxWidth()
.fillMaxSize() .background(Color.IvoryBeige)
// .padding(horizontal = 16.dp) .padding(horizontal = 20.dp, vertical = 28.dp)
) { ) {
AdvertisingArea() Row() {
SummaryCard() Box(
Spacer(modifier = Modifier.height(16.dp)) modifier = Modifier
MenuGrid( .size(80.dp)
onNavigateAmount = onNavigateAmount, .clip(CircleShape)
onNavigateSignOn = onNavigateSignOn .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")
} }
} }
} }
) {
Scaffold(
containerColor = Color.IvoryBeige,
topBar = {
AppBar(
title = "Dashboard",
icon = Icons.Default.Menu,
onIconClick = { scope.launch { drawerState.open() } }
)
}
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
// .padding(horizontal = 16.dp)
) {
AdvertisingArea()
SummaryCard()
Spacer(modifier = Modifier.height(16.dp))
MenuGrid(
onNavigateAmount = onNavigateAmount,
onNavigateSignOn = onNavigateSignOn
)
}
}
}
}
@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)
)
}
} }
@Composable Card(
private fun DrawerItem( modifier = Modifier
title: String, .fillMaxWidth()
icon: ImageVector, .height(170.dp),
onClick: () -> Unit shape = RoundedCornerShape(0.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
) { ) {
NavigationDrawerItem( HorizontalPager(
label = { state = pageState,
Text( modifier = Modifier
text = title, .fillMaxSize()
fontWeight = FontWeight.Medium ) { page ->
) AsyncImage(
}, model = imageArray[page],
selected = false, contentDescription = "ads images",
onClick = onClick, modifier = Modifier.fillMaxSize(),
icon = { contentScale = ContentScale.Crop
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 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 @Composable
private fun AdvertisingArea() { private fun MenuGrid(
onNavigateAmount: (String) -> Unit,
val imageArray = listOf( onNavigateSignOn: () -> Unit
"https://i.ytimg.com/vi/eRUVxGRp1Ms/maxresdefault.jpg", ) {
"https://sunmi.ua/wp-content/themes/yootheme/cache/04/p6-3-en-04a68bb5.jpeg", Column(
"https://mma.prnewswire.com/media/2080956/SUNMI_3rd_generation_products_T3_PRO_series_V3_MIX.jpg?p=facebook" verticalArrangement = Arrangement.spacedBy(10.dp),
); modifier = Modifier.padding(horizontal = 16.dp)
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( Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
verticalAlignment = Alignment.Top, MenuCard(
modifier = Modifier.padding(6.dp) title = "Sale",
) { icon = Icons.Default.PointOfSale,
Column(modifier = Modifier.weight(1f)) { modifier = Modifier.weight(1f),
Text(title, fontSize = 12.sp) onClick = { onNavigateAmount("Sale") }
Text( )
value, MenuCard("MMQR", Icons.Default.QrCode, Modifier.weight(1f))
fontSize = 14.sp, MenuCard("History", Icons.Default.History, Modifier.weight(1f))
color = Color.LegacyRed, }
fontWeight = FontWeight.Bold
) Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
Text(subtitle, fontSize = 12.sp) MenuCard(
} "Sign On",
IconCircle(icon, iconBg) 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 @Composable
private fun IconCircle( private fun MenuCard(
icon: ImageVector, title: String,
color: androidx.compose.ui.graphics.Color 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( Box(
modifier = Modifier modifier = Modifier
.size(38.dp) .fillMaxSize()
.clip(CircleShape) .padding(6.dp)
.background(color.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) { ) {
Icon( Column {
imageVector = icon, Icon(
contentDescription = null, imageVector = icon,
tint = color, contentDescription = title,
modifier = Modifier.size(22.dp) 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)) { Spacer(modifier = Modifier.weight(1f))
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 Row(
private fun MenuCard( modifier = Modifier.fillMaxWidth(),
title: String, verticalAlignment = Alignment.CenterVertically
icon: ImageVector, ) {
modifier: Modifier = Modifier, Text(
onClick: (() -> Unit)? = null text = title,
) { fontSize = 12.sp,
Card( color = Color.Black,
modifier = modifier overflow = TextOverflow.Ellipsis,
.height(100.dp) maxLines = 1,
.then( modifier = Modifier.weight(1f)
if (onClick != null) { )
Modifier.clickable(onClick = onClick) Icon(
} else { imageVector = Icons.Default.ChevronRight,
Modifier contentDescription = null,
} tint = Color.LegacyRed,
), modifier = Modifier.size(28.dp)
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)
)
}
} }
} }
} }
} }
}
@P2Preview @P2Preview
@Composable @Composable
fun PreviewDashboardScreen2() { fun PreviewDashboardScreen2() {
DashboardScreen2() DashboardScreen2()
} }

View File

@ -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
)

View File

@ -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) {
""
}
}
}

View File

@ -22,4 +22,5 @@ object Color {
val Black = Color(0xFF000000) val Black = Color(0xFF000000)
val Gray = Color(0xFF898989) val Gray = Color(0xFF898989)
val Success = Color(0xFF007E33) val Success = Color(0xFF007E33)
val Error = Color(0xFFCD2029)
} }