Лаб 5: мне было страшно, но я это сделал

This commit is contained in:
Safgerd 2024-01-18 12:57:55 +04:00
parent dd8628e0ce
commit 1b14d0c301
86 changed files with 1674 additions and 873 deletions

View File

@ -3,6 +3,7 @@ plugins {
id("org.jetbrains.kotlin.android")
id ("kotlin-kapt")
id("com.google.dagger.hilt.android")
id("org.jetbrains.kotlin.plugin.serialization")
}
android {
@ -88,4 +89,10 @@ dependencies {
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")
// lab5
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
}

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MobileApp"
@ -12,6 +14,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MobileApp"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"

View File

@ -2,18 +2,22 @@ package com.example.mobileapp
import android.app.Application
import androidx.room.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.mobileapp.db.AppDatabase
import com.example.mobileapp.repositories.CategoryRepository
import com.example.mobileapp.repositories.OrderProductRepository
import com.example.mobileapp.repositories.OrderRepository
import com.example.mobileapp.repositories.ProductRepository
import com.example.mobileapp.repositories.RoleRepository
import com.example.mobileapp.repositories.StatusRepository
import com.example.mobileapp.repositories.UserRepository
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.repositories.RestCategoryRepository
import com.example.mobileapp.data.api.repositories.RestOrderProductRepository
import com.example.mobileapp.data.api.repositories.RestOrderRepository
import com.example.mobileapp.data.api.repositories.RestProductRepository
import com.example.mobileapp.data.api.repositories.RestRoleRepository
import com.example.mobileapp.data.api.repositories.RestStatusRepository
import com.example.mobileapp.data.api.repositories.RestUserRepository
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.repositories.CategoryRepository
import com.example.mobileapp.data.repositories.OrderProductRepository
import com.example.mobileapp.data.repositories.OrderRepository
import com.example.mobileapp.data.repositories.ProductRepository
import com.example.mobileapp.data.repositories.RoleRepository
import com.example.mobileapp.data.repositories.StatusRepository
import com.example.mobileapp.data.repositories.UserRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -37,29 +41,55 @@ object AppModule {
@Provides
@Singleton
fun provideCategoryRepository(db: AppDatabase) = CategoryRepository(db.categoryDao())
fun provideServerService() : MyServerService {
return MyServerService.getInstance()
}
@Provides
@Singleton
fun provideOrderProductRepository(db: AppDatabase) = OrderProductRepository(db.orderProductDao())
fun provideRestUserRepository(service: MyServerService) : RestUserRepository {
return RestUserRepository(service)
}
@Provides
@Singleton
fun provideOrderRepository(db: AppDatabase) = OrderRepository(db.orderDao())
fun provideCategoryRepository(db: AppDatabase, restCategoryRepository: RestCategoryRepository) : CategoryRepository {
return CategoryRepository(db.categoryDao(), db, restCategoryRepository)
}
@Provides
@Singleton
fun provideProductRepository(db: AppDatabase) = ProductRepository(db.productDao())
fun provideOrderProductRepository(db: AppDatabase, restOrderProductRepository: RestOrderProductRepository) : OrderProductRepository {
return OrderProductRepository(db.orderProductDao(), restOrderProductRepository)
}
@Provides
@Singleton
fun provideRoleRepository(db: AppDatabase) = RoleRepository(db.roleDao())
fun provideOrderRepository(db: AppDatabase, restOrderRepository: RestOrderRepository) : OrderRepository {
return OrderRepository(db, db.orderDao(), db.orderProductDao(), restOrderRepository)
}
@Provides
@Singleton
fun provideStatusRepository(db: AppDatabase) = StatusRepository(db.statusDao())
fun provideProductRepository(db: AppDatabase, restProductRepository: RestProductRepository) : ProductRepository {
return ProductRepository(db.productDao(), db.orderProductDao(), restProductRepository)
}
@Provides
@Singleton
fun provideUserRepository(db: AppDatabase) = UserRepository(db.userDao())
fun provideRoleRepository(db: AppDatabase, restRoleRepository: RestRoleRepository) : RoleRepository {
return RoleRepository(db.roleDao(), restRoleRepository)
}
@Provides
@Singleton
fun provideStatusRepository(db: AppDatabase, restStatusRepository: RestStatusRepository) : StatusRepository {
return StatusRepository(db.statusDao(), restStatusRepository)
}
@Provides
@Singleton
fun provideUserRepository(db: AppDatabase, restUserRepository: RestUserRepository) : UserRepository {
return UserRepository(db.userDao(), db, restUserRepository)
}
}

View File

@ -3,7 +3,7 @@ package com.example.mobileapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import com.example.mobileapp.navigation.AppNavigation
import com.example.mobileapp.ui.navigation.AppNavigation
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint

View File

@ -1,24 +0,0 @@
package com.example.mobileapp.dao
import androidx.room.*
import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow
import androidx.paging.PagingSource
@Dao
interface CategoryDao {
@Insert
suspend fun insert(category: Category)
@Update
suspend fun update(category: Category)
@Delete
suspend fun delete(category: Category)
@Query("select * from category")
fun getAll() : Flow<List<Category>>
@Query("select * from category where category.id = :id")
fun getById(id: Int) : Flow<Category>
@Query("select * from category where category.name = :name")
fun getByName(name: String) : Flow<Category>
}

View File

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

View File

@ -1,15 +0,0 @@
package com.example.mobileapp.dao
import androidx.room.*
import com.example.mobileapp.models.OrderProduct
@Dao
interface OrderProductDao {
@Insert
suspend fun insert(orderProduct: OrderProduct)
@Update
suspend fun update(orderProduct: OrderProduct)
@Delete
suspend fun delete(orderProduct: OrderProduct)
@Query("delete from order_product WHERE order_id = :orderId AND product_id = :productId")
suspend fun deleteByProductId(orderId: Int, productId: Int);
}

View File

@ -1,25 +0,0 @@
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 {
@Insert
suspend fun insert(product: Product)
@Update
suspend fun update(product: Product)
@Delete
suspend fun delete(product: Product)
@Query("select * from product")
fun getAll() : Flow<List<Product>>
@Query("select * from product where product.id = :id")
fun getById(id: Int): Flow<Product>
@Query("select * from product where product.category_id = :categoryId")
fun getProductsByCategoryId(categoryId: Int) : PagingSource<Int, Product>
@Query("select * from category")
fun getCategoriesWithProducts() : PagingSource<Int, CategoryWithProducts>
}

View File

@ -1,26 +0,0 @@
package com.example.mobileapp.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.mobileapp.models.*
import kotlinx.coroutines.flow.Flow
@Dao
interface RoleDao {
@Insert
suspend fun insert(role: Role)
@Update
suspend fun update(role: Role)
@Delete
suspend fun delete(role: Role)
@Query("select * from role")
fun getAll() : Flow<List<Role>>
@Query("select * from role where role.id = :id")
fun getById(id: Int) : Flow<Role>
@Query("select * from role where role.name = :name")
fun getByName(name: String) : Flow<Role>
}

View File

@ -1,27 +0,0 @@
package com.example.mobileapp.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.mobileapp.models.Role
import com.example.mobileapp.models.Status
import kotlinx.coroutines.flow.Flow
@Dao
interface StatusDao {
@Insert
suspend fun insert(status: Status)
@Update
suspend fun update(status: Status)
@Delete
suspend fun delete(status: Status)
@Query("select * from status")
fun getAll() : Flow<List<Status>>
@Query("select * from status where status.id = :id")
fun getById(id: Int) : Flow<Status>
@Query("select * from status where status.name = :name")
fun getByName(name: String) : Flow<Status>
}

View File

@ -1,27 +0,0 @@
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
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Update
suspend fun update(user: User)
@Delete
suspend fun delete(user: User)
@Query("select * from user order by login collate nocase asc")
fun getAll() : Flow<List<User>>
@Query("select * from user order by login collate nocase asc")
fun getAllPaged() : PagingSource<Int, User>
@Query("select * from user where user.id = :id")
fun getById(id: Int): Flow<User>
@Query("select * from user where user.login = :login and user.password = :password limit 1")
fun getByLoginAndPassword(login: String, password: String): Flow<User?>
}

View File

