ои бронирования норм удаляются

This commit is contained in:
Татьяна Артамонова 2023-12-27 03:18:53 +04:00
parent 778ee2feac
commit 60fce778ed
11 changed files with 202 additions and 386 deletions

View File

@ -7,7 +7,6 @@ import androidx.paging.PagingSource
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import ru.ulstu.`is`.airticketrentservice.database.dao.TicketDao import ru.ulstu.`is`.airticketrentservice.database.dao.TicketDao
import ru.ulstu.`is`.airticketrentservice.database.models.Flight
import ru.ulstu.`is`.airticketrentservice.database.models.Ticket import ru.ulstu.`is`.airticketrentservice.database.models.Ticket
class OfflineTicketRepository(private val ticketDao: TicketDao) : TicketRepository { class OfflineTicketRepository(private val ticketDao: TicketDao) : TicketRepository {
@ -27,5 +26,5 @@ class OfflineTicketRepository(private val ticketDao: TicketDao) : TicketReposito
override suspend fun getFlightsTickets(flightId: Int): List<Ticket> = ticketDao.getFlightsTickets(flightId) override suspend fun getFlightsTickets(flightId: Int): List<Ticket> = ticketDao.getFlightsTickets(flightId)
suspend fun clearTickets() = ticketDao.deleteAll() suspend fun clearTickets() = ticketDao.deleteAll()
suspend fun insertTickets(tickets: List<Ticket>) = suspend fun insertTickets(tickets: List<Ticket>) =
ticketDao.insert(*tickets.toTypedArray())[0] ticketDao.insert(*tickets.toTypedArray())
} }

View File

@ -18,6 +18,7 @@ import ru.ulstu.`is`.airticketrentservice.screen.MyRents
import ru.ulstu.`is`.airticketrentservice.screen.Profile import ru.ulstu.`is`.airticketrentservice.screen.Profile
import ru.ulstu.`is`.airticketrentservice.screen.RentEdit import ru.ulstu.`is`.airticketrentservice.screen.RentEdit
import ru.ulstu.`is`.airticketrentservice.screen.RentList import ru.ulstu.`is`.airticketrentservice.screen.RentList
import ru.ulstu.`is`.airticketrentservice.screen.RentStatusEdit
import ru.ulstu.`is`.airticketrentservice.screen.TicketEdit import ru.ulstu.`is`.airticketrentservice.screen.TicketEdit
import ru.ulstu.`is`.airticketrentservice.screen.TicketList import ru.ulstu.`is`.airticketrentservice.screen.TicketList
import ru.ulstu.`is`.airticketrentservice.screen.TicketView import ru.ulstu.`is`.airticketrentservice.screen.TicketView
@ -109,7 +110,17 @@ fun HomeNavGraph(
} }
) )
){ ){
RentEdit(navController) RentEdit()
}
composable(
route = BottomBarScreen.RentStatusEdit.route,
arguments = listOf(
navArgument("id") {
type = NavType.IntType
}
)
){
RentStatusEdit(navController)
} }
composable( composable(
route = BottomBarScreen.FlightEdit.route, route = BottomBarScreen.FlightEdit.route,

View File

@ -112,6 +112,15 @@ sealed class BottomBarScreen(
return "rent-edit/$id" return "rent-edit/$id"
} }
} }
object RentStatusEdit: BottomBarScreen(
route = "rent-status-edit/{id}",
title ="",
icon = Icons.Filled.AccountCircle
) {
fun passId(id: String): String{
return "rent-status-edit/$id"
}
}
object TicketEdit: BottomBarScreen( object TicketEdit: BottomBarScreen(
route = "ticket-edit/{id}", route = "ticket-edit/{id}",
title ="", title ="",

View File

@ -1,38 +1,28 @@
package ru.ulstu.`is`.airticketrentservice.screen package ru.ulstu.`is`.airticketrentservice.screen
import android.annotation.SuppressLint
import android.util.Log import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize 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.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
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.Delete
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DismissDirection import androidx.compose.material3.DismissDirection
import androidx.compose.material3.DismissState import androidx.compose.material3.DismissState
import androidx.compose.material3.DismissValue import androidx.compose.material3.DismissValue
import androidx.compose.material3.DismissValue.DismissedToStart
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -40,38 +30,29 @@ import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberDismissState import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
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 kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.ulstu.`is`.airticketrentservice.database.models.Rent import ru.ulstu.`is`.airticketrentservice.database.models.Rent
import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider
import ru.ulstu.`is`.airticketrentservice.viewModel.CurrentUserViewModel import ru.ulstu.`is`.airticketrentservice.viewModel.CurrentUserViewModel
import ru.ulstu.`is`.airticketrentservice.viewModel.RentListViewModel
import ru.ulstu.`is`.airticketrentservice.R import ru.ulstu.`is`.airticketrentservice.R
import ru.ulstu.`is`.airticketrentservice.database.models.Flight
import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen
import ru.ulstu.`is`.airticketrentservice.viewModel.UsersRentsViewModel import ru.ulstu.`is`.airticketrentservice.viewModel.UsersRentsViewModel
@ -82,9 +63,11 @@ fun MyRents(
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory) currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
var userRentsUiState by remember { mutableStateOf(viewModel.userRentsUiState) }
val getUser by remember { mutableStateOf(currentUserViewModel.user) } SideEffect {
val userRentsUiState = viewModel.userRentsUiState userRentsUiState = viewModel.userRentsUiState
}
Log.d("RentListViewModel", "мои бронирования: ${userRentsUiState.rentList}") Log.d("RentListViewModel", "мои бронирования: ${userRentsUiState.rentList}")
Scaffold( Scaffold(
@ -101,67 +84,118 @@ fun MyRents(
onSwipe = { rent: Rent -> onSwipe = { rent: Rent ->
coroutineScope.launch { coroutineScope.launch {
viewModel.deleteRent(rent) viewModel.deleteRent(rent)
viewModel.refreshRents()
} }
} }
) )
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DismissBackground(dismissState: DismissState) {
val color = when (dismissState.dismissDirection) {
DismissDirection.StartToEnd -> Color.Transparent
DismissDirection.EndToStart -> Color(0xFFFF1744)
null -> Color.Transparent
}
val direction = dismissState.dismissDirection
Row(
modifier = Modifier
.fillMaxSize()
.background(color)
.padding(12.dp, 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
if (direction == DismissDirection.EndToStart) {
Icon(
Icons.Default.Delete,
contentDescription = "delete",
tint = Color.White
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun SwipeToDelete( private fun SwipeToDelete(
dismissState: DismissState, dismissState: DismissState,
rentList: MutableList<Rent>,
rent: Rent, rent: Rent,
onClick: (id: Int) -> Unit onClick: (id: Int) -> Unit
) { ) {
LaunchedEffect(dismissState.targetValue) {
if (dismissState.targetValue == DismissedToStart) {
rentList.remove(rent)
}
}
SwipeToDismiss( SwipeToDismiss(
modifier = Modifier.zIndex(1f),
state = dismissState, state = dismissState,
directions = setOf( directions = setOf(DismissDirection.EndToStart),
DismissDirection.EndToStart
),
background = { background = {
DismissBackground(dismissState) val backgroundColor by animateColorAsState(
when (dismissState.targetValue) {
DismissedToStart -> Color.Red.copy(alpha = 0.8f)
else -> Color.White
}, label = ""
)
val iconScale by animateFloatAsState(
targetValue = if (dismissState.targetValue == DismissedToStart) 1.3f else 0.5f,
label = ""
)
Box(
Modifier
.fillMaxSize()
.background(color = backgroundColor)
.padding(end = 16.dp),
contentAlignment = Alignment.CenterEnd
) {
Icon(
modifier = Modifier.scale(iconScale),
imageVector = Icons.Outlined.Delete,
contentDescription = "Delete",
tint = Color.White
)
}
}, },
dismissContent = { dismissContent = {
RentListItem(rent = rent, RentListItem(
rent = rent,
modifier = Modifier modifier = Modifier
.padding(vertical = 7.dp) .padding(vertical = 7.dp)
.clip(shape = RoundedCornerShape(15.dp)) .clip(shape = RoundedCornerShape(15.dp))
.clickable { onClick(rent.id) }) .clickable { onClick(rent.id) }
)
} }
) )
} }
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
//@OptIn(ExperimentalMaterial3Api::class)
//@Composable
//private fun SwipeToDelete(
// dismissState: DismissState,
// rent: Rent,
// onClick: (id: Int) -> Unit
//) {
// SwipeToDismiss(
// state = dismissState,
// directions = setOf(
// DismissDirection.EndToStart
// ),
// background = {
// val backgroundColor by animateColorAsState(
// when (dismissState.targetValue) {
// DismissedToStart -> Color.Red.copy(alpha = 0.8f)
// else -> Color.White
// }, label = ""
// )
// val iconScale by animateFloatAsState(
// targetValue = if (dismissState.targetValue == DismissedToStart) 1.3f else 0.5f,
// label = ""
// )
// Box(
// Modifier
// .fillMaxSize()
// .background(color = backgroundColor)
// .padding(end = 16.dp),
// contentAlignment = Alignment.CenterEnd
// ) {
// Icon(
// modifier = Modifier.scale(iconScale),
// imageVector = Icons.Outlined.Delete,
// contentDescription = "Delete",
// tint = Color.White
// )
// }
// },
// dismissContent = {
// RentListItem(rent = rent,
// modifier = Modifier
// .padding(vertical = 7.dp)
// .clip(shape = RoundedCornerShape(15.dp))
// .clickable { onClick(rent.id) })
// }
// )
//}
@SuppressLint("MutableCollectionMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun MyRents( private fun MyRents(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -191,6 +225,7 @@ private fun MyRents(
SwipeToDelete( SwipeToDelete(
dismissState = dismissState, dismissState = dismissState,
rentList = rentList.toMutableList(),
rent = rent, rent = rent,
onClick = onClick onClick = onClick
) )
@ -200,13 +235,15 @@ private fun MyRents(
} }
} }
@Composable @Composable
private fun RentListItem( private fun RentListItem(
modifier: Modifier = Modifier, rent: Rent modifier: Modifier = Modifier, rent: Rent
) { ) {
Card( Card(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
colors = CardDefaults.cardColors(colorResource(id = R.color.lightlightBlue))
) { ) {
Column( Column(
modifier = modifier.padding(all = 10.dp) modifier = modifier.padding(all = 10.dp)

View File

@ -170,7 +170,7 @@ fun Profile(
Button( Button(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(5.dp), .padding(top = 5.dp, bottom = 50.dp),
onClick = { onClick = {
navController.navigate(AuthScreen.Login.route) navController.navigate(AuthScreen.Login.route)
}, },
@ -179,7 +179,7 @@ fun Profile(
pressedElevation = 6.dp pressedElevation = 6.dp
), ),
shape = RoundedCornerShape(15.dp), shape = RoundedCornerShape(15.dp),
colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)), colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
content = { content = {
Text("Выйти") Text("Выйти")
} }

View File

@ -51,93 +51,27 @@ import ru.ulstu.`is`.airticketrentservice.viewModel.UsersListUiState
@SuppressLint("UnrememberedMutableState") @SuppressLint("UnrememberedMutableState")
@Composable @Composable
fun RentEdit( fun RentEdit(
navController: NavController,
viewModel: RentEditViewModel = viewModel(factory = AppViewModelProvider.Factory), viewModel: RentEditViewModel = viewModel(factory = AppViewModelProvider.Factory),
userViewModel: UserEditViewModel = viewModel(factory = AppViewModelProvider.Factory),
ticketViewModel: TicketEditViewModel = viewModel(factory = AppViewModelProvider.Factory) ticketViewModel: TicketEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
val coroutineScope = rememberCoroutineScope()
userViewModel.setCurrentUser(viewModel.rentUiState.rentDetails.userId)
ticketViewModel.setCurrentTicket(viewModel.rentUiState.rentDetails.ticketId) ticketViewModel.setCurrentTicket(viewModel.rentUiState.rentDetails.ticketId)
RentEdit( RentEdit(
rentUiState = viewModel.rentUiState, rentUiState = viewModel.rentUiState,
userUiState = userViewModel.userUiState, ticketUiState = ticketViewModel.ticketUiState
ticketUiState = ticketViewModel.ticketUiState,
onClick = {
coroutineScope.launch {
viewModel.saveRent()
navController.popBackStack()
}
},
onUpdate = viewModel::updateUiState
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun RentEdit( private fun RentEdit(
rentUiState: RentUiState, rentUiState: RentUiState,
userUiState: UserUiState, ticketUiState: TicketUiState
ticketUiState: TicketUiState,
onClick: () -> Unit,
onUpdate: (RentDetails) -> Unit
) { ) {
Column( Column(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(all = 10.dp) .padding(all = 10.dp)
) { ) {
TextField(
value = rentUiState.rentDetails.userId.toString(),
onValueChange = { onUpdate(rentUiState.rentDetails.copy(userId = it.toInt())) },
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.LightGray.copy(.2f),
unfocusedContainerColor = Color.LightGray.copy(.2f),
disabledContainerColor = Color.LightGray.copy(.2f),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
shape = RoundedCornerShape(15.dp),
label = {
Text("Номер пользователя")
}
)
TextField(
value = rentUiState.rentDetails.ticketId.toString(),
onValueChange = { onUpdate(rentUiState.rentDetails.copy(ticketId = it.toInt())) },
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.LightGray.copy(.2f),
unfocusedContainerColor = Color.LightGray.copy(.2f),
disabledContainerColor = Color.LightGray.copy(.2f),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
shape = RoundedCornerShape(15.dp),
label = {
Text("Номер билета")
}
)
TextField(
value = "${userUiState.userDetails.surname} ${userUiState.userDetails.name} ${userUiState.userDetails.patronymic}",
onValueChange = {},
readOnly = true,
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.LightGray.copy(.2f),
unfocusedContainerColor = Color.LightGray.copy(.2f),
disabledContainerColor = Color.LightGray.copy(.2f),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
shape = RoundedCornerShape(15.dp),
label = {
Text("Пользователь")
}
)
TextField( TextField(
value = "${ticketUiState.ticketDetails.ticket_cost}", value = "${ticketUiState.ticketDetails.ticket_cost}",
onValueChange = {}, onValueChange = {},
@ -155,7 +89,6 @@ private fun RentEdit(
Text("Стоимость билета") Text("Стоимость билета")
} }
) )
TextField( TextField(
value = "${ticketUiState.ticketDetails.passengers_count}", value = "${ticketUiState.ticketDetails.passengers_count}",
onValueChange = {}, onValueChange = {},
@ -173,108 +106,22 @@ private fun RentEdit(
Text("Количество пассажиров") Text("Количество пассажиров")
} }
) )
// TextField(
// TextField( value = rentUiState.rentDetails.status,
// value = "Ожидает подтверждения", onValueChange = {},
// onValueChange = { onUpdate(rentUiState.rentDetails.copy(status = it)) }, readOnly = true,
// readOnly = true, modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
// modifier = Modifier.fillMaxWidth(), colors = TextFieldDefaults.colors(
// colors = TextFieldDefaults.colors( focusedContainerColor = Color.LightGray.copy(.2f),
// focusedContainerColor = Color.LightGray.copy(.2f), unfocusedContainerColor = Color.LightGray.copy(.2f),
// unfocusedContainerColor = Color.LightGray.copy(.2f), disabledContainerColor = Color.LightGray.copy(.2f),
// disabledContainerColor = Color.LightGray.copy(.2f), focusedIndicatorColor = Color.Transparent,
// focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
// unfocusedIndicatorColor = Color.Transparent,
// ),
// shape = RoundedCornerShape(15.dp),
// label = {
// Text(stringResource(id = R.string.rent_status))
// }
// )
var expanded by remember { mutableStateOf(false) }
Box(
modifier = Modifier.fillMaxWidth().padding(all = 5.dp).clip(RoundedCornerShape(15.dp))
) {
ExposedDropdownMenuBox(
modifier = Modifier.fillMaxWidth(),
expanded = expanded,
onExpandedChange = { expanded = !expanded },
)
{
TextField(
value = rentUiState.rentDetails.status,
onValueChange = {},
readOnly = true,
trailingIcon = {
TrailingIcon(expanded = expanded)
},
modifier = Modifier.menuAnchor().fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.LightGray.copy(.2f),
unfocusedContainerColor = Color.LightGray.copy(.2f),
disabledContainerColor = Color.LightGray.copy(.2f),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
shape = RoundedCornerShape(15.dp),
label = {
Text(stringResource(id = R.string.rent_status))
}
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier
.background(Color.LightGray.copy(.2f))
.exposedDropdownSize()
.fillMaxWidth()
) {
DropdownMenuItem(
modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(15.dp)),
text = { Text("Подтверждено") },
onClick = {
onUpdate(rentUiState.rentDetails.copy(status = "Подтверждено"))
expanded = false
}
)
DropdownMenuItem(
modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(15.dp)),
text = { Text("Ожидает подтверждения") },
onClick = {
onUpdate(rentUiState.rentDetails.copy(status = "Ожидает подтверждения"))
expanded = false
}
)
DropdownMenuItem(
modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(15.dp)),
text = { Text("Отклонено") },
onClick = {
onUpdate(rentUiState.rentDetails.copy(status = "Отклонено"))
expanded = false
}
)
}
}
}
Button(
enabled = rentUiState.isEntryValid,
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = onClick,
elevation = ButtonDefaults.buttonElevation(
defaultElevation = 10.dp,
pressedElevation = 6.dp
), ),
shape = RoundedCornerShape(15.dp), shape = RoundedCornerShape(15.dp),
colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)), label = {
content = { Text(stringResource(id = R.string.rent_status))
Text(text = stringResource(R.string.rent_save_button))
} }
) )
} }
} }

View File

@ -50,6 +50,7 @@ import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
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.tooling.preview.Preview
@ -65,6 +66,7 @@ import androidx.paging.compose.itemKey
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.ulstu.`is`.airticketrentservice.R
import ru.ulstu.`is`.airticketrentservice.database.models.Rent import ru.ulstu.`is`.airticketrentservice.database.models.Rent
import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen
import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider
@ -85,17 +87,6 @@ fun RentList(
val rentListUiState = viewModel.rentListUiState.collectAsLazyPagingItems() val rentListUiState = viewModel.rentListUiState.collectAsLazyPagingItems()
Scaffold( Scaffold(
topBar = {},
floatingActionButton = {
FloatingActionButton(
onClick = {
val route = BottomBarScreen.RentEdit.passId(0.toString())
navController.navigate(route)
},
) {
Icon(Icons.Filled.Add, "Добавить")
}
}
) { innerPadding -> ) { innerPadding ->
RentList( RentList(
modifier = Modifier modifier = Modifier
@ -103,7 +94,7 @@ fun RentList(
.fillMaxSize(), .fillMaxSize(),
rentList = rentListUiState, rentList = rentListUiState,
onClick = { uid: Int -> onClick = { uid: Int ->
val route = BottomBarScreen.RentEdit.passId(uid.toString()) val route = BottomBarScreen.RentStatusEdit.passId(uid.toString())
navController.navigate(route) navController.navigate(route)
}, },
onSwipe = { rent: Rent -> onSwipe = { rent: Rent ->
@ -246,7 +237,8 @@ private fun RentListItem(
) { ) {
Card( Card(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
colors = CardDefaults.cardColors(colorResource(id = R.color.lightlightBlue))
) { ) {
Column( Column(
modifier = modifier.padding(all = 10.dp) modifier = modifier.padding(all = 10.dp)

View File

@ -1,15 +1,8 @@
package ru.ulstu.`is`.airticketrentservice.screen package ru.ulstu.`is`.airticketrentservice.screen
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -19,53 +12,31 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
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.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DismissDirection import androidx.compose.material3.DismissDirection
import androidx.compose.material3.DismissState import androidx.compose.material3.DismissState
import androidx.compose.material3.DismissValue
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.SwipeToDismiss import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberDismissState import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.colorResource
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.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
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 kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.ulstu.`is`.airticketrentservice.R
import ru.ulstu.`is`.airticketrentservice.database.models.User import ru.ulstu.`is`.airticketrentservice.database.models.User
import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen
import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider
@ -97,34 +68,6 @@ fun UserList(
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DismissBackground(dismissState: DismissState) {
val color = when (dismissState.dismissDirection) {
DismissDirection.StartToEnd -> Color.Transparent
DismissDirection.EndToStart -> Color(0xFFFF1744)
null -> Color.Transparent
}
val direction = dismissState.dismissDirection
Row(
modifier = Modifier
.fillMaxSize()
.background(color)
.padding(12.dp, 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
if (direction == DismissDirection.EndToStart) {
Icon(
Icons.Default.Delete,
contentDescription = "delete",
tint = Color.White
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun SwipeToDelete( private fun SwipeToDelete(
@ -135,12 +78,8 @@ private fun SwipeToDelete(
SwipeToDismiss( SwipeToDismiss(
modifier = Modifier.zIndex(1f), modifier = Modifier.zIndex(1f),
state = dismissState, state = dismissState,
directions = setOf( directions = setOf(),
DismissDirection.EndToStart background = {},
),
background = {
DismissBackground(dismissState)
},
dismissContent = { dismissContent = {
UserListItem(user = user, UserListItem(user = user,
modifier = Modifier modifier = Modifier
@ -173,11 +112,6 @@ private fun UserList(
val dismissState: DismissState = rememberDismissState( val dismissState: DismissState = rememberDismissState(
positionalThreshold = { 200.dp.toPx() } positionalThreshold = { 200.dp.toPx() }
) )
if (dismissState.isDismissed(direction = DismissDirection.EndToStart)) {
onSwipe(user)
}
SwipeToDelete( SwipeToDelete(
dismissState = dismissState, dismissState = dismissState,
user = user, user = user,
@ -195,7 +129,8 @@ private fun UserListItem(
) { ) {
Card( Card(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
colors = CardDefaults.cardColors(colorResource(id = R.color.lightlightBlue))
) { ) {
Column( Column(
modifier = modifier.padding(all = 10.dp) modifier = modifier.padding(all = 10.dp)

View File

@ -7,8 +7,13 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.ulstu.`is`.airticketrentservice.database.AppContainer
import ru.ulstu.`is`.airticketrentservice.database.AppDataContainer
import ru.ulstu.`is`.airticketrentservice.database.models.Rent import ru.ulstu.`is`.airticketrentservice.database.models.Rent
import ru.ulstu.`is`.airticketrentservice.database.repository.RentRepository import ru.ulstu.`is`.airticketrentservice.database.repository.RentRepository
import ru.ulstu.`is`.airticketrentservice.database.repository.UserRepository import ru.ulstu.`is`.airticketrentservice.database.repository.UserRepository
@ -18,7 +23,6 @@ class UsersRentsViewModel(
private val userRepository: UserRepository, private val userRepository: UserRepository,
private val rentRepository: RentRepository private val rentRepository: RentRepository
) : ViewModel() { ) : ViewModel() {
var userRentsUiState by mutableStateOf(UserRentsUiState()) var userRentsUiState by mutableStateOf(UserRentsUiState())
private set private set
@ -37,6 +41,17 @@ class UsersRentsViewModel(
} }
} }
fun refreshRents() {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val rents = userRepository.getUserRents(userUid)
launch(Dispatchers.Main) {
userRentsUiState = UserRentsUiState(rents)
}
}
}
}
suspend fun deleteRent(rent: Rent) { suspend fun deleteRent(rent: Rent) {
rentRepository.deleteRent(rent) rentRepository.deleteRent(rent)
} }

View File

@ -42,12 +42,6 @@
"flightId": 9, "flightId": 9,
"id": 7 "id": 7
}, },
{
"passengers_count": 6,
"ticket_cost": 106800,
"flightId": 9,
"id": 8
},
{ {
"passengers_count": 6, "passengers_count": 6,
"ticket_cost": 106800, "ticket_cost": 106800,
@ -131,6 +125,12 @@
"ticket_cost": 10000, "ticket_cost": 10000,
"flightId": 2, "flightId": 2,
"id": 22 "id": 22
},
{
"passengers_count": 6,
"ticket_cost": 6000,
"flightId": 2,
"id": 23
} }
], ],
"flights": [ "flights": [
@ -229,16 +229,6 @@
"role": "User", "role": "User",
"id": 4 "id": 4
}, },
{
"surname": "ыщылы",
"name": "шчшчгч",
"patronymic": "шчшчшч",
"date_of_birth": "10-12-2015",
"email": "aa@mail.ru",
"password": "aaa",
"role": "User",
"id": 5
},
{ {
"surname": "фффф", "surname": "фффф",
"name": "ффф", "name": "ффф",
@ -271,29 +261,23 @@
} }
], ],
"rents": [ "rents": [
{ {
"id": 1, "id": 1,
"status": "Ожидает подтверждения", "status": "Ожидает подтверждения",
"userId": 2, "userId": 2,
"ticketId": 1 "ticketId": 1
}, },
{ {
"id": 2, "id": 2,
"status": "Подтверждено", "status": "Ожидает подтверждения",
"userId": 2, "userId": 2,
"ticketId": 2 "ticketId": 2
}, },
{ {
"id": 3,
"status": "Ожидает подтверждения", "status": "Ожидает подтверждения",
"userId": 2, "userId": 2,
"ticketId": 21, "ticketId": 3
"id": 3
},
{
"status": "Ожидает подтверждения",
"userId": 2,
"ticketId": 22,
"id": 4
} }
] ]
} }

View File

@ -42,12 +42,6 @@
"flightId": 9, "flightId": 9,
"id": 7 "id": 7
}, },
{
"passengers_count": 6,
"ticket_cost": 106800,
"flightId": 9,
"id": 8
},
{ {
"passengers_count": 6, "passengers_count": 6,
"ticket_cost": 106800, "ticket_cost": 106800,
@ -125,6 +119,18 @@
"ticket_cost": 3000, "ticket_cost": 3000,
"flightId": 2, "flightId": 2,
"id": 21 "id": 21
},
{
"passengers_count": 10,
"ticket_cost": 10000,
"flightId": 2,
"id": 22
},
{
"passengers_count": 6,
"ticket_cost": 6000,
"flightId": 2,
"id": 23
} }
], ],
"flights": [ "flights": [
@ -201,7 +207,7 @@
"date_of_birth": "7-11-2003", "date_of_birth": "7-11-2003",
"email": "usertt@mail.ru", "email": "usertt@mail.ru",
"password": "usertt", "password": "usertt",
"role": "Admin" "role": "User"
}, },
{ {
"surname": "а", "surname": "а",
@ -223,16 +229,6 @@
"role": "User", "role": "User",
"id": 4 "id": 4
}, },
{
"surname": "ыщылы",
"name": "шчшчгч",
"patronymic": "шчшчшч",
"date_of_birth": "10-12-2015",
"email": "aa@mail.ru",
"password": "aaa",
"role": "User",
"id": 5
},
{ {
"surname": "фффф", "surname": "фффф",
"name": "ффф", "name": "ффф",
@ -252,26 +248,17 @@
"password": "kkk", "password": "kkk",
"role": "User", "role": "User",
"id": 7 "id": 7
},
{
"id": 8,
"surname": "Артамонова",
"name": "Татьяна",
"patronymic": "Валерьевна",
"date_of_birth": "7-11-2003",
"email": "admin@mail.ru",
"password": "admin",
"role": "Admin"
} }
], ],
"rents": [ "rents": []
{
"id": 1,
"status": "Ожидает подтверждения",
"userId": 2,
"ticketId": 1
},
{
"id": 2,
"status": "Подтверждено",
"userId": 2,
"ticketId": 2
},
{
"status": "Ожидает подтверждения",
"userId": 2,
"ticketId": 21,
"id": 3
}
]
} }