Compare commits

...

8 Commits
main ... laba5

69 changed files with 2258 additions and 245 deletions

View File

@ -4,6 +4,7 @@ plugins {
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id("androidx.navigation.safeargs.kotlin") id("androidx.navigation.safeargs.kotlin")
id("kotlin-kapt") id("kotlin-kapt")
kotlin("plugin.serialization") version "1.4.21"
} }
android { android {
@ -51,6 +52,8 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5")
implementation("com.google.android.material:material:1.9.0") implementation("com.google.android.material:material:1.9.0")
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0") implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
implementation("androidx.navigation:navigation-ui-ktx:2.6.0") implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
@ -73,6 +76,16 @@ dependencies {
// optional - RxJava3 support // optional - RxJava3 support
implementation("androidx.paging:paging-rxjava3:$paging_version") implementation("androidx.paging:paging-rxjava3:$paging_version")
//retrofit
val retrofitVersion = "2.9.0"
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
implementation("com.squareup.retrofit2:adapter-rxjava3:$retrofitVersion")
implementation("com.squareup.retrofit2:converter-moshi:$retrofitVersion")
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")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
// Test // Test
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.ext:junit:1.1.5")

View File

@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:name=".PizzaApplication"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
@ -11,6 +16,8 @@
android:roundIcon="@drawable/icon" android:roundIcon="@drawable/icon"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Pizza" android:theme="@style/Theme.Pizza"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@ -1,6 +1,8 @@
package com.example.pizza package com.example.pizza
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -11,26 +13,44 @@ import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.ViewModelStoreOwner
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.paging.PagingData
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.UserViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.runBlocking
class Auth : Fragment() { class Auth : Fragment() {
private var userDao: UserDao? = null private var userViewModel : UserViewModel? = null
val viewModel: myViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel : UserViewModel by viewModels(
factoryProducer = {AppViewModelProvider.Factory}
)
userViewModel = viewModel
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// Inflate the layout for this fragment // Inflate the layout for this fragment
userDao = context?.let { AppDatabase.getInstance(it).userDao() }
val view = inflater.inflate(R.layout.fragment_auth, container, false) val view = inflater.inflate(R.layout.fragment_auth, container, false)
view.findViewById<Button>(R.id.button_auth).setOnClickListener {buttonClick(view)} view.findViewById<Button>(R.id.button_auth).setOnClickListener {buttonClick(view)}
view.findViewById<TextView>(R.id.link_to_reg).setOnClickListener{TextViewClick(view)} view.findViewById<TextView>(R.id.link_to_reg).setOnClickListener{TextViewClick(view)}
@ -42,31 +62,38 @@ class Auth : Fragment() {
private fun buttonClick(view: View) { private fun buttonClick(view: View) {
val login = view.findViewById<TextView>(R.id.auth_user_login)?.text.toString().trim() val login = view.findViewById<TextView>(R.id.auth_user_login)?.text.toString().trim()
val pass = view.findViewById<TextView>(R.id.auth_user_pass)?.text.toString().trim() val pass = view.findViewById<TextView>(R.id.auth_user_pass)?.text.toString().trim()
val viewModel: myViewModel by activityViewModels()
if(login.length == 0 || pass.length ==0){ if(login.length == 0 || pass.length ==0){
Toast.makeText(view.context, "Укажите логин или пароль", Toast.LENGTH_SHORT).show() Toast.makeText(view.context, "Укажите логин или пароль", Toast.LENGTH_SHORT).show()
return return
} }
userViewModel!!.getUserByLP(login,pass,
userDao?.getByLoginAndPassword(login, pass)?.subscribeOn(Schedulers.io()) onLoad =
?.observeOn(AndroidSchedulers.mainThread()) {data: User -> viewModel.setId(data.uid!!)
?.doOnError { Toast.makeText(view.context, "Неверный логин или пароль", Toast.LENGTH_SHORT).show() } if (data.role == "admin")
?.doOnSuccess { Toast.makeText(view.context, "Добро пожаловать", Toast.LENGTH_SHORT).show() }
?.onErrorComplete()
?.subscribe{user ->
viewModel.setId(user.uid!!)
if(user.role.equals("admin"))
viewModel.setRole(true) viewModel.setRole(true)
Toast.makeText(view.context, "Добро пожаловать", Toast.LENGTH_SHORT).show()
val action = AuthDirections val action = AuthDirections
.actionNavigationAuthToNavigationPizzaList() .actionNavigationAuthToNavigationPizzaList()
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
} },
onError = { Toast.makeText(view.context, "Неверно указаны дынные", Toast.LENGTH_SHORT).show() }
)
}
override fun onStart() {
super.onStart()
} }
private fun TextViewClick(view: View) { private fun TextViewClick(view: View) {
val action = AuthDirections val action = AuthDirections
.actionNavigationAuthToNavigationReg() .actionNavigationAuthToNavigationReg(-1)
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
} }
fun openURL() {
val openURL = Intent(Intent.ACTION_VIEW)
openURL.data = Uri.parse("https://ulstu.ru/")
startActivity(openURL)
}
} }

View File

@ -15,7 +15,9 @@ import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.paging.PagingData
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Pizza.Pizza
@ -23,6 +25,9 @@ import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.PizzaAdapter import com.example.pizza.Model.PizzaAdapter
import com.example.pizza.Model.User.User import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.BasketEditViewModel
import com.example.pizza.ViewModels.PizzaListViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
@ -30,12 +35,29 @@ import io.reactivex.rxjava3.schedulers.Schedulers
class ListPizza : Fragment() { class ListPizza : Fragment() {
private var pizzaDao: PizzaDao? = null private var pizzaDao: PizzaDao? = null
private var userDao: UserDao? = null private var userDao: UserDao? = null
private var currentUser: User? = null private var pizzaViewModel: PizzaListViewModel? = null
private var pizzaAdapter: PizzaAdapter? = null
private var basketViewModel : BasketEditViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val viewModel: PizzaListViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
pizzaViewModel = viewModel
val viewModel2: BasketEditViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
basketViewModel = viewModel2
}
override fun onStart() {
super.onStart()
val pizzas: LiveData<PagingData<Pizza>>? = pizzaViewModel?.getPizzas()
pizzas?.observe(viewLifecycleOwner) { data ->
data?.let {
pizzaAdapter?.submitData(lifecycle, it)
}
}
} }
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun onCreateView( override fun onCreateView(
@ -50,18 +72,25 @@ class ListPizza : Fragment() {
val view = inflater.inflate(R.layout.fragment_list_pizza, container, false) val view = inflater.inflate(R.layout.fragment_list_pizza, container, false)
val itemsList : RecyclerView = view.findViewById(R.id.pizzasList) val itemsList : RecyclerView = view.findViewById(R.id.pizzasList)
if(!viewModel.getRole()) if(!viewModel.getRole()) {
view.findViewById<Button>(R.id.button_add).visibility = View.GONE view.findViewById<Button>(R.id.button_add).visibility = View.GONE
var items = pizzaDao?.getAll() pizzaAdapter = PizzaAdapter(view.context, viewModel.getId()!!, basketViewModel!!,
if (items != null) { onSave = {Toast.makeText(view.context, "Пицца добавлена в корзину ", Toast.LENGTH_SHORT).show()},
items.subscribeOn(Schedulers.io()) onClick = {})
.observeOn(AndroidSchedulers.mainThread())
.subscribe { pizzas ->
itemsList.adapter = PizzaAdapter(pizzas,view.context, viewModel.getId()!!) }
} }
else{
pizzaAdapter = PizzaAdapter(view.context, viewModel.getId()!!, basketViewModel!!,
onSave = {Toast.makeText(view.context, "Пицца добавлена в корзину ", Toast.LENGTH_SHORT).show()},
onClick = {data : Int -> val action = ListPizzaDirections
.actionNavigationListToNavigationCreatePizza(data)
Navigation.findNavController(view).navigate(action)})
}
itemsList.adapter = pizzaAdapter
view.findViewById<Button>(R.id.button_add).setOnClickListener{ view.findViewById<Button>(R.id.button_add).setOnClickListener{
val action = ListPizzaDirections val action = ListPizzaDirections
.actionNavigationListToNavigationCreatePizza() .actionNavigationListToNavigationCreatePizza(-1)
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
} }
itemsList.layoutManager = LinearLayoutManager(view.context) itemsList.layoutManager = LinearLayoutManager(view.context)

View File

@ -14,14 +14,14 @@ import com.example.pizza.Model.User.User
entity = Pizza::class, entity = Pizza::class,
parentColumns = ["uid"], parentColumns = ["uid"],
childColumns = ["pizza_id"], childColumns = ["pizza_id"],
onDelete = ForeignKey.RESTRICT, onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.RESTRICT), onUpdate = ForeignKey.CASCADE),
ForeignKey( ForeignKey(
entity = User::class, entity = User::class,
parentColumns = ["uid"], parentColumns = ["uid"],
childColumns = ["user_id"], childColumns = ["user_id"],
onDelete = ForeignKey.RESTRICT, onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.RESTRICT), onUpdate = ForeignKey.CASCADE),
], ],
primaryKeys = ["user_id", "pizza_id"]) primaryKeys = ["user_id", "pizza_id"])
data class Basket( data class Basket(

View File

@ -1,10 +1,12 @@
package com.example.pizza.Model.Basket package com.example.pizza.Model.Basket
import androidx.paging.rxjava3.RxPagingSource
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.pizza.Model.Pizza.Pizza
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Flowable
@ -12,8 +14,12 @@ import io.reactivex.rxjava3.core.Flowable
interface BasketDao { interface BasketDao {
@Query("select * from basket inner join pizzas on basket.pizza_id = pizzas.uid where basket.user_id = :uid") @Query("select * from basket inner join pizzas on basket.pizza_id = pizzas.uid where basket.user_id = :uid")
fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>>
@Query("select * from basket inner join pizzas on basket.pizza_id = pizzas.uid where basket.user_id = :uid")
fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>>
@Insert @Insert
fun insert(group: Basket): Completable fun insert(group: Basket): Completable
@Insert
fun insertAll(group: List<Basket>): Completable
@Update @Update
fun update(group: Basket): Completable fun update(group: Basket): Completable
@ -22,6 +28,8 @@ interface BasketDao {
fun delete(group: Basket): Completable fun delete(group: Basket): Completable
@Query("delete from basket where basket.user_id = :uid") @Query("delete from basket where basket.user_id = :uid")
fun deleteByUser(uid : Int): Completable fun deleteByUser(uid : Int): Completable
@Query("delete from basket ")
fun deleteAll(): Completable
@Query("delete from basket where basket.user_id = :uid and basket.pizza_id = :pid") @Query("delete from basket where basket.user_id = :uid and basket.pizza_id = :pid")
fun deleteByUserAndPizza(uid : Int, pid:Int): Completable fun deleteByUserAndPizza(uid : Int, pid:Int): Completable
} }

View File

@ -0,0 +1,22 @@
package com.example.pizza.Model.Dto
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Pizza.Pizza
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class BasketDto(
@SerializedName("user")val user: Int,
@SerializedName("pizza")val pizza: Int,
@SerializedName("count")val countPizza: Int = 1
){
}
fun BasketDto.toBasket(): Basket = Basket(
user, pizza, countPizza)
fun Basket.toBasketDto(): BasketDto = BasketDto(
user, pizza, countPizza
)

View File

@ -0,0 +1,23 @@
package com.example.pizza.Model.Dto
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Pizza.Pizza
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
import java.util.Date
@Serializable
data class OrderDto(
@SerializedName("id") val uid : Int?,
@SerializedName("date")val date: Long ,
@SerializedName("pizza")val pizza: Int,
@SerializedName("user")val user: Int ,
@SerializedName("price")val price : Int
)
fun OrderDto.toOrder(): Order = Order(
uid, Date(date), pizza, user, price)
fun Order.toOrderDto(): OrderDto = OrderDto(
uid, date.time, pizza, user, price
)

View File

@ -0,0 +1,45 @@
package com.example.pizza.Model.Dto
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import androidx.annotation.RequiresApi
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.User.User
import kotlinx.serialization.Serializable
import java.io.ByteArrayOutputStream
import java.util.Base64
@Serializable
data class PizzaDto(
val id : Int?,
val title : String,
val price : Int,
val image : String,
val ingredients : String
){
constructor(
title : String,
price : Int,
image : String,
ingredients : String
) : this(null, title,price, image, ingredients)
}
@RequiresApi(Build.VERSION_CODES.O)
fun PizzaDto.toPizza(): Pizza = Pizza(
id,
title, BitmapFactory.decodeByteArray(Base64.getDecoder().decode(image), 0, Base64.getDecoder().decode(image).size),ingredients,price)
@RequiresApi(Build.VERSION_CODES.O)
fun Pizza.toPizzaDto(): PizzaDto {
val outputStream = ByteArrayOutputStream()
image?.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
val encoded = Base64.getEncoder().encodeToString(outputStream.toByteArray())
return PizzaDto(uid, title,price, encoded, ingredients, )
}

View File

@ -0,0 +1,31 @@
package com.example.pizza.Model.Dto
import com.example.pizza.Model.User.User
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable
@Serializable
data class UserDto(
@SerializedName("id")val id : Int?,
@SerializedName("login")val login : String?,
@SerializedName("email")val email : String?,
@SerializedName("password")val password : String?,
@SerializedName("role")val role : String?
){
constructor(
login: String,
email : String,
password: String,
role : String
) : this(null, login,email,password,role)
}
fun UserDto.toUser(): User = User(
id,
login?:"", email?:"", password?:"", role?:"")
fun User.toUserDto(): UserDto = UserDto(
uid,
login, email, password, role
)

View File

@ -5,32 +5,50 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Order.Order import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.PizzaOrder import com.example.pizza.Model.Order.PizzaOrder
import com.example.pizza.R import com.example.pizza.R
import java.text.SimpleDateFormat
import java.util.Objects
class HistoryAdapter(var orders: List<PizzaOrder>, var context: Context) : RecyclerView.Adapter<HistoryAdapter.MyViewHolder>() { class HistoryAdapter(var context: Context,
diffUtil: DiffUtil.ItemCallback<PizzaOrder> = HistoryAdapter.OrderComparator()
) : PagingDataAdapter<PizzaOrder, HistoryAdapter.MyViewHolder>(diffUtil) {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){ class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){
val date: TextView = view.findViewById(R.id.date_order) val date: TextView = view.findViewById(R.id.date_order)
val pizzas: TextView = view.findViewById(R.id.pizza_order) val pizzas: TextView = view.findViewById(R.id.pizza_order)
val price: TextView = view.findViewById(R.id.price_order) val price: TextView = view.findViewById(R.id.price_order)
} }
class OrderComparator : DiffUtil.ItemCallback<PizzaOrder>() {
override fun areItemsTheSame(oldItem: PizzaOrder, newItem: PizzaOrder): Boolean {
return Objects.equals(oldItem.date.toString()+ oldItem.pizzas, newItem.date.toString() + newItem.pizzas)
}
override fun areContentsTheSame(oldItem: PizzaOrder, newItem: PizzaOrder): Boolean {
return Objects.equals(oldItem.date.toString() + oldItem.pizzas, newItem.date.toString() + newItem.pizzas)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.history_list,parent,false) val view = LayoutInflater.from(parent.context).inflate(R.layout.history_list,parent,false)
return MyViewHolder(view) return MyViewHolder(view)
} }
override fun getItemCount(): Int {
return orders.count()
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) { override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.date.text = orders[position].date val pizza = getItem(position)
holder.pizzas.text = orders[position].pizzas pizza?.let{
holder.price.text = orders[position].price.toString() val sdf = SimpleDateFormat("dd.M.yyyy")
holder.date.text = sdf.format(it.date)
holder.pizzas.text = it.pizzas
holder.price.text = it.price.toString()
}
} }
} }