@ -0,0 +1,199 @@
package com.example.mobileapp.data.api
import com.example.mobileapp.data.api.models.CategoryListResponse
import com.example.mobileapp.data.api.models.CategoryRemote
import com.example.mobileapp.data.api.models.OrderListResponse
import com.example.mobileapp.data.api.models.OrderProductRemote
import com.example.mobileapp.data.api.models.OrderRemote
import com.example.mobileapp.data.api.models.ProductRemote
import com.example.mobileapp.data.api.models.RoleRemote
import com.example.mobileapp.data.api.models.StatusRemote
import com.example.mobileapp.data.api.models.TokenRemote
import com.example.mobileapp.data.api.models.UserListResponse
import com.example.mobileapp.data.api.models.UserRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
interface MyServerService {
// User
@POST("register")
suspend fun createUser(
@Body user: UserRemote,
): UserRemote
@POST("auth")
suspend fun getToken(
@Body user: UserRemote
) : TokenRemote
@POST("check/login")
suspend fun checkLogin(
@Body user: UserRemote
) : UserRemote?
@GET("users/{after}")
suspend fun getUsersList(
@Path("after") after: Int,
@Header("Authorization") token: String
) : UserListResponse
@PUT("user/update")
suspend fun updateUser(
@Body user: UserRemote,
@Header("Authorization") token: String
): UserRemote
@DELETE("user/delete/{id}")
suspend fun deleteUser(
@Path("id") id: Int,
@Header("Authorization") token: String
)
// Product
@POST("product")
suspend fun insertProduct(
@Body product: ProductRemote,
@Header("Authorization") token: String
) : ProductRemote
@PUT("product")
suspend fun updateProduct(
@Body product: ProductRemote,
@Header("Authorization") token: String
): ProductRemote
@DELETE("product/{id}")
suspend fun deleteProduct(
@Path("id") id: Int,
@Header("Authorization") token: String
)
@GET("product/{id}")
suspend fun getProductById(
@Path("id") id: Int,
@Header("Authorization") token: String
): ProductRemote
@GET("products/{category_id}")
suspend fun getProductsByCategoryId(
@Path("category_id") category_id: Int,
@Header("Authorization") token: String
): List<ProductRemote>
// Role
@POST("role")
suspend fun getRole(
@Body role: RoleRemote,
) : RoleRemote?
@GET("roles")
suspend fun getRoles() : List<RoleRemote>
// Category
@POST("category")
suspend fun getCategory(
@Body category: CategoryRemote,
) : CategoryRemote?
@GET("categories")
suspend fun getCategories() : List<CategoryRemote>
@GET("categories/{after}")
suspend fun getCategoriesList(
@Path("after") after: Int,
@Header("Authorization") token: String
) : CategoryListResponse
// Status
@POST("status")
suspend fun getStatus(
@Body status: StatusRemote,
) : StatusRemote?
// Order
@GET("order/cart")
suspend fun getCartByUser(
@Header("Authorization") token: String
) : OrderRemote
@GET("order/to_worker/{after}")
suspend fun getOrdersToWorkList(
@Path("after") after: Int,
@Header("Authorization") token: String
) : OrderListResponse
@GET("order/to_user/{after}")
suspend fun getOrdersByUserList(
@Path("after") after: Int,
@Header("Authorization") token: String
) : OrderListResponse
@POST("order")
suspend fun insertOrder(
@Body order: OrderRemote,
@Header("Authorization") token: String
) : OrderRemote?
@PUT("order")
suspend fun updateOrder(
@Body order: OrderRemote,
@Header("Authorization") token: String
) : OrderRemote?
@DELETE("order/{id}")
suspend fun deleteOrder(
@Path("id") id: Int,
@Header("Authorization") token: String
)
// Order_Product
@POST("order/product")
suspend fun insertOrderProduct(
@Body orderProduct: OrderProductRemote,
@Header("Authorization") token: String
)
@PUT("order/product")
suspend fun updateOrderProduct(
@Body orderProduct: OrderProductRemote,
@Header("Authorization") token: String
)
@POST("order/product/delete")
suspend fun deleteOrderProduct(
@Body orderProduct: OrderProductRemote,
@Header("Authorization") token: String
)
companion object {
private const val BASE_URL ="http://10.0.2.2:8000/api/"
@Volatile
private var INSTANCE: MyServerService? = null
fun getInstance(): MyServerService {
return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = UnsafeOkHttpClient.getUnsafeOkHttpClient()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
.create(MyServerService::class.java)
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,55 @@
package com.example.mobileapp.data.api;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
public class UnsafeOkHttpClient {
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,60 @@
package com.example.mobileapp.data.api.mediators
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.CategoryListResponse
import com.example.mobileapp.data.api.models.toCategory
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.Category
import java.io.IOException
@OptIn(ExperimentalPagingApi::class)
class CategoryRemoteMediator (
private val database: AppDatabase,
private val serverService: MyServerService,
private val token: String
) : RemoteMediator<Int, Category>(){
private val categoryDao = database.categoryDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, Category>
): MediatorResult {
return try {
var loadKey = when (loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastItem = state.lastItemOrNull()
?: return MediatorResult.Success(endOfPaginationReached = true)
lastItem.id
}
}
if (loadKey == null) {
loadKey = 0
}
val response: CategoryListResponse = serverService.getCategoriesList(after = loadKey, token = token)
database.withTransaction {
if (loadType == LoadType.REFRESH) {
categoryDao.deleteAll()
}
for (category in response.categories) {
categoryDao.insert(category.toCategory())
}
}
MediatorResult.Success(endOfPaginationReached = response.nextKey == -1)
} catch (e: IOException) {
MediatorResult.Error(e)
}
}
}

View File

@ -0,0 +1,63 @@
package com.example.mobileapp.data.api.mediators
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.OrderListResponse
import com.example.mobileapp.data.api.models.toOrder
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.OrderWithProducts
import java.io.IOException
@OptIn(ExperimentalPagingApi::class)
class OrderRemoteMediator (
private val database: AppDatabase,
private val serverService: MyServerService,
private val query: String,
private val token: String
) : RemoteMediator<Int, OrderWithProducts>(){
private val orderDao = database.orderDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, OrderWithProducts>
): MediatorResult {
return try {
var loadKey = when (loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastItem = state.lastItemOrNull()
?: return MediatorResult.Success(endOfPaginationReached = true)
lastItem.order.id
}
}
if (loadKey == null) {
loadKey = 0
}
val response: OrderListResponse = if (query.isEmpty()) {
serverService.getOrdersToWorkList (after = loadKey, token = token)
} else {serverService.getOrdersByUserList(after = loadKey, token = token)}
database.withTransaction {
if (loadType == LoadType.REFRESH) {
orderDao.deleteByQuery(query)
}
for (order in response.orders) {
orderDao.insert(order.toOrder())
}
}
MediatorResult.Success(endOfPaginationReached = response.nextKey == -1)
} catch (e: IOException) {
MediatorResult.Error(e)
}
}
}

View File

@ -0,0 +1,60 @@
package com.example.mobileapp.data.api.mediators
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.UserListResponse
import com.example.mobileapp.data.api.models.toUser
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.User
import java.io.IOException
@OptIn(ExperimentalPagingApi::class)
class UserRemoteMediator (
private val database: AppDatabase,
private val serverService: MyServerService,
private val token: String
) : RemoteMediator<Int, User>(){
private val userDao = database.userDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, User>
): MediatorResult {
return try {
var loadKey = when (loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastItem = state.lastItemOrNull()
?: return MediatorResult.Success(endOfPaginationReached = true)
lastItem.id
}
}
if (loadKey == null) {
loadKey = 0
}
val response: UserListResponse = serverService.getUsersList(after = loadKey, token = token)
database.withTransaction {
if (loadType == LoadType.REFRESH) {
userDao.deleteAll()
}
for (user in response.users) {
userDao.insert(user.toUser())
}
}
MediatorResult.Success(endOfPaginationReached = response.nextKey == -1)
} catch (e: IOException) {
MediatorResult.Error(e)
}
}
}

View File

@ -0,0 +1,24 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.Category
import kotlinx.serialization.Serializable
@Serializable
data class CategoryRemote(
val id: Int? = 0,
val name: String = ""
)
@Serializable
data class CategoryListResponse(
val categories: List<CategoryRemote> = listOf(),
val nextKey: Int? = null
)
fun CategoryRemote.toCategory(): Category = Category(
id, name
)
fun Category.toCategoryRemote(): CategoryRemote = CategoryRemote(
id = id, name = name
)

View File

@ -0,0 +1,48 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.Order
import com.example.mobileapp.data.db.models.OrderProduct
import kotlinx.serialization.Serializable
@Serializable
data class OrderRemote(
val id: Int? = null,
val user_id: Int? = -1,
val price: Int = -1,
val status_id: Int? = -1,
val order_products: List<OrderProductRemote> = listOf()
)
@Serializable
data class OrderListResponse(
val orders: List<OrderRemote> = listOf(),
val nextKey: Int? = null
)
fun OrderRemote.toOrder() : Order = Order(
id= id, userId = user_id, price= price, statusId = status_id
)
fun Order.toOrderRemote() : OrderRemote = OrderRemote(
id= id, user_id= userId, price= price, status_id = statusId
)
@Serializable
data class OrderProductRemote(
val id: Int? = null,
val order_id: Int = -1,
val product_id: Int = -1,
val amount: Int = 0,
val order: OrderRemote? = null,
val product: ProductRemote? = null
)
fun OrderProductRemote.toOrderProduct() : OrderProduct = OrderProduct(
order_id, product_id, amount
)
fun OrderProduct.toOrderProductRemote() : OrderProductRemote = OrderProductRemote(
order_id = orderId, product_id = productId, amount = amount
)

View File

@ -0,0 +1,20 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.Product
import kotlinx.serialization.Serializable
@Serializable
data class ProductRemote(
val id: Int? = null,
val name: String = "",
val category_id: Int = 0,
val price: Int = 0,
)
fun ProductRemote.toProduct(): Product = Product(
id, name, category_id, price
)
fun Product.toProductRemote(): ProductRemote = ProductRemote(
id = id, name = name, category_id = categoryId, price = price
)

View File

@ -0,0 +1,18 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.Role
import kotlinx.serialization.Serializable
@Serializable
data class RoleRemote(
val id: Int? = 0,
val name: String = ""
)
fun RoleRemote.toRole(): Role = Role(
id, name
)
fun Role.toRoleRemote(): RoleRemote = RoleRemote(
id = id, name = name
)

View File

