add views models and drop func to interfaces

This commit is contained in:
andrew 2023-12-08 13:25:12 +04:00
parent e5adf214b7
commit 5a9c56f573
38 changed files with 1282 additions and 706 deletions

View File

@ -0,0 +1,14 @@
package com.example.testapp
import android.app.Application
import com.example.testapp.room.AppContainer
import com.example.testapp.room.AppDataContainer
class CryptoDealApplication : Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
container = AppDataContainer(this)
}
}

View File

@ -2,26 +2,19 @@ package com.example.testapp
import android.annotation.SuppressLint
import android.os.Bundle
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.annotation.RequiresApi
import androidx.navigation.compose.rememberNavController
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.RootNavigationGraph
import com.example.testapp.ui.theme.TestAppTheme
import org.w3c.dom.Text
import com.example.testapp.viewModels.CurrentUserViewModel
class MainActivity : ComponentActivity() {
private val sharedViewModel: SharedViewModel by viewModels()
private val currentUserViewModel: CurrentUserViewModel by viewModels()
@RequiresApi(34)
@SuppressLint("MissingInflatedId", "SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -29,7 +22,7 @@ class MainActivity : ComponentActivity() {
TestAppTheme {
RootNavigationGraph(
navController = rememberNavController(),
sharedViewModel = sharedViewModel
currentUserViewModel = currentUserViewModel
)
}
}

View File

@ -5,25 +5,42 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.navigation
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.screensMobile.EntryScreen
import com.example.testapp.screensMobile.RegisterScreen
import com.example.testapp.screensMobile.authScreens.EntryScreen
import com.example.testapp.screensMobile.authScreens.RegisterScreen
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.EntryScreenViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel
fun NavGraphBuilder.authNavGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
fun NavGraphBuilder.authNavGraph(
navController: NavHostController,
currentUserViewModel: CurrentUserViewModel,
entryScreenViewModel: EntryScreenViewModel,
registrationScreenViewModel: RegistrationScreenViewModel
) {
navigation(
route=Graph.AUTHENTICATION,
route = Graph.AUTHENTICATION,
startDestination = AuthScreen.Entry.route
){
composable(route=AuthScreen.Entry.route){
EntryScreen(navController = navController, modifier = Modifier, sharedViewModel = sharedViewModel)
) {
composable(route = AuthScreen.Entry.route) {
EntryScreen(
navController,
Modifier,
currentUserViewModel,
entryScreenViewModel
)
}
composable(route=AuthScreen.Register.route){
RegisterScreen(navController = navController, modifier = Modifier, sharedViewModel = sharedViewModel)
composable(route = AuthScreen.Register.route) {
RegisterScreen(
navController,
Modifier,
currentUserViewModel,
registrationScreenViewModel
)
}
}
}
sealed class AuthScreen(val route: String){
object Entry : AuthScreen(route="ENTRY")
object Register : AuthScreen(route="REGISTER")
sealed class AuthScreen(val route: String) {
object Entry : AuthScreen(route = "ENTRY")
object Register : AuthScreen(route = "REGISTER")
}

View File

@ -1,44 +1,72 @@
package com.example.testapp.graphs
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.screensMobile.AccountPage
import com.example.testapp.screensMobile.CreateDeal
import com.example.testapp.screensMobile.DealList
import com.example.testapp.screensMobile.History
import com.example.testapp.screensMobile.Wallet
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.WalletViewModel
@RequiresApi(34)
@Composable
fun HomeNavGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
fun HomeNavGraph(
navController: NavHostController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
NavHost(
navController = navController,
route = Graph.MAIN,
startDestination = BottomBarScreen.Wallet.route
){
composable(route=BottomBarScreen.Wallet.route){
Wallet(sharedViewModel = sharedViewModel)
) {
composable(route = BottomBarScreen.Wallet.route) {
Wallet(
navController = navController,
currentUserViewModel = currentUserViewModel,
walletViewModel = walletViewModel
)
}
composable(route=BottomBarScreen.Profile.route){
AccountPage(sharedViewModel = sharedViewModel, navController = navController)
composable(route = BottomBarScreen.Profile.route) {
AccountPage(
navController = navController,
currentUserViewModel = currentUserViewModel
)
}
composable(route=BottomBarScreen.Deals.route){
DealList(navController = navController, sharedViewModel = sharedViewModel)
composable(route = BottomBarScreen.Deals.route) {
DealList(
navController = navController,
currentUserViewModel = currentUserViewModel,
dealListViewModel = dealListViewModel
)
}
composable(route=BottomBarScreen.CDEAL.route) {
CreateDeal(sharedViewModel = sharedViewModel, navController = navController)
composable(route = BottomBarScreen.CDEAL.route) {
CreateDeal(
navController = navController,
currentUserViewModel = currentUserViewModel,
dealCreateViewModel = dealCreateViewModel
)
}
composable(route=BottomBarScreen.History.route){
History(sharedViewModel = sharedViewModel)
composable(route = BottomBarScreen.History.route) {
History(
navController = navController,
currentUserViewModel = currentUserViewModel,
historyViewModel = historyViewModel
)
}
}
}

View File

@ -1,42 +1,71 @@
package com.example.testapp.graphs
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.screensMobile.LoadScreen
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.EntryScreenViewModel
import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel
import com.example.testapp.viewModels.WalletViewModel
const val USERID_ARGUMENT="userId"
const val USERID_ARGUMENT = "userId"
@RequiresApi(34)
@Composable
fun RootNavigationGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
fun RootNavigationGraph(
navController: NavHostController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
entryScreenViewModel: EntryScreenViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
registrationScreenViewModel: RegistrationScreenViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
NavHost(
navController=navController,
navController = navController,
route = Graph.ROOT,
startDestination = Graph.AUTHENTICATION
){
authNavGraph(navController=navController,sharedViewModel)
composable(route=Graph.MAIN,
arguments = listOf(navArgument(USERID_ARGUMENT){
type= NavType.StringType
})){
LoadScreen(sharedViewModel = sharedViewModel)
) {
authNavGraph(
navController = navController,
currentUserViewModel,
entryScreenViewModel,
registrationScreenViewModel
)
composable(
route = Graph.MAIN,
arguments = listOf(navArgument(USERID_ARGUMENT) {
type = NavType.StringType
})
) {
LoadScreen(
currentUserViewModel = currentUserViewModel,
dealCreateViewModel = dealCreateViewModel,
dealListViewModel = dealListViewModel,
historyViewModel = historyViewModel,
walletViewModel = walletViewModel
)
}
}
}
object Graph{
const val ROOT="root_graph"
const val AUTHENTICATION="auth_graph"
const val MAIN="main_graph/{$USERID_ARGUMENT}"
object Graph {
const val ROOT = "root_graph"
const val AUTHENTICATION = "auth_graph"
const val MAIN = "main_graph/{$USERID_ARGUMENT}"
fun passUserId(userId: String): String{
fun passUserId(userId: String): String {
return "main_graph/$userId"
}
}

View File

@ -0,0 +1,40 @@
package com.example.testapp.room
import android.content.Context
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import com.example.testapp.room.repository.basic.UserRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
import com.example.testapp.room.repository.offline.OfflineCoinRepository
import com.example.testapp.room.repository.offline.OfflineDealRepository
import com.example.testapp.room.repository.offline.OfflineUserRepository
import com.example.testapp.room.repository.offline.OfflineWalletItemRepository
interface AppContainer {
val userRepository: UserRepository
val dealRepository: DealRepository
val coinRepository: CoinRepository
val walletItemRepository: WalletItemRepository
}
class AppDataContainer(
private val context: Context
) : AppContainer {
companion object {
const val TIMEOUT = 5000L
}
override val userRepository: UserRepository by lazy {
OfflineUserRepository(CryptoDealDb.getInstance(context).userDao())
}
override val dealRepository: DealRepository by lazy {
OfflineDealRepository(CryptoDealDb.getInstance(context).dealDao())
}
override val coinRepository: CoinRepository by lazy {
OfflineCoinRepository(CryptoDealDb.getInstance(context).coinDao())
}
override val walletItemRepository: WalletItemRepository by lazy {
OfflineWalletItemRepository(CryptoDealDb.getInstance(context).walletItemDao())
}
}

View File

@ -1,21 +1,12 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.testapp.room.models.Coin
import kotlinx.coroutines.flow.Flow
@Dao
interface CoinDao{
interface CoinDao : IDao<Coin> {
@Query("select * from coin")
fun getAll(): Flow<List<Coin>>
@Insert
suspend fun insert(obj: Coin)
@Update
suspend fun update(obj: Coin)
@Delete
suspend fun delete(obj: Coin)
}

View File

@ -1,24 +1,18 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import kotlinx.coroutines.flow.Flow
@Dao
interface DealDao{
interface DealDao : IDao<Deal> {
@Query("select * from deal")
fun getAll(): Flow<List<Deal>>
@Query("select * from deal ORDER BY id DESC LIMIT :limit OFFSET :offset")
fun getAll(limit: Int, offset: Int): List<Deal>
@Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser")
fun getUserDeals(idUser: Int): Flow<List<Deal>>
@Insert
suspend fun insert(obj: Deal)
@Update
suspend fun update(obj: Deal)
@Delete
suspend fun delete(obj: Deal)
}

View File

@ -0,0 +1,18 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Update
@Dao
interface IDao<T> {
@Insert
suspend fun insert(obj: T)
@Update
suspend fun update(obj: T)
@Delete
suspend fun delete(obj: T)
}

View File

@ -1,29 +1,23 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
@Dao
interface UserDao {
interface UserDao : IDao<User> {
@Query("select * from user")
fun getAll(): Flow<List<User>>
@Query("select * from user where user.id = :idUser")
fun getUserById(idUser: Int): Flow<User>
@Query("select * from walletitem where walletitem.userId = :idUser")
fun getUserWallet(idUser: Int): Flow<List<WalletItem>>
@Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser")
fun getUserDeals(idUser: Int): Flow<List<Deal>>
@Insert
fun insert(obj: User)
@Update
fun update(obj: User)
@Delete
fun delete(obj: User)
}

View File

@ -1,23 +1,15 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
@Dao
interface WalletItemDao {
interface WalletItemDao : IDao<WalletItem> {
@Query("select * from walletitem")
fun getAll(): Flow<List<WalletItem>>
@Insert
suspend fun insert(obj: WalletItem)
@Update
suspend fun update(obj: WalletItem)
@Delete
suspend fun delete(obj: WalletItem)
@Query("select * from walletitem where walletitem.userId = :id")
fun getUserWallet(id: Int): Flow<List<WalletItem>>
}

View File

@ -0,0 +1,38 @@
package com.example.testapp.room.pagination
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.testapp.room.dao.DealDao
import com.example.testapp.room.models.Deal
import kotlinx.coroutines.delay
class DealPagination(
private val dao: DealDao
) : PagingSource<Int, Deal>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Deal> {
val page = params.key ?: 0
return try {
Log.d("MainPagingSource", "load: $page")
val entities = dao.getAll(params.loadSize, page * params.loadSize)
if (page != 0) delay(1000)
LoadResult.Page(
data = entities,
prevKey = if (page == 0) null else page - 1,
nextKey = if (entities.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override val jumpingSupported: Boolean = true
override fun getRefreshKey(state: PagingState<Int, Deal>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
}

View File

@ -0,0 +1,6 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.Coin
interface CoinRepository : IRepository<Coin> {
}

View File

@ -0,0 +1,9 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.Deal
import kotlinx.coroutines.flow.Flow
interface DealRepository : IRepository<Deal> {
fun getUserDeals(id: Int): Flow<List<Deal>>
fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean
}

View File

@ -0,0 +1,12 @@
package com.example.testapp.room.repository.basic
import kotlinx.coroutines.flow.Flow
interface IRepository<T> {
suspend fun insert(x: T)
suspend fun update(x: T)
suspend fun delete(x: T)
fun getAll(): Flow<List<T>>
fun getById(id: Int): Flow<T>
fun getAll(limit: Int, offset: Int): List<T>
}

View File

@ -0,0 +1,11 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface UserRepository : IRepository<User> {
fun getUserWallet(id: Int): Flow<List<WalletItem>>
fun getUserDeals(id: Int): Flow<List<Deal>>
}

View File

@ -0,0 +1,8 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface WalletItemRepository : IRepository<WalletItem> {
fun getUserWallet(id: Int): Flow<List<WalletItem>>
}

View File

@ -0,0 +1,14 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.CoinDao
import com.example.testapp.room.models.Coin
import com.example.testapp.room.repository.basic.CoinRepository
import kotlinx.coroutines.flow.Flow
class OfflineCoinRepository(
private val coinDao: CoinDao
) : OfflineRepository<Coin>(coinDao), CoinRepository {
override fun getAll(): Flow<List<Coin>> = coinDao.getAll()
override fun getAll(limit: Int, offset: Int): List<Coin> = throw NotImplementedError()
override fun getById(id: Int): Flow<Coin> = throw NotImplementedError()
}

View File

@ -0,0 +1,43 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.DealDao
import com.example.testapp.room.models.Deal
import com.example.testapp.room.repository.basic.DealRepository
import kotlinx.coroutines.flow.Flow
class OfflineDealRepository(
private val dealDao: DealDao
) : OfflineRepository<Deal>(dealDao), DealRepository {
override fun getAll(): Flow<List<Deal>> = dealDao.getAll()
override fun getAll(limit: Int, offset: Int) = dealDao.getAll(limit, offset)
override fun getById(id: Int): Flow<Deal> = throw NotImplementedError()
override fun getUserDeals(id: Int): Flow<List<Deal>> = dealDao.getUserDeals(id)
override fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean {
// val userRepository = UserRepository()
// val buyer = deal.buyerId?.let { userRepository.getById(it) }
// val seller = userRepository.getById(id)
//
// val coin = seller.wallet[deal.sellerCoin]
// if (coin != null && coin >= deal.countSell) {
// if (buyer != null) {
// if (buyer.wallet.containsKey(deal.sellerCoin))
// buyer.wallet[deal.sellerCoin] = buyer.wallet[deal.sellerCoin]!! + deal.countSell
// else buyer.wallet[deal.sellerCoin] = deal.countSell
// buyer.wallet[deal.buyerCoin] = buyer.wallet[deal.buyerCoin]!! - deal.countBuy
// }
// seller.wallet[deal.sellerCoin] = seller.wallet[deal.sellerCoin]!! - deal.countSell
// if (seller.wallet.containsKey(deal.buyerCoin))
// seller.wallet[deal.buyerCoin] = seller.wallet[deal.buyerCoin]!! + deal.countBuy
// else seller.wallet[deal.buyerCoin] = deal.countSell
// }
// deal.date = LocalDateTime.now()
// deal.sellerId = id
// DealRepository().update(deal)
// navController.navigate(BottomBarScreen.Deals.route) {
// popUpTo(navController.graph.findStartDestination().id)
// launchSingleTop = true
// }
return true;
}
}

View File

@ -0,0 +1,12 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.IDao
import com.example.testapp.room.repository.basic.IRepository
abstract class OfflineRepository<T> (
private val dao: IDao<T>
) : IRepository<T> {
override suspend fun insert(x: T) = dao.insert(x)
override suspend fun update(x: T) = dao.update(x)
override suspend fun delete(x: T) = dao.delete(x)
}

View File

@ -0,0 +1,18 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.UserDao
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.Flow
class OfflineUserRepository(
private val userDao: UserDao
) : OfflineRepository<User>(userDao), UserRepository {
override fun getAll(): Flow<List<User>> = userDao.getAll()
override fun getAll(limit: Int, offset: Int) = throw NotImplementedError()
override fun getById(id: Int): Flow<User> = userDao.getUserById(id)
override fun getUserWallet(id: Int): Flow<List<WalletItem>> = userDao.getUserWallet(id)
override fun getUserDeals(id: Int): Flow<List<Deal>> = userDao.getUserDeals(id)
}

View File

@ -0,0 +1,15 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.WalletItemDao
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.flow.Flow
class OfflineWalletItemRepository(
private val walletItemDao: WalletItemDao
) : OfflineRepository<WalletItem>(walletItemDao), WalletItemRepository {
override fun getUserWallet(id: Int): Flow<List<WalletItem>> = walletItemDao.getUserWallet(id)
override fun getAll(): Flow<List<WalletItem>> = walletItemDao.getAll()
override fun getAll(limit: Int, offset: Int): List<WalletItem> = throw NotImplementedError()
override fun getById(id: Int): Flow<WalletItem> = throw NotImplementedError()
}

View File

@ -19,44 +19,36 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun AccountPage(modifier: Modifier = Modifier, sharedViewModel: SharedViewModel, navController: NavController) {
val argument = sharedViewModel.argument.value
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
var user: User? = null;
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).userDao().getUserById(argument!!.toInt()).collect { data ->
user = data
}
}
fun AccountPage(
modifier: Modifier = Modifier,
navController: NavController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val user by remember { mutableStateOf(currentUserViewModel.user) }
val coroutineScope = rememberCoroutineScope()
Box(
modifier = modifier
@ -86,7 +78,9 @@ fun AccountPage(modifier: Modifier = Modifier, sharedViewModel: SharedViewModel,
if (user != null) {
Container(
name = user!!.email.substring(0, 2),
modifier = Modifier.align(alignment = Alignment.TopStart).offset(15.dp, 15.dp)
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(15.dp, 15.dp)
)
}
}
@ -107,13 +101,16 @@ fun AccountPage(modifier: Modifier = Modifier, sharedViewModel: SharedViewModel,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
Box(
modifier = Modifier
.requiredWidth(width = 17.dp)
.requiredHeight(height = 4.dp))
.requiredHeight(height = 4.dp)
)
}
}
}
@ -135,7 +132,8 @@ fun AccountPage(modifier: Modifier = Modifier, sharedViewModel: SharedViewModel,
.offset(
x = 0.dp,
y = 24.dp
))
)
)
}
}
@ -169,10 +167,12 @@ fun Property1Switch(modifier: Modifier = Modifier) {
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.weight(weight = 1f)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
Viewchecked()
}
}
@ -194,9 +194,11 @@ fun Container(modifier: Modifier = Modifier, name: String) {
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Medium),
fontWeight = FontWeight.Medium
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
@ -216,12 +218,14 @@ fun Viewchecked(modifier: Modifier = Modifier) {
modifier = Modifier
.fillMaxSize()
.clip(shape = RoundedCornerShape(100.dp))
.background(color = Color(0xff4bb2f9)))
.background(color = Color(0xff4bb2f9))
)
Box(
modifier = Modifier
.fillMaxSize()
.clip(shape = CircleShape)
.background(color = Color.White))
.background(color = Color.White)
)
}
}
}
@ -256,10 +260,12 @@ fun Property1Arrow(modifier: Modifier = Modifier) {
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.weight(weight = 1f)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
@ -269,7 +275,7 @@ fun Property1Clear(modifier: Modifier = Modifier, navController: NavController)
modifier = modifier
.fillMaxSize()
.clip(shape = RoundedCornerShape(10.dp))
.clickable{
.clickable {
navController.navigate(route = AuthScreen.Entry.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
@ -302,7 +308,9 @@ fun Property1Clear(modifier: Modifier = Modifier, navController: NavController)
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
}
@ -343,9 +351,11 @@ fun Property1(modifier: Modifier = Modifier) {
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
fontWeight = FontWeight.Medium
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
}
}
}

View File

@ -1,5 +1,6 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -20,11 +21,8 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
@ -33,66 +31,47 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.testapp.designElem.DropDown
import com.example.testapp.designElem.DropDownConfig
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@SuppressLint("UnrememberedMutableState")
@RequiresApi(34)
@Composable
fun CreateDeal(modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel,
navController: NavHostController) {
val argument = sharedViewModel.argument.value
val editDeal: Deal? = sharedViewModel.argument_edit.value as? Deal
val isEdit = editDeal != null
val id = if (isEdit) editDeal?.buyerId else argument?.toInt()
fun CreateDeal(
modifier: Modifier = Modifier,
navController: NavHostController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
dealCreateViewModel.setupLists(currentUserViewModel.user!!.id.toString())
val context = LocalContext.current
val coins = remember { mutableStateListOf<Coin>() }
SideEffect() {
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).coinDao().getAll().collect { data ->
coins.clear()
coins.addAll(data)
}
}
}
val isEdit = dealCreateViewModel.isEdit()
val editDeal: Deal? = dealCreateViewModel.deal
val id = if (isEdit) editDeal?.buyerId else currentUserViewModel.user!!.id
val wallet = remember { mutableStateListOf<WalletItem>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
if (id != null) {
CryptoDealDb.getInstance(context).userDao().getUserWallet(id).collect{data ->
wallet.clear();
wallet.addAll(data);
}
}
}
}
val coins = mutableStateOf(dealCreateViewModel.coins)
val wallet = mutableStateOf(dealCreateViewModel.wallet)
val coinsBuyer = wallet.filter { x -> x.userId == id }.toList()
val coinsBuyer = wallet.value.filter { x -> x.userId == id }.toList()
var coinBuyer by rememberSaveable {
mutableStateOf(if (isEdit) coins.first{y -> y.id == editDeal?.buyerCoinId }.name else coinsBuyer[0])
mutableStateOf(if (isEdit) coins.value.first { y -> y.id == editDeal?.buyerCoinId }.name else coinsBuyer[0])
}
var buyCount by remember {
@ -102,9 +81,10 @@ fun CreateDeal(modifier: Modifier = Modifier,
mutableStateOf(if (isEdit) editDeal?.tip else "")
}
val coinsSeller = wallet.map { x -> coins.first{y -> y.id == x.coinId}.name }.toList()
val coinsSeller =
wallet.value.map { x -> coins.value.first { y -> y.id == x.coinId }.name }.toList()
var coinSeller by rememberSaveable {
mutableStateOf(if (isEdit) coins.first{y -> y.id == editDeal?.sellerCoinId }.name else coinsSeller[0])
mutableStateOf(if (isEdit) coins.value.first { y -> y.id == editDeal?.sellerCoinId }.name else coinsSeller[0])
}
var sellCount by remember {
mutableFloatStateOf(if (isEdit) editDeal?.countSell!! else 0f)
@ -141,7 +121,8 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium)
fontWeight = FontWeight.Medium
)
)
Text(
text = "-",
@ -150,7 +131,8 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 0.83.em,
style = TextStyle(
fontSize = 24.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.clickable {
navController.navigate(route = BottomBarScreen.Deals.route)
@ -165,15 +147,18 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
item {
DropDown(
modifier = Modifier.padding(horizontal = 10.dp),
downConfig = DropDownConfig<String>(
values = coinsBuyer.map { x -> coins.first{y -> y.id == x.coinId}.name }.toList(),
values = coinsBuyer.map { x -> coins.value.first { y -> y.id == x.coinId }.name }
.toList(),
title = "Select coin",
onValueChange = { x -> coinBuyer = x },
selected = coinBuyer as String
@ -184,22 +169,25 @@ fun CreateDeal(modifier: Modifier = Modifier,
OutlinedTextField(
value = buyCount.toString(),
onValueChange = {
val value = coinsBuyer.first{ x -> coinBuyer == coins.first{y -> y.id == x.coinId} }
if (it.toFloatOrNull() != null && it.toFloat() <= value.count) {
buyCount = it.toFloat()
}
val value =
coinsBuyer.first { x -> coinBuyer == coins.value.first { y -> y.id == x.coinId } }
if (it.toFloatOrNull() != null && it.toFloat() <= value.count) {
buyCount = it.toFloat()
}
},
label = {
Text(
text = "Fill count 0 -> ${coinsBuyer.first{ x -> coinBuyer == coins.first{y -> y.id == x.coinId} }.count}",
text = "Fill count 0 -> ${coinsBuyer.first { x -> coinBuyer == coins.value.first { y -> y.id == x.coinId } }.count}",
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
},
modifier = Modifier
.fillMaxWidth()
@ -207,7 +195,8 @@ fun CreateDeal(modifier: Modifier = Modifier,
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
)
)
}
item {
OutlinedTextField(
@ -221,9 +210,11 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
},
modifier = Modifier
.fillMaxWidth()
@ -232,7 +223,8 @@ fun CreateDeal(modifier: Modifier = Modifier,
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
)
)
}
item {
Text(
@ -241,9 +233,11 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
item {
DropDown(
@ -268,9 +262,11 @@ fun CreateDeal(modifier: Modifier = Modifier,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
},
modifier = Modifier
.fillMaxWidth()
@ -278,7 +274,8 @@ fun CreateDeal(modifier: Modifier = Modifier,
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
)
)
}
item {
Button(
@ -288,32 +285,32 @@ fun CreateDeal(modifier: Modifier = Modifier,
id = editDeal?.id,
sellerId = editDeal?.sellerId,
buyerId = id,
buyerCoinId = coins.first { x -> x.name == coinBuyer }.id!!,
buyerCoinId = coins.value.first { x -> x.name == coinBuyer }.id!!,
countBuy = buyCount,
sellerCoinId = coins.first { x -> x.name == coinSeller }.id!!,
sellerCoinId = coins.value.first { x -> x.name == coinSeller }.id!!,
countSell = sellCount,
tip = tip!!,
operation = "Buy",
date = null,
)
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).dealDao().update(deal)
dealCreateViewModel.update(deal)
}
} else {
val deal = Deal(
id = null,
sellerId = null,
buyerId = id,
buyerCoinId = coins.first { x -> x.name == coinBuyer }.id!!,
buyerCoinId = coins.value.first { x -> x.name == coinBuyer }.id!!,
countBuy = buyCount,
sellerCoinId = coins.first { x -> x.name == coinSeller }.id!!,
sellerCoinId = coins.value.first { x -> x.name == coinSeller }.id!!,
countSell = sellCount,
tip = tip!!,
operation = "Buy",
date = null,
)
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).dealDao().insert(deal)
dealCreateViewModel.create(deal)
}
}
navController.navigate(route = BottomBarScreen.Deals.route)
@ -350,7 +347,9 @@ fun CreateDeal(modifier: Modifier = Modifier,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
}
@ -393,23 +392,13 @@ fun CreateDeal(modifier: Modifier = Modifier,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
}
}
}
}
}
@RequiresApi(34)
@Preview
@Composable
private fun Frame20Preview() {
val sharedViewModel = SharedViewModel()
sharedViewModel.setArgument("0")
CreateDeal(Modifier,
navController = rememberNavController(),
sharedViewModel = sharedViewModel
)
}

View File

@ -1,37 +1,28 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -39,73 +30,40 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.testapp.R
import com.example.testapp.designElem.AlertDialogExample
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.Graph
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate
import java.time.LocalDateTime
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun DealList(navController: NavHostController,
sharedViewModel: SharedViewModel,
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier
fun DealList(
modifier: Modifier = Modifier,
navController: NavHostController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val argument = sharedViewModel.argument.value
val id = argument?.toInt()
val id = currentUserViewModel.user!!.id
dealListViewModel.setupLists()
val context = LocalContext.current
val deals = remember { mutableStateListOf<Deal>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).dealDao().getAll().collect { data ->
deals.clear()
deals.addAll(data)
}
}
}
val wallet = remember { mutableStateListOf<WalletItem>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
if (id != null) {
CryptoDealDb.getInstance(context).userDao().getUserWallet(id).collect{data ->
wallet.clear();
wallet.addAll(data);
}
}
}
}
val deals = remember { mutableStateOf(dealListViewModel.deals) }
val coins = remember { mutableStateOf(dealListViewModel.coins) }
val coins = remember { mutableStateListOf<Coin>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).coinDao().getAll().collect { data ->
coins.clear()
coins.addAll(data)
}
}
}
LazyColumn (
LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
@ -117,27 +75,32 @@ fun DealList(navController: NavHostController,
PropertyDeal(navController = navController)
}
item {
deals.filter { x -> x.date == null }.forEach{ x -> Deal(
deal = x,
coins = coins,
modifier = Modifier.padding(vertical = 5.dp),
id = id,
navController = navController,
sharedViewModel = sharedViewModel,
wallet = wallet)}
deals.value.filter { x -> x.date == null }.forEach { x ->
DealItem(
deal = x,
coins = coins.value,
modifier = Modifier.padding(vertical = 5.dp),
id = id,
navController = navController,
dealCreateViewModel = dealCreateViewModel,
dealListViewModel = dealListViewModel
)
}
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun Deal(modifier: Modifier = Modifier,
deal: Deal,
coins: List<Coin>,
id: Int?,
navController: NavHostController,
sharedViewModel: SharedViewModel,
wallet: List<WalletItem>) {
fun DealItem(
modifier: Modifier = Modifier,
deal: Deal,
coins: List<Coin>,
id: Int?,
navController: NavHostController,
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
@ -177,14 +140,16 @@ fun Deal(modifier: Modifier = Modifier,
)
) {
Text(
text = coins.first{x -> x.id == deal.buyerCoinId}.shortName(),
text = coins.first { x -> x.id == deal.buyerCoinId }.shortName(),
color = Color.White,
lineHeight = 1.em,
style = TextStyle(
fontSize = 20.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Text(
text = deal.countBuy.toString(),
@ -193,10 +158,12 @@ fun Deal(modifier: Modifier = Modifier,
lineHeight = 1.em,
style = TextStyle(
fontSize = 20.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Text(
text = deal.tip,
@ -206,11 +173,13 @@ fun Deal(modifier: Modifier = Modifier,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 40.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
Row(
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
@ -225,33 +194,9 @@ fun Deal(modifier: Modifier = Modifier,
Button(
onClick = {
if (id != null && id != deal.buyerId) {
// val userRepository = UserRepository()
// val buyer = deal.buyerId?.let { userRepository.getById(it) }
// val seller = userRepository.getById(id)
//
// val coin = seller.wallet[deal.sellerCoin]
// if (coin != null && coin >= deal.countSell) {
// if (buyer != null) {
// if (buyer.wallet.containsKey(deal.sellerCoin))
// buyer.wallet[deal.sellerCoin] = buyer.wallet[deal.sellerCoin]!! + deal.countSell
// else buyer.wallet[deal.sellerCoin] = deal.countSell
// buyer.wallet[deal.buyerCoin] = buyer.wallet[deal.buyerCoin]!! - deal.countBuy
// }
// seller.wallet[deal.sellerCoin] = seller.wallet[deal.sellerCoin]!! - deal.countSell
// if (seller.wallet.containsKey(deal.buyerCoin))
// seller.wallet[deal.buyerCoin] = seller.wallet[deal.buyerCoin]!! + deal.countBuy
// else seller.wallet[deal.buyerCoin] = deal.countSell
// }
// deal.date = LocalDateTime.now()
// deal.sellerId = id
// DealRepository().update(deal)
// navController.navigate(BottomBarScreen.Deals.route) {
// popUpTo(navController.graph.findStartDestination().id)
// launchSingleTop = true
// }
deal.buyerId?.let { dealListViewModel.submitDeal(deal, id, it) }
} else {
sharedViewModel.setArgumentEdit(deal)
sharedViewModel.setArgumentAdd(wallet, coins)
deal.id?.let { dealCreateViewModel.setupEdit(it) }
navController.navigate(BottomBarScreen.CDEAL.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
@ -265,7 +210,10 @@ fun Deal(modifier: Modifier = Modifier,
.weight(weight = 0.5f)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
horizontalArrangement = Arrangement.spacedBy(
10.dp,
Alignment.CenterHorizontally
),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.requiredWidth(width = 168.dp)
@ -278,9 +226,11 @@ fun Deal(modifier: Modifier = Modifier,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.requiredWidth(width = 29.dp))
.requiredWidth(width = 29.dp)
)
}
}
Row(
@ -294,14 +244,16 @@ fun Deal(modifier: Modifier = Modifier,
.padding(horizontal = 10.dp)
) {
Text(
text = coins.first{x -> x.id == deal.sellerCoinId}.shortName(),
text = coins.first { x -> x.id == deal.sellerCoinId }.shortName(),
color = Color.White,
textAlign = TextAlign.End,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
Text(
text = "${deal.countSell}\n",
color = Color.White,
@ -310,10 +262,12 @@ fun Deal(modifier: Modifier = Modifier,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 20.dp))
.requiredHeight(height = 20.dp)
)
}
}
}
@ -345,7 +299,9 @@ fun PropertyDeal(modifier: Modifier = Modifier, navController: NavHostController
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium))
fontWeight = FontWeight.Medium
)
)
Text(
text = "+",
color = Color(0xff4bb2f9),
@ -353,7 +309,8 @@ fun PropertyDeal(modifier: Modifier = Modifier, navController: NavHostController
lineHeight = 0.83.em,
style = TextStyle(
fontSize = 24.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.clickable {
navController.navigate(BottomBarScreen.CDEAL.route) {

View File

@ -1,189 +0,0 @@
package com.example.testapp.screensMobile
import androidx.compose.foundation.background
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
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.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.testapp.designElem.Btn
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.designElem.btnConfig
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.graphs.Graph
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.User
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
fun isValidEmail(email: String): Boolean {
val emailRegex = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex()
return email.matches(emailRegex)
}
@Composable
fun EntryScreen(navController: NavController,
modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
var emailValue by rememberSaveable { mutableStateOf("") }
var passwordValue by rememberSaveable { mutableStateOf("") }
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
}
Box(
modifier = modifier
.fillMaxSize()
.background(color = Color.White)
) {
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 40.dp)
) {
Text(
text = "Sign On",
color = Color(0xff0b1f33),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Medium),
modifier = Modifier
.fillMaxSize())
}
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp, y = 278.dp)
.padding(start = 5.dp, end = 5.dp)
) {
TextField(
value = emailValue,
onValueChange = { emailValue = it },
label = {
Text(
text = "Email",
color = Color(0xff66727f),
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp)
)
},
placeholder = { Text("Enter email") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth())
TextField(
value = passwordValue,
onValueChange = { passwordValue = it },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
label = {
Text(
text = "Password",
color = Color(0xff66727f),
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp))
},
placeholder = { Text("Enter password") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth())
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 602.dp)
.padding(horizontal = 5.dp,
vertical = 5.dp)
.fillMaxWidth()
) {
Btn(btnConfig = btnConfig(
onClick = {
if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) {
users.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
sharedViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString()))
}
}
}},
text = "Sign In",
color = Color(0xff85c3ff),
offsetX = 0.dp,
offsetY = 0.dp
), modifier = Modifier.fillMaxWidth())
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 656.dp)
.padding(horizontal = 5.dp,
vertical = 5.dp)
.fillMaxWidth()
) {
Btn(btnConfig = btnConfig(
onClick = {
navController.navigate(route = AuthScreen.Register.route)
{
popUpTo(AuthScreen.Register.route)
}
},
text = "Sign On",
color = Color(0xff85c3f3),
offsetX = 0.dp,
offsetY = 0.dp
), modifier = Modifier.fillMaxWidth())
}
}
}

View File

@ -1,6 +1,5 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
@ -18,14 +17,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
@ -34,47 +31,27 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.HistoryViewModel
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun History(navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel
fun History(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val argument = sharedViewModel.argument.value
val id = argument?.toInt()
val context = LocalContext.current
val deals = remember { mutableStateListOf<Deal>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).dealDao().getAll().collect { data ->
deals.clear()
deals.addAll(data)
}
}
}
val coins = remember { mutableStateListOf<Coin>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).coinDao().getAll().collect { data ->
coins.clear()
coins.addAll(data)
}
}
}
var history: List<Deal> = listOf();
if (id != null) {
history = deals.filter { x -> x.buyerId == id || x.sellerId == id }
}
val id = currentUserViewModel.user!!.id
historyViewModel.setArgument(id.toString());
val history = remember { mutableStateOf(historyViewModel.deals) }
val coins = remember { mutableStateOf(historyViewModel.coins) }
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
@ -86,8 +63,14 @@ fun History(navController: NavHostController = rememberNavController(),
.verticalScroll(rememberScrollState())
) {
PropertyHistory()
history.forEach {
x -> HistoryCard(deal = x, modifier = Modifier.padding( vertical = 5.dp, horizontal = 5.dp), coins = coins)
history.value?.forEach { x ->
coins.value?.let {
HistoryCard(
deal = x,
modifier = Modifier.padding(vertical = 5.dp, horizontal = 5.dp),
coins = it
)
}
}
}
}
@ -119,23 +102,31 @@ fun HistoryCard(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
.padding(all = 10.dp)
) {
Text(
text = "-${deal.countSell} ${coins.first{x -> x.id == deal.sellerCoinId}.shortName()}",
text = "-${deal.countSell} ${
coins.first { x -> x.id == deal.sellerCoinId }.shortName()
}",
color = Color(0xfff96161),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
Text(
text = "+${deal.countBuy} ${coins.first{x -> x.id == deal.buyerCoinId}.shortName()}",
text = "+${deal.countBuy} ${
coins.first { x -> x.id == deal.buyerCoinId }.shortName()
}",
color = Color(0xff5acb48),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterVertically),
@ -152,22 +143,31 @@ fun HistoryCard(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
Text(
lineHeight = 1.sp,
text = buildAnnotatedString {
withStyle(style = SpanStyle(
color = Color(0xff1e1e1e),
fontSize = 16.sp)
) {append("Status: ")}
withStyle(style = SpanStyle(
color = Color(color),
fontSize = 16.sp)) {append(text)}},
withStyle(
style = SpanStyle(
color = Color(0xff1e1e1e),
fontSize = 16.sp
)
) { append("Status: ") }
withStyle(
style = SpanStyle(
color = Color(color),
fontSize = 16.sp
)
) { append(text) }
},
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
@ -197,9 +197,11 @@ fun PropertyHistory(modifier: Modifier = Modifier) {
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
fontWeight = FontWeight.Medium
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
}
}
}

View File

@ -11,79 +11,45 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.pmulabs.designElem.NavBar
import com.example.testapp.designElem.ListItem
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.HomeNavGraph
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.WalletViewModel
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun Wallet(navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
val argument = sharedViewModel.argument.value
val id = argument?.toInt()
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
}
var wallet: List<WalletItem> = listOf()
val walletItem = remember { mutableStateListOf<WalletItem>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
if (id != null) {
CryptoDealDb.getInstance(context).walletItemDao().getAll().collect{ data ->
walletItem.clear()
walletItem.addAll(data)
}
}
}
}
wallet = walletItem.filter { x -> x.userId == id };
val coins = remember { mutableStateListOf<Coin>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).coinDao().getAll().collect { data ->
coins.clear()
coins.addAll(data)
}
}
}
fun Wallet(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val id = currentUserViewModel.user!!.id
walletViewModel.setArgument(id.toString())
val wallet = remember { mutableStateOf(walletViewModel.wallet) }
val coins = remember { mutableStateOf(walletViewModel.coins) }
LazyColumn(
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
@ -97,12 +63,14 @@ fun Wallet(navController: NavHostController = rememberNavController(),
PropertyWallet()
}
item {
wallet.forEach { coin ->
ListItem(
coin = coins.first{ x -> x.id == coin.coinId },
count = coin.count,
modifier = Modifier.padding( vertical = 5.dp)
)
wallet.value?.forEach { coin ->
coins.value?.let {
ListItem(
coin = it.first { x -> x.id == coin.coinId },
count = coin.count,
modifier = Modifier.padding(vertical = 5.dp)
)
}
}
}
}
@ -110,15 +78,28 @@ fun Wallet(navController: NavHostController = rememberNavController(),
@RequiresApi(34)
@Composable
fun LoadScreen(navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
fun LoadScreen(
navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealCreateViewModel: DealCreateViewModel = viewModel(factory = AppViewModelProvider.Factory),
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
Scaffold(
bottomBar = { NavBar(navController = navController) },
) {
Modifier
.padding(it)
HomeNavGraph(navController, sharedViewModel)
HomeNavGraph(
navController,
currentUserViewModel,
dealCreateViewModel,
dealListViewModel,
historyViewModel,
walletViewModel
)
}
}
@ -147,9 +128,11 @@ fun PropertyWallet(modifier: Modifier = Modifier) {
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
fontWeight = FontWeight.Medium
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
}
}
}

View File

@ -0,0 +1,226 @@
package com.example.testapp.screensMobile.authScreens
import android.annotation.SuppressLint
import androidx.compose.foundation.background
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
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.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.testapp.designElem.Btn
import com.example.testapp.designElem.btnConfig
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.graphs.Graph
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.EntryScreenViewModel
fun isValidEmail(email: String): Boolean {
val emailRegex = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex()
return email.matches(emailRegex)
}
@OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("UnrememberedMutableState")
@Composable
fun EntryScreen(
navController: NavController,
modifier: Modifier = Modifier,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
entryScreenViewModel: EntryScreenViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
var emailValue by rememberSaveable { mutableStateOf("") }
var passwordValue by rememberSaveable { mutableStateOf("") }
entryScreenViewModel.setupList()
val users = mutableStateOf(entryScreenViewModel.userList)
val argument = currentUserViewModel.argument.value
var passwordVisibility by rememberSaveable { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
Box(
modifier = modifier
.fillMaxSize()
.background(color = Color.White)
) {
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 40.dp
)
) {
Text(
text = "Sign On",
color = Color(0xff0b1f33),
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Medium
),
modifier = Modifier
.fillMaxSize()
)
}
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp, y = 278.dp)
.padding(start = 5.dp, end = 5.dp)
) {
TextField(
value = emailValue,
onValueChange = { emailValue = it },
label = {
Text(
text = "Email",
color = Color(0xff66727f),
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp
)
)
},
placeholder = { Text("Enter email") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth()
)
TextField(
value = passwordValue,
onValueChange = { passwordValue = it },
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.White,
unfocusedContainerColor = Color.White,
disabledContainerColor = Color.White,
),
modifier = modifier
.fillMaxWidth()
.shadow(shape = RoundedCornerShape(40.dp), elevation = 5.dp)
.clip(shape = RoundedCornerShape(40.dp)),
label = { Text("Password") },
singleLine = true,
placeholder = { Text("Enter password") },
visualTransformation = if (passwordVisibility) VisualTransformation.None else PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
trailingIcon = {
val image = if (passwordVisibility)
Icons.Filled.Visibility
else Icons.Filled.VisibilityOff
val description =
if (passwordVisibility) "Hide password" else "Show password"
IconButton(onClick = { passwordVisibility = !passwordVisibility }) {
Icon(imageVector = image, description)
}
})
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 602.dp
)
.padding(
horizontal = 5.dp,
vertical = 5.dp
)
.fillMaxWidth()
) {
Btn(
btnConfig = btnConfig(
onClick = {
if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) {
users.value.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
currentUserViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString()))
}
}
}
},
text = "Sign In",
color = Color(0xff85c3ff),
offsetX = 0.dp,
offsetY = 0.dp
), modifier = Modifier.fillMaxWidth()
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 656.dp
)
.padding(
horizontal = 5.dp,
vertical = 5.dp
)
.fillMaxWidth()
) {
Btn(
btnConfig = btnConfig(
onClick = {
navController.navigate(route = AuthScreen.Register.route)
{
popUpTo(AuthScreen.Register.route)
}
},
text = "Sign On",
color = Color(0xff85c3f3),
offsetX = 0.dp,
offsetY = 0.dp
), modifier = Modifier.fillMaxWidth()
)
}
}
}

