melhorando tela de testes

This commit is contained in:
Ighor Moura 2025-07-23 17:42:10 -04:00
parent 427c75b93c
commit 79515f1205
4 changed files with 93 additions and 46 deletions

View File

@ -1,6 +1,8 @@
package com.example.mypos.models package com.example.mypos.models
import android.content.Context import android.content.Context
import android.nfc.Tag
import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -20,6 +22,7 @@ class PaymentViewModel(
private val aditumSdkService: AditumSdkService private val aditumSdkService: AditumSdkService
) : ViewModel() { ) : ViewModel() {
private val paymentApplication = application private val paymentApplication = application
private val TAG = "PaymentViewModel"
private val _isServiceConnected = MutableStateFlow(false) private val _isServiceConnected = MutableStateFlow(false)
val isServiceConnected: StateFlow<Boolean> = _isServiceConnected.asStateFlow() val isServiceConnected: StateFlow<Boolean> = _isServiceConnected.asStateFlow()
@ -35,7 +38,12 @@ class PaymentViewModel(
transactionStatus: TransactionStatus?, transactionStatus: TransactionStatus?,
command: AbecsCommands? command: AbecsCommands?
) { ) {
TODO("Not yet implemented") val notificationMessage = when (command) {
AbecsCommands.Display -> "Exibindo mensagem: $message"
AbecsCommands.GetPin -> "Aguardando digitação do PIN"
else -> message ?: "Processando..."
}
Log.d(TAG, notificationMessage)
} }
} }
) )

View File

@ -1,8 +1,10 @@
package com.example.mypos.screen package com.example.mypos.screen
import android.os.Handler
import androidx.compose.foundation.text.KeyboardOptions import android.os.Looper
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -14,39 +16,28 @@ import br.com.aditum.data.v2.enums.PaymentType
import com.example.mypos.BuildConfig import com.example.mypos.BuildConfig
import com.example.mypos.models.PaymentViewModel import com.example.mypos.models.PaymentViewModel
import com.example.mypos.services.AditumSdkService import com.example.mypos.services.AditumSdkService
import com.example.mypos.services.PaymentApplication
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@Composable @Composable
fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkService) { fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkService) {
val context = LocalContext.current val context = LocalContext.current
var amount by remember { mutableStateOf("") } var amount by remember { mutableStateOf("") }
var installments by remember { mutableStateOf("1") }
var paymentType by remember { mutableStateOf(PaymentType.Credit) } var paymentType by remember { mutableStateOf(PaymentType.Credit) }
var isServiceConnected by remember { mutableStateOf(false) } val isServiceConnected by viewModel.isServiceConnected.collectAsState()
var message by remember { mutableStateOf("") } val message by aditumSdkService.messageFlow.collectAsState()
var pinLength by remember { mutableStateOf(0) } val pinLength by aditumSdkService.pinLengthFlow.collectAsState()
var isInitializing by remember { mutableStateOf(false) } var isInitializing by remember { mutableStateOf(false) }
var isPaying by remember { mutableStateOf(false) } var isPaying by remember { mutableStateOf(false) }
var showLoading by remember { mutableStateOf(false) }
val handler = remember { Handler(Looper.getMainLooper()) }
LaunchedEffect(Unit) {
viewModel.isServiceConnected.collectLatest { connected ->
isServiceConnected = connected
}
}
if (showLoading) {
LaunchedEffect(Unit) { LoadingScreen(
aditumSdkService.messageFlow.collectLatest { msg -> message = message,
message = msg onDismiss = { showLoading = false }
} )
}
LaunchedEffect(Unit) {
aditumSdkService.pinLengthFlow.collectLatest { length ->
pinLength = length
}
} }
Column( Column(
@ -61,37 +52,44 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
style = MaterialTheme.typography.headlineMedium style = MaterialTheme.typography.headlineMedium
) )
Text( Text(
text = if (isServiceConnected) "Serviço Conectado" else "Serviço Desconectado", text = if (isServiceConnected) "Serviço Conectado" else "Serviço Desconectado",
color = if (isServiceConnected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error color = if (isServiceConnected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.error
) )
Button( Button(
onClick = { onClick = {
if (!isServiceConnected) { if (!isServiceConnected) {
viewModel.startService() viewModel.startService()
Toast.makeText(context, "Tentando conectar ao serviço...", Toast.LENGTH_SHORT).show() handler.post {
Toast.makeText(context, "Tentando conectar ao serviço...", Toast.LENGTH_SHORT).show()
}
return@Button return@Button
} }
if (!isInitializing) { if (!isInitializing) {
isInitializing = true isInitializing = true
showLoading = true
aditumSdkService.initAditumSdk( aditumSdkService.initAditumSdk(
applicationName = "MyPOS", applicationName = "MyPOS",
applicationVersion = "1.0.0", applicationVersion = "1.0.0",
activationCode = BuildConfig.ACTIVATION_CODE, activationCode = BuildConfig.ACTIVATION_CODE,
resolve = { success -> resolve = { success ->
isInitializing = false isInitializing = false
Toast.makeText( showLoading = false
context, handler.post {
if (success) "SDK inicializado com sucesso!" else "Falha na inicialização.", Toast.makeText(
Toast.LENGTH_LONG context,
).show() if (success) "SDK inicializado com sucesso!" else "Falha na inicialização.",
Toast.LENGTH_LONG
).show()
}
}, },
reject = { errorCode, errorMessage -> reject = { errorCode, errorMessage ->
isInitializing = false isInitializing = false
Toast.makeText(context, "Erro: $errorMessage", Toast.LENGTH_LONG).show() showLoading = false
handler.post {
Toast.makeText(context, "Erro: $errorMessage", Toast.LENGTH_LONG).show()
}
} }
) )
} }
@ -102,7 +100,6 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
Text(if (isInitializing) "Inicializando..." else "Inicializar SDK") Text(if (isInitializing) "Inicializando..." else "Inicializar SDK")
} }
OutlinedTextField( OutlinedTextField(
value = amount, value = amount,
onValueChange = { amount = it.filter { char -> char.isDigit() || char == '.' } }, onValueChange = { amount = it.filter { char -> char.isDigit() || char == '.' } },
@ -111,7 +108,15 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
OutlinedTextField(
value = installments,
onValueChange = { installments = it.filter { char -> char.isDigit() } },
label = { Text("Quantidade de Parcelas") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.fillMaxWidth(),
enabled = paymentType == PaymentType.Credit
)
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly horizontalArrangement = Arrangement.SpaceEvenly
@ -132,31 +137,43 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
} }
} }
Button( Button(
onClick = { onClick = {
val amountValue = amount.toDoubleOrNull()?.times(100)?.toLong() val amountValue = amount.toDoubleOrNull()?.times(100)?.toLong()
val installmentCount = installments.toIntOrNull() ?: 1
if (amountValue == null || amountValue <= 0) { if (amountValue == null || amountValue <= 0) {
Toast.makeText(context, "Insira um valor válido", Toast.LENGTH_SHORT).show() handler.post {
Toast.makeText(context, "Insira um valor válido", Toast.LENGTH_SHORT).show()
}
return@Button return@Button
} }
if (!isServiceConnected) { if (!isServiceConnected) {
Toast.makeText(context, "Serviço não conectado", Toast.LENGTH_SHORT).show() handler.post {
Toast.makeText(context, "Serviço não conectado", Toast.LENGTH_SHORT).show()
}
return@Button return@Button
} }
if (!isPaying) { if (!isPaying) {
isPaying = true isPaying = true
showLoading = true
aditumSdkService.pay( aditumSdkService.pay(
amount = amountValue, amount = amountValue,
installments = if (paymentType == PaymentType.Credit) installmentCount else null,
paymentType = paymentType, paymentType = paymentType,
allowContactless = true, allowContactless = true,
resolve = { response -> resolve = { response ->
isPaying = false isPaying = false
Toast.makeText(context, "Pagamento realizado com sucesso!", Toast.LENGTH_LONG).show() showLoading = false
handler.post {
Toast.makeText(context, "Pagamento realizado com sucesso!", Toast.LENGTH_LONG).show()
}
}, },
reject = { errorCode, errorMessage -> reject = { errorCode, errorMessage ->
isPaying = false isPaying = false
Toast.makeText(context, "Erro no pagamento: $errorMessage", Toast.LENGTH_LONG).show() showLoading = false
handler.post {
Toast.makeText(context, "Erro no pagamento: $errorMessage", Toast.LENGTH_LONG).show()
}
} }
) )
} }
@ -167,15 +184,13 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
Text(if (isPaying) "Processando Pagamento..." else "Realizar Pagamento") Text(if (isPaying) "Processando Pagamento..." else "Realizar Pagamento")
} }
if (message.isNotEmpty() && !showLoading) {
if (message.isNotEmpty()) {
Text( Text(
text = "Mensagem do PIN pad: $message", text = "Mensagem do PIN pad: $message",
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium
) )
} }
if (pinLength > 0) { if (pinLength > 0) {
Text( Text(
text = "Comprimento do PIN: $pinLength", text = "Comprimento do PIN: $pinLength",
@ -183,4 +198,28 @@ fun PaymentScreen(viewModel: PaymentViewModel, aditumSdkService: AditumSdkServic
) )
} }
} }
}
@Composable
fun LoadingScreen(message: String, onDismiss: () -> Unit) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background.copy(alpha = 0.8f)),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier
.background(MaterialTheme.colorScheme.surface)
.padding(16.dp)
) {
CircularProgressIndicator()
Text(
text = message.ifEmpty { "Processando..." },
style = MaterialTheme.typography.bodyLarge
)
}
}
} }