View File

@ -0,0 +1,18 @@
package com.example.pizza.Model.Order
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.room.TypeConverter
import java.io.ByteArrayOutputStream
import java.util.Date
class DateConverter {
@TypeConverter
fun getLongFromDate(time: Date): Long {
return time.time
}
@TypeConverter
fun getDateFromLong(data: Long): Date {
return Date(data)
}
}

View File

@ -5,6 +5,8 @@ import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.Ignore import androidx.room.Ignore
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import com.example.pizza.Model.Pizza.ImageConverter
import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.User.User import com.example.pizza.Model.User.User
import java.util.Date import java.util.Date
@ -15,24 +17,25 @@ import java.util.Date
entity = Pizza::class, entity = Pizza::class,
parentColumns = ["uid"], parentColumns = ["uid"],
childColumns = ["pizza_id"], childColumns = ["pizza_id"],
onDelete = ForeignKey.RESTRICT, onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.RESTRICT), onUpdate = ForeignKey.CASCADE),
ForeignKey( ForeignKey(
entity = User::class, entity = User::class,
parentColumns = ["uid"], parentColumns = ["uid"],
childColumns = ["user_id"], childColumns = ["user_id"],
onDelete = ForeignKey.RESTRICT, onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.RESTRICT), onUpdate = ForeignKey.CASCADE),
]) ])
@TypeConverters(DateConverter::class)
class Order( class Order(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
val uid : Int?, val uid : Int?,
@ColumnInfo(name = "date") @ColumnInfo(name = "date")
val date: String, val date: Date,
@ColumnInfo(name = "pizza_id", index = true) @ColumnInfo(name = "pizza_id", index = true)
val pizza: Int? , val pizza: Int ,
@ColumnInfo(name = "user_id", index = true) @ColumnInfo(name = "user_id", index = true)
val user: Int? , val user: Int ,
val price : Int ) { val price : Int ) {
@Ignore @Ignore
constructor( constructor(
@ -40,7 +43,7 @@ class Order(
Pizza : Pizza, Pizza : Pizza,
User : User, User : User,
Price : Int Price : Int
) : this(null , Date.toString(), Pizza.uid, User.uid, Price) ) : this(null , Date, Pizza.uid!!, User.uid!!, Price)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false

View File

@ -1,8 +1,10 @@
package com.example.pizza.Model.Order package com.example.pizza.Model.Order
import androidx.paging.rxjava3.RxPagingSource
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.pizza.Model.Basket.Basket import com.example.pizza.Model.Basket.Basket
@ -11,20 +13,21 @@ import io.reactivex.rxjava3.core.Flowable
@Dao @Dao
interface OrderDao { interface OrderDao {
@Query("select orders.date as date, group_concat(pizzas.pizza_title) as pizzas, Sum(orders.price) as price from orders" +
" join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid group by orders.date ")
fun getUserHistory(uid: Int): Flowable<List<PizzaOrder>>
@Query("select * from orders") // @Query("select orders.date as date, group_concat(pizzas.pizza_title) as pizzas, Sum(orders.price) as price from orders" +
fun getAll(): Flowable<List<Order>> // " join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid group by orders.date order by orders.date desc")
@Query("select orders.uid as uid, orders.date as date, pizzas.pizza_title as pizzas, orders.price as price from orders" +
" join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid ")
fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder>
@Insert @Insert
fun insert(group: Order): Completable fun insert(group: Order): Completable
@Insert
fun insertMany(group: List<Order>): Completable
@Update
fun update(group: Order): Completable
@Delete @Delete
fun delete(group: Order): Completable fun delete(group: Order): Completable
@Query("DELETE FROM orders")
fun deleteAll(): Completable
@Insert
fun insertAll(group: List<Order>): Completable
} }

View File

@ -1,4 +1,6 @@
package com.example.pizza.Model.Order package com.example.pizza.Model.Order
class PizzaOrder(val date: String, val pizzas : String, val price : Int) { import java.util.Date
class PizzaOrder(val uid: Int,val date: Date, val pizzas : String, val price : Int) {
} }

View File

@ -7,20 +7,21 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
import androidx.lifecycle.LiveData
import androidx.lifecycle.map
import androidx.paging.PagingData
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.BasketDao
import com.example.pizza.Model.Basket.PizzaBasket import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.R import com.example.pizza.R
import com.example.pizza.database.AppDatabase import com.example.pizza.ViewModels.BasketListViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import java.util.Objects
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.flow.combineTransform class OrderAdapter( var context: Context, val resSum: TextView, val basketVm : BasketListViewModel,
import java.util.function.ToIntFunction diffUtil: DiffUtil.ItemCallback<PizzaBasket> = OrderAdapter.PizzaComparator()
) : PagingDataAdapter<PizzaBasket, OrderAdapter.MyViewHolder>(diffUtil) {
class OrderAdapter(var orders: List<PizzaBasket>, var context: Context, val resSum: TextView ) : RecyclerView.Adapter<OrderAdapter.MyViewHolder>() {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val title: TextView = view.findViewById(R.id.order_title) val title: TextView = view.findViewById(R.id.order_title)
val btnP: TextView = view.findViewById(R.id.plus) val btnP: TextView = view.findViewById(R.id.plus)
@ -29,51 +30,75 @@ class OrderAdapter(var orders: List<PizzaBasket>, var context: Context, val resS
val sum: TextView = view.findViewById(R.id.order_sum) val sum: TextView = view.findViewById(R.id.order_sum)
val btnTrash : Button = view.findViewById(R.id.button_trash) val btnTrash : Button = view.findViewById(R.id.button_trash)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.table_order, parent, false) val view = LayoutInflater.from(parent.context).inflate(R.layout.table_order, parent, false)
return MyViewHolder(view) return MyViewHolder(view)
} }
class PizzaComparator : DiffUtil.ItemCallback<PizzaBasket>() {
override fun getItemCount(): Int { override fun areItemsTheSame(oldItem: PizzaBasket, newItem: PizzaBasket): Boolean {
return orders.count() return Objects.equals(oldItem.pizza_id, newItem.pizza_id)
} }
override fun areContentsTheSame(oldItem: PizzaBasket, newItem: PizzaBasket): Boolean {
return Objects.equals(oldItem.pizza_id, newItem.pizza_id)
}
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) { override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val pizza = getItem(position)
pizza?.let{
holder.btnM.setOnClickListener{btnMinus(holder,position)} holder.btnM.setOnClickListener{btnMinus(holder,position)}
holder.btnP.setOnClickListener{btnPlus(holder,position)} holder.btnP.setOnClickListener{btnPlus(holder,position)}
holder.title.text = orders[position].pizza_title holder.title.text = it.pizza_title
holder.count.text = orders[position].count_pizza.toString() holder.count.text = it.count_pizza.toString()
holder.sum.text = orders[position].pizza_price.toString() holder.sum.text = it.pizza_price.toString()
resSum.text = (resSum.text.toString().toInt() + orders[position].pizza_price).toString() resSum.text = (resSum.text.toString().toInt() + it.pizza_price).toString()
holder.btnTrash.setOnClickListener{deleteFromBasket(holder,position)} holder.btnTrash.setOnClickListener{deleteFromBasket(holder,pizza.user_id,pizza.pizza_id,pizza.pizza_price)}
}
} }
public fun getItemFromPosition(position: Int): PizzaBasket? {
return getItem(position)
}
@SuppressLint("SetTextI18n")
fun btnPlus(holder:MyViewHolder, position: Int){ fun btnPlus(holder:MyViewHolder, position: Int){
val pizza = getItem(position)
pizza?.let {
var count = holder.count.text.toString().toInt() var count = holder.count.text.toString().toInt()
count++ count++
holder.count.text = count.toString() holder.count.text = count.toString()
holder.sum.text = (count * orders[position].pizza_price).toString() holder.sum.text = (count * it.pizza_price).toString()
resSum.text = (resSum.text.toString().toInt() + orders[position].pizza_price).toString() resSum.text = (resSum.text.toString().toInt() + it.pizza_price).toString() }
} }
fun btnMinus(holder:MyViewHolder,position: Int){ fun btnMinus(holder:MyViewHolder,position: Int){
val pizza = getItem(position)
pizza?.let {
var count = holder.count.text.toString().toInt() var count = holder.count.text.toString().toInt()
if(count == 0) if(count == 0)
return return
count-- count--
holder.count.text = count.toString() holder.count.text = count.toString()
holder.sum.text = (count * orders[position].pizza_price).toString() holder.sum.text = (count * it.pizza_price).toString()
resSum.text = (resSum.text.toString().toInt() - orders[position].pizza_price).toString() resSum.text = (resSum.text.toString().toInt() - it.pizza_price).toString()
} }
@SuppressLint("CheckResult")
fun deleteFromBasket(holder: OrderAdapter.MyViewHolder, position: Int){ }
val basketDao : BasketDao? = context?.let { AppDatabase.getInstance(it).basketDao() } @SuppressLint("CheckResult", "NotifyDataSetChanged")
basketDao?.deleteByUserAndPizza(orders[position].user_id,orders[position].pizza_id)?.subscribeOn(Schedulers.io()) fun deleteFromBasket(holder: OrderAdapter.MyViewHolder, uid:Int,pid:Int,price:Int){
?.observeOn(AndroidSchedulers.mainThread()) val count = holder.count.text.toString().toInt()
?.doOnComplete({}) val sum = price*count
?.doOnError({}) basketVm.deletePizza(uid,pid)
?.onErrorComplete() {
?.subscribe({resSum.text = "0"} ) val oldSum = resSum.text.toString().toInt()
val newSum = oldSum - sum
resSum.text = newSum.toString()
}
} }
} }

