ViewModel главного экрана + фикс удаления продукта

This commit is contained in:
Данила Мочалов 2023-11-22 05:11:16 +04:00
parent 65ff36e9bc
commit 377da2968c
10 changed files with 137 additions and 56 deletions

View File

@ -3,6 +3,8 @@ package com.example.shawarma
import android.app.Application import android.app.Application
import androidx.room.Room import androidx.room.Room
import com.example.shawarma.data.db.AppDatabase import com.example.shawarma.data.db.AppDatabase
import com.example.shawarma.data.repos.OrderProductRepository
import com.example.shawarma.data.repos.OrderRepository
import com.example.shawarma.data.repos.ProductRepository import com.example.shawarma.data.repos.ProductRepository
import com.example.shawarma.data.repos.UserRepository import com.example.shawarma.data.repos.UserRepository
import dagger.Module import dagger.Module
@ -33,6 +35,18 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideProductRepository(db: AppDatabase) : ProductRepository { fun provideProductRepository(db: AppDatabase) : ProductRepository {
return ProductRepository(db.productDao()) return ProductRepository(db.productDao(), db.orderProductDao())
}
@Provides
@Singleton
fun provideOrderRepository(db: AppDatabase) : OrderRepository {
return OrderRepository(db.orderDao())
}
@Provides
@Singleton
fun provideOrderProductRepository(db: AppDatabase) : OrderProductRepository {
return OrderProductRepository(db.orderProductDao())
} }
} }

View File

@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface OrderDao { interface OrderDao {
@Insert @Insert
suspend fun insert(order: OrderModel) suspend fun insert(order: OrderModel) : Long
@Update @Update
suspend fun update(order: OrderModel) suspend fun update(order: OrderModel)
@Delete @Delete
@ -22,4 +22,6 @@ interface OrderDao {
fun getById(id: Int): Flow<List<OrderWithProducts>> fun getById(id: Int): Flow<List<OrderWithProducts>>
@Query("select * from orders where orders.user_id =:userId") @Query("select * from orders where orders.user_id =:userId")
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> fun getByUserId(userId: Int): Flow<List<OrderWithProducts>>
@Query("select * from orders where orders.user_id =:userId and orders.order_status = 'Неоплачено'")
fun getUnpaidByUser(userId: Int) : Flow<OrderWithProducts>
} }

View File

@ -2,9 +2,16 @@ package com.example.shawarma.data.interfaces.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.shawarma.data.models.OrderProductModel import com.example.shawarma.data.models.OrderProductModel
@Dao @Dao
interface OrderProductDao { interface OrderProductDao {
@Insert @Insert
suspend fun insert(order: OrderProductModel) suspend fun insert(order: OrderProductModel)
@Update
suspend fun update(order: OrderProductModel)
@Query("delete from order_product WHERE product_id = :productId")
suspend fun deleteByProductId(productId: Int);
} }

View File

@ -15,7 +15,7 @@ interface ProductDao {
@Update @Update
suspend fun update(product: ProductModel) suspend fun update(product: ProductModel)
@Delete @Delete()
suspend fun delete(product: ProductModel) suspend fun delete(product: ProductModel)
@Query("select * from products where products.product_old_price is null") @Query("select * from products where products.product_old_price is null")

View File

@ -10,7 +10,7 @@ data class OrderProductModel(
@ColumnInfo(name = "product_id", index = true) @ColumnInfo(name = "product_id", index = true)
var productId: Int, var productId: Int,
@ColumnInfo(name = "quantity") @ColumnInfo(name = "quantity")
val quantity: Int, var quantity: Int,
@ColumnInfo(name = "total_price") @ColumnInfo(name = "total_price")
val totalPrice: Int var totalPrice: Int
) )

View File

@ -1,8 +1,5 @@
package com.example.shawarma.data.repos package com.example.shawarma.data.repos
import androidx.room.Dao
import androidx.room.Insert
import com.example.shawarma.data.interfaces.dao.OrderDao
import com.example.shawarma.data.interfaces.dao.OrderProductDao import com.example.shawarma.data.interfaces.dao.OrderProductDao
import com.example.shawarma.data.models.OrderProductModel import com.example.shawarma.data.models.OrderProductModel
import javax.inject.Inject import javax.inject.Inject
@ -13,4 +10,7 @@ class OrderProductRepository @Inject constructor(
suspend fun insert(order: OrderProductModel) { suspend fun insert(order: OrderProductModel) {
return orderProductDao.insert(order) return orderProductDao.insert(order)
} }
suspend fun update(order: OrderProductModel) {
return orderProductDao.update(order)
}
} }