View File

@ -1,5 +1,7 @@
package com.example.testapp.screensMobile
package com.example.testapp.screensMobile.authScreens
import android.annotation.SuppressLint
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -18,18 +20,15 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
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.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@ -37,34 +36,32 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.graphs.Graph
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.models.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RegisterScreen(navController: NavController,
modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
fun RegisterScreen(
navController: NavController,
modifier: Modifier = Modifier,
currentUserViewModel: CurrentUserViewModel,
registrationScreenViewModel: RegistrationScreenViewModel
) {
var emailValue by rememberSaveable { mutableStateOf("") }
var passwordValue by rememberSaveable { mutableStateOf("") }
var passwordConfirmValue by rememberSaveable { mutableStateOf("") }
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
registrationScreenViewModel.setUserList()
val users = mutableStateOf<List<User>>(emptyList())
registrationScreenViewModel.users.observeForever { userList ->
users.value = userList
}
val coroutineScope = rememberCoroutineScope()
Box(
modifier = modifier
@ -75,8 +72,10 @@ fun RegisterScreen(navController: NavController,
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 40.dp)
.offset(
x = 0.dp,
y = 40.dp
)
) {
Text(
text = "Sign On",
@ -95,8 +94,10 @@ fun RegisterScreen(navController: NavController,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.padding(start = 5.dp, end = 5.dp)
.offset(x = 0.dp,
y = 232.dp)
.offset(
x = 0.dp,
y = 232.dp
)
) {
TextField(
value = emailValue,
@ -108,14 +109,18 @@ fun RegisterScreen(navController: NavController,
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp))
letterSpacing = 0.2.sp
)
)
},
placeholder = { Text("Enter email") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
TextField(
value = passwordValue,
onValueChange = { passwordValue = it },
@ -126,14 +131,18 @@ fun RegisterScreen(navController: NavController,
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp))
letterSpacing = 0.2.sp
)
)
},
placeholder = { Text("Enter password") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
TextField(
value = passwordConfirmValue,
onValueChange = { passwordConfirmValue = it },
@ -144,40 +153,49 @@ fun RegisterScreen(navController: NavController,
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp))
letterSpacing = 0.2.sp
)
)
},
placeholder = { Text("Confirm password") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
letterSpacing = 0.1.sp
),
modifier = Modifier
.fillMaxWidth())
.fillMaxWidth()
)
}
TextButton(
onClick = {
var isExist = false;
if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) {
users.forEach { user ->
users.value.forEach { user ->
if (user.email == emailValue) {
Log.d("User already exist. User id: ", user.id.toString())
isExist = true
}
}
if (!isExist) {
val newUser = User(null, emailValue, passwordValue)
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).userDao().insert(newUser)
CryptoDealDb.getInstance(context).userDao().getAll()
.collect { data ->
data.forEach { user ->
if ((user.password == passwordValue) && (user.email == emailValue)) {
withContext(Dispatchers.Main) {
sharedViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString()))
}
}
coroutineScope.launch {
val insertResult = async {
registrationScreenViewModel.insert(newUser)
}
insertResult.await()
registrationScreenViewModel.setUserList()
registrationScreenViewModel.users.observeForever { userList ->
users.value = userList
Log.println(Log.ASSERT, "UsersList", users.value.toString())
users.value.forEach { user ->
if (user.password == passwordValue && user.email == emailValue) {
currentUserViewModel.setArgument(user.id.toString())
navController.navigate(route = Graph.passUserId(user.id.toString()))
}
}
}
}
}
}
@ -185,8 +203,10 @@ fun RegisterScreen(navController: NavController,
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 656.dp)
.offset(
x = 0.dp,
y = 656.dp
)
) {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top)
@ -206,8 +226,10 @@ fun RegisterScreen(navController: NavController,
modifier = Modifier
.align(alignment = Alignment.TopStart)
.fillMaxWidth()
.offset(x = 0.dp,
y = 602.dp)
.offset(
x = 0.dp,
y = 602.dp
)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
@ -220,7 +242,9 @@ fun RegisterScreen(navController: NavController,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
}
@ -240,8 +264,10 @@ fun Property1Primary(modifier: Modifier = Modifier) {
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(x = 0.dp,
y = 0.dp)
.offset(
x = 0.dp,
y = 0.dp
)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
@ -253,7 +279,9 @@ fun Property1Primary(modifier: Modifier = Modifier) {
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
letterSpacing = 0.1.sp
)
)
}
}
}