View File

@ -12,7 +12,7 @@ class ImageConverter {
@TypeConverter @TypeConverter
fun getByteArrayFromBitmap(bitmap: Bitmap): ByteArray { fun getByteArrayFromBitmap(bitmap: Bitmap): ByteArray {
val outputStream = ByteArrayOutputStream() val outputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 70, outputStream) bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
return outputStream.toByteArray() return outputStream.toByteArray()
} }
@TypeConverter @TypeConverter

View File

@ -13,13 +13,13 @@ class Pizza(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
val uid: Int?, val uid: Int?,
@ColumnInfo(name = "pizza_title") @ColumnInfo(name = "pizza_title")
val title:String, var title:String,
val image : Bitmap?, var image : Bitmap?,
@ColumnInfo(name = "pizza_ingredients") @ColumnInfo(name = "pizza_ingredients")
val ingredients: String, var ingredients: String,
@ColumnInfo(name = "pizza_price") @ColumnInfo(name = "pizza_price")
val price: Int var price: Int
){ ){
@Ignore @Ignore
constructor( constructor(

View File

@ -1,5 +1,6 @@
package com.example.pizza.Model.Pizza package com.example.pizza.Model.Pizza
import androidx.paging.rxjava3.RxPagingSource
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
@ -14,13 +15,21 @@ import io.reactivex.rxjava3.core.Single
@Dao @Dao
interface PizzaDao { interface PizzaDao {
@Query("select * from pizzas") @Query("select * from pizzas")
fun getAll(): Flowable<List<Pizza>> fun getAll(): RxPagingSource<Int, Pizza>
@Query("select * from pizzas where pizzas.uid = :uid")
fun getById(uid : Int): Single<Pizza>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(group: Pizza): Completable fun insert(group: Pizza): Completable
@Insert
fun insertAll(group: List<Pizza>): Completable
@Update @Update
fun update(group: Pizza): Completable fun update(group: Pizza): Completable
@Delete @Delete
fun delete(group: Pizza): Completable fun delete(group: Pizza): Completable
@Query("DELETE FROM pizzas")
fun deleteAll(): Completable
} }

View File

@ -10,20 +10,28 @@ import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.navigation.Navigation
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.pizza.ListPizzaDirections
import com.example.pizza.Model.Basket.Basket import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.BasketDao import com.example.pizza.Model.Basket.BasketDao
import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Pizza.PizzaDao import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.User.User import com.example.pizza.Model.User.User
import com.example.pizza.R import com.example.pizza.R
import com.example.pizza.ViewModels.BasketEditViewModel
import com.example.pizza.ViewModels.BasketListViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.Objects
class PizzaAdapter(var pizzas: List<Pizza>, var context: Context, var user : Int) : RecyclerView.Adapter<PizzaAdapter.MyViewHolder>() { class PizzaAdapter(var context: Context,
val basketDao : BasketDao? = context?.let { AppDatabase.getInstance(it).basketDao() } var user : Int, val basketVm : BasketEditViewModel, var onClick: (id : Int) -> Unit,
diffUtil: DiffUtil.ItemCallback<Pizza> = PizzaComparator(), var onSave: () -> Unit) : PagingDataAdapter<Pizza, PizzaAdapter.MyViewHolder>(diffUtil) {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){ class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){
val image: ImageView = view.findViewById(R.id.pizza_list_image) val image: ImageView = view.findViewById(R.id.pizza_list_image)
val title: TextView = view.findViewById(R.id.pizza_list_title) val title: TextView = view.findViewById(R.id.pizza_list_title)
@ -32,30 +40,36 @@ class PizzaAdapter(var pizzas: List<Pizza>, var context: Context, var user : Int
val btn : Button = view.findViewById(R.id.item_list_botton) val btn : Button = view.findViewById(R.id.item_list_botton)
} }
class PizzaComparator : DiffUtil.ItemCallback<Pizza>() {
override fun areItemsTheSame(oldItem: Pizza, newItem: Pizza): Boolean {
return Objects.equals(oldItem.uid, newItem.uid)
}
override fun areContentsTheSame(oldItem: Pizza, newItem: Pizza): Boolean {
return Objects.equals(oldItem, newItem)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.pizza_in_list,parent,false) val view = LayoutInflater.from(parent.context).inflate(R.layout.pizza_in_list,parent,false)
return MyViewHolder(view) return MyViewHolder(view)
} }
override fun getItemCount(): Int {
return pizzas.count()
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) { override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.title.text = pizzas[position].title val pizza = getItem(position)
holder.ingredients.text = pizzas[position].ingredients.toString() pizza?.let { currentPizza ->
holder.price.text = pizzas[position].price.toString() holder.title.text = currentPizza.title
holder.image.setImageBitmap(pizzas[position].image) holder.ingredients.text = currentPizza.ingredients.toString()
holder.price.text = currentPizza.price.toString()
holder.image.setImageBitmap(currentPizza.image)
holder.btn.setOnClickListener { addToBasket(holder, position) } holder.btn.setOnClickListener { addToBasket(holder, position) }
holder.image.setOnClickListener{ onClick(pizza.uid!!) }
}
} }
fun addToBasket(holder: PizzaAdapter.MyViewHolder, position: Int){ fun addToBasket(holder: PizzaAdapter.MyViewHolder, position: Int){
val pizza : Basket = Basket(user,pizzas[position].uid!!,1) val currentPizza = getItem(position)
basketDao?.insert(pizza)?.subscribeOn(Schedulers.io()) val pizza = Basket(user,currentPizza?.uid!!,1)
?.observeOn(AndroidSchedulers.mainThread()) basketVm.savePizza(pizza){onSave}
?.doOnComplete({})
?.doOnError({})
?.onErrorComplete()
?.subscribe()
} }
} }

View File

@ -0,0 +1,19 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.PizzaBasket
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
interface BasketRepository {
fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>>
fun insert(group: Basket): Completable
fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>>
fun update(group: Basket): Completable
fun delete(group: Basket): Completable
fun deleteByUser(uid : Int): Completable
fun deleteByUserAndPizza(uid : Int, pid:Int): Completable
}

View File

@ -0,0 +1,26 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.BasketDao
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Pizza.PizzaDao
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
class OfflineBasketRepository(private val basketDao : BasketDao) : BasketRepository {
override fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> = basketDao.getUserBasket(uid)
override fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>> = basketDao.getUserAllBasket(uid)
override fun insert(group: Basket): Completable = basketDao.insert(group)
fun insertAll(group: List<Basket>): Completable = basketDao.insertAll(group)
override fun update(group: Basket): Completable = basketDao.update(group)
override fun delete(group: Basket): Completable = basketDao.delete(group)
override fun deleteByUser(uid: Int): Completable = basketDao.deleteByUser(uid)
fun deleteAll(): Completable = basketDao.deleteAll()
override fun deleteByUserAndPizza(uid: Int, pid: Int): Completable = basketDao.deleteByUserAndPizza(uid,pid)
}

View File

@ -0,0 +1,18 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Basket.BasketDao
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.OrderDao
import com.example.pizza.Model.Order.PizzaOrder
import io.reactivex.rxjava3.core.Completable
class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository {
override fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder> = orderDao.getUserHistory(uid)
override fun insert(group: Order): Completable = orderDao.insert(group)
override fun insertAll(group: List<Order>): Completable = orderDao.insertAll(group)
fun delete(group: Order): Completable = orderDao.delete(group)
fun deleteAll(): Completable = orderDao.deleteAll()
}

View File

@ -0,0 +1,21 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Pizza.PizzaDao
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
class OfflinePizzaRepository(private val pizzaDao : PizzaDao) : PizzaRepository {
override fun getAll(): RxPagingSource<Int, Pizza> = pizzaDao.getAll()
override fun getById(uid: Int): Single<Pizza> = pizzaDao.getById(uid)
override fun insert(group: Pizza): Completable = pizzaDao.insert(group)
override fun update(group: Pizza): Completable = pizzaDao.update(group)
override fun delete(group: Pizza): Completable = pizzaDao.delete(group)
override fun deleteAll(): Completable = pizzaDao.deleteAll()
override fun insertAll(pizzas: List<Pizza>): Completable = pizzaDao.insertAll(pizzas)
}

View File

@ -0,0 +1,24 @@
package com.example.pizza.Model.Repository
import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single
class OfflineUserRepository(private val userDao : UserDao) : UserRepository {
override fun getById(uid: Int): Single<User> = userDao.getById(uid)
fun getAll(): Flowable<List<User>> = throw Exception()
override fun getByLoginAndPassword(login: String, pass: String): Single<User> = userDao.getByLoginAndPassword(login,pass)
override fun insert(group: User): Completable = userDao.insert(group)
fun deleteAll(): Completable = userDao.deleteAll()
override fun update(group: User): Completable = userDao.update(group)
override fun delete(group: User): Completable = userDao.delete(group)
}

View File

@ -0,0 +1,15 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.PizzaOrder
import io.reactivex.rxjava3.core.Completable
interface OrderRepository {
fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder>
fun insert(group: Order): Completable
fun insertAll(group: List<Order>): Completable
}

View File

@ -0,0 +1,16 @@
package com.example.pizza.Model.Repository
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Pizza.Pizza
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
interface PizzaRepository {
fun getAll(): RxPagingSource<Int, Pizza>
fun getById(uid : Int): Single<Pizza>
fun insert(group: Pizza): Completable
fun update(group: Pizza): Completable
fun delete(group: Pizza): Completable
fun deleteAll() : Completable
fun insertAll(pizzas: List<Pizza>) : Completable
}

View File

