некорректное отображение данных в корзине
This commit is contained in:
parent
a14249d6ef
commit
a66218c7ab
@ -90,6 +90,11 @@ interface MyServerService {
|
|||||||
@Query("userId") userId: Int,
|
@Query("userId") userId: Int,
|
||||||
): List<UserSessionWithSessionRemote>
|
): List<UserSessionWithSessionRemote>
|
||||||
|
|
||||||
|
@GET("userssessions")
|
||||||
|
suspend fun getUserSessions(
|
||||||
|
@Query("userId") userId: Int,
|
||||||
|
): List<UserSessionRemote>
|
||||||
|
|
||||||
@GET("userssessions?_expand=session")
|
@GET("userssessions?_expand=session")
|
||||||
suspend fun getUsersSessions(): List<UserSessionWithSessionRemote>
|
suspend fun getUsersSessions(): List<UserSessionWithSessionRemote>
|
||||||
|
|
||||||
|
@ -48,13 +48,13 @@ class RestCinemaRepository(
|
|||||||
|
|
||||||
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
override suspend fun getCinema(uid: Int): CinemaWithSessions {
|
||||||
val cinemaWithSessions = service.getCinemaWithSessions(uid)
|
val cinemaWithSessions = service.getCinemaWithSessions(uid)
|
||||||
|
val orders = service.getOrders()
|
||||||
val sessions = cinemaWithSessions.sessions.map { sessionFromCinemaRemote ->
|
val sessions = cinemaWithSessions.sessions.map { sessionFromCinemaRemote ->
|
||||||
SessionFromCinema(
|
SessionFromCinema(
|
||||||
sessionFromCinemaRemote.id,
|
sessionFromCinemaRemote.id,
|
||||||
sessionFromCinemaRemote.dateTime,
|
sessionFromCinemaRemote.dateTime,
|
||||||
sessionFromCinemaRemote.price,
|
sessionFromCinemaRemote.price,
|
||||||
sessionFromCinemaRemote.maxCount - service.getOrders().flatMap
|
sessionFromCinemaRemote.maxCount - orders.flatMap
|
||||||
{ order ->
|
{ order ->
|
||||||
order.sessions.filter { session ->
|
order.sessions.filter { session ->
|
||||||
session.id == sessionFromCinemaRemote.id &&
|
session.id == sessionFromCinemaRemote.id &&
|
||||||
|
@ -11,7 +11,7 @@ class RestOrderSessionRepository(
|
|||||||
private val dbOrderSessionRepository: OfflineOrderSessionRepository
|
private val dbOrderSessionRepository: OfflineOrderSessionRepository
|
||||||
) : OrderSessionRepository {
|
) : OrderSessionRepository {
|
||||||
override suspend fun insertOrderSession(orderSessionCrossRef: OrderSessionCrossRef) {
|
override suspend fun insertOrderSession(orderSessionCrossRef: OrderSessionCrossRef) {
|
||||||
var orderRemote = service.getOrder(orderSessionCrossRef.orderId)
|
val orderRemote = service.getOrder(orderSessionCrossRef.orderId)
|
||||||
val session = service.getSession(orderSessionCrossRef.sessionId)
|
val session = service.getSession(orderSessionCrossRef.sessionId)
|
||||||
|
|
||||||
val sessionFromOrder = SessionFromOrderRemote(
|
val sessionFromOrder = SessionFromOrderRemote(
|
||||||
@ -23,10 +23,9 @@ class RestOrderSessionRepository(
|
|||||||
session.cinema
|
session.cinema
|
||||||
)
|
)
|
||||||
|
|
||||||
val updatedSessions = orderRemote.sessions.toMutableList()
|
orderRemote.sessions = orderRemote.sessions.toMutableList().apply {
|
||||||
updatedSessions.add(sessionFromOrder)
|
add(sessionFromOrder)
|
||||||
|
}
|
||||||
orderRemote = orderRemote.copy(sessions = updatedSessions)
|
|
||||||
service.updateOrder(orderSessionCrossRef.orderId, orderRemote)
|
service.updateOrder(orderSessionCrossRef.orderId, orderRemote)
|
||||||
dbOrderSessionRepository.insertOrderSession(orderSessionCrossRef)
|
dbOrderSessionRepository.insertOrderSession(orderSessionCrossRef)
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,13 @@ class RestUserRepository(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
val orders = service.getOrders()
|
||||||
val sessions = cart.map { sessionFromCartRemote ->
|
val sessions = cart.map { sessionFromCartRemote ->
|
||||||
SessionFromCart(
|
SessionFromCart(
|
||||||
uid = sessionFromCartRemote.sessionId,
|
uid = sessionFromCartRemote.sessionId,
|
||||||
dateTime = sessionFromCartRemote.session.dateTime,
|
dateTime = sessionFromCartRemote.session.dateTime,
|
||||||
price = sessionFromCartRemote.session.price,
|
price = sessionFromCartRemote.session.price,
|
||||||
availableCount = sessionFromCartRemote.session.maxCount - service.getOrders()
|
availableCount = sessionFromCartRemote.session.maxCount - orders
|
||||||
.flatMap
|
.flatMap
|
||||||
{ order ->
|
{ order ->
|
||||||
order.sessions.filter { session ->
|
order.sessions.filter { session ->
|
||||||
|
@ -46,16 +46,20 @@ class RestUserSessionRepository(
|
|||||||
val userSessionRemote = service.getUserSession(
|
val userSessionRemote = service.getUserSession(
|
||||||
userSessionCrossRef.userId,
|
userSessionCrossRef.userId,
|
||||||
userSessionCrossRef.sessionId
|
userSessionCrossRef.sessionId
|
||||||
).first()
|
).firstOrNull() ?: return
|
||||||
service.deleteUserSession(userSessionRemote.id)
|
service.deleteUserSession(userSessionRemote.id)
|
||||||
dbUserSessionRepository.deleteUserSession(userSessionCrossRef)
|
dbUserSessionRepository.deleteUserSession(userSessionCrossRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteUserSessions(userId: Int) {
|
override suspend fun deleteUserSessions(userId: Int) {
|
||||||
val cart = service.getUserCart(userId)
|
val cart = service.getUserSessions(userId)
|
||||||
cart.forEach {
|
cart.forEach {
|
||||||
service.deleteUserSession(it.id)
|
service.deleteUserSession(it.id)
|
||||||
}
|
}
|
||||||
dbUserSessionRepository.deleteUserSessions(userId)
|
dbUserSessionRepository.deleteUserSessions(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteUserSessions(userSessionCrossRefs: List<UserSessionCrossRef>) {
|
||||||
|
userSessionCrossRefs.forEach { deleteUserSession(it) }
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@ -16,6 +17,7 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@ -33,8 +35,11 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.NavController
|
||||||
import com.example.myapplication.LiveStore
|
import com.example.myapplication.LiveStore
|
||||||
import com.example.myapplication.R
|
import com.example.myapplication.R
|
||||||
|
import com.example.myapplication.api.ApiStatus
|
||||||
|
import com.example.myapplication.composeui.navigation.Screen
|
||||||
import com.example.myapplication.database.entities.composeui.AppViewModelProvider
|
import com.example.myapplication.database.entities.composeui.AppViewModelProvider
|
||||||
import com.example.myapplication.database.entities.model.Session
|
import com.example.myapplication.database.entities.model.Session
|
||||||
import com.example.myapplication.database.entities.model.SessionFromCart
|
import com.example.myapplication.database.entities.model.SessionFromCart
|
||||||
@ -44,6 +49,7 @@ import org.threeten.bp.format.DateTimeFormatter
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Cart(
|
fun Cart(
|
||||||
|
navController: NavController,
|
||||||
viewModel: CartViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
viewModel: CartViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
@ -52,29 +58,52 @@ fun Cart(
|
|||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.refreshState()
|
viewModel.refreshState()
|
||||||
}
|
}
|
||||||
Cart(
|
when (viewModel.apiStatus) {
|
||||||
cartUiState = cartUiState,
|
ApiStatus.DONE -> {
|
||||||
modifier = Modifier
|
Cart(
|
||||||
.padding(all = 10.dp),
|
cartUiState = cartUiState,
|
||||||
onChangeCount = { session: SessionFromCart, count: Int ->
|
modifier = Modifier
|
||||||
coroutineScope.launch {
|
.padding(all = 10.dp),
|
||||||
viewModel.updateFromCart(
|
onChangeCount = { session: SessionFromCart, count: Int ->
|
||||||
session = Session(
|
coroutineScope.launch {
|
||||||
uid = session.uid,
|
viewModel.updateFromCart(
|
||||||
dateTime = session.dateTime,
|
session = Session(
|
||||||
price = session.price,
|
uid = session.uid,
|
||||||
maxCount = 0,
|
dateTime = session.dateTime,
|
||||||
cinemaId = session.cinemaId
|
price = session.price,
|
||||||
), count = count, availableCount = session.availableCount
|
maxCount = 0,
|
||||||
)
|
cinemaId = session.cinemaId
|
||||||
}
|
), count = count, availableCount = session.availableCount
|
||||||
},
|
)
|
||||||
onAddToOrder = { sessions: List<SessionFromCart> ->
|
}
|
||||||
coroutineScope.launch {
|
},
|
||||||
viewModel.addToOrder(sessions = sessions)
|
onAddToOrder = { sessions: List<SessionFromCart> ->
|
||||||
}
|
coroutineScope.launch {
|
||||||
|
viewModel.addToOrder(sessions = sessions)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDelete = { session: SessionFromCart ->
|
||||||
|
coroutineScope.launch {
|
||||||
|
viewModel.removeFromCart(
|
||||||
|
session = Session(
|
||||||
|
uid = session.uid,
|
||||||
|
dateTime = session.dateTime,
|
||||||
|
price = session.price,
|
||||||
|
maxCount = 0,
|
||||||
|
cinemaId = session.cinemaId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
ApiStatus.LOADING -> LoadingPlaceholder()
|
||||||
|
else -> ErrorPlaceholder(
|
||||||
|
message = viewModel.apiError,
|
||||||
|
onBack = { navController.navigate(Screen.Report.route) }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -82,7 +111,8 @@ private fun Cart(
|
|||||||
cartUiState: CartUiState,
|
cartUiState: CartUiState,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onChangeCount: (SessionFromCart, Int) -> Unit,
|
onChangeCount: (SessionFromCart, Int) -> Unit,
|
||||||
onAddToOrder: (List<SessionFromCart>) -> Unit
|
onAddToOrder: (List<SessionFromCart>) -> Unit,
|
||||||
|
onDelete: (SessionFromCart) -> Unit
|
||||||
) {
|
) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@ -95,9 +125,13 @@ private fun Cart(
|
|||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
.clip(RoundedCornerShape(16.dp))
|
.clip(RoundedCornerShape(16.dp))
|
||||||
.background(MaterialTheme.colorScheme.secondary),
|
.background(MaterialTheme.colorScheme.secondary),
|
||||||
onChangeCount = onChangeCount
|
onChangeCount = onChangeCount,
|
||||||
|
onDelete = onDelete,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val user = LiveStore.user.observeAsState()
|
val user = LiveStore.user.observeAsState()
|
||||||
if (user.value?.role == UserRole.USER) {
|
if (user.value?.role == UserRole.USER) {
|
||||||
@ -107,7 +141,7 @@ private fun Cart(
|
|||||||
Button(
|
Button(
|
||||||
onClick = { onAddToOrder(cartUiState.sessionList) },
|
onClick = { onAddToOrder(cartUiState.sessionList) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(16.dp)
|
.padding(6.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) { Text("Купить") }
|
) { Text("Купить") }
|
||||||
}
|
}
|
||||||
@ -119,25 +153,26 @@ private fun SessionListItem(
|
|||||||
session: SessionFromCart,
|
session: SessionFromCart,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onChangeCount: (SessionFromCart, Int) -> Unit,
|
onChangeCount: (SessionFromCart, Int) -> Unit,
|
||||||
|
onDelete: (SessionFromCart) -> Unit
|
||||||
) {
|
) {
|
||||||
val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
|
val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
|
||||||
val formattedDate = dateFormatter.format(session.dateTime)
|
val formattedDate = dateFormatter.format(session.dateTime)
|
||||||
Column {
|
Text(
|
||||||
Text(
|
text = formattedDate,
|
||||||
text = formattedDate,
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
color = MaterialTheme.colorScheme.onBackground,
|
)
|
||||||
)
|
Column(modifier = modifier.fillMaxWidth()) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth(),
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.SpaceBetween
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
) {
|
) {
|
||||||
if (session.cinema.image != null)
|
if (session.cinema.image != null) {
|
||||||
Image(
|
Image(
|
||||||
bitmap = BitmapFactory.decodeByteArray(
|
bitmap = BitmapFactory.decodeByteArray(
|
||||||
session.cinema.image,
|
session.cinema.image,
|
||||||
@ -149,6 +184,7 @@ private fun SessionListItem(
|
|||||||
.size(90.dp)
|
.size(90.dp)
|
||||||
.padding(4.dp)
|
.padding(4.dp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
@ -157,54 +193,65 @@ private fun SessionListItem(
|
|||||||
Text(
|
Text(
|
||||||
text = "${session.cinema.name}, ${session.cinema.year}\n" +
|
text = "${session.cinema.name}, ${session.cinema.year}\n" +
|
||||||
"Цена: ${session.price}\n" +
|
"Цена: ${session.price}\n" +
|
||||||
"${session.count}/${session.availableCount}",
|
if (session.availableCount == 0) "Недоступно" else "${session.count}/${session.availableCount}",
|
||||||
color = MaterialTheme.colorScheme.onSecondary
|
color = MaterialTheme.colorScheme.onSecondary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(
|
.background(color = MaterialTheme.colorScheme.primary)
|
||||||
color = MaterialTheme.colorScheme.background,
|
.fillMaxWidth(),
|
||||||
shape = RoundedCornerShape(10.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
) // Задаем фон для кнопок
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { onDelete(session) }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Delete,
|
||||||
|
contentDescription = "Удалить",
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1F))
|
||||||
|
|
||||||
|
if (session.availableCount != 0) {
|
||||||
|
IconButton(
|
||||||
|
enabled = session.count != 1,
|
||||||
|
onClick = { onChangeCount(session, session.count - 1) }
|
||||||
) {
|
) {
|
||||||
Row(
|
Icon(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
imageVector = ImageVector.vectorResource(id = R.drawable.minus),
|
||||||
) {
|
contentDescription = "Уменьшить",
|
||||||
IconButton(
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
onClick = { onChangeCount(session, session.count - 1) }
|
)
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = ImageVector.vectorResource(id = R.drawable.minus),
|
|
||||||
contentDescription = "Уменьшить",
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
modifier = Modifier.size(10.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = "${session.count}",
|
|
||||||
color = MaterialTheme.colorScheme.onBackground
|
|
||||||
)
|
|
||||||
|
|
||||||
IconButton(
|
|
||||||
onClick = {
|
|
||||||
onChangeCount(
|
|
||||||
session,
|
|
||||||
if (session.count != session.availableCount) session.count + 1 else session.count
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Add,
|
|
||||||
contentDescription = "Увеличить",
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
modifier = Modifier.size(10.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "${session.count}",
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
enabled = session.count != session.availableCount,
|
||||||
|
onClick = {
|
||||||
|
onChangeCount(
|
||||||
|
session,
|
||||||
|
if (session.count != session.availableCount) session.count + 1 else session.count
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Add,
|
||||||
|
contentDescription = "Увеличить",
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.example.myapplication.composeui
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.room.Transaction
|
||||||
import com.example.myapplication.LiveStore
|
import com.example.myapplication.LiveStore
|
||||||
import com.example.myapplication.database.entities.model.Order
|
import com.example.myapplication.database.entities.model.Order
|
||||||
import com.example.myapplication.database.entities.model.OrderSessionCrossRef
|
import com.example.myapplication.database.entities.model.OrderSessionCrossRef
|
||||||
@ -25,39 +26,45 @@ class CartViewModel(
|
|||||||
var cartUiState by mutableStateOf(CartUiState())
|
var cartUiState by mutableStateOf(CartUiState())
|
||||||
private set
|
private set
|
||||||
|
|
||||||
suspend fun refreshState() {
|
suspend fun refreshState(needLoadingScreen: Boolean = true) {
|
||||||
val userId: Int = LiveStore.user.value?.uid ?: 0
|
val userId: Int = LiveStore.user.value?.uid ?: return
|
||||||
runInScope(
|
runInScope(
|
||||||
actionSuccess = {
|
actionSuccess = {
|
||||||
val cart = userRepository.getCartByUser(userId)
|
cartUiState = CartUiState(userRepository.getCartByUser(userId))
|
||||||
cartUiState = CartUiState(cart)
|
|
||||||
}, actionError = {
|
}, actionError = {
|
||||||
cartUiState = CartUiState()
|
cartUiState = CartUiState()
|
||||||
}
|
},
|
||||||
|
needLoadingScreen = needLoadingScreen
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transaction
|
||||||
suspend fun addToOrder(sessions: List<SessionFromCart>) {
|
suspend fun addToOrder(sessions: List<SessionFromCart>) {
|
||||||
if (isLoading)
|
if (isLoading)
|
||||||
return
|
return
|
||||||
isLoading = true
|
isLoading = true
|
||||||
val userId: Int = LiveStore.user.value?.uid ?: return
|
val userId: Int = LiveStore.user.value?.uid ?: return
|
||||||
if (sessions.isEmpty())
|
val cart = sessions.filter { it.availableCount != 0 }
|
||||||
|
if (cart.isEmpty())
|
||||||
return
|
return
|
||||||
runInScope(
|
runInScope(
|
||||||
actionSuccess = {
|
actionSuccess = {
|
||||||
val orderId = orderRepository.insertOrder(Order(0, userId, LocalDateTime.now()))
|
val orderId = orderRepository.insertOrder(Order(0, userId, LocalDateTime.now()))
|
||||||
sessions.forEach { session ->
|
cart.forEach { session ->
|
||||||
orderSessionRepository.insertOrderSession(
|
if (session.availableCount != 0) {
|
||||||
OrderSessionCrossRef(
|
orderSessionRepository.insertOrderSession(
|
||||||
orderId.toInt(),
|
OrderSessionCrossRef(
|
||||||
session.uid,
|
orderId.toInt(),
|
||||||
session.price,
|
session.uid,
|
||||||
session.count
|
session.price,
|
||||||
|
session.count
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
userSessionRepository.deleteUserSessions(userId)
|
userSessionRepository.deleteUserSessions(cart.map {
|
||||||
|
UserSessionCrossRef(userId, it.uid, it.count)
|
||||||
|
})
|
||||||
refreshState()
|
refreshState()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -97,7 +104,9 @@ class CartViewModel(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
refreshState()
|
refreshState()
|
||||||
}
|
},
|
||||||
|
actionError = { },
|
||||||
|
needLoadingScreen = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.example.myapplication.composeui
|
package com.example.myapplication.composeui
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@ -8,8 +7,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -17,12 +14,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import androidx.compose.ui.unit.TextUnitType
|
import androidx.compose.ui.unit.TextUnitType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.example.myapplication.R
|
import com.example.myapplication.R
|
||||||
import com.example.myapplication.ui.theme.PmudemoTheme
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -68,29 +63,3 @@ fun LoadingPlaceholder() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 ErrorPlaceholderPreview() {
|
|
||||||
PmudemoTheme {
|
|
||||||
Surface(
|
|
||||||
color = MaterialTheme.colorScheme.background
|
|
||||||
) {
|
|
||||||
ErrorPlaceholder("Error", onBack = {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 LoadingPlaceholderPreview() {
|
|
||||||
PmudemoTheme {
|
|
||||||
Surface(
|
|
||||||
color = MaterialTheme.colorScheme.background
|
|
||||||
) {
|
|
||||||
LoadingPlaceholder()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,8 +25,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.NavController
|
||||||
import com.example.myapplication.api.ApiStatus
|
import com.example.myapplication.api.ApiStatus
|
||||||
import com.example.myapplication.api.session.ReportRemote
|
import com.example.myapplication.api.session.ReportRemote
|
||||||
|
import com.example.myapplication.composeui.navigation.Screen
|
||||||
import com.example.myapplication.database.entities.composeui.AppViewModelProvider
|
import com.example.myapplication.database.entities.composeui.AppViewModelProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.threeten.bp.format.DateTimeFormatter
|
import org.threeten.bp.format.DateTimeFormatter
|
||||||
@ -35,6 +37,7 @@ import java.util.Date
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Report(
|
fun Report(
|
||||||
|
navController: NavController,
|
||||||
viewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
viewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||||
) {
|
) {
|
||||||
val dateStateStart = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)
|
val dateStateStart = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)
|
||||||
@ -87,7 +90,6 @@ fun Report(
|
|||||||
Button(
|
Button(
|
||||||
onClick = { coroutineScope.launch { viewModel.getReport() } },
|
onClick = { coroutineScope.launch { viewModel.getReport() } },
|
||||||
enabled = viewModel.reportUiState.isEntryValid,
|
enabled = viewModel.reportUiState.isEntryValid,
|
||||||
shape = MaterialTheme.shapes.small,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(text = "Получить отчет")
|
Text(text = "Получить отчет")
|
||||||
@ -100,7 +102,7 @@ fun Report(
|
|||||||
ApiStatus.LOADING -> LoadingPlaceholder()
|
ApiStatus.LOADING -> LoadingPlaceholder()
|
||||||
else -> ErrorPlaceholder(
|
else -> ErrorPlaceholder(
|
||||||
message = viewModel.apiError,
|
message = viewModel.apiError,
|
||||||
onBack = { }
|
onBack = { navController.navigate(Screen.Report.route) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ fun Navhost(
|
|||||||
) {
|
) {
|
||||||
composable(Screen.CinemaList.route) { CinemaList(navController) }
|
composable(Screen.CinemaList.route) { CinemaList(navController) }
|
||||||
composable(Screen.OrderList.route) { OrderList(navController) }
|
composable(Screen.OrderList.route) { OrderList(navController) }
|
||||||
composable(Screen.Cart.route) { Cart() }
|
composable(Screen.Cart.route) { Cart(navController) }
|
||||||
composable(Screen.UserProfile.route) { UserProfile(isDarkTheme, dataStore) }
|
composable(Screen.UserProfile.route) { UserProfile(isDarkTheme, dataStore) }
|
||||||
composable(
|
composable(
|
||||||
Screen.CinemaEdit.route,
|
Screen.CinemaEdit.route,
|
||||||
@ -189,7 +189,7 @@ fun Navhost(
|
|||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
backStackEntry.arguments?.let { OrderView(navController) }
|
backStackEntry.arguments?.let { OrderView(navController) }
|
||||||
}
|
}
|
||||||
composable(Screen.Report.route) { Report() }
|
composable(Screen.Report.route) { Report(navController) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +113,7 @@ fun SessionList(
|
|||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
if (session.availableCount != 0)
|
viewModel.addSessionInCart(sessionId = session.uid)
|
||||||
viewModel.addSessionInCart(sessionId = session.uid)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
@ -29,17 +29,13 @@ class SessionListViewModel(
|
|||||||
suspend fun addSessionInCart(sessionId: Int, count: Int = 1) {
|
suspend fun addSessionInCart(sessionId: Int, count: Int = 1) {
|
||||||
val userId: Int = LiveStore.user.value?.uid ?: return
|
val userId: Int = LiveStore.user.value?.uid ?: return
|
||||||
runInScope(actionSuccess = {
|
runInScope(actionSuccess = {
|
||||||
try {
|
userSessionRepository.insertUserSession(
|
||||||
userSessionRepository.insertUserSession(
|
UserSessionCrossRef(
|
||||||
UserSessionCrossRef(
|
userId,
|
||||||
userId,
|
sessionId,
|
||||||
sessionId,
|
count
|
||||||
count
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
} catch (_: Exception) {
|
)
|
||||||
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,7 +76,7 @@ fun UserProfile(
|
|||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(8.dp)
|
.padding(start = 2.dp, top = 10.dp)
|
||||||
) { Text("Выход") }
|
) { Text("Выход") }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -160,7 +160,7 @@ fun UserProfile(
|
|||||||
onClick = { coroutine.launch { viewModel.signUp() } },
|
onClick = { coroutine.launch { viewModel.signUp() } },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(8.dp)
|
.padding(start = 2.dp, top = 8.dp)
|
||||||
) {
|
) {
|
||||||
Text("Регистрация")
|
Text("Регистрация")
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ fun UserProfile(
|
|||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(8.dp)
|
.padding(start = 2.dp, top = 8.dp)
|
||||||
) {
|
) {
|
||||||
Text("Вход")
|
Text("Вход")
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,6 @@ private fun CinemaEdit(
|
|||||||
Button(
|
Button(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
enabled = cinemaUiState.isEntryValid,
|
enabled = cinemaUiState.isEntryValid,
|
||||||
shape = MaterialTheme.shapes.small,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.Save_button))
|
Text(text = stringResource(R.string.Save_button))
|
||||||
|
@ -9,7 +9,6 @@ import androidx.compose.material3.Button
|
|||||||
import androidx.compose.material3.DatePicker
|
import androidx.compose.material3.DatePicker
|
||||||
import androidx.compose.material3.DisplayMode
|
import androidx.compose.material3.DisplayMode
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TimePicker
|
import androidx.compose.material3.TimePicker
|
||||||
@ -153,7 +152,6 @@ private fun SessionEdit(
|
|||||||
Button(
|
Button(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
enabled = sessionUiState.isEntryValid,
|
enabled = sessionUiState.isEntryValid,
|
||||||
shape = MaterialTheme.shapes.small,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.Save_button))
|
Text(text = stringResource(R.string.Save_button))
|
||||||
|
@ -17,7 +17,7 @@ interface UserSessionCrossRefDao {
|
|||||||
suspend fun update(userSessionCrossRef: UserSessionCrossRef)
|
suspend fun update(userSessionCrossRef: UserSessionCrossRef)
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(userSessionCrossRef: UserSessionCrossRef)
|
suspend fun delete(vararg userSessionCrossRef: UserSessionCrossRef)
|
||||||
|
|
||||||
@Query("DELETE FROM users_sessions where users_sessions.user_id = :userId")
|
@Query("DELETE FROM users_sessions where users_sessions.user_id = :userId")
|
||||||
suspend fun deleteByUserUid(userId: Int)
|
suspend fun deleteByUserUid(userId: Int)
|
||||||
|
@ -16,5 +16,8 @@ class OfflineUserSessionRepository(private val userSessionDao: UserSessionCrossR
|
|||||||
|
|
||||||
override suspend fun deleteUserSessions(userId: Int) = userSessionDao.deleteByUserUid(userId)
|
override suspend fun deleteUserSessions(userId: Int) = userSessionDao.deleteByUserUid(userId)
|
||||||
|
|
||||||
|
override suspend fun deleteUserSessions(userSessionCrossRefs: List<UserSessionCrossRef>) =
|
||||||
|
userSessionDao.delete(*userSessionCrossRefs.toTypedArray())
|
||||||
|
|
||||||
suspend fun deleteSessionsByUid(sessionId: Int) = userSessionDao.deleteBySessionUid(sessionId)
|
suspend fun deleteSessionsByUid(sessionId: Int) = userSessionDao.deleteBySessionUid(sessionId)
|
||||||
}
|
}
|
@ -7,4 +7,5 @@ interface UserSessionRepository {
|
|||||||
suspend fun updateUserSession(userSessionCrossRef: UserSessionCrossRef)
|
suspend fun updateUserSession(userSessionCrossRef: UserSessionCrossRef)
|
||||||
suspend fun deleteUserSession(userSessionCrossRef: UserSessionCrossRef)
|
suspend fun deleteUserSession(userSessionCrossRef: UserSessionCrossRef)
|
||||||
suspend fun deleteUserSessions(userId: Int)
|
suspend fun deleteUserSessions(userId: Int)
|
||||||
|
suspend fun deleteUserSessions(userSessionCrossRefs: List<UserSessionCrossRef>)
|
||||||
}
|
}
|
243084
server/data.json
243084
server/data.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user