Лаб 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("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id ("kotlin-kapt") id ("kotlin-kapt")
id("com.google.dagger.hilt.android")
} }
android { android {
@ -76,4 +77,15 @@ dependencies {
implementation ("androidx.room:room-runtime:2.5.0") // Библиотека "Room" implementation ("androidx.room:room-runtime:2.5.0") // Библиотека "Room"
kapt ("androidx.room:room-compiler:2.5.0") // Кодогенератор kapt ("androidx.room:room-compiler:2.5.0") // Кодогенератор
implementation ("androidx.room:room-ktx: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"> xmlns:tools="http://schemas.android.com/tools">
<application <application
android:name=".MobileApp"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_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 android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent 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.AppNavigation
import com.example.mobileapp.navigation.listOfAdminNavItems import dagger.hilt.android.AndroidEntryPoint
import com.example.mobileapp.navigation.listOfUserNavItems
import com.example.mobileapp.navigation.listOfWorkerNavItems
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@AndroidEntryPoint
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) 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 androidx.room.*
import com.example.mobileapp.models.* import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import androidx.paging.PagingSource
@Dao @Dao
interface CategoryDao { interface CategoryDao {
@ -17,8 +18,7 @@ interface CategoryDao {
@Query("select * from category where category.id = :id") @Query("select * from category where category.id = :id")
fun getById(id: Int) : Flow<Category> fun getById(id: Int) : Flow<Category>
@Query("select * from category where category.name = :name") @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 package com.example.mobileapp.dao
import androidx.paging.PagingSource
import androidx.room.* import androidx.room.*
import com.example.mobileapp.models.* import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -6,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface OrderDao { interface OrderDao {
@Insert @Insert
suspend fun insert(order: Order) suspend fun insert(order: Order) : Long
@Update @Update
suspend fun update(order: Order) suspend fun update(order: Order)
@Delete @Delete
@ -14,14 +15,14 @@ interface OrderDao {
@Query("select * from `order`") @Query("select * from `order`")
fun getAll() : Flow<List<OrderWithProducts>> fun getAll() : Flow<List<OrderWithProducts>>
@Query("select * from `order` where `order`.`user_id` =:id") @Query("select * from `order` where `order`.`id` =:id")
fun getById(id: Int): Flow<List<OrderWithProducts>> 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") @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>> fun getOrdersByUserId(userId: Int): PagingSource<Int, OrderWithProducts>
@Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` = 1") @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") @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 @Dao
interface OrderProductDao { interface OrderProductDao {
@Insert @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 package com.example.mobileapp.dao
import androidx.room.* import androidx.room.*
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product import com.example.mobileapp.models.Product
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import androidx.paging.PagingSource
@Dao @Dao
interface ProductDao { interface ProductDao {
@ -16,4 +18,8 @@ interface ProductDao {
fun getAll() : Flow<List<Product>> fun getAll() : Flow<List<Product>>
@Query("select * from product where product.id = :id") @Query("select * from product where product.id = :id")
fun getById(id: Int): Flow<Product> 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>> fun getAll() : Flow<List<Status>>
@Query("select * from status where status.id = :id") @Query("select * from status where status.id = :id")
fun getById(id: Int) : Flow<Status> 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 package com.example.mobileapp.dao
import androidx.paging.PagingSource
import androidx.room.* import androidx.room.*
import com.example.mobileapp.models.Product
import com.example.mobileapp.models.User import com.example.mobileapp.models.User
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -14,7 +16,12 @@ interface UserDao {
@Query("select * from user order by login collate nocase asc") @Query("select * from user order by login collate nocase asc")
fun getAll() : Flow<List<User>> 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") @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, Product::class,
OrderProduct::class, OrderProduct::class,
], ],
version = 1, version = 2,
exportSchema = false exportSchema = false
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@ -32,94 +32,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun orderProductDao() : OrderProductDao abstract fun orderProductDao() : OrderProductDao
companion object { companion object {
private const val DB_NAME: String = "mobileapp-db" 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 }
}
}
} }
} }

View File

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

View File

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

View File

@ -11,7 +11,7 @@ data class User(
@ColumnInfo(name = "password") @ColumnInfo(name = "password")
val password: String, val password: String,
@ColumnInfo(name = "role_id") @ColumnInfo(name = "role_id")
val roleId: Int var roleId: Int
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true 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.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.User import com.example.mobileapp.models.User
import com.example.mobileapp.screens.AuthorizationScreen import com.example.mobileapp.screens.AuthorizationScreen
@ -74,13 +75,13 @@ fun AppNavigation(){
composable(route = Screens.OrderScreen.name){ OrderScreen() } composable(route = Screens.OrderScreen.name){ OrderScreen() }
composable(route = Screens.AuthorizationScreen.name){ AuthorizationScreen(navController) } 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.EditMenuScreen.name){ EditMenuScreen(navController) }
composable(route = Screens.RegistrationScreen.name){ RegistrationScreen(navController) } composable(route = Screens.RegistrationScreen.name){ RegistrationScreen(navController) }
composable(route = Screens.UsersScreen.name){ UsersScreen() } composable(route = Screens.UsersScreen.name){ UsersScreen() }
composable(route = Screens.EditProductScreen.name + "/{productId}"){ backStackEntry -> composable(route = Screens.EditProductScreen.name + "/{productId}"){ backStackEntry ->
val productId = backStackEntry.arguments?.getString("productId") val productId = backStackEntry.arguments?.getString("productId")
EditProductScreen(productId.toString().toInt()) EditProductScreen(navController, productId.toString().toInt())
} }
} }
} }
@ -89,31 +90,24 @@ fun AppNavigation(){
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@Composable @Composable
fun CustomNavigationBar(navController: NavController) { fun CustomNavigationBar(navController: NavController) {
val user = remember { mutableStateOf(User(-1, "", "", -1)) } val sharedPref = PreferencesManager(LocalContext.current)
val context = LocalContext.current val user_role = sharedPref.getData("userRole", "user")
val listOfNavItems = remember { mutableStateListOf<NavItem>() } val listOfNavItems = remember { mutableStateListOf<NavItem>() }
LaunchedEffect(Unit) { when (user_role) {
withContext(Dispatchers.IO) { "admin" -> {
user.value = (AppDatabase.getInstance(context).userDao().getById(1)) listOfNavItems.clear()
listOfNavItems.addAll(listOfAdminNavItems)
(AppDatabase.getInstance(context).roleDao().getById(user.value.roleId)).collect{data -> }
when (data.name) { "worker" -> {
"admin" -> { listOfNavItems.clear()
listOfNavItems.clear() listOfNavItems.addAll(listOfWorkerNavItems)
listOfNavItems.addAll(listOfAdminNavItems) }
} "user" -> {
"worker" -> { listOfNavItems.clear()
listOfNavItems.clear() listOfNavItems.addAll(listOfUserNavItems)
listOfNavItems.addAll(listOfWorkerNavItems)
}
"user" -> {
listOfNavItems.clear()
listOfNavItems.addAll(listOfUserNavItems)
}
}
}
} }
} }
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .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.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily 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.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.mobileapp.PreferencesManager
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.AuthorizationViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
@Composable @Composable
@ -46,9 +54,50 @@ fun AuthorizationScreen(navController: NavController) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun AuthorizationCard(navController: NavController){ fun AuthorizationCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val login = remember { mutableStateOf(TextFieldValue("")) } val login = remember { mutableStateOf(TextFieldValue("")) }
val password = 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( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
@ -124,10 +173,7 @@ fun AuthorizationCard(navController: NavController){
Button( Button(
onClick = { onClick = {
navController.navigate(Screens.MenuScreen.name) { viewModel.login(sharedPref, login.value.text, password.value.text)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White), colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White),
shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp), shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp),
@ -147,10 +193,7 @@ fun AuthorizationCard(navController: NavController){
Button( Button(
onClick = { onClick = {
navController.navigate(Screens.RegistrationScreen.name) { navController.navigate(Screens.RegistrationScreen.name)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
colors = ButtonDefaults.buttonColors(Color(212,206,203)), colors = ButtonDefaults.buttonColors(Color(212,206,203)),
modifier = Modifier 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect 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.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.res.painterResource
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.R
import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.models.OrderProductWithProduct
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderWithProducts import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.viewmodels.CartViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable @Composable
fun CartScreen(){ fun CartScreen(){
@ -59,6 +53,11 @@ fun CartScreen(){
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@Composable @Composable
fun CartCard(){ fun CartCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
cartViewModel.retrieveUser(sharedPref)
val cart: OrderWithProducts? = cartViewModel.cart.observeAsState().value
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -84,187 +83,187 @@ fun CartCard(){
.padding(top = 10.dp), .padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
val cartWithProducts = remember { mutableStateOf(OrderWithProducts(Order(-1, -1, -1, -1), listOf())) }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) { if (cart != null && cart.orderWithProducts.size != 0) {
withContext(Dispatchers.IO) { LazyColumn(
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(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(Color.White),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
){ ){
Text( items(cart.orderWithProducts.size) { index ->
text = "Итого: " + cartWithProducts.value.order.price.toString() + " р.", CartProductCard(cartViewModel, cart.orderWithProducts[index])
color = Color.Black, }
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), }
fontSize = 20.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(start = 5.dp),
)
OutlinedButton( Card(
onClick = { shape = RoundedCornerShape(20.dp),
/*TODO*/ border = BorderStroke(3.dp, Color(222,161,69)),
}, modifier = Modifier
border = BorderStroke(4.dp, Color(222,161,69)), .padding(top = 15.dp, start = 5.dp, end = 5.dp)
shape = RoundedCornerShape(20.dp), ){
colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), Row(
modifier = Modifier.padding(5.dp) modifier = Modifier
) { .fillMaxWidth()
Text(text = "Заказать", fontSize = 20.sp, color = Color.White) .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.TextFieldDefaults
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -31,7 +31,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.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 com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun CreateProductScreen(){ fun CreateProductScreen(navController: NavController){
Column ( Column (
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Header(Color(212, 206, 203)) Header(Color(212, 206, 203))
CreateProductCard() CreateProductCard(navController)
} }
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @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( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color(212, 206, 203)), .background(Color(212, 206, 203)),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.fillMaxWidth(0.9f) .fillMaxWidth(0.9f)
.background(Color.White), .background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Text( Text(
@ -84,9 +94,6 @@ fun CreateProductCard(){
.padding(top = 10.dp), .padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
Card( Card(
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)), border = BorderStroke(3.dp, Color(222,161,69)),
@ -127,19 +134,6 @@ fun CreateProductCard(){
onSurface = Color.Gray 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( ExposedDropdownMenuBox(
expanded = expanded, expanded = expanded,
onExpandedChange = { onExpandedChange = {
@ -162,7 +156,7 @@ fun CreateProductCard(){
expanded = false expanded = false
}, },
) { ) {
categoryList.forEach { selectionOption -> categoryList.first().forEach { selectionOption ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(selectionOption) }, text = { Text(selectionOption) },
onClick = { onClick = {
@ -195,10 +189,9 @@ fun CreateProductCard(){
.fillMaxWidth() .fillMaxWidth()
.padding(top = 20.dp, start = 20.dp, end = 20.dp), .padding(top = 20.dp, start = 20.dp, end = 20.dp),
) )
OutlinedButton( OutlinedButton(
onClick = { onClick = {
/*TODO*/ productViewModel.addProduct(title.value.text, selectedCategory, price.value.text)
}, },
border = BorderStroke(4.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp), 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
@ -20,10 +19,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController 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.R
import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.models.Category
import com.example.mobileapp.models.CategoryWithProducts import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.navigation.Screens import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.MenuViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun EditMenuScreen(navController: NavController){ fun EditMenuScreen(navController: NavController){
@ -56,6 +55,11 @@ fun EditMenuScreen(navController: NavController){
@Composable @Composable
fun EditMenuCard(navController: NavController){ fun EditMenuCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -71,146 +75,156 @@ fun EditMenuCard(navController: NavController){
horizontalAlignment = Alignment.CenterHorizontally, 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( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .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(
text = item.category.name, text = product.price.toString() + " р.",
color = Color.Black, color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp, fontSize = 17.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
textAlign = TextAlign.Center, 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( Icon(
modifier = Modifier painterResource(id = R.drawable.icon_settings),
.fillMaxSize() contentDescription = null,
.background(Color.White), Modifier.size(30.dp),
verticalAlignment = Alignment.CenterVertically, tint = Color.Black
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 ( OutlinedButton(
horizontalAlignment = Alignment.CenterHorizontally, onClick = {
verticalArrangement = Arrangement.SpaceAround menuViewModel.deleteProduct(product)
) { },
Text( border = BorderStroke(4.dp, Color(222,161,69)),
text = product.name, shape = RoundedCornerShape(10.dp),
color = Color.Black, colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
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)),
){ ){
Icon( Icon(
painterResource(id = R.drawable.icon_settings), painterResource(id = R.drawable.icon_trash),
contentDescription = null, contentDescription = null,
Modifier.size(30.dp), Modifier.size(30.dp),
tint = Color.Black 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
)
}
}
}
}
}
} }
} }
} }
} }
} }
} }
@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.TextFieldDefaults
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -33,7 +33,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.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 com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable @Composable
fun EditProductScreen(id: Int){ fun EditProductScreen(navController: NavController, id: Int){
Column ( Column (
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Header(Color(212, 206, 203)) Header(Color(212, 206, 203))
EditProductCard(id) EditProductCard(navController, id)
} }
} }
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @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( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -88,25 +114,6 @@ fun EditProductCard(id: Int){
.padding(top = 10.dp), .padding(top = 10.dp),
textAlign = TextAlign.Center, 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( Card(
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)), border = BorderStroke(3.dp, Color(222,161,69)),
@ -138,7 +145,9 @@ fun EditProductCard(id: Int){
Card( Card(
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
border = BorderStroke(1.dp, Color(222,161,69)), 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( MaterialTheme(
@ -148,13 +157,6 @@ fun EditProductCard(id: Int){
onSurface = Color.Gray 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( ExposedDropdownMenuBox(
expanded = expanded, expanded = expanded,
onExpandedChange = { onExpandedChange = {
@ -163,7 +165,8 @@ fun EditProductCard(id: Int){
) { ) {
TextField( TextField(
modifier = Modifier modifier = Modifier
.menuAnchor().fillMaxWidth(), .menuAnchor()
.fillMaxWidth(),
readOnly = true, readOnly = true,
value = selectedCategory, value = selectedCategory,
onValueChange = {}, onValueChange = {},
@ -177,7 +180,7 @@ fun EditProductCard(id: Int){
expanded = false expanded = false
}, },
) { ) {
categoryList.forEach { selectionOption -> categoryList.first().forEach { selectionOption ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(selectionOption) }, text = { Text(selectionOption) },
onClick = { onClick = {
@ -213,7 +216,7 @@ fun EditProductCard(id: Int){
OutlinedButton( OutlinedButton(
onClick = { onClick = {
/*TODO*/ productViewModel.updateProduct(currentProduct.value?.id!!, title.value.text, selectedCategory, price.value.text)
}, },
border = BorderStroke(4.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),

View File

@ -74,10 +74,7 @@ fun ManagmentCard(navController: NavController){
){ ){
OutlinedButton( OutlinedButton(
onClick = { onClick = {
navController.navigate(Screens.CreateProductScreen.name) { navController.navigate(Screens.CreateProductScreen.name)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
border = BorderStroke(4.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
@ -94,10 +91,7 @@ fun ManagmentCard(navController: NavController){
OutlinedButton( OutlinedButton(
onClick = { onClick = {
navController.navigate(Screens.EditMenuScreen.name) { navController.navigate(Screens.EditMenuScreen.name)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
border = BorderStroke(4.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
@ -124,10 +118,7 @@ fun ManagmentCard(navController: NavController){
) )
OutlinedButton( OutlinedButton(
onClick = { onClick = {
navController.navigate(Screens.UsersScreen.name) { navController.navigate(Screens.UsersScreen.name)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
border = BorderStroke(4.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp), 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Category import com.example.mobileapp.models.Category
import com.example.mobileapp.models.CategoryWithProducts 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 com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun MenuScreen(){ fun MenuScreen(){
@ -55,6 +52,11 @@ fun MenuScreen(){
@Composable @Composable
fun MenuCard(){ fun MenuCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -70,119 +72,132 @@ fun MenuCard(){
horizontalAlignment = Alignment.CenterHorizontally, 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( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .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(
text = item.category.name, text = product.price.toString() + " р.",
color = Color.Black, color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 34.sp, fontSize = 17.sp,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
OutlinedButton(
item.products.forEach{ product -> onClick = {
Card( menuViewModel.addProductToCart(product.id!!)
shape = RoundedCornerShape(20.dp), },
border = BorderStroke(3.dp, Color(222,161,69)), border = BorderStroke(4.dp, Color(222,161,69)),
modifier = Modifier shape = RoundedCornerShape(30.dp),
.fillMaxSize() colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)),
.padding(top = 15.dp, start = 5.dp, end = 5.dp) ) {
){ Text(text = "+", fontSize = 20.sp, color = Color.Black)
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)
}
}
}
}
}
} }
} }
} }
} }
} }
} }
@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.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color 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.Font
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Order
import com.example.mobileapp.models.OrderWithProducts import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.viewmodels.OrderViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable @Composable
fun OrderScreen(){ fun OrderScreen(){
@ -48,13 +47,16 @@ fun OrderScreen(){
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Header(Color(212, 206, 203)) Header(Color(212, 206, 203))
OrderCard() OrdersCard()
} }
} }
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@Composable @Composable
fun OrderCard(){ fun OrdersCard(){
val orderViewModel: OrderViewModel = hiltViewModel<OrderViewModel>()
val orderListUiState = orderViewModel.orderList.observeAsState().value?.collectAsLazyPagingItems()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -80,121 +82,17 @@ fun OrderCard(){
.padding(top = 10.dp), .padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
if (orderListUiState != null){
val ordersWithProducts = remember { mutableStateListOf<OrderWithProducts> () } LazyColumn(
val context = LocalContext.current modifier = Modifier
val scope = rememberCoroutineScope() .fillMaxWidth()
) {
LaunchedEffect(Unit) { items(
withContext(Dispatchers.IO) { count = orderListUiState.itemCount,
AppDatabase.getInstance(context).orderDao().getOrdersToWork().collect { data -> key = orderListUiState.itemKey()
ordersWithProducts.addAll(data) ){ index ->
} if (orderListUiState[index] != null){
} OrderCard(orderListUiState[index]!!, orderViewModel)
}
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
)
}
}
} }
} }
} }
@ -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.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope 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.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController 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.R
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.OrderWithProducts import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.navigation.Screens import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.ProfileViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable @Composable
fun ProfileScreen(navController: NavController){ fun ProfileScreen(navController: NavController){
@ -56,12 +55,15 @@ fun ProfileScreen(navController: NavController){
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@Composable @Composable
fun ProfileCard(navController: NavController){ 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( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color(212, 206, 203)), .background(Color(212, 206, 203)),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@ -76,10 +78,8 @@ fun ProfileCard(navController: NavController){
.fillMaxWidth() .fillMaxWidth()
.padding(top = 15.dp, start = 5.dp, end = 5.dp), .padding(top = 15.dp, start = 5.dp, end = 5.dp),
onClick = { onClick = {
navController.navigate(Screens.AuthorizationScreen.name) { profileViewModel.logout(sharedPref)
popUpTo(navController.graph.startDestinationId) navController.navigate(Screens.AuthorizationScreen.name)
launchSingleTop = true
}
}, },
border = BorderStroke(4.dp, Color(255,86,86)), border = BorderStroke(4.dp, Color(255,86,86)),
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
@ -104,94 +104,92 @@ fun ProfileCard(navController: NavController){
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
val ordersWithProducts = remember { mutableStateListOf<OrderWithProducts> () }
val context = LocalContext.current
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) { if (activeOrdersListUiState != null){
withContext(Dispatchers.IO) { LazyColumn(
AppDatabase.getInstance(context).orderDao().getByUserId(1).collect { data -> modifier = Modifier
ordersWithProducts.clear() .fillMaxWidth()
ordersWithProducts.addAll(data) ) {
} items(
} count = activeOrdersListUiState.itemCount,
} key = activeOrdersListUiState.itemKey()
){ index ->
LazyColumn( ActiveOrderCard(activeOrdersListUiState[index]!!, profileViewModel)
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,
)
}
} }
} }
} }
} }
} }
} }
@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.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment 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.TextStyle
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily 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.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.viewmodels.RegistrationViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
@Composable @Composable
@ -50,6 +56,44 @@ fun RegistrationCard(navController: NavController){
val password = remember { mutableStateOf(TextFieldValue("")) } val password = remember { mutableStateOf(TextFieldValue("")) }
val passwordRepeat = 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( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
@ -146,10 +190,7 @@ fun RegistrationCard(navController: NavController){
Button( Button(
onClick = { onClick = {
navController.navigate(Screens.MenuScreen.name) { viewModel.registration(login.value.text, password.value.text, passwordRepeat.value.text)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White), colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White),
shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp), shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp),
@ -169,10 +210,7 @@ fun RegistrationCard(navController: NavController){
Button( Button(
onClick = { onClick = {
navController.navigate(Screens.AuthorizationScreen.name) { navController.navigate(Screens.AuthorizationScreen.name)
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
}, },
colors = ButtonDefaults.buttonColors(Color(212,206,203)), colors = ButtonDefaults.buttonColors(Color(212,206,203)),
modifier = Modifier modifier = Modifier

View File

@ -30,6 +30,7 @@ import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf 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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.R
import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.User import com.example.mobileapp.models.User
import com.example.mobileapp.viewmodels.UsersViewModel
import com.example.mobileapp.widgets.Header import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.Dispatchers 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.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -69,9 +80,12 @@ fun UsersScreen() {
} }
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun UsersCard(){ fun UsersCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val usersViewModel: UsersViewModel = hiltViewModel<UsersViewModel>()
val userListUiState = usersViewModel.getUsersList().collectAsLazyPagingItems()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -97,141 +111,17 @@ fun UsersCard(){
.padding(top = 10.dp), .padding(top = 10.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
val users = remember { mutableStateListOf<User> () } if (userListUiState != null){
val context = LocalContext.current LazyColumn(
val scope = rememberCoroutineScope() modifier = Modifier
LaunchedEffect(Unit) { .fillMaxSize()
withContext(Dispatchers.IO) { ) {
AppDatabase.getInstance(context).userDao().getAll().collect { data -> items(
users.addAll(data) count = userListUiState.itemCount,
} key = userListUiState.itemKey()
} ){ index ->
} if (userListUiState[index]!!.id != sharedPref.getData("userId", "-1").toInt()){
UserCard(userListUiState[index]!!, usersViewModel)
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
)
}
} }
} }
} }
@ -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 { plugins {
id("com.android.application") version "8.1.1" apply false id("com.android.application") version "8.1.1" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false
id("com.google.dagger.hilt.android") version "2.44" apply false
} }