View File

@ -207,7 +207,7 @@ class AditumSdkService(private val paymentApplication: PaymentApplication) {
override fun onResponse(paymentResponse: PaymentResponse?) { override fun onResponse(paymentResponse: PaymentResponse?) {
if (paymentResponse != null) { if (paymentResponse != null) {
val json = gson.toJson(paymentResponse) val json = gson.toJson(paymentResponse)
Log.e(TAG, "onResponse - $json") Log.d(TAG, "onResponse - $json")
resolve(paymentResponse) resolve(paymentResponse)
} else { } else {
Log.e(TAG, "onResponse - paymentResponse is null") Log.e(TAG, "onResponse - paymentResponse is null")

View File

@ -19,11 +19,11 @@ import kotlinx.coroutines.withContext
class PaymentApplication : Application() { class PaymentApplication : Application() {
companion object { companion object {
private const val TAG = "PaymentApplication"
private const val PACKAGE_BASE_NAME = "br.com.aditum" private const val PACKAGE_BASE_NAME = "br.com.aditum"
const val PACKAGE_NAME = "$PACKAGE_BASE_NAME.smartpostef" const val PACKAGE_NAME = "$PACKAGE_BASE_NAME.smartpostef"
const val ACTION_COMMUNICATION_SERVICE = "$PACKAGE_BASE_NAME.AditumSdkService" const val ACTION_COMMUNICATION_SERVICE = "$PACKAGE_BASE_NAME.AditumSdkService"
} }
private val TAG = "PaymentApplication"
private val _isServiceConnectedFlow = MutableStateFlow(false) private val _isServiceConnectedFlow = MutableStateFlow(false)
val isServiceConnectedFlow: StateFlow<Boolean> = _isServiceConnectedFlow.asStateFlow() val isServiceConnectedFlow: StateFlow<Boolean> = _isServiceConnectedFlow.asStateFlow()