From dd8628e0cecf15a595d374bc69f88aec3242f870 Mon Sep 17 00:00:00 2001 From: Safgerd Date: Wed, 27 Dec 2023 02:36:24 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=B0=D0=B1=204:=200=5Fo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 12 + app/src/main/AndroidManifest.xml | 1 + .../java/com/example/mobileapp/AppModule.kt | 65 ++++ .../com/example/mobileapp/MainActivity.kt | 16 +- .../java/com/example/mobileapp/MobileApp.kt | 11 + .../example/mobileapp/PreferencesManager.kt | 23 ++ .../com/example/mobileapp/dao/CategoryDao.kt | 6 +- .../com/example/mobileapp/dao/OrderDao.kt | 15 +- .../example/mobileapp/dao/OrderProductDao.kt | 8 +- .../com/example/mobileapp/dao/ProductDao.kt | 6 + .../com/example/mobileapp/dao/StatusDao.kt | 2 + .../java/com/example/mobileapp/dao/UserDao.kt | 9 +- .../com/example/mobileapp/db/AppDatabase.kt | 92 +---- .../com/example/mobileapp/models/Order.kt | 4 +- .../example/mobileapp/models/OrderProduct.kt | 2 +- .../java/com/example/mobileapp/models/User.kt | 2 +- .../mobileapp/navigation/AppNavigation.kt | 42 +- .../repositories/CategoryRepository.kt | 18 + .../repositories/OrderProductRepository.kt | 15 + .../mobileapp/repositories/OrderRepository.kt | 39 ++ .../repositories/ProductRepository.kt | 37 ++ .../mobileapp/repositories/RoleRepository.kt | 16 + .../repositories/StatusRepository.kt | 17 + .../mobileapp/repositories/UserRepository.kt | 27 ++ .../mobileapp/screens/AuthorizationScreen.kt | 59 ++- .../example/mobileapp/screens/CartScreen.kt | 367 +++++++++--------- .../mobileapp/screens/CreateProductScreen.kt | 51 ++- .../mobileapp/screens/EditMenuScreen.kt | 276 ++++++------- .../mobileapp/screens/EditProductScreen.kt | 79 ++-- .../mobileapp/screens/ManagmentScreen.kt | 15 +- .../example/mobileapp/screens/MenuScreen.kt | 235 +++++------ .../example/mobileapp/screens/OrderScreen.kt | 242 ++++++------ .../mobileapp/screens/ProfileScreen.kt | 188 +++++---- .../mobileapp/screens/RegistrationScreen.kt | 54 ++- .../example/mobileapp/screens/UsersScreen.kt | 290 +++++++------- .../viewmodels/AuthorizationViewModel.kt | 73 ++++ .../mobileapp/viewmodels/CartViewModel.kt | 102 +++++ .../mobileapp/viewmodels/MenuViewModel.kt | 87 +++++ .../mobileapp/viewmodels/OrderViewModel.kt | 60 +++ .../mobileapp/viewmodels/ProductViewModel.kt | 93 +++++ .../mobileapp/viewmodels/ProfileViewModel.kt | 42 ++ .../viewmodels/RegistrationViewModel.kt | 52 +++ .../mobileapp/viewmodels/UsersViewModel.kt | 83 ++++ build.gradle.kts | 1 + 44 files changed, 1914 insertions(+), 1020 deletions(-) create mode 100644 app/src/main/java/com/example/mobileapp/AppModule.kt create mode 100644 app/src/main/java/com/example/mobileapp/MobileApp.kt create mode 100644 app/src/main/java/com/example/mobileapp/PreferencesManager.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/CategoryRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/OrderProductRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/OrderRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/ProductRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/RoleRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/StatusRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/repositories/UserRepository.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/AuthorizationViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/CartViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/MenuViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/OrderViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/ProductViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/ProfileViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/RegistrationViewModel.kt create mode 100644 app/src/main/java/com/example/mobileapp/viewmodels/UsersViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8c72749..251d534 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id ("kotlin-kapt") + id("com.google.dagger.hilt.android") } android { @@ -76,4 +77,15 @@ dependencies { implementation ("androidx.room:room-runtime:2.5.0") // Библиотека "Room" kapt ("androidx.room:room-compiler:2.5.0") // Кодогенератор implementation ("androidx.room:room-ktx:2.5.0") + + // lab4 + implementation ("com.google.dagger:hilt-android:2.44") + kapt ("com.google.dagger:hilt-android-compiler:2.44") + implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + implementation ("androidx.compose.runtime:runtime-livedata:1.0.0-beta01") + implementation ("androidx.datastore:datastore-preferences:1.0.0") + + implementation ("androidx.paging:paging-runtime-ktx:3.2.1") + implementation ("androidx.paging:paging-compose:3.2.1") + implementation("androidx.room:room-paging:2.5.0") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0e06458..a349b4c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> @Query("select * from category where category.name = :name") - fun getByName(name: String) : Flow + fun getByName(name: String) : Flow + - @Query("select * from category") - fun getCategoryWithProducts() : Flow> } diff --git a/app/src/main/java/com/example/mobileapp/dao/OrderDao.kt b/app/src/main/java/com/example/mobileapp/dao/OrderDao.kt index e395188..db0d4bb 100644 --- a/app/src/main/java/com/example/mobileapp/dao/OrderDao.kt +++ b/app/src/main/java/com/example/mobileapp/dao/OrderDao.kt @@ -1,4 +1,5 @@ package com.example.mobileapp.dao +import androidx.paging.PagingSource import androidx.room.* import com.example.mobileapp.models.* import kotlinx.coroutines.flow.Flow @@ -6,7 +7,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface OrderDao { @Insert - suspend fun insert(order: Order) + suspend fun insert(order: Order) : Long @Update suspend fun update(order: Order) @Delete @@ -14,14 +15,14 @@ interface OrderDao { @Query("select * from `order`") fun getAll() : Flow> - @Query("select * from `order` where `order`.`user_id` =:id") - fun getById(id: Int): Flow> - @Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4") - fun getByUserId(userId: Int): Flow> + @Query("select * from `order` where `order`.`id` =:id") + fun getById(id: Int): Flow + @Query("select * from `order` where (`order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4)") + fun getOrdersByUserId(userId: Int): PagingSource @Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` = 1") - fun getCartByUserId(userId: Int): Flow + fun getCartByUserId(userId: Int): Flow @Query("select * from `order` where `order`.`status_id` != 1 and `order`.`status_id` != 4") - fun getOrdersToWork(): Flow> + fun getOrdersToWork(): PagingSource } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/dao/OrderProductDao.kt b/app/src/main/java/com/example/mobileapp/dao/OrderProductDao.kt index e9610cd..d9482dd 100644 --- a/app/src/main/java/com/example/mobileapp/dao/OrderProductDao.kt +++ b/app/src/main/java/com/example/mobileapp/dao/OrderProductDao.kt @@ -5,5 +5,11 @@ import com.example.mobileapp.models.OrderProduct @Dao interface OrderProductDao { @Insert - suspend fun insert(order: OrderProduct) + suspend fun insert(orderProduct: OrderProduct) + @Update + suspend fun update(orderProduct: OrderProduct) + @Delete + suspend fun delete(orderProduct: OrderProduct) + @Query("delete from order_product WHERE order_id = :orderId AND product_id = :productId") + suspend fun deleteByProductId(orderId: Int, productId: Int); } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/dao/ProductDao.kt b/app/src/main/java/com/example/mobileapp/dao/ProductDao.kt index 454cabf..d326573 100644 --- a/app/src/main/java/com/example/mobileapp/dao/ProductDao.kt +++ b/app/src/main/java/com/example/mobileapp/dao/ProductDao.kt @@ -1,7 +1,9 @@ package com.example.mobileapp.dao import androidx.room.* +import com.example.mobileapp.models.CategoryWithProducts import com.example.mobileapp.models.Product import kotlinx.coroutines.flow.Flow +import androidx.paging.PagingSource @Dao interface ProductDao { @@ -16,4 +18,8 @@ interface ProductDao { fun getAll() : Flow> @Query("select * from product where product.id = :id") fun getById(id: Int): Flow + @Query("select * from product where product.category_id = :categoryId") + fun getProductsByCategoryId(categoryId: Int) : PagingSource + @Query("select * from category") + fun getCategoriesWithProducts() : PagingSource } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/dao/StatusDao.kt b/app/src/main/java/com/example/mobileapp/dao/StatusDao.kt index 3f562a0..13456f1 100644 --- a/app/src/main/java/com/example/mobileapp/dao/StatusDao.kt +++ b/app/src/main/java/com/example/mobileapp/dao/StatusDao.kt @@ -22,4 +22,6 @@ interface StatusDao { fun getAll() : Flow> @Query("select * from status where status.id = :id") fun getById(id: Int) : Flow + @Query("select * from status where status.name = :name") + fun getByName(name: String) : Flow } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/dao/UserDao.kt b/app/src/main/java/com/example/mobileapp/dao/UserDao.kt index 4de4cef..70cd4d5 100644 --- a/app/src/main/java/com/example/mobileapp/dao/UserDao.kt +++ b/app/src/main/java/com/example/mobileapp/dao/UserDao.kt @@ -1,5 +1,7 @@ package com.example.mobileapp.dao +import androidx.paging.PagingSource import androidx.room.* +import com.example.mobileapp.models.Product import com.example.mobileapp.models.User import kotlinx.coroutines.flow.Flow @@ -14,7 +16,12 @@ interface UserDao { @Query("select * from user order by login collate nocase asc") fun getAll() : Flow> + @Query("select * from user order by login collate nocase asc") + fun getAllPaged() : PagingSource @Query("select * from user where user.id = :id") - fun getById(id: Int): User + fun getById(id: Int): Flow + + @Query("select * from user where user.login = :login and user.password = :password limit 1") + fun getByLoginAndPassword(login: String, password: String): Flow } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/db/AppDatabase.kt b/app/src/main/java/com/example/mobileapp/db/AppDatabase.kt index f82d1b0..bc029db 100644 --- a/app/src/main/java/com/example/mobileapp/db/AppDatabase.kt +++ b/app/src/main/java/com/example/mobileapp/db/AppDatabase.kt @@ -19,7 +19,7 @@ import kotlinx.coroutines.launch Product::class, OrderProduct::class, ], - version = 1, + version = 2, exportSchema = false ) abstract class AppDatabase : RoomDatabase() { @@ -32,94 +32,6 @@ abstract class AppDatabase : RoomDatabase() { abstract fun orderProductDao() : OrderProductDao companion object { - private const val DB_NAME: String = "mobileapp-db" - - @Volatile - private var INSTANCE: AppDatabase? = null - - private suspend fun populateDatabase() { - INSTANCE?.let { database -> - - //Roles - val roleDao = database.roleDao() - roleDao.insert(Role(1, "admin")) - roleDao.insert(Role(2, "worker")) - roleDao.insert(Role(3, "user")) - - //Statuses - val statusDao = database.statusDao() - statusDao.insert(Status(1, "Корзина")) - statusDao.insert(Status(2, "Принят")) - statusDao.insert(Status(3, "Готов")) - statusDao.insert(Status(4, "Выдан")) - - //Categories - val categoryDao = database.categoryDao() - categoryDao.insert(Category(1, "Бургеры")) - categoryDao.insert(Category(2, "Картошка")) - categoryDao.insert(Category(3, "Напитки")) - - //Users - val userDao = database.userDao() - userDao.insert(User(1, "admin", "admin", 1)) - userDao.insert(User(2, "worker", "worker", 2)) - userDao.insert(User(3, "user", "user", 3)) - - //Products - val productDao = database.productDao() - //Бургеры - productDao.insert(Product(1, "Бургер1", 1, 150)) - productDao.insert(Product(2, "Бургер2", 1, 300)) - productDao.insert(Product(3, "Бургер3", 1, 450)) - //Картошка - productDao.insert(Product(4, "Картошка1", 2, 50)) - productDao.insert(Product(5, "Картошка2", 2, 100)) - productDao.insert(Product(6, "Картошка3", 2, 150)) - //Напитки - productDao.insert(Product(7, "Напиток1", 3, 100)) - productDao.insert(Product(8, "Напиток2", 3, 200)) - productDao.insert(Product(9, "Напиток3", 3, 300)) - - //Orders - val orderDao = database.orderDao() - //Корзины - orderDao.insert(Order(1,1,400,1)) - //Заказы - orderDao.insert(Order(2,1,250,3)) - orderDao.insert(Order(3,1,400,2)) - - //region OrderProducts - val orderProductDao = database.orderProductDao() - //Корзины - orderProductDao.insert(OrderProduct(1,1,2)) - orderProductDao.insert(OrderProduct(1,7,1)) - //Заказы - orderProductDao.insert(OrderProduct(2,1,1)) - orderProductDao.insert(OrderProduct(2,7,1)) - orderProductDao.insert(OrderProduct(3,2,1)) - orderProductDao.insert(OrderProduct(3,5,1)) - } - } - - fun getInstance(appContext: Context): AppDatabase { - return INSTANCE ?: synchronized(this) { - Room - .databaseBuilder( - appContext, - AppDatabase::class.java, - DB_NAME - ) - .addCallback(object : Callback() { - override fun onCreate(db: SupportSQLiteDatabase) { - super.onCreate(db) - CoroutineScope(Dispatchers.IO).launch { - populateDatabase() - } - } - }) - .build() - .also { INSTANCE = it } - } - } + const val DB_NAME: String = "mobileapp-db" } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/models/Order.kt b/app/src/main/java/com/example/mobileapp/models/Order.kt index d97eb35..5942bfd 100644 --- a/app/src/main/java/com/example/mobileapp/models/Order.kt +++ b/app/src/main/java/com/example/mobileapp/models/Order.kt @@ -14,9 +14,9 @@ data class Order( @ColumnInfo(name = "user_id") val userId: Int, @ColumnInfo(name = "price") - val price: Int, + var price: Int, @ColumnInfo(name = "status_id") - val statusId: Int, + var statusId: Int, ) { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/app/src/main/java/com/example/mobileapp/models/OrderProduct.kt b/app/src/main/java/com/example/mobileapp/models/OrderProduct.kt index a1a6f58..b611b3b 100644 --- a/app/src/main/java/com/example/mobileapp/models/OrderProduct.kt +++ b/app/src/main/java/com/example/mobileapp/models/OrderProduct.kt @@ -8,5 +8,5 @@ data class OrderProduct( @ColumnInfo(name = "product_id", index = true) var productId: Int, @ColumnInfo(name = "amount") - val amount: Int + var amount: Int ) diff --git a/app/src/main/java/com/example/mobileapp/models/User.kt b/app/src/main/java/com/example/mobileapp/models/User.kt index a95c1a4..be0f421 100644 --- a/app/src/main/java/com/example/mobileapp/models/User.kt +++ b/app/src/main/java/com/example/mobileapp/models/User.kt @@ -11,7 +11,7 @@ data class User( @ColumnInfo(name = "password") val password: String, @ColumnInfo(name = "role_id") - val roleId: Int + var roleId: Int ) { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/app/src/main/java/com/example/mobileapp/navigation/AppNavigation.kt b/app/src/main/java/com/example/mobileapp/navigation/AppNavigation.kt index 24fa5d2..d972afe 100644 --- a/app/src/main/java/com/example/mobileapp/navigation/AppNavigation.kt +++ b/app/src/main/java/com/example/mobileapp/navigation/AppNavigation.kt @@ -30,6 +30,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.models.User import com.example.mobileapp.screens.AuthorizationScreen @@ -74,13 +75,13 @@ fun AppNavigation(){ composable(route = Screens.OrderScreen.name){ OrderScreen() } composable(route = Screens.AuthorizationScreen.name){ AuthorizationScreen(navController) } - composable(route = Screens.CreateProductScreen.name){ CreateProductScreen() } + composable(route = Screens.CreateProductScreen.name){ CreateProductScreen(navController) } composable(route = Screens.EditMenuScreen.name){ EditMenuScreen(navController) } composable(route = Screens.RegistrationScreen.name){ RegistrationScreen(navController) } composable(route = Screens.UsersScreen.name){ UsersScreen() } composable(route = Screens.EditProductScreen.name + "/{productId}"){ backStackEntry -> val productId = backStackEntry.arguments?.getString("productId") - EditProductScreen(productId.toString().toInt()) + EditProductScreen(navController, productId.toString().toInt()) } } } @@ -89,31 +90,24 @@ fun AppNavigation(){ @SuppressLint("CoroutineCreationDuringComposition") @Composable fun CustomNavigationBar(navController: NavController) { - val user = remember { mutableStateOf(User(-1, "", "", -1)) } - val context = LocalContext.current + val sharedPref = PreferencesManager(LocalContext.current) + val user_role = sharedPref.getData("userRole", "user") val listOfNavItems = remember { mutableStateListOf() } - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - user.value = (AppDatabase.getInstance(context).userDao().getById(1)) - - (AppDatabase.getInstance(context).roleDao().getById(user.value.roleId)).collect{data -> - when (data.name) { - "admin" -> { - listOfNavItems.clear() - listOfNavItems.addAll(listOfAdminNavItems) - } - "worker" -> { - listOfNavItems.clear() - listOfNavItems.addAll(listOfWorkerNavItems) - } - "user" -> { - listOfNavItems.clear() - listOfNavItems.addAll(listOfUserNavItems) - } - } - } + when (user_role) { + "admin" -> { + listOfNavItems.clear() + listOfNavItems.addAll(listOfAdminNavItems) + } + "worker" -> { + listOfNavItems.clear() + listOfNavItems.addAll(listOfWorkerNavItems) + } + "user" -> { + listOfNavItems.clear() + listOfNavItems.addAll(listOfUserNavItems) } } + Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/example/mobileapp/repositories/CategoryRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/CategoryRepository.kt new file mode 100644 index 0000000..95342e8 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/CategoryRepository.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/OrderProductRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/OrderProductRepository.kt new file mode 100644 index 0000000..3beb112 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/OrderProductRepository.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/OrderRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/OrderRepository.kt new file mode 100644 index 0000000..64bb358 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/OrderRepository.kt @@ -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 { + return orderDao.getCartByUserId(userId) + } + fun getOrdersToWork() = Pager( + PagingConfig( + pageSize = 3, + enablePlaceholders = false + ), + pagingSourceFactory = { orderDao.getOrdersToWork() } + ).flow +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/ProductRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/ProductRepository.kt new file mode 100644 index 0000000..cbfdeac --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/ProductRepository.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/RoleRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/RoleRepository.kt new file mode 100644 index 0000000..37ea0a0 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/RoleRepository.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/StatusRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/StatusRepository.kt new file mode 100644 index 0000000..ef7b3e3 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/StatusRepository.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/repositories/UserRepository.kt b/app/src/main/java/com/example/mobileapp/repositories/UserRepository.kt new file mode 100644 index 0000000..765bb86 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/repositories/UserRepository.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/AuthorizationScreen.kt b/app/src/main/java/com/example/mobileapp/screens/AuthorizationScreen.kt index 5442dd2..f25d865 100644 --- a/app/src/main/java/com/example/mobileapp/screens/AuthorizationScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/AuthorizationScreen.kt @@ -7,29 +7,37 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.AuthorizationViewModel import com.example.mobileapp.widgets.Header @Composable @@ -46,9 +54,50 @@ fun AuthorizationScreen(navController: NavController) { @OptIn(ExperimentalMaterial3Api::class) @Composable fun AuthorizationCard(navController: NavController){ + val sharedPref = PreferencesManager(LocalContext.current) val login = remember { mutableStateOf(TextFieldValue("")) } val password = remember { mutableStateOf(TextFieldValue("")) } + val viewModel = hiltViewModel() + + val success = viewModel.successState.observeAsState().value + + if (success == true) { + navController.navigate(Screens.MenuScreen.name) + } + + if (success == false) { + AlertDialog( + title = { + Text( + text = "Ошибка авторизации", + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + }, + text = { + Text( + text = "Неверный логин или пароль", + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + }, + onDismissRequest = { + viewModel.calmSuccessState() + }, + confirmButton = { + TextButton( + onClick = { + viewModel.calmSuccessState() + } + ) { + Text("ОК") + } + + } + ) + } + Column( horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -124,10 +173,7 @@ fun AuthorizationCard(navController: NavController){ Button( onClick = { - navController.navigate(Screens.MenuScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + viewModel.login(sharedPref, login.value.text, password.value.text) }, colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White), shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp), @@ -147,10 +193,7 @@ fun AuthorizationCard(navController: NavController){ Button( onClick = { - navController.navigate(Screens.RegistrationScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + navController.navigate(Screens.RegistrationScreen.name) }, colors = ButtonDefaults.buttonColors(Color(212,206,203)), modifier = Modifier diff --git a/app/src/main/java/com/example/mobileapp/screens/CartScreen.kt b/app/src/main/java/com/example/mobileapp/screens/CartScreen.kt index 627f971..c12f1db 100644 --- a/app/src/main/java/com/example/mobileapp/screens/CartScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/CartScreen.kt @@ -13,16 +13,13 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -31,19 +28,16 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase -import com.example.mobileapp.models.CategoryWithProducts -import com.example.mobileapp.models.Order +import com.example.mobileapp.models.OrderProductWithProduct import com.example.mobileapp.models.OrderWithProducts +import com.example.mobileapp.viewmodels.CartViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext @Composable fun CartScreen(){ @@ -59,6 +53,11 @@ fun CartScreen(){ @SuppressLint("CoroutineCreationDuringComposition") @Composable fun CartCard(){ + val sharedPref = PreferencesManager(LocalContext.current) + val cartViewModel: CartViewModel = hiltViewModel() + cartViewModel.retrieveUser(sharedPref) + val cart: OrderWithProducts? = cartViewModel.cart.observeAsState().value + Column( modifier = Modifier .fillMaxSize() @@ -84,187 +83,187 @@ fun CartCard(){ .padding(top = 10.dp), textAlign = TextAlign.Center, ) - val cartWithProducts = remember { mutableStateOf(OrderWithProducts(Order(-1, -1, -1, -1), listOf())) } - val context = LocalContext.current - val scope = rememberCoroutineScope() - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).orderDao().getCartByUserId(1).collect { data -> - cartWithProducts.value = data - } - } - } - - LazyColumn( - modifier = Modifier - .fillMaxWidth() - ) { - items(cartWithProducts.value.orderWithProducts){ cartProduct -> - val amount = remember { mutableStateOf(TextFieldValue(cartProduct.orderProduct.amount.toString())) } - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .fillMaxSize() - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( - modifier = Modifier - .fillMaxSize() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - val category = remember { mutableStateOf("")} - scope.launch { - AppDatabase.getInstance(context).categoryDao().getById(cartProduct.product.categoryId).collect { data -> - category.value = data.name - } - } - if (category.value == "Бургеры"){ - Image( - painterResource( - id = R.drawable.burger - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (category.value == "Картошка"){ - Image( - painterResource( - id = R.drawable.potato - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (category.value == "Напитки"){ - Image( - painterResource( - id = R.drawable.pepsi - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - - Column ( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceAround - ) { - Text( - text = cartProduct.product.name, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - Text( - text = cartProduct.product.price.toString() + " р.", - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - modifier = Modifier - .fillMaxWidth(0.8f) - ){ - OutlinedButton( - modifier = Modifier - .fillMaxHeight(), - onClick = { - /*TODO*/ - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(topStart = 30.dp, bottomStart = 30.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - ) { - Text(text = "-", fontSize = 20.sp, color = Color.Black) - } - - Card( - modifier = Modifier - .fillMaxHeight(), - border = BorderStroke(3.dp, Color(222,161,69)), - shape = RoundedCornerShape(0.dp), - ){ - Text( - modifier = Modifier - .background(Color.White) - .fillMaxHeight() - .padding(start = 20.dp, end = 20.dp, top = 7.dp, bottom = 7.dp), - text = amount.value.text, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_bold)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } - - OutlinedButton( - modifier = Modifier - .fillMaxHeight(), - onClick = { - /*TODO*/ - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - ) { - Text(text = "+", fontSize = 20.sp, color = Color.Black) - } - } - } - } - } - } - } - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( + if (cart != null && cart.orderWithProducts.size != 0) { + LazyColumn( modifier = Modifier .fillMaxWidth() - .background(Color.White), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, ){ - Text( - text = "Итого: " + cartWithProducts.value.order.price.toString() + " р.", - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - modifier = Modifier.padding(start = 5.dp), - ) + items(cart.orderWithProducts.size) { index -> + CartProductCard(cartViewModel, cart.orderWithProducts[index]) + } + } - OutlinedButton( - onClick = { - /*TODO*/ - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - modifier = Modifier.padding(5.dp) - ) { - Text(text = "Заказать", fontSize = 20.sp, color = Color.White) + Card( + shape = RoundedCornerShape(20.dp), + border = BorderStroke(3.dp, Color(222,161,69)), + modifier = Modifier + .padding(top = 15.dp, start = 5.dp, end = 5.dp) + ){ + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.White), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ){ + Text( + text = "Итого: " + cart.order.price.toString() + " р.", + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 20.sp, + textAlign = TextAlign.Center, + modifier = Modifier.padding(start = 5.dp), + ) + + OutlinedButton( + onClick = { + cartViewModel.makeOrder() + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(20.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), + modifier = Modifier.padding(5.dp) + ) { + Text(text = "Заказать", fontSize = 20.sp, color = Color.White) + } } } } } } +} + +@Composable +fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProduct){ + Card( + shape = RoundedCornerShape(20.dp), + border = BorderStroke(3.dp, Color(222,161,69)), + modifier = Modifier + .fillMaxSize() + .padding(top = 15.dp, start = 5.dp, end = 5.dp) + ){ + Row( + modifier = Modifier + .fillMaxSize() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ){ + CartProductImageCard(product.product.categoryId) + + Column ( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceAround + ) { + Text( + text = product.product.name, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 17.sp, + textAlign = TextAlign.Center, + ) + Text( + text = product.product.price.toString() + " р.", + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 17.sp, + textAlign = TextAlign.Center, + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth(0.8f) + ){ + OutlinedButton( + modifier = Modifier + .fillMaxHeight(), + onClick = { + cartViewModel.removeProductFromOrder(product.product.id!!) + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(topStart = 30.dp, bottomStart = 30.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), + ) { + Text(text = "-", fontSize = 20.sp, color = Color.Black) + } + + Card( + modifier = Modifier + .fillMaxHeight(), + border = BorderStroke(3.dp, Color(222,161,69)), + shape = RoundedCornerShape(0.dp), + ){ + Text( + modifier = Modifier + .background(Color.White) + .fillMaxHeight() + .padding( + start = 20.dp, + end = 20.dp, + top = 7.dp, + bottom = 7.dp + ), + text = product.orderProduct.amount.toString(), + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_bold)), + fontSize = 20.sp, + textAlign = TextAlign.Center, + ) + } + + OutlinedButton( + modifier = Modifier + .fillMaxHeight(), + onClick = { + cartViewModel.addProductToOrder(product.product.id!!) + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), + ) { + Text(text = "+", fontSize = 20.sp, color = Color.Black) + } + } + } + } + } +} + +@Composable +fun CartProductImageCard(categoryId : Int){ + if (categoryId == 1){ + Image( + painterResource( + id = R.drawable.burger + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryId == 2){ + Image( + painterResource( + id = R.drawable.potato + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryId == 3){ + Image( + painterResource( + id = R.drawable.pepsi + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/CreateProductScreen.kt b/app/src/main/java/com/example/mobileapp/screens/CreateProductScreen.kt index d01a366..bf96bfd 100644 --- a/app/src/main/java/com/example/mobileapp/screens/CreateProductScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/CreateProductScreen.kt @@ -22,8 +22,8 @@ import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -31,7 +31,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -39,39 +38,50 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase +import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.ProductViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext @Composable -fun CreateProductScreen(){ +fun CreateProductScreen(navController: NavController){ Column ( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, ) { Header(Color(212, 206, 203)) - CreateProductCard() + CreateProductCard(navController) } } @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreateProductCard(){ +fun CreateProductCard(navController: NavController){ + val productViewModel: ProductViewModel = hiltViewModel() + val title = remember { mutableStateOf(TextFieldValue("")) } + val price = remember { mutableStateOf(TextFieldValue("")) } + val categoryList = remember { mutableStateListOf(productViewModel.categories) } + var selectedCategory by remember { mutableStateOf("") } + var expanded by remember { mutableStateOf(false) } + val success = productViewModel.successState.observeAsState().value + + if (success == true) { + navController.navigate(Screens.ManagmentScreen.name) + } + Column( modifier = Modifier .fillMaxSize() .background(Color(212, 206, 203)), horizontalAlignment = Alignment.CenterHorizontally, - ) { Column( modifier = Modifier .fillMaxHeight() .fillMaxWidth(0.9f) .background(Color.White), - horizontalAlignment = Alignment.CenterHorizontally, ) { Text( @@ -84,9 +94,6 @@ fun CreateProductCard(){ .padding(top = 10.dp), textAlign = TextAlign.Center, ) - val title = remember { mutableStateOf(TextFieldValue("")) } - val price = remember { mutableStateOf(TextFieldValue("")) } - Card( shape = RoundedCornerShape(20.dp), border = BorderStroke(3.dp, Color(222,161,69)), @@ -127,19 +134,6 @@ fun CreateProductCard(){ onSurface = Color.Gray ) ){ - val categoryList = remember { mutableStateListOf() } - var selectedCategory by remember { mutableStateOf("") } - var expanded by remember { mutableStateOf(false) } - val context = LocalContext.current - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).categoryDao().getAll().collect { data -> - categoryList.clear() - categoryList.addAll(data.map { category -> category.name }) - selectedCategory = data.first().name - } - } - } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { @@ -162,7 +156,7 @@ fun CreateProductCard(){ expanded = false }, ) { - categoryList.forEach { selectionOption -> + categoryList.first().forEach { selectionOption -> DropdownMenuItem( text = { Text(selectionOption) }, onClick = { @@ -195,10 +189,9 @@ fun CreateProductCard(){ .fillMaxWidth() .padding(top = 20.dp, start = 20.dp, end = 20.dp), ) - OutlinedButton( onClick = { - /*TODO*/ + productViewModel.addProduct(title.value.text, selectedCategory, price.value.text) }, border = BorderStroke(4.dp, Color(222,161,69)), shape = RoundedCornerShape(20.dp), diff --git a/app/src/main/java/com/example/mobileapp/screens/EditMenuScreen.kt b/app/src/main/java/com/example/mobileapp/screens/EditMenuScreen.kt index a1a443a..6295b60 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditMenuScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditMenuScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card @@ -20,10 +19,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -34,14 +29,18 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase +import com.example.mobileapp.models.Category import com.example.mobileapp.models.CategoryWithProducts +import com.example.mobileapp.models.Product import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.MenuViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext @Composable fun EditMenuScreen(navController: NavController){ @@ -56,6 +55,11 @@ fun EditMenuScreen(navController: NavController){ @Composable fun EditMenuCard(navController: NavController){ + val sharedPref = PreferencesManager(LocalContext.current) + val menuViewModel: MenuViewModel = hiltViewModel() + menuViewModel.retrieveUser(sharedPref) + val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems() + Column( modifier = Modifier .fillMaxSize() @@ -71,146 +75,156 @@ fun EditMenuCard(navController: NavController){ horizontalAlignment = Alignment.CenterHorizontally, ) { - val categoryWithProducts = remember { mutableStateListOf() } - val context = LocalContext.current - val scope = rememberCoroutineScope() - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).categoryDao().getCategoryWithProducts().collect { data -> - categoryWithProducts.addAll(data) - } - } - } LazyColumn( modifier = Modifier .fillMaxSize() ) { - items(categoryWithProducts){ item -> + items( + count = categoriesWithProducts.itemCount, + key = categoriesWithProducts.itemKey() + ){ index -> + EditMenuCategoryProductsCard(navController, menuViewModel, categoriesWithProducts[index]!!) + } + } + } + } +} + +@Composable +fun EditMenuCategoryProductsCard(navController: NavController, menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){ + if (categoryWithProducts.products.size == 0){ + return + } + + Text( + text = categoryWithProducts.category.name, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 34.sp, + modifier = Modifier + .fillMaxWidth() + .padding(top = 10.dp), + textAlign = TextAlign.Center, + ) + + categoryWithProducts.products.forEach{ product -> + EditMenuProductsCard(navController, menuViewModel, product, categoryWithProducts.category) + } +} + +@Composable +fun EditMenuProductsCard(navController: NavController, menuViewModel : MenuViewModel, product : Product, category: Category){ + Card( + shape = RoundedCornerShape(20.dp), + border = BorderStroke(3.dp, Color(222,161,69)), + modifier = Modifier + .fillMaxSize() + .padding(top = 15.dp, start = 5.dp, end = 5.dp) + ){ + Row( + modifier = Modifier + .fillMaxSize() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ){ + EditMenuProductImageCard(category.name) + + Column ( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceAround + ) { + Text( + text = product.name, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 17.sp, + textAlign = TextAlign.Center, + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ){ Text( - text = item.category.name, + text = product.price.toString() + " р.", color = Color.Black, fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 34.sp, - modifier = Modifier - .fillMaxWidth() - .padding(top = 10.dp), + fontSize = 17.sp, textAlign = TextAlign.Center, ) + OutlinedButton( + onClick = { + navController.navigate(Screens.EditProductScreen.name + "/${product.id}") + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(10.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - item.products.forEach{ product -> - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .fillMaxSize() - .padding(top = 15.dp, start = 5.dp, end = 5.dp) ){ - Row( - modifier = Modifier - .fillMaxSize() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - if (item.category.name == "Бургеры"){ - Image( - painterResource( - id = R.drawable.burger - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (item.category.name == "Картошка"){ - Image( - painterResource( - id = R.drawable.potato - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (item.category.name == "Напитки"){ - Image( - painterResource( - id = R.drawable.pepsi - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } + Icon( + painterResource(id = R.drawable.icon_settings), + contentDescription = null, + Modifier.size(30.dp), + tint = Color.Black + ) + } - Column ( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceAround - ) { - Text( - text = product.name, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp), - ){ - Text( - text = product.price.toString() + " р.", - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - OutlinedButton( - onClick = { - navController.navigate(Screens.EditProductScreen.name + "/${product.id}") { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(10.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), + OutlinedButton( + onClick = { + menuViewModel.deleteProduct(product) + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(10.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - ){ - Icon( - painterResource(id = R.drawable.icon_settings), - contentDescription = null, - Modifier.size(30.dp), - tint = Color.Black - ) - } - - OutlinedButton( - onClick = { /*TODO*/}, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(10.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - - ){ - Icon( - painterResource(id = R.drawable.icon_trash), - contentDescription = null, - Modifier.size(30.dp), - tint = Color.Black - ) - } - } - } - } - } + ){ + Icon( + painterResource(id = R.drawable.icon_trash), + contentDescription = null, + Modifier.size(30.dp), + tint = Color.Black + ) } } } } } +} + +@Composable +fun EditMenuProductImageCard(categoryName : String){ + if (categoryName == "Бургеры"){ + Image( + painterResource( + id = R.drawable.burger + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryName == "Картошка"){ + Image( + painterResource( + id = R.drawable.potato + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryName == "Напитки"){ + Image( + painterResource( + id = R.drawable.pepsi + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/EditProductScreen.kt b/app/src/main/java/com/example/mobileapp/screens/EditProductScreen.kt index 3423783..2290ab3 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditProductScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditProductScreen.kt @@ -23,8 +23,8 @@ import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -33,7 +33,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -41,28 +40,55 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase +import com.example.mobileapp.models.Product +import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.ProductViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext @Composable -fun EditProductScreen(id: Int){ +fun EditProductScreen(navController: NavController, id: Int){ Column ( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, ) { Header(Color(212, 206, 203)) - EditProductCard(id) + EditProductCard(navController, id) } } @SuppressLint("CoroutineCreationDuringComposition") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun EditProductCard(id: Int){ +fun EditProductCard(navController: NavController, productId : Int){ + val scope = rememberCoroutineScope() + val productViewModel: ProductViewModel = hiltViewModel() + productViewModel.getProduct(productId) + + val currentProduct = remember { mutableStateOf(null) } + val title = remember { mutableStateOf(TextFieldValue("")) } + val price = remember { mutableStateOf(TextFieldValue("")) } + val categoryList = remember { mutableStateListOf(productViewModel.categories) } + var selectedCategory by remember { mutableStateOf("") } + var expanded by remember { mutableStateOf(false) } + val success = productViewModel.successState.observeAsState().value + + if (productViewModel.product.value != null){ + currentProduct.value = productViewModel.product.value!! + title.value = TextFieldValue(productViewModel.product.value!!.name) + price.value = TextFieldValue(productViewModel.product.value!!.price.toString()) + scope.launch { + selectedCategory = productViewModel.getCategory(productViewModel.product.value!!.categoryId) + } + } + + if (success == true) { + navController.navigate(Screens.EditMenuScreen.name) + } + Column( modifier = Modifier .fillMaxSize() @@ -88,25 +114,6 @@ fun EditProductCard(id: Int){ .padding(top = 10.dp), textAlign = TextAlign.Center, ) - val context = LocalContext.current - - var selectedCategory by remember { mutableStateOf("") } - var expanded by remember { mutableStateOf(false) } - val title = remember { mutableStateOf(TextFieldValue("")) } - val price = remember { mutableStateOf(TextFieldValue("")) } - val scope = rememberCoroutineScope() - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).productDao().getById(id).collect {data -> - title.value = TextFieldValue(data.name) - price.value = TextFieldValue(data.price.toString()) - - AppDatabase.getInstance(context).categoryDao().getById(data.categoryId).collect { - selectedCategory = it.name - } - } - } - } Card( shape = RoundedCornerShape(20.dp), border = BorderStroke(3.dp, Color(222,161,69)), @@ -138,7 +145,9 @@ fun EditProductCard(id: Int){ Card( shape = RoundedCornerShape(20.dp), border = BorderStroke(1.dp, Color(222,161,69)), - modifier = Modifier.fillMaxWidth().padding(top = 20.dp, start = 20.dp, end = 20.dp), + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, start = 20.dp, end = 20.dp), ){ MaterialTheme( @@ -148,13 +157,6 @@ fun EditProductCard(id: Int){ onSurface = Color.Gray ) ){ - val categoryList = remember { mutableStateListOf() } - scope.launch { - AppDatabase.getInstance(context).categoryDao().getAll().collect { data -> - categoryList.clear() - categoryList.addAll(data.map { category -> category.name }) - } - } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { @@ -163,7 +165,8 @@ fun EditProductCard(id: Int){ ) { TextField( modifier = Modifier - .menuAnchor().fillMaxWidth(), + .menuAnchor() + .fillMaxWidth(), readOnly = true, value = selectedCategory, onValueChange = {}, @@ -177,7 +180,7 @@ fun EditProductCard(id: Int){ expanded = false }, ) { - categoryList.forEach { selectionOption -> + categoryList.first().forEach { selectionOption -> DropdownMenuItem( text = { Text(selectionOption) }, onClick = { @@ -213,7 +216,7 @@ fun EditProductCard(id: Int){ OutlinedButton( onClick = { - /*TODO*/ + productViewModel.updateProduct(currentProduct.value?.id!!, title.value.text, selectedCategory, price.value.text) }, border = BorderStroke(4.dp, Color(222,161,69)), shape = RoundedCornerShape(20.dp), diff --git a/app/src/main/java/com/example/mobileapp/screens/ManagmentScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ManagmentScreen.kt index 9c59938..7e212a9 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ManagmentScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ManagmentScreen.kt @@ -74,10 +74,7 @@ fun ManagmentCard(navController: NavController){ ){ OutlinedButton( onClick = { - navController.navigate(Screens.CreateProductScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + navController.navigate(Screens.CreateProductScreen.name) }, border = BorderStroke(4.dp, Color(222,161,69)), shape = RoundedCornerShape(20.dp), @@ -94,10 +91,7 @@ fun ManagmentCard(navController: NavController){ OutlinedButton( onClick = { - navController.navigate(Screens.EditMenuScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + navController.navigate(Screens.EditMenuScreen.name) }, border = BorderStroke(4.dp, Color(222,161,69)), shape = RoundedCornerShape(20.dp), @@ -124,10 +118,7 @@ fun ManagmentCard(navController: NavController){ ) OutlinedButton( onClick = { - navController.navigate(Screens.UsersScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + navController.navigate(Screens.UsersScreen.name) }, border = BorderStroke(4.dp, Color(222,161,69)), shape = RoundedCornerShape(20.dp), diff --git a/app/src/main/java/com/example/mobileapp/screens/MenuScreen.kt b/app/src/main/java/com/example/mobileapp/screens/MenuScreen.kt index a1d273e..4f2a5b6 100644 --- a/app/src/main/java/com/example/mobileapp/screens/MenuScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/MenuScreen.kt @@ -12,18 +12,12 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -34,13 +28,16 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.models.Category import com.example.mobileapp.models.CategoryWithProducts +import com.example.mobileapp.models.Product +import com.example.mobileapp.viewmodels.MenuViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext @Composable fun MenuScreen(){ @@ -55,6 +52,11 @@ fun MenuScreen(){ @Composable fun MenuCard(){ + val sharedPref = PreferencesManager(LocalContext.current) + val menuViewModel: MenuViewModel = hiltViewModel() + menuViewModel.retrieveUser(sharedPref) + val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems() + Column( modifier = Modifier .fillMaxSize() @@ -70,119 +72,132 @@ fun MenuCard(){ horizontalAlignment = Alignment.CenterHorizontally, ) { - val categoryWithProducts = remember { mutableStateListOf()} - val context = LocalContext.current - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - (AppDatabase.getInstance(context).categoryDao().getCategoryWithProducts()).collect { data -> - categoryWithProducts.addAll(data) - } - } - } - LazyColumn( modifier = Modifier .fillMaxSize() ) { - items(categoryWithProducts){ item -> + items( + count = categoriesWithProducts.itemCount, + key = categoriesWithProducts.itemKey() + ){ index -> + MenuCategoryProductsCard(menuViewModel, categoriesWithProducts[index]!!) + } + } + } + } +} + +@Composable +fun MenuCategoryProductsCard(menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){ + if (categoryWithProducts.products.size == 0){ + return + } + + Text( + text = categoryWithProducts.category.name, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 34.sp, + modifier = Modifier + .fillMaxWidth() + .padding(top = 10.dp), + textAlign = TextAlign.Center, + ) + + categoryWithProducts.products.forEach{ product -> + MenuProductsCard(menuViewModel, product, categoryWithProducts.category) + } +} + +@Composable +fun MenuProductsCard(menuViewModel : MenuViewModel, product : Product, category: Category){ + Card( + shape = RoundedCornerShape(20.dp), + border = BorderStroke(3.dp, Color(222,161,69)), + modifier = Modifier + .fillMaxSize() + .padding(top = 15.dp, start = 5.dp, end = 5.dp) + ){ + Row( + modifier = Modifier + .fillMaxSize() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ){ + MenuProductImageCard(category.name) + + Column ( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceAround + ) { + Text( + text = product.name, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 17.sp, + textAlign = TextAlign.Center, + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ){ Text( - text = item.category.name, + text = product.price.toString() + " р.", color = Color.Black, fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 34.sp, - modifier = Modifier - .fillMaxWidth() - .padding(top = 10.dp), + fontSize = 17.sp, textAlign = TextAlign.Center, ) - - item.products.forEach{ product -> - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .fillMaxSize() - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( - modifier = Modifier - .fillMaxSize() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - if (item.category.name == "Бургеры"){ - Image( - painterResource( - id = R.drawable.burger - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (item.category.name == "Картошка"){ - Image( - painterResource( - id = R.drawable.potato - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - if (item.category.name == "Напитки"){ - Image( - painterResource( - id = R.drawable.pepsi - ), - contentDescription = null, - modifier = Modifier - .size(100.dp, 100.dp) - .padding(5.dp), - ) - } - - Column ( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceAround - ) { - Text( - text = product.name, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(10.dp), - ){ - Text( - text = product.price.toString() + " р.", - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - ) - OutlinedButton( - onClick = {/*TODO*/}, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(30.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - ) { - Text(text = "+", fontSize = 20.sp, color = Color.Black) - } - } - } - } - } + OutlinedButton( + onClick = { + menuViewModel.addProductToCart(product.id!!) + }, + border = BorderStroke(4.dp, Color(222,161,69)), + shape = RoundedCornerShape(30.dp), + colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), + ) { + Text(text = "+", fontSize = 20.sp, color = Color.Black) } } } } } +} + +@Composable +fun MenuProductImageCard(categoryName : String){ + if (categoryName == "Бургеры"){ + Image( + painterResource( + id = R.drawable.burger + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryName == "Картошка"){ + Image( + painterResource( + id = R.drawable.potato + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } + if (categoryName == "Напитки"){ + Image( + painterResource( + id = R.drawable.pepsi + ), + contentDescription = null, + modifier = Modifier + .size(100.dp, 100.dp) + .padding(5.dp), + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/OrderScreen.kt b/app/src/main/java/com/example/mobileapp/screens/OrderScreen.kt index 8c9b47f..e235e8c 100644 --- a/app/src/main/java/com/example/mobileapp/screens/OrderScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/OrderScreen.kt @@ -11,35 +11,34 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase -import com.example.mobileapp.models.Order import com.example.mobileapp.models.OrderWithProducts +import com.example.mobileapp.viewmodels.OrderViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext @Composable fun OrderScreen(){ @@ -48,13 +47,16 @@ fun OrderScreen(){ horizontalAlignment = Alignment.CenterHorizontally, ) { Header(Color(212, 206, 203)) - OrderCard() + OrdersCard() } } @SuppressLint("CoroutineCreationDuringComposition") @Composable -fun OrderCard(){ +fun OrdersCard(){ + val orderViewModel: OrderViewModel = hiltViewModel() + val orderListUiState = orderViewModel.orderList.observeAsState().value?.collectAsLazyPagingItems() + Column( modifier = Modifier .fillMaxSize() @@ -80,125 +82,115 @@ fun OrderCard(){ .padding(top = 10.dp), textAlign = TextAlign.Center, ) - - val ordersWithProducts = remember { mutableStateListOf () } - val context = LocalContext.current - val scope = rememberCoroutineScope() - - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).orderDao().getOrdersToWork().collect { data -> - ordersWithProducts.addAll(data) - } - } - } - - LazyColumn( - modifier = Modifier - .fillMaxWidth() - ) { - items(ordersWithProducts){ order -> - val status = remember { mutableStateOf("")} - scope.launch { - AppDatabase.getInstance(context).statusDao().getById(order.order.statusId).collect { data -> - status.value = data.name - } - } - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - Text( - text = "№" + order.order.id, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 34.sp, - textAlign = TextAlign.Center, - ) - - Text( - text = "Статус: " + status.value, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } - - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceAround, - ){ - Column { - order.orderWithProducts.forEach{ orderProduct -> - Row( - modifier = Modifier - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - ){ - Text( - text = orderProduct.product.name + " x" + orderProduct.orderProduct.amount.toString(), - color = Color.Gray, - fontFamily = FontFamily(Font(R.font.nunito_bold)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } - } - } - if (order.order.statusId == 2){ - OutlinedButton( - onClick = { - /*TODO*/ - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - modifier = Modifier.padding(bottom = 10.dp) - ) { - Text( - text = "Готов", - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 30.sp, - color = Color.White - ) - } - } - if (order.order.statusId == 3){ - OutlinedButton( - onClick = { - /*TODO*/ - }, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - modifier = Modifier.padding(bottom = 10.dp) - ) { - Text( - text = "Выдать", - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 30.sp, - color = Color.White - ) - } - } + if (orderListUiState != null){ + LazyColumn( + modifier = Modifier + .fillMaxWidth() + ) { + items( + count = orderListUiState.itemCount, + key = orderListUiState.itemKey() + ){ index -> + if (orderListUiState[index] != null){ + OrderCard(orderListUiState[index]!!, orderViewModel) } } } } } } +} + +@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 + ) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/ProfileScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ProfileScreen.kt index e15975b..0e2f4f8 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ProfileScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ProfileScreen.kt @@ -11,15 +11,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -32,15 +29,17 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R -import com.example.mobileapp.db.AppDatabase import com.example.mobileapp.models.OrderWithProducts import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.ProfileViewModel import com.example.mobileapp.widgets.Header -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext @Composable fun ProfileScreen(navController: NavController){ @@ -56,12 +55,15 @@ fun ProfileScreen(navController: NavController){ @SuppressLint("CoroutineCreationDuringComposition") @Composable fun ProfileCard(navController: NavController){ + val sharedPref = PreferencesManager(LocalContext.current) + val profileViewModel: ProfileViewModel = hiltViewModel() + val activeOrdersListUiState = profileViewModel.getActiveOrders(sharedPref.getData("userId", "-1").toInt())?.collectAsLazyPagingItems() + Column( modifier = Modifier .fillMaxSize() .background(Color(212, 206, 203)), horizontalAlignment = Alignment.CenterHorizontally, - ) { Column( modifier = Modifier @@ -76,10 +78,8 @@ fun ProfileCard(navController: NavController){ .fillMaxWidth() .padding(top = 15.dp, start = 5.dp, end = 5.dp), onClick = { - navController.navigate(Screens.AuthorizationScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + profileViewModel.logout(sharedPref) + navController.navigate(Screens.AuthorizationScreen.name) }, border = BorderStroke(4.dp, Color(255,86,86)), shape = RoundedCornerShape(20.dp), @@ -104,94 +104,92 @@ fun ProfileCard(navController: NavController){ textAlign = TextAlign.Center, ) - val ordersWithProducts = remember { mutableStateListOf () } - val context = LocalContext.current - val scope = rememberCoroutineScope() - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).orderDao().getByUserId(1).collect { data -> - ordersWithProducts.clear() - ordersWithProducts.addAll(data) - } - } - } - - LazyColumn( - modifier = Modifier - .fillMaxWidth() - ) { - items(ordersWithProducts){ order -> - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - Text( - text = "№" + order.order.id.toString(), - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 34.sp, - textAlign = TextAlign.Center, - ) - val status = remember { mutableStateOf("")} - scope.launch { - AppDatabase.getInstance(context).statusDao().getById(order.order.statusId).collect { data -> - status.value = data.name - } - } - Text( - text = "Статус: " + status.value, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } - order.orderWithProducts.forEach{ orderProduct -> - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - ){ - Text( - text = orderProduct.product.name + " " + orderProduct.product.price.toString() + "р. x" + orderProduct.orderProduct.amount.toString(), - color = Color.Gray, - fontFamily = FontFamily(Font(R.font.nunito_bold)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } - } - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Start, - ){ - Text( - text = "К оплате: " + order.order.price.toString() + " р.", - modifier = Modifier.padding(start = 20.dp), - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 20.sp, - textAlign = TextAlign.Center, - ) - } + if (activeOrdersListUiState != null){ + LazyColumn( + modifier = Modifier + .fillMaxWidth() + ) { + items( + count = activeOrdersListUiState.itemCount, + key = activeOrdersListUiState.itemKey() + ){ index -> + ActiveOrderCard(activeOrdersListUiState[index]!!, profileViewModel) } } } } } +} + +@SuppressLint("CoroutineCreationDuringComposition") +@Composable +fun ActiveOrderCard(order: OrderWithProducts, profileViewModel: ProfileViewModel) { + val scope = rememberCoroutineScope() + val status = remember { mutableStateOf("")} + scope.launch { + status.value = profileViewModel.getOrderStatus(order.order.statusId) + } + Card( + shape = RoundedCornerShape(20.dp), + border = BorderStroke(3.dp, Color(222,161,69)), + modifier = Modifier + .padding(top = 15.dp, start = 5.dp, end = 5.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + Text( + text = "№" + order.order.id.toString(), + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 34.sp, + textAlign = TextAlign.Center, + ) + Text( + text = "Статус: " + status.value, + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 20.sp, + textAlign = TextAlign.Center, + ) + } + order.orderWithProducts.forEach { orderProduct -> + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + ) { + Text( + text = orderProduct.product.name + " " + orderProduct.product.price.toString() + "р. x" + orderProduct.orderProduct.amount.toString(), + color = Color.Gray, + fontFamily = FontFamily(Font(R.font.nunito_bold)), + fontSize = 20.sp, + textAlign = TextAlign.Center, + ) + } + } + Row( + modifier = Modifier + .fillMaxWidth() + .background(Color.White), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start, + ) { + Text( + text = "К оплате: " + order.order.price.toString() + " р.", + modifier = Modifier.padding(start = 20.dp), + color = Color.Black, + fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), + fontSize = 20.sp, + textAlign = TextAlign.Center, + ) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/RegistrationScreen.kt b/app/src/main/java/com/example/mobileapp/screens/RegistrationScreen.kt index 70c947e..229ffaa 100644 --- a/app/src/main/java/com/example/mobileapp/screens/RegistrationScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/RegistrationScreen.kt @@ -7,14 +7,17 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -23,13 +26,16 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.example.mobileapp.R import com.example.mobileapp.navigation.Screens +import com.example.mobileapp.viewmodels.RegistrationViewModel import com.example.mobileapp.widgets.Header @Composable @@ -50,6 +56,44 @@ fun RegistrationCard(navController: NavController){ val password = remember { mutableStateOf(TextFieldValue("")) } val passwordRepeat = remember { mutableStateOf(TextFieldValue("")) } + val viewModel = hiltViewModel() + val success = viewModel.successState.observeAsState().value + + if (success == true) { + navController.navigate(Screens.AuthorizationScreen.name) + } + + if (success == false) { + AlertDialog( + title = { + Text( + text = "Ошибка регистрации", + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + }, + text = { + Text( + text = "Проверьте корректность введенных данных", + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + }, + onDismissRequest = { + viewModel.calmSuccessState() + }, + confirmButton = { + TextButton( + onClick = { + viewModel.calmSuccessState() + } + ) { + Text("ОК") + } + } + ) + } + Column( horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -146,10 +190,7 @@ fun RegistrationCard(navController: NavController){ Button( onClick = { - navController.navigate(Screens.MenuScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + viewModel.registration(login.value.text, password.value.text, passwordRepeat.value.text) }, colors = ButtonDefaults.buttonColors(Color(255,186,83), Color.White), shape = RoundedCornerShape(30.dp, 30.dp, 30.dp, 30.dp), @@ -169,10 +210,7 @@ fun RegistrationCard(navController: NavController){ Button( onClick = { - navController.navigate(Screens.AuthorizationScreen.name) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } + navController.navigate(Screens.AuthorizationScreen.name) }, colors = ButtonDefaults.buttonColors(Color(212,206,203)), modifier = Modifier diff --git a/app/src/main/java/com/example/mobileapp/screens/UsersScreen.kt b/app/src/main/java/com/example/mobileapp/screens/UsersScreen.kt index 8954388..9535d0f 100644 --- a/app/src/main/java/com/example/mobileapp/screens/UsersScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/UsersScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf @@ -49,11 +50,21 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.map +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey +import com.example.mobileapp.PreferencesManager import com.example.mobileapp.R import com.example.mobileapp.db.AppDatabase +import com.example.mobileapp.models.Role import com.example.mobileapp.models.User +import com.example.mobileapp.viewmodels.UsersViewModel import com.example.mobileapp.widgets.Header import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -69,9 +80,12 @@ fun UsersScreen() { } @SuppressLint("CoroutineCreationDuringComposition") -@OptIn(ExperimentalMaterial3Api::class) @Composable fun UsersCard(){ + val sharedPref = PreferencesManager(LocalContext.current) + val usersViewModel: UsersViewModel = hiltViewModel() + val userListUiState = usersViewModel.getUsersList().collectAsLazyPagingItems() + Column( modifier = Modifier .fillMaxSize() @@ -97,145 +111,149 @@ fun UsersCard(){ .padding(top = 10.dp), textAlign = TextAlign.Center, ) - val users = remember { mutableStateListOf () } - val context = LocalContext.current - val scope = rememberCoroutineScope() - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - AppDatabase.getInstance(context).userDao().getAll().collect { data -> - users.addAll(data) - } - } - } - - - LazyColumn( - modifier = Modifier - .fillMaxSize() - ) { - items(users){ user -> - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(3.dp, Color(222,161,69)), - modifier = Modifier - .fillMaxSize() - .padding(top = 15.dp, start = 5.dp, end = 5.dp) - ){ - Row( - modifier = Modifier - .fillMaxSize() - .background(Color.White), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ){ - Column ( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceAround, - modifier = Modifier.fillMaxWidth(0.4f) - ) { - Text( - text = "Логин: " + user.login, - color = Color.Black, - fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)), - fontSize = 17.sp, - textAlign = TextAlign.Center, - modifier = Modifier.padding(top = 5.dp) - ) - Card( - shape = RoundedCornerShape(20.dp), - border = BorderStroke(1.dp, Color(222,161,69)), - modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp), - ){ - val roleList = remember { mutableStateListOf() } - var expanded by remember { mutableStateOf(false) } - var selectedRole by remember { mutableStateOf("") } - - scope.launch { - AppDatabase.getInstance(context).roleDao().getAll().collect { data -> - roleList.clear() - roleList.addAll(data.map {role -> role.name}) - } - } - scope.launch { - AppDatabase.getInstance(context).roleDao().getById(user.roleId).collect { data -> - selectedRole = data.name - } - } - MaterialTheme( - colorScheme = lightColorScheme( - surfaceVariant= Color.White, - surface = Color.White, - onSurface = Color.Gray - ) - ){ - ExposedDropdownMenuBox( - expanded = expanded, - onExpandedChange = { - expanded = !expanded - }, - ) { - TextField( - modifier = Modifier - .menuAnchor().fillMaxWidth(), - readOnly = true, - value = selectedRole, - onValueChange = {}, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, - ) - - ExposedDropdownMenu( - expanded = expanded, - onDismissRequest = { - expanded = false - }, - ) { - roleList.forEach { selectionOption -> - DropdownMenuItem( - text = { Text(selectionOption) }, - onClick = { - selectedRole = selectionOption - expanded = false - }, - contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, - ) - } - } - } - } - } - } - OutlinedButton( - onClick = { /*TODO*/}, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(10.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - - ){ - Icon( - painterResource(id = R.drawable.icon_settings), - contentDescription = null, - Modifier.size(30.dp), - tint = Color.Black - ) - } - OutlinedButton( - onClick = { /*TODO*/}, - border = BorderStroke(4.dp, Color(222,161,69)), - shape = RoundedCornerShape(10.dp), - colors = ButtonDefaults.outlinedButtonColors(Color(255,186,83)), - - ){ - Icon( - painterResource(id = R.drawable.icon_trash), - contentDescription = null, - Modifier.size(30.dp), - tint = Color.Black - ) - } + if (userListUiState != null){ + LazyColumn( + modifier = Modifier + .fillMaxSize() + ) { + items( + count = userListUiState.itemCount, + key = userListUiState.itemKey() + ){ index -> + if (userListUiState[index]!!.id != sharedPref.getData("userId", "-1").toInt()){ + UserCard(userListUiState[index]!!, usersViewModel) } } } } } } +} + +@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 + ) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/AuthorizationViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/AuthorizationViewModel.kt new file mode 100644 index 0000000..415e1e9 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/AuthorizationViewModel.kt @@ -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() + val successState: LiveData + 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)) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/CartViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/CartViewModel.kt new file mode 100644 index 0000000..41a704e --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/CartViewModel.kt @@ -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() + val user: LiveData + get() = _user + private val _cart = MutableLiveData() + val cart: LiveData + 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!!) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/MenuViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/MenuViewModel.kt new file mode 100644 index 0000000..533f059 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/MenuViewModel.kt @@ -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() + val user: LiveData + 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> = 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) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/OrderViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/OrderViewModel.kt new file mode 100644 index 0000000..0adacfb --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/OrderViewModel.kt @@ -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>>() + + 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) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/ProductViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/ProductViewModel.kt new file mode 100644 index 0000000..598e8d1 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/ProductViewModel.kt @@ -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() + private val _categories = mutableStateListOf() + val categories: List + get() = _categories + val successState: LiveData + get() = _successState + + private val _product = MutableLiveData() + val product: LiveData + 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) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/ProfileViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/ProfileViewModel.kt new file mode 100644 index 0000000..16baa6a --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/ProfileViewModel.kt @@ -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>? { + 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") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/RegistrationViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/RegistrationViewModel.kt new file mode 100644 index 0000000..a74ffe0 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/RegistrationViewModel.kt @@ -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() + val successState: LiveData + 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) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/viewmodels/UsersViewModel.kt b/app/src/main/java/com/example/mobileapp/viewmodels/UsersViewModel.kt new file mode 100644 index 0000000..cac8207 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/viewmodels/UsersViewModel.kt @@ -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() + val roles: List + get() = _roles + + init { + viewModelScope.launch { + roleRepository.getAll().collect{data -> + _roles.addAll(data.map { role -> role.name }) + } + } + } + + fun getUsersList() : Flow> { + 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()) + } + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 9861456..b547f79 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { id("com.android.application") version "8.1.1" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false + id("com.google.dagger.hilt.android") version "2.44" apply false } \ No newline at end of file