some done
This commit is contained in:
parent
f79fd6d658
commit
105378ca52
@ -2,6 +2,7 @@ package com.zyzf.coffeepreorder.api
|
||||
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import com.zyzf.coffeepreorder.api.model.CoffeeRemote
|
||||
import com.zyzf.coffeepreorder.api.model.OrderRemote
|
||||
import com.zyzf.coffeepreorder.api.model.UserRemote
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
@ -77,8 +78,32 @@ interface MyServerService {
|
||||
@Path("id") id: Int,
|
||||
): CoffeeRemote
|
||||
|
||||
@GET("/orders/byDate")
|
||||
suspend fun getOrdersByDate(
|
||||
@Query("startDate") startDate: String,
|
||||
@Query("endDate") endDate: String,
|
||||
): List<OrderRemote>
|
||||
|
||||
@POST("orders")
|
||||
suspend fun createOrder(
|
||||
@Body order: OrderRemote,
|
||||
): OrderRemote
|
||||
|
||||
@GET("/orders/byUser")
|
||||
suspend fun getOrdersByUser(
|
||||
@Query("userId") userId: Int,
|
||||
@Query("pageNo") page: Int,
|
||||
@Query("pageSize") limit: Int,
|
||||
): List<OrderRemote>
|
||||
|
||||
@GET("/orders/coffeesByOrder")
|
||||
suspend fun getCoffeesByOrder(
|
||||
@Query("orderId") orderId: Int,
|
||||
): List<CoffeeRemote>
|
||||
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = "http://192.168.0.100:8080/api/"
|
||||
private const val BASE_URL = "http://192.168.42.59:8080/api/"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: MyServerService? = null
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.zyzf.coffeepreorder.api.model
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.OrderCoffeeCrossRef
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class OrderCoffeeCrossRefRemote(
|
||||
val orderId: Int = 0,
|
||||
val coffeeId: Int = 0,
|
||||
)
|
||||
|
||||
fun OrderCoffeeCrossRefRemote.toOrderCoffeeCrossRef(): OrderCoffeeCrossRef = OrderCoffeeCrossRef(
|
||||
orderId,
|
||||
coffeeId
|
||||
)
|
||||
|
||||
fun OrderCoffeeCrossRef.toOrderCoffeeCrossRefRemote(): OrderCoffeeCrossRefRemote = OrderCoffeeCrossRefRemote(
|
||||
orderId,
|
||||
coffeeId
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
package com.zyzf.coffeepreorder.api.model
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.OrderWithCoffees
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class OrderCoffeeRemote(
|
||||
val order: OrderRemote = OrderRemote(),
|
||||
val coffees: List<CoffeeRemote> = listOf()
|
||||
)
|
||||
|
||||
fun OrderCoffeeRemote.toOrdersWithCoffees(): OrderWithCoffees {
|
||||
val convertedOrder = this.order.toOrder()
|
||||
val convertedCoffees = this.coffees.map { it.toCoffee() }
|
||||
return OrderWithCoffees(convertedOrder, convertedCoffees)
|
||||
}
|
||||
|
||||
fun OrderWithCoffees.toOrderCoffeeRemote(): OrderCoffeeRemote {
|
||||
val convertedOrder = this.order.toOrderRemote()
|
||||
val convertedCoffees = this.coffees.map { it.toCoffeeRemote() }
|
||||
return OrderCoffeeRemote(convertedOrder, convertedCoffees)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.zyzf.coffeepreorder.api.model
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class OrderRemote(
|
||||
val id: Int = 0,
|
||||
val date: String = "",
|
||||
val userId: Int = 0,
|
||||
val sum: Double = 0.0
|
||||
)
|
||||
|
||||
fun OrderRemote.toOrder(): Order = Order(
|
||||
id,
|
||||
date,
|
||||
userId,
|
||||
sum
|
||||
)
|
||||
|
||||
fun Order.toOrderRemote(): OrderRemote = OrderRemote(
|
||||
uid,
|
||||
date,
|
||||
userId,
|
||||
sum
|
||||
)
|
@ -0,0 +1,111 @@
|
||||
package com.zyzf.coffeepreorder.api.order
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.zyzf.coffeepreorder.CoffeeApplication
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.api.model.toOrder
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineOrderRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class OrderRemoteMediator(
|
||||
private val service: MyServerService,
|
||||
private val dbOrderRepository: OfflineOrderRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : RemoteMediator<Int, Order>() {
|
||||
|
||||
override suspend fun initialize(): InitializeAction {
|
||||
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||
}
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Order>
|
||||
): MediatorResult {
|
||||
val page = when (loadType) {
|
||||
LoadType.REFRESH -> {
|
||||
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
|
||||
remoteKeys?.nextKey?.minus(1) ?: 1
|
||||
}
|
||||
|
||||
LoadType.PREPEND -> {
|
||||
val remoteKeys = getRemoteKeyForFirstItem(state)
|
||||
remoteKeys?.prevKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
|
||||
LoadType.APPEND -> {
|
||||
val remoteKeys = getRemoteKeyForLastItem(state)
|
||||
remoteKeys?.nextKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val orders = service.getOrdersByUser(CoffeeApplication.currentUser!!.uid, page, state.config.pageSize).map { it.toOrder() }
|
||||
val endOfPaginationReached = orders.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.ORDER)
|
||||
dbOrderRepository.deleteAll()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = orders.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid,
|
||||
type = RemoteKeyType.ORDER,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
dbOrderRepository.insertOrders(orders)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
return MediatorResult.Error(exception)
|
||||
} catch (exception: HttpException) {
|
||||
return MediatorResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Order>): RemoteKeys? {
|
||||
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||
?.let { order ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(order.uid, RemoteKeyType.ORDER)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Order>): RemoteKeys? {
|
||||
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||
?.let { order ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(order.uid, RemoteKeyType.ORDER)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||
state: PagingState<Int, Order>
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { orderUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(orderUid, RemoteKeyType.ORDER)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.zyzf.coffeepreorder.api.order
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.api.model.toOrder
|
||||
import com.zyzf.coffeepreorder.api.model.toOrderRemote
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineOrderRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OrderRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class RestOrderRepository(
|
||||
private val service: MyServerService,
|
||||
private val dbOrderRepository: OfflineOrderRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : OrderRepository {
|
||||
override suspend fun getCoffeesByOrder(orderId: Int): Flow<List<Coffee>> {
|
||||
return flowOf(service.getCoffeesByOrder(orderId).map { it.toCoffee() })
|
||||
}
|
||||
|
||||
override suspend fun getOrdersByDate(startDate: String, endDate: String): Flow<List<Order>> {
|
||||
return flowOf(service.getOrdersByDate(startDate, endDate).map { it.toOrder() })
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
override fun getOrdersByUser(id: Int): Flow<PagingData<Order>> {
|
||||
Log.d(RestOrderRepository::class.simpleName, "Get Orders by User")
|
||||
|
||||
val pagingSourceFactory = { dbOrderRepository.getOrdersByUserPagingSource(id) }
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = OrderRemoteMediator(
|
||||
service,
|
||||
dbOrderRepository,
|
||||
dbRemoteKeyRepository,
|
||||
database
|
||||
),
|
||||
pagingSourceFactory = pagingSourceFactory
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun insert(order: Order) {
|
||||
service.createOrder(order.toOrderRemote()).toOrder()
|
||||
}
|
||||
}
|
@ -44,18 +44,18 @@ class RestUserRepository(
|
||||
}
|
||||
|
||||
override suspend fun getByUid(uid: Int): User =
|
||||
service.getUser(uid).toUser()!!
|
||||
service.getUser(uid).toUser()
|
||||
|
||||
override suspend fun tryLogin(login: String, password: String): User? =
|
||||
override suspend fun tryLogin(login: String, password: String): User =
|
||||
service.tryLogin(login, password).toUser()
|
||||
|
||||
|
||||
override suspend fun insert(user: User): Long {
|
||||
return service.createUser(user.toUserRemote()).toUser()?.uid?.toLong()!!
|
||||
return service.createUser(user.toUserRemote()).toUser().uid?.toLong()!!
|
||||
}
|
||||
|
||||
override suspend fun update(user: User): Int {
|
||||
return service.updateUser(user.uid, user.toUserRemote()).toUser()?.uid!!
|
||||
return service.updateUser(user.uid, user.toUserRemote()).toUser().uid
|
||||
}
|
||||
|
||||
override suspend fun delete(user: User) {
|
||||
|
@ -0,0 +1,52 @@
|
||||
package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface OrderDao {
|
||||
@Query("select * from order by name collate nocase asc")
|
||||
fun getAll(): PagingSource<Int, Order>
|
||||
|
||||
@Query("select * from order where order.uid = :uid")
|
||||
suspend fun getByUid(uid: Int): Order?
|
||||
|
||||
@Query("""
|
||||
SELECT order.* FROM order
|
||||
WHERE user_id = :userId
|
||||
""")
|
||||
fun getOrdersByUser(userId: Int): PagingSource<Int, Order>
|
||||
|
||||
@Query("""
|
||||
SELECT coffee.* FROM coffee
|
||||
INNER JOIN ordercoffeecrossref ON order.uid = ordercoffeecrossref.coffee_id
|
||||
WHERE ordercoffeecrossref.order_id = :orderId
|
||||
""")
|
||||
fun getCoffeesByOrder(orderId: Int): Flow<List<Coffee>>
|
||||
|
||||
@Query("""
|
||||
SELECT order.* FROM order
|
||||
WHERE date >= :startDate and date <= :endDate
|
||||
""")
|
||||
fun getOrdersByDate(startDate: String, endDate: String): Flow<List<Order>>
|
||||
|
||||
@Insert
|
||||
fun insert(order: Order)
|
||||
|
||||
@Insert
|
||||
suspend fun insert(vararg order: Order)
|
||||
|
||||
@Update
|
||||
fun update(order: Order): Int
|
||||
|
||||
@Delete
|
||||
suspend fun delete(order: Order)
|
||||
|
||||
@Query("delete from order")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import com.zyzf.coffeepreorder.database.model.OrderCoffeeCrossRef
|
||||
|
||||
@Dao
|
||||
interface OrderWithCoffees {
|
||||
@Query("select * from ordercoffeecrossref")
|
||||
fun getAll(): List<OrderCoffeeCrossRef>
|
||||
@Insert
|
||||
suspend fun insert(vararg order: OrderCoffeeCrossRef)
|
||||
@Delete
|
||||
suspend fun delete(order: OrderCoffeeCrossRef)
|
||||
}
|
@ -20,7 +20,7 @@ data class Cart(
|
||||
val uid: Int = 0,
|
||||
@ColumnInfo(name = "coffee_id", index = true)
|
||||
val coffeeId: Int,
|
||||
@ColumnInfo(name = "count", index = true)
|
||||
@ColumnInfo(name = "count")
|
||||
val count: Int = 0
|
||||
) {
|
||||
@Ignore
|
||||
|
@ -0,0 +1,65 @@
|
||||
package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(
|
||||
tableName = "order",
|
||||
foreignKeys = [ForeignKey(
|
||||
entity = User::class,
|
||||
parentColumns = arrayOf("uid"),
|
||||
childColumns = arrayOf("user_id"),
|
||||
onDelete = ForeignKey.RESTRICT,
|
||||
onUpdate = ForeignKey.RESTRICT
|
||||
)],
|
||||
indices = [Index(value = ["user_id"])]
|
||||
)
|
||||
data class Order(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val uid: Int = 0,
|
||||
@ColumnInfo(name = "date")
|
||||
var date: String,
|
||||
@ColumnInfo(name = "user_id", index = true)
|
||||
val userId: Int,
|
||||
@ColumnInfo(name = "sum")
|
||||
val sum: Double
|
||||
) {
|
||||
@Ignore
|
||||
constructor(
|
||||
date: String,
|
||||
userId: Int
|
||||
) : this(0, date, userId, 0.0)
|
||||
|
||||
companion object {
|
||||
fun getOrder(index: Int = 0): Order {
|
||||
return Order(
|
||||
index,
|
||||
"",
|
||||
0,
|
||||
0.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as Order
|
||||
if (uid != other.uid) return false
|
||||
if (date != other.date) return false
|
||||
if (userId != other.userId) return false
|
||||
return sum == other.sum
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = uid
|
||||
result = 31 * result + date.hashCode()
|
||||
result = 31 * result + userId.hashCode()
|
||||
result = 31 * result + sum.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
|
||||
@Entity(primaryKeys = ["order_id", "coffee_id"])
|
||||
class OrderCoffeeCrossRef (
|
||||
@ColumnInfo(name = "order_id")
|
||||
val orderId: Int,
|
||||
@ColumnInfo(name = "coffee_id")
|
||||
val coffeeId: Int
|
||||
)
|
@ -0,0 +1,15 @@
|
||||
package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Junction
|
||||
import androidx.room.Relation
|
||||
|
||||
data class OrderWithCoffees(
|
||||
@Embedded val order: Order,
|
||||
@Relation(
|
||||
parentColumn = "order_id",
|
||||
entityColumn = "coffee_id",
|
||||
associateBy = Junction(OrderCoffeeCrossRef::class)
|
||||
)
|
||||
val coffees: List<Coffee>
|
||||
)
|
@ -7,7 +7,8 @@ import androidx.room.TypeConverters
|
||||
|
||||
enum class RemoteKeyType(private val type: String) {
|
||||
COFFEE(Coffee::class.simpleName ?: "Coffee"),
|
||||
USER(User::class.simpleName ?: "User");
|
||||
USER(User::class.simpleName ?: "User"),
|
||||
ORDER(Order::class.simpleName ?: "Order");
|
||||
|
||||
@TypeConverter
|
||||
fun toRemoteKeyType(value: String) = entries.first { it.type == value }
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.dao.OrderDao
|
||||
import com.zyzf.coffeepreorder.database.dao.OrderWithCoffees
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository {
|
||||
override fun getOrdersByUser(id: Int): Flow<PagingData<Order>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = { orderDao.getOrdersByUser(id) }
|
||||
).flow
|
||||
override suspend fun getCoffeesByOrder(orderId: Int): Flow<List<Coffee>> = orderDao.getCoffeesByOrder(orderId)
|
||||
override suspend fun insert(order: Order) = orderDao.insert(order)
|
||||
override suspend fun getOrdersByDate(
|
||||
startDate: String,
|
||||
endDate: String
|
||||
): Flow<List<Order>> = orderDao.getOrdersByDate(startDate, endDate)
|
||||
fun getOrdersByUserPagingSource(id: Int): PagingSource<Int, Order> = orderDao.getOrdersByUser(id)
|
||||
suspend fun deleteAll() = orderDao.deleteAll()
|
||||
suspend fun insertOrders(orders: List<Order>) =
|
||||
orderDao.insert(*orders.toTypedArray())
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface OrderRepository {
|
||||
suspend fun getCoffeesByOrder(orderId: Int): Flow<List<Coffee>>
|
||||
fun getOrdersByUser(id: Int): Flow<PagingData<Order>>
|
||||
suspend fun insert(order: Order)
|
||||
suspend fun getOrdersByDate(startDate: String, endDate: String): Flow<List<Order>>
|
||||
}
|
@ -25,6 +25,6 @@ class ProfileViewModel(
|
||||
val userUid: Int? = userRepository.update(User(
|
||||
userUid, userLogin, userFIO, userPhone, currentUserPassw, userRole))
|
||||
}
|
||||
return userRepository.getByUid(userUid!!)!!
|
||||
return userRepository.getByUid(userUid)!!
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,213 @@
|
||||
package com.zyzf.coffeepreorder.ui.statistic
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.PickVisualMediaRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.outlined.Create
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.OutlinedIconButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableDoubleStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.zyzf.coffeepreorder.CoffeeApplication
|
||||
import com.zyzf.coffeepreorder.R
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.Order
|
||||
import com.zyzf.coffeepreorder.database.model.OrderWithCoffees
|
||||
import com.zyzf.coffeepreorder.ui.AppViewModelProvider
|
||||
import com.zyzf.coffeepreorder.ui.coffee.CoffeeListViewModel
|
||||
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
|
||||
import eu.bambooapps.material3.pullrefresh.PullRefreshIndicator
|
||||
import eu.bambooapps.material3.pullrefresh.pullRefresh
|
||||
import eu.bambooapps.material3.pullrefresh.rememberPullRefreshState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun OrderStatistic(
|
||||
viewModel: CoffeeListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val orderListUiState = viewModel.coffeeListUiState.collectAsLazyPagingItems()
|
||||
val openDialog = remember { mutableStateOf(false) }
|
||||
var refreshing by remember { mutableStateOf(false) }
|
||||
fun refresh() = coroutineScope.launch {
|
||||
refreshing = true
|
||||
orderListUiState.refresh()
|
||||
refreshing = false
|
||||
}
|
||||
val state = rememberPullRefreshState(refreshing, ::refresh)
|
||||
Scaffold(
|
||||
topBar = {},
|
||||
floatingActionButton = {
|
||||
if (CoffeeApplication.currentUser?.role == "admin") {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
//TODO
|
||||
}
|
||||
},
|
||||
Modifier
|
||||
.padding(all = 20.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Check,
|
||||
contentDescription = "Add",
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box (modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.pullRefresh(state)) {
|
||||
PullRefreshIndicator(refreshing = refreshing, state = state,
|
||||
modifier = Modifier
|
||||
.zIndex(100f)
|
||||
.align(Alignment.TopCenter)
|
||||
)
|
||||
OrderList(
|
||||
orderList = orderListUiState
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OrderList(
|
||||
orderList: LazyPagingItems<OrderWithCoffees>,
|
||||
) {
|
||||
LazyColumn(
|
||||
horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
items(
|
||||
count = orderList.itemCount,
|
||||
key = orderList.itemKey(),
|
||||
contentType = orderList.itemContentType()
|
||||
) {index ->
|
||||
val order = orderList[index]
|
||||
order?.let {
|
||||
OrderListItem(
|
||||
order = order
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OrderListItem(
|
||||
order: OrderWithCoffees
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(max = 140.dp)
|
||||
.padding(bottom = 10.dp, top = 10.dp)) {
|
||||
Text(text = order.order.userId.toString(), fontSize = 25.sp)
|
||||
Text(text = String.format("%.2f", order.coffees.sumOf { it.cost }), fontSize = 20.sp)
|
||||
order.coffees.map {
|
||||
Text(text = it.name, fontSize = 15.sp)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
//@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
//@Composable
|
||||
//fun CoffeeListPreview() {
|
||||
// CoffeePreorderTheme {
|
||||
// Surface(
|
||||
// color = MaterialTheme.colorScheme.background
|
||||
// ) {
|
||||
// OrderList(
|
||||
// orderList = MutableStateFlow(
|
||||
// PagingData.from((1..20).map { i -> Coffee.getCoffee(i) })
|
||||
// ).collectAsLazyPagingItems(),
|
||||
// onAddToCartClick = {}
|
||||
// ) {}
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
//@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
//@Composable
|
||||
//fun CoffeeEmptyListPreview() {
|
||||
// CoffeePreorderTheme {
|
||||
// Surface(
|
||||
// color = MaterialTheme.colorScheme.background
|
||||
// ) {
|
||||
// CoffeeList(
|
||||
// coffeeList = MutableStateFlow(
|
||||
// PagingData.empty<Coffee>()
|
||||
// ).collectAsLazyPagingItems(),
|
||||
// onAddToCartClick = {}
|
||||
// ) {}
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -0,0 +1,70 @@
|
||||
package com.zyzf.coffeepreorder.ui.statistic
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.repository.CartRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
import com.zyzf.coffeepreorder.ui.coffee.copyFileToSftp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class OrderStatisticViewModel(
|
||||
private val coffeeRepository: CoffeeRepository,
|
||||
private val cartRepository: CartRepository
|
||||
) : ViewModel() {
|
||||
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAllCoffees()
|
||||
|
||||
suspend fun addCoffeeToCart(coffeeUid: Int) {
|
||||
cartRepository.insertCoffee(coffeeUid, 1)
|
||||
}
|
||||
suspend fun createCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
|
||||
val newCoffee: Long = coffeeRepository.insert(coffee)
|
||||
val inputStream = context.contentResolver.openInputStream(imageUri)
|
||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
|
||||
val f = File(context.cacheDir, "coffee_image_$newCoffee.png")
|
||||
withContext(Dispatchers.IO) {
|
||||
f.createNewFile()
|
||||
val bos = ByteArrayOutputStream()
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos)
|
||||
val bitmapdata = bos.toByteArray()
|
||||
val fos = FileOutputStream(f)
|
||||
fos.write(bitmapdata)
|
||||
fos.flush()
|
||||
fos.close()
|
||||
}
|
||||
|
||||
copyFileToSftp(f, "/mnt/nextcloud/data/Zyzf/files/Images")
|
||||
}
|
||||
suspend fun editCoffee(coffee: Coffee, imageUri: Any?, context: Context) {
|
||||
val editedCoffee: Int = coffeeRepository.update(coffee)
|
||||
if (imageUri !is Uri) return
|
||||
val inputStream = context.contentResolver.openInputStream(imageUri)
|
||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
|
||||
val f = File(context.cacheDir, "coffee_image_$editedCoffee.png")
|
||||
withContext(Dispatchers.IO) {
|
||||
f.createNewFile()
|
||||
val bos = ByteArrayOutputStream()
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos)
|
||||
val bitmapdata = bos.toByteArray()
|
||||
val fos = FileOutputStream(f)
|
||||
fos.write(bitmapdata)
|
||||
fos.flush()
|
||||
fos.close()
|
||||
}
|
||||
copyFileToSftp(f, "/mnt/nextcloud/data/Zyzf/files/Images")
|
||||
}
|
||||
suspend fun deleteCoffee(coffee: Coffee) {
|
||||
coffeeRepository.delete(coffee)
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">192.168.0.100</domain>
|
||||
<domain includeSubdomains="true">192.168.42.59</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
Loading…
x
Reference in New Issue
Block a user