Complete lab

This commit is contained in:
andrew 2023-12-07 23:52:40 +04:00
commit e5adf214b7
32 changed files with 3195 additions and 0 deletions

View File

@ -0,0 +1,37 @@
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.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
class MainActivity : ComponentActivity() {
private val sharedViewModel: SharedViewModel by viewModels()
@SuppressLint("MissingInflatedId", "SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TestAppTheme {
RootNavigationGraph(
navController = rememberNavController(),
sharedViewModel = sharedViewModel
)
}
}
}
}

View File

@ -0,0 +1,44 @@
package com.example.testapp.designElem
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
@Composable
fun AlertDialogExample(
onDismissRequest: () -> Unit,
onConfirmation: () -> Unit,
dialogTitle: String,
dialogText: String,
) {
AlertDialog(
title = {
Text(text = dialogTitle)
},
text = {
Text(text = dialogText)
},
onDismissRequest = {
onDismissRequest()
},
confirmButton = {
TextButton(
onClick = {
onConfirmation()
}
) {
Text("Confirm")
}
},
dismissButton = {
TextButton(
onClick = {
onDismissRequest()
}
) {
Text("Dismiss")
}
}
)
}

View File

@ -0,0 +1,70 @@
package com.example.testapp.designElem
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.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
@Composable
fun Btn(modifier: Modifier = Modifier, btnConfig: btnConfig) {
Button(
onClick = btnConfig.onClick,
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = btnConfig.color),
modifier = modifier
.requiredHeight(height = 44.dp)
) {
Box(
modifier = Modifier
.requiredHeight(height = 44.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(x = btnConfig.offsetX, y = btnConfig.offsetY)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = btnConfig.text,
color = Color.White,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp)
)
}
}
}
}
}
data class btnConfig(
val onClick: () -> Unit = {},
val text: String,
val color: Color,
val offsetX: Dp,
val offsetY: Dp
)

View File

@ -0,0 +1,182 @@
package com.example.testapp.designElem
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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.requiredSize
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
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.ui.Alignment
import androidx.compose.ui.Modifier
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.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 com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
@Composable
fun DealItem(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
Box(
modifier = modifier
.requiredWidth(width = 356.dp)
.requiredHeight(height = 86.dp)
) {
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 10.dp,
y = 5.dp)
.requiredWidth(width = 336.dp)
.requiredHeight(height = 131.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color(0xfffafafa))
.border(border = BorderStroke(2.dp, Color.White),
shape = RoundedCornerShape(8.dp)))
Property1ListAvatar(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 10.dp,
y = 10.dp), deal, coins)
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 201.dp,
y = 86.dp)
.requiredWidth(width = 130.dp)
.requiredHeight(height = 40.dp)
) {
Box(
modifier = Modifier
.requiredWidth(width = 130.dp)
.requiredHeight(height = 40.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color(0xff85c3ff)))
Text(
text = "${coins.first{ x -> deal.buyerCoinId == x.id }.name} ${deal.countBuy}",
color = Color.White,
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 21.dp,
y = 10.dp)
.requiredWidth(width = 87.dp))
}
Box(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 25.dp,
y = 86.dp)
.requiredWidth(width = 170.dp)
.requiredHeight(height = 40.dp)
) {
Box(
modifier = Modifier
.requiredWidth(width = 170.dp)
.requiredHeight(height = 40.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color(0xff5acb48)))
Button(
onClick = { },
colors = ButtonDefaults.buttonColors(containerColor = Color.White),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 52.dp,
y = 10.dp)
.requiredWidth(width = 66.dp)){ }
}
}
}
@Composable
fun Property1ListAvatar(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.requiredWidth(width = 336.dp)
.requiredHeight(height = 66.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color.White)
.padding(start = 12.dp,
end = 16.dp,
top = 4.dp,
bottom = 4.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(all = 12.dp)
) {
Avatar(deal = deal, coins = coins)
}
Text(
text = coins.first {x -> x.id == deal.sellerCoinId}.name,
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
@Composable
fun Avatar(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
Box(
modifier = modifier
.requiredSize(size = 32.dp)
.clip(shape = MaterialTheme.shapes.small)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(color = Color(0xfff9a825)))
Box(
modifier = Modifier
.fillMaxSize()
.background(brush = Brush.linearGradient(
0f to Color.White,
1f to Color.White,
start = Offset(16f, 0f),
end = Offset(16f, 32f))))
Text(
text = coins.first {x -> x.id == deal.sellerCoinId}.shortName(),
color = Color.White,
textAlign = TextAlign.Center,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxSize()
.wrapContentHeight(align = Alignment.CenterVertically))
}
}

View File

@ -0,0 +1,85 @@
package com.example.testapp.designElem
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.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.text.TextStyle
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
data class DropDownConfig<T>(
val values: List<T>,
var title: String,
val onValueChange: (T) -> Unit,
val selected: T?
)
@Composable
fun <T> DropDown(modifier: Modifier = Modifier, downConfig: DropDownConfig<T>) {
var expanded by remember { mutableStateOf(false) }
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(8.dp))
.clickable { expanded = !expanded }
.background(color = Color.Transparent)
.border(
border = BorderStroke(1.dp, Color.Black),
shape = RoundedCornerShape(8.dp)
)
.padding(
horizontal = 10.dp,
vertical = 8.dp
)
) {
Text(
text = if (downConfig.selected == null) downConfig.title else downConfig.selected.toString(),
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
Modifier.background(color = Color.Transparent),
) {
downConfig.values.forEach { x ->
DropdownMenuItem(
text = { Text(x.toString()) },
onClick = {
downConfig.onValueChange(x);
expanded = false;
downConfig.title = x.toString()
}
)
}
}
}
}

