Лаб 4: 0_o

This commit is contained in:
Safgerd 2023-12-27 02:36:24 +04:00
parent 442d1202b2
commit dd8628e0ce
44 changed files with 1914 additions and 1020 deletions

View File

@ -2,6 +2,7 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id ("kotlin-kapt")
id("com.google.dagger.hilt.android")
}
android {
@ -76,4 +77,15 @@ dependencies {
implementation ("androidx.room:room-runtime:2.5.0") // Библиотека "Room"
kapt ("androidx.room:room-compiler:2.5.0") // Кодогенератор
implementation ("androidx.room:room-ktx:2.5.0")
// lab4
implementation ("com.google.dagger:hilt-android:2.44")
kapt ("com.google.dagger:hilt-android-compiler:2.44")
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
implementation ("androidx.compose.runtime:runtime-livedata:1.0.0-beta01")
implementation ("androidx.datastore:datastore-preferences:1.0.0")
implementation ("androidx.paging:paging-runtime-ktx:3.2.1")
implementation ("androidx.paging:paging-compose:3.2.1")
implementation("androidx.room:room-paging:2.5.0")
}

View File

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".MobileApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"

View File

@ -0,0 +1,65 @@
package com.example.mobileapp
import android.app.Application
import androidx.room.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.repositories.CategoryRepository
import com.example.mobileapp.repositories.OrderProductRepository
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.ProductRepository
import com.example.mobileapp.repositories.RoleRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideDatabase(app: Application) : AppDatabase {
return Room.databaseBuilder(
app,
AppDatabase::class.java,
AppDatabase.DB_NAME
)
.fallbackToDestructiveMigration()
.build()
}
@Provides
@Singleton
fun provideCategoryRepository(db: AppDatabase) = CategoryRepository(db.categoryDao())
@Provides
@Singleton
fun provideOrderProductRepository(db: AppDatabase) = OrderProductRepository(db.orderProductDao())
@Provides
@Singleton
fun provideOrderRepository(db: AppDatabase) = OrderRepository(db.orderDao())
@Provides
@Singleton
fun provideProductRepository(db: AppDatabase) = ProductRepository(db.productDao())
@Provides
@Singleton
fun provideRoleRepository(db: AppDatabase) = RoleRepository(db.roleDao())
@Provides
@Singleton
fun provideStatusRepository(db: AppDatabase) = StatusRepository(db.statusDao())
@Provides
@Singleton
fun provideUserRepository(db: AppDatabase) = UserRepository(db.userDao())
}

View File

@ -3,22 +3,10 @@ package com.example.mobileapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Category
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.Status
import com.example.mobileapp.models.User
import com.example.mobileapp.navigation.AppNavigation
import com.example.mobileapp.navigation.listOfAdminNavItems
import com.example.mobileapp.navigation.listOfUserNavItems
import com.example.mobileapp.navigation.listOfWorkerNavItems
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@ -0,0 +1,11 @@
package com.example.mobileapp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MobileApp : Application() {
override fun onCreate() {
super.onCreate()
}
}

View File

@ -0,0 +1,23 @@
package com.example.mobileapp
import android.content.Context
import android.content.SharedPreferences
class PreferencesManager(context: Context) {
private val sharedPreferences: SharedPreferences =
context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
fun saveData(key: String, value: String) {
val editor = sharedPreferences.edit()
editor.putString(key, value)
editor.apply()
}
fun getData(key: String, defaultValue: String): String {
return sharedPreferences.getString(key, defaultValue) ?: defaultValue
}
fun deleteData(key: String) {
sharedPreferences.edit().remove(key).apply()
}
}

View File

@ -2,6 +2,7 @@ package com.example.mobileapp.dao
import androidx.room.*
import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow
import androidx.paging.PagingSource
@Dao
interface CategoryDao {
@ -17,8 +18,7 @@ interface CategoryDao {
@Query("select * from category where category.id = :id")
fun getById(id: Int) : Flow<Category>
@Query("select * from category where category.name = :name")
fun getByName(name: String) : Flow<CategoryWithProducts>
fun getByName(name: String) : Flow<Category>
@Query("select * from category")
fun getCategoryWithProducts() : Flow<List<CategoryWithProducts>>
}

View File

@ -1,4 +1,5 @@
package com.example.mobileapp.dao
import androidx.paging.PagingSource
import androidx.room.*
import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow
@ -6,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface OrderDao {
@Insert
suspend fun insert(order: Order)
suspend fun insert(order: Order) : Long
@Update
suspend fun update(order: Order)
@Delete
@ -14,14 +15,14 @@ interface OrderDao {
@Query("select * from `order`")
fun getAll() : Flow<List<OrderWithProducts>>
@Query("select * from `order` where `order`.`user_id` =:id")
fun getById(id: Int): Flow<List<OrderWithProducts>>
@Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4")
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>>
@Query("select * from `order` where `order`.`id` =:id")
fun getById(id: Int): Flow<OrderWithProducts>
@Query("select * from `order` where (`order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4)")
fun getOrdersByUserId(userId: Int): PagingSource<Int, OrderWithProducts>
@Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` = 1")
fun getCartByUserId(userId: Int): Flow<OrderWithProducts>
fun getCartByUserId(userId: Int): Flow<OrderWithProducts?>
@Query("select * from `order` where `order`.`status_id` != 1 and `order`.`status_id` != 4")
fun getOrdersToWork(): Flow<List<OrderWithProducts>>
fun getOrdersToWork(): PagingSource<Int, OrderWithProducts>
}

View File

@ -5,5 +5,11 @@ import com.example.mobileapp.models.OrderProduct
@Dao
interface OrderProductDao {
@Insert
suspend fun insert(order: OrderProduct)
suspend fun insert(orderProduct: OrderProduct)
@Update
suspend fun update(orderProduct: OrderProduct)
@Delete
suspend fun delete(orderProduct: OrderProduct)
@Query("delete from order_product WHERE order_id = :orderId AND product_id = :productId")
suspend fun deleteByProductId(orderId: Int, productId: Int);
}

View File

@ -1,7 +1,9 @@
package com.example.mobileapp.dao
import androidx.room.*
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product
import kotlinx.coroutines.flow.Flow
import androidx.paging.PagingSource
@Dao
interface ProductDao {
@ -16,4 +18,8 @@ interface ProductDao {
fun getAll() : Flow<List<Product>>
@Query("select * from product where product.id = :id")
fun getById(id: Int): Flow<Product>
@Query("select * from product where product.category_id = :categoryId")
fun getProductsByCategoryId(categoryId: Int) : PagingSource<Int, Product>
@Query("select * from category")
fun getCategoriesWithProducts() : PagingSource<Int, CategoryWithProducts>
}

View File

@ -22,4 +22,6 @@ interface StatusDao {
fun getAll() : Flow<List<Status>>
@Query("select * from status where status.id = :id")
fun getById(id: Int) : Flow<Status>
@Query("select * from status where status.name = :name")
fun getByName(name: String) : Flow<Status>
}

View File

@ -1,5 +1,7 @@
package com.example.mobileapp.dao
import androidx.paging.PagingSource
import androidx.room.*
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.User
import kotlinx.coroutines.flow.Flow
@ -14,7 +16,12 @@ interface UserDao {
@Query("select * from user order by login collate nocase asc")
fun getAll() : Flow<List<User>>
@Query("select * from user order by login collate nocase asc")
fun getAllPaged() : PagingSource<Int, User>
@Query("select * from user where user.id = :id")
fun getById(id: Int): User
fun getById(id: Int): Flow<User>
@Query("select * from user where user.login = :login and user.password = :password limit 1")
fun getByLoginAndPassword(login: String, password: String): Flow<User?>
}

View File

@ -19,7 +19,7 @@ import kotlinx.coroutines.launch
Product::class,
OrderProduct::class,
],
version = 1,
version = 2,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
@ -32,94 +32,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun orderProductDao() : OrderProductDao
companion object {
private const val DB_NAME: String = "mobileapp-db"
@Volatile
private var INSTANCE: AppDatabase? = null
private suspend fun populateDatabase() {
INSTANCE?.let { database ->
//Roles
val roleDao = database.roleDao()
roleDao.insert(Role(1, "admin"))
roleDao.insert(Role(2, "worker"))
roleDao.insert(Role(3, "user"))
//Statuses
val statusDao = database.statusDao()
statusDao.insert(Status(1, "Корзина"))
statusDao.insert(Status(2, "Принят"))
statusDao.insert(Status(3, "Готов"))
statusDao.insert(Status(4, "Выдан"))
//Categories
val categoryDao = database.categoryDao()
categoryDao.insert(Category(1, "Бургеры"))
categoryDao.insert(Category(2, "Картошка"))
categoryDao.insert(Category(3, "Напитки"))
//Users
val userDao = database.userDao()
userDao.insert(User(1, "admin", "admin", 1))
userDao.insert(User(2, "worker", "worker", 2))
userDao.insert(User(3, "user", "user", 3))
//Products
val productDao = database.productDao()
//Бургеры
productDao.insert(Product(1, "Бургер1", 1, 150))
productDao.insert(Product(2, "Бургер2", 1, 300))
productDao.insert(Product(3, "Бургер3", 1, 450))
//Картошка
productDao.insert(Product(4, "Картошка1", 2, 50))
productDao.insert(Product(5, "Картошка2", 2, 100))
productDao.insert(Product(6, "Картошка3", 2, 150))
//Напитки
productDao.insert(Product(7, "Напиток1", 3, 100))
productDao.insert(Product(8, "Напиток2", 3, 200))
productDao.insert(Product(9, "Напиток3", 3, 300))
//Orders
val orderDao = database.orderDao()
//Корзины
orderDao.insert(Order(1,1,400,1))
//Заказы
orderDao.insert(Order(2,1,250,3))
orderDao.insert(Order(3,1,400,2))
//region OrderProducts
val orderProductDao = database.orderProductDao()
//Корзины
orderProductDao.insert(OrderProduct(1,1,2))
orderProductDao.insert(OrderProduct(1,7,1))
//Заказы
orderProductDao.insert(OrderProduct(2,1,1))
orderProductDao.insert(OrderProduct(2,7,1))
orderProductDao.insert(OrderProduct(3,2,1))
orderProductDao.insert(OrderProduct(3,5,1))
}
}
fun getInstance(appContext: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
Room
.databaseBuilder(
appContext,
AppDatabase::class.java,
DB_NAME
)
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch {
populateDatabase()
}
}
})
.build()
.also { INSTANCE = it }
}
}
const val DB_NAME: String = "mobileapp-db"
}
}

View File

@ -14,9 +14,9 @@ data class Order(
@ColumnInfo(name = "user_id")
val userId: Int,
@ColumnInfo(name = "price")
val price: Int,
var price: Int,
@ColumnInfo(name = "status_id")
val statusId: Int,
var statusId: Int,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true

View File

@ -8,5 +8,5 @@ data class OrderProduct(
@ColumnInfo(name = "product_id", index = true)
var productId: Int,
@ColumnInfo(name = "amount")
val amount: Int
var amount: Int
)

View File

@ -11,7 +11,7 @@ data class User(
@ColumnInfo(name = "password")
val password: String,
@ColumnInfo(name = "role_id")
val roleId: Int
var roleId: Int
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true

View File

@ -30,6 +30,7 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.User
import com.example.mobileapp.screens.AuthorizationScreen
@ -74,13 +75,13 @@ fun AppNavigation(){
composable(route = Screens.OrderScreen.name){ OrderScreen() }
composable(route = Screens.AuthorizationScreen.name){ AuthorizationScreen(navController) }
composable(route = Screens.CreateProductScreen.name){ CreateProductScreen() }
composable(route = Screens.CreateProductScreen.name){ CreateProductScreen(navController) }
composable(route = Screens.EditMenuScreen.name){ EditMenuScreen(navController) }
composable(route = Screens.RegistrationScreen.name){ RegistrationScreen(navController) }
composable(route = Screens.UsersScreen.name){ UsersScreen() }
composable(route = Screens.EditProductScreen.name + "/{productId}"){ backStackEntry ->
val productId = backStackEntry.arguments?.getString("productId")
EditProductScreen(productId.toString().toInt())
EditProductScreen(navController, productId.toString().toInt())
}
}
}
@ -89,31 +90,24 @@ fun AppNavigation(){
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun CustomNavigationBar(navController: NavController) {
val user = remember { mutableStateOf(User(-1, "", "", -1)) }
val context = LocalContext.current
val sharedPref = PreferencesManager(LocalContext.current)
val user_role = sharedPref.getData("userRole", "user")
val listOfNavItems = remember { mutableStateListOf<NavItem>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
user.value = (AppDatabase.getInstance(context).userDao().getById(1))
(AppDatabase.getInstance(context).roleDao().getById(user.value.roleId)).collect{data ->
when (data.name) {
"admin" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfAdminNavItems)
}
"worker" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfWorkerNavItems)
}
"user" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfUserNavItems)
}
}
}
when (user_role) {
"admin" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfAdminNavItems)
}
"worker" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfWorkerNavItems)
}
"user" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfUserNavItems)
}
}
Row(
modifier = Modifier
.fillMaxWidth()

View File

@ -0,0 +1,18 @@
package com.example.mobileapp.repositories
import com.example.mobileapp.dao.CategoryDao
import com.example.mobileapp.models.Category
import javax.inject.Inject
import androidx.paging.*
import kotlinx.coroutines.flow.Flow
class CategoryRepository @Inject constructor(
private val categoryDao: CategoryDao
){
suspend fun insert(category: Category) = categoryDao.insert(category)
suspend fun update(category: Category) = categoryDao.update(category)
suspend fun delete(category: Category) = categoryDao.delete(category)
fun getAll() = categoryDao.getAll()
fun getById(id: Int) = categoryDao.getById(id)
fun getByName(name: String) = categoryDao.getByName(name)
}

View File

@ -0,0 +1,15 @@
package com.example.mobileapp.repositories
import com.example.mobileapp.dao.OrderProductDao
import com.example.mobileapp.dao.ProductDao
import com.example.mobileapp.models.OrderProduct
import com.example.mobileapp.models.Product
import javax.inject.Inject
class OrderProductRepository @Inject constructor(
private val orderProductDao: OrderProductDao
){
suspend fun insert(orderProduct: OrderProduct) = orderProductDao.insert(orderProduct)
suspend fun update(orderProduct: OrderProduct) = orderProductDao.update(orderProduct)
suspend fun delete(orderProduct: OrderProduct) = orderProductDao.delete(orderProduct)
}

View File

@ -0,0 +1,39 @@
package com.example.mobileapp.repositories
import com.example.mobileapp.dao.OrderDao
import androidx.paging.*
import com.example.mobileapp.dao.OrderProductDao
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderProduct
import com.example.mobileapp.models.OrderWithProducts
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class OrderRepository @Inject constructor(
private val orderDao: OrderDao
){
suspend fun insert(order: Order):Long {
return orderDao.insert(order)
}
suspend fun update(order: Order) = orderDao.update(order)
suspend fun delete(order: Order) = orderDao.delete(order)
fun getAll() = orderDao.getAll()
fun getById(id: Int) = orderDao.getById(id)
fun getOrdersByUserId(userId: Int) = Pager(
PagingConfig(
pageSize = 3,
enablePlaceholders = false
),
pagingSourceFactory = { orderDao.getOrdersByUserId(userId) }
).flow
fun getCartByUserId(userId: Int) : Flow<OrderWithProducts?> {
return orderDao.getCartByUserId(userId)
}
fun getOrdersToWork() = Pager(
PagingConfig(
pageSize = 3,
enablePlaceholders = false
),
pagingSourceFactory = { orderDao.getOrdersToWork() }
).flow
}

View File

@ -0,0 +1,37 @@
package com.example.mobileapp.repositories
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import com.example.mobileapp.dao.ProductDao
import com.example.mobileapp.dao.RoleDao
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.Role
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class ProductRepository @Inject constructor(
private val productDao: ProductDao
){
suspend fun insert(product: Product) = productDao.insert(product)
suspend fun update(product: Product) = productDao.update(product)
suspend fun delete(product: Product) = productDao.delete(product)
fun getAll() = productDao.getAll()
fun getById(id: Int) = productDao.getById(id)
fun getProductsByCategoryId(categoryId: Int) = Pager(
PagingConfig(
pageSize = 3,
enablePlaceholders = false
),
pagingSourceFactory = { productDao.getProductsByCategoryId(categoryId) }
).flow
fun getCategoriesWithProducts() = Pager(
PagingConfig(
pageSize = 3,
enablePlaceholders = false
),
pagingSourceFactory = { productDao.getCategoriesWithProducts() }
).flow
}

View File

@ -0,0 +1,16 @@
package com.example.mobileapp.repositories
import com.example.mobileapp.dao.RoleDao
import com.example.mobileapp.models.Role
import javax.inject.Inject
class RoleRepository @Inject constructor(
private val roleDao: RoleDao
){
suspend fun insert(role: Role) = roleDao.insert(role)
suspend fun update(role:Role) = roleDao.update(role)
suspend fun delete(role:Role) = roleDao.delete(role)
fun getAll() = roleDao.getAll()
fun getById(id: Int) = roleDao.getById(id)
fun getByName(name: String) = roleDao.getByName(name)
}

View File

@ -0,0 +1,17 @@
package com.example.mobileapp.repositories
import com.example.mobileapp.dao.StatusDao
import com.example.mobileapp.models.Status
import javax.inject.Inject
class StatusRepository @Inject constructor(
private val statusDao: StatusDao
){
suspend fun insert(status: Status) = statusDao.insert(status)
suspend fun update(status: Status) = statusDao.update(status)
suspend fun delete(status: Status) = statusDao.delete(status)
fun getAll() = statusDao.getAll()
fun getById(id: Int) = statusDao.getById(id)
fun getByName(name: String) = statusDao.getByName(name)
}

View File

@ -0,0 +1,27 @@
package com.example.mobileapp.repositories
import androidx.paging.Pager
import androidx.paging.PagingConfig
import com.example.mobileapp.dao.RoleDao
import com.example.mobileapp.dao.UserDao
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.User
import javax.inject.Inject
class UserRepository @Inject constructor(
private val userDao: UserDao
){
suspend fun insert(user: User) = userDao.insert(user)
suspend fun update(user: User) = userDao.update(user)
suspend fun delete(user: User) = userDao.delete(user)
fun getAll() = userDao.getAll()
fun getAllPaged() = Pager(
PagingConfig(
pageSize = 6,
enablePlaceholders = false
),
pagingSourceFactory = { userDao.getAllPaged() }
).flow
fun getById(id: Int) = userDao.getById(id)
fun getByLoginAndPassword(login: String, password: String) = userDao.getByLoginAndPassword(login, password)
}

View File

@ -7,29 +7,37 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
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.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.AuthorizationViewModel
import com.example.mobileapp.widgets.Header
@Composable
@ -46,9 +54,50 @@ fun AuthorizationScreen(navController: NavController) {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AuthorizationCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val login = remember { mutableStateOf(TextFieldValue("")) }
val password = remember { mutableStateOf(TextFieldValue("")) }
val viewModel = hiltViewModel<AuthorizationViewModel>()
val success = viewModel.successState.observeAsState().value
if (success == true) {
navController.navigate(Screens.MenuScreen.name)
}
if (success == false) {
AlertDialog(
title = {
Text(
text = "Ошибка авторизации",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
},
text = {
Text(
text = "Неверный логин или пароль",
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
},
onDismissRequest = {
viewModel.calmSuccessState()
},
confirmButton = {
TextButton(
onClick = {
viewModel.calmSuccessState()
}
) {
Text("ОК")
}
}
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
@ -124,10 +173,7 @@ fun AuthorizationCard(navController: NavController){
Button(
onClick = {
navController.navigate(Screens.MenuScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
viewModel.login(sharedPref, login.value.text, password.value.text)
},
colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White),
shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp),
@ -147,10 +193,7 @@ fun AuthorizationCard(navController: NavController){
Button(
onClick = {
navController.navigate(Screens.RegistrationScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
navController.navigate(Screens.RegistrationScreen.name)
},
colors = ButtonDefaults.buttonColors(Color(212,206,203)),
modifier = Modifier

View File

@ -13,16 +13,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -31,19 +28,16 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderProductWithProduct
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.viewmodels.CartViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
fun CartScreen(){
@ -59,6 +53,11 @@ fun CartScreen(){
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun CartCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
cartViewModel.retrieveUser(sharedPref)
val cart: OrderWithProducts? = cartViewModel.cart.observeAsState().value
Column(
modifier = Modifier
.fillMaxSize()
@ -84,187 +83,187 @@ fun CartCard(){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
val cartWithProducts = remember { mutableStateOf(OrderWithProducts(Order(-1, -1, -1, -1), listOf())) }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).orderDao().getCartByUserId(1).collect { data ->
cartWithProducts.value = data
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(cartWithProducts.value.orderWithProducts){ cartProduct ->
val amount = remember { mutableStateOf(TextFieldValue(cartProduct.orderProduct.amount.toString())) }
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
val category = remember { mutableStateOf("")}
scope.launch {
AppDatabase.getInstance(context).categoryDao().getById(cartProduct.product.categoryId).collect { data ->
category.value = data.name
}
}
if (category.value == "Бургеры"){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (category.value == "Картошка"){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (category.value == "Напитки"){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = cartProduct.product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Text(
text = cartProduct.product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth(0.8f)
){
OutlinedButton(
modifier = Modifier
.fillMaxHeight(),
onClick = {
/*TODO*/
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topStart = 30.dp, bottomStart = 30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "-", fontSize = 20.sp, color = Color.Black)
}
Card(
modifier = Modifier
.fillMaxHeight(),
border = BorderStroke(3.dp, Color(222,161,69)),
shape = RoundedCornerShape(0.dp),
){
Text(
modifier = Modifier
.background(Color.White)
.fillMaxHeight()
.padding(start = 20.dp, end = 20.dp, top = 7.dp, bottom = 7.dp),
text = amount.value.text,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
OutlinedButton(
modifier = Modifier
.fillMaxHeight(),
onClick = {
/*TODO*/
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "+", fontSize = 20.sp, color = Color.Black)
}
}
}
}
}
}
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
if (cart != null && cart.orderWithProducts.size != 0) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
){
Text(
text = "Итого: " + cartWithProducts.value.order.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(start = 5.dp),
)
items(cart.orderWithProducts.size) { index ->
CartProductCard(cartViewModel, cart.orderWithProducts[index])
}
}
OutlinedButton(
onClick = {
/*TODO*/
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
modifier = Modifier.padding(5.dp)
) {
Text(text = "Заказать", fontSize = 20.sp, color = Color.White)
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
){
Text(
text = "Итого: " + cart.order.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(start = 5.dp),
)
OutlinedButton(
onClick = {
cartViewModel.makeOrder()
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
modifier = Modifier.padding(5.dp)
) {
Text(text = "Заказать", fontSize = 20.sp, color = Color.White)
}
}
}
}
}
}
}
@Composable
fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProduct){
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
CartProductImageCard(product.product.categoryId)
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = product.product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Text(
text = product.product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth(0.8f)
){
OutlinedButton(
modifier = Modifier
.fillMaxHeight(),
onClick = {
cartViewModel.removeProductFromOrder(product.product.id!!)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topStart = 30.dp, bottomStart = 30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "-", fontSize = 20.sp, color = Color.Black)
}
Card(
modifier = Modifier
.fillMaxHeight(),
border = BorderStroke(3.dp, Color(222,161,69)),
shape = RoundedCornerShape(0.dp),
){
Text(
modifier = Modifier
.background(Color.White)
.fillMaxHeight()
.padding(
start = 20.dp,
end = 20.dp,
top = 7.dp,
bottom = 7.dp
),
text = product.orderProduct.amount.toString(),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
OutlinedButton(
modifier = Modifier
.fillMaxHeight(),
onClick = {
cartViewModel.addProductToOrder(product.product.id!!)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "+", fontSize = 20.sp, color = Color.Black)
}
}
}
}
}
}
@Composable
fun CartProductImageCard(categoryId : Int){
if (categoryId == 1){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryId == 2){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryId == 3){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
}

View File

@ -22,8 +22,8 @@ import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -31,7 +31,6 @@ 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.Font
import androidx.compose.ui.text.font.FontFamily
@ -39,39 +38,50 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.ProductViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun CreateProductScreen(){
fun CreateProductScreen(navController: NavController){
Column (
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Header(Color(212, 206, 203))
CreateProductCard()
CreateProductCard(navController)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreateProductCard(){
fun CreateProductCard(navController: NavController){
val productViewModel: ProductViewModel = hiltViewModel<ProductViewModel>()
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
val categoryList = remember { mutableStateListOf(productViewModel.categories) }
var selectedCategory by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val success = productViewModel.successState.observeAsState().value
if (success == true) {
navController.navigate(Screens.ManagmentScreen.name)
}
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(212, 206, 203)),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.9f)
.background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
@ -84,9 +94,6 @@ fun CreateProductCard(){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -127,19 +134,6 @@ fun CreateProductCard(){
onSurface = Color.Gray
)
){
val categoryList = remember { mutableStateListOf<String>() }
var selectedCategory by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val context = LocalContext.current
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).categoryDao().getAll().collect { data ->
categoryList.clear()
categoryList.addAll(data.map { category -> category.name })
selectedCategory = data.first().name
}
}
}
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
@ -162,7 +156,7 @@ fun CreateProductCard(){
expanded = false
},
) {
categoryList.forEach { selectionOption ->
categoryList.first().forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
@ -195,10 +189,9 @@ fun CreateProductCard(){
.fillMaxWidth()
.padding(top = 20.dp, start = 20.dp, end = 20.dp),
)
OutlinedButton(
onClick = {
/*TODO*/
productViewModel.addProduct(title.value.text, selectedCategory, price.value.text)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),

View File

@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
@ -20,10 +19,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton
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.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -34,14 +29,18 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Category
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.MenuViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun EditMenuScreen(navController: NavController){
@ -56,6 +55,11 @@ fun EditMenuScreen(navController: NavController){
@Composable
fun EditMenuCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
Column(
modifier = Modifier
.fillMaxSize()
@ -71,146 +75,156 @@ fun EditMenuCard(navController: NavController){
horizontalAlignment = Alignment.CenterHorizontally,
) {
val categoryWithProducts = remember { mutableStateListOf<CategoryWithProducts>() }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).categoryDao().getCategoryWithProducts().collect { data ->
categoryWithProducts.addAll(data)
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
items(categoryWithProducts){ item ->
items(
count = categoriesWithProducts.itemCount,
key = categoriesWithProducts.itemKey()
){ index ->
EditMenuCategoryProductsCard(navController, menuViewModel, categoriesWithProducts[index]!!)
}
}
}
}
}
@Composable
fun EditMenuCategoryProductsCard(navController: NavController, menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){
if (categoryWithProducts.products.size == 0){
return
}
Text(
text = categoryWithProducts.category.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
categoryWithProducts.products.forEach{ product ->
EditMenuProductsCard(navController, menuViewModel, product, categoryWithProducts.category)
}
}
@Composable
fun EditMenuProductsCard(navController: NavController, menuViewModel : MenuViewModel, product : Product, category: Category){
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
EditMenuProductImageCard(category.name)
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
){
Text(
text = item.category.name,
text = product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
OutlinedButton(
onClick = {
navController.navigate(Screens.EditProductScreen.name + "/${product.id}")
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
item.products.forEach{ product ->
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
if (item.category.name == "Бургеры"){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (item.category.name == "Картошка"){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (item.category.name == "Напитки"){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
Icon(
painterResource(id = R.drawable.icon_settings),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
){
Text(
text = product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
OutlinedButton(
onClick = {
navController.navigate(Screens.EditProductScreen.name + "/${product.id}") {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
OutlinedButton(
onClick = {
menuViewModel.deleteProduct(product)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_settings),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
OutlinedButton(
onClick = { /*TODO*/},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_trash),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
}
}
}
}
){
Icon(
painterResource(id = R.drawable.icon_trash),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
}
}
}
}
}
@Composable
fun EditMenuProductImageCard(categoryName : String){
if (categoryName == "Бургеры"){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryName == "Картошка"){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryName == "Напитки"){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
}

View File

@ -23,8 +23,8 @@ import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -33,7 +33,6 @@ 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.Font
import androidx.compose.ui.text.font.FontFamily
@ -41,28 +40,55 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Product
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.ProductViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
fun EditProductScreen(id: Int){
fun EditProductScreen(navController: NavController, id: Int){
Column (
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Header(Color(212, 206, 203))
EditProductCard(id)
EditProductCard(navController, id)
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditProductCard(id: Int){
fun EditProductCard(navController: NavController, productId : Int){
val scope = rememberCoroutineScope()
val productViewModel: ProductViewModel = hiltViewModel<ProductViewModel>()
productViewModel.getProduct(productId)
val currentProduct = remember { mutableStateOf<Product?>(null) }
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
val categoryList = remember { mutableStateListOf(productViewModel.categories) }
var selectedCategory by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val success = productViewModel.successState.observeAsState().value
if (productViewModel.product.value != null){
currentProduct.value = productViewModel.product.value!!
title.value = TextFieldValue(productViewModel.product.value!!.name)
price.value = TextFieldValue(productViewModel.product.value!!.price.toString())
scope.launch {
selectedCategory = productViewModel.getCategory(productViewModel.product.value!!.categoryId)
}
}
if (success == true) {
navController.navigate(Screens.EditMenuScreen.name)
}
Column(
modifier = Modifier
.fillMaxSize()
@ -88,25 +114,6 @@ fun EditProductCard(id: Int){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
val context = LocalContext.current
var selectedCategory by remember { mutableStateOf("") }
var expanded by remember { mutableStateOf(false) }
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).productDao().getById(id).collect {data ->
title.value = TextFieldValue(data.name)
price.value = TextFieldValue(data.price.toString())
AppDatabase.getInstance(context).categoryDao().getById(data.categoryId).collect {
selectedCategory = it.name
}
}
}
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -138,7 +145,9 @@ fun EditProductCard(id: Int){
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(1.dp, Color(222,161,69)),
modifier = Modifier.fillMaxWidth().padding(top = 20.dp, start = 20.dp, end = 20.dp),
modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp, start = 20.dp, end = 20.dp),
){
MaterialTheme(
@ -148,13 +157,6 @@ fun EditProductCard(id: Int){
onSurface = Color.Gray
)
){
val categoryList = remember { mutableStateListOf<String>() }
scope.launch {
AppDatabase.getInstance(context).categoryDao().getAll().collect { data ->
categoryList.clear()
categoryList.addAll(data.map { category -> category.name })
}
}
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
@ -163,7 +165,8 @@ fun EditProductCard(id: Int){
) {
TextField(
modifier = Modifier
.menuAnchor().fillMaxWidth(),
.menuAnchor()
.fillMaxWidth(),
readOnly = true,
value = selectedCategory,
onValueChange = {},
@ -177,7 +180,7 @@ fun EditProductCard(id: Int){
expanded = false
},
) {
categoryList.forEach { selectionOption ->
categoryList.first().forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
@ -213,7 +216,7 @@ fun EditProductCard(id: Int){
OutlinedButton(
onClick = {
/*TODO*/
productViewModel.updateProduct(currentProduct.value?.id!!, title.value.text, selectedCategory, price.value.text)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),

View File

@ -74,10 +74,7 @@ fun ManagmentCard(navController: NavController){
){
OutlinedButton(
onClick = {
navController.navigate(Screens.CreateProductScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
navController.navigate(Screens.CreateProductScreen.name)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
@ -94,10 +91,7 @@ fun ManagmentCard(navController: NavController){
OutlinedButton(
onClick = {
navController.navigate(Screens.EditMenuScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
navController.navigate(Screens.EditMenuScreen.name)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
@ -124,10 +118,7 @@ fun ManagmentCard(navController: NavController){
)
OutlinedButton(
onClick = {
navController.navigate(Screens.UsersScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
navController.navigate(Screens.UsersScreen.name)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),

View File

@ -12,18 +12,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
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.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -34,13 +28,16 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Category
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.viewmodels.MenuViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun MenuScreen(){
@ -55,6 +52,11 @@ fun MenuScreen(){
@Composable
fun MenuCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
Column(
modifier = Modifier
.fillMaxSize()
@ -70,119 +72,132 @@ fun MenuCard(){
horizontalAlignment = Alignment.CenterHorizontally,
) {
val categoryWithProducts = remember { mutableStateListOf<CategoryWithProducts>()}
val context = LocalContext.current
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
(AppDatabase.getInstance(context).categoryDao().getCategoryWithProducts()).collect { data ->
categoryWithProducts.addAll(data)
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
items(categoryWithProducts){ item ->
items(
count = categoriesWithProducts.itemCount,
key = categoriesWithProducts.itemKey()
){ index ->
MenuCategoryProductsCard(menuViewModel, categoriesWithProducts[index]!!)
}
}
}
}
}
@Composable
fun MenuCategoryProductsCard(menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){
if (categoryWithProducts.products.size == 0){
return
}
Text(
text = categoryWithProducts.category.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
categoryWithProducts.products.forEach{ product ->
MenuProductsCard(menuViewModel, product, categoryWithProducts.category)
}
}
@Composable
fun MenuProductsCard(menuViewModel : MenuViewModel, product : Product, category: Category){
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
MenuProductImageCard(category.name)
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
){
Text(
text = item.category.name,
text = product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
item.products.forEach{ product ->
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
if (item.category.name == "Бургеры"){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (item.category.name == "Картошка"){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (item.category.name == "Напитки"){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
Text(
text = product.name,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
){
Text(
text = product.price.toString() + " р.",
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
)
OutlinedButton(
onClick = {/*TODO*/},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "+", fontSize = 20.sp, color = Color.Black)
}
}
}
}
}
OutlinedButton(
onClick = {
menuViewModel.addProductToCart(product.id!!)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(30.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
) {
Text(text = "+", fontSize = 20.sp, color = Color.Black)
}
}
}
}
}
}
@Composable
fun MenuProductImageCard(categoryName : String){
if (categoryName == "Бургеры"){
Image(
painterResource(
id = R.drawable.burger
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryName == "Картошка"){
Image(
painterResource(
id = R.drawable.potato
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
if (categoryName == "Напитки"){
Image(
painterResource(
id = R.drawable.pepsi
),
contentDescription = null,
modifier = Modifier
.size(100.dp, 100.dp)
.padding(5.dp),
)
}
}

View File

@ -11,35 +11,34 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.viewmodels.OrderViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
fun OrderScreen(){
@ -48,13 +47,16 @@ fun OrderScreen(){
horizontalAlignment = Alignment.CenterHorizontally,
) {
Header(Color(212, 206, 203))
OrderCard()
OrdersCard()
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun OrderCard(){
fun OrdersCard(){
val orderViewModel: OrderViewModel = hiltViewModel<OrderViewModel>()
val orderListUiState = orderViewModel.orderList.observeAsState().value?.collectAsLazyPagingItems()
Column(
modifier = Modifier
.fillMaxSize()
@ -80,121 +82,17 @@ fun OrderCard(){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
val ordersWithProducts = remember { mutableStateListOf<OrderWithProducts> () }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).orderDao().getOrdersToWork().collect { data ->
ordersWithProducts.addAll(data)
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(ordersWithProducts){ order ->
val status = remember { mutableStateOf("")}
scope.launch {
AppDatabase.getInstance(context).statusDao().getById(order.order.statusId).collect { data ->
status.value = data.name
}
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
Text(
text = "" + order.order.id,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
textAlign = TextAlign.Center,
)
Text(
text = "Статус: " + status.value,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
){
Column {
order.orderWithProducts.forEach{ orderProduct ->
Row(
modifier = Modifier
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
){
Text(
text = orderProduct.product.name + " x" + orderProduct.orderProduct.amount.toString(),
color = Color.Gray,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
}
}
if (order.order.statusId == 2){
OutlinedButton(
onClick = {
/*TODO*/
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
modifier = Modifier.padding(bottom = 10.dp)
) {
Text(
text = "Готов",
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 30.sp,
color = Color.White
)
}
}
if (order.order.statusId == 3){
OutlinedButton(
onClick = {
/*TODO*/
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
modifier = Modifier.padding(bottom = 10.dp)
) {
Text(
text = "Выдать",
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 30.sp,
color = Color.White
)
}
}
if (orderListUiState != null){
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(
count = orderListUiState.itemCount,
key = orderListUiState.itemKey()
){ index ->
if (orderListUiState[index] != null){
OrderCard(orderListUiState[index]!!, orderViewModel)
}
}
}
@ -202,3 +100,97 @@ fun OrderCard(){
}
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun OrderCard(order: OrderWithProducts, orderViewModel: OrderViewModel){
val scope = rememberCoroutineScope()
var status by remember { mutableStateOf("")}
scope.launch {
status = orderViewModel.getOrderStatus(order.order.statusId)
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
Text(
text = "" + order.order.id,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
textAlign = TextAlign.Center,
)
Text(
text = "Статус: " + status,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
){
Column {
if (order.orderWithProducts.size != 0){
order.orderWithProducts.forEach{ orderProduct ->
Row(
modifier = Modifier
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
){
Text(
text = orderProduct.product.name + " x" + orderProduct.orderProduct.amount.toString(),
color = Color.Gray,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
}
}
}
OutlinedButton(
onClick = {
orderViewModel.changeOrderStatus(order.order.id!!)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
modifier = Modifier.padding(bottom = 10.dp)
) {
if (order.order.statusId == 2){
Text(
text = "Готов",
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 30.sp,
color = Color.White
)
}
if (order.order.statusId == 3){
Text(
text = "Выдать",
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 30.sp,
color = Color.White
)
}
}
}
}
}

View File

@ -11,15 +11,12 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
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.runtime.rememberCoroutineScope
@ -32,15 +29,17 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.ProfileViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
fun ProfileScreen(navController: NavController){
@ -56,12 +55,15 @@ fun ProfileScreen(navController: NavController){
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun ProfileCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val profileViewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>()
val activeOrdersListUiState = profileViewModel.getActiveOrders(sharedPref.getData("userId", "-1").toInt())?.collectAsLazyPagingItems()
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(212, 206, 203)),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
modifier = Modifier
@ -76,10 +78,8 @@ fun ProfileCard(navController: NavController){
.fillMaxWidth()
.padding(top = 15.dp, start = 5.dp, end = 5.dp),
onClick = {
navController.navigate(Screens.AuthorizationScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
profileViewModel.logout(sharedPref)
navController.navigate(Screens.AuthorizationScreen.name)
},
border = BorderStroke(4.dp, Color(255,86,86)),
shape = RoundedCornerShape(20.dp),
@ -104,94 +104,92 @@ fun ProfileCard(navController: NavController){
textAlign = TextAlign.Center,
)
val ordersWithProducts = remember { mutableStateListOf<OrderWithProducts> () }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).orderDao().getByUserId(1).collect { data ->
ordersWithProducts.clear()
ordersWithProducts.addAll(data)
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(ordersWithProducts){ order ->
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
Text(
text = "" + order.order.id.toString(),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
textAlign = TextAlign.Center,
)
val status = remember { mutableStateOf("")}
scope.launch {
AppDatabase.getInstance(context).statusDao().getById(order.order.statusId).collect { data ->
status.value = data.name
}
}
Text(
text = "Статус: " + status.value,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
order.orderWithProducts.forEach{ orderProduct ->
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
){
Text(
text = orderProduct.product.name + " " + orderProduct.product.price.toString() + "р. x" + orderProduct.orderProduct.amount.toString(),
color = Color.Gray,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
){
Text(
text = "К оплате: " + order.order.price.toString() + " р.",
modifier = Modifier.padding(start = 20.dp),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
if (activeOrdersListUiState != null){
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
items(
count = activeOrdersListUiState.itemCount,
key = activeOrdersListUiState.itemKey()
){ index ->
ActiveOrderCard(activeOrdersListUiState[index]!!, profileViewModel)
}
}
}
}
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun ActiveOrderCard(order: OrderWithProducts, profileViewModel: ProfileViewModel) {
val scope = rememberCoroutineScope()
val status = remember { mutableStateOf("")}
scope.launch {
status.value = profileViewModel.getOrderStatus(order.order.statusId)
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
) {
Text(
text = "" + order.order.id.toString(),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp,
textAlign = TextAlign.Center,
)
Text(
text = "Статус: " + status.value,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
order.orderWithProducts.forEach { orderProduct ->
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Text(
text = orderProduct.product.name + " " + orderProduct.product.price.toString() + "р. x" + orderProduct.orderProduct.amount.toString(),
color = Color.Gray,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
) {
Text(
text = "К оплате: " + order.order.price.toString() + " р.",
modifier = Modifier.padding(start = 20.dp),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 20.sp,
textAlign = TextAlign.Center,
)
}
}
}

View File

@ -7,14 +7,17 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@ -23,13 +26,16 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.RegistrationViewModel
import com.example.mobileapp.widgets.Header
@Composable
@ -50,6 +56,44 @@ fun RegistrationCard(navController: NavController){
val password = remember { mutableStateOf(TextFieldValue("")) }
val passwordRepeat = remember { mutableStateOf(TextFieldValue("")) }
val viewModel = hiltViewModel<RegistrationViewModel>()
val success = viewModel.successState.observeAsState().value
if (success == true) {
navController.navigate(Screens.AuthorizationScreen.name)
}
if (success == false) {
AlertDialog(
title = {
Text(
text = "Ошибка регистрации",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
},
text = {
Text(
text = "Проверьте корректность введенных данных",
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
},
onDismissRequest = {
viewModel.calmSuccessState()
},
confirmButton = {
TextButton(
onClick = {
viewModel.calmSuccessState()
}
) {
Text("ОК")
}
}
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
@ -146,10 +190,7 @@ fun RegistrationCard(navController: NavController){
Button(
onClick = {
navController.navigate(Screens.MenuScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
viewModel.registration(login.value.text, password.value.text, passwordRepeat.value.text)
},
colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White),
shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp),
@ -169,10 +210,7 @@ fun RegistrationCard(navController: NavController){
Button(
onClick = {
navController.navigate(Screens.AuthorizationScreen.name) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
navController.navigate(Screens.AuthorizationScreen.name)
},
colors = ButtonDefaults.buttonColors(Color(212,206,203)),
modifier = Modifier

View File

@ -30,6 +30,7 @@ import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
@ -49,11 +50,21 @@ 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.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.map
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.User
import com.example.mobileapp.viewmodels.UsersViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -69,9 +80,12 @@ fun UsersScreen() {
}
@SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UsersCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val usersViewModel: UsersViewModel = hiltViewModel<UsersViewModel>()
val userListUiState = usersViewModel.getUsersList().collectAsLazyPagingItems()
Column(
modifier = Modifier
.fillMaxSize()
@ -97,141 +111,17 @@ fun UsersCard(){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
val users = remember { mutableStateListOf<User> () }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).userDao().getAll().collect { data ->
users.addAll(data)
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
items(users){ user ->
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround,
modifier = Modifier.fillMaxWidth(0.4f)
) {
Text(
text = "Логин: " + user.login,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 5.dp)
)
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(1.dp, Color(222,161,69)),
modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
){
val roleList = remember { mutableStateListOf<String>() }
var expanded by remember { mutableStateOf(false) }
var selectedRole by remember { mutableStateOf("") }
scope.launch {
AppDatabase.getInstance(context).roleDao().getAll().collect { data ->
roleList.clear()
roleList.addAll(data.map {role -> role.name})
}
}
scope.launch {
AppDatabase.getInstance(context).roleDao().getById(user.roleId).collect { data ->
selectedRole = data.name
}
}
MaterialTheme(
colorScheme = lightColorScheme(
surfaceVariant= Color.White,
surface = Color.White,
onSurface = Color.Gray
)
){
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
},
) {
TextField(
modifier = Modifier
.menuAnchor().fillMaxWidth(),
readOnly = true,
value = selectedRole,
onValueChange = {},
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
},
) {
roleList.forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
selectedRole = selectionOption
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
}
}
}
OutlinedButton(
onClick = { /*TODO*/},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_settings),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
OutlinedButton(
onClick = { /*TODO*/},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_trash),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
if (userListUiState != null){
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
items(
count = userListUiState.itemCount,
key = userListUiState.itemKey()
){ index ->
if (userListUiState[index]!!.id != sharedPref.getData("userId", "-1").toInt()){
UserCard(userListUiState[index]!!, usersViewModel)
}
}
}
@ -239,3 +129,131 @@ fun UsersCard(){
}
}
}
@SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserCard (user: User, usersViewModel: UsersViewModel){
val scope = rememberCoroutineScope()
val roleList = remember { mutableStateListOf(usersViewModel.roles)}
var selectedRole by remember { mutableStateOf("")}
scope.launch {
selectedRole = usersViewModel.getUserRole(user)
}
var expanded by remember { mutableStateOf(false) }
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxSize()
.padding(top = 15.dp, start = 5.dp, end = 5.dp)
){
Row(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
){
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround,
modifier = Modifier.fillMaxWidth(0.4f)
) {
Text(
text = "Логин: " + user.login,
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 17.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 5.dp)
)
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(1.dp, Color(222,161,69)),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp),
){
MaterialTheme(
colorScheme = lightColorScheme(
surfaceVariant= Color.White,
surface = Color.White,
onSurface = Color.Gray
)
){
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
},
) {
TextField(
modifier = Modifier
.menuAnchor()
.fillMaxWidth(),
readOnly = true,
value = selectedRole,
onValueChange = {},
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
},
) {
roleList.first().forEach {selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
selectedRole = selectionOption
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
}
}
}
OutlinedButton(
onClick = {
usersViewModel.changeUserRole(user.id!!, selectedRole)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_settings),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
OutlinedButton(
onClick = {
usersViewModel.deleteUser(user.id!!)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
){
Icon(
painterResource(id = R.drawable.icon_trash),
contentDescription = null,
Modifier.size(30.dp),
tint = Color.Black
)
}
}
}
}

View File

@ -0,0 +1,73 @@
package com.example.mobileapp.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.models.Category
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.Status
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.CategoryRepository
import com.example.mobileapp.repositories.RoleRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class AuthorizationViewModel @Inject constructor(
private val userRepository: UserRepository,
private val categoryRepository: CategoryRepository,
private val roleRepository: RoleRepository,
private val statusRepository: StatusRepository,
) : ViewModel() {
private val _successState = MutableLiveData<Boolean?>()
val successState: LiveData<Boolean?>
get() = _successState
init {
addAdmin()
}
fun calmSuccessState() {
_successState.postValue(null)
}
fun login(sharedPref: PreferencesManager, login: String, password: String) {
viewModelScope.launch {
userRepository.getByLoginAndPassword(login, password).collect {
if (it == null) {
_successState.postValue(false)
} else {
sharedPref.saveData("userId", it.id.toString())
sharedPref.saveData("userRole", roleRepository.getById(it.roleId).first().name)
_successState.postValue(true)
}
}
}
}
private fun addAdmin() {
viewModelScope.launch {
userRepository.getAll().collect {
if (it.size == 0) {
roleRepository.insert(Role(1, "admin"))
roleRepository.insert(Role(2, "worker"))
roleRepository.insert(Role(3, "user"))
statusRepository.insert(Status(1, "Корзина"))
statusRepository.insert(Status(2, "Принят"))
statusRepository.insert(Status(3, "Готов"))
statusRepository.insert(Status(4, "Выдан"))
categoryRepository.insert(Category(1, "Бургеры"))
categoryRepository.insert(Category(2, "Картошка"))
categoryRepository.insert(Category(3, "Напитки"))
userRepository.insert(User(1, "admin", "admin", 1))
}
}
}
}
}

View File

@ -0,0 +1,102 @@
package com.example.mobileapp.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.models.OrderProduct
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.OrderProductRepository
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class CartViewModel @Inject constructor(
private val orderRepository: OrderRepository,
private val orderProductRepository: OrderProductRepository,
private val statusRepository: StatusRepository,
private val userRepository: UserRepository
) : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User>
get() = _user
private val _cart = MutableLiveData<OrderWithProducts?>()
val cart: LiveData<OrderWithProducts?>
get() = _cart
fun retrieveUser(sharedPref: PreferencesManager) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
viewModelScope.launch {
userRepository.getById(userId).collect {
_user.postValue(it)
}
}
viewModelScope.launch {
orderRepository.getCartByUserId(userId).collect{
_cart.postValue(it)
}
}
}
fun makeOrder() {
viewModelScope.launch {
val model = cart.value!!.order
model.statusId = statusRepository.getByName("Принят").first().id!!
orderRepository.update(model)
}
}
fun removeProductFromOrder(productId: Int) {
val orderModel = cart.value!!.order
var productModel : OrderProduct? = null
cart.value!!.orderWithProducts.map {
if (it.orderProduct.productId == productId){
productModel = it.orderProduct
orderModel.price -= it.product.price
}
}
if(productModel!!.amount == 1) {
// delete
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.delete(productModel!!)
}
}
else{
// update
productModel!!.amount -= 1
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.update(productModel!!)
}
}
}
fun addProductToOrder(productId: Int) {
val orderModel = cart.value!!.order
var productModel : OrderProduct? = null
cart.value!!.orderWithProducts.map {
if (it.orderProduct.productId == productId){
productModel = it.orderProduct
orderModel.price += it.product.price
}
}
// update
productModel!!.amount += 1
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.update(productModel!!)
}
}
}

View File

@ -0,0 +1,87 @@
package com.example.mobileapp.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderProduct
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.CategoryRepository
import com.example.mobileapp.repositories.OrderProductRepository
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.ProductRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import javax.inject.Inject
@HiltViewModel
class MenuViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val orderRepository: OrderRepository,
private val orderProductRepository: OrderProductRepository,
private val userRepository: UserRepository
) : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User>
get() = _user
fun retrieveUser(sharedPref: PreferencesManager) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
viewModelScope.launch {
userRepository.getById(userId).collect {
_user.postValue(it)
}
}
}
val categoiesWithProductsListUiState: Flow<PagingData<CategoryWithProducts>> = productRepository.getCategoriesWithProducts()
fun deleteProduct(product : Product) {
viewModelScope.launch {
productRepository.delete(product)
}
}
fun addProductToCart(productId: Int) {
viewModelScope.launch {
val product = productRepository.getById(productId).first()
val order = orderRepository.getCartByUserId(user.value?.id!!).first()
if (order == null) {
val newOrderId = orderRepository.insert(Order(null, user.value?.id!!, product.price, 1 ))
orderProductRepository.insert(OrderProduct(newOrderId.toInt(), productId, 1))
}
else {
var isAlreadyAdded = false
for (prod in order.orderWithProducts) {
if (prod.product.id == productId) {
val newOrderProduct = prod.orderProduct
newOrderProduct.amount += 1
val newOrder = order.order
newOrder.price += prod.product.price
orderProductRepository.update(newOrderProduct)
orderRepository.update(newOrder)
isAlreadyAdded = true
}
}
if (!isAlreadyAdded) {
orderProductRepository.insert(OrderProduct(order.order.id!!, productId, 1))
val newOrder = order.order
newOrder.price += product.price
orderRepository.update(newOrder)
}
}
}
}
}

View File

@ -0,0 +1,60 @@
package com.example.mobileapp.viewmodels
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.StatusRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class OrderViewModel @Inject constructor(
private val statusRepository: StatusRepository,
private val orderRepository: OrderRepository
) : ViewModel() {
val orderList = MutableLiveData<Flow<PagingData<OrderWithProducts>>>()
init {
updateOrderList()
}
private fun updateOrderList(){
orderList.postValue(orderRepository.getOrdersToWork())
}
suspend fun getOrderStatus(statusId: Int) : String{
return statusRepository.getById(statusId).first().name
}
fun changeOrderStatus(orderId: Int) {
viewModelScope.launch {
val order = orderRepository.getById(orderId).first()
when(statusRepository.getById(order.order.statusId).first().name){
"Принят" -> {
val newOrder = order.order
newOrder.statusId = statusRepository.getByName("Готов").first().id!!
orderRepository.update(newOrder)
}
"Готов" -> {
val newOrder = order.order
newOrder.statusId = statusRepository.getByName("Выдан").first().id!!
orderRepository.update(newOrder)
}
}
updateOrderList()
// для удобства
if (orderRepository.getById(orderId).first().order.statusId == 4){
orderRepository.delete(orderRepository.getById(orderId).first().order)
}
}
}
}

View File

@ -0,0 +1,93 @@
package com.example.mobileapp.viewmodels
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.CategoryRepository
import com.example.mobileapp.repositories.ProductRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class ProductViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val categoryRepository: CategoryRepository
) : ViewModel() {
private val _successState = MutableLiveData<Boolean?>()
private val _categories = mutableStateListOf<String>()
val categories: List<String>
get() = _categories
val successState: LiveData<Boolean?>
get() = _successState
private val _product = MutableLiveData<Product?>()
val product: LiveData<Product?>
get() = _product
fun getProduct(productId: Int) {
viewModelScope.launch {
_product.postValue(productRepository.getById(productId).first())
}
}
init {
viewModelScope.launch {
categoryRepository.getAll().collect{data ->
_categories.addAll(data.map { category -> category.name })
}
}
}
suspend fun getCategory(categoryId : Int) : String{
return categoryRepository.getById(categoryId).first().name
}
fun calmSuccessState() {
_successState.postValue(null)
}
fun addProduct(name: String, category: String, price: String) {
if (name.isEmpty() || name.length > 10 || name.length < 3){
_successState.postValue(false)
return
}
if (category.isEmpty()){
_successState.postValue(false)
return
}
if (price.isEmpty() || price.toIntOrNull() == null){
_successState.postValue(false)
return
}
viewModelScope.launch {
productRepository.insert(Product(null, name, categoryRepository.getByName(category).first().id!!, price.toInt()))
_successState.postValue(true)
}
}
fun updateProduct(id: Int, name: String, category: String, price: String) {
if (name.isEmpty() || name.length > 10 || name.length < 3){
_successState.postValue(false)
return
}
if (category.isEmpty()){
_successState.postValue(false)
return
}
if (price.isEmpty() || price.toIntOrNull() == null){
_successState.postValue(false)
return
}
viewModelScope.launch {
productRepository.update(Product(id, name, categoryRepository.getByName(category).first().id!!, price.toInt()))
_successState.postValue(true)
}
}
}

View File

@ -0,0 +1,42 @@
package com.example.mobileapp.viewmodels
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingData
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class ProfileViewModel @Inject constructor(
private val orderRepository: OrderRepository,
private val statusRepository: StatusRepository
) : ViewModel() {
fun getActiveOrders(userId : Int) : Flow<PagingData<OrderWithProducts>>? {
if (userId == -1) return null
return orderRepository.getOrdersByUserId(userId)
}
suspend fun getOrderStatus(statusId: Int) : String{
return statusRepository.getById(statusId).first().name
}
fun logout(sharedPref: PreferencesManager) {
sharedPref.deleteData("userId")
sharedPref.deleteData("userRole")
}
}

View File

@ -0,0 +1,52 @@
package com.example.mobileapp.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class RegistrationViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
private val _successState = MutableLiveData<Boolean?>()
val successState: LiveData<Boolean?>
get() = _successState
fun calmSuccessState() {
_successState.postValue(null)
}
fun registration(login: String, password: String, confirmPassword: String) {
if (login.length < 3 || login.length > 20) {
_successState.postValue(false)
return
}
if (password.length < 3 || password.length > 20) {
_successState.postValue(false)
return
}
if (password != confirmPassword) {
_successState.postValue(false)
return
}
viewModelScope.launch {
userRepository.getByLoginAndPassword(login, password).collect {
if (it != null) {
_successState.postValue(false)
} else {
userRepository.insert(User(null, login, password, 3))
_successState.postValue(true)
}
}
}
}
}

View File

@ -0,0 +1,83 @@
package com.example.mobileapp.viewmodels
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.User
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.RoleRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class UsersViewModel @Inject constructor(
private val roleRepository: RoleRepository,
private val userRepository: UserRepository
) : ViewModel() {
private val _roles = mutableStateListOf<String>()
val roles: List<String>
get() = _roles
init {
viewModelScope.launch {
roleRepository.getAll().collect{data ->
_roles.addAll(data.map { role -> role.name })
}
}
}
fun getUsersList() : Flow<PagingData<User>> {
return userRepository.getAllPaged()
}
suspend fun getUserRole(user: User) : String {
return roleRepository.getById(user.roleId).first().name
}
fun changeUserRole(userId: Int, roleName: String) {
viewModelScope.launch {
val user = userRepository.getById(userId).first()
when(roleName){
"user" -> {
val newUser = user
user.roleId = roleRepository.getByName("user").first().id!!
userRepository.update(newUser)
}
"worker" -> {
val newUser = user
user.roleId = roleRepository.getByName("worker").first().id!!
userRepository.update(newUser)
}
"admin" -> {
val newUser = user
user.roleId = roleRepository.getByName("admin").first().id!!
userRepository.update(newUser)
}
}
}
}
fun deleteUser(userId: Int){
viewModelScope.launch{
userRepository.delete(userRepository.getById(userId).first())
}
}
}

View File

@ -2,4 +2,5 @@
plugins {
id("com.android.application") version "8.1.1" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
id("com.google.dagger.hilt.android") version "2.44" apply false
}