@ -0,0 +1,163 @@
package com.example.pizza.Model.Repository.Rest.Mediators
import android.annotation.SuppressLint
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.paging.rxjava3.RxRemoteMediator
import com.example.pizza.Model.Dto.UserDto
import com.example.pizza.Model.Dto.toOrder
import com.example.pizza.Model.Dto.toPizza
import com.example.pizza.Model.Dto.toUser
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.PizzaOrder
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.OfflineOrderRepository
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.RemoteKeys.RemoteKeyType
import com.example.pizza.RemoteKeys.RemoteKeys
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import java.io.InvalidObjectException
import java.util.concurrent.atomic.AtomicInteger
@OptIn(ExperimentalPagingApi::class)
class OrderRemoteMediator(
private val service: MyServerService,
private val dbOrderRepository: OfflineOrderRepository,
private val dbPizzaRepository: OfflinePizzaRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase,
private val id : Int
): RxRemoteMediator<Int, PizzaOrder>() {
@RequiresApi(Build.VERSION_CODES.O)
override fun loadSingle(
loadType: LoadType,
state: PagingState<Int, PizzaOrder>
): Single<MediatorResult> {
Log.d(this::class.simpleName, state.toString())
return when (loadType){
LoadType.REFRESH -> getRemoteKeyClosestToCurrentPosition(state).subscribeOn(Schedulers.io()).toSingle().map{
Log.d("StudentRemoteMediator", "Refresh" + it.toString())
val page = AtomicInteger(it?.nextKey?.minus(1)?:1)
getMediatorResout(loadType,page,state).blockingGet()
}.onErrorReturn {
data -> Log.d(this::class.simpleName, data.message?:"not message this")
getMediatorResout(loadType, AtomicInteger(1),state).blockingGet() }
LoadType.PREPEND ->
getRemoteKeyForFirstItem(state).subscribeOn(Schedulers.io()).toSingle().map {
Log.d("StudentRemoteMediator", "PREPEND" + it.toString())
if(it?.prevKey != null) {
getMediatorResout(loadType, AtomicInteger(it.prevKey),state).blockingGet()
}
else {
MediatorResult.Success(endOfPaginationReached = it != null)
}
}.onErrorReturn{
data ->Log.d("StudentRemoteMediator", data.message?:"not message this")
MediatorResult.Success(false)}
LoadType.APPEND ->
getRemoteKeyForLastItem(state).subscribeOn(Schedulers.io()).toSingle().map{
Log.d("StudentRemoteMediator", "APPEND" + it.toString())
Log.d(this::class.simpleName, "trying to load more")
if(it?.nextKey != null) {
getMediatorResout(loadType,AtomicInteger(it.nextKey),state).blockingGet()
}
else {
MediatorResult.Success(endOfPaginationReached = it != null)
}
}
.onErrorReturn{
data ->
Log.d(this::class.simpleName, data.message?:"not message this")
MediatorResult.Success(false)}
}
}
@SuppressLint("CheckResult")
@RequiresApi(Build.VERSION_CODES.O)
fun getMediatorResout(loadType: LoadType, page : AtomicInteger, state: PagingState<Int, PizzaOrder>)
: Single<MediatorResult> {
Log.d(OrderRemoteMediator::class.simpleName,"Load")
return service.getAllPizzas()
.subscribeOn(Schedulers.io())
.map {
if(loadType == LoadType.REFRESH){
database.runInTransaction {
dbPizzaRepository.deleteAll().blockingAwait()
Log.d(OrderRemoteMediator::class.simpleName,"pizzas deleted")
dbPizzaRepository.insertAll(it.map { it.toPizza() }).blockingAwait()
Log.d(OrderRemoteMediator::class.simpleName,"pizzas loaded ${it.size}")
}
}
}
.flatMap { service.getUserOrders(id,state.config.pageSize,(page.get()-1)*state.config.pageSize) }
.map{
database.runInTransaction {
if(loadType == LoadType.REFRESH) {
dbOrderRepository.deleteAll().blockingAwait()
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.ORDER).blockingAwait()
Log.d(OrderRemoteMediator::class.simpleName,"orders deleted")
}
Log.d(OrderRemoteMediator::class.simpleName,"start load orders")
dbOrderRepository.insertAll(it.map { it.toOrder() }).blockingAwait()
val prevKey = if (page.get() == 1) null else page.get() - 1
val nextKey = if (it.isEmpty()) null else page.get() + 1
val keys = it.map {
RemoteKeys(
entityId = it.uid!!,
type = RemoteKeyType.ORDER,
prevKey = prevKey,
nextKey = nextKey
)
}
dbRemoteKeyRepository.createRemoteKeys(keys).blockingAwait()
}
MediatorResult.Success(it.isEmpty()) as MediatorResult
}.singleOrError()
.onErrorResumeNext {
e->
Single.just(MediatorResult.Error(e) as MediatorResult)
}
}
private fun getRemoteKeyForLastItem(state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { group ->
dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.ORDER)
} ?: Maybe.empty()
}
private fun getRemoteKeyForFirstItem(state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { group ->
dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.ORDER)
}?: Maybe.empty()
}
private fun getRemoteKeyClosestToCurrentPosition( state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.uid?.let { studentUid ->
dbRemoteKeyRepository.getAllRemoteKeys(studentUid, RemoteKeyType.ORDER)
}
}?: Maybe.empty()
}
}

View File

@ -0,0 +1,140 @@
package com.example.pizza.Model.Repository.Rest.Mediators
import android.annotation.SuppressLint
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.paging.rxjava3.RxRemoteMediator
import com.example.pizza.Model.Dto.PizzaDto
import com.example.pizza.Model.Dto.toPizza
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.Model.User.User
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.RemoteKeys.RemoteKeyType
import com.example.pizza.RemoteKeys.RemoteKeys
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import java.io.InvalidObjectException
import java.util.concurrent.atomic.AtomicInteger
@OptIn(ExperimentalPagingApi::class)
class PizzaRemoteMediator(
private val service: MyServerService,
private val dbPizzaRepository: OfflinePizzaRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase
) : RxRemoteMediator<Int, Pizza>(){
@RequiresApi(Build.VERSION_CODES.O)
override fun loadSingle(
loadType: LoadType,
state: PagingState<Int, Pizza>
): Single<MediatorResult> {
Log.d(this::class.simpleName, state.toString())
return when (loadType){
LoadType.REFRESH -> getRemoteKeyClosestToCurrentPosition(state).subscribeOn(Schedulers.io()).toSingle().map{
Log.d("StudentRemoteMediator", "Refresh" + it.toString())
val page = AtomicInteger(it?.nextKey?.minus(1)?:1)
getMediatorResout(loadType,page,state).blockingGet()
}.onErrorReturn {
data -> Log.d(this::class.simpleName, data.message?:"not message this")
getMediatorResout(loadType, AtomicInteger(1),state).blockingGet() }
LoadType.PREPEND ->
getRemoteKeyForFirstItem(state).subscribeOn(Schedulers.io()).toSingle().map {
Log.d("StudentRemoteMediator", "PREPEND" + it.toString())
if(it?.prevKey != null) {
getMediatorResout(loadType, AtomicInteger(it.prevKey),state).blockingGet()
}
else {
MediatorResult.Success(endOfPaginationReached = it != null)
}
}.onErrorReturn{
data ->Log.d("StudentRemoteMediator", data.message?:"not message this")
MediatorResult.Success(false)}
LoadType.APPEND ->
getRemoteKeyForLastItem(state).subscribeOn(Schedulers.io()).toSingle().map{
Log.d("StudentRemoteMediator", "APPEND" + it.toString())
Log.d(this::class.simpleName, "trying to load more")
if(it?.nextKey != null) {
getMediatorResout(loadType,AtomicInteger(it.nextKey),state).blockingGet()
}
else {
MediatorResult.Success(endOfPaginationReached = it != null)
}
}
.onErrorReturn{
data ->
Log.d(this::class.simpleName, data.message?:"not message this")
MediatorResult.Success(false)}
}
}
@SuppressLint("CheckResult")
@RequiresApi(Build.VERSION_CODES.O)
fun getMediatorResout(loadType: LoadType, page : AtomicInteger, state: PagingState<Int, Pizza>)
: Single<MediatorResult> {
Log.d(PizzaRemoteMediator::class.simpleName,"Load")
return service.getPizzas(state.config.pageSize,(page.get()-1)*state.config.pageSize)
.subscribeOn(Schedulers.io())
.map{
database.runInTransaction {
if(loadType == LoadType.REFRESH) {
dbPizzaRepository.deleteAll().blockingAwait()
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.PIZZA).blockingAwait()
}
dbPizzaRepository.insertAll(it.map { it.toPizza() }).blockingAwait()
val prevKey = if (page.get() == 1) null else page.get() - 1
val nextKey = if (it.isEmpty()) null else page.get() + 1
val keys = it.map {
RemoteKeys(
entityId = it.id!!,
type = RemoteKeyType.PIZZA,
prevKey = prevKey,
nextKey = nextKey
)
}
dbRemoteKeyRepository.createRemoteKeys(keys).blockingAwait()
}
MediatorResult.Success(it.isEmpty()) as MediatorResult
}.singleOrError()
.onErrorResumeNext {
e->
Single.just(MediatorResult.Error(e) as MediatorResult)
}
}
private fun getRemoteKeyForLastItem(state: PagingState<Int, Pizza>): Maybe<RemoteKeys> {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { group ->
dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.PIZZA)
} ?: Maybe.empty()
}
private fun getRemoteKeyForFirstItem(state: PagingState<Int, Pizza>): Maybe<RemoteKeys> {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { group ->
dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.PIZZA)
}?: Maybe.empty()
}
private fun getRemoteKeyClosestToCurrentPosition( state: PagingState<Int, Pizza>): Maybe<RemoteKeys> {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.uid?.let { studentUid ->
dbRemoteKeyRepository.getAllRemoteKeys(studentUid, RemoteKeyType.PIZZA)
}
}?: Maybe.empty()
}
}

View File

@ -0,0 +1,90 @@
package com.example.pizza.Model.Repository.Rest
import android.annotation.SuppressLint
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Dto.BasketDto
import com.example.pizza.Model.Dto.toBasket
import com.example.pizza.Model.Dto.toBasketDto
import com.example.pizza.Model.Dto.toPizza
import com.example.pizza.Model.Dto.toUser
import com.example.pizza.Model.Dto.toUserDto
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.BasketRepository
import com.example.pizza.Model.Repository.OfflineBasketRepository
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
import okhttp3.internal.wait
class RestBasketRepository(private val service: MyServerService,
private val dbBasketRepository: OfflineBasketRepository,
private val dbPizzaRepository: OfflinePizzaRepository,
private val dbUserRepository: OfflineUserRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase
) : BasketRepository {
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CheckResult")
override fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> {
Log.d("RestBasketRepository", "Insert All")
var fff = service.getAllPizzas()
.map{data ->
val ps = data.map { it.toPizza() }
database.runInTransaction{
dbPizzaRepository.deleteAll().blockingAwait()
dbPizzaRepository.insertAll(ps).blockingAwait()
Log.d("RestBasketRepository", ps.toString())
}
}
.flatMap { service.getUserBaskets(uid) }
.map{data ->
val bks = data.map { it.toBasket() }
database.runInTransaction{
dbBasketRepository.deleteAll().blockingAwait()
dbBasketRepository.insertAll(bks).blockingAwait()
Log.d("RestBasketRepository", bks.toString())
}
}
.flatMap { dbBasketRepository.getUserBasket(uid) }
return fff
}
@SuppressLint("CheckResult")
override fun insert(group: Basket): Completable = Completable.fromObservable(service.createBasket(group.toBasketDto()))
override fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>> {
return dbBasketRepository.getUserAllBasket(uid)
}
override fun update(group: Basket): Completable = throw Exception()
override fun delete(group: Basket): Completable {
throw Exception()
}
@SuppressLint("CheckResult")
override fun deleteByUser(uid: Int): Completable {
return Completable.fromObservable(service.deleteUserBaskets(uid)).andThen { dbBasketRepository.deleteByUser(uid).blockingAwait() }
}
@SuppressLint("CheckResult")
override fun deleteByUserAndPizza(uid: Int, pid: Int): Completable {
return Completable.fromObservable( service.deleteBasket(uid, pid)).andThen {dbBasketRepository.deleteByUserAndPizza(uid, pid).blockingAwait() }
}
}

