поиск и бронирования пользователя работают
This commit is contained in:
parent
f67c6d76be
commit
a270794281
@ -24,22 +24,22 @@ interface AppService {
|
||||
@GET("users")
|
||||
suspend fun getAllUsers(): List<UserRemote>
|
||||
@GET("rents")
|
||||
suspend fun getAllRents(): List<RentRemote>
|
||||
@GET("rents")
|
||||
suspend fun getRents(
|
||||
@Query("_page") page: Int,
|
||||
@Query("_limit") limit: Int,
|
||||
): List<RentRemote>
|
||||
@GET("searchFlights")
|
||||
suspend fun foundFlights(
|
||||
@GET("flights")
|
||||
suspend fun findFlights(
|
||||
@Query("direction_from") direction_from: String,
|
||||
@Query("direction_to") direction_to: String,
|
||||
@Query("departure_date") departure_date: String
|
||||
): List<FlightRemote>
|
||||
// suspend fun findFlights(
|
||||
// @Path("direction_from") from: String,
|
||||
// @Path("direction_to") to: String,
|
||||
// @Path("departure_date") departureDate: String
|
||||
// ): List<FlightRemote>
|
||||
@GET("tickets")
|
||||
suspend fun getAllTickets(): List<TicketRemote>
|
||||
|
||||
@GET("foundFlights")
|
||||
@GET("flights")
|
||||
suspend fun getAllFlights(): List<FlightRemote>
|
||||
@GET("tickets")
|
||||
suspend fun getTickets(
|
||||
@ -55,8 +55,8 @@ interface AppService {
|
||||
@GET("tickets")
|
||||
suspend fun getFlightsTickets(@Query("flightId") flightId: Int): List<TicketRemote>
|
||||
|
||||
@GET("userrents/{userId}")
|
||||
suspend fun getUserRents(@Path("userId") userId: Int): List<RentRemote>
|
||||
@GET("rents")
|
||||
suspend fun getUserRents(@Query("userId") userId: Int): List<RentRemote>
|
||||
|
||||
@GET("users/{id}")
|
||||
suspend fun getUser(
|
||||
@ -131,7 +131,7 @@ interface AppService {
|
||||
@Path("id") id: Int,
|
||||
): TicketRemote
|
||||
|
||||
companion object : AppService {
|
||||
companion object {
|
||||
private const val BASE_URL = "http://192.168.1.100:8079/"
|
||||
|
||||
@Volatile
|
||||
|
@ -9,6 +9,7 @@ import retrofit2.HttpException
|
||||
import ru.ulstu.`is`.airticketrentservice.api.AppService
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toRent
|
||||
import ru.ulstu.`is`.airticketrentservice.api.repository.RestTicketRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.api.repository.RestUserRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.database.AppDatabase
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.OfflineRemoteKeyRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.OfflineRentRepository
|
||||
@ -22,6 +23,7 @@ class RentRemoteMediator(
|
||||
private val service: AppService,
|
||||
private val dbRentRepository: OfflineRentRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val userRestRepository: RestUserRepository,
|
||||
private val ticketRestRepository: RestTicketRepository,
|
||||
private val database: AppDatabase
|
||||
) : RemoteMediator<Int, Rent>() {
|
||||
@ -71,8 +73,9 @@ class RentRemoteMediator(
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
userRestRepository.getAllUsers()
|
||||
ticketRestRepository.getAllTickets()
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
ticketRestRepository.getTickets()
|
||||
dbRentRepository.insertRents(rents)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
|
@ -9,6 +9,7 @@ import retrofit2.HttpException
|
||||
import ru.ulstu.`is`.airticketrentservice.api.AppService
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toTicket
|
||||
import ru.ulstu.`is`.airticketrentservice.api.repository.RestFlightRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.api.repository.RestUserRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.database.AppDatabase
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.RemoteKeyType
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.RemoteKeys
|
||||
@ -71,7 +72,7 @@ class TicketRemoteMediator(
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
flightRestRepository.getFlights()
|
||||
flightRestRepository.getAllFlights()
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
dbTicketRepository.insertTickets(tickets)
|
||||
}
|
||||
|
@ -35,21 +35,3 @@ fun Flight.toFlightRemote(): FlightRemote = FlightRemote(
|
||||
tickets_count,
|
||||
one_ticket_cost
|
||||
)
|
||||
|
||||
fun foundFlights(
|
||||
from: String,
|
||||
to: String,
|
||||
departureDate: String
|
||||
): List<Flight> {
|
||||
val json = File("C:\\Users\\User\\AndroidStudioProjects\\AirTicketRentService\\server").readText()
|
||||
|
||||
val flights = Json.decodeFromString<List<Flight>>(json)
|
||||
|
||||
val matchingFlights = flights.filter { flight ->
|
||||
flight.direction_from == from ||
|
||||
flight.direction_to == to ||
|
||||
flight.departure_date == departureDate
|
||||
}
|
||||
|
||||
return matchingFlights
|
||||
}
|
@ -61,26 +61,61 @@ class RestFlightRepository(
|
||||
override suspend fun getFlightById(flightId: Int): Flight =
|
||||
service.getFlight(flightId).toFlight()
|
||||
|
||||
override suspend fun foundFlights(
|
||||
// override suspend fun findFlights(
|
||||
// from: String,
|
||||
// to: String,
|
||||
// departureDate: String
|
||||
// ): List<Flight> {
|
||||
// val existFlights = dbFlightRepository.getAllFlights().associateBy { it.id }.toMutableMap()
|
||||
//
|
||||
// service.findFlights(from, to, departureDate)
|
||||
// .map { it.toFlight() }
|
||||
// .forEach { flight ->
|
||||
// existFlights[flight.id] = flight
|
||||
// }
|
||||
// return existFlights.map { it.value }.sortedBy { it.id }
|
||||
// }
|
||||
|
||||
override suspend fun findFlights(
|
||||
from: String,
|
||||
to: String,
|
||||
departureDate: String
|
||||
): List<Flight> {
|
||||
return try {
|
||||
val foundFlights = service.findFlights(from, to, departureDate)
|
||||
if (foundFlights.isNotEmpty()) {
|
||||
foundFlights.map { it.toFlight() }
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.message?.let { Log.d(RestFlightRepository::class.simpleName, it) }
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAllFlights(): List<Flight> {
|
||||
Log.d(RestFlightRepository::class.simpleName, "Get all flights")
|
||||
|
||||
val existFlights = dbFlightRepository.getAllFlights().associateBy { it.id }.toMutableMap()
|
||||
|
||||
service.foundFlights()
|
||||
service.getAllFlights()
|
||||
.map { it.toFlight() }
|
||||
.forEach { flight ->
|
||||
flight.direction_from == from ||
|
||||
flight.direction_to == to ||
|
||||
flight.departure_date == departureDate
|
||||
val existFlight = existFlights[flight.id]
|
||||
if (existFlight == null) {
|
||||
dbFlightRepository.insertFlight(flight)
|
||||
} else if (existFlight != flight) {
|
||||
dbFlightRepository.updateFlight(flight)
|
||||
}
|
||||
existFlights[flight.id] = flight
|
||||
}
|
||||
|
||||
return existFlights.map { it.value }.sortedBy { it.id }
|
||||
|
||||
}
|
||||
// flight.direction_from == from ||
|
||||
// flight.direction_to == to ||
|
||||
// flight.departure_date == departureDate
|
||||
|
||||
// override suspend fun findFlights(
|
||||
// from: String,
|
||||
|
@ -21,6 +21,7 @@ class RestRentRepository(
|
||||
private val service: AppService,
|
||||
private val dbRentRepository: OfflineRentRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val userRestRepository: RestUserRepository,
|
||||
private val ticketRestRepository: RestTicketRepository,
|
||||
private val database: AppDatabase
|
||||
) : RentRepository {
|
||||
@ -39,6 +40,7 @@ class RestRentRepository(
|
||||
service,
|
||||
dbRentRepository,
|
||||
dbRemoteKeyRepository,
|
||||
userRestRepository,
|
||||
ticketRestRepository,
|
||||
database
|
||||
),
|
||||
@ -61,21 +63,21 @@ class RestRentRepository(
|
||||
rent.id.let { service.deleteRent(it).toRent() }
|
||||
}
|
||||
|
||||
// override suspend fun getAllRents(): List<Rent> {
|
||||
// val existRents = dbRentRepository.getAllRents().associateBy { it.id }.toMutableMap()
|
||||
//
|
||||
// service.getAllRents()
|
||||
// .map { it.toRent() }
|
||||
// .forEach { rent ->
|
||||
// val existRent = existRents[rent.id]
|
||||
// if (existRent == null) {
|
||||
// dbRentRepository.insertRent(rent)
|
||||
// } else if (existRent != rent) {
|
||||
// dbRentRepository.updateRent(rent)
|
||||
// }
|
||||
// existRents[rent.id] = rent
|
||||
// }
|
||||
//
|
||||
// return existRents.map { it.value }.sortedBy { it.id }
|
||||
// }
|
||||
override suspend fun getAllRents(): List<Rent> {
|
||||
val existRents = dbRentRepository.getAllRents().associateBy { it.id }.toMutableMap()
|
||||
|
||||
service.getAllRents()
|
||||
.map { it.toRent() }
|
||||
.forEach { rent ->
|
||||
val existRent = existRents[rent.id]
|
||||
if (existRent == null) {
|
||||
dbRentRepository.insertRent(rent)
|
||||
} else if (existRent != rent) {
|
||||
dbRentRepository.updateRent(rent)
|
||||
}
|
||||
existRents[rent.id] = rent
|
||||
}
|
||||
|
||||
return existRents.map { it.value }.sortedBy { it.id }
|
||||
}
|
||||
}
|
@ -2,9 +2,11 @@ package ru.ulstu.`is`.airticketrentservice.api.repository
|
||||
|
||||
import android.util.Log
|
||||
import ru.ulstu.`is`.airticketrentservice.api.AppService
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toFlight
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toRent
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toUser
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toUserRemote
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Flight
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.User
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.OfflineRentRepository
|
||||
@ -56,26 +58,40 @@ class RestUserRepository(
|
||||
return existUsers.map { it.value }.sortedBy { it.id }
|
||||
}
|
||||
|
||||
override suspend fun getUserRents(id: Int): List<Rent> {
|
||||
Log.d(RestUserRepository::class.simpleName, "Get users $id rents")
|
||||
val existRents = dbUserRepository.getUserRents(id).associateBy { it.id }.toMutableMap()
|
||||
// override suspend fun getUserRents(userId: Int): List<Rent> {
|
||||
// Log.d(RestUserRepository::class.simpleName, "Get user's $userId rents")
|
||||
// val existRents = dbUserRepository.getUserRents(userId).associateBy { it.id }.toMutableMap()
|
||||
//
|
||||
// service.getUserRents(userId)
|
||||
// .map { it.toRent() }
|
||||
// .forEach { rent ->
|
||||
// Log.d(RestUserRepository::class.simpleName, "айди брони: ${rent.id}, и пользователя: ${rent.userId}")
|
||||
// if(rent.userId == userId) {
|
||||
//// val existRent = existRents[rent.id]
|
||||
//// if (existRent == null) {
|
||||
//// Log.d(RestUserRepository::class.simpleName, "бронирования нет в бд")
|
||||
//// dbRentRepository.insertRent(rent)
|
||||
//// } else if (existRent != rent) {
|
||||
//// Log.d(RestUserRepository::class.simpleName, "бронирование есть в бд")
|
||||
//// dbRentRepository.updateRent(rent)
|
||||
//// }
|
||||
// existRents[rent.id] = rent
|
||||
// }
|
||||
// }
|
||||
// return existRents.map { it.value }.sortedBy { it.id }
|
||||
// }
|
||||
|
||||
service.getUserRents(id)
|
||||
.map { it.toRent() }
|
||||
.forEach { rent ->
|
||||
Log.d(RestUserRepository::class.simpleName, "айди брони: ${rent.id}, и пользователя: ${rent.userId}")
|
||||
if(rent.userId == id) {
|
||||
val existRent = existRents[rent.id]
|
||||
if (existRent == null) {
|
||||
Log.d(RestUserRepository::class.simpleName, "бронирования нет в бд")
|
||||
dbRentRepository.insertRent(rent)
|
||||
} else if (existRent != rent) {
|
||||
Log.d(RestUserRepository::class.simpleName, "бронирование есть в бд")
|
||||
dbRentRepository.updateRent(rent)
|
||||
override suspend fun getUserRents(userId: Int): List<Rent> {
|
||||
return try {
|
||||
val usersRents = service.getUserRents(userId)
|
||||
if (usersRents.isNotEmpty()) {
|
||||
usersRents.map { it.toRent() }
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
existRents[rent.id] = rent
|
||||
} catch (e: Exception) {
|
||||
e.message?.let { Log.d(RestUserRepository::class.simpleName, it) }
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
return existRents.map { it.value }.sortedBy { it.id }
|
||||
}
|
||||
}
|
@ -68,6 +68,7 @@ class AppDataContainer(private val context: Context) : AppContainer {
|
||||
AppService.getInstance(),
|
||||
rentRepository,
|
||||
remoteKeyRepository,
|
||||
userRestRepository,
|
||||
ticketRestRepository,
|
||||
AppDatabase.getInstance(context)
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun remoteKeysDao(): RemoteKeysDao
|
||||
|
||||
companion object {
|
||||
private const val DB_NAME: String = "ticketservicedatabase"
|
||||
private const val DB_NAME: String = "ticketservicedatabase5"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: AppDatabase? = null
|
||||
|
@ -12,7 +12,7 @@ import ru.ulstu.`is`.airticketrentservice.database.models.Flight
|
||||
@Dao
|
||||
interface FlightDao {
|
||||
@Query("select * from flights")
|
||||
fun getAll(): List<Flight>
|
||||
suspend fun getAll(): List<Flight>
|
||||
|
||||
@Query("select * from flights where flights.id = :flightId")
|
||||
fun getFlightById(flightId: Int): Flow<Flight>
|
||||
|
@ -11,8 +11,8 @@ import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
|
||||
@Dao
|
||||
interface RentDao {
|
||||
// @Query("select * from rents")
|
||||
// fun getAll(): List<Rent>
|
||||
@Query("select * from rents")
|
||||
fun getAll(): List<Rent>
|
||||
|
||||
@Query("select * from rents where rents.id = :rentId")
|
||||
fun getRentById(rentId: Int): Flow<Rent>
|
||||
|
@ -3,6 +3,7 @@ package ru.ulstu.`is`.airticketrentservice.database.models
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "rents",
|
||||
@ -11,14 +12,17 @@ import androidx.room.PrimaryKey
|
||||
entity = User::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["user_id"],
|
||||
onDelete = ForeignKey.RESTRICT,
|
||||
onUpdate = ForeignKey.RESTRICT),
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
onUpdate = ForeignKey.CASCADE),
|
||||
ForeignKey(
|
||||
entity = Ticket::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["ticket_id"],
|
||||
onDelete = ForeignKey.RESTRICT,
|
||||
onUpdate = ForeignKey.RESTRICT)
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
onUpdate = ForeignKey.CASCADE)
|
||||
],
|
||||
indices = [
|
||||
Index(value = ["ticket_id"], unique = true)
|
||||
])
|
||||
data class Rent(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
|
@ -3,6 +3,7 @@ package ru.ulstu.`is`.airticketrentservice.database.models
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "tickets",
|
||||
|
@ -5,10 +5,11 @@ import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Flight
|
||||
|
||||
interface FlightRepository {
|
||||
suspend fun getAllFlights(): List<Flight>
|
||||
suspend fun insertFlight(flight: Flight)
|
||||
suspend fun updateFlight(flight: Flight)
|
||||
suspend fun deleteFlight(flight: Flight)
|
||||
suspend fun getFlightById(flightId: Int): Flight
|
||||
suspend fun foundFlights(from: String, to: String, departureDate: String): List<Flight>
|
||||
suspend fun findFlights(from: String, to: String, departureDate: String): List<Flight>
|
||||
fun getFlights(): Flow<PagingData<Flight>>
|
||||
}
|
@ -11,7 +11,7 @@ import ru.ulstu.`is`.airticketrentservice.database.models.Flight
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
|
||||
class OfflineFlightRepository(private val flightDao: FlightDao) : FlightRepository{
|
||||
suspend fun getAllFlights(): List<Flight> = flightDao.getAll()
|
||||
override suspend fun getAllFlights(): List<Flight> = flightDao.getAll()
|
||||
override suspend fun insertFlight(flight: Flight) = flightDao.insert(flight)
|
||||
override suspend fun updateFlight(flight: Flight) = flightDao.update(flight)
|
||||
override suspend fun deleteFlight(flight: Flight) = flightDao.delete(flight)
|
||||
@ -25,7 +25,7 @@ class OfflineFlightRepository(private val flightDao: FlightDao) : FlightReposito
|
||||
).flow
|
||||
|
||||
fun getAllFlightsPagingSource(): PagingSource<Int, Flight> = flightDao.getFlights()
|
||||
override suspend fun foundFlights(from: String, to: String, departureDate: String): List<Flight> = flightDao.findFlights(from, to, departureDate)
|
||||
override suspend fun findFlights(from: String, to: String, departureDate: String): List<Flight> = flightDao.findFlights(from, to, departureDate)
|
||||
suspend fun clearFlights() = flightDao.deleteAll()
|
||||
suspend fun insertFlights(flights: List<Flight>) =
|
||||
flightDao.insert(*flights.toTypedArray())
|
||||
|
@ -14,7 +14,7 @@ class OfflineRentRepository(private val rentDao: RentDao) : RentRepository{
|
||||
override suspend fun insertRent(rent: Rent) = rentDao.insert(rent)
|
||||
override suspend fun updateRent(rent: Rent) = rentDao.update(rent)
|
||||
override suspend fun deleteRent(rent: Rent) = rentDao.delete(rent)
|
||||
// override suspend fun getAllRents(): List<Rent> = rentDao.getAll()
|
||||
override suspend fun getAllRents(): List<Rent> = rentDao.getAll()
|
||||
override suspend fun getRentById(rentId: Int): Rent = rentDao.getRentById(rentId).first()
|
||||
override fun getRents(): Flow<PagingData<Rent>> = Pager(
|
||||
config = PagingConfig(
|
||||
|
@ -9,7 +9,7 @@ interface RentRepository {
|
||||
suspend fun insertRent(rent: Rent)
|
||||
suspend fun updateRent(rent: Rent)
|
||||
suspend fun deleteRent(rent: Rent)
|
||||
// suspend fun getAllRents(): List<Rent>
|
||||
suspend fun getAllRents(): List<Rent>
|
||||
suspend fun getRentById(rentId: Int): Rent
|
||||
fun getRents(): Flow<PagingData<Rent>>
|
||||
}
|
@ -9,5 +9,5 @@ interface UserRepository {
|
||||
suspend fun deleteUser(user: User)
|
||||
suspend fun getAllUsers(): List<User>
|
||||
suspend fun getUserById(userId: Int): User
|
||||
suspend fun getUserRents(id: Int): List<Rent>
|
||||
suspend fun getUserRents(userId: Int): List<Rent>
|
||||
}
|
@ -10,6 +10,7 @@ import androidx.navigation.navArgument
|
||||
import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.Admin
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.FlightEdit
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.FlightInfo
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.FlightList
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.FoundFlights
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.MainPage
|
||||
@ -18,6 +19,8 @@ import ru.ulstu.`is`.airticketrentservice.screen.Profile
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.RentEdit
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.RentList
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.TicketEdit
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.TicketList
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.TicketView
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.UserEdit
|
||||
import ru.ulstu.`is`.airticketrentservice.screen.UserList
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider
|
||||
@ -61,12 +64,17 @@ fun HomeNavGraph(
|
||||
composable(
|
||||
route = BottomBarScreen.UserList.route
|
||||
){
|
||||
UserList(navController)
|
||||
UserList(navController, userListViewModel)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.TicketList.route
|
||||
){
|
||||
TicketList(navController, flightListViewModel, ticketListViewModel)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.RentList.route
|
||||
){
|
||||
RentList(navController, rentListViewModel, ticketListViewModel)
|
||||
RentList(navController, userListViewModel, currentUserViewModel, ticketListViewModel, rentListViewModel)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.Admin.route
|
||||
@ -113,6 +121,16 @@ fun HomeNavGraph(
|
||||
){
|
||||
FlightEdit(navController)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.FlightInfo.route,
|
||||
arguments = listOf(
|
||||
navArgument("id") {
|
||||
type = NavType.IntType
|
||||
}
|
||||
)
|
||||
){
|
||||
FlightInfo(navController)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.MyRents.route,
|
||||
arguments = listOf(
|
||||
@ -131,5 +149,13 @@ fun HomeNavGraph(
|
||||
) {
|
||||
TicketEdit(navController)
|
||||
}
|
||||
composable(
|
||||
route = BottomBarScreen.TicketView.route,
|
||||
arguments = listOf(
|
||||
navArgument("id") { type = NavType.IntType }
|
||||
)
|
||||
) {
|
||||
TicketView(navController)
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import ru.ulstu.`is`.airticketrentservice.viewModel.FlightListViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.LoginViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.RegistrationViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.RentListViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.TicketListViewModel
|
||||
//import ru.ulstu.`is`.airticketrentservice.viewModel.TicketEditViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.UserListViewModel
|
||||
|
||||
@ -22,11 +23,12 @@ const val USERID_ARGUMENT="userId"
|
||||
@Composable
|
||||
fun RootNavigationGraph(
|
||||
navController: NavHostController,
|
||||
userListViewModel: UserListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
registrationViewModel: RegistrationViewModel= viewModel(factory = AppViewModelProvider.Factory),
|
||||
loginViewModel: LoginViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
flightListViewModel: FlightListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
userListViewModel: UserListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
ticketListViewModel: TicketListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
rentListViewModel: RentListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
){
|
||||
NavHost(
|
||||
@ -43,6 +45,7 @@ fun RootNavigationGraph(
|
||||
currentUserViewModel = currentUserViewModel,
|
||||
flightListViewModel = flightListViewModel,
|
||||
userListViewModel = userListViewModel,
|
||||
ticketListViewModel = ticketListViewModel,
|
||||
rentListViewModel = rentListViewModel
|
||||
)
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ sealed class BottomBarScreen(
|
||||
title ="",
|
||||
icon = Icons.Filled.AccountCircle
|
||||
)
|
||||
object TicketList: BottomBarScreen(
|
||||
route = "ticket-list",
|
||||
title ="",
|
||||
icon = Icons.Filled.AccountCircle
|
||||
)
|
||||
object RentList: BottomBarScreen(
|
||||
route = "rent-list",
|
||||
title ="",
|
||||
@ -80,6 +85,15 @@ sealed class BottomBarScreen(
|
||||
return "flight-edit/$id"
|
||||
}
|
||||
}
|
||||
object TicketView: BottomBarScreen(
|
||||
route = "ticket-view/{id}",
|
||||
title ="",
|
||||
icon = Icons.Filled.AccountCircle
|
||||
) {
|
||||
fun passId(id: String): String{
|
||||
return "ticket-view/$id"
|
||||
}
|
||||
}
|
||||
object FlightInfo: BottomBarScreen(
|
||||
route = "flight-info/{id}",
|
||||
title ="",
|
||||
|
@ -79,5 +79,22 @@ fun Admin (
|
||||
) {
|
||||
Text("Бронирования")
|
||||
}
|
||||
Button(
|
||||
onClick = { navController.navigate(BottomBarScreen.TicketList.route)},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = (colorResource(id = R.color.lightBlue)),
|
||||
contentColor = Color.White
|
||||
),
|
||||
elevation = ButtonDefaults.buttonElevation(
|
||||
defaultElevation = 10.dp,
|
||||
pressedElevation = 6.dp
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp),
|
||||
) {
|
||||
Text("Билеты")
|
||||
}
|
||||
}
|
||||
}
|
@ -40,12 +40,14 @@ import java.util.Date
|
||||
@Composable
|
||||
fun FlightInfo(
|
||||
navController: NavController,
|
||||
flightViewModel: FlightEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
flightViewModel: FlightEditViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
ticketViewModel: TicketEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
FlightInfo(
|
||||
flightUiState = flightViewModel.flightUiState,
|
||||
onClick = {
|
||||
val route = BottomBarScreen.TicketEdit.passId(0.toString())
|
||||
flightViewModel.setCurrentFlight(ticketViewModel.ticketUiState.ticketDetails.flightId)
|
||||
val route = BottomBarScreen.TicketView.passId(0.toString())
|
||||
navController.navigate(route)
|
||||
}
|
||||
)
|
||||
@ -78,7 +80,8 @@ private fun FlightInfo(
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_from)) },
|
||||
singleLine = true
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
@ -93,12 +96,43 @@ private fun FlightInfo(
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_to)) },
|
||||
singleLine = true
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
|
||||
Text(text = " ${flightUiState.flightDetails.departure_date}", fontSize = 15.sp, color = Color.DarkGray)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = flightUiState.flightDetails.departure_date,
|
||||
onValueChange = { },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_arrivalDate)) },
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
|
||||
Text(text = flightUiState.flightDetails.arrival_date, fontSize = 15.sp, color = Color.DarkGray)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = flightUiState.flightDetails.arrival_date,
|
||||
onValueChange = { },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_departureDate)) },
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
@ -113,7 +147,8 @@ private fun FlightInfo(
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text("Количество билетов") },
|
||||
singleLine = true
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
|
||||
TextField(
|
||||
@ -129,7 +164,8 @@ private fun FlightInfo(
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text("Стоимость одного билета") },
|
||||
singleLine = true
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
Button(
|
||||
onClick = onClick,
|
||||
|
@ -46,7 +46,7 @@ fun FoundFlights(
|
||||
navController: NavController,
|
||||
viewModel: FindFlightsViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val foundFlightsUiState = viewModel.foundFlightsList
|
||||
val foundFlightsUiState = viewModel.foundFlightsUiState
|
||||
|
||||
Scaffold(
|
||||
topBar = {}
|
||||
@ -55,7 +55,7 @@ fun FoundFlights(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
flightList = foundFlightsUiState,
|
||||
flightList = foundFlightsUiState.flightList,
|
||||
onClick = { uid: Int ->
|
||||
val route = BottomBarScreen.FlightInfo.passId(uid.toString())
|
||||
navController.navigate(route)
|
||||
|
@ -54,7 +54,6 @@ fun Profile(
|
||||
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val getUser by remember { mutableStateOf(currentUserViewModel.user) }
|
||||
val userUiState = getUser?.toUiState(true)
|
||||
Log.d("CurrentUserViewModel1", "Текущий пользователь: $getUser")
|
||||
val state = rememberScrollState()
|
||||
LaunchedEffect(Unit) { state.animateScrollTo(100) }
|
||||
@ -150,40 +149,40 @@ fun Profile(
|
||||
Text("Изменить")
|
||||
}
|
||||
)
|
||||
// Button(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .padding(5.dp),
|
||||
// onClick = {
|
||||
// val route = BottomBarScreen.MyRents.passId(getUser?.id.toString())
|
||||
// navController.navigate(route)
|
||||
// },
|
||||
// elevation = ButtonDefaults.buttonElevation(
|
||||
// defaultElevation = 10.dp,
|
||||
// pressedElevation = 6.dp
|
||||
// ),
|
||||
// shape = RoundedCornerShape(15.dp),
|
||||
// colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)),
|
||||
// content = {
|
||||
// Text("Мои бронирования")
|
||||
// }
|
||||
// )
|
||||
// Button(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .padding(5.dp),
|
||||
// onClick = {
|
||||
// navController.navigate(AuthScreen.Login.route)
|
||||
// },
|
||||
// elevation = ButtonDefaults.buttonElevation(
|
||||
// defaultElevation = 10.dp,
|
||||
// pressedElevation = 6.dp
|
||||
// ),
|
||||
// shape = RoundedCornerShape(15.dp),
|
||||
// colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)),
|
||||
// content = {
|
||||
// Text("Выйти")
|
||||
// }
|
||||
// )
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(5.dp),
|
||||
onClick = {
|
||||
val route = BottomBarScreen.MyRents.passId(getUser?.id.toString())
|
||||
navController.navigate(route)
|
||||
},
|
||||
elevation = ButtonDefaults.buttonElevation(
|
||||
defaultElevation = 10.dp,
|
||||
pressedElevation = 6.dp
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)),
|
||||
content = {
|
||||
Text("Мои бронирования")
|
||||
}
|
||||
)
|
||||
Button(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(5.dp),
|
||||
onClick = {
|
||||
navController.navigate(AuthScreen.Login.route)
|
||||
},
|
||||
elevation = ButtonDefaults.buttonElevation(
|
||||
defaultElevation = 10.dp,
|
||||
pressedElevation = 6.dp
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)),
|
||||
content = {
|
||||
Text("Выйти")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -88,11 +88,43 @@ private fun RentEdit(
|
||||
.fillMaxWidth()
|
||||
.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(),
|
||||
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
|
||||
colors = TextFieldDefaults.colors(
|
||||
focusedContainerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedContainerColor = Color.LightGray.copy(.2f),
|
||||
@ -110,7 +142,7 @@ private fun RentEdit(
|
||||
value = "${ticketUiState.ticketDetails.ticket_cost}",
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
|
||||
colors = TextFieldDefaults.colors(
|
||||
focusedContainerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedContainerColor = Color.LightGray.copy(.2f),
|
||||
@ -128,7 +160,7 @@ private fun RentEdit(
|
||||
value = "${ticketUiState.ticketDetails.passengers_count}",
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.fillMaxWidth().padding(all = 5.dp),
|
||||
colors = TextFieldDefaults.colors(
|
||||
focusedContainerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedContainerColor = Color.LightGray.copy(.2f),
|
||||
@ -141,44 +173,12 @@ private fun RentEdit(
|
||||
Text("Количество пассажиров")
|
||||
}
|
||||
)
|
||||
|
||||
TextField(
|
||||
value = "Ожидает подтверждения",
|
||||
onValueChange = { onUpdate(rentUiState.rentDetails.copy(status = it)) },
|
||||
readOnly = true,
|
||||
modifier = Modifier.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))
|
||||
}
|
||||
)
|
||||
|
||||
// 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 = {},
|
||||
// value = "Ожидает подтверждения",
|
||||
// onValueChange = { onUpdate(rentUiState.rentDetails.copy(status = it)) },
|
||||
// readOnly = true,
|
||||
// trailingIcon = {
|
||||
// TrailingIcon(expanded = expanded)
|
||||
// },
|
||||
// modifier = Modifier.menuAnchor().fillMaxWidth(),
|
||||
// modifier = Modifier.fillMaxWidth(),
|
||||
// colors = TextFieldDefaults.colors(
|
||||
// focusedContainerColor = Color.LightGray.copy(.2f),
|
||||
// unfocusedContainerColor = Color.LightGray.copy(.2f),
|
||||
@ -191,41 +191,73 @@ private fun RentEdit(
|
||||
// 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
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
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,
|
||||
|
@ -68,14 +68,18 @@ import kotlinx.coroutines.launch
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
import ru.ulstu.`is`.airticketrentservice.navigation.BottomBarScreen
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.AppViewModelProvider
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.CurrentUserViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.RentListViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.TicketListViewModel
|
||||
import ru.ulstu.`is`.airticketrentservice.viewModel.UserListViewModel
|
||||
|
||||
@Composable
|
||||
fun RentList(
|
||||
navController: NavController,
|
||||
viewModel: RentListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
ticketListViewModel: TicketListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
userListViewModel: UserListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
ticketListViewModel: TicketListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
viewModel: RentListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val rentListUiState = viewModel.rentListUiState.collectAsLazyPagingItems()
|
||||
|
@ -38,13 +38,14 @@ fun TicketEdit(
|
||||
flightViewModel: FlightEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
flightViewModel.setCurrentFlight(viewModel.ticketUiState.ticketDetails.flightId)
|
||||
TicketEdit(
|
||||
ticketUiState = viewModel.ticketUiState,
|
||||
flightUiState = flightViewModel.flightUiState,
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
viewModel.saveTicket()
|
||||
navController.navigate(BottomBarScreen.RentEdit.passId(0.toString()))
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
onUpdate = viewModel::updateUiState,
|
||||
@ -70,6 +71,21 @@ private fun TicketEdit(
|
||||
.padding(vertical = 32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = ticketUiState.ticketDetails.flightId.toString(),
|
||||
onValueChange = { onUpdate(ticketUiState.ticketDetails.copy(flightId = it.toInt())) },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text("Номер рейса") },
|
||||
singleLine = true
|
||||
)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@ -106,33 +122,16 @@ private fun TicketEdit(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = flightUiState.flightDetails.departure_date,
|
||||
onValueChange = {},
|
||||
value = ticketUiState.ticketDetails.passengers_count.toString(),
|
||||
onValueChange = { onUpdate(ticketUiState.ticketDetails.copy(passengers_count = it.toInt())) },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_arrivalDate)) },
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = flightUiState.flightDetails.arrival_date,
|
||||
onValueChange = {},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text(stringResource(id = R.string.ticket_departureDate)) },
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
label = { Text("Количество пассажиров") },
|
||||
singleLine = true
|
||||
)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
@ -150,21 +149,6 @@ private fun TicketEdit(
|
||||
singleLine = true,
|
||||
readOnly = true
|
||||
)
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp),
|
||||
value = ticketUiState.ticketDetails.passengers_count.toString(),
|
||||
onValueChange = { onUpdate(ticketUiState.ticketDetails.copy(passengers_count = it.toInt())) },
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
containerColor = Color.LightGray.copy(.2f),
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent
|
||||
),
|
||||
shape = RoundedCornerShape(15.dp),
|
||||
label = { Text("Количество пассажиров") },
|
||||
singleLine = true
|
||||
)
|
||||
// TextField(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
@ -192,7 +176,7 @@ private fun TicketEdit(
|
||||
colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.lightBlue)),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = "Забронировать")
|
||||
Text(text = "Сохранить")
|
||||
}
|
||||
}
|
||||
}
|
@ -51,7 +51,6 @@ fun UserEdit(
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
viewModel.saveUser()
|
||||
currentUserViewModel.user = viewModel.userUiState.user
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
|
@ -6,11 +6,13 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.ulstu.`is`.airticketrentservice.api.AppService
|
||||
import ru.ulstu.`is`.airticketrentservice.api.model.toFlight
|
||||
import ru.ulstu.`is`.airticketrentservice.database.AppContainer
|
||||
@ -19,30 +21,29 @@ import ru.ulstu.`is`.airticketrentservice.database.repository.FlightRepository
|
||||
|
||||
class FindFlightsViewModel(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val flightRepository: FlightRepository,
|
||||
|
||||
private val flightRepository: FlightRepository
|
||||
) : ViewModel() {
|
||||
private val from: String = checkNotNull(savedStateHandle["direction_from"])
|
||||
private val to: String = checkNotNull(savedStateHandle["direction_to"])
|
||||
private val departureDate: String = checkNotNull(savedStateHandle["departure_date"])
|
||||
// private val appService: AppService
|
||||
// get() {
|
||||
// return AppService
|
||||
// }
|
||||
var foundFlightsList: List<Flight> by mutableStateOf(emptyList())
|
||||
private set
|
||||
|
||||
|
||||
|
||||
var foundFlightsUiState by mutableStateOf(FoundFlightsUiState())
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
//foundFlightsList = appService.foundFlights().map { it.toFlight() }
|
||||
foundFlightsUiState = FoundFlightsUiState(flightRepository.foundFlights(from, to, departureDate))
|
||||
withContext(Dispatchers.IO) {
|
||||
val flights = flightRepository.findFlights(from, to, departureDate)
|
||||
launch(Dispatchers.Main) {
|
||||
foundFlightsUiState = FoundFlightsUiState(flights)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class FoundFlightsUiState(val flightList: List<Flight> = listOf())
|
||||
|
||||
// var foundFlightsList: List<Flight> by mutableStateOf(emptyList())
|
||||
// private set
|
||||
|
||||
|
||||
//foundFlightsList = appService.foundFlights().map { it.toFlight() }
|
||||
|
@ -17,6 +17,9 @@ class FlightEditViewModel(
|
||||
private val flightRepository: FlightRepository
|
||||
) : ViewModel() {
|
||||
|
||||
var flightsListUiState by mutableStateOf(FlightsListUiState())
|
||||
private set
|
||||
|
||||
var flightUiState by mutableStateOf(FlightUiState())
|
||||
private set
|
||||
|
||||
@ -25,16 +28,23 @@ class FlightEditViewModel(
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if (flightUid > 0) {
|
||||
flightsListUiState = FlightsListUiState(flightRepository.getAllFlights())
|
||||
flightUiState = flightRepository.getFlightById(flightUid)
|
||||
.toUiState(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentFlight(flightId: Int) {
|
||||
val flight: Flight? = flightsListUiState.flightList.firstOrNull { flight -> flight.id == flightId }
|
||||
flight?.let { updateUiState(it.toDetails()) }
|
||||
}
|
||||
|
||||
fun updateUiState(flightDetails: FlightDetails) {
|
||||
flightUiState = FlightUiState(
|
||||
flightDetails = flightDetails,
|
||||
isEntryValid = validateInput(flightDetails)
|
||||
isEntryValid = validateInput(flightDetails),
|
||||
flight = flightDetails.toFlight()
|
||||
)
|
||||
}
|
||||
|
||||
@ -66,7 +76,8 @@ class FlightEditViewModel(
|
||||
|
||||
data class FlightUiState(
|
||||
val flightDetails: FlightDetails = FlightDetails(),
|
||||
val isEntryValid: Boolean = false
|
||||
val isEntryValid: Boolean = false,
|
||||
val flight: Flight? = null
|
||||
)
|
||||
|
||||
data class FlightDetails(
|
||||
@ -102,3 +113,6 @@ fun Flight.toUiState(isEntryValid: Boolean = false): FlightUiState = FlightUiSta
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
data class FlightsListUiState(val flightList: List<Flight> = listOf())
|
||||
|
||||
|
||||
|
@ -12,28 +12,8 @@ class FlightListViewModel(
|
||||
private val flightRepository: FlightRepository
|
||||
): ViewModel() {
|
||||
|
||||
//val foundFlightsUiState: Flow<PagingData<Flight>> = flightRepository.findPagingFlights(from, to, departureDate)
|
||||
var flightsListUiState: Flow<PagingData<Flight>> = flightRepository.getFlights()
|
||||
|
||||
// val flightListUiState: StateFlow<FlightListUiState> = flightRepository.getAllFlights().map {
|
||||
// FlightListUiState(it)
|
||||
// }.stateIn(
|
||||
// scope = viewModelScope,
|
||||
// started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppContainer.TIMEOUT),
|
||||
// initialValue = FlightListUiState()
|
||||
// )
|
||||
|
||||
|
||||
// val _searchResults = MutableStateFlow<PagingData<Flight>>(PagingData.empty())
|
||||
// val searchResults: MutableStateFlow<PagingData<Flight>> = _searchResults
|
||||
//
|
||||
// fun searchFlights(from: String, to: String, departureDate: String) {
|
||||
// viewModelScope.launch {
|
||||
// val results = flightRepository.findPagingFlights(from, to, departureDate).single()
|
||||
// _searchResults.value = results
|
||||
// }
|
||||
// }
|
||||
|
||||
fun deleteFlight(flight: Flight) = viewModelScope.launch {
|
||||
flightRepository.deleteFlight(flight)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.RentRepository
|
||||
|
||||
@ -23,9 +24,15 @@ class RentEditViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if (rentUid > 0) {
|
||||
rentUiState = rentRepository.getRentById(rentUid)
|
||||
withContext(Dispatchers.IO) {
|
||||
val rent = rentRepository.getRentById(rentUid)
|
||||
.toUiState(true)
|
||||
launch(Dispatchers.Main) {
|
||||
if (rentUid > 0) {
|
||||
rentUiState = rent
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Ticket
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.TicketRepository
|
||||
|
||||
@ -25,30 +27,41 @@ class TicketEditViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
ticketsListUiState = TicketsListUiState(ticketRepository.getAllTickets())
|
||||
if (ticketUid > 0) {
|
||||
ticketUiState = ticketRepository.getTicketById(ticketUid)
|
||||
withContext(Dispatchers.IO) {
|
||||
val tickets = ticketRepository.getAllTickets()
|
||||
val ticket = ticketRepository.getTicketById(ticketUid)
|
||||
.toUiState(true)
|
||||
launch(Dispatchers.Main) {
|
||||
if (ticketUid > 0) {
|
||||
ticketsListUiState = TicketsListUiState(tickets)
|
||||
ticketUiState = ticket
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// init {
|
||||
// viewModelScope.launch {
|
||||
// if (ticketUid > 0) {
|
||||
// ticketsListUiState = TicketsListUiState(ticketRepository.getAllTickets())
|
||||
// ticketUiState = ticketRepository.getTicketById(ticketUid)
|
||||
// .toUiState(true)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fun setCurrentTicket(ticketId: Int) {
|
||||
val ticket: Ticket? =
|
||||
ticketsListUiState.ticketList.firstOrNull { ticket -> ticket.id == ticketId }
|
||||
ticket?.let { updateTicketUiState(it) }
|
||||
}
|
||||
|
||||
fun updateTicketUiState(ticket: Ticket) {
|
||||
ticketUiState = TicketUiState(
|
||||
ticket = ticket
|
||||
)
|
||||
ticket?.let { updateUiState(it.toDetails()) }
|
||||
}
|
||||
|
||||
fun updateUiState(ticketDetails: TicketDetails) {
|
||||
ticketUiState = TicketUiState(
|
||||
ticketDetails = ticketDetails,
|
||||
isEntryValid = validateInput(ticketDetails)
|
||||
isEntryValid = validateInput(ticketDetails),
|
||||
ticket = ticketDetails.toTicket()
|
||||
)
|
||||
}
|
||||
|
||||
@ -84,7 +97,7 @@ data class TicketUiState(
|
||||
data class TicketDetails(
|
||||
val passengers_count: Int = 0,
|
||||
var ticket_cost: Double = 0.0,
|
||||
var flightId: Int = 0,
|
||||
var flightId: Int = 0
|
||||
)
|
||||
|
||||
fun TicketDetails.toTicket(uid: Int = 0): Ticket = Ticket(
|
||||
|
@ -10,23 +10,11 @@ import kotlinx.coroutines.launch
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Ticket
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.TicketRepository
|
||||
|
||||
class TicketListViewModel(private val ticketRepository: TicketRepository): ViewModel() {
|
||||
val ticketListUiState: Flow<PagingData<Ticket>> = ticketRepository.getTickets()
|
||||
class TicketListViewModel(
|
||||
private val ticketRepository: TicketRepository
|
||||
): ViewModel() {
|
||||
|
||||
// private var userId: Int = 0
|
||||
// fun setUserId(userId: Int) {
|
||||
// this.userId = userId
|
||||
// }
|
||||
// var userRentsUiState by mutableStateOf(UserRentsUiState())
|
||||
// private set
|
||||
//
|
||||
// init {
|
||||
// viewModelScope.launch {
|
||||
// if (userId > 0) {
|
||||
// userRentsUiState = UserRentsUiState(userRepository.getUserRents(userId))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
val ticketListUiState: Flow<PagingData<Ticket>> = ticketRepository.getTickets()
|
||||
|
||||
suspend fun deleteTicket(ticket: Ticket) {
|
||||
ticketRepository.deleteTicket(ticket)
|
||||
|
@ -27,8 +27,8 @@ class UserEditViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
usersListUiState = UsersListUiState(userRepository.getAllUsers())
|
||||
if (userUid > 0) {
|
||||
usersListUiState = UsersListUiState(userRepository.getAllUsers())
|
||||
userUiState = userRepository.getUserById(userUid)
|
||||
.toUiState(true)!!
|
||||
}
|
||||
@ -38,19 +38,14 @@ class UserEditViewModel(
|
||||
fun setCurrentUser(userId: Int) {
|
||||
val user: User? =
|
||||
usersListUiState.userList.firstOrNull { user -> user.id == userId }
|
||||
user?.let { updateUserUiState(it) }
|
||||
}
|
||||
|
||||
fun updateUserUiState(user: User) {
|
||||
userUiState = UserUiState(
|
||||
user = user
|
||||
)
|
||||
user?.let { it.toDetails()?.let { it1 -> updateUiState(it1) } }
|
||||
}
|
||||
|
||||
fun updateUiState(userDetails: UserDetails) {
|
||||
userUiState = UserUiState(
|
||||
userDetails = userDetails,
|
||||
isEntryValid = validateInput(userDetails)
|
||||
isEntryValid = validateInput(userDetails),
|
||||
user = userDetails.toUser()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,9 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.ulstu.`is`.airticketrentservice.database.models.Rent
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.RentRepository
|
||||
import ru.ulstu.`is`.airticketrentservice.database.repository.UserRepository
|
||||
@ -24,8 +26,13 @@ class UsersRentsViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val rents = userRepository.getUserRents(userUid)
|
||||
launch(Dispatchers.Main) {
|
||||
if (userUid > 0) {
|
||||
userRentsUiState = UserRentsUiState(userRepository.getUserRents(userUid))
|
||||
userRentsUiState = UserRentsUiState(rents)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,17 @@
|
||||
{
|
||||
"id": 1,
|
||||
"passengers_count": 1,
|
||||
"ticket_cost": 1000,
|
||||
"flightId": 2
|
||||
"ticket_cost": 2680,
|
||||
"flightId": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"passengers_count": 1,
|
||||
"ticket_cost": 2435,
|
||||
"flightId": 5
|
||||
}
|
||||
],
|
||||
"searchFlights": [
|
||||
"flights": [
|
||||
{
|
||||
"id": 2,
|
||||
"direction_from": "a",
|
||||
@ -34,9 +40,7 @@
|
||||
"arrival_date": "26-12-2023",
|
||||
"tickets_count": 50,
|
||||
"one_ticket_cost": 2680
|
||||
}
|
||||
],
|
||||
"flights": [
|
||||
},
|
||||
{
|
||||
"direction_from": "Хабаровск",
|
||||
"direction_to": "Кострома ",
|
||||
@ -79,7 +83,7 @@
|
||||
"id": 2,
|
||||
"surname": "Артамонова",
|
||||
"name": "Татьяна",
|
||||
"patronymic": "Валерьевна",
|
||||
"patronymic": "Валерьевн",
|
||||
"date_of_birth": "7-11-2003",
|
||||
"email": "usertt@mail.ru",
|
||||
"password": "usertt",
|
||||
@ -142,6 +146,12 @@
|
||||
"status": "Ожидает подтверждения",
|
||||
"userId": 2,
|
||||
"ticketId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"status": "Подтверждено",
|
||||
"userId": 2,
|
||||
"ticketId": 2
|
||||
}
|
||||
]
|
||||
}
|
@ -3,11 +3,17 @@
|
||||
{
|
||||
"id": 1,
|
||||
"passengers_count": 1,
|
||||
"ticket_cost": 1000,
|
||||
"flightId": 2
|
||||
"ticket_cost": 2680,
|
||||
"flightId": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"passengers_count": 1,
|
||||
"ticket_cost": 2435,
|
||||
"flightId": 5
|
||||
}
|
||||
],
|
||||
"foundFlights": [
|
||||
"flights": [
|
||||
{
|
||||
"id": 2,
|
||||
"direction_from": "a",
|
||||
@ -34,9 +40,7 @@
|
||||
"arrival_date": "26-12-2023",
|
||||
"tickets_count": 50,
|
||||
"one_ticket_cost": 2680
|
||||
}
|
||||
],
|
||||
"flights": [
|
||||
},
|
||||
{
|
||||
"direction_from": "Хабаровск",
|
||||
"direction_to": "Кострома ",
|
||||
@ -142,6 +146,12 @@
|
||||
"status": "Ожидает подтверждения",
|
||||
"userId": 2,
|
||||
"ticketId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"status": "Подтверждено",
|
||||
"userId": 2,
|
||||
"ticketId": 2
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user