@ -0,0 +1,18 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.Status
import kotlinx.serialization.Serializable
@Serializable
data class StatusRemote(
val id: Int? = 0,
val name: String = ""
)
fun StatusRemote.toStatus(): Status = Status(
id, name
)
fun Status.toStatusRemote(): StatusRemote = StatusRemote(
id = id, name = name
)

View File

@ -0,0 +1,31 @@
package com.example.mobileapp.data.api.models
import com.example.mobileapp.data.db.models.User
import kotlinx.serialization.Serializable
@Serializable
data class TokenRemote(
val access_token: String = ""
)
@Serializable
data class UserRemote(
val id: Int? = 0,
val login: String = "",
val password:String = "",
val role_id:Int = -1
)
@Serializable
data class UserListResponse(
val users: List<UserRemote> = listOf(),
val nextKey: Int? = null
)
fun UserRemote.toUser(): User = User(
id, login, password, role_id
)
fun User.toUserRemote(): UserRemote = UserRemote(
id = id, login = login, password = password, role_id = roleId
)

View File

@ -0,0 +1,13 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.CategoryRemote
import javax.inject.Inject
class RestCategoryRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun getCategories() : List<CategoryRemote> {
return service.getCategories()
}
}

View File

@ -0,0 +1,21 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.OrderProductRemote
import javax.inject.Inject
class RestOrderProductRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun insertOrderProduct(token: String, orderProduct: OrderProductRemote) {
service.insertOrderProduct(orderProduct, token)
}
suspend fun updateOrderProduct(token: String, orderProduct: OrderProductRemote) {
service.updateOrderProduct(orderProduct, token)
}
suspend fun deleteOrderProduct(token: String, orderProduct: OrderProductRemote) {
service.deleteOrderProduct(orderProduct, token)
}
}

View File

@ -0,0 +1,25 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.OrderRemote
import javax.inject.Inject
class RestOrderRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun getCartByUser(token:String) : OrderRemote {
return service.getCartByUser(token)
}
suspend fun insertOrder(token: String, order: OrderRemote): OrderRemote? {
return service.insertOrder(order, token)
}
suspend fun updateOrder(token: String, order: OrderRemote): OrderRemote? {
return service.updateOrder(order, token)
}
suspend fun deleteOrder(token: String, orderId: Int) {
service.deleteOrder(orderId, token)
}
}

View File

@ -0,0 +1,32 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.ProductRemote
import com.example.mobileapp.data.api.models.toProduct
import com.example.mobileapp.data.api.models.toProductRemote
import com.example.mobileapp.data.db.models.Product
import javax.inject.Inject
class RestProductRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun insert(product: Product, token: String) {
service.insertProduct(product.toProductRemote(), token)
}
suspend fun update(product: Product, token: String) {
service.updateProduct((product.toProductRemote()), token)
}
suspend fun delete(id: Int, token: String) {
service.deleteProduct(id, token)
}
suspend fun getProductById(id: Int, token: String) : Product {
return service.getProductById(id, token).toProduct()
}
suspend fun getProductsByCategoryId(categoryId: Int, token: String) : List<ProductRemote> {
return service.getProductsByCategoryId(categoryId, token)
}
}

View File

@ -0,0 +1,19 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.RoleRemote
import com.example.mobileapp.data.api.models.toRoleRemote
import com.example.mobileapp.data.db.models.Role
import javax.inject.Inject
class RestRoleRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun getRole(role: Role): RoleRemote? {
return service.getRole(role.toRoleRemote())
}
suspend fun getRoles() : List<RoleRemote> {
return service.getRoles()
}
}

View File

@ -0,0 +1,15 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.StatusRemote
import com.example.mobileapp.data.api.models.toStatusRemote
import com.example.mobileapp.data.db.models.Status
import javax.inject.Inject
class RestStatusRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun getStatus(status: Status): StatusRemote? {
return service.getStatus(status.toStatusRemote())
}
}

View File

@ -0,0 +1,32 @@
package com.example.mobileapp.data.api.repositories
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.TokenRemote
import com.example.mobileapp.data.api.models.UserRemote
import com.example.mobileapp.data.api.models.toUserRemote
import com.example.mobileapp.data.db.models.User
import javax.inject.Inject
class RestUserRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun insert(user: User) {
service.createUser(user.toUserRemote())
}
suspend fun update(user: User, token: String) {
service.updateUser((user.toUserRemote()), token)
}
suspend fun delete(id: Int, token: String) {
service.deleteUser(id, token)
}
suspend fun getToken(user: User): TokenRemote {
return service.getToken(user.toUserRemote())
}
suspend fun checkLogin(user: User): UserRemote? {
return service.checkLogin(user.toUserRemote())
}
}

View File

@ -1,12 +1,7 @@
package com.example.mobileapp.db
import android.content.Context
package com.example.mobileapp.data.db
import androidx.room.*
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.mobileapp.dao.*
import com.example.mobileapp.models.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import com.example.mobileapp.data.db.dao.*
import com.example.mobileapp.data.db.models.*
@Database(
entities =
@ -19,7 +14,7 @@ import kotlinx.coroutines.launch
Product::class,
OrderProduct::class,
],
version = 2,
version = 5,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {

View File

@ -0,0 +1,19 @@
package com.example.mobileapp.data.db.dao
import androidx.room.*
import com.example.mobileapp.data.db.models.*
import androidx.paging.PagingSource
import com.example.mobileapp.data.db.models.Category
@Dao
interface CategoryDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(category: Category)
@Update
suspend fun update(category: Category)
@Delete
suspend fun delete(category: Category)
@Query("delete from category")
fun deleteAll()
@Query("select * from category")
fun getPaged() : PagingSource<Int, Category>
}

View File

@ -0,0 +1,41 @@
package com.example.mobileapp.data.db.dao
import androidx.paging.PagingSource
import androidx.room.*
import com.example.mobileapp.data.db.models.Order
import com.example.mobileapp.data.db.models.OrderWithProducts
import kotlinx.coroutines.flow.Flow
@Dao
interface OrderDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(order: Order)
@Update
suspend fun update(order: Order)
@Delete
suspend fun delete(order: Order)
@Query("select * from `order` where `order`.`id` =:id")
fun getById(id: Int): Flow<OrderWithProducts>
@Query("select * from `order` where `order`.`user_id` =:userId and `order`.`status_id` = 1")
fun getCartByUser(userId: Int): Flow<OrderWithProducts?>
@Query("select * from `order` where `order`.`status_id` != 1 and `order`.`status_id` != 4")
fun getOrdersToWork(): PagingSource<Int, OrderWithProducts>
@Query("select * from `order` where (`order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4)")
fun getOrdersByUser(userId: Int): PagingSource<Int, OrderWithProducts>
@Query("delete from `order` where `order`.`status_id` != 1 and `order`.`status_id` != 4")
fun deleteOrdersToWork()
@Query("delete from `order` where (`order`.`user_id` =:userId and `order`.`status_id` != 1 and `order`.`status_id` != 4)")
fun deleteOrdersByUser(userId: Int)
fun deleteByQuery(query: String) {
if (query.isEmpty()) {
deleteOrdersToWork()
}
else {
deleteOrdersByUser(query.toInt())
}
}
}

View File

@ -0,0 +1,17 @@
package com.example.mobileapp.data.db.dao
import androidx.room.*
import com.example.mobileapp.data.db.models.OrderProduct
@Dao
interface OrderProductDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
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")
suspend fun deleteByOrderId(orderId: Int)
@Query("delete from order_product WHERE product_id = :productId")
suspend fun deleteByProductId(productId: Int)
}

View File

@ -0,0 +1,13 @@
package com.example.mobileapp.data.db.dao
import androidx.room.*
import com.example.mobileapp.data.db.models.Product
@Dao
interface ProductDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(product: Product)
@Update
suspend fun update(product: Product)
@Delete
suspend fun delete(product: Product)
}

View File

@ -0,0 +1,17 @@
package com.example.mobileapp.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Update
import com.example.mobileapp.data.db.models.Role
@Dao
interface RoleDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(role: Role)
@Update
suspend fun update(role: Role)
@Delete
suspend fun delete(role: Role)
}

View File

@ -0,0 +1,17 @@
package com.example.mobileapp.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Update
import com.example.mobileapp.data.db.models.Status
@Dao
interface StatusDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(status: Status)
@Update
suspend fun update(status: Status)
@Delete
suspend fun delete(status: Status)
}

View File

@ -0,0 +1,18 @@
package com.example.mobileapp.data.db.dao
import androidx.paging.PagingSource
import androidx.room.*
import com.example.mobileapp.data.db.models.User
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(user: User)
@Update
suspend fun update(user: User)
@Delete
suspend fun delete(user: User)
@Query("delete from user")
fun deleteAll()
@Query("select * from user")
fun getPaged() : PagingSource<Int, User>
}

View File

@ -1,4 +1,5 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "category")

View File

@ -1,22 +1,19 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(
tableName = "order",
foreignKeys = [
ForeignKey(User::class, ["id"], ["user_id"])
]
tableName = "order"
)
data class Order(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
val id: Int?,
@ColumnInfo(name = "user_id")
val userId: Int,
val userId: Int?,
@ColumnInfo(name = "price")
var price: Int,
@ColumnInfo(name = "status_id")
var statusId: Int,
var statusId: Int?,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "order_product", primaryKeys = ["order_id", "product_id"])

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
data class OrderProductWithProduct(

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
data class OrderWithProducts(

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "product")

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "role")

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "status")

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.models
package com.example.mobileapp.data.db.models
import androidx.room.*
@Entity(tableName = "user")