View File

@ -1,12 +1,6 @@
package com.example.shawarma.data.repos package com.example.shawarma.data.repos
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.shawarma.data.interfaces.dao.OrderDao import com.example.shawarma.data.interfaces.dao.OrderDao
import com.example.shawarma.data.interfaces.dao.ProductDao
import com.example.shawarma.data.models.OrderModel import com.example.shawarma.data.models.OrderModel
import com.example.shawarma.data.models.OrderWithProducts import com.example.shawarma.data.models.OrderWithProducts
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -15,7 +9,7 @@ import javax.inject.Inject
class OrderRepository @Inject constructor( class OrderRepository @Inject constructor(
private val orderDao: OrderDao private val orderDao: OrderDao
){ ){
suspend fun insert(order: OrderModel) { suspend fun insert(order: OrderModel): Long {
return orderDao.insert(order) return orderDao.insert(order)
} }
suspend fun update(order:OrderModel) { suspend fun update(order:OrderModel) {
@ -33,4 +27,7 @@ class OrderRepository @Inject constructor(
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> { fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> {
return orderDao.getByUserId(userId) return orderDao.getByUserId(userId)
} }
fun getUnpaidByUser(userId: Int) : Flow<OrderWithProducts?> {
return orderDao.getUnpaidByUser(userId)
}
} }

View File

@ -1,17 +1,14 @@
package com.example.shawarma.data.repos package com.example.shawarma.data.repos
import androidx.room.Delete import com.example.shawarma.data.interfaces.dao.OrderProductDao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.shawarma.data.interfaces.dao.ProductDao import com.example.shawarma.data.interfaces.dao.ProductDao
import com.example.shawarma.data.interfaces.dao.UserDao
import com.example.shawarma.data.models.ProductModel import com.example.shawarma.data.models.ProductModel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import javax.inject.Inject import javax.inject.Inject
class ProductRepository @Inject constructor( class ProductRepository @Inject constructor(
private val productDao: ProductDao private val productDao: ProductDao,
private val orderProductDao: OrderProductDao
) { ) {
suspend fun insert(product: ProductModel) { suspend fun insert(product: ProductModel) {
return productDao.insert(product) return productDao.insert(product)
@ -20,6 +17,7 @@ class ProductRepository @Inject constructor(
return productDao.update(product) return productDao.update(product)
} }
suspend fun delete(product: ProductModel) { suspend fun delete(product: ProductModel) {
orderProductDao.deleteByProductId(product.id!!)
return productDao.delete(product) return productDao.delete(product)
} }
fun getAll(): Flow<List<ProductModel>> { fun getAll(): Flow<List<ProductModel>> {

View File

@ -20,9 +20,7 @@ import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Card import androidx.compose.material.Card
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -33,18 +31,18 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.shawarma.R import com.example.shawarma.R
import com.example.shawarma.data.db.AppDatabase
import com.example.shawarma.data.models.ProductModel import com.example.shawarma.data.models.ProductModel
import com.example.shawarma.data.sharedpref.PreferencesManager
import com.example.shawarma.ui.theme.MarckFamily import com.example.shawarma.ui.theme.MarckFamily
import com.example.shawarma.ui.theme.MyLightYellow import com.example.shawarma.ui.theme.MyLightYellow
import com.example.shawarma.ui.theme.MyMainBackground import com.example.shawarma.ui.theme.MyMainBackground
import com.example.shawarma.ui.theme.MyOrange import com.example.shawarma.ui.theme.MyOrange
import com.example.shawarma.ui.theme.MyPriceBackground import com.example.shawarma.ui.theme.MyPriceBackground
import com.example.shawarma.ui.theme.NunitoFamily import com.example.shawarma.ui.theme.NunitoFamily
import com.example.shawarma.viewmodels.HomeViewModel
import com.example.shawarma.widgets.ShawarmaLogo2 import com.example.shawarma.widgets.ShawarmaLogo2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun HomeScreen() { fun HomeScreen() {
@ -58,16 +56,10 @@ fun HomeScreen() {
@Composable @Composable
fun HomeList(){ fun HomeList(){
val context = LocalContext.current val homeViewModel: HomeViewModel = hiltViewModel<HomeViewModel>()
val products = remember { mutableStateListOf<ProductModel>() }
LaunchedEffect(Unit) { val products = homeViewModel.products.observeAsState().value
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).productDao().getAll().collect { data ->
products.clear()
products.addAll(data)
}
}
}
Box( Box(
modifier = Modifier modifier = Modifier
@ -76,7 +68,6 @@ fun HomeList(){
.fillMaxSize() .fillMaxSize()
.background(color = MyMainBackground) .background(color = MyMainBackground)
.zIndex(2f), .zIndex(2f),
contentAlignment = Alignment.TopCenter contentAlignment = Alignment.TopCenter
){ ){
Text( Text(
@ -90,19 +81,9 @@ fun HomeList(){
modifier = Modifier.padding(top = 80.dp) modifier = Modifier.padding(top = 80.dp)
) )
{ {
items(products.size) { index -> if (products != null) {
if (index % 2 == 0 && index == products.size - 1) { items(products.size) { index ->
Row( if (index % 2 == 0 && index == products.size - 1) {
horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp)
) {
ProductCard(products[index])
}
}
else {
if (index % 2 != 1) {
Row( Row(
horizontalArrangement = Arrangement.SpaceAround, horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier modifier = Modifier
@ -110,12 +91,23 @@ fun HomeList(){
.padding(top = 10.dp) .padding(top = 10.dp)
) { ) {
ProductCard(products[index]) ProductCard(products[index])
ProductCard(products[index + 1]) }
} else {
if (index % 2 != 1) {
Row(
horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp)
) {
ProductCard(products[index])
ProductCard(products[index + 1])
}
} }
} }
} if (index == products.size - 1) {
if (index == products.size - 1) { Spacer(modifier = Modifier.height(70.dp))
Spacer(modifier = Modifier.height(70.dp)) }
} }
} }
} }
@ -124,6 +116,9 @@ fun HomeList(){
@Composable @Composable
fun ProductCard(product: ProductModel){ fun ProductCard(product: ProductModel){
val homeViewModel: HomeViewModel = hiltViewModel<HomeViewModel>()
val preferencesManager = PreferencesManager(LocalContext.current)
Card( Card(
shape = RoundedCornerShape(20.dp), shape = RoundedCornerShape(20.dp),
backgroundColor = Color.White, backgroundColor = Color.White,
@ -155,6 +150,7 @@ fun ProductCard(product: ProductModel){
.size(160.dp, 36.dp) .size(160.dp, 36.dp)
) { ) {
Row( Row(
horizontalArrangement = Arrangement.SpaceBetween
){ ){
Text( Text(
text = product.price.toString() + " руб.", text = product.price.toString() + " руб.",
@ -164,7 +160,9 @@ fun ProductCard(product: ProductModel){
modifier = Modifier.padding(start = 12.dp, top = 6.dp) modifier = Modifier.padding(start = 12.dp, top = 6.dp)
) )
Button( Button(
onClick = { /*TODO*/ }, onClick = {
product.id?.let { homeViewModel.addProductToCart(it, preferencesManager.getData("user_id", "null")) }
},
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
backgroundColor = MyLightYellow, backgroundColor = MyLightYellow,
contentColor = Color.Black contentColor = Color.Black

View File

@ -0,0 +1,65 @@
package com.example.shawarma.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.shawarma.data.models.OrderModel
import com.example.shawarma.data.models.OrderProductModel
import com.example.shawarma.data.models.OrderStatus
import com.example.shawarma.data.models.ProductModel
import com.example.shawarma.data.repos.OrderProductRepository
import com.example.shawarma.data.repos.OrderRepository
import com.example.shawarma.data.repos.ProductRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.util.Date
import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor(
private val productRepository: ProductRepository,
private val orderRepository: OrderRepository,
private val orderProductRepository: OrderProductRepository
) : ViewModel() {
private val _products = MutableLiveData<List<ProductModel>>()
val products: LiveData<List<ProductModel>>
get() = _products
init {
viewModelScope.launch {
productRepository.getAll().collect {
_products.postValue(it)
}
}
}
fun addProductToCart(productId: Int, userId: String) {
if (userId == "null") return
viewModelScope.launch {
val product = productRepository.getById(productId).first()
val order = orderRepository.getUnpaidByUser(userId.toInt()).first()
if (order == null) {
val newOrderId = orderRepository.insert(OrderModel(null, OrderStatus.Неоплачено.name, userId.toInt(), Date()))
orderProductRepository.insert(OrderProductModel(newOrderId.toInt(), productId, 1, product.price))
}
else {
var isAlreadyAdded = false
for (prod in order.orderWithProducts) {
if (prod.product.id == productId) {
val model = prod.orderProductModel
model.quantity += 1
model.totalPrice += prod.product.price
orderProductRepository.update(model)
isAlreadyAdded = true
}
}
if (!isAlreadyAdded) {
orderProductRepository.insert(OrderProductModel(order.order.id!!, productId, 1, product.price))
}
}
}
}
}