View File

@ -0,0 +1,84 @@
package com.example.testapp.designElem
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.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 com.example.testapp.room.models.Coin
@Composable
fun ListItem(modifier: Modifier = Modifier, coin : Coin, count: Float) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.requiredWidth(width = 340.dp)
.requiredHeight(height = 36.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color.White)
.padding(end = 12.dp,
top = 4.dp,
bottom = 4.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.requiredWidth(width = 56.dp)
.padding(all = 12.dp)
) {
Box(
modifier = Modifier
.requiredWidth(width = 40.dp)
.requiredHeight(height = 32.dp)
.clip(shape = MaterialTheme.shapes.small)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(color = Color(0xfff9a825)))
Text(
text = coin.shortName(),
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxSize()
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
Text(
text = "$count ${coin.name}",
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
}

View File

@ -0,0 +1,108 @@
package com.example.pmulabs.designElem
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.text.toUpperCase
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.example.testapp.navigate.BottomBarScreen
import java.util.Locale
@Composable
fun NavBar(navController: NavHostController){
val screens = listOf(
BottomBarScreen.Profile,
BottomBarScreen.Wallet,
BottomBarScreen.Deals,
BottomBarScreen.History
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination=navBackStackEntry?.destination
val bottomBarDestination=screens.any{ it.route==currentDestination?.route }
NavigationBar(
modifier = Modifier
.height(48.dp)
) {
Row(
modifier = Modifier
.padding(horizontal = 5.dp)
.background(Color.Transparent),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
if (bottomBarDestination) {
screens.forEach { screen ->
AddItem(
screen = screen,
currentDestination = currentDestination,
navController = navController
)
}
}
}
}
}
@Composable
fun AddItem(
screen: BottomBarScreen,
currentDestination: NavDestination?,
navController: NavController
){
val selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true
val background = if (selected) Color(0xff4BB2F9) else Color.Transparent
val contentColor = if (selected) Color.White else Color(0xFF4BB2F9)
Box(
modifier = Modifier
.height(40.dp)
.background(background)
.clickable(onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
})
.clip(shape = RoundedCornerShape(10.dp))
.requiredWidth(100.dp)
) {
Row(
modifier = Modifier
.padding(start = 5.dp, end = 5.dp, top = 8.dp, bottom = 8.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
AnimatedVisibility(visible = true) {
Text(
text = screen.shortName(),
color = contentColor
)
}
}
}
}

View File

@ -0,0 +1,24 @@
package com.example.testapp.designElem
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class SharedViewModel : ViewModel() {
val argument = mutableStateOf<String?>(null)
val argument_edit = mutableStateOf<Any?>(null)
val argument_add_f = mutableStateOf<Any?>(null)
val argument_add_c = mutableStateOf<Any?>(null)
fun setArgumentAdd(arg1: Any, arg2: Any) {
argument_add_f.value = arg1
argument_add_c.value = arg2
}
fun setArgumentEdit(arg: Any) {
argument_edit.value = arg
}
fun setArgument(arg: String) {
argument.value = arg
}
}

View File

@ -0,0 +1,81 @@
package com.example.testapp.designElem
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.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableDoubleStateOf
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
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.text.TextStyle
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
data class SliderRangeConfig(
val start: Float,
val end: Float
)
@Composable
fun SliderWithRange(modifier: Modifier = Modifier,
sliderRangeConfig: SliderRangeConfig = SliderRangeConfig(0.0f, 1.0f),
onValueChange: (Float) -> Unit = {}
) {
var value by remember { mutableFloatStateOf(sliderRangeConfig.start) }
Column(
verticalArrangement = Arrangement.spacedBy(2.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color.Transparent)
.border(
border = BorderStroke(1.dp, Color.Black),
shape = RoundedCornerShape(8.dp)
)
.padding(
horizontal = 10.dp,
vertical = 8.dp
)
) {
Slider(
value = value,
onValueChange = { value = it; onValueChange(value) },
onValueChangeFinished = { },
valueRange = sliderRangeConfig.start..sliderRangeConfig.end,
modifier = modifier
.fillMaxWidth()
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
Text(
text = value.toString(),
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
modifier = modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
}

View File

@ -0,0 +1,29 @@
package com.example.testapp.graphs
import androidx.compose.ui.Modifier
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
fun NavGraphBuilder.authNavGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
navigation(
route=Graph.AUTHENTICATION,
startDestination = AuthScreen.Entry.route
){
composable(route=AuthScreen.Entry.route){
EntryScreen(navController = navController, modifier = Modifier, sharedViewModel = sharedViewModel)
}
composable(route=AuthScreen.Register.route){
RegisterScreen(navController = navController, modifier = Modifier, sharedViewModel = sharedViewModel)
}
}
}
sealed class AuthScreen(val route: String){
object Entry : AuthScreen(route="ENTRY")
object Register : AuthScreen(route="REGISTER")
}

View File

@ -0,0 +1,44 @@
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.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
@RequiresApi(34)
@Composable
fun HomeNavGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
NavHost(
navController = navController,
route = Graph.MAIN,
startDestination = BottomBarScreen.Wallet.route
){
composable(route=BottomBarScreen.Wallet.route){
Wallet(sharedViewModel = sharedViewModel)
}
composable(route=BottomBarScreen.Profile.route){
AccountPage(sharedViewModel = sharedViewModel, navController = navController)
}
composable(route=BottomBarScreen.Deals.route){
DealList(navController = navController, sharedViewModel = sharedViewModel)
}
composable(route=BottomBarScreen.CDEAL.route) {
CreateDeal(sharedViewModel = sharedViewModel, navController = navController)
}
composable(route=BottomBarScreen.History.route){
History(sharedViewModel = sharedViewModel)
}
}
}

View File

@ -0,0 +1,42 @@
package com.example.testapp.graphs
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
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
const val USERID_ARGUMENT="userId"
@RequiresApi(34)
@Composable
fun RootNavigationGraph(navController: NavHostController, sharedViewModel: SharedViewModel){
NavHost(
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)
}
}
}
object Graph{
const val ROOT="root_graph"
const val AUTHENTICATION="auth_graph"
const val MAIN="main_graph/{$USERID_ARGUMENT}"
fun passUserId(userId: String): String{
return "main_graph/$userId"
}
}

View File

@ -0,0 +1,31 @@
package com.example.testapp.navigate
sealed class BottomBarScreen(
val route: String,
val title: String
) {
object Profile: BottomBarScreen(
route = "PROFILE",
title = "Account",
);
object Wallet: BottomBarScreen(
route = "WALLET",
title = "Wallet"
);
object Deals: BottomBarScreen(
route = "DEALS",
title = "Deals"
)
object History: BottomBarScreen(
route = "HISTORY",
title = "History"
)
object CDEAL: BottomBarScreen(
route = "CDEAL",
title = "CDEAL"
)
fun shortName(): String {
return title.uppercase().substring(0, 4)
}
}

View File

@ -0,0 +1,21 @@
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{
@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

@ -0,0 +1,24 @@
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{
@Query("select * from deal")
fun getAll(): Flow<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,29 @@
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 {
@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

@ -0,0 +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 WalletItemDao {
@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)
}

View File

@ -0,0 +1,91 @@
package com.example.testapp.room.database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.testapp.room.dao.*
import com.example.testapp.room.models.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Database(
entities = [User::class, Deal::class, Coin::class, WalletItem::class],
version = 2,
exportSchema = false)
abstract class CryptoDealDb: RoomDatabase() {
abstract fun userDao(): UserDao;
abstract fun coinDao(): CoinDao;
abstract fun dealDao(): DealDao;
abstract fun walletItemDao(): WalletItemDao;
companion object {
private const val DB_NAME: String = "crypto-deal2"
@Volatile
private var INSTANCE: CryptoDealDb? = null
private suspend fun populateDatabase() {
INSTANCE?.let { database ->
val userDao = database.userDao();
val user1 = User(0, "u11@gmail.com","12345")
val user2 = User(1, "u22@gmail.com","12345")
val user3 = User(2, "u33@gmail.com","12345")
userDao.insert(user1)
userDao.insert(user2)
userDao.insert(user3)
val coinDao = database.coinDao();
val c1 = Coin(0, "BidCoin");
val c2 = Coin(1, "Edhereum");
val c3 = Coin(2, "CatCoin");
val c4 = Coin(3, "BuzCoin");
coinDao.insert(c1);
coinDao.insert(c2)
coinDao.insert(c3)
coinDao.insert(c4)
val walletItemDao = database.walletItemDao();
val wi1 = WalletItem(0, 0, 0.5f);
val wi2 = WalletItem(1, 0, 0.6f);
val wi3 = WalletItem(3, 0, 0.7f);
val wi4 = WalletItem(0, 1, 1000f);
val wi5 = WalletItem(3, 1, 10f);
val wi6 = WalletItem(2, 1, 1f);
walletItemDao.insert(wi1);
walletItemDao.insert(wi2);
walletItemDao.insert(wi3);
walletItemDao.insert(wi4);
walletItemDao.insert(wi5);
walletItemDao.insert(wi6);
val dealDao = database.dealDao();
val d1 = Deal(0, null, 0, 2, 0, 0.1f, 0.2f, "Buy", null, "TEST1")
val d2 = Deal(1, null, 0, 0, 2, 0.1f, 0.2f, "Buy", null, "TEST2")
dealDao.insert(d1);
dealDao.insert(d2);
}
}
fun getInstance(appContext: Context): CryptoDealDb {
return INSTANCE ?: synchronized(this) {
Room.databaseBuilder(
appContext,
CryptoDealDb::class.java,
DB_NAME
)
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch {
populateDatabase()
}
}
})
.build()
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,17 @@
package com.example.testapp.room.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "coin")
class Coin(
@PrimaryKey(autoGenerate = true)
val id: Int?,
@ColumnInfo(name = "name")
val name: String
) {
fun shortName(): String {
return this.name.substring(0, 2)
}
}

View File

@ -0,0 +1,22 @@
package com.example.testapp.room.models
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.LocalDateTime
@Entity
class Deal (
@PrimaryKey(autoGenerate = true)
val id: Int?,
val sellerId: Int?,
val buyerId: Int?,
val sellerCoinId: Int,
val buyerCoinId: Int,
val countSell: Float,
val countBuy: Float,
val operation: String,
var date: Long?,
val tip: String,
) {
}

View File

@ -0,0 +1,29 @@
package com.example.testapp.room.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = "user",
indices = [Index(value = ["email"], unique = true)])
class User(
@PrimaryKey(autoGenerate = true)
val id: Int?,
@ColumnInfo(name = "email")
var email: String,
@ColumnInfo(name = "password")
var password: String
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as User
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id ?: -1
}
}

View File

@ -0,0 +1,18 @@
package com.example.testapp.room.models
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
primaryKeys = ["coinId", "userId"],
foreignKeys = [
ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE),
ForeignKey(entity = Coin::class, parentColumns = ["id"], childColumns = ["coinId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE)
]
)
class WalletItem (
val coinId: Int,
val userId: Int,
val count: Float
)

View File

@ -0,0 +1,352 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.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.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.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.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.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
@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
}
}
Box(
modifier = modifier
.background(color = Color(0xfff4f7fb))
) {
Column(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 104.dp
)
.background(color = Color.White)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.requiredSize(size = 84.dp)
) {
if (user != null) {
Container(
name = user!!.email.substring(0, 2),
modifier = Modifier.align(alignment = Alignment.TopStart).offset(15.dp, 15.dp)
)
}
}
}
Column(
modifier = Modifier
.padding(vertical = 7.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.Start),
modifier = Modifier
.padding(vertical = 3.dp)
) {
if (user != null) {
Text(
text = user!!.email,
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp))
}
}
Box(
modifier = Modifier
.requiredWidth(width = 17.dp)
.requiredHeight(height = 4.dp))
}
}
}
Column(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 204.dp
)
) {
Property1Switch(modifier = Modifier.padding(vertical = 5.dp))
Property1Arrow(modifier = Modifier.padding(vertical = 5.dp))
}
Property1Clear(navController = navController)
Property1(
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(
x = 0.dp,
y = 24.dp
))
}
}
@Composable
fun Property1Switch(modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.background(color = Color.White)
.padding(
start = 12.dp,
end = 16.dp,
top = 4.dp,
bottom = 4.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(all = 12.dp)
) {
// Icon(
// painter = painterResource(id = R.drawable.sizem),
// contentDescription = "IconFavorite",
// tint = Color(0xff002033).copy(alpha = 0.35f))
}
Text(
text = "Enable Notifications",
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.weight(weight = 1f)
.wrapContentHeight(align = Alignment.CenterVertically))
Viewchecked()
}
}
@Composable
fun Container(modifier: Modifier = Modifier, name: String) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.requiredSize(size = 54.dp)
.clip(shape = RoundedCornerShape(27.dp))
.background(color = Color(0xff4bb2f9))
.padding(all = 10.dp)
) {
Text(
text = name,
color = Color.White,
textAlign = TextAlign.Center,
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Medium),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
@Composable
fun Viewchecked(modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
) {
Box(
modifier = Modifier
.requiredWidth(width = 44.dp)
.requiredHeight(height = 24.dp)
) {
Box(
modifier = Modifier
.fillMaxSize()
.clip(shape = RoundedCornerShape(100.dp))
.background(color = Color(0xff4bb2f9)))
Box(
modifier = Modifier
.fillMaxSize()
.clip(shape = CircleShape)
.background(color = Color.White))
}
}
}
@Composable
fun Property1Arrow(modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.background(color = Color.White)
.padding(
start = 12.dp,
end = 16.dp,
top = 4.dp,
bottom = 4.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(all = 12.dp)
) {
// Icon(
// painter = painterResource(id = R.drawable.sizem),
// contentDescription = "IconFavorite",
// tint = Color(0xff002033).copy(alpha = 0.35f))
}
Text(
text = "Confirm Account",
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.weight(weight = 1f)
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
@Composable
fun Property1Clear(modifier: Modifier = Modifier, navController: NavController) {
Box(
modifier = modifier
.fillMaxSize()
.clip(shape = RoundedCornerShape(10.dp))
.clickable{
navController.navigate(route = AuthScreen.Entry.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
.padding(
start = 16.dp,
end = 16.dp,
top = 580.dp,
bottom = 20.dp
)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(
x = 0.dp,
y = 0.dp
)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Log Out",
color = Color(0xffee3f58),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
}
}
}
}
@Composable
fun Property1(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.requiredHeight(height = 56.dp)
.background(color = Color.White)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(end = 56.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
modifier = Modifier
.padding(all = 16.dp)
) {
// Icon(
// painter = painterResource(id = R.drawable.drawer),
// contentDescription = "Drawer",
// tint = Color(0xff0b1f33))
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
Text(
text = "Account",
color = Color(0xff0b1f33),
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
modifier = Modifier
.fillMaxWidth())
}
}
}
}

View File

@ -0,0 +1,415 @@
package com.example.testapp.screensMobile
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.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.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
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
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
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.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 kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@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()
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 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 coinsBuyer = wallet.filter { x -> x.userId == id }.toList()
var coinBuyer by rememberSaveable {
mutableStateOf(if (isEdit) coins.first{y -> y.id == editDeal?.buyerCoinId }.name else coinsBuyer[0])
}
var buyCount by remember {
mutableFloatStateOf(if (isEdit) editDeal?.countBuy!! else 0f)
}
var tip by remember {
mutableStateOf(if (isEdit) editDeal?.tip else "")
}
val coinsSeller = wallet.map { x -> coins.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])
}
var sellCount by remember {
mutableFloatStateOf(if (isEdit) editDeal?.countSell!! else 0f)
}
LazyColumn(
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.fillMaxSize()
.background(color = Color(0xfff4f7fb))
.padding(
horizontal = 0.dp,
vertical = 20.dp
)
) {
item {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth(1f)
.requiredHeight(height = 56.dp)
.background(color = Color.White)
.padding(
horizontal = 17.dp,
vertical = 6.dp
)
) {
Text(
text = "CREATE DEAL",
color = Color.Black,
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium)
)
Text(
text = "-",
color = Color(0xff4bb2f9),
textAlign = TextAlign.Center,
lineHeight = 0.83.em,
style = TextStyle(
fontSize = 24.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.clickable {
navController.navigate(route = BottomBarScreen.Deals.route)
}
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
item {
Text(
text = "You",
color = Color(0xff66727f),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.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(),
title = "Select coin",
onValueChange = { x -> coinBuyer = x },
selected = coinBuyer as String
)
)
}
item {
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()
}
},
label = {
Text(
text = "Fill count 0 -> ${coinsBuyer.first{ x -> coinBuyer == coins.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),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
},
modifier = Modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(8.dp))
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
}
item {
OutlinedTextField(
value = tip!!,
onValueChange = { tip = it },
label = {
Text(
text = "Enter tip (up to 100 symbols)",
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
},
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 100.dp)
.clip(shape = RoundedCornerShape(8.dp))
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
}
item {
Text(
text = "Buyer",
color = Color(0xff66727f),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
item {
DropDown(
modifier = Modifier.padding(horizontal = 10.dp),
downConfig = DropDownConfig<String>(
values = coinsSeller.filter { x -> x != (coinBuyer as String) },
title = "Select coin",
onValueChange = { x -> coinSeller = x },
selected = coinSeller
)
)
}
item {
OutlinedTextField(
value = sellCount.toString(),
onValueChange = { sellCount = it.toFloat() },
label = {
Text(
text = "Fill count",
color = Color.Black,
textAlign = TextAlign.Center,
lineHeight = 1.43.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
},
modifier = Modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(8.dp))
.padding(
horizontal = 10.dp,
vertical = 2.dp
))
}
item {
Button(
onClick = {
if (isEdit) {
val deal = Deal(
id = editDeal?.id,
sellerId = editDeal?.sellerId,
buyerId = id,
buyerCoinId = coins.first { x -> x.name == coinBuyer }.id!!,
countBuy = buyCount,
sellerCoinId = coins.first { x -> x.name == coinSeller }.id!!,
countSell = sellCount,
tip = tip!!,
operation = "Buy",
date = null,
)
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).dealDao().update(deal)
}
} else {
val deal = Deal(
id = null,
sellerId = null,
buyerId = id,
buyerCoinId = coins.first { x -> x.name == coinBuyer }.id!!,
countBuy = buyCount,
sellerCoinId = coins.first { x -> x.name == coinSeller }.id!!,
countSell = sellCount,
tip = tip!!,
operation = "Buy",
date = null,
)
CoroutineScope(Dispatchers.IO).launch {
CryptoDealDb.getInstance(context).dealDao().insert(deal)
}
}
navController.navigate(route = BottomBarScreen.Deals.route)
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff4bb2f9)),
modifier = Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp, top = 30.dp)
.requiredHeight(height = 44.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 44.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(
x = 0.dp,
y = 0.dp
)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = if (isEdit) "Confirm" else "Create",
color = Color.White,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
}
}
}
}
}
item {
Button(
onClick = {
navController.navigate(route = BottomBarScreen.Deals.route)
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff4bb2f9)),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp)
.requiredHeight(height = 44.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 44.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(
x = 0.dp,
y = 0.dp
)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Cancel",
color = Color.White,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
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

@ -0,0 +1,367 @@
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.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.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
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun DealList(navController: NavHostController,
sharedViewModel: SharedViewModel,
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier
) {
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 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 = remember { mutableStateListOf<Coin>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
CryptoDealDb.getInstance(context).coinDao().getAll().collect { data ->
coins.clear()
coins.addAll(data)
}
}
}
LazyColumn (
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.background(color = Color(0xfff4f7fb))
.padding(vertical = 20.dp)
.fillMaxSize()
) {
item {
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)}
}
}
}
@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>) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.requiredWidth(width = 360.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(color = Color(0xffEEEEEE))
.padding(
start = 10.dp,
end = 10.dp,
bottom = 10.dp
)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.requiredWidth(width = 360.dp)
.requiredHeight(height = 60.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(color = Color.White)
.padding(horizontal = 22.dp)
) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.requiredSize(size = 35.dp)
.clip(shape = MaterialTheme.shapes.small)
.background(
brush = Brush.linearGradient(
0f to Color(0xffffcc7a),
1f to Color(0xffe4a031),
start = Offset(17.5f, 0f),
end = Offset(17.5f, 35f)
)
)
) {
Text(
text = coins.first{x -> x.id == deal.buyerCoinId}.shortName(),
color = Color.White,
lineHeight = 1.em,
style = TextStyle(
fontSize = 20.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
Text(
text = deal.countBuy.toString(),
color = Color.Black,
textAlign = TextAlign.End,
lineHeight = 1.em,
style = TextStyle(
fontSize = 20.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(align = Alignment.CenterVertically))
}
Text(
text = deal.tip,
color = Color(0xffa3abb3),
textAlign = TextAlign.Center,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 40.dp)
.wrapContentHeight(align = Alignment.CenterVertically))
Row(
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.requiredWidth(width = 360.dp)
.requiredHeight(height = 45.dp)
.padding(
horizontal = 10.dp,
vertical = 5.dp
)
) {
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
// }
} else {
sharedViewModel.setArgumentEdit(deal)
sharedViewModel.setArgumentAdd(wallet, coins)
navController.navigate(BottomBarScreen.CDEAL.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff5acb48)),
modifier = Modifier
.fillMaxSize()
.weight(weight = 0.5f)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.requiredWidth(width = 168.dp)
.requiredHeight(height = 35.dp)
) {
Text(
text = if (id == deal.buyerId) "Edit" else deal.operation,
color = Color.White,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.requiredWidth(width = 29.dp))
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.weight(weight = 0.5f)
.clip(shape = RoundedCornerShape(10.dp))
.background(color = Color(0xff85c3ff))
.padding(horizontal = 10.dp)
) {
Text(
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))
Text(
text = "${deal.countSell}\n",
color = Color.White,
textAlign = TextAlign.End,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 20.dp))
}
}
}
}
@Composable
fun PropertyDeal(modifier: Modifier = Modifier, navController: NavHostController) {
Box(
modifier = modifier
.fillMaxWidth()
.requiredHeight(height = 56.dp)
.background(color = Color.White)
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.requiredHeight(height = 56.dp)
.background(color = Color.White)
.padding(
horizontal = 17.dp,
vertical = 6.dp
)
) {
Text(
text = "CREATE DEAL",
color = Color.Black,
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium))
Text(
text = "+",
color = Color(0xff4bb2f9),
textAlign = TextAlign.Center,
lineHeight = 0.83.em,
style = TextStyle(
fontSize = 24.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.clickable {
navController.navigate(BottomBarScreen.CDEAL.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
}

View File

@ -0,0 +1,189 @@
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

@ -0,0 +1,206 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
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.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
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.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
import androidx.compose.ui.text.font.FontWeight
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.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
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun History(navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel
) {
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 }
}
Column(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.requiredHeight(height = 720.dp)
.background(color = Color(0xfff4f7fb))
.padding(vertical = 20.dp)
.verticalScroll(rememberScrollState())
) {
PropertyHistory()
history.forEach {
x -> HistoryCard(deal = x, modifier = Modifier.padding( vertical = 5.dp, horizontal = 5.dp), coins = coins)
}
}
}
@Composable
fun HistoryCard(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
val status = !(deal.buyerId == null || deal.sellerId == null)
val text = if (!status) "In work" else deal.date.toString()
val color = if (!status) 0xfff96161 else 0xff5acb48
Column(
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.requiredHeight(height = 150.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color.White)
.padding(
horizontal = 12.dp,
vertical = 5.dp
)
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp)
) {
Text(
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),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
Text(
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),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
Column(
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(5.dp))
.background(color = Color(0xfff4f7fb))
.padding(all = 10.dp)
) {
Text(
text = deal.tip,
color = Color.Black,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.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)}},
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
@Composable
fun PropertyHistory(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.requiredHeight(height = 56.dp)
.background(color = Color.White)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(end = 56.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
Text(
text = "HISTORY",
color = Color(0xff0b1f33),
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
modifier = Modifier
.fillMaxWidth())
}
}
}
}

View File

@ -0,0 +1,260 @@
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.PaddingValues
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.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
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.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
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 kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RegisterScreen(navController: NavController,
modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
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)
}
}
}
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)
.padding(start = 5.dp, end = 5.dp)
.offset(x = 0.dp,
y = 232.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 },
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())
TextField(
value = passwordConfirmValue,
onValueChange = { passwordConfirmValue = it },
label = {
Text(
text = "Confirm Password",
color = Color(0xff66727f),
lineHeight = 1.33.em,
style = TextStyle(
fontSize = 15.sp,
letterSpacing = 0.2.sp))
},
placeholder = { Text("Confirm password") },
textStyle = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp),
modifier = Modifier
.fillMaxWidth())
}
TextButton(
onClick = {
var isExist = false;
if (passwordValue.isNotEmpty() && isValidEmail(emailValue)) {
users.forEach { user ->
if (user.email == emailValue) {
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()))
}
}
}
}
}
}
}
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.offset(x = 0.dp,
y = 656.dp)
) {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.Top)
) {
Property1Primary()
}
}
TextButton(
onClick = {
navController.navigate(route = AuthScreen.Entry.route)
{
popUpTo(AuthScreen.Entry.route)
}
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
contentPadding = PaddingValues(horizontal = 10.dp, vertical = 12.dp),
modifier = Modifier
.align(alignment = Alignment.TopStart)
.fillMaxWidth()
.offset(x = 0.dp,
y = 602.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Sign In",
color = Color(0xff4bb2f9),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
}
}
}
}
@Composable
fun Property1Primary(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.requiredHeight(height = 44.dp)
.clip(shape = RoundedCornerShape(10.dp))
.background(color = Color(0xff85c3ff))
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.align(alignment = Alignment.Center)
.offset(x = 0.dp,
y = 0.dp)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Sign On",
color = Color.White,
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
letterSpacing = 0.1.sp))
}
}
}
}

View File

@ -0,0 +1,156 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
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.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.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
@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)
}
}
}
LazyColumn(
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.background(color = Color(0xfff4f7fb))
.padding(vertical = 20.dp)
.fillMaxSize()
) {
item {
PropertyWallet()
}
item {
wallet.forEach { coin ->
ListItem(
coin = coins.first{ x -> x.id == coin.coinId },
count = coin.count,
modifier = Modifier.padding( vertical = 5.dp)
)
}
}
}
}
@RequiresApi(34)
@Composable
fun LoadScreen(navController: NavHostController = rememberNavController(),
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier,
sharedViewModel: SharedViewModel) {
Scaffold(
bottomBar = { NavBar(navController = navController) },
) {
Modifier
.padding(it)
HomeNavGraph(navController, sharedViewModel)
}
}
@Composable
fun PropertyWallet(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.requiredHeight(height = 56.dp)
.background(color = Color.White)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(end = 56.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
modifier = Modifier
.padding(all = 16.dp)
) {
Text(
text = "Wallet",
color = Color(0xff0b1f33),
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium),
modifier = Modifier
.fillMaxWidth())
}
}
}
}

View File

@ -0,0 +1,11 @@
package com.example.testapp.ui.theme
import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)

View File

@ -0,0 +1,70 @@
package com.example.testapp.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun TestAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View File

@ -0,0 +1,34 @@
package com.example.testapp.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)