View File

@ -0,0 +1,35 @@
package com.example.mobileapp.data.repositories
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.mediators.CategoryRemoteMediator
import com.example.mobileapp.data.api.models.CategoryRemote
import com.example.mobileapp.data.api.repositories.RestCategoryRepository
import com.example.mobileapp.data.db.dao.CategoryDao
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.Category
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class CategoryRepository @Inject constructor(
private val categoryDao: CategoryDao,
private val database: AppDatabase,
private val restRepository: RestCategoryRepository
){
@OptIn(ExperimentalPagingApi::class)
fun getAllPaged(token: String): Flow<PagingData<Category>> = Pager(
config = PagingConfig(
pageSize = 3,
enablePlaceholders = false
),
pagingSourceFactory = categoryDao::getPaged,
remoteMediator = CategoryRemoteMediator(database = database, serverService = MyServerService.getInstance(), token = token)
).flow
suspend fun getCategories() : List<CategoryRemote> {
return restRepository.getCategories()
}
}

View File

@ -0,0 +1,25 @@
package com.example.mobileapp.data.repositories
import com.example.mobileapp.data.api.models.toOrderProductRemote
import com.example.mobileapp.data.api.repositories.RestOrderProductRepository
import com.example.mobileapp.data.db.dao.OrderProductDao
import com.example.mobileapp.data.db.models.OrderProduct
import javax.inject.Inject
class OrderProductRepository @Inject constructor(
private val orderProductDao: OrderProductDao,
private val restOrderProductRepository: RestOrderProductRepository
){
suspend fun insert(token: String, orderProduct: OrderProduct) {
orderProductDao.insert(orderProduct)
return restOrderProductRepository.insertOrderProduct(token, orderProduct.toOrderProductRemote())
}
suspend fun update(token: String, orderProduct: OrderProduct) {
orderProductDao.update(orderProduct)
return restOrderProductRepository.updateOrderProduct(token, orderProduct.toOrderProductRemote())
}
suspend fun delete(token: String, orderProduct: OrderProduct) {
orderProductDao.delete(orderProduct)
restOrderProductRepository.deleteOrderProduct(token, orderProduct.toOrderProductRemote())
}
}

View File

@ -0,0 +1,75 @@
package com.example.mobileapp.data.repositories
import com.example.mobileapp.data.db.dao.OrderDao
import androidx.paging.*
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.models.toOrder
import com.example.mobileapp.data.api.models.toOrderProduct
import com.example.mobileapp.data.api.models.toOrderRemote
import com.example.mobileapp.data.api.repositories.RestOrderRepository
import com.example.mobileapp.data.db.dao.OrderProductDao
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.Order
import com.example.mobileapp.data.api.mediators.OrderRemoteMediator
import com.example.mobileapp.data.db.models.OrderWithProducts
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import javax.inject.Inject
class OrderRepository @Inject constructor(
private val database: AppDatabase,
private val orderDao: OrderDao,
private val orderProductDao: OrderProductDao,
private val restRepository: RestOrderRepository
){
suspend fun insert(token: String, order: Order): Order? {
orderDao.insert(order)
val result = restRepository.insertOrder(token, order.toOrderRemote())
if (result == null) {
return result
}
return result.toOrder()
}
suspend fun update(token: String, order: Order) {
orderDao.update(order)
restRepository.updateOrder(token, order.toOrderRemote())
}
suspend fun delete(token: String, order: Order) {
orderProductDao.deleteByOrderId(order.id!!)
orderDao.delete(order)
restRepository.deleteOrder(token, order.id)
}
fun getById(id: Int) = orderDao.getById(id)
suspend fun getCartByUser(token: String) : OrderWithProducts? {
val order = restRepository.getCartByUser(token)
if (order.id != null) {
orderDao.insert(order.toOrder())
for (product in order.order_products) {
orderProductDao.insert(product.toOrderProduct())
}
return orderDao.getCartByUser(order.user_id!!).first()
}
return null
}
@OptIn(ExperimentalPagingApi::class)
fun getOrdersToWorkPaged(token: String): Flow<PagingData<OrderWithProducts>> = Pager(
config = PagingConfig(
pageSize = 6,
enablePlaceholders = false
),
pagingSourceFactory = orderDao::getOrdersToWork,
remoteMediator = OrderRemoteMediator(database = database, serverService = MyServerService.getInstance(), query = "", token = token)
).flow
@OptIn(ExperimentalPagingApi::class)
fun getOrdersByUserPaged(token: String, userId: Int): Flow<PagingData<OrderWithProducts>> = Pager(
config = PagingConfig(
pageSize = 6,
enablePlaceholders = false
),
pagingSourceFactory = {orderDao.getOrdersByUser(userId)},
remoteMediator = OrderRemoteMediator(database = database, serverService = MyServerService.getInstance(), query = userId.toString(), token = token)
).flow
}

View File

@ -0,0 +1,43 @@
package com.example.mobileapp.data.repositories
import com.example.mobileapp.data.api.models.ProductRemote
import com.example.mobileapp.data.api.models.toProduct
import com.example.mobileapp.data.api.repositories.RestProductRepository
import com.example.mobileapp.data.db.dao.OrderProductDao
import com.example.mobileapp.data.db.dao.ProductDao
import com.example.mobileapp.data.db.models.Product
import javax.inject.Inject
class ProductRepository @Inject constructor(
private val productDao: ProductDao,
private val orderProductDao: OrderProductDao,
private val restRepository: RestProductRepository
){
suspend fun insert(product: Product, token: String) {
productDao.insert(product)
return restRepository.insert(product, token)
}
suspend fun update(product: Product, token: String) {
productDao.update(product)
return restRepository.update(product, token)
}
suspend fun delete(product: Product, token: String) {
productDao.delete(product)
product.id?.let { orderProductDao.deleteByProductId(it) }
return restRepository.delete(product.id!!, token)
}
suspend fun getProductById(id: Int, token: String) : Product {
val product = restRepository.getProductById(id, token)
productDao.insert(product)
return product
}
suspend fun getProductsByCategoryId(categoryId: Int, token: String) : List<ProductRemote> {
val products = restRepository.getProductsByCategoryId(categoryId, token)
products.forEach{ productRemote ->
productDao.insert(productRemote.toProduct())
}
return products
}
}

View File

@ -0,0 +1,24 @@
package com.example.mobileapp.data.repositories
import com.example.mobileapp.data.api.models.RoleRemote
import com.example.mobileapp.data.api.repositories.RestRoleRepository
import com.example.mobileapp.data.db.dao.RoleDao
import com.example.mobileapp.data.db.models.Role
import javax.inject.Inject
class RoleRepository @Inject constructor(
private val roleDao: RoleDao,
private val restRepository: RestRoleRepository
){
suspend fun insert(role: Role) = roleDao.insert(role)
suspend fun update(role: Role) = roleDao.update(role)
suspend fun delete(role: Role) = roleDao.delete(role)
suspend fun getRole(role: Role): RoleRemote? {
return restRepository.getRole(role)
}
suspend fun getRoles() : List<RoleRemote> {
return restRepository.getRoles()
}
}

View File

@ -0,0 +1,24 @@
package com.example.mobileapp.data.repositories
import com.example.mobileapp.data.api.models.StatusRemote
import com.example.mobileapp.data.api.models.toStatus
import com.example.mobileapp.data.api.repositories.RestStatusRepository
import com.example.mobileapp.data.db.dao.StatusDao
import com.example.mobileapp.data.db.models.Status
import javax.inject.Inject
class StatusRepository @Inject constructor(
private val statusDao: StatusDao,
private val restRepository: RestStatusRepository
){
suspend fun insert(status: Status) = statusDao.insert(status)
suspend fun update(status: Status) = statusDao.update(status)
suspend fun delete(status: Status) = statusDao.delete(status)
suspend fun getStatus(status: Status): StatusRemote? {
val statusModel = restRepository.getStatus(status)
if (statusModel != null){
statusDao.insert(statusModel.toStatus())
}
return statusModel
}
}

View File

@ -0,0 +1,51 @@
package com.example.mobileapp.data.repositories
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.mobileapp.data.api.MyServerService
import com.example.mobileapp.data.api.mediators.UserRemoteMediator
import com.example.mobileapp.data.api.models.TokenRemote
import com.example.mobileapp.data.api.models.UserRemote
import com.example.mobileapp.data.api.repositories.RestUserRepository
import com.example.mobileapp.data.db.dao.UserDao
import com.example.mobileapp.data.db.AppDatabase
import com.example.mobileapp.data.db.models.User
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class UserRepository @Inject constructor(
private val userDao: UserDao,
private val database: AppDatabase,
private val restRepository: RestUserRepository
){
suspend fun insert(user: User){
userDao.insert(user)
restRepository.insert(user)
}
suspend fun update(user: User, token: String) {
return restRepository.update(user, token)
}
suspend fun delete(user: User, token: String) {
userDao.delete(user)
return restRepository.delete(user.id!!, token)
}
@OptIn(ExperimentalPagingApi::class)
fun getAllPaged(token: String): Flow<PagingData<User>> = Pager(
config = PagingConfig(
pageSize = 6,
enablePlaceholders = false
),
pagingSourceFactory = userDao::getPaged,
remoteMediator = UserRemoteMediator(database = database, serverService = MyServerService.getInstance(), token = token)
).flow
suspend fun getToken(user: User): TokenRemote {
return restRepository.getToken(user)
}
suspend fun checkLogin(user: User): UserRemote? {
return restRepository.checkLogin(user)
}
}

View File

@ -1,4 +1,4 @@
package com.example.mobileapp
package com.example.mobileapp.data.sharedpref
import android.content.Context
import android.content.SharedPreferences

View File

@ -1,9 +0,0 @@
package com.example.mobileapp.models
import androidx.room.*
data class CategoryWithProducts(
@Embedded
val category: Category,
@Relation(parentColumn = "id", entityColumn = "category_id")
val products: List<Product>
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.navigation
package com.example.mobileapp.ui.navigation
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -14,12 +14,9 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
@ -30,24 +27,18 @@ 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
import com.example.mobileapp.screens.CartScreen
import com.example.mobileapp.screens.CreateProductScreen
import com.example.mobileapp.screens.EditMenuScreen
import com.example.mobileapp.screens.EditProductScreen
import com.example.mobileapp.screens.ManagmentScreen
import com.example.mobileapp.screens.MenuScreen
import com.example.mobileapp.screens.OrderScreen
import com.example.mobileapp.screens.ProfileScreen
import com.example.mobileapp.screens.RegistrationScreen
import com.example.mobileapp.screens.UsersScreen
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.example.mobileapp.data.sharedpref.PreferencesManager
import com.example.mobileapp.ui.screens.AuthorizationScreen
import com.example.mobileapp.ui.screens.CartScreen
import com.example.mobileapp.ui.screens.CreateProductScreen
import com.example.mobileapp.ui.screens.EditMenuScreen
import com.example.mobileapp.ui.screens.EditProductScreen
import com.example.mobileapp.ui.screens.ManagmentScreen
import com.example.mobileapp.ui.screens.MenuScreen
import com.example.mobileapp.ui.screens.OrderScreen
import com.example.mobileapp.ui.screens.ProfileScreen
import com.example.mobileapp.ui.screens.RegistrationScreen
import com.example.mobileapp.ui.screens.UsersScreen
@OptIn(ExperimentalMaterial3Api::class)
@Composable

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.navigation
package com.example.mobileapp.ui.navigation
import com.example.mobileapp.R

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.navigation
package com.example.mobileapp.ui.navigation
enum class Screens {
CartScreen,

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
@ -34,11 +34,11 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.viewmodels.AuthorizationViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun AuthorizationScreen(navController: NavController) {
@ -57,11 +57,8 @@ fun AuthorizationCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val login = remember { mutableStateOf(TextFieldValue("")) }
val password = remember { mutableStateOf(TextFieldValue("")) }
val viewModel = hiltViewModel<AuthorizationViewModel>()
val success = viewModel.successState.observeAsState().value
if (success == true) {
navController.navigate(Screens.MenuScreen.name)
}

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -19,8 +19,11 @@ import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -32,12 +35,12 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.models.OrderProductWithProduct
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.data.db.models.OrderProductWithProduct
import com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.viewmodels.CartViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun CartScreen(){
@ -54,8 +57,9 @@ fun CartScreen(){
@Composable
fun CartCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
cartViewModel.retrieveUser(sharedPref)
cartViewModel.getCart(searchToken)
val cart: OrderWithProducts? = cartViewModel.cart.observeAsState().value
Column(
@ -63,14 +67,12 @@ fun CartCard(){
.fillMaxSize()
.background(Color(212, 206, 203)),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(0.9f)
.background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
@ -93,7 +95,6 @@ fun CartCard(){
CartProductCard(cartViewModel, cart.orderWithProducts[index])
}
}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -118,7 +119,7 @@ fun CartCard(){
OutlinedButton(
onClick = {
cartViewModel.makeOrder()
cartViewModel.makeOrder(searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),
@ -135,7 +136,14 @@ fun CartCard(){
}
@Composable
fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProduct){
fun CartProductCard(
cartViewModel: CartViewModel,
product: OrderProductWithProduct
){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
var amountProduct by remember { mutableStateOf(product.orderProduct.amount)}
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -180,7 +188,8 @@ fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProdu
modifier = Modifier
.fillMaxHeight(),
onClick = {
cartViewModel.removeProductFromOrder(product.product.id!!)
cartViewModel.removeProductFromOrder(searchToken, product.product.id!!)
amountProduct -= 1
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topStart = 30.dp, bottomStart = 30.dp),
@ -205,7 +214,7 @@ fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProdu
top = 7.dp,
bottom = 7.dp
),
text = product.orderProduct.amount.toString(),
text = amountProduct.toString(),
color = Color.Black,
fontFamily = FontFamily(Font(R.font.nunito_bold)),
fontSize = 20.sp,
@ -217,7 +226,8 @@ fun CartProductCard(cartViewModel: CartViewModel, product: OrderProductWithProdu
modifier = Modifier
.fillMaxHeight(),
onClick = {
cartViewModel.addProductToOrder(product.product.id!!)
cartViewModel.addProductToOrder(searchToken, product.product.id!!)
amountProduct += 1
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
@ -31,6 +31,7 @@ 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
@ -40,10 +41,11 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.viewmodels.ProductViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun CreateProductScreen(navController: NavController){
@ -59,6 +61,8 @@ fun CreateProductScreen(navController: NavController){
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreateProductCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val productViewModel: ProductViewModel = hiltViewModel<ProductViewModel>()
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
@ -158,9 +162,9 @@ fun CreateProductCard(navController: NavController){
) {
categoryList.first().forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
text = { Text(selectionOption.name) },
onClick = {
selectedCategory = selectionOption
selectedCategory = selectionOption.name
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
@ -191,7 +195,7 @@ fun CreateProductCard(navController: NavController){
)
OutlinedButton(
onClick = {
productViewModel.addProduct(title.value.text, selectedCategory, price.value.text)
productViewModel.addProduct(title.value.text, selectedCategory, price.value.text, searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
@ -19,6 +19,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -33,14 +34,13 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
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.data.db.models.Category
import com.example.mobileapp.data.db.models.Product
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.viewmodels.MenuViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun EditMenuScreen(navController: NavController){
@ -56,9 +56,9 @@ fun EditMenuScreen(navController: NavController){
@Composable
fun EditMenuCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
val categoryListUi = menuViewModel.getCategoriesList(searchToken).collectAsLazyPagingItems()
Column(
modifier = Modifier
@ -75,16 +75,12 @@ fun EditMenuCard(navController: NavController){
horizontalAlignment = Alignment.CenterHorizontally,
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
LazyColumn() {
items(
count = categoriesWithProducts.itemCount,
key = categoriesWithProducts.itemKey()
count = categoryListUi.itemCount,
key = categoryListUi.itemKey()
){ index ->
EditMenuCategoryProductsCard(navController, menuViewModel, categoriesWithProducts[index]!!)
EditMenuCategoryProductsCard(navController, menuViewModel, categoryListUi[index]!!, searchToken)
}
}
}
@ -92,29 +88,42 @@ fun EditMenuCard(navController: NavController){
}
@Composable
fun EditMenuCategoryProductsCard(navController: NavController, menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){
if (categoryWithProducts.products.size == 0){
return
}
fun EditMenuCategoryProductsCard(
navController: NavController,
menuViewModel: MenuViewModel,
category: Category,
searchToken: String
){
val productListUiState = menuViewModel.getProductsByCategoryId(category.id!!, searchToken).collectAsState(initial = listOf())
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,
)
if (productListUiState.value?.size != 0){
Text(
text = 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)
Column {
productListUiState.value!!.forEach{product ->
EditMenuProductsCard(navController, menuViewModel, product, category, searchToken)
}
}
}
}
@Composable
fun EditMenuProductsCard(navController: NavController, menuViewModel : MenuViewModel, product : Product, category: Category){
fun EditMenuProductsCard(
navController: NavController,
menuViewModel: MenuViewModel,
product: Product,
category: Category,
searchToken: String
){
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -172,7 +181,8 @@ fun EditMenuProductsCard(navController: NavController, menuViewModel : MenuViewM
OutlinedButton(
onClick = {
menuViewModel.deleteProduct(product)
menuViewModel.deleteProduct(product, searchToken)
navController.navigate(Screens.EditMenuScreen.name)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -28,11 +28,11 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
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.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
@ -42,12 +42,12 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.models.Product
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.data.db.models.Product
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.viewmodels.ProductViewModel
import com.example.mobileapp.widgets.Header
import kotlinx.coroutines.launch
import com.example.mobileapp.ui.widgets.Header
@Composable
fun EditProductScreen(navController: NavController, id: Int){
@ -64,10 +64,10 @@ fun EditProductScreen(navController: NavController, id: Int){
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditProductCard(navController: NavController, productId : Int){
val scope = rememberCoroutineScope()
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val productViewModel: ProductViewModel = hiltViewModel<ProductViewModel>()
productViewModel.getProduct(productId)
productViewModel.getProduct(productId, searchToken)
val currentProduct = remember { mutableStateOf<Product?>(null) }
val title = remember { mutableStateOf(TextFieldValue("")) }
val price = remember { mutableStateOf(TextFieldValue("")) }
@ -80,9 +80,7 @@ fun EditProductCard(navController: NavController, productId : Int){
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)
}
selectedCategory = productViewModel.getProductCategory(productViewModel.product.value!!.categoryId)
}
if (success == true) {
@ -149,7 +147,6 @@ fun EditProductCard(navController: NavController, productId : Int){
.fillMaxWidth()
.padding(top = 20.dp, start = 20.dp, end = 20.dp),
){
MaterialTheme(
colorScheme = lightColorScheme(
surfaceVariant= Color.White,
@ -182,9 +179,9 @@ fun EditProductCard(navController: NavController, productId : Int){
) {
categoryList.first().forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
text = { Text(selectionOption.name) },
onClick = {
selectedCategory = selectionOption
selectedCategory = selectionOption.name
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
@ -199,7 +196,6 @@ fun EditProductCard(navController: NavController, productId : Int){
onValueChange = {price.value = it},
placeholder = { Text(text = "Цена", fontSize = 20.sp, color = Color.LightGray) },
singleLine = true,
shape = RoundedCornerShape(20.dp),
textStyle = TextStyle(fontSize = 20.sp),
colors = TextFieldDefaults.outlinedTextFieldColors(
@ -216,7 +212,12 @@ fun EditProductCard(navController: NavController, productId : Int){
OutlinedButton(
onClick = {
productViewModel.updateProduct(currentProduct.value?.id!!, title.value.text, selectedCategory, price.value.text)
productViewModel.updateProduct(
currentProduct.value?.id!!,
title.value.text,
selectedCategory,
price.value.text,
searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(20.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
@ -27,8 +27,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.mobileapp.R
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.ui.widgets.Header
@Composable
fun ManagmentScreen(navController: NavController){
@ -55,7 +55,6 @@ fun ManagmentCard(navController: NavController){
.fillMaxHeight()
.fillMaxWidth(0.9f)
.background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
@ -18,6 +18,7 @@ import androidx.compose.material3.Card
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -31,13 +32,12 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.models.Category
import com.example.mobileapp.models.CategoryWithProducts
import com.example.mobileapp.models.Product
import com.example.mobileapp.data.db.models.Category
import com.example.mobileapp.data.db.models.Product
import com.example.mobileapp.viewmodels.MenuViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun MenuScreen(){
@ -53,9 +53,9 @@ fun MenuScreen(){
@Composable
fun MenuCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val menuViewModel: MenuViewModel = hiltViewModel<MenuViewModel>()
menuViewModel.retrieveUser(sharedPref)
val categoriesWithProducts = menuViewModel.categoiesWithProductsListUiState.collectAsLazyPagingItems()
val categoryListUi = menuViewModel.getCategoriesList(searchToken).collectAsLazyPagingItems()
Column(
modifier = Modifier
@ -72,15 +72,12 @@ fun MenuCard(){
horizontalAlignment = Alignment.CenterHorizontally,
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
) {
LazyColumn() {
items(
count = categoriesWithProducts.itemCount,
key = categoriesWithProducts.itemKey()
count = categoryListUi.itemCount,
key = categoryListUi.itemKey()
){ index ->
MenuCategoryProductsCard(menuViewModel, categoriesWithProducts[index]!!)
MenuCategoryProductsCard(menuViewModel, categoryListUi[index]!!, searchToken)
}
}
}
@ -88,29 +85,42 @@ fun MenuCard(){
}
@Composable
fun MenuCategoryProductsCard(menuViewModel : MenuViewModel, categoryWithProducts: CategoryWithProducts){
if (categoryWithProducts.products.size == 0){
return
}
fun MenuCategoryProductsCard(
menuViewModel: MenuViewModel,
category: Category,
searchToken: String
){
val productListUiState = menuViewModel.getProductsByCategoryId(category.id!!, searchToken).collectAsState(initial = listOf())
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,
)
if (productListUiState.value?.size != 0){
Text(
text = 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)
Column {
productListUiState.value!!.forEach{product ->
MenuProductsCard(menuViewModel, product, category, searchToken)
}
}
}
}
@Composable
fun MenuProductsCard(menuViewModel : MenuViewModel, product : Product, category: Category){
fun MenuProductsCard(
menuViewModel: MenuViewModel,
product: Product,
category: Category,
searchToken: String
){
val sharedPref = PreferencesManager(LocalContext.current)
val userId = sharedPref.getData("userId", "").toInt()
Card(
shape = RoundedCornerShape(20.dp),
border = BorderStroke(3.dp, Color(222,161,69)),
@ -151,7 +161,7 @@ fun MenuProductsCard(menuViewModel : MenuViewModel, product : Product, category:
)
OutlinedButton(
onClick = {
menuViewModel.addProductToCart(product.id!!)
menuViewModel.addProductToCart(product.id!!, userId, searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(30.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -18,7 +18,6 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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
@ -26,6 +25,7 @@ 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
@ -34,10 +34,11 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.viewmodels.OrderViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
import kotlinx.coroutines.launch
@Composable
@ -54,8 +55,10 @@ fun OrderScreen(){
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun OrdersCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val orderViewModel: OrderViewModel = hiltViewModel<OrderViewModel>()
val orderListUiState = orderViewModel.orderList.observeAsState().value?.collectAsLazyPagingItems()
val orderListUiState = orderViewModel.getOrdersList(searchToken).collectAsLazyPagingItems()
Column(
modifier = Modifier
@ -103,11 +106,16 @@ fun OrdersCard(){
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun OrderCard(order: OrderWithProducts, orderViewModel: OrderViewModel){
fun OrderCard(
order: OrderWithProducts,
orderViewModel: OrderViewModel
){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val scope = rememberCoroutineScope()
var status by remember { mutableStateOf("")}
scope.launch {
status = orderViewModel.getOrderStatus(order.order.statusId)
status = orderViewModel.getOrderStatus(order.order.statusId!!)
}
Card(
shape = RoundedCornerShape(20.dp),
@ -167,29 +175,29 @@ fun OrderCard(order: OrderWithProducts, orderViewModel: OrderViewModel){
}
OutlinedButton(
onClick = {
orderViewModel.changeOrderStatus(order.order.id!!)
orderViewModel.changeOrderStatus(searchToken, order.order.id!!)
when(status){
"Принят" -> {status = "Готов"}
"Готов" -> {status = "Выдан"}
"Выдан" -> {status = "..."}
}
},
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
)
}
Text(
text = when(status){
"Принят" -> {"Готов"}
"Готов" -> {"Выдать"}
"Выдан" -> {"..."}
else -> {""}
},
fontFamily = FontFamily(Font(R.font.nunito_extrabold_italic)),
fontSize = 30.sp,
color = Color.White
)
}
}
}

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -33,12 +33,12 @@ 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.data.sharedpref.PreferencesManager
import com.example.mobileapp.R
import com.example.mobileapp.models.OrderWithProducts
import com.example.mobileapp.navigation.Screens
import com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.ui.navigation.Screens
import com.example.mobileapp.viewmodels.ProfileViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
import kotlinx.coroutines.launch
@Composable
@ -56,8 +56,9 @@ fun ProfileScreen(navController: NavController){
@Composable
fun ProfileCard(navController: NavController){
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val profileViewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>()
val activeOrdersListUiState = profileViewModel.getActiveOrders(sharedPref.getData("userId", "-1").toInt())?.collectAsLazyPagingItems()
val activeOrdersListUiState = profileViewModel.getActiveOrders(searchToken, sharedPref.getData("userId", "-1").toInt())?.collectAsLazyPagingItems()
Column(
modifier = Modifier
@ -70,7 +71,6 @@ fun ProfileCard(navController: NavController){
.fillMaxHeight()
.fillMaxWidth(0.9f)
.background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally,
) {
OutlinedButton(
@ -78,8 +78,8 @@ fun ProfileCard(navController: NavController){
.fillMaxWidth()
.padding(top = 15.dp, start = 5.dp, end = 5.dp),
onClick = {
profileViewModel.logout(sharedPref)
navController.navigate(Screens.AuthorizationScreen.name)
profileViewModel.logout(sharedPref)
},
border = BorderStroke(4.dp, Color(255,86,86)),
shape = RoundedCornerShape(20.dp),
@ -128,7 +128,7 @@ fun ActiveOrderCard(order: OrderWithProducts, profileViewModel: ProfileViewModel
val scope = rememberCoroutineScope()
val status = remember { mutableStateOf("")}
scope.launch {
status.value = profileViewModel.getOrderStatus(order.order.statusId)
status.value = profileViewModel.getOrderStatus(order.order.statusId!!)
}
Card(
shape = RoundedCornerShape(20.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
@ -34,9 +34,9 @@ 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.ui.navigation.Screens
import com.example.mobileapp.viewmodels.RegistrationViewModel
import com.example.mobileapp.widgets.Header
import com.example.mobileapp.ui.widgets.Header
@Composable
fun RegistrationScreen(navController: NavController) {
@ -55,7 +55,6 @@ fun RegistrationCard(navController: NavController){
val login = remember { mutableStateOf(TextFieldValue("")) }
val password = remember { mutableStateOf(TextFieldValue("")) }
val passwordRepeat = remember { mutableStateOf(TextFieldValue("")) }
val viewModel = hiltViewModel<RegistrationViewModel>()
val success = viewModel.successState.observeAsState().value

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.screens
package com.example.mobileapp.ui.screens
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
@ -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
@ -23,50 +22,33 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
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.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.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.res.painterResource
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.input.TextFieldValue
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.data.sharedpref.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.data.db.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
import com.example.mobileapp.ui.widgets.Header
@Composable
fun UsersScreen() {
@ -84,7 +66,8 @@ fun UsersScreen() {
fun UsersCard(){
val sharedPref = PreferencesManager(LocalContext.current)
val usersViewModel: UsersViewModel = hiltViewModel<UsersViewModel>()
val userListUiState = usersViewModel.getUsersList().collectAsLazyPagingItems()
val searchToken = sharedPref.getData("token", "")
val userListUiState = usersViewModel.getUsersList(searchToken).collectAsLazyPagingItems()
Column(
modifier = Modifier
@ -111,7 +94,7 @@ fun UsersCard(){
.padding(top = 10.dp),
textAlign = TextAlign.Center,
)
if (userListUiState != null){
if (userListUiState != null && usersViewModel.allRoles.size != 0){
LazyColumn(
modifier = Modifier
.fillMaxSize()
@ -134,13 +117,10 @@ fun UsersCard(){
@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)
}
val sharedPref = PreferencesManager(LocalContext.current)
val searchToken = sharedPref.getData("token", "")
val roleList = remember { mutableStateListOf(usersViewModel.allRoles)}
var selectedRole by remember { mutableStateOf(usersViewModel.getUserRole(user.roleId))}
var expanded by remember { mutableStateOf(false) }
Card(
@ -209,9 +189,9 @@ fun UserCard (user: User, usersViewModel: UsersViewModel){
roleList.first().forEach {selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
text = { Text(selectionOption.name) },
onClick = {
selectedRole = selectionOption
selectedRole = selectionOption.name
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
@ -224,7 +204,7 @@ fun UserCard (user: User, usersViewModel: UsersViewModel){
}
OutlinedButton(
onClick = {
usersViewModel.changeUserRole(user.id!!, selectedRole)
usersViewModel.changeUserRole(user.id!!, selectedRole, searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),
@ -240,7 +220,7 @@ fun UserCard (user: User, usersViewModel: UsersViewModel){
}
OutlinedButton(
onClick = {
usersViewModel.deleteUser(user.id!!)
usersViewModel.deleteUser(user.id!!, searchToken)
},
border = BorderStroke(4.dp, Color(222,161,69)),
shape = RoundedCornerShape(10.dp),

View File

@ -1,4 +1,4 @@
package com.example.mobileapp.widgets
package com.example.mobileapp.ui.widgets
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.mobileapp.R
@Composable
fun Header(backColor: Color){
Column {

View File

@ -4,69 +4,46 @@ 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 com.example.mobileapp.data.sharedpref.PreferencesManager
import com.example.mobileapp.data.db.models.Role
import com.example.mobileapp.data.db.models.User
import com.example.mobileapp.data.repositories.RoleRepository
import com.example.mobileapp.data.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,
private val roleRepository: RoleRepository
) : ViewModel() {
private val _successState = MutableLiveData<Boolean?>()
val successState: LiveData<Boolean?>
get() = _successState
init {
addAdmin()
}
fun calmSuccessState() {
_successState.postValue(null)
}
fun login(sharedPref: PreferencesManager, login: String, password: String) {
viewModelScope.launch {
userRepository.getByLoginAndPassword(login, password).collect {
if (it == null) {
_successState.postValue(false)
} else {
sharedPref.saveData("userId", it.id.toString())
sharedPref.saveData("userRole", roleRepository.getById(it.roleId).first().name)
_successState.postValue(true)
val token_response = userRepository.getToken(User(null, login, password,-1))
if (token_response.access_token.isNotEmpty()) {
val user = userRepository.checkLogin(User(null, login, password, -1))
if (user != null){
val role = roleRepository.getRole(Role(user.role_id, ""))
if (role != null){
sharedPref.saveData("userId", user.id.toString())
sharedPref.saveData("userRole", role.name)
sharedPref.saveData("token", token_response.access_token)
_successState.postValue(true)
println(token_response.access_token)
}
}
}
}
}
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))
}
else {
_successState.postValue(false)
}
}
}

View File

@ -4,59 +4,42 @@ 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 com.example.mobileapp.data.db.models.OrderProduct
import com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.data.repositories.OrderProductRepository
import com.example.mobileapp.data.repositories.OrderRepository
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
private val orderProductRepository: OrderProductRepository
) : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User>
get() = _user
private val _cart = MutableLiveData<OrderWithProducts?>()
val cart: LiveData<OrderWithProducts?>
get() = _cart
fun retrieveUser(sharedPref: PreferencesManager) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
fun getCart(token: String) {
viewModelScope.launch {
userRepository.getById(userId).collect {
_user.postValue(it)
}
}
viewModelScope.launch {
orderRepository.getCartByUserId(userId).collect{
_cart.postValue(it)
}
_cart.postValue(orderRepository.getCartByUser(token))
}
}
fun makeOrder() {
viewModelScope.launch {
val model = cart.value!!.order
model.statusId = statusRepository.getByName("Принят").first().id!!
orderRepository.update(model)
fun makeOrder(token: String) {
if (cart.value == null){
return
}
val model = cart.value!!.order
model.statusId = 2
viewModelScope.launch {
orderRepository.update(token, model)
}
_cart.postValue(null)
}
fun removeProductFromOrder(productId: Int) {
fun removeProductFromOrder(token: String, productId: Int) {
val orderModel = cart.value!!.order
var productModel : OrderProduct? = null
@ -70,20 +53,22 @@ class CartViewModel @Inject constructor(
if(productModel!!.amount == 1) {
// delete
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.delete(productModel!!)
orderRepository.update(token, orderModel)
orderProductRepository.delete(token, productModel!!)
getCart(token)
}
}
else{
// update
productModel!!.amount -= 1
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.update(productModel!!)
orderRepository.update(token, orderModel)
orderProductRepository.update(token, productModel!!)
getCart(token)
}
}
}
fun addProductToOrder(productId: Int) {
fun addProductToOrder(token: String, productId: Int) {
val orderModel = cart.value!!.order
var productModel : OrderProduct? = null
cart.value!!.orderWithProducts.map {
@ -95,8 +80,10 @@ class CartViewModel @Inject constructor(
// update
productModel!!.amount += 1
viewModelScope.launch {
orderRepository.update(orderModel)
orderProductRepository.update(productModel!!)
orderRepository.update(token, orderModel)
orderProductRepository.update(token, productModel!!)
getCart(token)
}
}
}

View File

@ -1,85 +1,78 @@
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 com.example.mobileapp.data.api.models.ProductRemote
import com.example.mobileapp.data.api.models.toProduct
import com.example.mobileapp.data.db.models.Category
import com.example.mobileapp.data.db.models.Order
import com.example.mobileapp.data.db.models.OrderProduct
import com.example.mobileapp.data.db.models.Product
import com.example.mobileapp.data.repositories.CategoryRepository
import com.example.mobileapp.data.repositories.OrderProductRepository
import com.example.mobileapp.data.repositories.OrderRepository
import com.example.mobileapp.data.repositories.ProductRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import java.util.stream.Collectors
import javax.inject.Inject
@HiltViewModel
class MenuViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val categoryRepository: CategoryRepository,
private val orderRepository: OrderRepository,
private val orderProductRepository: OrderProductRepository,
private val userRepository: UserRepository
private val productRepository: ProductRepository
) : ViewModel() {
private val _user = MutableLiveData<User>()
val user: LiveData<User>
get() = _user
fun getCategoriesList(token: String) : Flow<PagingData<Category>> {
return categoryRepository.getAllPaged(token)
}
fun retrieveUser(sharedPref: PreferencesManager) {
val userId = sharedPref.getData("userId", "-1").toInt()
if (userId == -1) return
fun getProductsByCategoryId(categoryId: Int, token: String): Flow<MutableList<Product>?> {
return flow{ emit(productRepository.getProductsByCategoryId(categoryId, token).stream().map(
ProductRemote::toProduct).collect(Collectors.toList())) }
}
fun deleteProduct(product : Product, token: String) {
viewModelScope.launch {
userRepository.getById(userId).collect {
_user.postValue(it)
}
productRepository.delete(product, token)
}
}
val categoiesWithProductsListUiState: Flow<PagingData<CategoryWithProducts>> = productRepository.getCategoriesWithProducts()
fun deleteProduct(product : Product) {
fun addProductToCart(productId: Int, userId: Int, token: String) {
viewModelScope.launch {
productRepository.delete(product)
}
}
val product = productRepository.getProductById(productId, token)
val order = orderRepository.getCartByUser(token)
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))
val newOrder = orderRepository.insert(token, Order(null, userId, product.price, 1 ))
if (newOrder != null) {
orderProductRepository.insert(token, OrderProduct(newOrder.id!!, 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 (prod.product != null) {
if (prod.product.id == productId) {
val newOrderProduct = prod.orderProduct
newOrderProduct.amount += 1
val newOrder = order.order
newOrder.price += prod.product.price
orderProductRepository.update(token, newOrderProduct)
orderRepository.update(token, newOrder)
isAlreadyAdded = true
}
}
}
if (!isAlreadyAdded) {
orderProductRepository.insert(OrderProduct(order.order.id!!, productId, 1))
orderProductRepository.insert(token, OrderProduct(order.order.id!!, productId, 1))
val newOrder = order.order
newOrder.price += product.price
orderRepository.update(newOrder)
orderRepository.update(token, newOrder)
}
}
}

View File

@ -1,12 +1,12 @@
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 com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.data.db.models.Status
import com.example.mobileapp.data.repositories.OrderRepository
import com.example.mobileapp.data.repositories.StatusRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
@ -18,43 +18,31 @@ class OrderViewModel @Inject constructor(
private val statusRepository: StatusRepository,
private val orderRepository: OrderRepository
) : ViewModel() {
val orderList = MutableLiveData<Flow<PagingData<OrderWithProducts>>>()
init {
updateOrderList()
}
private fun updateOrderList(){
orderList.postValue(orderRepository.getOrdersToWork())
fun getOrdersList(token: String) : Flow<PagingData<OrderWithProducts>> {
return orderRepository.getOrdersToWorkPaged(token)
}
suspend fun getOrderStatus(statusId: Int) : String{
return statusRepository.getById(statusId).first().name
return statusRepository.getStatus(Status(statusId, ""))!!.name
}
fun changeOrderStatus(orderId: Int) {
fun changeOrderStatus(token: String, orderId: Int) {
viewModelScope.launch {
val order = orderRepository.getById(orderId).first()
when(statusRepository.getById(order.order.statusId).first().name){
when(statusRepository.getStatus(Status(order.order.statusId, ""))!!.name){
"Принят" -> {
val newOrder = order.order
newOrder.statusId = statusRepository.getByName("Готов").first().id!!
orderRepository.update(newOrder)
newOrder.statusId = statusRepository.getStatus(Status(null, "Готов"))!!.id!!
orderRepository.update(token, newOrder)
}
"Готов" -> {
val newOrder = order.order
newOrder.statusId = statusRepository.getByName("Выдан").first().id!!
orderRepository.update(newOrder)
newOrder.statusId = statusRepository.getStatus(Status(null, "Выдан"))!!.id!!
orderRepository.update(token, newOrder)
}
}
updateOrderList()
// для удобства
if (orderRepository.getById(orderId).first().order.statusId == 4){
orderRepository.delete(orderRepository.getById(orderId).first().order)
}
}
}
}

View File

@ -5,24 +5,25 @@ 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 com.example.mobileapp.data.api.models.CategoryRemote
import com.example.mobileapp.data.api.models.toCategory
import com.example.mobileapp.data.db.models.Category
import com.example.mobileapp.data.db.models.Product
import com.example.mobileapp.data.repositories.CategoryRepository
import com.example.mobileapp.data.repositories.ProductRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.util.stream.Collectors
import javax.inject.Inject
@HiltViewModel
class ProductViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val categoryRepository: CategoryRepository
private val categoryRepository: CategoryRepository,
) : ViewModel() {
private val _successState = MutableLiveData<Boolean?>()
private val _categories = mutableStateListOf<String>()
val categories: List<String>
private val _categories = mutableStateListOf<Category>()
val categories: List<Category>
get() = _categories
val successState: LiveData<Boolean?>
get() = _successState
@ -31,62 +32,76 @@ class ProductViewModel @Inject constructor(
val product: LiveData<Product?>
get() = _product
fun getProduct(productId: Int) {
fun getProduct(productId: Int, token: String) {
viewModelScope.launch {
_product.postValue(productRepository.getById(productId).first())
_product.postValue(productRepository.getProductById(productId, token))
}
}
init {
viewModelScope.launch {
categoryRepository.getAll().collect{data ->
_categories.addAll(data.map { category -> category.name })
if (categories.size == 0){
viewModelScope.launch {
_categories.addAll(categoryRepository.getCategories().stream().map(CategoryRemote::toCategory).collect(Collectors.toList()))
}
}
}
suspend fun getCategory(categoryId : Int) : String{
return categoryRepository.getById(categoryId).first().name
fun getProductCategory(categoryId : Int) : String{
return categories.find { it.id == categoryId }?.name ?: ""
}
fun calmSuccessState() {
_successState.postValue(null)
}
fun addProduct(name: String, category: String, price: String) {
fun addProduct(name: String, categoryName: String, price: String, token: String) {
if (name.isEmpty() || name.length > 10 || name.length < 3){
_successState.postValue(false)
return
}
if (category.isEmpty()){
if (categoryName.isEmpty()){
_successState.postValue(false)
return
}
if (price.isEmpty() || price.toIntOrNull() == null){
if (price.isEmpty() || price.toIntOrNull() == null || price.toInt() <= 0){
_successState.postValue(false)
return
}
viewModelScope.launch {
productRepository.insert(Product(null, name, categoryRepository.getByName(category).first().id!!, price.toInt()))
productRepository.insert(
Product(
null,
name,
categories.find { it.name == categoryName }!!.id!!,
price.toInt()
),
token
)
_successState.postValue(true)
}
}
fun updateProduct(id: Int, name: String, category: String, price: String) {
fun updateProduct(id: Int, name: String, categoryName: String, price: String, token: String) {
if (name.isEmpty() || name.length > 10 || name.length < 3){
_successState.postValue(false)
return
}
if (category.isEmpty()){
if (categoryName.isEmpty()){
_successState.postValue(false)
return
}
if (price.isEmpty() || price.toIntOrNull() == null){
if (price.isEmpty() || price.toIntOrNull() == null || price.toInt() <= 0){
_successState.postValue(false)
return
}
viewModelScope.launch {
productRepository.update(Product(id, name, categoryRepository.getByName(category).first().id!!, price.toInt()))
productRepository.update(
Product(
id,
name,
categories.find {it.name == categoryName}!!.id!!,
price.toInt()
),
token
)
_successState.postValue(true)
}
}

View File

@ -1,24 +1,14 @@
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 com.example.mobileapp.data.sharedpref.PreferencesManager
import com.example.mobileapp.data.db.models.OrderWithProducts
import com.example.mobileapp.data.db.models.Status
import com.example.mobileapp.data.repositories.OrderRepository
import com.example.mobileapp.data.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
@ -26,17 +16,20 @@ class ProfileViewModel @Inject constructor(
private val orderRepository: OrderRepository,
private val statusRepository: StatusRepository
) : ViewModel() {
fun getActiveOrders(userId : Int) : Flow<PagingData<OrderWithProducts>>? {
if (userId == -1) return null
return orderRepository.getOrdersByUserId(userId)
fun getActiveOrders(token: String, userId: Int) : Flow<PagingData<OrderWithProducts>>? {
if (token.isNotEmpty() && userId.toString().isNotEmpty()){
return orderRepository.getOrdersByUserPaged(token, userId)
}
return null
}
suspend fun getOrderStatus(statusId: Int) : String{
return statusRepository.getById(statusId).first().name
return statusRepository.getStatus(Status(statusId, ""))!!.name
}
fun logout(sharedPref: PreferencesManager) {
sharedPref.deleteData("userId")
sharedPref.deleteData("userRole")
sharedPref.deleteData("token")
}
}

View File

@ -4,8 +4,8 @@ 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 com.example.mobileapp.data.db.models.User
import com.example.mobileapp.data.repositories.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -39,12 +39,20 @@ class RegistrationViewModel @Inject constructor(
}
viewModelScope.launch {
userRepository.getByLoginAndPassword(login, password).collect {
if (it != null) {
val user_response = userRepository.checkLogin(User(null, login, password, -1))
if (user_response != null) {
if (user_response.login.isNullOrEmpty()) {
if (login == "admin" && password == "admin") {
userRepository.insert(User(null, login, password, 1))
_successState.postValue(true)
}
else {
userRepository.insert(User(null, login, password, 3))
_successState.postValue(true)
}
}
else {
_successState.postValue(false)
} else {
userRepository.insert(User(null, login, password, 3))
_successState.postValue(true)
}
}
}

View File

@ -1,83 +1,58 @@
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 com.example.mobileapp.data.api.models.RoleRemote
import com.example.mobileapp.data.api.models.toRole
import com.example.mobileapp.data.db.models.Role
import com.example.mobileapp.data.db.models.User
import com.example.mobileapp.data.repositories.RoleRepository
import com.example.mobileapp.data.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 java.util.stream.Collectors
import javax.inject.Inject
@HiltViewModel
class UsersViewModel @Inject constructor(
private val roleRepository: RoleRepository,
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val roleRepository: RoleRepository
) : ViewModel() {
private val _roles = mutableStateListOf<String>()
val roles: List<String>
get() = _roles
private val _allRoles = mutableStateListOf<Role>()
val allRoles: List<Role>
get() = _allRoles
init {
viewModelScope.launch {
roleRepository.getAll().collect{data ->
_roles.addAll(data.map { role -> role.name })
}
_allRoles.addAll(roleRepository.getRoles().stream().map(RoleRemote::toRole).collect(Collectors.toList()))
}
}
fun getUsersList() : Flow<PagingData<User>> {
return userRepository.getAllPaged()
fun getUsersList(token: String) : Flow<PagingData<User>> {
return userRepository.getAllPaged(token)
}
suspend fun getUserRole(user: User) : String {
return roleRepository.getById(user.roleId).first().name
fun getUserRole(roleId: Int) : String {
return allRoles.find { it.id == roleId }?.name ?: ""
}
fun changeUserRole(userId: Int, roleName: String) {
fun changeUserRole(userId: Int, roleName: String, token: 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)
}
}
userRepository.update(
User(
userId, "","",
allRoles.find { it.name == roleName }!!.id!!),
token
)
}
}
fun deleteUser(userId: Int){
fun deleteUser(userId: Int, token: String){
viewModelScope.launch{
userRepository.delete(userRepository.getById(userId).first())
userRepository.delete(User(userId, "","",-1),token)
}
}
}

View File

@ -1,6 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
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
id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10" apply false
}