View File

@ -0,0 +1,59 @@
package com.example.pizza.Model.Repository.Rest
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.paging.rxjava3.RxPagingSource
import androidx.room.Index
import com.example.pizza.Model.Dto.OrderDto
import com.example.pizza.Model.Dto.toOrderDto
import com.example.pizza.Model.Dto.toPizza
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.PizzaOrder
import com.example.pizza.Model.Repository.OfflineOrderRepository
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Repository.OrderRepository
import com.example.pizza.Model.Repository.Rest.Mediators.OrderRemoteMediator
import com.example.pizza.Model.Repository.Rest.Mediators.PizzaRemoteMediator
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.schedulers.Schedulers
class RestOrderRepository(private val service: MyServerService,
private val dbOrderRepository: OfflineOrderRepository,
private val dbPizzaRepository: OfflinePizzaRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase
) : OrderRepository {
var mediator: OrderRemoteMediator? = null
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CheckResult")
override fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder> {
if (mediator==null){
mediator = OrderRemoteMediator(
service,
dbOrderRepository,
dbPizzaRepository,
dbRemoteKeyRepository,
database,
uid
)
}
return dbOrderRepository.getUserHistory(uid)
}
override fun insert(group: Order): Completable = Completable.fromObservable(service.createOrder(group.toOrderDto()))
override fun insertAll(group: List<Order>): Completable
{
var list = group.map{it.toOrderDto()}
return Completable.fromObservable(service.createOrders(list))
}
}

View File

@ -0,0 +1,62 @@
package com.example.pizza.Model.Repository.Rest
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.paging.rxjava3.RxPagingSource
import com.example.pizza.Model.Dto.toPizza
import com.example.pizza.Model.Dto.toPizzaDto
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.PizzaRepository
import com.example.pizza.Model.Repository.Rest.Mediators.PizzaRemoteMediator
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import java.net.ConnectException
import java.net.SocketTimeoutException
class RestPizzaRepository(
private val service: MyServerService,
private val dbPizzaRepository: OfflinePizzaRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase
) : PizzaRepository{
var mediator: PizzaRemoteMediator? = null
override fun getAll(): RxPagingSource<Int, Pizza> {
if (mediator==null){
mediator = PizzaRemoteMediator(
service,
dbPizzaRepository,
dbRemoteKeyRepository,
database,
)
}
return dbPizzaRepository.getAll()
}
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CheckResult")
override fun getById(uid: Int): Single<Pizza> {
return service.getPizza(uid).subscribeOn(Schedulers.io()).map { it.toPizza() }
}
@RequiresApi(Build.VERSION_CODES.O)
override fun insert(group: Pizza): Completable = Completable.fromObservable(
service.createPizza(group.toPizzaDto()))
@RequiresApi(Build.VERSION_CODES.O)
override fun update(group: Pizza): Completable = Completable.fromObservable(
service.updatePizza(group.uid!!,group.toPizzaDto()))
override fun delete(group: Pizza): Completable = throw Exception()
override fun deleteAll(): Completable = throw Exception()
override fun insertAll(pizzas: List<Pizza>): Completable = throw Exception()
}

View File

@ -0,0 +1,51 @@
package com.example.pizza.Model.Repository.Rest
import android.annotation.SuppressLint
import android.util.Log
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.pizza.Model.Dto.toUser
import com.example.pizza.Model.Dto.toUserDto
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Repository.UserRepository
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.Model.User.User
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Single
class RestUserRepository (
private val service: MyServerService,
private val dbUserRepository: OfflineUserRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: AppDatabase
) : UserRepository {
@SuppressLint("CheckResult")
override fun getById(uid: Int): Single<User> = service.getUser(uid).map {
Log.d(RestUserRepository::class.simpleName ,"load user by id")
database.runInTransaction{
dbUserRepository.deleteAll().blockingAwait()
dbUserRepository.insert(it.toUser()).blockingAwait()
}
it.toUser() }
override fun getByLoginAndPassword(login: String, pass: String): Single<User> {
return service.getUserLP(login, pass).map {
Log.d(RestUserRepository::class.simpleName ,"load user by lp")
database.runInTransaction{
dbUserRepository.deleteAll().blockingAwait()
dbUserRepository.insert(it.toUser()).blockingAwait()
}
it.toUser() }
}
override fun insert(group: User): Completable = Completable.fromObservable(service.createUser(group.toUserDto()))
override fun update(group: User): Completable = Completable.fromObservable(service.updateUser(group.uid!!,group.toUserDto()))
override fun delete(group: User): Completable = Completable.fromObservable(service.updateUser(group.uid!!,group.toUserDto()))
}

View File

@ -0,0 +1,21 @@
package com.example.pizza.Model.Repository
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.pizza.Model.User.User
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single
interface UserRepository {
fun getById(uid : Int): Single<User>
fun getByLoginAndPassword(login : String, pass : String): Single<User>
fun insert(group: User): Completable
fun update(group: User): Completable
fun delete(group: User): Completable
}

View File

@ -0,0 +1,150 @@
package com.example.pizza.Model.Rest
import com.example.pizza.Model.Dto.BasketDto
import com.example.pizza.Model.Dto.OrderDto
import com.example.pizza.Model.Dto.PizzaDto
import com.example.pizza.Model.Dto.UserDto
import com.google.gson.GsonBuilder
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.Field
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
interface MyServerService {
@GET("pizzas")
fun getPizzas(
@Query("limit") limit: Int,
@Query("offset") offset: Int,
): Flowable<List<PizzaDto>>
@GET("allpizzas")
fun getAllPizzas(
): Flowable<List<PizzaDto>>
@GET("baskets/{id}")
fun getUserBaskets(
@Path("id") id: Int,
): Flowable<List<BasketDto>>
@GET("pizza/{id}")
fun getPizza(
@Path("id") id: Int,
): Single<PizzaDto>
@GET("baskets")
fun getAllBaskets(
): Observable<List<BasketDto>>
@GET("orders/{id}")
fun getUserOrders(
@Path("id") id: Int,
@Query("limit") limit: Int,
@Query("offset") offset: Int,
): Flowable<List<OrderDto>>
@GET("orders")
fun getAllOrders(
): Observable<List<OrderDto>>
@GET("users")
fun getAllUsers(
): Observable<UserDto>
@GET("user/{id}")
fun getUser(
@Path("id") id: Int,
): Single<UserDto>
@GET("user")
fun getUserLP(
@Query("login") login : String ,
@Query("password") password : String
): Single<UserDto>
@POST("user")
fun createUser(
@Body user: UserDto,
): Observable<UserDto>
@POST("pizza")
fun createPizza(
@Body pizza: PizzaDto,
): Observable<PizzaDto>
@POST("basket")
fun createBasket(
@Body basket: BasketDto,
): Observable<BasketDto>
@POST("order")
fun createOrder(
@Body order: OrderDto,
): Observable<OrderDto>
@POST("orders")
fun createOrders(
@Body order: List<OrderDto>,
): Observable<OrderDto>
@PUT("user/{id}")
fun updateUser(
@Path("id") id: Int,
@Body user: UserDto,
): Observable<UserDto>
@PUT("pizza/{id}")
fun updatePizza(
@Path("id") id: Int,
@Body user: PizzaDto,
): Observable<PizzaDto>
@DELETE("baskets/{id}")
fun deleteUserBaskets(
@Path("id") id: Int,
): Observable<List<BasketDto>>
@DELETE("basket")
fun deleteBasket(
@Query("uid") uid : Int ,
@Query("pid") pid : Int
): Observable<BasketDto>
companion object {
private const val BASE_URL = "http://192.168.42.168:8080/api/"
@Volatile
private var INSTANCE: MyServerService? = null
fun getInstance(): MyServerService {
return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
val gsonBuilder = GsonBuilder()
gsonBuilder.setLenient()
val gson = gsonBuilder.create()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
//.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
//.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
.create(MyServerService::class.java)
.also { INSTANCE = it }
}
}
}
}

View File

@ -12,11 +12,11 @@ data class User(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
public val uid: Int?, public val uid: Int?,
@ColumnInfo(name = "login") @ColumnInfo(name = "login")
val login:String , var login:String ,
@ColumnInfo(name = "email") @ColumnInfo(name = "email")
val email : String , var email : String ,
@ColumnInfo(name = "password") @ColumnInfo(name = "password")
val password: String , var password: String ,
@ColumnInfo(name = "role") @ColumnInfo(name = "role")
val role : String ) { val role : String ) {
@Ignore @Ignore

View File

@ -7,6 +7,7 @@ import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.Single
@Dao @Dao
@ -25,7 +26,8 @@ interface UserDao {
@Update @Update
fun update(group: User): Completable fun update(group: User): Completable
@Query("DELETE FROM users")
fun deleteAll(): Completable
@Delete @Delete
fun delete(group: User): Completable fun delete(group: User): Completable
} }

View File

@ -0,0 +1,21 @@
package com.example.pizza
import android.app.Application
import androidx.lifecycle.MutableLiveData
import com.example.pizza.database.AppContainer
import com.example.pizza.database.AppDataContainer
class PizzaApplication : Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
container = AppDataContainer(this)
}
}
operator fun <T> MutableLiveData<ArrayList<T>>.plusAssign(values: List<T>) {
val value = this.value ?: arrayListOf()
value.addAll(values)
this.value = value
}

View File

