From 7af968a96ac9b7d8723f42452d0eaee46af641e2 Mon Sep 17 00:00:00 2001 From: VictoriaPresnyakova Date: Sun, 17 Dec 2023 21:47:25 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BB=D0=B0=D0=B1=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 9 ++ .../com/example/androidlabs/AppContainer.kt | 4 + .../example/androidlabs/AppDataContainer.kt | 26 ++++- .../com/example/androidlabs/DB/AppDatabase.kt | 14 ++- .../example/androidlabs/DB/dao/HotelDao.kt | 8 +- .../androidlabs/DB/dao/RemoteKeysDao.kt | 19 ++++ .../example/androidlabs/DB/models/Order.kt | 4 +- .../androidlabs/DB/models/PhotoManager.kt | 2 +- .../androidlabs/DB/models/RemoteKeys.kt | 22 ++++ .../com/example/androidlabs/DB/models/User.kt | 2 +- .../androidlabs/DB/repository/HotelRepImpl.kt | 22 ++-- .../DB/repository/HotelRepository.kt | 4 +- .../androidlabs/DB/repository/OrderRepImpl.kt | 34 +++--- .../DB/repository/OrderRepository.kt | 9 +- .../DB/repository/RemoteKeyRepository.kt | 10 ++ .../DB/repository/RemoteKeysRepositoryImpl.kt | 16 +++ .../androidlabs/DB/repository/UserRepImpl.kt | 24 ++-- .../DB/repository/UserRepository.kt | 4 +- .../DB/viewModels/HotelViewModel.kt | 2 +- .../DB/viewModels/OrderViewModel.kt | 11 +- .../DB/viewModels/UserViewModel.kt | 17 ++- .../MyOrderScreen/MyOrderScreen.kt | 24 +++- .../androidlabs/MyOrderScreen/OrderCard.kt | 23 +++- .../androidlabs/Navigation/NavController.kt | 5 +- .../androidlabs/adminPanel/AdminPanel.kt | 2 +- .../example/androidlabs/api/BackendService.kt | 105 ++++++++++++++++++ .../androidlabs/api/HotelRemoteMediator.kt | 104 +++++++++++++++++ .../androidlabs/api/model/HotelRemote.kt | 36 ++++++ .../androidlabs/api/model/OrderRemote.kt | 39 +++++++ .../androidlabs/api/model/UserRemote.kt | 41 +++++++ .../androidlabs/api/model/UserRemoteSignIn.kt | 9 ++ .../api/repository/RestHotelRepository.kt | 60 ++++++++++ .../api/repository/RestOrderRepository.kt | 32 ++++++ .../api/repository/RestUserRepository.kt | 25 +++++ .../androidlabs/booking/BookingScreen.kt | 4 +- 35 files changed, 681 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/com/example/androidlabs/DB/dao/RemoteKeysDao.kt create mode 100644 app/src/main/java/com/example/androidlabs/DB/models/RemoteKeys.kt create mode 100644 app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeyRepository.kt create mode 100644 app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeysRepositoryImpl.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/BackendService.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/HotelRemoteMediator.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/model/HotelRemote.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/model/OrderRemote.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/model/UserRemote.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/model/UserRemoteSignIn.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/repository/RestHotelRepository.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/repository/RestOrderRepository.kt create mode 100644 app/src/main/java/com/example/androidlabs/api/repository/RestUserRepository.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d3dd81e..ad3911f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id ("kotlin-kapt") + kotlin("plugin.serialization") version "1.4.21" } android { @@ -87,4 +88,12 @@ dependencies { //Paging implementation ("androidx.paging:paging-compose:3.2.1") implementation ("androidx.paging:paging-runtime:3.2.1") + + // retrofit + val retrofitVersion = "2.9.0" + implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") + implementation("com.squareup.okhttp3:logging-interceptor:4.11.0") + implementation("androidx.paging:paging-compose:3.2.1") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") + implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/AppContainer.kt b/app/src/main/java/com/example/androidlabs/AppContainer.kt index b5b0cda..4d62536 100644 --- a/app/src/main/java/com/example/androidlabs/AppContainer.kt +++ b/app/src/main/java/com/example/androidlabs/AppContainer.kt @@ -8,4 +8,8 @@ interface AppContainer { val hotelRepo: HotelRepository val userRepo: UserRepository val orderRepo: OrderRepository + companion object { + const val TIMEOUT = 5000L + const val LIMIT = 10 + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/AppDataContainer.kt b/app/src/main/java/com/example/androidlabs/AppDataContainer.kt index c9f7ed0..8559605 100644 --- a/app/src/main/java/com/example/androidlabs/AppDataContainer.kt +++ b/app/src/main/java/com/example/androidlabs/AppDataContainer.kt @@ -1,22 +1,38 @@ package com.example.androidlabs +import RestUserRepository import android.content.Context import com.example.androidlabs.DB.AppDatabase import com.example.androidlabs.DB.repository.HotelRepImpl import com.example.androidlabs.DB.repository.HotelRepository -import com.example.androidlabs.DB.repository.OrderRepImpl import com.example.androidlabs.DB.repository.OrderRepository -import com.example.androidlabs.DB.repository.UserRepImpl +import com.example.androidlabs.DB.repository.RemoteKeysRepositoryImpl import com.example.androidlabs.DB.repository.UserRepository +import com.example.androidlabs.api.BackendService +import com.example.androidlabs.api.repository.RestHotelRepository +import com.example.androidlabs.api.repository.RestOrderRepository + class AppDataContainer(private val context: Context) : AppContainer { override val hotelRepo: HotelRepository by lazy { - HotelRepImpl(AppDatabase.getInstance(context).hotelDao()) + RestHotelRepository( + BackendService.getInstance(), + hotelRepository, + AppDatabase.getInstance(context), + remoteKeyRepository + ) } override val userRepo: UserRepository by lazy { - UserRepImpl(AppDatabase.getInstance(context).userDao()) + RestUserRepository(BackendService.getInstance()) } + override val orderRepo: OrderRepository by lazy { - OrderRepImpl(AppDatabase.getInstance(context).orderDao()) + RestOrderRepository(BackendService.getInstance()) + } + private val hotelRepository: HotelRepImpl by lazy { + HotelRepImpl(AppDatabase.getInstance(context).hotelDao()) + } + private val remoteKeyRepository: RemoteKeysRepositoryImpl by lazy { + RemoteKeysRepositoryImpl(AppDatabase.getInstance(context).remoteKeysDao()) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/AppDatabase.kt b/app/src/main/java/com/example/androidlabs/DB/AppDatabase.kt index 1fa2823..af36372 100644 --- a/app/src/main/java/com/example/androidlabs/DB/AppDatabase.kt +++ b/app/src/main/java/com/example/androidlabs/DB/AppDatabase.kt @@ -7,21 +7,25 @@ import androidx.room.RoomDatabase import androidx.sqlite.db.SupportSQLiteDatabase import com.example.androidlabs.DB.dao.HotelDao import com.example.androidlabs.DB.dao.OrderDao +import com.example.androidlabs.DB.dao.RemoteKeysDao import com.example.androidlabs.DB.dao.UserDao import com.example.androidlabs.DB.models.Hotel import com.example.androidlabs.DB.models.Order +import com.example.androidlabs.DB.models.RemoteKeys import com.example.androidlabs.DB.models.RoleEnum import com.example.androidlabs.DB.models.User import com.example.androidlabs.R import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch - -@Database(entities = [Hotel::class, User::class, Order::class], version = 5) +// TODO +@Database(entities = [Hotel::class, User::class, Order::class, RemoteKeys::class], version = 5) abstract class AppDatabase : RoomDatabase() { abstract fun hotelDao(): HotelDao abstract fun userDao(): UserDao abstract fun orderDao(): OrderDao + abstract fun remoteKeysDao(): RemoteKeysDao + companion object { private const val DB_NAME: String = "my-db" @@ -33,9 +37,9 @@ abstract class AppDatabase : RoomDatabase() { INSTANCE?.let { database -> // User val userDao = database.userDao() - val user1 = User(null, "Artem", "Emelyanov", "artem@mail.ru", "123", RoleEnum.User) - val user2 = User(null, "Danil", "Markov", "danil@mail.ru", "123", RoleEnum.User) - val user3 = User(null, "Viktoria", "Presnyakova", "vika@mail.ru", "123", RoleEnum.Admin) + val user1 = User(null, "Artem", "Emelyanov", "artem@mail.ru", "123", "USER") + val user2 = User(null, "Danil", "Markov", "danil@mail.ru", "123", "ADMIN") + val user3 = User(null, "Viktoria", "Presnyakova", "vika@mail.ru", "123", "USER") userDao.createUser(user1) userDao.createUser(user2) userDao.createUser(user3) diff --git a/app/src/main/java/com/example/androidlabs/DB/dao/HotelDao.kt b/app/src/main/java/com/example/androidlabs/DB/dao/HotelDao.kt index 0f067e0..8d98905 100644 --- a/app/src/main/java/com/example/androidlabs/DB/dao/HotelDao.kt +++ b/app/src/main/java/com/example/androidlabs/DB/dao/HotelDao.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface HotelDao { @Insert - suspend fun insert(hotel: Hotel) + suspend fun insert(vararg hotel: Hotel) @Update suspend fun update(hotel: Hotel) @@ -24,4 +24,10 @@ interface HotelDao { @Query("SELECT * FROM Hotel WHERE hotelId = :id") suspend fun getHotelById(id: Int): Hotel + + @Query("select * from Hotel") + fun getAll(): PagingSource + + @Query("DELETE FROM Hotel") + suspend fun deleteAll() } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/dao/RemoteKeysDao.kt b/app/src/main/java/com/example/androidlabs/DB/dao/RemoteKeysDao.kt new file mode 100644 index 0000000..d50a2f3 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/DB/dao/RemoteKeysDao.kt @@ -0,0 +1,19 @@ +package com.example.androidlabs.DB.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.androidlabs.DB.models.RemoteKeyType +import com.example.androidlabs.DB.models.RemoteKeys + + +@Dao +interface RemoteKeysDao { + @Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type") + suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys? + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(remoteKey: List) + @Query("DELETE FROM remote_keys WHERE type = :type") + suspend fun clearRemoteKeys(type: RemoteKeyType) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/models/Order.kt b/app/src/main/java/com/example/androidlabs/DB/models/Order.kt index 2238468..8195474 100644 --- a/app/src/main/java/com/example/androidlabs/DB/models/Order.kt +++ b/app/src/main/java/com/example/androidlabs/DB/models/Order.kt @@ -21,6 +21,6 @@ data class Order( val creatorUserId: Int, @ColumnInfo(name = "BookedHotelId") val bookedHotelId: Int, - @Embedded - val hotel: Hotel +// @Embedded +// val hotel: Hotel ) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/models/PhotoManager.kt b/app/src/main/java/com/example/androidlabs/DB/models/PhotoManager.kt index c531a14..3c3a67c 100644 --- a/app/src/main/java/com/example/androidlabs/DB/models/PhotoManager.kt +++ b/app/src/main/java/com/example/androidlabs/DB/models/PhotoManager.kt @@ -2,7 +2,7 @@ package com.example.androidlabs.DB.models import com.example.androidlabs.R -class PhotoManager { +class PhotoManager { private val photos = listOf( R.drawable.img, R.drawable.img_1, diff --git a/app/src/main/java/com/example/androidlabs/DB/models/RemoteKeys.kt b/app/src/main/java/com/example/androidlabs/DB/models/RemoteKeys.kt new file mode 100644 index 0000000..d623595 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/DB/models/RemoteKeys.kt @@ -0,0 +1,22 @@ +package com.example.androidlabs.DB.models + +import androidx.room.Entity +import androidx.room.PrimaryKey +import androidx.room.TypeConverter +import androidx.room.TypeConverters + +enum class RemoteKeyType(private val type: String) { + SNEAKER(Hotel::class.simpleName ?: "Hotel"); + @TypeConverter + fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value } + @TypeConverter + fun fromRemoteKeyType(value: RemoteKeyType) = value.type +} +@Entity(tableName = "remote_keys") +data class RemoteKeys( + @PrimaryKey val entityId: Int, + @TypeConverters(RemoteKeyType::class) + val type: RemoteKeyType, + val prevKey: Int?, + val nextKey: Int? +) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/models/User.kt b/app/src/main/java/com/example/androidlabs/DB/models/User.kt index c2a58c5..cf8ba0e 100644 --- a/app/src/main/java/com/example/androidlabs/DB/models/User.kt +++ b/app/src/main/java/com/example/androidlabs/DB/models/User.kt @@ -17,7 +17,7 @@ data class User( @ColumnInfo(name = "Password") val password: String, @ColumnInfo(name = "Role") - val role: RoleEnum, + val role: String, @ColumnInfo(name = "Photo") val photo: Int? = null, ) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepImpl.kt b/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepImpl.kt index cabba75..a34d211 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepImpl.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepImpl.kt @@ -6,6 +6,7 @@ import androidx.paging.PagingData import com.example.androidlabs.DB.dao.HotelDao import com.example.androidlabs.DB.models.Hotel import androidx.paging.PagingSource +import com.example.androidlabs.AppContainer import kotlinx.coroutines.flow.Flow @@ -18,12 +19,17 @@ class HotelRepImpl (private val hotelDao: HotelDao) : HotelRepository { override suspend fun deleteHotel(hotel: Hotel) = hotelDao.delete(hotel) override suspend fun getHotelById(id: Int): Hotel = hotelDao.getHotelById(id) - override fun getAllHotelsPaged(): PagingSource = hotelDao.getAllHotelsPaged() - override fun call(): Flow> { - return Pager( - PagingConfig(pageSize = 5) - ) { - hotelDao.getAllHotelsPaged() - }.flow - } + override fun getAllHotels(): Flow> = Pager( + config = PagingConfig( + pageSize = AppContainer.LIMIT, + enablePlaceholders = false + ), + pagingSourceFactory = hotelDao::getAll + ).flow + + suspend fun clearHotels() = hotelDao.deleteAll() + suspend fun insertHotels(hotels: List) = + hotelDao.insert(*hotels.toTypedArray()) + + fun getAllHotelsPagingSource(): PagingSource = hotelDao.getAll() } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepository.kt b/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepository.kt index f895cd8..ebb3fd2 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepository.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/HotelRepository.kt @@ -9,6 +9,6 @@ interface HotelRepository { suspend fun updateHotel(hotel: Hotel) suspend fun deleteHotel(hotel: Hotel) suspend fun getHotelById(id: Int): Hotel - fun getAllHotelsPaged(): PagingSource - fun call(): Flow> + fun getAllHotels(): Flow> + } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepImpl.kt b/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepImpl.kt index 3bfa70d..42cc1c1 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepImpl.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepImpl.kt @@ -1,17 +1,17 @@ -package com.example.androidlabs.DB.repository - -import com.example.androidlabs.DB.dao.OrderDao -import com.example.androidlabs.DB.models.Order -import com.example.androidlabs.DB.models.UserWithOrder -import kotlinx.coroutines.flow.Flow - -class OrderRepImpl (private val orderDao: OrderDao) : OrderRepository { - - override suspend fun createOrder(order: Order): Long = orderDao.createOrder(order) - - override suspend fun delete(order: Order) = orderDao.delete(order) - - override fun getAllOrder(): Flow> = orderDao.getAllOrder() - - override fun getUserOrders(id: Int): Flow = orderDao.getUserOrders(id) -} \ No newline at end of file +//package com.example.androidlabs.DB.repository +// +//import com.example.androidlabs.DB.dao.OrderDao +//import com.example.androidlabs.DB.models.Order +//import com.example.androidlabs.DB.models.UserWithOrder +//import kotlinx.coroutines.flow.Flow +// +//class OrderRepImpl (private val orderDao: OrderDao) : OrderRepository { +// +// override suspend fun createOrder(order: Order): Long = orderDao.createOrder(order) +// +// override suspend fun delete(order: Order) = orderDao.delete(order) +// +// override fun getAllOrder(): Flow> = orderDao.getAllOrder() +// +// override fun getUserOrders(id: Int): Flow = orderDao.getUserOrders(id) +//} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepository.kt b/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepository.kt index 2fba881..77b7dae 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepository.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/OrderRepository.kt @@ -1,12 +1,15 @@ package com.example.androidlabs.DB.repository +import com.example.androidlabs.DB.models.Hotel import com.example.androidlabs.DB.models.Order import com.example.androidlabs.DB.models.UserWithOrder import kotlinx.coroutines.flow.Flow interface OrderRepository { suspend fun createOrder(order: Order): Long - suspend fun delete(order: Order) - fun getAllOrder(): Flow> - fun getUserOrders(id: Int) : Flow + suspend fun delete(orderId: Int) + //fun getAllOrder(): Flow> + suspend fun getHotelFromOrder(id: Int): Hotel + + suspend fun getUserOrders(id: Int) : Flow> } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeyRepository.kt b/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeyRepository.kt new file mode 100644 index 0000000..305619f --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeyRepository.kt @@ -0,0 +1,10 @@ +package com.example.androidlabs.DB.repository + +import com.example.androidlabs.DB.models.RemoteKeyType +import com.example.androidlabs.DB.models.RemoteKeys + +interface RemoteKeyRepository { + suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys? + suspend fun createRemoteKeys(remoteKeys: List) + suspend fun deleteRemoteKey(type: RemoteKeyType) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeysRepositoryImpl.kt b/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeysRepositoryImpl.kt new file mode 100644 index 0000000..67d2c0f --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/DB/repository/RemoteKeysRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.example.androidlabs.DB.repository + +import com.example.androidlabs.DB.dao.RemoteKeysDao +import com.example.androidlabs.DB.models.RemoteKeyType +import com.example.androidlabs.DB.models.RemoteKeys + +class RemoteKeysRepositoryImpl(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository { + override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) = + remoteKeysDao.getRemoteKeys(id, type) + + override suspend fun createRemoteKeys(remoteKeys: List) = + remoteKeysDao.insertAll(remoteKeys) + + override suspend fun deleteRemoteKey(type: RemoteKeyType) = + remoteKeysDao.clearRemoteKeys(type) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/UserRepImpl.kt b/app/src/main/java/com/example/androidlabs/DB/repository/UserRepImpl.kt index b454b26..406f865 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/UserRepImpl.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/UserRepImpl.kt @@ -3,15 +3,15 @@ package com.example.androidlabs.DB.repository import com.example.androidlabs.DB.dao.UserDao import com.example.androidlabs.DB.models.User -class UserRepImpl(private val userDao: UserDao) : UserRepository { - - override suspend fun createUser(user: User) = userDao.createUser(user) - - override suspend fun updateUser(user: User) = userDao.updateUser(user) - - override suspend fun deleteUser(user: User) = userDao.deleteUser(user) - - override suspend fun getUserById(id: Int): User = userDao.getUserById(id) - - override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email) -} \ No newline at end of file +//class UserRepImpl(private val userDao: UserDao) : UserRepository { +// +// override suspend fun createUser(user: User) = userDao.createUser(user) +// +// override suspend fun updateUser(user: User) = userDao.updateUser(user) +// +// override suspend fun deleteUser(user: User) = userDao.deleteUser(user) +// +// override suspend fun getUserById(id: Int): User = userDao.getUserById(id) +// +// override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email) +//} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/repository/UserRepository.kt b/app/src/main/java/com/example/androidlabs/DB/repository/UserRepository.kt index af8a992..8df9e19 100644 --- a/app/src/main/java/com/example/androidlabs/DB/repository/UserRepository.kt +++ b/app/src/main/java/com/example/androidlabs/DB/repository/UserRepository.kt @@ -1,11 +1,11 @@ package com.example.androidlabs.DB.repository import com.example.androidlabs.DB.models.User +import com.example.androidlabs.api.model.UserRemoteSignIn interface UserRepository { suspend fun createUser(user: User) suspend fun updateUser(user: User) suspend fun deleteUser(user: User) - suspend fun getUserById(id: Int): User - suspend fun getUserByEmail(email: String): User + suspend fun authUser(user: UserRemoteSignIn): User } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/DB/viewModels/HotelViewModel.kt b/app/src/main/java/com/example/androidlabs/DB/viewModels/HotelViewModel.kt index 3d165b7..5a494a8 100644 --- a/app/src/main/java/com/example/androidlabs/DB/viewModels/HotelViewModel.kt +++ b/app/src/main/java/com/example/androidlabs/DB/viewModels/HotelViewModel.kt @@ -22,7 +22,7 @@ class HotelViewModel(private val hotelRepository: HotelRepository): ViewModel() val stars = mutableStateOf("") val info = mutableStateOf("") val img = mutableStateOf(R.drawable.img) - val HotelList = hotelRepository.call().cachedIn(viewModelScope) + val HotelList = hotelRepository.getAllHotels() var hotel: Hotel? = null fun insertHotel() = viewModelScope.launch { diff --git a/app/src/main/java/com/example/androidlabs/DB/viewModels/OrderViewModel.kt b/app/src/main/java/com/example/androidlabs/DB/viewModels/OrderViewModel.kt index 7d64932..92b979d 100644 --- a/app/src/main/java/com/example/androidlabs/DB/viewModels/OrderViewModel.kt +++ b/app/src/main/java/com/example/androidlabs/DB/viewModels/OrderViewModel.kt @@ -23,14 +23,17 @@ class OrderViewModel(private val orderRepository: OrderRepository) : ViewModel() var dateFrom = mutableStateOf("") var dateTo = mutableStateOf("") - fun deleteOrder(order: Order) = viewModelScope.launch { - orderRepository.delete(order) + fun deleteOrder(orderId: Int) = viewModelScope.launch { + orderRepository.delete(orderId) } - fun getOrderList(id: Int) : Flow { + suspend fun getOrderList(id: Int) : Flow> { return orderRepository.getUserOrders(id) } + suspend fun getHotelFromOrder(id: Int) : Hotel { + return orderRepository.getHotelFromOrder(id) + } fun createOrder() = viewModelScope.launch { Log.d("MyLog", GlobalUser.getInstance().getUser()?.userId.toString()) @@ -42,7 +45,7 @@ class OrderViewModel(private val orderRepository: OrderRepository) : ViewModel() total = getSubTotal(), bookedHotelId = selectedItem?.hotelId!!, creatorUserId = GlobalUser.getInstance().getUser()?.userId!!, - hotel = selectedItem!! + //hotel = selectedItem!! ) val orderId = orderRepository.createOrder(order) diff --git a/app/src/main/java/com/example/androidlabs/DB/viewModels/UserViewModel.kt b/app/src/main/java/com/example/androidlabs/DB/viewModels/UserViewModel.kt index 24bfd5d..f0bc048 100644 --- a/app/src/main/java/com/example/androidlabs/DB/viewModels/UserViewModel.kt +++ b/app/src/main/java/com/example/androidlabs/DB/viewModels/UserViewModel.kt @@ -12,6 +12,8 @@ import com.example.androidlabs.DB.models.RoleEnum import com.example.androidlabs.DB.models.User import com.example.androidlabs.DB.repository.UserRepository import com.example.androidlabs.GlobalUser +import com.example.androidlabs.R +import com.example.androidlabs.api.model.UserRemoteSignIn import kotlinx.coroutines.launch class UserViewModel(private val userRepository: UserRepository): ViewModel() { @@ -26,22 +28,17 @@ class UserViewModel(private val userRepository: UserRepository): ViewModel() { surname = surname.value, email = email.value, password = password.value, - role = RoleEnum.User + role = "USER", + photo = R.drawable.img_2 ) userRepository.createUser(user) } fun authUser() = viewModelScope.launch { - val user = userRepository.getUserByEmail(email.value) - if (password.value != "" && user.password == password.value) { - val globalUser = GlobalUser.getInstance() - globalUser.setUser(user) - Log.d("MyLog", GlobalUser.getInstance().getUser()?.userId.toString()) - println() - - } + val user = userRepository.authUser(UserRemoteSignIn(email.value, password.value)) + GlobalUser.getInstance().setUser(user) } + fun isValidEmail(email: String): Boolean { return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches() } - } \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/MyOrderScreen/MyOrderScreen.kt b/app/src/main/java/com/example/androidlabs/MyOrderScreen/MyOrderScreen.kt index d641ea7..f65e459 100644 --- a/app/src/main/java/com/example/androidlabs/MyOrderScreen/MyOrderScreen.kt +++ b/app/src/main/java/com/example/androidlabs/MyOrderScreen/MyOrderScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight @@ -19,13 +20,24 @@ import com.example.androidlabs.DB.viewModels.OrderViewModel import com.example.androidlabs.GlobalUser import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.androidlabs.DB.viewModels.AppViewModelProvider +import kotlinx.coroutines.flow.first + + + @Composable -fun MyOrderScreen(orderViewModel: OrderViewModel) { +fun MyOrderScreen(orderViewModel: OrderViewModel= viewModel(factory = AppViewModelProvider.Factory)) { // val userWithOrder by orderViewModel.database.userDao().getUserOrders(GlobalUser.getInstance().getUser()?.userId!!).collectAsState(null) val userId = GlobalUser.getInstance().getUser()?.userId - val userWithOrder = orderViewModel.getOrderList(userId!!).collectAsState(null).value?.orders - println() + var usersOrder by remember { mutableStateOf>(emptyList()) } + LaunchedEffect(userId) { + usersOrder = orderViewModel.getOrderList(userId!!).first() + } Column( modifier = Modifier .padding(bottom = 50.dp) @@ -46,9 +58,9 @@ fun MyOrderScreen(orderViewModel: OrderViewModel) { modifier = Modifier .fillMaxSize() ) { - if (userWithOrder != null) { - for (item in userWithOrder) { - OrderCard(item, orderViewModel) + if (usersOrder != null) { + for (item in usersOrder) { + OrderCard(item) } } } diff --git a/app/src/main/java/com/example/androidlabs/MyOrderScreen/OrderCard.kt b/app/src/main/java/com/example/androidlabs/MyOrderScreen/OrderCard.kt index d87996a..4778bdd 100644 --- a/app/src/main/java/com/example/androidlabs/MyOrderScreen/OrderCard.kt +++ b/app/src/main/java/com/example/androidlabs/MyOrderScreen/OrderCard.kt @@ -14,6 +14,10 @@ import androidx.compose.material.ButtonDefaults import androidx.compose.material.Text 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.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -22,9 +26,11 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import com.example.androidlabs.DB.AppDatabase import com.example.androidlabs.DB.models.Hotel import com.example.androidlabs.DB.models.Order +import com.example.androidlabs.DB.viewModels.AppViewModelProvider import com.example.androidlabs.DB.viewModels.OrderViewModel import com.example.androidlabs.R import kotlinx.coroutines.Dispatchers @@ -32,7 +38,11 @@ import kotlinx.coroutines.withContext import java.util.Date @Composable -fun OrderCard(order: Order, orderViewModel: OrderViewModel){ +fun OrderCard(order: Order, orderViewModel: OrderViewModel = viewModel(factory = AppViewModelProvider.Factory)){ + var hotels by remember { mutableStateOf>(emptyList()) } + LaunchedEffect(order.orderId) { + hotels = listOf(orderViewModel.getHotelFromOrder(order.orderId!!)) + } Row( modifier = Modifier .fillMaxWidth() @@ -53,17 +63,18 @@ fun OrderCard(order: Order, orderViewModel: OrderViewModel){ Row(){ - + if (hotels != null) { + for(hotel in hotels) { Image( contentScale = ContentScale.FillBounds, - painter = painterResource(id =order.hotel.img), + painter = painterResource(id = hotel.img), // TODO contentDescription = null, modifier = Modifier .size(70.dp) .padding(0.dp, 10.dp, 10.dp, 10.dp) ) - - + } + } } Button( colors = ButtonDefaults.buttonColors( @@ -71,7 +82,7 @@ fun OrderCard(order: Order, orderViewModel: OrderViewModel){ contentColor = Color.White ), onClick = { - orderViewModel.deleteOrder(order) + orderViewModel.deleteOrder(order.orderId!!) }, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/example/androidlabs/Navigation/NavController.kt b/app/src/main/java/com/example/androidlabs/Navigation/NavController.kt index 07d9bbc..5ca5969 100644 --- a/app/src/main/java/com/example/androidlabs/Navigation/NavController.kt +++ b/app/src/main/java/com/example/androidlabs/Navigation/NavController.kt @@ -24,7 +24,6 @@ import com.google.gson.Gson @Composable fun NavController(navController: NavHostController) { - var orderViewModel: OrderViewModel = viewModel(factory = AppViewModelProvider.Factory) NavHost( navController = navController, startDestination = NavItem.Home.route @@ -41,7 +40,7 @@ fun NavController(navController: NavHostController) { HomeScreen(navController) } composable(NavItem.MyOrder.route){ - MyOrderScreen(orderViewModel) + MyOrderScreen() } composable(NavItem.Profile.route) { ProfileScreen(navController) @@ -56,7 +55,7 @@ fun NavController(navController: NavHostController) { backStackEntry -> val hotelItemString = backStackEntry.arguments?.getString("hotelItem") val hotelItem = Gson().fromJson(hotelItemString, Hotel::class.java) - hotelItem?.let { BookingScreen(orderViewModel, it, navController) + hotelItem?.let { BookingScreen(it, navController) } } composable(NavItem.ChangeHotel.route) { backStackEntry -> diff --git a/app/src/main/java/com/example/androidlabs/adminPanel/AdminPanel.kt b/app/src/main/java/com/example/androidlabs/adminPanel/AdminPanel.kt index 941e380..891794f 100644 --- a/app/src/main/java/com/example/androidlabs/adminPanel/AdminPanel.kt +++ b/app/src/main/java/com/example/androidlabs/adminPanel/AdminPanel.kt @@ -26,7 +26,7 @@ import com.example.androidlabs.profileScreen.signIn.LoginScreen fun AdminPanel(navHostController: NavHostController) { var isAddPanelVisible by remember { mutableStateOf(false) } var isChangePanelVisible by remember { mutableStateOf(true) } - var showDialog by remember { mutableStateOf(GlobalUser.getInstance().getUser()?.role == RoleEnum.User || GlobalUser.getInstance().getUser()?.role == null) } + var showDialog by remember { mutableStateOf(GlobalUser.getInstance().getUser()?.role == "USER" || GlobalUser.getInstance().getUser()?.role == null) } if (showDialog) { AlertDialog( onDismissRequest = { showDialog = false }, diff --git a/app/src/main/java/com/example/androidlabs/api/BackendService.kt b/app/src/main/java/com/example/androidlabs/api/BackendService.kt new file mode 100644 index 0000000..817bd17 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/BackendService.kt @@ -0,0 +1,105 @@ +package com.example.androidlabs.api + +import com.example.androidlabs.api.model.HotelRemote +import com.example.androidlabs.api.model.OrderRemote +import com.example.androidlabs.api.model.UserRemote +import com.example.androidlabs.api.model.UserRemoteSignIn +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import kotlinx.serialization.json.Json +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path +import retrofit2.http.Query + +interface BackendService { + + //SNEAKER + @GET("hotel/get/{id}") + suspend fun getHotel( + @Path("id") id: Int, + ): HotelRemote + + @GET("hotel/getAll") + suspend fun getHotels( + @Query("page") page: Int, + @Query("size") size: Int, + ): List + + @POST("hotel/create") + suspend fun createHotel( + @Body hotel: HotelRemote, + ): HotelRemote + + @PUT("hotel/update/{id}") + suspend fun updateHotel( + @Path("id") id: Int, + @Body hotel: HotelRemote + ): HotelRemote + + @DELETE("sneaker/delete/{id}") + suspend fun deleteHotel( + @Path("id") id: Int + ) + + //USER + @POST("user/signup") + suspend fun SignUp( + @Body user: UserRemote, + ): UserRemote + + @POST("user/signin") + suspend fun SignIn( + @Body user: UserRemoteSignIn + ): UserRemote + + @POST("order/create") + suspend fun createOrder( + @Body order: OrderRemote + ): Long + + @GET("order/getUserOrders/{userId}") + suspend fun getUserOrders( + @Path("userId") userId: Int + ) : List + + @GET("order/getHotelFromOrder/{orderId}") + suspend fun getHotelFromOrder( + @Path("orderId") orderId: Int + ) : HotelRemote + + @GET("order/deleteOrder/{orderId}") + suspend fun deleteOrder( + @Path("orderId") orderId: Int + ) + + companion object { + private const val BASE_URL = "https://59k4pfj3-8080.euw.devtunnels.ms/api/" + + @Volatile + private var INSTANCE: BackendService? = null + + fun getInstance(): BackendService { + return INSTANCE ?: synchronized(this) { + val logger = HttpLoggingInterceptor() + logger.level = HttpLoggingInterceptor.Level.BASIC + val client = OkHttpClient.Builder() + .addInterceptor(logger) + .build() + return Retrofit.Builder() + .baseUrl(BASE_URL) + .client(client) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + .create(BackendService::class.java) + .also { INSTANCE = it } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/HotelRemoteMediator.kt b/app/src/main/java/com/example/androidlabs/api/HotelRemoteMediator.kt new file mode 100644 index 0000000..89d4dc2 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/HotelRemoteMediator.kt @@ -0,0 +1,104 @@ +package com.example.androidlabs.api + +import androidx.paging.ExperimentalPagingApi +import androidx.paging.LoadType +import androidx.paging.PagingState +import androidx.paging.RemoteMediator +import androidx.room.withTransaction +import com.example.androidlabs.DB.AppDatabase +import com.example.androidlabs.DB.models.Hotel +import com.example.androidlabs.DB.models.RemoteKeyType +import com.example.androidlabs.DB.models.RemoteKeys +import com.example.androidlabs.DB.repository.HotelRepImpl +import com.example.androidlabs.DB.repository.RemoteKeysRepositoryImpl +import com.example.androidlabs.api.model.toHotel + +import retrofit2.HttpException +import java.io.IOException + +@OptIn(ExperimentalPagingApi::class) +class HotelRemoteMediator( + private val service: BackendService, + private val hotelRepository: HotelRepImpl, + private val database: AppDatabase, + private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl +) : RemoteMediator() { + override suspend fun initialize(): InitializeAction { + return InitializeAction.LAUNCH_INITIAL_REFRESH + } + override suspend fun load( + loadType: LoadType, + state: PagingState + ): MediatorResult { + val page = when (loadType) { + LoadType.REFRESH -> { + val remoteKeys = getRemoteKeyClosestToCurrentPosition(state) + remoteKeys?.nextKey?.minus(1) ?: 1 + } + + LoadType.PREPEND -> { + val remoteKeys = getRemoteKeyForFirstItem(state) + remoteKeys?.prevKey + ?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null) + } + + LoadType.APPEND -> { + val remoteKeys = getRemoteKeyForLastItem(state) + remoteKeys?.nextKey + ?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null) + } + } + + try { + val sneakers = service.getHotels(page, state.config.pageSize).map { it.toHotel() } + val endOfPaginationReached = sneakers.isEmpty() + database.withTransaction { + if (loadType == LoadType.REFRESH) { + dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.SNEAKER) + hotelRepository.clearHotels() + } + val prevKey = if (page == 1) null else page - 1 + val nextKey = if (endOfPaginationReached) null else page + 1 + val keys = sneakers.map { + RemoteKeys( + entityId = it.hotelId!!, + type = RemoteKeyType.SNEAKER, + prevKey = prevKey, + nextKey = nextKey + ) + } + dbRemoteKeyRepository.createRemoteKeys(keys) + hotelRepository.insertHotels(sneakers) + } + return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached) + } catch (exception: IOException) { + return MediatorResult.Error(exception) + } catch (exception: HttpException) { + return MediatorResult.Error(exception) + } + } + + private suspend fun getRemoteKeyForLastItem(state: PagingState): RemoteKeys? { + return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull() + ?.let { hotel -> + hotel.hotelId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) } + } + } + + private suspend fun getRemoteKeyForFirstItem(state: PagingState): RemoteKeys? { + return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull() + ?.let { hotel -> + hotel.hotelId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) } + } + } + + private suspend fun getRemoteKeyClosestToCurrentPosition( + state: PagingState + ): RemoteKeys? { + return state.anchorPosition?.let { position -> + state.closestItemToPosition(position)?.hotelId?.let { hotelUid -> + dbRemoteKeyRepository.getAllRemoteKeys(hotelUid, RemoteKeyType.SNEAKER) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/model/HotelRemote.kt b/app/src/main/java/com/example/androidlabs/api/model/HotelRemote.kt new file mode 100644 index 0000000..c63b350 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/model/HotelRemote.kt @@ -0,0 +1,36 @@ +package com.example.androidlabs.api.model + +import com.example.androidlabs.DB.models.Hotel +import kotlinx.serialization.Serializable + +@Serializable +data class HotelRemote ( + val id: Int? = 0, + val name: String = "", + val price: Double = 0.0, + val img: Int = 0, + val stars: Int = 0, + val location: String = "", + val info: String = "", + + ) + +fun HotelRemote.toHotel(): Hotel = Hotel( + id, + name, + price, + img, + stars, + location, + info +) + +fun Hotel.toHotelRemote():HotelRemote = HotelRemote( + hotelId, + name, + price, + img, + stars, + location, + info +) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/model/OrderRemote.kt b/app/src/main/java/com/example/androidlabs/api/model/OrderRemote.kt new file mode 100644 index 0000000..6d8b250 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/model/OrderRemote.kt @@ -0,0 +1,39 @@ +package com.example.androidlabs.api.model + +import androidx.room.ColumnInfo +import androidx.room.PrimaryKey +import com.example.androidlabs.DB.models.Hotel +import com.example.androidlabs.DB.models.Order + +import kotlinx.serialization.Serializable + +@Serializable +data class OrderRemote( + val id: Int? = 0, + val dateFrom: String = "", + val dateTo: String = "", + val rooms: Int = 0, + val total: Double = 0.0, + val userId: Int = 0, + val bookedHotelId: Int = 0 + ) + +fun OrderRemote.toOrder(): Order = Order( + id, + dateFrom, + dateTo, + rooms, + total, + userId, + bookedHotelId, + ) + +fun Order.toOrderRemote():OrderRemote = OrderRemote( + orderId, + dateFrom, + dateTo, + rooms, + total, + creatorUserId, + bookedHotelId, +) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/model/UserRemote.kt b/app/src/main/java/com/example/androidlabs/api/model/UserRemote.kt new file mode 100644 index 0000000..af33334 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/model/UserRemote.kt @@ -0,0 +1,41 @@ +package com.example.androidlabs.api.model + +import androidx.room.ColumnInfo +import androidx.room.PrimaryKey + +import com.example.androidlabs.DB.models.User +import com.example.androidlabs.DB.models.RoleEnum + +import kotlinx.serialization.Serializable + +@Serializable +data class UserRemote ( + val id: Int? = 0, + val name: String = "", + val surname: String = "", + val email: String = "", + val password: String = "", + val role: String = "", + val photo: Int? = 0, +) + + +fun UserRemote.toUser(): User = User( + id, + name, + surname, + email, + password, + role, + photo +) + +fun User.toUserRemote():UserRemote = UserRemote( + userId, + name, + surname, + email, + password, + role, + photo +) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/model/UserRemoteSignIn.kt b/app/src/main/java/com/example/androidlabs/api/model/UserRemoteSignIn.kt new file mode 100644 index 0000000..a79834d --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/model/UserRemoteSignIn.kt @@ -0,0 +1,9 @@ +package com.example.androidlabs.api.model + +import kotlinx.serialization.Serializable + +@Serializable +data class UserRemoteSignIn( + val email: String = "", + val password: String = "", +) \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/repository/RestHotelRepository.kt b/app/src/main/java/com/example/androidlabs/api/repository/RestHotelRepository.kt new file mode 100644 index 0000000..e131bcd --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/repository/RestHotelRepository.kt @@ -0,0 +1,60 @@ +package com.example.androidlabs.api.repository + + +import androidx.paging.ExperimentalPagingApi +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import com.example.androidlabs.AppContainer +import com.example.androidlabs.DB.AppDatabase +import com.example.androidlabs.DB.models.Hotel +import com.example.androidlabs.DB.repository.HotelRepImpl +import com.example.androidlabs.DB.repository.HotelRepository +import com.example.androidlabs.DB.repository.RemoteKeysRepositoryImpl +import com.example.androidlabs.api.BackendService +import com.example.androidlabs.api.HotelRemoteMediator +import com.example.androidlabs.api.model.toHotel +import com.example.androidlabs.api.model.toHotelRemote + +import kotlinx.coroutines.flow.Flow + +class RestHotelRepository( + private val service: BackendService, + private val dbHotelRepository: HotelRepImpl, + private val database: AppDatabase, + private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl + +) : HotelRepository { + + override fun getAllHotels(): Flow> { + val pagingSourceFactory = { dbHotelRepository.getAllHotelsPagingSource() } + + @OptIn(ExperimentalPagingApi::class) + return Pager( + config = PagingConfig( + pageSize = AppContainer.LIMIT, + enablePlaceholders = false + ), + remoteMediator = HotelRemoteMediator( + service, + dbHotelRepository, + database, + dbRemoteKeyRepository, + ), + pagingSourceFactory = pagingSourceFactory + ).flow + } + + override suspend fun getHotelById(id: Int): Hotel = service.getHotel(id).toHotel() + override suspend fun insertHotel(hotel: Hotel) { + service.createHotel(hotel.toHotelRemote()) + } + + override suspend fun updateHotel(hotel: Hotel) { + hotel.hotelId?.let { service.updateHotel(it, hotel.toHotelRemote()) } + } + + override suspend fun deleteHotel(hotel: Hotel) { + hotel.hotelId?.let { service.deleteHotel(it) } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/repository/RestOrderRepository.kt b/app/src/main/java/com/example/androidlabs/api/repository/RestOrderRepository.kt new file mode 100644 index 0000000..5dbf980 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/repository/RestOrderRepository.kt @@ -0,0 +1,32 @@ +package com.example.androidlabs.api.repository + +import com.example.androidlabs.DB.models.Hotel +import com.example.androidlabs.DB.models.Order +import com.example.androidlabs.DB.repository.OrderRepository +import com.example.androidlabs.api.BackendService +import com.example.androidlabs.api.model.toHotel +import com.example.androidlabs.api.model.toOrder +import com.example.androidlabs.api.model.toOrderRemote +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + +class RestOrderRepository(private val service: BackendService): OrderRepository { + override suspend fun createOrder(order: Order): Long { + return service.createOrder(order.toOrderRemote()) + } + + + override suspend fun delete(orderId: Int) { + service.deleteOrder(orderId) + } + + override suspend fun getHotelFromOrder(id: Int): Hotel { + return service.getHotelFromOrder(id).toHotel() + } + + override suspend fun getUserOrders(id: Int): Flow> { + val ordersRemoteList = service.getUserOrders(id) + val ordersList = ordersRemoteList.map { it.toOrder() } + return flowOf(ordersList.toList()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/api/repository/RestUserRepository.kt b/app/src/main/java/com/example/androidlabs/api/repository/RestUserRepository.kt new file mode 100644 index 0000000..d75d501 --- /dev/null +++ b/app/src/main/java/com/example/androidlabs/api/repository/RestUserRepository.kt @@ -0,0 +1,25 @@ +import com.example.androidlabs.DB.models.User +import com.example.androidlabs.DB.repository.UserRepository +import com.example.androidlabs.api.BackendService +import com.example.androidlabs.api.model.UserRemoteSignIn +import com.example.androidlabs.api.model.toUser +import com.example.androidlabs.api.model.toUserRemote + +class RestUserRepository( + private var service: BackendService +): UserRepository { + override suspend fun createUser(user: User) { + service.SignUp(user.toUserRemote()) + } + + override suspend fun updateUser(user: User) { + println() + } + + override suspend fun deleteUser(user: User) { + println() + } + override suspend fun authUser(user: UserRemoteSignIn): User { + return service.SignIn(user).toUser() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidlabs/booking/BookingScreen.kt b/app/src/main/java/com/example/androidlabs/booking/BookingScreen.kt index ef24f53..cfdda35 100644 --- a/app/src/main/java/com/example/androidlabs/booking/BookingScreen.kt +++ b/app/src/main/java/com/example/androidlabs/booking/BookingScreen.kt @@ -40,11 +40,13 @@ import com.example.androidlabs.R import android.app.DatePickerDialog import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextAlign +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.androidlabs.DB.viewModels.AppViewModelProvider import java.util.Calendar import java.util.Date @Composable -fun BookingScreen(orderViewModel: OrderViewModel, hotel: Hotel, navHostController: NavHostController) { +fun BookingScreen(hotel: Hotel, navHostController: NavHostController, orderViewModel: OrderViewModel = viewModel(factory = AppViewModelProvider.Factory)) { Column( modifier = Modifier .fillMaxSize()