View File

@ -0,0 +1,49 @@
package com.example.testapp.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.testapp.CryptoDealApplication
object AppViewModelProvider {
val Factory = viewModelFactory {
initializer {
CurrentUserViewModel(application().container.userRepository)
}
initializer {
DealListViewModel(
application().container.dealRepository,
application().container.coinRepository
)
}
initializer {
DealCreateViewModel(
application().container.dealRepository,
application().container.coinRepository,
application().container.walletItemRepository
)
}
initializer {
EntryScreenViewModel(application().container.userRepository)
}
initializer {
HistoryViewModel(
application().container.dealRepository,
application().container.coinRepository
)
}
initializer {
RegistrationScreenViewModel(application().container.userRepository)
}
initializer {
WalletViewModel(
application().container.walletItemRepository,
application().container.coinRepository
)
}
}
}
fun CreationExtras.application(): CryptoDealApplication =
(this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as CryptoDealApplication)

View File

@ -0,0 +1,28 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel() {
val argument = mutableStateOf<String?>(null)
private val id = mutableStateOf<Int?>(null)
var user by mutableStateOf<User?>(null)
fun setArgument(arg: String) {
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch {
user = userRepository.getById(id.value!!)
.filterNotNull()
.first()
}
}
}

View File

@ -0,0 +1,56 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class DealCreateViewModel(
private val dealRepository: DealRepository,
private val coinRepository: CoinRepository,
private val walletItemRepository: WalletItemRepository
) : ViewModel() {
val argument = mutableStateOf<String?>(null)
private val user_id = mutableStateOf<Int?>(null)
private val deal_id = mutableStateOf<Int?>(null)
var deal by mutableStateOf<Deal?>(null)
var deals by mutableStateOf<List<Deal>>(emptyList())
var coins by mutableStateOf<List<Coin>>(emptyList())
var wallet by mutableStateOf<List<WalletItem>>(emptyList())
suspend fun update(deal: Deal) = dealRepository.update(deal)
suspend fun create(deal: Deal) = dealRepository.insert(deal)
fun setupLists(arg: String) {
argument.value = arg
user_id.value = arg.toInt()
viewModelScope.launch {
deals = dealRepository.getAll().first();
coins = coinRepository.getAll().first();
wallet = walletItemRepository.getUserWallet(user_id.value!!).first();
}
}
fun isEdit(): Boolean {
return deal != null;
}
fun setupEdit(id: Int) {
deal_id.value = id;
viewModelScope.launch {
deal = dealRepository.getById(id).first();
}
}
}

View File

@ -0,0 +1,32 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class DealListViewModel(
private val dealRepository: DealRepository,
private val coinRepository: CoinRepository,
) : ViewModel() {
var deals by mutableStateOf<List<Deal>>(emptyList())
var coins by mutableStateOf<List<Coin>>(emptyList())
fun setupLists() {
viewModelScope.launch {
deals = dealRepository.getAll().first();
coins = coinRepository.getAll().first();
}
}
fun submitDeal(deal: Deal, sellerId: Int, buyerId: Int) {
dealRepository.completeDeal(deal, sellerId, buyerId)
}
}

View File

@ -0,0 +1,22 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class EntryScreenViewModel(
private val userRepository: UserRepository
) : ViewModel() {
var userList by mutableStateOf<List<User>>(emptyList())
fun setupList() {
viewModelScope.launch {
userList = userRepository.getAll().first()
}
}
}

View File

@ -0,0 +1,30 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class HistoryViewModel(private val dealRepository: DealRepository,
private val coinRepository: CoinRepository) : ViewModel() {
val argument = mutableStateOf<String?>(null)
private val id = mutableStateOf<Int?>(null)
var deals by mutableStateOf<List<Deal>?>(emptyList())
var coins by mutableStateOf<List<Coin>?>(emptyList())
fun setArgument(arg: String) {
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch {
deals = dealRepository.getUserDeals(id.value!!).first()
coins = coinRepository.getAll().first()
}
}
}

View File

@ -0,0 +1,25 @@
package com.example.testapp.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class RegistrationScreenViewModel(private val userRepository: UserRepository) : ViewModel() {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> get() = _users
fun setUserList() {
viewModelScope.launch {
_users.value = userRepository.getAll().first()
}
}
suspend fun insert(user: User) {
userRepository.insert(user)
}
}

View File

@ -0,0 +1,32 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class WalletViewModel(
private val walletItemRepository: WalletItemRepository,
private val coinRepository: CoinRepository
) : ViewModel() {
val argument = mutableStateOf<String?>(null)
private val id = mutableStateOf<Int?>(null)
var wallet by mutableStateOf<List<WalletItem>?>(emptyList())
var coins by mutableStateOf<List<Coin>?>(emptyList())
fun setArgument(arg: String) {
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch {
wallet = walletItemRepository.getUserWallet(id.value!!).first()
coins = coinRepository.getAll().first()
}
}
}