4 Lab Recover Old Functional
This commit is contained in:
parent
7f9450d02e
commit
756cfa14c0
@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:name=".FoodWarriorsApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
@ -0,0 +1,32 @@
|
||||
package com.example.myapplication
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
||||
import com.example.myapplication.ui.dishes.view.DishViewModel
|
||||
import com.example.myapplication.ui.extra.ErrorsViewModel
|
||||
import com.example.myapplication.ui.user.UserViewModel
|
||||
|
||||
|
||||
object AppViewModelProvider {
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
DishListViewModel(foodWarriorsApplication().container.dishRepository,
|
||||
foodWarriorsApplication().container.userFavoritesRepository)
|
||||
}
|
||||
initializer {
|
||||
ErrorsViewModel()
|
||||
}
|
||||
initializer {
|
||||
UserViewModel(foodWarriorsApplication().container.userRepository)
|
||||
}
|
||||
initializer {
|
||||
DishViewModel(foodWarriorsApplication().container.dishRepository)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CreationExtras.foodWarriorsApplication(): FoodWarriorsApplication =
|
||||
(this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as FoodWarriorsApplication)
|
@ -1,195 +0,0 @@
|
||||
package com.example.myapplication.Dishes.ui
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
//import com.example.myapplication.Dishes.Model.getAllDishes
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.User.Model.UserFavorites
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
fun DishList(navController: NavController?, onlyFavorites: Boolean = false, someUser: Int? = remember { null }, userPage: Boolean = false) {
|
||||
val context = LocalContext.current
|
||||
val dishes = remember { mutableStateListOf<Dish>() }
|
||||
val favoriteDishes = remember { mutableStateListOf<Dish>() }
|
||||
val scope = rememberCoroutineScope()
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
|
||||
if (someUser != null && onlyFavorites) {
|
||||
AppDatabase.getInstance(context).userFavoritesDao().getUserFavorites(someUser).collect() {data ->
|
||||
dishes.clear()
|
||||
favoriteDishes.clear()
|
||||
dishes.addAll(data)
|
||||
favoriteDishes.addAll(data)
|
||||
}
|
||||
}
|
||||
else if (someUser != null && userPage) {
|
||||
AppDatabase.getInstance(context).dishDao().getAllOFUser(someUser).collect() {data ->
|
||||
dishes.clear()
|
||||
favoriteDishes.clear()
|
||||
dishes.addAll(data)
|
||||
AppDatabase.getInstance(context).userFavoritesDao().getUserFavorites(someUser).collect() {data ->
|
||||
favoriteDishes.addAll(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
AppDatabase.getInstance(context).dishDao().getAll().collect() { data ->
|
||||
dishes.clear()
|
||||
favoriteDishes.clear()
|
||||
dishes.addAll(data)
|
||||
AppDatabase.getInstance(context).userFavoritesDao().getUserFavorites(someUser).collect() {data ->
|
||||
favoriteDishes.addAll(data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(ScrollState(0))) {
|
||||
|
||||
Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
|
||||
Column {
|
||||
var text = stringResource(R.string.all_dishes)
|
||||
if (onlyFavorites) text = stringResource(id = R.string.favorite_dishes)
|
||||
if (userPage) text = stringResource(id = R.string.user_dishes)
|
||||
Text(text, fontFamily= textFont,
|
||||
fontSize=26.sp, textAlign = TextAlign.Start)
|
||||
}
|
||||
}
|
||||
dishes.forEachIndexed() {index, dish ->
|
||||
Row(
|
||||
Modifier
|
||||
.padding(vertical = 5.dp)
|
||||
.fillMaxSize()
|
||||
.clickable {
|
||||
navController?.navigate("dish/" + dish.uid!!)
|
||||
}) {
|
||||
|
||||
Column() {
|
||||
if (dish.image != null) { // TODO Image input check
|
||||
Image(
|
||||
bitmap = dish.getBitmapFromByteArray()!!.asImageBitmap(),
|
||||
contentDescription = "Dish Image",
|
||||
Modifier.width(150.dp)
|
||||
)
|
||||
}
|
||||
else {
|
||||
Image(
|
||||
Icons.Filled.Warning,
|
||||
contentDescription = "Dish Image",
|
||||
Modifier.width(150.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Column {
|
||||
Text(dish.name, fontFamily=textFont,
|
||||
fontSize=15.sp, textAlign=TextAlign.Center )
|
||||
Text(
|
||||
dish.description, fontFamily=textFont,
|
||||
fontSize = 12.sp,
|
||||
softWrap = true,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 3)
|
||||
}
|
||||
Column(
|
||||
Modifier
|
||||
.clickable {
|
||||
scope.launch {
|
||||
if (favoriteDishes.contains(dish)) {
|
||||
AppDatabase
|
||||
.getInstance(context)
|
||||
.userFavoritesDao()
|
||||
.delete(
|
||||
UserFavorites(someUser!!, dish.uid!!)
|
||||
).run { favoriteDishes.clear() }
|
||||
|
||||
}
|
||||
else {
|
||||
AppDatabase
|
||||
.getInstance(context)
|
||||
.userFavoritesDao()
|
||||
.insert(
|
||||
UserFavorites(someUser!!, dish.uid!!)
|
||||
).run { favoriteDishes.clear() }
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(horizontal = 5.dp)
|
||||
) {
|
||||
if (favoriteDishes.contains(dish)) {
|
||||
Icon(Icons.Filled.Favorite, contentDescription = "")
|
||||
}
|
||||
else {
|
||||
Icon(Icons.Filled.FavoriteBorder, contentDescription = "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Preview
|
||||
@Composable
|
||||
fun ListDishes() {
|
||||
MyApplicationTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
DishList(navController = null, onlyFavorites = false)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.example.myapplication
|
||||
|
||||
import android.app.Application
|
||||
import com.example.myapplication.database.AppContainer
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
|
||||
class FoodWarriorsApplication : Application() {
|
||||
lateinit var container: AppContainer
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
container = AppDataContainer(this)
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.example.myapplication.database
|
||||
|
||||
import android.content.Context
|
||||
import com.example.myapplication.database.repository.CategoryRepository
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.OfflineCategoryRepository
|
||||
import com.example.myapplication.database.repository.OfflineDishRepository
|
||||
import com.example.myapplication.database.repository.OfflineUserFavoritesRepository
|
||||
import com.example.myapplication.database.repository.OfflineUserRepository
|
||||
import com.example.myapplication.database.repository.UserRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
|
||||
|
||||
interface AppContainer {
|
||||
val userRepository : UserRepository
|
||||
val dishRepository : DishRepository
|
||||
val categoryRepository : CategoryRepository
|
||||
val userFavoritesRepository: UserWithFavoritesRepository
|
||||
}
|
||||
|
||||
class AppDataContainer(private val context: Context) : AppContainer {
|
||||
|
||||
override val userRepository: UserRepository by lazy {
|
||||
OfflineUserRepository(AppDatabase.getInstance(context).userDao())
|
||||
}
|
||||
|
||||
override val dishRepository: DishRepository by lazy {
|
||||
OfflineDishRepository(AppDatabase.getInstance(context).dishDao())
|
||||
}
|
||||
|
||||
override val categoryRepository: CategoryRepository by lazy {
|
||||
OfflineCategoryRepository(AppDatabase.getInstance(context).categoryDao())
|
||||
}
|
||||
|
||||
override val userFavoritesRepository: UserWithFavoritesRepository by lazy {
|
||||
OfflineUserFavoritesRepository(AppDatabase.getInstance(context).userFavoritesDao())
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
}
|
||||
}
|
@ -5,15 +5,14 @@ import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.example.myapplication.Dishes.Model.Category
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
import com.example.myapplication.Dishes.dao.CategoryDao
|
||||
import com.example.myapplication.Dishes.dao.DishDao
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.User.Model.UserFavorites
|
||||
import com.example.myapplication.User.Model.UserWithFavorites
|
||||
import com.example.myapplication.User.dao.UserDao
|
||||
import com.example.myapplication.User.dao.UserFavoritesDao
|
||||
import com.example.myapplication.database.model.Category
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.dao.CategoryDao
|
||||
import com.example.myapplication.database.dao.DishDao
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import com.example.myapplication.database.dao.UserDao
|
||||
import com.example.myapplication.database.dao.UserFavoritesDao
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -1,16 +1,17 @@
|
||||
package com.example.myapplication.Dishes.dao
|
||||
package com.example.myapplication.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.example.myapplication.Dishes.Model.Category
|
||||
import com.example.myapplication.database.model.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CategoryDao {
|
||||
@Query("select * from categories order by category_name collate nocase asc")
|
||||
fun getAll(): List<Category>
|
||||
fun getAll(): Flow<List<Category>>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(category: Category)
|
@ -1,12 +1,12 @@
|
||||
package com.example.myapplication.Dishes.dao
|
||||
package com.example.myapplication.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
import com.example.myapplication.Dishes.Model.DishWithCategoryAndUser
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
@ -16,7 +16,7 @@ interface DishDao {
|
||||
|
||||
@Query("select * from dishes left join categories on dishes.category_id = categories.category_id " +
|
||||
"left join users on dishes.user_id = users.user_id where dishes.dish_id = :uid")
|
||||
suspend fun getByUid(uid: Int): DishWithCategoryAndUser
|
||||
fun getByUid(uid: Int): Flow<DishWithCategoryAndUser?>
|
||||
|
||||
@Query("select * from dishes where dishes.user_id = :uid")
|
||||
fun getAllOFUser(uid: Int): Flow<List<Dish>>
|
@ -1,13 +1,12 @@
|
||||
package com.example.myapplication.User.dao
|
||||
package com.example.myapplication.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.User.Model.UserWithFavorites
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.model.UserWithFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
@ -16,7 +15,7 @@ interface UserDao {
|
||||
fun getAll(): Flow<List<User>>
|
||||
|
||||
@Query("select * from users where users.user_id = :uid")
|
||||
suspend fun getByUid(uid: Int): User
|
||||
fun getByUid(uid: Int): Flow<User?>
|
||||
|
||||
|
||||
@Query("select * from user_favorites left join users on user_favorites.user_id = users.user_id " +
|
@ -1,4 +1,4 @@
|
||||
package com.example.myapplication.User.dao
|
||||
package com.example.myapplication.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
@ -6,9 +6,9 @@ import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.User.Model.UserFavorites
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
@ -29,4 +29,8 @@ interface UserFavoritesDao {
|
||||
@Transaction
|
||||
@Query("SELECT * FROM user_favorites us JOIN dishes d ON d.dish_id = us.dish_id WHERE us.user_id = :uid")
|
||||
fun getUserFavorites(uid: Int?): Flow<List<Dish>>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM user_favorites us WHERE us.user_id = :userUid AND us.dish_id = :dishUid")
|
||||
fun getUserFavorite(userUid: Int?, dishUid: Int?): Flow<UserFavorites?>
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.example.myapplication.Dishes.Model
|
||||
package com.example.myapplication.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
@ -1,4 +1,4 @@
|
||||
package com.example.myapplication.Dishes.Model
|
||||
package com.example.myapplication.database.model
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
@ -7,9 +7,6 @@ import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.User.Model.User
|
||||
import java.io.Serializable
|
||||
|
||||
//data class Dish (
|
||||
// val name: String,
|
@ -1,4 +1,4 @@
|
||||
package com.example.myapplication.Dishes.Model
|
||||
package com.example.myapplication.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Embedded
|
@ -1,8 +1,7 @@
|
||||
package com.example.myapplication.User.Model
|
||||
package com.example.myapplication.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
//data class User (
|
@ -1,11 +1,8 @@
|
||||
package com.example.myapplication.User.Model;
|
||||
package com.example.myapplication.database.model;
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
|
||||
@Entity(tableName = "user_favorites", primaryKeys = ["user_id", "dish_id"])
|
||||
data class UserFavorites(
|
@ -1,13 +1,8 @@
|
||||
package com.example.myapplication.User.Model
|
||||
package com.example.myapplication.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.Junction
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.Relation
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
|
||||
data class FavoriteWithUsers(
|
||||
@Embedded
|
@ -0,0 +1,8 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.model.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CategoryRepository {
|
||||
fun getAllCategories(): Flow<List<Category>>
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DishRepository {
|
||||
fun getAllDishes(): Flow<List<Dish>>
|
||||
fun getDish(uid: Int): Flow<DishWithCategoryAndUser?>
|
||||
|
||||
fun getUserDishes(userUid: Int) : Flow<List<Dish>>
|
||||
suspend fun insertDish(dish: Dish)
|
||||
suspend fun updateDish(dish: Dish)
|
||||
suspend fun deleteDish(dish: Dish)
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.dao.CategoryDao
|
||||
import com.example.myapplication.database.model.Category
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineCategoryRepository(private val categoryDao: CategoryDao) : CategoryRepository {
|
||||
override fun getAllCategories(): Flow<List<Category>> {
|
||||
return categoryDao.getAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.dao.DishDao
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineDishRepository(private val dishDao: DishDao) : DishRepository {
|
||||
override fun getAllDishes(): Flow<List<Dish>> {
|
||||
return dishDao.getAll()
|
||||
}
|
||||
|
||||
override fun getDish(uid: Int): Flow<DishWithCategoryAndUser?> {
|
||||
return dishDao.getByUid(uid)
|
||||
}
|
||||
|
||||
override fun getUserDishes(userUid: Int): Flow<List<Dish>> {
|
||||
return dishDao.getAllOFUser(userUid);
|
||||
}
|
||||
|
||||
override suspend fun insertDish(dish: Dish) {
|
||||
dishDao.insert(dish)
|
||||
}
|
||||
|
||||
override suspend fun updateDish(dish: Dish) {
|
||||
dishDao.update(dish)
|
||||
}
|
||||
|
||||
override suspend fun deleteDish(dish: Dish) {
|
||||
dishDao.delete(dish)
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.dao.UserFavoritesDao
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineUserFavoritesRepository(private val userFavoritesDao: UserFavoritesDao) : UserWithFavoritesRepository {
|
||||
override fun getUserFavorites(userUid: Int): Flow<List<Dish>> {
|
||||
return userFavoritesDao.getUserFavorites(userUid)
|
||||
}
|
||||
|
||||
override fun getUserFavorite(userUid: Int, dishUid: Int): Flow<UserFavorites?> {
|
||||
return userFavoritesDao.getUserFavorite(userUid, dishUid)
|
||||
}
|
||||
|
||||
override suspend fun deleteUserFavorites(userUid: Int, dishUid: Int) {
|
||||
userFavoritesDao.delete(UserFavorites(userUid, dishUid))
|
||||
}
|
||||
|
||||
override suspend fun insertUserFavorites(userUid: Int, dishUid: Int) {
|
||||
userFavoritesDao.insert(UserFavorites(userUid, dishUid))
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.dao.UserDao
|
||||
import com.example.myapplication.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
|
||||
override fun getAllUsers(): Flow<List<User>> {
|
||||
return userDao.getAll()
|
||||
}
|
||||
|
||||
override fun getUser(uid: Int): Flow<User?> {
|
||||
return userDao.getByUid(uid)
|
||||
}
|
||||
|
||||
override suspend fun insertUser(user: User) {
|
||||
userDao.insert(user)
|
||||
}
|
||||
|
||||
override suspend fun updateUser(user: User) {
|
||||
userDao.update(user)
|
||||
}
|
||||
|
||||
override suspend fun deleteUser(user: User) {
|
||||
userDao.delete(user)
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserRepository {
|
||||
fun getAllUsers(): Flow<List<User>>
|
||||
fun getUser(uid: Int): Flow<User?>
|
||||
suspend fun insertUser(user: User)
|
||||
suspend fun updateUser(user: User)
|
||||
suspend fun deleteUser(user: User)
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.example.myapplication.database.repository
|
||||
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserWithFavoritesRepository {
|
||||
fun getUserFavorites(userUid: Int): Flow<List<Dish>>
|
||||
|
||||
fun getUserFavorite(userUid: Int, dishUid: Int): Flow<UserFavorites?>
|
||||
|
||||
suspend fun deleteUserFavorites(userUid: Int, dishUid: Int)
|
||||
|
||||
suspend fun insertUserFavorites(userUid: Int, dishUid: Int)
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
package com.example.myapplication.ui.dishes.list
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.myapplication.AppViewModelProvider
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.database.model.UserFavorites
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.ui.extra.ErrorElement
|
||||
import com.example.myapplication.ui.extra.ErrorsType
|
||||
import com.example.myapplication.ui.navigation.Screen
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
fun DishList(
|
||||
navController: NavController,
|
||||
viewModel: DishListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
typeDishList: TypeDishList = TypeDishList.AllDishes,
|
||||
userUid: Int?
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val dishListUiState by viewModel.dishListUiState.collectAsState()
|
||||
val userDishes by viewModel.userDishes(userUid ?: 0).collectAsState()
|
||||
val favorites by viewModel.dishFavorites(userUid ?: 0).collectAsState()
|
||||
Scaffold(
|
||||
) { innerPadding ->
|
||||
if (typeDishList != TypeDishList.AllDishes && userUid == null) {
|
||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_AUTH)
|
||||
}
|
||||
else {
|
||||
DishList(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(ScrollState(0)),
|
||||
typeDishList = typeDishList,
|
||||
dishList = when (typeDishList) {
|
||||
TypeDishList.AllDishes -> dishListUiState.dishList
|
||||
TypeDishList.FavoritesDishes -> favorites.dishList
|
||||
TypeDishList.UserDishes -> userDishes.dishList
|
||||
else -> dishListUiState.dishList
|
||||
},
|
||||
favorites = favorites.dishList,
|
||||
addToFavorites = {uid: Int ->
|
||||
if (userUid != null) {
|
||||
coroutineScope.launch {
|
||||
viewModel.addFavoritesToUser(userUid, uid)
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick = {uid: Int ->
|
||||
val route = Screen.DishView.route.replace("{id}", uid.toString())
|
||||
navController.navigate(route)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
private fun DishList(
|
||||
modifier: Modifier = Modifier,
|
||||
typeDishList: TypeDishList,
|
||||
dishList: List<Dish>,
|
||||
favorites: List<Dish>,
|
||||
addToFavorites: (uid : Int) -> Unit,
|
||||
onClick: (uid : Int) -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier
|
||||
) {
|
||||
Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
|
||||
Column {
|
||||
val text: String = when (typeDishList) {
|
||||
TypeDishList.AllDishes -> stringResource(R.string.all_dishes)
|
||||
TypeDishList.FavoritesDishes -> stringResource(id = R.string.favorite_dishes)
|
||||
TypeDishList.UserDishes -> stringResource(id = R.string.user_dishes)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
Text(text, fontFamily= textFont,
|
||||
fontSize=26.sp, textAlign = TextAlign.Start)
|
||||
}
|
||||
}
|
||||
dishList.forEachIndexed() {index, dish ->
|
||||
DishListItem(index=index, dish = dish, favorites = favorites, addToFavorites, onClick = onClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
private fun DishListItem(
|
||||
index: Int,
|
||||
dish: Dish,
|
||||
favorites: List<Dish>,
|
||||
addToFavorites: (uid : Int) -> Unit,
|
||||
onClick: (uid: Int) -> Unit
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.padding(vertical = 5.dp)
|
||||
.fillMaxSize()
|
||||
.clickable {
|
||||
onClick(dish.uid!!)
|
||||
}) {
|
||||
|
||||
Column() {
|
||||
if (dish.image != null) { // TODO Image input check
|
||||
Image(
|
||||
bitmap = dish.getBitmapFromByteArray()!!.asImageBitmap(),
|
||||
contentDescription = "Dish Image",
|
||||
Modifier.width(150.dp)
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
Icons.Filled.Warning,
|
||||
contentDescription = "Dish Image",
|
||||
Modifier.width(150.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Column {
|
||||
Text(
|
||||
dish.name, fontFamily = textFont,
|
||||
fontSize = 15.sp, textAlign = TextAlign.Center
|
||||
)
|
||||
Text(
|
||||
dish.description, fontFamily = textFont,
|
||||
fontSize = 12.sp,
|
||||
softWrap = true,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 3
|
||||
)
|
||||
}
|
||||
Column(
|
||||
Modifier.clickable { addToFavorites(dish.uid!!) }
|
||||
) {
|
||||
if (favorites.contains(dish)) {
|
||||
Icon(Icons.Filled.Favorite, contentDescription = "")
|
||||
}
|
||||
else {
|
||||
Icon(Icons.Filled.FavoriteBorder, contentDescription = "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Preview
|
||||
@Composable
|
||||
fun ListDishes() {
|
||||
// MyApplicationTheme {
|
||||
// Surface(
|
||||
// color = MaterialTheme.colorScheme.background
|
||||
// ) {
|
||||
// DishList(navController = null, onlyFavorites = false)
|
||||
// }
|
||||
// }
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.example.myapplication.ui.dishes.list
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
enum class TypeDishList {
|
||||
AllDishes,
|
||||
FavoritesDishes,
|
||||
UserDishes
|
||||
}
|
||||
class DishListViewModel(
|
||||
private val dishRepository: DishRepository,
|
||||
private val userWithFavoritesRepository: UserWithFavoritesRepository
|
||||
) : ViewModel() {
|
||||
val dishListUiState: StateFlow<DishListUiState> = dishRepository.getAllDishes().map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
|
||||
fun dishFavorites(userUid: Int) : StateFlow<DishListUiState> {
|
||||
return userWithFavoritesRepository.getUserFavorites(userUid).map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
}
|
||||
|
||||
fun userDishes(userUid: Int) : StateFlow<DishListUiState> {
|
||||
return dishRepository.getUserDishes(userUid).map {
|
||||
DishListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishListUiState()
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun addFavoritesToUser(userUid: Int, dishUid: Int) {
|
||||
var flag = true;
|
||||
userWithFavoritesRepository.getUserFavorite(userUid, dishUid).collect {
|
||||
if (flag) {
|
||||
if (it == null) {
|
||||
flag = false
|
||||
userWithFavoritesRepository.insertUserFavorites(userUid, dishUid)
|
||||
} else {
|
||||
flag = false
|
||||
userWithFavoritesRepository.deleteUserFavorites(userUid, dishUid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data class DishListUiState(val dishList: List<Dish> = listOf())
|
@ -1,4 +1,4 @@
|
||||
package com.example.myapplication.Dishes.ui
|
||||
package com.example.myapplication.ui.dishes
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
@ -10,59 +10,86 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.myapplication.Dishes.Model.Dish
|
||||
import com.example.myapplication.Dishes.Model.DishWithCategoryAndUser
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.myapplication.AppViewModelProvider
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.ui.dishes.view.DishViewModel
|
||||
import com.example.myapplication.ui.extra.ErrorElement
|
||||
import com.example.myapplication.ui.extra.ErrorsType
|
||||
//import com.example.myapplication.Dishes.Model.getAllDishes
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
import com.example.myapplication.ui.user.UserViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun DishView(id: Int) {
|
||||
var dish = remember { mutableStateOf(DishWithCategoryAndUser(
|
||||
Dish(0, "", "", null, null, null),
|
||||
null, null))
|
||||
fun DishView(navController: NavController,
|
||||
viewModel: DishViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
userUid: Int?,
|
||||
dishUid: Int?) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val dishUiState by viewModel.getDish(dishUid ?: 0).collectAsState()
|
||||
Scaffold(
|
||||
|
||||
){ innerPadding ->
|
||||
if (dishUiState.dish == null) {
|
||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_FOUND)
|
||||
}
|
||||
val context = LocalContext.current
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
dish.value = AppDatabase.getInstance(context).dishDao().getByUid(id)
|
||||
else {
|
||||
DishView(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
dish = dishUiState.dish!!
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
private fun DishView(
|
||||
modifier: Modifier,
|
||||
dish : DishWithCategoryAndUser
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 5.dp, horizontal = 10.dp)
|
||||
.verticalScroll(ScrollState(0))) {
|
||||
Row(Modifier.padding(vertical = 5.dp)) {
|
||||
if (dish.value.dish?.image != null) { // TODO Image input check
|
||||
if (dish.dish?.image != null) {
|
||||
Image(
|
||||
bitmap = dish.value.dish!!.getBitmapFromByteArray()!!.asImageBitmap(),
|
||||
bitmap = dish.dish.getBitmapFromByteArray()!!.asImageBitmap(),
|
||||
contentDescription = "Dish Image",
|
||||
Modifier.fillMaxSize()
|
||||
)
|
||||
@ -77,11 +104,11 @@ fun DishView(id: Int) {
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier.fillMaxWidth()) {
|
||||
Column {
|
||||
Text(dish.value.dish!!.name, fontFamily=textFont,
|
||||
Text(dish.dish!!.name, fontFamily=textFont,
|
||||
fontSize=15.sp, textAlign = TextAlign.Start)
|
||||
}
|
||||
Column {
|
||||
Text("@" + dish.value.nickname, fontFamily=textFont,
|
||||
Text("@" + dish.nickname, fontFamily=textFont,
|
||||
fontSize=15.sp, textAlign = TextAlign.End)
|
||||
}
|
||||
}
|
||||
@ -89,9 +116,10 @@ fun DishView(id: Int) {
|
||||
.fillMaxSize()
|
||||
.padding(
|
||||
horizontal = 30.dp, vertical = 10.dp
|
||||
)) {
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
dish.value.dish!!.description,
|
||||
dish.dish!!.description,
|
||||
fontFamily=textFont,
|
||||
fontSize = 13.sp,
|
||||
softWrap = true,
|
||||
@ -100,16 +128,3 @@ fun DishView(id: Int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Preview
|
||||
@Composable
|
||||
fun DishPreview() {
|
||||
MyApplicationTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
DishView(id = 0)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.example.myapplication.ui.dishes.view
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.DishWithCategoryAndUser
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.ui.user.UserUiState
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class DishViewModel(
|
||||
private val dishRepository: DishRepository
|
||||
) : ViewModel() {
|
||||
fun getDish(uid: Int) : StateFlow<DishUiState> {
|
||||
return dishRepository.getDish(uid).map {
|
||||
DishUiState(it!!)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = DishUiState()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class DishUiState(val dish: DishWithCategoryAndUser? = null)
|
@ -0,0 +1,43 @@
|
||||
package com.example.myapplication.ui.extra
|
||||
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.myapplication.AppViewModelProvider
|
||||
import com.example.myapplication.ui.dishes.list.DishList
|
||||
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
||||
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ErrorElement(
|
||||
navController: NavController,
|
||||
viewModel: ErrorsViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
typeErrorsType: ErrorsType
|
||||
) {
|
||||
Scaffold(
|
||||
) { innerPadding ->
|
||||
ErrorElement(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
text = viewModel.getError(typeErrorsType).errorText
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ErrorElement(
|
||||
modifier: Modifier,
|
||||
text: String
|
||||
) {
|
||||
Text(text = text)
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.example.myapplication.ui.extra
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.ui.dishes.list.DishListUiState
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
enum class ErrorsType {
|
||||
NOT_AUTH,
|
||||
NOT_FOUND
|
||||
}
|
||||
class ErrorsViewModel : ViewModel() {
|
||||
fun getError(type: ErrorsType) : ErrorUiState {
|
||||
return when (type) {
|
||||
ErrorsType.NOT_AUTH -> ErrorUiState("Auth first")
|
||||
ErrorsType.NOT_FOUND -> ErrorUiState("Not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data class ErrorUiState(val errorText: String = "")
|
@ -1,7 +1,6 @@
|
||||
package com.example.myapplication.ui.navigation
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.background
|
||||
@ -12,9 +11,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@ -25,16 +22,15 @@ import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import com.example.myapplication.Dishes.ui.DishList
|
||||
import com.example.myapplication.Dishes.ui.DishView
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.User.ui.UserView
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.ui.dishes.list.DishList
|
||||
//import com.example.myapplication.ui.dishes.DishView
|
||||
import com.example.myapplication.database.model.User
|
||||
//import com.example.myapplication.ui.user.UserView
|
||||
import com.example.myapplication.ui.components.Navbar
|
||||
import com.example.myapplication.ui.dishes.DishView
|
||||
import com.example.myapplication.ui.dishes.list.TypeDishList
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import com.example.myapplication.ui.user.UserView
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
@ -43,8 +39,7 @@ fun Navhost(
|
||||
innerPadding: PaddingValues, modifier:
|
||||
Modifier = Modifier
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var someUser: User? = null
|
||||
val userUid = 1;
|
||||
NavHost(
|
||||
navController,
|
||||
startDestination = Screen.AllDishes.route,
|
||||
@ -52,14 +47,14 @@ fun Navhost(
|
||||
) {
|
||||
|
||||
|
||||
composable(Screen.AllDishes.route) { DishList(navController, someUser = 1) }
|
||||
composable(Screen.FavoriteDishes.route) { DishList(navController, true, 1)}
|
||||
composable(Screen.UserPage.route) {UserView(id = 1, navController = navController)} // TODO Remove hardcode
|
||||
composable(Screen.AllDishes.route) { DishList(navController, userUid = userUid) }
|
||||
composable(Screen.FavoriteDishes.route) { DishList(navController, userUid = userUid, typeDishList = TypeDishList.FavoritesDishes) }
|
||||
composable(Screen.UserPage.route) { UserView(navController, userUid = userUid) }
|
||||
|
||||
composable(Screen.DishView.route,
|
||||
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||
) { backStackEntry ->
|
||||
backStackEntry.arguments?.let { DishView(it.getInt("id")) }
|
||||
backStackEntry.arguments?.let { DishView(navController, userUid = userUid, dishUid = it.getInt("id")) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,42 @@
|
||||
package com.example.myapplication.User.ui
|
||||
package com.example.myapplication.ui.user
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
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.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.modifier.modifierLocalConsumer
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.myapplication.AppViewModelProvider
|
||||
//import com.example.myapplication.Dishes.Model.getAllDishes
|
||||
import com.example.myapplication.Dishes.ui.DishList
|
||||
import com.example.myapplication.User.Model.User
|
||||
import com.example.myapplication.ui.dishes.list.DishList
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.AppDatabase
|
||||
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
||||
import com.example.myapplication.ui.dishes.list.TypeDishList
|
||||
import com.example.myapplication.ui.extra.ErrorElement
|
||||
import com.example.myapplication.ui.extra.ErrorsType
|
||||
//import com.example.myapplication.User.Model.getAllUsers
|
||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||
import com.example.myapplication.ui.theme.textFont
|
||||
@ -40,46 +44,54 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun UserView(id: Int, navController: NavController?) {
|
||||
var user = remember { mutableStateOf(User(0, "", "", "")) }
|
||||
val context = LocalContext.current
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
user.value = AppDatabase.getInstance(context).userDao().getByUid(id)
|
||||
fun UserView (
|
||||
navController: NavController,
|
||||
viewModel: UserViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
userUid: Int?
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val userUiState by viewModel.getUser(userUid ?: 0).collectAsState()
|
||||
|
||||
Scaffold(
|
||||
|
||||
) {innerPadding ->
|
||||
if (userUiState.user == null) {
|
||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_AUTH)
|
||||
}
|
||||
else {
|
||||
UserView(
|
||||
navController = navController,
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
user = userUiState.user!!
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Composable
|
||||
private fun UserView(
|
||||
navController: NavController,
|
||||
modifier: Modifier,
|
||||
user: User
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 5.dp, horizontal = 10.dp)) {
|
||||
Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
|
||||
Column {
|
||||
Text(user.value.nickname, fontFamily= textFont,
|
||||
Text(user.nickname, fontFamily= textFont,
|
||||
fontSize=26.sp, textAlign = TextAlign.Start)
|
||||
}
|
||||
}
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
// Button(onClick = { }, Modifier.fillMaxWidth()) {
|
||||
// Text("Create New Dish")
|
||||
// }
|
||||
}
|
||||
Row(modifier = Modifier.fillMaxSize()) {
|
||||
DishList(navController, someUser = id, userPage = true)
|
||||
DishList(navController, userUid = user.uid, typeDishList = TypeDishList.UserDishes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
@Preview
|
||||
@Composable
|
||||
fun UserPreview() {
|
||||
MyApplicationTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
UserView(id = 0, null)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.example.myapplication.ui.user
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.myapplication.database.AppDataContainer
|
||||
import com.example.myapplication.database.model.Dish
|
||||
import com.example.myapplication.database.model.User
|
||||
import com.example.myapplication.database.repository.DishRepository
|
||||
import com.example.myapplication.database.repository.UserRepository
|
||||
import com.example.myapplication.database.repository.UserWithFavoritesRepository
|
||||
import com.example.myapplication.ui.dishes.list.DishListUiState
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class UserViewModel(
|
||||
private val userRepository: UserRepository,
|
||||
) : ViewModel() {
|
||||
fun getUser(uid: Int) : StateFlow<UserUiState> {
|
||||
return userRepository.getUser(uid).map {
|
||||
UserUiState(it!!)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = UserUiState()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class UserUiState(val user: User? = null)
|
Loading…
Reference in New Issue
Block a user