4 Lab
This commit is contained in:
parent
756cfa14c0
commit
8c81b83717
@ -1,10 +1,13 @@
|
|||||||
package com.example.myapplication
|
package com.example.myapplication
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.createSavedStateHandle
|
||||||
import androidx.lifecycle.viewmodel.CreationExtras
|
import androidx.lifecycle.viewmodel.CreationExtras
|
||||||
import androidx.lifecycle.viewmodel.initializer
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
import com.example.myapplication.ui.dishes.list.DishListViewModel
|
||||||
|
import com.example.myapplication.ui.dishes.view.CategoryDropDownViewModel
|
||||||
|
import com.example.myapplication.ui.dishes.view.DishEditViewModel
|
||||||
import com.example.myapplication.ui.dishes.view.DishViewModel
|
import com.example.myapplication.ui.dishes.view.DishViewModel
|
||||||
import com.example.myapplication.ui.extra.ErrorsViewModel
|
import com.example.myapplication.ui.extra.ErrorsViewModel
|
||||||
import com.example.myapplication.ui.user.UserViewModel
|
import com.example.myapplication.ui.user.UserViewModel
|
||||||
@ -25,6 +28,15 @@ object AppViewModelProvider {
|
|||||||
initializer {
|
initializer {
|
||||||
DishViewModel(foodWarriorsApplication().container.dishRepository)
|
DishViewModel(foodWarriorsApplication().container.dishRepository)
|
||||||
}
|
}
|
||||||
|
initializer {
|
||||||
|
DishEditViewModel(
|
||||||
|
this.createSavedStateHandle(),
|
||||||
|
foodWarriorsApplication().container.dishRepository
|
||||||
|
)
|
||||||
|
}
|
||||||
|
initializer {
|
||||||
|
CategoryDropDownViewModel(foodWarriorsApplication().container.categoryRepository)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
@Dao
|
@Dao
|
||||||
interface CategoryDao {
|
interface CategoryDao {
|
||||||
@Query("select * from categories order by category_name collate nocase asc")
|
@Query("select * from categories order by category_name collate nocase asc")
|
||||||
fun getAll(): Flow<List<Category>>
|
suspend fun getAll(): List<Category>
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
suspend fun insert(category: Category)
|
suspend fun insert(category: Category)
|
||||||
|
@ -4,5 +4,5 @@ import com.example.myapplication.database.model.Category
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface CategoryRepository {
|
interface CategoryRepository {
|
||||||
fun getAllCategories(): Flow<List<Category>>
|
suspend fun getAllCategories(): List<Category>
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ import com.example.myapplication.database.model.Category
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
class OfflineCategoryRepository(private val categoryDao: CategoryDao) : CategoryRepository {
|
class OfflineCategoryRepository(private val categoryDao: CategoryDao) : CategoryRepository {
|
||||||
override fun getAllCategories(): Flow<List<Category>> {
|
override suspend fun getAllCategories(): List<Category> {
|
||||||
return categoryDao.getAll();
|
return categoryDao.getAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.example.myapplication.ui.dishes.view
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.example.myapplication.database.model.Category
|
||||||
|
import com.example.myapplication.database.repository.CategoryRepository
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class CategoryDropDownViewModel(
|
||||||
|
private val categoryRepository: CategoryRepository
|
||||||
|
) : ViewModel() {
|
||||||
|
var categoryListUiState by mutableStateOf(CategoryListUiState())
|
||||||
|
private set
|
||||||
|
|
||||||
|
var categoryUiState by mutableStateOf(CategoryUiState())
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
categoryListUiState = CategoryListUiState(categoryRepository.getAllCategories())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCurrentCategory(categoryId: Int) {
|
||||||
|
val category: Category? =
|
||||||
|
categoryListUiState.categoryList.firstOrNull { category -> category.uid == categoryId }
|
||||||
|
category?.let { updateUiState(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateUiState(category: Category) {
|
||||||
|
categoryUiState = CategoryUiState(
|
||||||
|
category = category
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CategoryListUiState(val categoryList: List<Category> = listOf())
|
||||||
|
|
||||||
|
data class CategoryUiState(
|
||||||
|
val category: Category? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Category.toUiState() = CategoryUiState(category = Category(uid = uid, name = name))
|
@ -0,0 +1,156 @@
|
|||||||
|
package com.example.myapplication.ui.dishes.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.myapplication.AppViewModelProvider
|
||||||
|
import com.example.myapplication.R
|
||||||
|
import com.example.myapplication.database.model.Category
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun DishEditView (
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: DishEditViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||||
|
categoryViewModel: CategoryDropDownViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||||
|
userUid: Int
|
||||||
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
categoryViewModel.setCurrentCategory(viewModel.dishEditUiState.dishDetails.categoryUid!!)
|
||||||
|
viewModel.setCurrentUser(userUid)
|
||||||
|
DishEditView(
|
||||||
|
dishUiState = viewModel.dishEditUiState,
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
viewModel.saveDish()
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onUpdate = viewModel::updateUiState,
|
||||||
|
categoryUiState = categoryViewModel.categoryUiState,
|
||||||
|
categoryListUiState = categoryViewModel.categoryListUiState,
|
||||||
|
onCategoryUpdate = categoryViewModel::updateUiState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun CategoryDropDown(
|
||||||
|
categoryUiState: CategoryUiState,
|
||||||
|
categoryListUiState: CategoryListUiState,
|
||||||
|
onCategoryUpdate: (Category) -> Unit
|
||||||
|
) {
|
||||||
|
var expanded: Boolean by remember { mutableStateOf(false) }
|
||||||
|
ExposedDropdownMenuBox(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 7.dp),
|
||||||
|
expanded = expanded,
|
||||||
|
onExpandedChange = {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
TextField(
|
||||||
|
value = categoryUiState.category?.name
|
||||||
|
?: stringResource(id = R.string.category_not_found),
|
||||||
|
onValueChange = {},
|
||||||
|
readOnly = true,
|
||||||
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.menuAnchor()
|
||||||
|
)
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false },
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color.White)
|
||||||
|
.exposedDropdownSize()
|
||||||
|
) {
|
||||||
|
categoryListUiState.categoryList.forEach { category ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = {
|
||||||
|
Text(text = category.name)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
onCategoryUpdate(category)
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun DishEditView(
|
||||||
|
dishUiState: DishEditUiState,
|
||||||
|
categoryUiState: CategoryUiState,
|
||||||
|
categoryListUiState: CategoryListUiState,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
onUpdate: (DishDetails) -> Unit,
|
||||||
|
onCategoryUpdate: (Category) -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 10.dp)
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = dishUiState.dishDetails.name,
|
||||||
|
onValueChange = { onUpdate(dishUiState.dishDetails.copy(name = it)) },
|
||||||
|
label = { Text(stringResource(id = R.string.dish_label)) },
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = dishUiState.dishDetails.description,
|
||||||
|
onValueChange = { onUpdate(dishUiState.dishDetails.copy(description = it)) },
|
||||||
|
label = { Text(stringResource(id = R.string.dish_description)) },
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
CategoryDropDown(
|
||||||
|
categoryUiState = categoryUiState,
|
||||||
|
categoryListUiState = categoryListUiState,
|
||||||
|
onCategoryUpdate = {
|
||||||
|
onUpdate(dishUiState.dishDetails.copy(categoryUid = it.uid))
|
||||||
|
onCategoryUpdate(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
enabled = dishUiState.isEntryValid,
|
||||||
|
shape = MaterialTheme.shapes.small,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.dish_save))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.example.myapplication.ui.dishes.view
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.example.myapplication.database.model.Category
|
||||||
|
import com.example.myapplication.database.model.Dish
|
||||||
|
import com.example.myapplication.database.model.User
|
||||||
|
import com.example.myapplication.database.repository.DishRepository
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class DishEditViewModel (
|
||||||
|
savedStateHandle: SavedStateHandle,
|
||||||
|
private val dishRepository: DishRepository
|
||||||
|
) : ViewModel() {
|
||||||
|
var dishEditUiState by mutableStateOf(DishEditUiState())
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val dishUid: Int = checkNotNull(savedStateHandle["id"])
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
if (dishUid > 0) {
|
||||||
|
dishEditUiState = dishRepository.getDish(dishUid)
|
||||||
|
.filterNotNull()
|
||||||
|
.first().dish!!
|
||||||
|
.toUiState(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun updateUiState(dishDetails: DishDetails) {
|
||||||
|
dishEditUiState = DishEditUiState(
|
||||||
|
dishDetails = dishDetails,
|
||||||
|
isEntryValid = validateInput(dishDetails)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCurrentUser(userId: Int) {
|
||||||
|
val dish: DishDetails? =
|
||||||
|
dishEditUiState.dishDetails.copy(userUid = userId)
|
||||||
|
dish?.let { updateUiState(it) }
|
||||||
|
}
|
||||||
|
suspend fun saveDish() {
|
||||||
|
if (validateInput()) {
|
||||||
|
if (dishUid > 0) {
|
||||||
|
dishRepository.updateDish(dishEditUiState.dishDetails.toDish(dishUid))
|
||||||
|
} else {
|
||||||
|
// dishEditUiState.dishDetails.copy(uid)
|
||||||
|
dishRepository.insertDish(dishEditUiState.dishDetails.toDish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateInput(uiState: DishDetails = dishEditUiState.dishDetails): Boolean {
|
||||||
|
return with(uiState) {
|
||||||
|
name.isNotBlank()
|
||||||
|
&& description.isNotBlank()
|
||||||
|
&& userUid!! > 0
|
||||||
|
&& categoryUid!! > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class DishEditUiState(
|
||||||
|
val dishDetails: DishDetails = DishDetails(),
|
||||||
|
val isEntryValid: Boolean = false
|
||||||
|
)
|
||||||
|
data class DishDetails(
|
||||||
|
val name: String = "",
|
||||||
|
val description: String = "",
|
||||||
|
val image: ByteArray? = null,
|
||||||
|
val userUid: Int? = 0,
|
||||||
|
val categoryUid: Int? = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
fun DishDetails.toDish(uid: Int? = null): Dish = Dish(
|
||||||
|
uid = uid,
|
||||||
|
name = name,
|
||||||
|
description = description,
|
||||||
|
image = image,
|
||||||
|
userId = userUid,
|
||||||
|
categoryId = categoryUid
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Dish.toDetails(): DishDetails = DishDetails(
|
||||||
|
name = name,
|
||||||
|
description = description,
|
||||||
|
image = image,
|
||||||
|
userUid = userId,
|
||||||
|
categoryUid = categoryId
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Dish.toUiState(isEntryValid: Boolean = false): DishEditUiState = DishEditUiState(
|
||||||
|
dishDetails = this.toDetails(),
|
||||||
|
isEntryValid = isEntryValid
|
||||||
|
)
|
@ -11,7 +11,11 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
@ -42,6 +46,7 @@ import com.example.myapplication.database.AppDatabase
|
|||||||
import com.example.myapplication.ui.dishes.view.DishViewModel
|
import com.example.myapplication.ui.dishes.view.DishViewModel
|
||||||
import com.example.myapplication.ui.extra.ErrorElement
|
import com.example.myapplication.ui.extra.ErrorElement
|
||||||
import com.example.myapplication.ui.extra.ErrorsType
|
import com.example.myapplication.ui.extra.ErrorsType
|
||||||
|
import com.example.myapplication.ui.navigation.Screen
|
||||||
//import com.example.myapplication.Dishes.Model.getAllDishes
|
//import com.example.myapplication.Dishes.Model.getAllDishes
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
import com.example.myapplication.ui.theme.textFont
|
import com.example.myapplication.ui.theme.textFont
|
||||||
@ -59,7 +64,18 @@ fun DishView(navController: NavController,
|
|||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val dishUiState by viewModel.getDish(dishUid ?: 0).collectAsState()
|
val dishUiState by viewModel.getDish(dishUid ?: 0).collectAsState()
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
floatingActionButton = {
|
||||||
|
if (dishUiState.dish?.dish?.userId == userUid) {
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
val route = Screen.DishEdit.route.replace("{id}", dishUid.toString())
|
||||||
|
navController.navigate(route)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.Add, "Добавить")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
){ innerPadding ->
|
){ innerPadding ->
|
||||||
if (dishUiState.dish == null) {
|
if (dishUiState.dish == null) {
|
||||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_FOUND)
|
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_FOUND)
|
||||||
|
@ -3,10 +3,8 @@ package com.example.myapplication.ui.dishes.view
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.example.myapplication.database.AppDataContainer
|
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.model.DishWithCategoryAndUser
|
||||||
import com.example.myapplication.database.repository.DishRepository
|
import com.example.myapplication.database.repository.DishRepository
|
||||||
import com.example.myapplication.ui.user.UserUiState
|
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@ -15,15 +13,15 @@ import kotlinx.coroutines.flow.stateIn
|
|||||||
class DishViewModel(
|
class DishViewModel(
|
||||||
private val dishRepository: DishRepository
|
private val dishRepository: DishRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
fun getDish(uid: Int) : StateFlow<DishUiState> {
|
fun getDish(uid: Int) : StateFlow<DishViewUiState> {
|
||||||
return dishRepository.getDish(uid).map {
|
return dishRepository.getDish(uid).map {
|
||||||
DishUiState(it!!)
|
DishViewUiState(it!!)
|
||||||
}.stateIn(
|
}.stateIn(
|
||||||
scope = viewModelScope,
|
scope = viewModelScope,
|
||||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||||
initialValue = DishUiState()
|
initialValue = DishViewUiState()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class DishUiState(val dish: DishWithCategoryAndUser? = null)
|
data class DishViewUiState(val dish: DishWithCategoryAndUser? = null)
|
@ -29,6 +29,7 @@ import com.example.myapplication.database.model.User
|
|||||||
import com.example.myapplication.ui.components.Navbar
|
import com.example.myapplication.ui.components.Navbar
|
||||||
import com.example.myapplication.ui.dishes.DishView
|
import com.example.myapplication.ui.dishes.DishView
|
||||||
import com.example.myapplication.ui.dishes.list.TypeDishList
|
import com.example.myapplication.ui.dishes.list.TypeDishList
|
||||||
|
import com.example.myapplication.ui.dishes.view.DishEditView
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
import com.example.myapplication.ui.user.UserView
|
import com.example.myapplication.ui.user.UserView
|
||||||
|
|
||||||
@ -56,6 +57,11 @@ fun Navhost(
|
|||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
backStackEntry.arguments?.let { DishView(navController, userUid = userUid, dishUid = it.getInt("id")) }
|
backStackEntry.arguments?.let { DishView(navController, userUid = userUid, dishUid = it.getInt("id")) }
|
||||||
}
|
}
|
||||||
|
composable(Screen.DishEdit.route,
|
||||||
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
|
) {
|
||||||
|
DishEditView(navController = navController, userUid=userUid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.AccountCircle
|
import androidx.compose.material.icons.filled.AccountCircle
|
||||||
import androidx.compose.material.icons.filled.Favorite
|
import androidx.compose.material.icons.filled.Favorite
|
||||||
import androidx.compose.material.icons.filled.Info
|
import androidx.compose.material.icons.filled.Info
|
||||||
import androidx.compose.material.icons.filled.List
|
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import com.example.myapplication.R
|
import com.example.myapplication.R
|
||||||
|
|
||||||
@ -19,14 +18,16 @@ enum class Screen(
|
|||||||
AllDishes("all-dishes", R.string.all_dishes, icon_id = R.drawable.cooking_book),
|
AllDishes("all-dishes", R.string.all_dishes, icon_id = R.drawable.cooking_book),
|
||||||
DishView("dish/{id}", R.string.all_dishes, icon=Icons.Filled.Info),
|
DishView("dish/{id}", R.string.all_dishes, icon=Icons.Filled.Info),
|
||||||
FavoriteDishes("favorite-dishes", R.string.favorite_dishes, icon=Icons.Filled.Favorite),
|
FavoriteDishes("favorite-dishes", R.string.favorite_dishes, icon=Icons.Filled.Favorite),
|
||||||
UserPage("user", R.string.account_title, icon=Icons.Filled.AccountCircle);
|
UserPage("user", R.string.account_title, icon=Icons.Filled.AccountCircle),
|
||||||
|
DishEdit("dish-edit/{id}", R.string.all_dishes);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val navbarItems = listOf(
|
val navbarItems = listOf(
|
||||||
FavoriteDishes,
|
FavoriteDishes,
|
||||||
AllDishes,
|
AllDishes,
|
||||||
UserPage
|
UserPage,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getItem(route: String): Screen? {
|
fun getItem(route: String): Screen? {
|
||||||
|
@ -8,22 +8,19 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
@ -32,16 +29,12 @@ import com.example.myapplication.AppViewModelProvider
|
|||||||
//import com.example.myapplication.Dishes.Model.getAllDishes
|
//import com.example.myapplication.Dishes.Model.getAllDishes
|
||||||
import com.example.myapplication.ui.dishes.list.DishList
|
import com.example.myapplication.ui.dishes.list.DishList
|
||||||
import com.example.myapplication.database.model.User
|
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.dishes.list.TypeDishList
|
||||||
import com.example.myapplication.ui.extra.ErrorElement
|
import com.example.myapplication.ui.extra.ErrorElement
|
||||||
import com.example.myapplication.ui.extra.ErrorsType
|
import com.example.myapplication.ui.extra.ErrorsType
|
||||||
|
import com.example.myapplication.ui.navigation.Screen
|
||||||
//import com.example.myapplication.User.Model.getAllUsers
|
//import com.example.myapplication.User.Model.getAllUsers
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
|
||||||
import com.example.myapplication.ui.theme.textFont
|
import com.example.myapplication.ui.theme.textFont
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.Q)
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -55,7 +48,16 @@ fun UserView (
|
|||||||
val userUiState by viewModel.getUser(userUid ?: 0).collectAsState()
|
val userUiState by viewModel.getUser(userUid ?: 0).collectAsState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
floatingActionButton = {
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
val route = Screen.DishEdit.route.replace("{id}", 0.toString())
|
||||||
|
navController.navigate(route)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.Add, "Добавить")
|
||||||
|
}
|
||||||
|
}
|
||||||
) {innerPadding ->
|
) {innerPadding ->
|
||||||
if (userUiState.user == null) {
|
if (userUiState.user == null) {
|
||||||
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_AUTH)
|
ErrorElement(navController = navController, typeErrorsType = ErrorsType.NOT_AUTH)
|
||||||
|
@ -10,7 +10,9 @@ Quisque efficitur, nunc vitae varius faucibus, turpis nunc ullamcorper neque, in
|
|||||||
Donec molestie scelerisque sollicitudin. Duis orci felis, lacinia laoreet scelerisque sed, molestie sed ipsum. Duis auctor aliquet laoreet. Mauris vitae commodo nibh. Sed pulvinar metus lacus, a faucibus nulla ornare ultricies. Aliquam varius sem a nibh dapibus congue. Phasellus dignissim nibh diam. Etiam elit nulla, bibendum ac quam sed, dictum condimentum ligula.
|
Donec molestie scelerisque sollicitudin. Duis orci felis, lacinia laoreet scelerisque sed, molestie sed ipsum. Duis auctor aliquet laoreet. Mauris vitae commodo nibh. Sed pulvinar metus lacus, a faucibus nulla ornare ultricies. Aliquam varius sem a nibh dapibus congue. Phasellus dignissim nibh diam. Etiam elit nulla, bibendum ac quam sed, dictum condimentum ligula.
|
||||||
Phasellus eget ex sed tortor placerat suscipit quis quis magna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mi quam, auctor quis ante nec, condimentum maximus justo. Morbi varius est massa. Integer nec semper mi. Fusce nisl neque, mollis quis tempus eget, vulputate vitae sem. Donec sit amet maximus augue. Quisque sit amet ante fermentum, bibendum mi ut, porta eros. Phasellus ultrices, augue a fringilla accumsan, elit arcu vehicula lectus, condimentum malesuada lectus enim nec tellus. Nunc ante erat, convallis a dui vitae, rhoncus rhoncus metus. Suspendisse in sapien odio.
|
Phasellus eget ex sed tortor placerat suscipit quis quis magna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mi quam, auctor quis ante nec, condimentum maximus justo. Morbi varius est massa. Integer nec semper mi. Fusce nisl neque, mollis quis tempus eget, vulputate vitae sem. Donec sit amet maximus augue. Quisque sit amet ante fermentum, bibendum mi ut, porta eros. Phasellus ultrices, augue a fringilla accumsan, elit arcu vehicula lectus, condimentum malesuada lectus enim nec tellus. Nunc ante erat, convallis a dui vitae, rhoncus rhoncus metus. Suspendisse in sapien odio.
|
||||||
Cras semper magna id libero gravida, at varius elit molestie. Quisque ullamcorper nisi tincidunt, feugiat justo nec, aliquam massa. Quisque sit amet quam semper, pretium justo non, tincidunt lorem. Proin rhoncus turpis orci, efficitur dignissim ex sollicitudin eget. Etiam porttitor est eget erat pellentesque, ut maximus mi dictum. Pellentesque ac mauris non eros mollis pharetra et eu augue. Nam a bibendum ipsum, vel pellentesque nisi. Nam gravida dolor sed risus ornare dignissim. Praesent semper, tellus sed posuere efficitur, neque justo efficitur dui, et mollis leo ex in quam. Fusce pulvinar turpis a justo pretium semper. Integer dapibus, risus vel facilisis porttitor, eros sapien venenatis risus, eget aliquet lectus ipsum a orci. Ut at arcu a augue varius gravida non sit amet quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam eget enim eu mauris rutrum pulvinar.
|
Cras semper magna id libero gravida, at varius elit molestie. Quisque ullamcorper nisi tincidunt, feugiat justo nec, aliquam massa. Quisque sit amet quam semper, pretium justo non, tincidunt lorem. Proin rhoncus turpis orci, efficitur dignissim ex sollicitudin eget. Etiam porttitor est eget erat pellentesque, ut maximus mi dictum. Pellentesque ac mauris non eros mollis pharetra et eu augue. Nam a bibendum ipsum, vel pellentesque nisi. Nam gravida dolor sed risus ornare dignissim. Praesent semper, tellus sed posuere efficitur, neque justo efficitur dui, et mollis leo ex in quam. Fusce pulvinar turpis a justo pretium semper. Integer dapibus, risus vel facilisis porttitor, eros sapien venenatis risus, eget aliquet lectus ipsum a orci. Ut at arcu a augue varius gravida non sit amet quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam eget enim eu mauris rutrum pulvinar.
|
||||||
|
|
||||||
|
|
||||||
</string>
|
</string>
|
||||||
|
<string name="dish_label">Name of dish</string>
|
||||||
|
<string name="dish_description">Description</string>
|
||||||
|
<string name="dish_save">Save</string>
|
||||||
|
<string name="category_not_found">Choose category</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user