diff --git a/app/src/main/java/com/example/buspayment/realtimeDB/repository/DBRepository.kt b/app/src/main/java/com/example/buspayment/realtimeDB/repository/DBRepository.kt index c24b253..53fda8b 100644 --- a/app/src/main/java/com/example/buspayment/realtimeDB/repository/DBRepository.kt +++ b/app/src/main/java/com/example/buspayment/realtimeDB/repository/DBRepository.kt @@ -7,7 +7,7 @@ import android.util.Log import com.example.buspayment.funtions.NotificationService import com.example.buspayment.realtimeDB.responses.RealtimeBusResponse import com.example.buspayment.realtimeDB.responses.RealtimeDistanceResponse -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.responses.RealtimeUserResponse import com.example.buspayment.utils.ResultState import com.google.firebase.database.ChildEventListener @@ -51,19 +51,21 @@ class DBRepository @Inject constructor( } - override fun getConductorPaymentList(email: String): Flow>> = + override fun getConductorPaymentList(email: String): Flow>> = callbackFlow { trySend(ResultState.Loading) val valueEvent = object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { - val payment = snapshot.children.map { - RealtimeUserHistoryResponse( - it.getValue(RealtimeUserHistoryResponse.PaymentResponse::class.java), - key = it.key - ) + snapshot.children.map { item -> + val payment = item.children.map { + RealtimePaymentResponse( + it.getValue(RealtimePaymentResponse.PaymentResponse::class.java), + key = it.key + ) + } + trySend(ResultState.Success(payment)) } - trySend(ResultState.Success(payment)) } override fun onCancelled(error: DatabaseError) { @@ -72,22 +74,22 @@ class DBRepository @Inject constructor( } - db.child("conductorPaymentHistory").child(email).addValueEventListener(valueEvent) + db.child("paymentList").addValueEventListener(valueEvent) awaitClose { - db.child("conductorPaymentHistory").child(email).removeEventListener(valueEvent) + db.child("paymentList").removeEventListener(valueEvent) close() } } - override fun getPaymentHistoryByUser(email: String): Flow>> = + override fun getPaymentHistoryByUser(email: String): Flow>> = callbackFlow { trySend(ResultState.Loading) val valueEvent = object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val payment = snapshot.children.map { - RealtimeUserHistoryResponse( - it.getValue(RealtimeUserHistoryResponse.PaymentResponse::class.java), + RealtimePaymentResponse( + it.getValue(RealtimePaymentResponse.PaymentResponse::class.java), key = it.key ) } @@ -207,7 +209,10 @@ class DBRepository @Inject constructor( } } - override fun updatePayment(res: RealtimeUserHistoryResponse): Flow> = + override fun updatePayment( + email: String, + res: RealtimePaymentResponse + ): Flow> = callbackFlow { trySend(ResultState.Loading) val newUser = HashMap() @@ -218,7 +223,7 @@ class DBRepository @Inject constructor( newUser["paid"] = res.payment.paid!! newUser["bus"] = res.payment.bus!! newUser["status"] = res.payment.status!! - db.child("userPaymentList").child(res.key!!).updateChildren( + db.child("paymentList").child(email).child(res.key!!).updateChildren( newUser ).addOnCompleteListener { trySend(ResultState.Success("Data updated successfully")) @@ -231,12 +236,22 @@ class DBRepository @Inject constructor( } override fun submitPayment( - payment: RealtimeUserHistoryResponse.PaymentResponse, - email: String + payment: RealtimePaymentResponse.PaymentResponse, + from: String, + to: String ): Flow> = callbackFlow { trySend(ResultState.Loading) - db.child("paymentList").child(email).push().setValue( + db.child("paymentList").child(from).push().setValue( + payment + ).addOnCompleteListener { + if (it.isSuccessful) + trySend(ResultState.Success("Payment successful")) + } + .addOnFailureListener { + trySend(ResultState.Failure(it)) + } + db.child("conductorPaymentList").child(to).push().setValue( payment ).addOnCompleteListener { if (it.isSuccessful) diff --git a/app/src/main/java/com/example/buspayment/realtimeDB/repository/Repository.kt b/app/src/main/java/com/example/buspayment/realtimeDB/repository/Repository.kt index 13fd766..6e84b2e 100644 --- a/app/src/main/java/com/example/buspayment/realtimeDB/repository/Repository.kt +++ b/app/src/main/java/com/example/buspayment/realtimeDB/repository/Repository.kt @@ -2,7 +2,7 @@ package com.example.buspayment.realtimeDB.repository import com.example.buspayment.realtimeDB.responses.RealtimeBusResponse import com.example.buspayment.realtimeDB.responses.RealtimeDistanceResponse -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.responses.RealtimeUserResponse import com.example.buspayment.utils.ResultState import kotlinx.coroutines.flow.Flow @@ -17,13 +17,14 @@ interface Repository { fun getDistance(): Flow>> fun updateBalance(pay: Double, userId: String): Flow> fun submitPayment( - payment: RealtimeUserHistoryResponse.PaymentResponse, - email: String + payment: RealtimePaymentResponse.PaymentResponse, + from: String, + to: String ): Flow> - fun getConductorPaymentList(email: String): Flow>> - fun getPaymentHistoryByUser(email: String): Flow>> - fun updatePayment(res: RealtimeUserHistoryResponse): Flow> + fun getConductorPaymentList(email: String): Flow>> + fun getPaymentHistoryByUser(email: String): Flow>> + fun updatePayment(email: String, res: RealtimePaymentResponse): Flow> fun deleteUser( key: String ): Flow> diff --git a/app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimeUserHistoryResponse.kt b/app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimePaymentResponse.kt similarity index 84% rename from app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimeUserHistoryResponse.kt rename to app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimePaymentResponse.kt index 449406f..30714ed 100644 --- a/app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimeUserHistoryResponse.kt +++ b/app/src/main/java/com/example/buspayment/realtimeDB/responses/RealtimePaymentResponse.kt @@ -1,6 +1,6 @@ package com.example.buspayment.realtimeDB.responses -data class RealtimeUserHistoryResponse( +data class RealtimePaymentResponse( val payment: PaymentResponse?, val key: String? = "", ) { @@ -12,5 +12,6 @@ data class RealtimeUserHistoryResponse( val to: String? = "", val paid: Double? = 0.0, val bus: String? = "", + val code: String? = "", ) } diff --git a/app/src/main/java/com/example/buspayment/realtimeDB/ui/RealtimeViewModel.kt b/app/src/main/java/com/example/buspayment/realtimeDB/ui/RealtimeViewModel.kt index c676577..940aa08 100644 --- a/app/src/main/java/com/example/buspayment/realtimeDB/ui/RealtimeViewModel.kt +++ b/app/src/main/java/com/example/buspayment/realtimeDB/ui/RealtimeViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope import com.example.buspayment.realtimeDB.repository.Repository import com.example.buspayment.realtimeDB.responses.RealtimeBusResponse import com.example.buspayment.realtimeDB.responses.RealtimeDistanceResponse -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.responses.RealtimeUserResponse import com.example.buspayment.utils.ResultState import dagger.hilt.android.lifecycle.HiltViewModel @@ -32,8 +32,12 @@ class RealtimeViewModel @Inject constructor( private val _userHisRes: MutableState = mutableStateOf(PaymentState()) val userHisRes: State = _userHisRes fun addUser(users: RealtimeUserResponse.UserResponse) = repo.addUser(users) - fun submitPayment(payment: RealtimeUserHistoryResponse.PaymentResponse, email: String) = - repo.submitPayment(payment, email) + fun submitPayment( + payment: RealtimePaymentResponse.PaymentResponse, + from: String, + to: String + ) = + repo.submitPayment(payment, from, to) fun addBus(bus: RealtimeBusResponse.BusResponse) = repo.addBus(bus) @@ -189,7 +193,9 @@ class RealtimeViewModel @Inject constructor( fun delete(key: String) = repo.deleteUser(key) fun updateUser(user: RealtimeUserResponse) = repo.updateUser(user) - fun updatePayment(payment: RealtimeUserHistoryResponse) = repo.updatePayment(payment) + fun updatePayment(email: String, payment: RealtimePaymentResponse) = + repo.updatePayment(email, payment) + fun updateBalance(pay: Double, userId: String) = repo.updateBalance(pay, userId) } @@ -212,7 +218,7 @@ data class DistState( ) data class PaymentState( - val payment: List = emptyList(), + val payment: List = emptyList(), val error: String = "", val isLoading: Boolean = false ) diff --git a/app/src/main/java/com/example/buspayment/screens/common/SplashScreen.kt b/app/src/main/java/com/example/buspayment/screens/common/SplashScreen.kt index 40a687e..0e3a7dc 100755 --- a/app/src/main/java/com/example/buspayment/screens/common/SplashScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/common/SplashScreen.kt @@ -36,24 +36,24 @@ fun SplashScreen(navController: NavController) { val mUserViewModel: UserViewModel = viewModel(factory = UserViewModel.UserViewModelFactory(context.applicationContext as Application)) user = mUserViewModel.readUser.observeAsState(listOf()).value - LaunchedEffect(true) { + LaunchedEffect(user.isNotEmpty()) { delay(2000) if (user.isNotEmpty()) { // Credentials().setEmail(user[0].email) when (user[0].role) { - "User" -> { + "user" -> { navController.navigate(Screens.UHome.route) { popUpTo(0) } } - "Conductor" -> { + "conductor" -> { navController.navigate(Screens.CHome.route) { popUpTo(0); } } - "Admin" -> { + "admin" -> { navController.navigate(Screens.AHome.route) { popUpTo(0); } diff --git a/app/src/main/java/com/example/buspayment/screens/conductor/PaymentListScreen.kt b/app/src/main/java/com/example/buspayment/screens/conductor/PaymentListScreen.kt index b65f459..6262ecc 100644 --- a/app/src/main/java/com/example/buspayment/screens/conductor/PaymentListScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/conductor/PaymentListScreen.kt @@ -1,5 +1,6 @@ package com.example.buspayment.screens.conductor +import android.app.Application import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -23,16 +24,23 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +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.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController -import com.example.buspayment.funtions.NotificationService -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.data.User +import com.example.buspayment.data.UserViewModel +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.ui.RealtimeViewModel import com.example.buspayment.utils.ResultState import kotlinx.coroutines.launch @@ -43,6 +51,19 @@ fun PaymentListScreen( viewModel: RealtimeViewModel = hiltViewModel() ) { val res = viewModel.payres.value + val context = LocalContext.current + var user by remember { mutableStateOf(listOf()) } + val mUserViewModel: UserViewModel = + viewModel(factory = UserViewModel.UserViewModelFactory(context.applicationContext as Application)) + user = mUserViewModel.readUser.observeAsState(emptyList()).value + var email by remember { mutableStateOf("") } + LaunchedEffect(user) { + if (user.isNotEmpty()) { + email = user[0].email + viewModel.getConductorPaymentList(user[0].email.substringBefore("@")) + } + + } Column(Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) { Row( Modifier @@ -57,12 +78,17 @@ fun PaymentListScreen( navController.popBackStack() }, imageVector = Icons.Filled.ArrowBack, contentDescription = "Back button" ) - Text(text = "Manage buses", style = MaterialTheme.typography.headlineSmall) + Text(text = "Pending payments", style = MaterialTheme.typography.headlineSmall) Text(text = "", style = MaterialTheme.typography.headlineSmall) } Column { if (res.payment.isNotEmpty()) { - val paymentList = res.payment.filter { item -> item.payment!!.status == "Pending" } + val paymentList = + res.payment.filter { item -> + item.payment!!.status == "Pending" && item.payment.toUser == email.substringBefore( + "@" + ) + } LazyColumn() { items( paymentList, @@ -82,101 +108,109 @@ fun PaymentListScreen( @Composable fun PaymentListRow( - itemState: RealtimeUserHistoryResponse, + itemState: RealtimePaymentResponse, viewModel: RealtimeViewModel = hiltViewModel() ) { val scope = rememberCoroutineScope() val context = LocalContext.current - LaunchedEffect(key1 = true) { - NotificationService(context).showNotification("", "") - } Card( modifier = Modifier .fillMaxWidth() .padding(10.dp) ) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - ) { - Text(itemState.payment?.fromUser!!, style = MaterialTheme.typography.bodyLarge) - Text("Time") - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text(itemState.payment.paid!!.toString() + " Taka") - Text("${itemState.payment.from!!} -> ${itemState.payment.to!!}") - } - Row() { - Icon(imageVector = Icons.Filled.Done, contentDescription = "Accept", - modifier = Modifier.clickable { - scope.launch { - viewModel.updatePayment( - RealtimeUserHistoryResponse( - payment = RealtimeUserHistoryResponse.PaymentResponse( - fromUser = itemState.payment.fromUser, - status = "Accepted", - toUser = itemState.payment.toUser, - from = itemState.payment.from, - to = itemState.payment.to, - paid = itemState.payment.paid, - bus = itemState.payment.bus - ), - key = itemState.key - ) - ).collect { - when (it) { - is ResultState.Success -> { - Toast.makeText(context, "Payment accepted", Toast.LENGTH_SHORT).show() - } - - is ResultState.Failure -> { - Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show() - } - - is ResultState.Loading -> { - + Column() { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + Text(itemState.payment?.fromUser!!, style = MaterialTheme.typography.bodyLarge) + Text("Time") + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text(itemState.payment.paid!!.toString() + " Taka") + Text("${itemState.payment.from!!} -> ${itemState.payment.to!!}") + } + Row() { + Icon(imageVector = Icons.Filled.Done, contentDescription = "Accept", + modifier = Modifier.clickable { + scope.launch { + viewModel.updatePayment( + email = itemState.payment.fromUser, + RealtimePaymentResponse( + payment = RealtimePaymentResponse.PaymentResponse( + fromUser = itemState.payment.fromUser, + status = "Accepted", + toUser = itemState.payment.toUser, + from = itemState.payment.from, + to = itemState.payment.to, + paid = itemState.payment.paid, + bus = itemState.payment.bus + ), + key = itemState.key + ) + ).collect { + when (it) { + is ResultState.Success -> { + Toast.makeText(context, "Payment accepted", Toast.LENGTH_SHORT).show() + } + + is ResultState.Failure -> { + Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show() + } + + is ResultState.Loading -> { + + } } } } } - } - ) - Icon(imageVector = Icons.Filled.Close, contentDescription = "Reject", - modifier = Modifier.clickable { - scope.launch { - viewModel.updatePayment( - RealtimeUserHistoryResponse( - payment = RealtimeUserHistoryResponse.PaymentResponse( - fromUser = itemState.payment.fromUser, - status = "Rejected", - toUser = itemState.payment.toUser, - from = itemState.payment.from, - to = itemState.payment.to, - paid = itemState.payment.paid, - bus = itemState.payment.bus - ), - key = itemState.key - ) - ).collect { - when (it) { - is ResultState.Success -> { - Toast.makeText(context, "Payment rejected", Toast.LENGTH_SHORT).show() - } - - is ResultState.Failure -> { - Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show() - } - - is ResultState.Loading -> { - + ) + Icon(imageVector = Icons.Filled.Close, contentDescription = "Reject", + modifier = Modifier.clickable { + scope.launch { + viewModel.updatePayment( + email = itemState.payment.fromUser, + RealtimePaymentResponse( + payment = RealtimePaymentResponse.PaymentResponse( + fromUser = itemState.payment.fromUser, + status = "Rejected", + toUser = itemState.payment.toUser, + from = itemState.payment.from, + to = itemState.payment.to, + paid = itemState.payment.paid, + bus = itemState.payment.bus + ), + key = itemState.key + ) + ).collect { + when (it) { + is ResultState.Success -> { + Toast.makeText(context, "Payment rejected", Toast.LENGTH_SHORT).show() + } + + is ResultState.Failure -> { + Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show() + } + + is ResultState.Loading -> { + + } } } } } - } - ) + ) + } + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) + { + Text(text = itemState.payment!!.code!!, style = MaterialTheme.typography.headlineMedium) } } } diff --git a/app/src/main/java/com/example/buspayment/screens/user/RechargeScreen.kt b/app/src/main/java/com/example/buspayment/screens/user/RechargeScreen.kt index ba63a19..593756f 100644 --- a/app/src/main/java/com/example/buspayment/screens/user/RechargeScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/user/RechargeScreen.kt @@ -1,5 +1,7 @@ package com.example.buspayment.screens.user +import android.app.Application +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -18,15 +20,38 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +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.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController +import com.example.buspayment.data.User +import com.example.buspayment.data.UserViewModel +import com.example.buspayment.realtimeDB.ui.RealtimeViewModel +import com.example.buspayment.utils.ResultState +import kotlinx.coroutines.launch @Composable -fun RechargeScreen(navController: NavController) { +fun RechargeScreen( + navController: NavController, + viewModel: RealtimeViewModel = hiltViewModel() +) { + val context = LocalContext.current + var user by remember { mutableStateOf(listOf()) } + val mUserViewModel: UserViewModel = + viewModel(factory = UserViewModel.UserViewModelFactory(context.applicationContext as Application)) + user = mUserViewModel.readUser.observeAsState(emptyList()).value + val scope = rememberCoroutineScope() Column(Modifier.fillMaxSize()) { Row( Modifier @@ -55,6 +80,29 @@ fun RechargeScreen(navController: NavController) { Modifier .height(200.dp) .width(200.dp) + .clickable { + scope.launch { + viewModel + .updateBalance(50.0, user[0].email.substringBefore("@")) + .collect { response -> + when (response) { + is ResultState.Success -> { + Toast + .makeText(context, "Payment successful", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Failure -> { + Toast + .makeText(context, "Failed", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Loading -> {} + } + } + } + } ) { Text( "50 taka", @@ -67,6 +115,29 @@ fun RechargeScreen(navController: NavController) { Modifier .height(200.dp) .width(200.dp) + .clickable { + scope.launch { + viewModel + .updateBalance(100.0, user[0].email.substringBefore("@")) + .collect { response -> + when (response) { + is ResultState.Success -> { + Toast + .makeText(context, "Payment successful", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Failure -> { + Toast + .makeText(context, "Failed", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Loading -> {} + } + } + } + } ) { Text( "100 taka", @@ -80,6 +151,29 @@ fun RechargeScreen(navController: NavController) { Modifier .height(200.dp) .width(200.dp) + .clickable { + scope.launch { + viewModel + .updateBalance(500.0, user[0].email.substringBefore("@")) + .collect { response -> + when (response) { + is ResultState.Success -> { + Toast + .makeText(context, "Payment successful", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Failure -> { + Toast + .makeText(context, "Failed", Toast.LENGTH_SHORT) + .show() + } + + is ResultState.Loading -> {} + } + } + } + } ) { Text( "500 taka", diff --git a/app/src/main/java/com/example/buspayment/screens/user/ScanScreen.kt b/app/src/main/java/com/example/buspayment/screens/user/ScanScreen.kt index b270dd2..971bb47 100755 --- a/app/src/main/java/com/example/buspayment/screens/user/ScanScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/user/ScanScreen.kt @@ -66,7 +66,7 @@ import com.example.buspayment.data.User import com.example.buspayment.data.UserViewModel import com.example.buspayment.funtions.QrCodeAnalysis import com.example.buspayment.navigations.Screens -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.ui.RealtimeViewModel import com.example.buspayment.ui.theme.Typography import com.example.buspayment.utils.ResultState @@ -74,6 +74,7 @@ import com.google.android.gms.location.LocationServices import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlin.math.abs +import kotlin.random.Random @Composable fun ScanScreen( @@ -90,6 +91,7 @@ fun ScanScreen( viewModel(factory = UserViewModel.UserViewModelFactory(context.applicationContext as Application)) user = mUserViewModel.readUser.observeAsState(listOf()).value var code by remember { mutableStateOf("") } + var busName by remember { mutableStateOf("") } var isExpanded by remember { mutableStateOf(false) } var isToExpanded by remember { mutableStateOf(false) } val lifeCycleOwner = LocalLifecycleOwner.current @@ -111,9 +113,16 @@ fun ScanScreen( toList.add(item.dist.name) } } + LaunchedEffect(code) { + buses.bus.map { item -> + if (code == item.bus!!.id) { + busName = item.bus.name + } + } + } if (buses.bus.isNotEmpty()) { buses.bus.forEach { item -> - busList.add(item.bus!!.name) + busList.add(item.bus!!.id) } } if (fromList.isNotEmpty() && toList.isNotEmpty()) { @@ -159,7 +168,7 @@ fun ScanScreen( verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxSize() ) { - if (code in busList) { + if (busName.isNotEmpty()) { Card( modifier = Modifier .width(300.dp) @@ -258,15 +267,17 @@ fun ScanScreen( onClick = { scope.launch(Dispatchers.Main) { viewModel.submitPayment( - RealtimeUserHistoryResponse.PaymentResponse( + RealtimePaymentResponse.PaymentResponse( "Pending", from = selectedFrom, to = selectedTo, - fromUser = user[0].email, - toUser = "robinsrk3@gmail.com", + fromUser = user[0].email.substringBefore("@"), + toUser = code, paid = price, - bus = code, - ), email = "123" + bus = busName, + code = Random.nextInt(1000, 10000).toString() +// code = java.util.Random().nextInt(9999 - 1001) + 1000.toString(), + ), from = user[0].email.substringBefore("@"), to = code ).collect { response -> when (response) { is ResultState.Success -> { @@ -282,7 +293,7 @@ fun ScanScreen( } } scope.launch(Dispatchers.Main) { - viewModel.updateBalance(price, user[0].email.substringBefore("@")) + viewModel.updateBalance(-price, user[0].email.substringBefore("@")) .collect { response -> when (response) { is ResultState.Success -> { diff --git a/app/src/main/java/com/example/buspayment/screens/user/UserHistoryScreen.kt b/app/src/main/java/com/example/buspayment/screens/user/UserHistoryScreen.kt index af4dcd7..a3f797d 100644 --- a/app/src/main/java/com/example/buspayment/screens/user/UserHistoryScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/user/UserHistoryScreen.kt @@ -14,6 +14,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Done +import androidx.compose.material.icons.filled.HourglassBottom +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon @@ -36,7 +40,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import com.example.buspayment.data.User import com.example.buspayment.data.UserViewModel -import com.example.buspayment.realtimeDB.responses.RealtimeUserHistoryResponse +import com.example.buspayment.realtimeDB.responses.RealtimePaymentResponse import com.example.buspayment.realtimeDB.ui.RealtimeViewModel @Composable @@ -53,8 +57,9 @@ fun UserHistoryScreen( if (user.isNotEmpty()) { email = user[0].email } - LaunchedEffect(key1 = true) { - viewModel.getPaymentHistoryByUser(email = "123") + LaunchedEffect(key1 = user) { + if (email.isNotEmpty()) + viewModel.getPaymentHistoryByUser(email.substringBefore("@")) } val history = viewModel.userHisRes.value Column(Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) { @@ -93,12 +98,16 @@ fun UserHistoryScreen( @Composable fun HistoryRow( - itemState: RealtimeUserHistoryResponse.PaymentResponse + itemState: RealtimePaymentResponse.PaymentResponse ) { + var alert by remember { mutableStateOf(false) } Card( modifier = Modifier .fillMaxWidth() .padding(10.dp) + .clickable { + alert = true + } ) { Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -113,7 +122,34 @@ fun HistoryRow( Text(itemState.paid!!.toString() + " Taka") Text("${itemState.from!!} -> ${itemState.to!!}") } - Text(itemState.status!!) + when (itemState.status) { + "Accepted" -> { + Icon(imageVector = Icons.Filled.Done, contentDescription = "Accepted", tint = Color.Green) + } + + "Rejected" -> Icon( + imageVector = Icons.Filled.Close, + contentDescription = "Accepted", + tint = Color.Red + ) + + else -> Icon( + imageVector = Icons.Filled.HourglassBottom, + contentDescription = "Accepted", + ) + } + } + if (alert) { + AlertDialog( + onDismissRequest = { alert = false }, + confirmButton = { Text(text = "Done", modifier = Modifier.clickable { alert = false }) }, + title = { + Text( + itemState.code!!, + style = MaterialTheme.typography.headlineLarge + ) + }) } + } } diff --git a/app/src/main/java/com/example/buspayment/screens/user/UserHomeScreen.kt b/app/src/main/java/com/example/buspayment/screens/user/UserHomeScreen.kt index 9aad09c..5403420 100755 --- a/app/src/main/java/com/example/buspayment/screens/user/UserHomeScreen.kt +++ b/app/src/main/java/com/example/buspayment/screens/user/UserHomeScreen.kt @@ -1,6 +1,11 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + package com.example.buspayment.screens.user import android.app.Application +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.LinearOutSlowInEasing +import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -8,10 +13,15 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Person +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ElevatedAssistChip +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton @@ -38,7 +48,6 @@ import com.example.buspayment.data.UserViewModel import com.example.buspayment.navigations.Screens import com.example.buspayment.realtimeDB.ui.RealtimeViewModel import com.example.buspayment.ui.theme.LogoImage -import kotlinx.coroutines.delay @Composable fun UserHomeScreen( @@ -52,8 +61,7 @@ fun UserHomeScreen( val mUserViewModel: UserViewModel = viewModel(factory = UserViewModel.UserViewModelFactory(context.applicationContext as Application)) user = mUserViewModel.readUser.observeAsState(emptyList()).value - LaunchedEffect(key1 = true) { - delay(100) + LaunchedEffect(key1 = user) { if (user.isNotEmpty()) { viewModel.getUser(user[0].email) } @@ -74,10 +82,37 @@ fun UserHomeScreen( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Row { - Text( - text = "Balance $balance", - Modifier.clickable { navController.navigate(Screens.Recharge.route) }) + Row( + modifier = Modifier.animateContentSize( + animationSpec = tween( + durationMillis = 500, + easing = LinearOutSlowInEasing + ) + ) + ) { + ElevatedAssistChip(onClick = { navController.navigate(Screens.Recharge.route) }, label = { + Row( + modifier = Modifier.animateContentSize( + animationSpec = tween( + durationMillis = 500, + easing = LinearOutSlowInEasing + ), + ), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Balance " + ) + if (users.isLoading) { + CircularProgressIndicator( + modifier = Modifier + .height(16.dp) + .width(16.dp) + ) + } else Text("$balance") + + } + }) } Text("", style = MaterialTheme.typography.headlineSmall) Row {