@ -12,10 +12,13 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.constraintlayout.widget.StateSet.TAG import androidx.constraintlayout.widget.StateSet.TAG
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.example.pizza.Model.PizzaAdapter import com.example.pizza.Model.PizzaAdapter
import com.example.pizza.Model.User.User import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.UserViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
@ -23,14 +26,39 @@ import io.reactivex.rxjava3.schedulers.Schedulers
class Reg : Fragment() { class Reg : Fragment() {
private var userDao: UserDao? = null private var userViewModel : UserViewModel? = null
private var editing = false
private var editUser : User? = null
val viewModel: myViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewUserModel : UserViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory}
)
userViewModel = viewUserModel
}
override fun onStart() {
super.onStart()
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
userDao = context?.let { AppDatabase.getInstance(it).userDao() }
val view = inflater.inflate(R.layout.fragment_reg, container, false) val view = inflater.inflate(R.layout.fragment_reg, container, false)
val args = RegArgs.fromBundle(requireArguments())
if(args.id != -1) {
editing = true
userViewModel?.getUserById(viewModel.getId()!!,{data: User ->
editUser = data
view.findViewById<TextView>(R.id.reg_user_login).text = editUser?.login
view.findViewById<TextView>(R.id.reg_user_email).text = editUser?.email
view.findViewById<TextView>(R.id.reg_user_pass).text = editUser?.password
},{})
}
view.findViewById<Button>(R.id.button_reg).setOnClickListener {buttonClick(view)} view.findViewById<Button>(R.id.button_reg).setOnClickListener {buttonClick(view)}
view.findViewById<TextView>(R.id.link_to_auth).setOnClickListener{TextViewClick(view)} view.findViewById<TextView>(R.id.link_to_auth).setOnClickListener{TextViewClick(view)}
@ -43,34 +71,59 @@ class Reg : Fragment() {
val login = view.findViewById<TextView>(R.id.reg_user_login)?.text.toString().trim() val login = view.findViewById<TextView>(R.id.reg_user_login)?.text.toString().trim()
val email = view.findViewById<TextView>(R.id.reg_user_email)?.text.toString().trim() val email = view.findViewById<TextView>(R.id.reg_user_email)?.text.toString().trim()
val pass = view.findViewById<TextView>(R.id.reg_user_pass)?.text.toString().trim() val pass = view.findViewById<TextView>(R.id.reg_user_pass)?.text.toString().trim()
val viewModel: myViewModel by activityViewModels()
if(login.length == 0 || pass.length ==0 || email.length == 0){ if(login.length == 0 || pass.length ==0 || email.length == 0){
Toast.makeText(view.context, "Укажите данные", Toast.LENGTH_SHORT).show() Toast.makeText(view.context, "Укажите данные", Toast.LENGTH_SHORT).show()
return return
} }
if(!editing) {
val user1 = User(login, email, pass, "user") val user1 = User(login, email, pass, "user")
userDao?.insert(user1)?.subscribeOn(Schedulers.io()) userViewModel?.saveUser(user1,
?.observeOn(AndroidSchedulers.mainThread()) onSave = {
userViewModel?.getUserByLP(login, pass,
?.subscribe( onLoad = { user: User ->
{Toast.makeText(view.context, "Регистрация прошла успешно", Toast.LENGTH_SHORT).show()
userDao?.getByLoginAndPassword(login, pass)?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.doOnSuccess({})
?.onErrorComplete()
?.subscribe { user ->
viewModel.setId(user.uid!!) viewModel.setId(user.uid!!)
if (user.role.equals("admin")) if (user.role == ("admin"))
viewModel.setRole(true) viewModel.setRole(true)
Toast.makeText(
view.context,
"Регистрация прошла успешно",
Toast.LENGTH_SHORT
).show()
val action = RegDirections val action = RegDirections
.actionNavigationRegToNavigationPizzaList() .actionNavigationRegToNavigationPizzaList()
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
}}, },
{Toast.makeText(view.context, "Данный логин уже занят", Toast.LENGTH_SHORT).show()} onError = {
) Toast.makeText(
view.context,
"Сбой Системы!!!",
Toast.LENGTH_SHORT
).show()
})
},
onError = {
Toast.makeText(view.context, "Данный логин уже занят -_-", Toast.LENGTH_SHORT)
.show()
})
}else
{
editUser?.login = login
editUser?.password = pass
editUser?.email = email
userViewModel?.updateUser(editUser!!,
onSave = {Toast.makeText(
view.context,
"Изменения успешно приняты",
Toast.LENGTH_SHORT
).show()
val action = RegDirections
.actionNavigationRegToNavigationUser()
Navigation.findNavController(view).navigate(action)},
onError = {Toast.makeText(view.context, "Данный логин уже занят -_-", Toast.LENGTH_SHORT)
.show()})
}
} }
private fun TextViewClick(view: View) { private fun TextViewClick(view: View) {

View File

@ -0,0 +1,15 @@
package com.example.pizza.RemoteKeys
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository {
override fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
remoteKeysDao.getRemoteKeys(id, type)
override fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
remoteKeysDao.insertAll(remoteKeys)
override fun deleteRemoteKey(type: RemoteKeyType) =
remoteKeysDao.clearRemoteKeys(type)
}

View File

@ -0,0 +1,10 @@
package com.example.pizza.RemoteKeys
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
interface RemoteKeyRepository {
fun getAllRemoteKeys(id: Int, type: RemoteKeyType): Maybe<RemoteKeys>
fun createRemoteKeys(remoteKeys: List<RemoteKeys>) : Completable
fun deleteRemoteKey(type: RemoteKeyType) : Completable
}

View File

@ -0,0 +1,32 @@
package com.example.pizza.RemoteKeys
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverter
import androidx.room.TypeConverters
import com.example.pizza.Model.User.User
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Order.Order
@Entity(tableName = "remote_keys")
data class RemoteKeys(
@PrimaryKey val entityId: Int,
@TypeConverters(RemoteKeyType::class)
val type: RemoteKeyType,
val prevKey: Int?,
val nextKey: Int?
)
enum class RemoteKeyType(private val type: String) {
USER(User::class.simpleName ?: "User"),
PIZZA(Pizza::class.simpleName ?: "Pizza"),
ORDER(Order::class.simpleName ?: "Order"),
BASKET(Basket::class.simpleName ?: "Basket");
@TypeConverter
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
@TypeConverter
fun fromRemoteKeyType(value: RemoteKeyType) = value.type
}

View File

@ -0,0 +1,20 @@
package com.example.pizza.RemoteKeys
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
@Dao
interface RemoteKeysDao {
@Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type")
fun getRemoteKeys(entityId: Int, type: RemoteKeyType): Maybe<RemoteKeys>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(remoteKey: List<RemoteKeys>) : Completable
@Query("DELETE FROM remote_keys WHERE type = :type")
fun clearRemoteKeys(type: RemoteKeyType) : Completable
}

View File

@ -0,0 +1,37 @@
package com.example.pizza.ViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.pizza.PizzaApplication
object AppViewModelProvider {
val Factory = viewModelFactory {
initializer {
PizzaListViewModel(studentApplication().container.pizzaRepository)
}
initializer {
PizzaEditViewModel(studentApplication().container.pizzaRepository)
}
initializer {
BasketEditViewModel(studentApplication().container.basketRepository)
}
initializer {
BasketListViewModel(studentApplication().container.basketRepository)
}
initializer {
OrderEditViewModel(studentApplication().container.orderRepository)
}
initializer {
OrderListViewModel(studentApplication().container.orderRepository)
}
initializer {
UserViewModel(studentApplication().container.userRepository)
}
}
}
fun CreationExtras.studentApplication(): PizzaApplication =
(this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as PizzaApplication)

View File

@ -0,0 +1,38 @@
package com.example.pizza.ViewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.BasketRepository
import com.example.pizza.Model.Repository.PizzaRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
class BasketEditViewModel(
private val basketRepository: BasketRepository
) : ViewModel() {
private val mDisposable = CompositeDisposable()
fun savePizza(pizza: Basket, onSave: () -> Unit) {
val completable: Completable = basketRepository.insert(pizza)
val disposable = completable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete({})
.onErrorComplete()
.subscribe(onSave)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,80 @@
package com.example.pizza.ViewModels
import android.annotation.SuppressLint
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.rxjava3.RxPagingSource
import androidx.paging.rxjava3.cachedIn
import androidx.paging.rxjava3.flowable
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.BasketRepository
import com.example.pizza.Model.Repository.PizzaRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.ExperimentalCoroutinesApi
class BasketListViewModel(private val basketRepository: BasketRepository): ViewModel() {
private val mDisposable = CompositeDisposable()
private val pizzas: MutableLiveData<PagingData<PizzaBasket>?> = MutableLiveData()
fun getPizzas(uid: Int ): LiveData<PagingData<PizzaBasket>?> {
if (pizzas.value == null) {
loadPizzas(uid)
}
return pizzas
}
@SuppressLint("CheckResult")
fun getAllBaskets(uid : Int, onLoad: (data : List<PizzaBasket>) -> Unit, onError: () -> Unit){
basketRepository.getUserBasket(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( { data ->
onLoad(data)
},{onError()})
}
@OptIn(ExperimentalCoroutinesApi::class)
private fun loadPizzas(uid: Int) {
val disposable = basketRepository.getUserBasket(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError({pizzas.value = null})
.subscribe { data ->
val ps = PagingData.from<PizzaBasket>(data)
pizzas.postValue(ps)
}
mDisposable.add(disposable)
}
fun deletePizza(uid:Int, pid: Int, onDelete: () -> Unit) {
val disposable = basketRepository.deleteByUserAndPizza(uid,pid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { onDelete() }
mDisposable.add(disposable)
}
fun deleteAllPizza(uid:Int) {
val disposable = basketRepository.deleteByUser(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe()
mDisposable.add(disposable)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,35 @@
package com.example.pizza.ViewModels
import androidx.lifecycle.ViewModel
import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Repository.BasketRepository
import com.example.pizza.Model.Repository.OrderRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
class OrderEditViewModel(
private val orderRepository: OrderRepository
) : ViewModel() {
private val mDisposable = CompositeDisposable()
fun savePizza(pizzas: List<Order>, onSave: () -> Unit) {
val completable: Completable = orderRepository.insertAll(pizzas)
val disposable = completable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete({})
.onErrorComplete()
.subscribe(onSave)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,64 @@
package com.example.pizza.ViewModels
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.rxjava3.cachedIn
import androidx.paging.rxjava3.flowable
import com.example.pizza.Model.Order.PizzaOrder
import com.example.pizza.Model.Repository.OrderRepository
import com.example.pizza.Model.Repository.Rest.RestOrderRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.ExperimentalCoroutinesApi
class OrderListViewModel(private val orderRepository: OrderRepository): ViewModel() {
private val mDisposable = CompositeDisposable()
private val pizzas: MutableLiveData<PagingData<PizzaOrder>?> = MutableLiveData()
@RequiresApi(Build.VERSION_CODES.O)
fun getPizzas(uid: Int): LiveData<PagingData<PizzaOrder>?> {
loadPizzas(uid)
return pizzas
}
@OptIn(ExperimentalCoroutinesApi::class, ExperimentalPagingApi::class)
@RequiresApi(Build.VERSION_CODES.O)
private fun loadPizzas(uid: Int) {
val pageSize = 10
val placeholders = true
var config = PagingConfig(
pageSize = pageSize,
enablePlaceholders =placeholders
)
val disposable = Pager(
config = config,
pagingSourceFactory = {orderRepository.getUserHistory(uid)},
remoteMediator = (orderRepository as RestOrderRepository).mediator
).flowable
.cachedIn(viewModelScope)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError({pizzas.value = null})
.subscribe { data ->
pizzas.postValue(data)
}
mDisposable.add(disposable)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,63 @@
package com.example.pizza.ViewModels
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.PizzaRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
class PizzaEditViewModel(
private val pizzaRepository: PizzaRepository
) : ViewModel() {
private val mDisposable = CompositeDisposable()
private val pizza: MutableLiveData<Pizza> = MutableLiveData()
fun getPizza(uid: Int, onSave: (data : Pizza) -> Unit): LiveData<Pizza> {
if (pizza.value == null) {
loadPizza(uid,onSave)
}
return pizza
}
private fun loadPizza(uid: Int,onSave: (data : Pizza) -> Unit) {
val disposable = pizzaRepository.getById(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { data ->
pizza.postValue(data)
onSave(data)
}
mDisposable.add(disposable)
}
fun savePizza(pizza: Pizza, onSave: () -> Unit,onError: () -> Unit) {
val completable: Completable = pizzaRepository.insert(pizza)
val disposable = completable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ onSave() },{onError()})
mDisposable.add(disposable)
}
fun updatePizza(pizza: Pizza, onSave: () -> Unit, onError: () -> Unit) {
val completable: Completable = pizzaRepository.update(pizza)
val disposable = completable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ onSave() },{onError()})
mDisposable.add(disposable)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,69 @@
package com.example.pizza.ViewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.rxjava3.cachedIn
import androidx.paging.rxjava3.flowable
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.PizzaRepository
import com.example.pizza.Model.Repository.Rest.RestPizzaRepository
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.ExperimentalCoroutinesApi
class PizzaListViewModel(private val pizzaRepository: PizzaRepository): ViewModel() {
private val mDisposable = CompositeDisposable()
private val pizzas: MutableLiveData<PagingData<Pizza>> = MutableLiveData()
fun getPizzas(): LiveData<PagingData<Pizza>> {
loadPizzas()
return pizzas
}
@OptIn(ExperimentalCoroutinesApi::class, ExperimentalPagingApi::class)
private fun loadPizzas() {
var meditator = (pizzaRepository as RestPizzaRepository).mediator
var pagingSourceFactory = {pizzaRepository.getAll()}
val pageSize = 3
val placeholders = true
var config = PagingConfig(
pageSize = pageSize,
enablePlaceholders =placeholders
)
val disposable = Pager(
config = config,
pagingSourceFactory = pagingSourceFactory,
remoteMediator = meditator,
).flowable
.cachedIn(viewModelScope)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { data ->
pizzas.postValue(data)
}
mDisposable.add(disposable)
}
fun deletePizza(pizza: Pizza, onDelete: () -> Unit) {
val disposable = pizzaRepository.delete(pizza)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onDelete)
mDisposable.add(disposable)
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -0,0 +1,96 @@
package com.example.pizza.ViewModels
import android.annotation.SuppressLint
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Repository.PizzaRepository
import com.example.pizza.Model.Repository.UserRepository
import com.example.pizza.Model.User.User
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
class UserViewModel(
private val userRepository: UserRepository
) : ViewModel() {
private val mDisposable = CompositeDisposable()
private val user: MutableLiveData<User?> = MutableLiveData()
fun getUserById(uid: Int, onLoad: (data : User)-> Unit, onError: () -> Unit): LiveData<User?> {
if (user.value == null) {
loadUserById(uid,onLoad, onError)
}
return user
}
fun getUserByLP(login : String, pass : String,onLoad: (data : User) -> Unit,onError: () -> Unit): LiveData<User?> {
if (user.value == null) {
loadUserByLP(login, pass,onLoad, onError)
}
return user
}
private fun loadUserById(uid: Int,onLoad: (data : User) -> Unit, onError: () -> Unit) {
val disposable = userRepository.getById(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({ data ->
user.postValue(data)
onLoad(data)
},{onError()})
mDisposable.add(disposable)
}
@SuppressLint("SuspiciousIndentation", "CheckResult")
private fun loadUserByLP(login : String, pass : String,onLoad: (data : User) -> Unit,onError: () -> Unit) {
val disposable = userRepository.getByLoginAndPassword(login, pass)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({ data ->
user.postValue(data)
onLoad(data)
},{onError()})
mDisposable.add(disposable)
}
@SuppressLint("CheckResult")
fun saveUser(user: User, onSave: () -> Unit, onError: () -> Unit) {
userRepository.insert(user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({onSave() },{ onError()})
}
@SuppressLint("CheckResult")
fun updateUser(user: User, onSave: () -> Unit, onError: () -> Unit) {
userRepository.update(user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({onSave() },{ onError()})
}
@SuppressLint("CheckResult")
fun deleteUser(user: User, onSave: () -> Unit, onError: () -> Unit) {
userRepository.delete(user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({onSave() },{ onError()})
}
override fun onCleared() {
super.onCleared()
mDisposable.clear()
}
}

View File

@ -11,7 +11,9 @@ import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.paging.PagingData
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.recyclerview.widget.RecyclerView.ViewHolder
@ -23,6 +25,11 @@ import com.example.pizza.Model.Order.OrderDao
import com.example.pizza.Model.OrderAdapter import com.example.pizza.Model.OrderAdapter
import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.PizzaAdapter import com.example.pizza.Model.PizzaAdapter
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.BasketEditViewModel
import com.example.pizza.ViewModels.BasketListViewModel
import com.example.pizza.ViewModels.OrderEditViewModel
import com.example.pizza.ViewModels.PizzaListViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
@ -31,30 +38,48 @@ import java.util.Date
class crate : Fragment() { class crate : Fragment() {
private var basketDao: BasketDao? = null
lateinit var itemsList : RecyclerView lateinit var itemsList : RecyclerView
lateinit var listPizzas : List<PizzaBasket> private var orderAdapter : OrderAdapter? = null
val viewModel: myViewModel by activityViewModels() val viewModel: myViewModel by activityViewModels()
private var orderDao : OrderDao? = null private var orderDao : OrderDao? = null
private var basketVM : BasketListViewModel? = null
private var orderViewModel : OrderEditViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: BasketListViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
basketVM = viewModel
val viewModel2: OrderEditViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
orderViewModel = viewModel2
}
override fun onStart() {
super.onStart()
val pizzas: LiveData<PagingData<PizzaBasket>?>? = basketVM?.getPizzas(viewModel.getId()!!)
pizzas?.observe(viewLifecycleOwner) { data ->
data?.let {
orderAdapter?.submitData(lifecycle, it)
}
}
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
basketDao = context?.let { AppDatabase.getInstance(it).basketDao() }
orderDao = context?.let { AppDatabase.getInstance(it).orderDao() } orderDao = context?.let { AppDatabase.getInstance(it).orderDao() }
val view = inflater.inflate(R.layout.fragment_crate, container, false) val view = inflater.inflate(R.layout.fragment_crate, container, false)
itemsList = view.findViewById(R.id.inOrderList) itemsList = view.findViewById(R.id.inOrderList)
var resSum = view.findViewById<TextView>(R.id.sum_pizzas) var resSum = view.findViewById<TextView>(R.id.sum_pizzas)
val button : Button = view.findViewById<Button>(R.id.button_buy) val button : Button = view.findViewById<Button>(R.id.button_buy)
basketDao?.getUserBasket(viewModel.getId()!!)?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe { pizzas ->
listPizzas = pizzas
itemsList.layoutManager = LinearLayoutManager(view.context) itemsList.layoutManager = LinearLayoutManager(view.context)
itemsList.adapter = OrderAdapter(pizzas,view.context, resSum) orderAdapter = OrderAdapter(view.context, resSum, basketVM!!)
} itemsList.adapter = orderAdapter
button.setOnClickListener{buttonClick(view)} button.setOnClickListener{buttonClick(view)}
@ -64,35 +89,30 @@ class crate : Fragment() {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private fun buttonClick(view : View){ private fun buttonClick(view : View){
var list = arrayListOf<Order>() var list = arrayListOf<Order>()
val sdf = SimpleDateFormat("dd.M.yyyy") val currentDate =Date()
val currentDate = sdf.format(Date())
val x = itemsList.childCount val x = itemsList.childCount
if(x == 0){ if(x == 0){
return return
} }
basketVM?.getAllBaskets(viewModel.getId()!!,
onLoad = {listPizzas: List<PizzaBasket> ->
for(i in 0..<x){ for(i in 0..<x){
var child = itemsList.getChildAt(i) val child = itemsList.getChildAt(i)
var price = child.findViewById<TextView>(R.id.order_sum).text.toString().toInt() val price = child.findViewById<TextView>(R.id.order_sum).text.toString().toInt()
list.add(Order(null, currentDate, listPizzas[i].pizza_id, list.add(Order(null, currentDate, listPizzas.get(i).pizza_id,
viewModel.getId(), price)) viewModel.getId()!!, price))
} }
basketDao?.deleteByUser(viewModel.getId()!!)?.subscribeOn(Schedulers.io()) basketVM!!.deleteAllPizza(viewModel.getId()!!)
?.observeOn(AndroidSchedulers.mainThread()) orderViewModel!!.savePizza(list){
?.doOnError({ Toast.makeText(view.context, "Error", Toast.LENGTH_SHORT).show()})
?.doOnComplete({})
?.onErrorComplete()
?.subscribe {}
orderDao?.insertMany(list)?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.doOnComplete({})
?.doOnError({ Toast.makeText(view.context, "Error", Toast.LENGTH_SHORT).show()})
?.onErrorComplete()
?.subscribe {
Toast.makeText(view.context, "Заказ прошел успешно ", Toast.LENGTH_SHORT).show() Toast.makeText(view.context, "Заказ прошел успешно ", Toast.LENGTH_SHORT).show()
val action = crateDirections val action = crateDirections
.actionNavigationCretePizzaToListNavigation() .actionNavigationCretePizzaToListNavigation()
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
} }
},
onError = {})
} }
} }

View File

@ -13,15 +13,21 @@ import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Pizza.Pizza
import com.example.pizza.Model.Pizza.PizzaDao import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.PizzaEditViewModel
import com.example.pizza.ViewModels.PizzaListViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
@ -29,12 +35,20 @@ import io.reactivex.rxjava3.schedulers.Schedulers
private lateinit var selectedImage: AppCompatImageView private lateinit var selectedImage: AppCompatImageView
class create_pizza : Fragment() { class create_pizza : Fragment() {
private var pizzaDao: PizzaDao? = null private var pizzaViewModel: PizzaEditViewModel? = null
private var editing = false
private var editPizza : Pizza? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: PizzaEditViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
pizzaViewModel = viewModel
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
pizzaDao = context?.let { AppDatabase.getInstance(it).pizzaDao() }
val view = inflater.inflate(R.layout.fragment_create_pizza, container, false) val view = inflater.inflate(R.layout.fragment_create_pizza, container, false)
val button = view.findViewById<Button>(R.id.button_save) val button = view.findViewById<Button>(R.id.button_save)
button.setOnClickListener {buttonClick(view)} button.setOnClickListener {buttonClick(view)}
@ -43,7 +57,17 @@ class create_pizza : Fragment() {
val pickImg = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI) val pickImg = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI)
changeImage.launch(pickImg) changeImage.launch(pickImg)
} }
//TODO добавление в бд val args = RegArgs.fromBundle(requireArguments())
if(args.id != -1) {
editing = true
pizzaViewModel?.getPizza(args.id) { data: Pizza ->
editPizza = data
view.findViewById<TextView>(R.id.pizza_title).text = editPizza?.title
view.findViewById<TextView>(R.id.pizza_price).text = editPizza?.price.toString()
view.findViewById<TextView>(R.id.pizza_ingredients).text = editPizza?.ingredients
view.findViewById<ImageView>(R.id.pizza_image).setImageBitmap(editPizza?.image)
}
}
return view return view
} }
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
@ -58,16 +82,31 @@ class create_pizza : Fragment() {
Toast.makeText(view.context, "Укажите данные", Toast.LENGTH_SHORT).show() Toast.makeText(view.context, "Укажите данные", Toast.LENGTH_SHORT).show()
return return
} }
pizzaDao?.insert(pizza1)?.subscribeOn(Schedulers.io()) if(!editing) {
?.observeOn(AndroidSchedulers.mainThread()) pizzaViewModel!!.savePizza(pizza1,
?.doOnComplete({}) onSave = {
?.doOnError({ Toast.makeText(view.context, "Error", Toast.LENGTH_SHORT).show()})
?.onErrorComplete()
?.subscribe {
Toast.makeText(view.context, "Пицца успешно добавлена", Toast.LENGTH_SHORT).show() Toast.makeText(view.context, "Пицца успешно добавлена", Toast.LENGTH_SHORT).show()
val action = create_pizzaDirections val action = create_pizzaDirections
.actionNavigationCreatePizzaToListNavigation() .actionNavigationCreatePizzaToListNavigation()
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
},
onError = {Toast.makeText(view.context, "Ошибка!!!", Toast.LENGTH_SHORT).show()}
)
}
else
{
editPizza?.title = title
editPizza?.ingredients = ingredients
editPizza?.price = price
editPizza?.image = bitmap
pizzaViewModel?.updatePizza(editPizza!!,
onSave = {
Toast.makeText(view.context, "Пицца успешно обновлена", Toast.LENGTH_SHORT).show()
val action = create_pizzaDirections
.actionNavigationCreatePizzaToListNavigation()
Navigation.findNavController(view).navigate(action)
},
onError = {Toast.makeText(view.context, "Такая пицца уже есть", Toast.LENGTH_SHORT).show()})
} }

View File

@ -0,0 +1,69 @@
package com.example.pizza.database
import android.content.Context
import com.example.pizza.Model.Repository.BasketRepository
import com.example.pizza.Model.Repository.OfflineBasketRepository
import com.example.pizza.Model.Repository.OfflineOrderRepository
import com.example.pizza.Model.Repository.OfflinePizzaRepository
import com.example.pizza.Model.Repository.OfflineUserRepository
import com.example.pizza.Model.Repository.OrderRepository
import com.example.pizza.Model.Repository.PizzaRepository
import com.example.pizza.Model.Repository.Rest.RestBasketRepository
import com.example.pizza.Model.Repository.Rest.RestOrderRepository
import com.example.pizza.Model.Repository.Rest.RestPizzaRepository
import com.example.pizza.Model.Repository.Rest.RestUserRepository
import com.example.pizza.Model.Repository.UserRepository
import com.example.pizza.Model.Rest.MyServerService
import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository
import com.example.pizza.RemoteKeys.RemoteKeyRepository
interface AppContainer {
val pizzaRepository: PizzaRepository
val userRepository: UserRepository
val basketRepository: BasketRepository
val orderRepository : OrderRepository
val remoteKeyRepository: RemoteKeyRepository
}
class AppDataContainer(private val context: Context) : AppContainer {
override val pizzaRepository: PizzaRepository by lazy {
RestPizzaRepository(
MyServerService.getInstance(),
OfflinePizzaRepository(AppDatabase.getInstance(context).pizzaDao()),
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao()),
AppDatabase.getInstance(context))
}
override val userRepository: UserRepository by lazy {
RestUserRepository(
MyServerService.getInstance(),
OfflineUserRepository(AppDatabase.getInstance(context).userDao()),
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao()),
AppDatabase.getInstance(context)
)
}
override val basketRepository: BasketRepository by lazy {
RestBasketRepository(
MyServerService.getInstance(),
OfflineBasketRepository(AppDatabase.getInstance(context).basketDao()),
OfflinePizzaRepository(AppDatabase.getInstance(context).pizzaDao()),
OfflineUserRepository(AppDatabase.getInstance(context).userDao()),
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao()),
AppDatabase.getInstance(context))
}
override val orderRepository: OrderRepository by lazy {
RestOrderRepository(
MyServerService.getInstance(),
OfflineOrderRepository(AppDatabase.getInstance(context).orderDao()),
OfflinePizzaRepository(AppDatabase.getInstance(context).pizzaDao()),
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao()),
AppDatabase.getInstance(context))
}
override val remoteKeyRepository: RemoteKeyRepository by lazy {
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao())
}
}

View File

@ -17,6 +17,7 @@ import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.pizza.Model.Basket.Basket import com.example.pizza.Model.Basket.Basket
import com.example.pizza.Model.Basket.BasketDao import com.example.pizza.Model.Basket.BasketDao
import com.example.pizza.Model.Order.DateConverter
import com.example.pizza.Model.Order.Order import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.Order.OrderDao import com.example.pizza.Model.Order.OrderDao
import com.example.pizza.Model.Pizza.ImageConverter import com.example.pizza.Model.Pizza.ImageConverter
@ -25,22 +26,30 @@ import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.Pizza.Singleton import com.example.pizza.Model.Pizza.Singleton
import com.example.pizza.Model.User.User import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.RemoteKeys.RemoteKeys
import com.example.pizza.RemoteKeys.RemoteKeysDao
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.concurrent.Executors import java.util.concurrent.Executors
@Database(entities = [User::class, Pizza::class,Basket::class,Order::class], version = 1, exportSchema = false) @Database(entities = [
@TypeConverters(ImageConverter::class) User::class,
Pizza::class,
Basket::class,
Order::class,
RemoteKeys::class,
], version = 1, exportSchema = false)
@TypeConverters(ImageConverter::class, DateConverter::class)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun pizzaDao(): PizzaDao abstract fun pizzaDao(): PizzaDao
abstract fun basketDao(): BasketDao abstract fun basketDao(): BasketDao
abstract fun orderDao(): OrderDao abstract fun orderDao(): OrderDao
abstract fun remoteKeysDao(): RemoteKeysDao
companion object { companion object {
private const val DB_NAME: String = "dp7" private const val DB_NAME: String = "dp14"
@Volatile @Volatile
private var INSTANCE: AppDatabase? = null private var INSTANCE: AppDatabase? = null
@ -80,11 +89,11 @@ abstract class AppDatabase : RoomDatabase() {
val orderDao = database.orderDao() val orderDao = database.orderDao()
val sdf = SimpleDateFormat("dd.M.yyyy") val sdf = SimpleDateFormat("dd.M.yyyy")
val currentDate = sdf.format(Date()) val currentDate = Date()
val order1 = Order(1,currentDate.toString(),pizza1.uid,user1.uid,300) val order1 = Order(1,currentDate,pizza1.uid,user1.uid,300)
val order2 = Order(2,currentDate.toString(),pizza2.uid,user1.uid,300) val order2 = Order(2,currentDate,pizza2.uid,user1.uid,300)
val order3 = Order(3,currentDate.toString(),pizza1.uid,user2.uid,300) val order3 = Order(3,currentDate,pizza1.uid,user2.uid,300)
orderDao.insert(order1).subscribe().dispose() orderDao.insert(order1).subscribe().dispose()
orderDao.insert(order2).subscribe().dispose() orderDao.insert(order2).subscribe().dispose()
orderDao.insert(order3).subscribe().dispose() orderDao.insert(order3).subscribe().dispose()
@ -100,7 +109,7 @@ abstract class AppDatabase : RoomDatabase() {
.addCallback(object : Callback() { .addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) { override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db) super.onCreate(db)
Executors.newSingleThreadExecutor().execute { populateDatabase() } //Executors.newSingleThreadExecutor().execute { populateDatabase() }
} }
}) })
.build() .build()

View File

@ -1,6 +1,7 @@
package com.example.pizza package com.example.pizza
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
@ -8,10 +9,16 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.paging.PagingData
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.pizza.Model.Basket.PizzaBasket
import com.example.pizza.Model.Order.Order import com.example.pizza.Model.Order.Order
import com.example.pizza.Model.HistoryAdapter import com.example.pizza.Model.HistoryAdapter
import com.example.pizza.Model.Order.OrderDao import com.example.pizza.Model.Order.OrderDao
@ -19,15 +26,45 @@ import com.example.pizza.Model.Order.PizzaOrder
import com.example.pizza.Model.OrderAdapter import com.example.pizza.Model.OrderAdapter
import com.example.pizza.Model.Pizza.PizzaDao import com.example.pizza.Model.Pizza.PizzaDao
import com.example.pizza.Model.PizzaAdapter import com.example.pizza.Model.PizzaAdapter
import com.example.pizza.Model.User.User
import com.example.pizza.Model.User.UserDao import com.example.pizza.Model.User.UserDao
import com.example.pizza.ViewModels.AppViewModelProvider
import com.example.pizza.ViewModels.BasketListViewModel
import com.example.pizza.ViewModels.OrderEditViewModel
import com.example.pizza.ViewModels.OrderListViewModel
import com.example.pizza.ViewModels.UserViewModel
import com.example.pizza.database.AppDatabase import com.example.pizza.database.AppDatabase
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
class user : Fragment() { class user : Fragment() {
private var orderDao: OrderDao? = null private var orderViewModel : OrderListViewModel? = null
private var userDao: UserDao? = null private var userViewModel : UserViewModel? = null
private val viewModel: myViewModel by activityViewModels() private val viewModel: myViewModel by activityViewModels()
private var historyAdapter : HistoryAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel: UserViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
userViewModel = viewModel
val viewModel2: OrderListViewModel by viewModels(
factoryProducer = { AppViewModelProvider.Factory }
)
orderViewModel = viewModel2
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onStart() {
super.onStart()
val pizzas: LiveData<PagingData<PizzaOrder>?>? = orderViewModel?.getPizzas(viewModel.getId()!!)
pizzas?.observe(viewLifecycleOwner) { data ->
data?.let {
historyAdapter?.submitData(lifecycle, it)
}
}
}
@SuppressLint("CheckResult", "SetTextI18n") @SuppressLint("CheckResult", "SetTextI18n")
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
@ -35,32 +72,19 @@ class user : Fragment() {
): View? { ): View? {
userDao = context?.let { AppDatabase.getInstance(it).userDao() }
orderDao = context?.let { AppDatabase.getInstance(it).orderDao() }
val view = inflater.inflate(R.layout.fragment_user, container, false) val view = inflater.inflate(R.layout.fragment_user, container, false)
val itemsList : RecyclerView = view.findViewById(R.id.historyList) val itemsList : RecyclerView = view.findViewById(R.id.historyList)
userViewModel?.getUserById(viewModel.getId()!!,
userDao?.getById(viewModel.getId()!!) onLoad = {data: User ->
?.subscribeOn(Schedulers.io()) view.findViewById<TextView>(R.id.user_login).text = "Логин: "+ data?.login
?.observeOn(AndroidSchedulers.mainThread()) view.findViewById<TextView>(R.id.user_email).text = "Почта: " + data?.email },
?.doOnError { } onError = { Toast.makeText(view.context, "Сбой Системы!!!", Toast.LENGTH_SHORT).show()}
?.doOnSuccess { } )
?.onErrorComplete() historyAdapter = HistoryAdapter(view.context)
?.subscribe { user -> itemsList.adapter = historyAdapter
view.findViewById<TextView>(R.id.user_login).text = "Логин: "+ user.login
view.findViewById<TextView>(R.id.user_email).text = "Почта: " + user.email
}
orderDao?.getUserHistory(viewModel.getId()!!)?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe { pizzas ->
itemsList.adapter = HistoryAdapter(pizzas,view.context)
}
itemsList.layoutManager = LinearLayoutManager(view.context) itemsList.layoutManager = LinearLayoutManager(view.context)
view.findViewById<Button>(R.id.button_exit).setOnClickListener {buttonClick(view)} view.findViewById<Button>(R.id.button_exit).setOnClickListener {buttonClick(view)}
view.findViewById<Button>(R.id.button_edit).setOnClickListener {buttonEdit(view)}
return view return view
@ -73,5 +97,13 @@ class user : Fragment() {
.actionNavigationUserToNavigationAuth() .actionNavigationUserToNavigationAuth()
Navigation.findNavController(view).navigate(action) Navigation.findNavController(view).navigate(action)
} }
@SuppressLint("ResourceType")
private fun buttonEdit(view: View) {
val action = userDirections
.actionNavigationUserToNavigationReg(viewModel.getId()!!)
Navigation.findNavController(view).navigate(action)
}
} }

View File

@ -36,6 +36,9 @@
android:layout_gravity="left" android:layout_gravity="left"
android:text="Почта: " android:text="Почта: "
/> />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button <Button
android:id="@+id/button_exit" android:id="@+id/button_exit"
android:layout_width="150dp" android:layout_width="150dp"
@ -43,9 +46,22 @@
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:fontFamily="@font/inter_bold" android:fontFamily="@font/inter_bold"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="right" android:layout_gravity="center"
android:backgroundTint="#BD350A" android:backgroundTint="#BD350A"
android:text="Выход" /> android:text="Выход" />
<Button
android:id="@+id/button_edit"
android:layout_width="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginRight="15dp"
android:fontFamily="@font/inter_bold"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:backgroundTint="#BD350A"
android:text="Редактировать" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/historyList" android:id="@+id/historyList"

View File

@ -19,6 +19,7 @@
app:destination="@id/navigation_reg" app:destination="@id/navigation_reg"
app:popUpTo="@id/nav_graph" app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
</fragment> </fragment>
<fragment <fragment
@ -36,6 +37,14 @@
app:destination="@id/navigation_auth" app:destination="@id/navigation_auth"
app:popUpTo="@id/nav_graph" app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<action
android:id="@+id/action_navigation_reg_to_navigation_user"
app:destination="@id/navigation_user"
app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" />
<argument
android:name="id"
app:argType="integer" />
</fragment> </fragment>
<fragment <fragment
@ -70,6 +79,9 @@
app:destination="@id/navigation_pizza_list" app:destination="@id/navigation_pizza_list"
app:popUpTo="@id/nav_graph" app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<argument
android:name="id"
app:argType="integer" />
</fragment> </fragment>
<fragment <fragment
@ -82,6 +94,11 @@
app:destination="@id/navigation_auth" app:destination="@id/navigation_auth"
app:popUpTo="@id/nav_graph" app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<action
android:id="@+id/action_navigation_user_to_navigation_reg"
app:destination="@id/navigation_reg"
app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" />
</fragment> </fragment>
</navigation> </navigation>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
отчеты/Рег.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB