some done

This commit is contained in:
zyzf 2023-12-22 17:01:49 +04:00
parent f79fd6d658
commit 105378ca52
20 changed files with 764 additions and 9 deletions

View File

@ -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

View File

@ -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
)

View File

@ -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)
}

View File

@ -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
)

View File

@ -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)
}
}
}
}

View File

@ -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()
}
}

View File

@ -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) {

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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
)

View File

@ -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>
)

View File

@ -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 }

View File

@ -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())
}

View File

@ -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>>
}

View File

@ -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)!!
}
}

View File

@ -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 = {}
// ) {}
// }
// }
//}

View File

@ -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)
}
}

View File

@ -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>