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.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,9 +83,16 @@ 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) }
@ -85,10 +100,14 @@ fun DashboardScreen2(
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)
}
}
}
@ -202,21 +222,48 @@ fun DashboardScreen2(
Column(
modifier = Modifier
.fillMaxWidth()
.background(Color.LegacyRed)
.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 = "MOBPOS",
color = Color.White,
fontSize = 22.sp,
text = "MOB Merchant",
color = Color.CrimsonRed,
fontSize = 12.sp,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(6.dp))
Text(
text = "Quick navigation",
color = Color.White.copy(alpha = 0.85f),
fontSize = 13.sp
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))
@ -229,20 +276,6 @@ fun DashboardScreen2(
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() }
}
}
}
) {
@ -272,14 +305,14 @@ fun DashboardScreen2(
}
}
}
}
}
@Composable
private fun DrawerItem(
@Composable
private fun DrawerItem(
title: String,
icon: ImageVector,
onClick: () -> Unit
) {
) {
NavigationDrawerItem(
label = {
Text(
@ -302,20 +335,20 @@ fun DashboardScreen2(
unselectedTextColor = Color.Black
)
)
}
}
@Composable
private fun AdvertisingArea() {
@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})
val pageState = rememberPagerState(pageCount = { imageArray.size })
LaunchedEffect(pageState) {
while (true){
while (true) {
delay(10000)
val nextPage = (pageState.currentPage + 1) % imageArray.size;
@ -327,7 +360,9 @@ fun DashboardScreen2(
}
Card(
modifier = Modifier.fillMaxWidth().height(170.dp),
modifier = Modifier
.fillMaxWidth()
.height(170.dp),
shape = RoundedCornerShape(0.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
) {
@ -344,12 +379,14 @@ fun DashboardScreen2(
)
}
}
}
}
@Composable
private fun SummaryCard() {
@Composable
private fun SummaryCard() {
Card(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
elevation = CardDefaults.cardElevation(4.dp)
@ -405,16 +442,16 @@ fun DashboardScreen2(
}
}
}
}
}
@Composable
private fun SummaryItem(
@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)
@ -431,13 +468,13 @@ fun DashboardScreen2(
}
IconCircle(icon, iconBg)
}
}
}
@Composable
private fun IconCircle(
@Composable
private fun IconCircle(
icon: ImageVector,
color: androidx.compose.ui.graphics.Color
) {
) {
Box(
modifier = Modifier
.size(38.dp)
@ -452,13 +489,13 @@ fun DashboardScreen2(
modifier = Modifier.size(22.dp)
)
}
}
}
@Composable
private fun MenuGrid(
@Composable
private fun MenuGrid(
onNavigateAmount: (String) -> Unit,
onNavigateSignOn: () -> Unit
) {
) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier.padding(horizontal = 16.dp)
@ -485,15 +522,15 @@ fun DashboardScreen2(
MenuCard("See More", Icons.Default.GridView, Modifier.weight(1f))
}
}
}
}
@Composable
private fun MenuCard(
@Composable
private fun MenuCard(
title: String,
icon: ImageVector,
modifier: Modifier = Modifier,
onClick: (() -> Unit)? = null
) {
) {
Card(
modifier = modifier
.height(100.dp)
@ -545,10 +582,10 @@ fun DashboardScreen2(
}
}
}
}
}
@P2Preview
@Composable
fun PreviewDashboardScreen2() {
@P2Preview
@Composable
fun PreviewDashboardScreen2() {
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 Gray = Color(0xFF898989)
val Success = Color(0xFF007E33)
val Error = Color(0xFFCD2029)
}