This commit is contained in:
Артём Батылкин 2023-11-28 00:20:41 +04:00
parent d3b6668a51
commit aa2c281558
18 changed files with 495 additions and 252 deletions

View File

@ -83,4 +83,9 @@ dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4") androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest") debugImplementation("androidx.compose.ui:ui-test-manifest")
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2")
} }

View File

@ -16,7 +16,7 @@ import com.example.todolisttask.models.model.Task
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CreateTask(navController: NavController, onSaveClick: (Task) -> Unit) { fun CreateTask(navController: NavController, userId: Int , onSaveClick: (Task) -> Unit) {
var taskName by remember { mutableStateOf("") } var taskName by remember { mutableStateOf("") }
var taskDescription by remember { mutableStateOf("") } var taskDescription by remember { mutableStateOf("") }
@ -48,19 +48,19 @@ fun CreateTask(navController: NavController, onSaveClick: (Task) -> Unit) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// Button( Button(
// onClick = { onClick = {
// if (taskName.isNotEmpty()) { if (taskName.isNotEmpty()) {
// val newTask = Task(0, taskName, taskDescription) val newTask = Task(taskName, taskDescription, userId)
// onSaveClick(newTask) onSaveClick(newTask)
// taskName = "" taskName = ""
//
// navController.popBackStack() navController.popBackStack()
// } }
// }, },
// modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
// ) { ) {
// Text("Сохранить") Text("Сохранить")
// } }
} }
} }

View File

@ -1,6 +1,12 @@
package com.example.todolisttask.composeui package com.example.todolisttask.composeui
import android.annotation.SuppressLint
import android.os.Build.* import android.os.Build.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -29,17 +35,19 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.todolisttask.composeui.navigation.Screen import com.example.todolisttask.composeui.navigation.Screen
import com.example.todolisttask.models.model.AuthViewModel import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.TaskViewModel import com.example.todolisttask.models.model.Task
import com.example.todolisttask.models.model.UserViewModel import com.example.todolisttask.models.model.User
import com.example.todolisttask.models.model.ViewModels.TaskViewModel
import com.example.todolisttask.models.model.ViewModels.UserViewModel
import kotlinx.coroutines.coroutineScope
@RequiresApi(VERSION_CODES.O) @RequiresApi(VERSION_CODES.O)
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("RememberReturnType")
@Composable @Composable
fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, taskId : Int) { fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, task : Task?, onSaveClick: (Task) -> Unit) {
val task = (authViewModel.currentUser?.taskId ?: emptyList()).find { it.id == taskId } var taskName = remember { mutableStateOf(task?.name.orEmpty()) }
var taskDescriptions = remember { mutableStateOf(task?.description.orEmpty()) }
var taskName by remember { mutableStateOf(task?.name ?: "") }
var taskDescriptions by remember { mutableStateOf(task?.description ?: "") }
Column( Column(
modifier = Modifier modifier = Modifier
@ -48,8 +56,8 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
OutlinedTextField( OutlinedTextField(
value = taskName, value = taskName.value,
onValueChange = { taskName = it }, onValueChange = { taskName.value = it },
label = { Text("Название задания") }, label = { Text("Название задания") },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -57,8 +65,8 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie
) )
OutlinedTextField( OutlinedTextField(
value = taskDescriptions, value = taskDescriptions.value,
onValueChange = { taskDescriptions = it }, onValueChange = { taskDescriptions.value = it },
label = { Text("Описание задания") }, label = { Text("Описание задания") },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -75,11 +83,12 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie
Button( Button(
onClick = { onClick = {
val updatedTask = task?.copy(name = taskName, description = taskDescriptions) ?: return@Button val updatedTask = Task(
task?.uid ?:0,
taskViewModel.updateTask(updatedTask) taskName.value,
userViewModel.updateTaskOnUser(authViewModel.currentUser?.id ?: -1, updatedTask) taskDescriptions.value,
authViewModel.currentUser=userViewModel.getUser(authViewModel.currentUser?.id ?: -1) task?.userId ?:0)
onSaveClick(updatedTask)
navController.popBackStack() navController.popBackStack()
}, },
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(16.dp)
@ -88,4 +97,6 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie
} }
} }
} }

View File

@ -13,13 +13,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.todolisttask.models.model.AuthViewModel import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.TaskViewModel import com.example.todolisttask.models.model.ViewModels.TaskViewModel
import com.example.todolisttask.models.model.UserViewModel import com.example.todolisttask.models.model.ViewModels.UserViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("RememberReturnType") @SuppressLint("RememberReturnType")
@Composable @Composable
fun Favorite(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel) { fun Favorite(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel) {
/*
Column( Column(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
@ -29,4 +30,6 @@ fun Favorite(navController: NavController, authViewModel: AuthViewModel, taskVie
TaskList(navController, authViewModel, taskViewModel, userViewModel, authViewModel.currentUser?.id ?: -1, showFavorites = true) TaskList(navController, authViewModel, taskViewModel, userViewModel, authViewModel.currentUser?.id ?: -1, showFavorites = true)
} }
*/
} }

View File

@ -1,6 +1,7 @@
*/
package com.example.todolisttask.composeui package com.example.todolisttask.composeui
import com.example.todolisttask.models.model.ViewModels.TaskViewModel
import com.example.todolisttask.models.model.ViewModels.UserViewModel
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -16,9 +17,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.todolisttask.composeui.navigation.Screen import com.example.todolisttask.composeui.navigation.Screen
import com.example.todolisttask.models.composeui.TaskList
import com.example.todolisttask.models.model.AuthViewModel import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.TaskViewModel
import com.example.todolisttask.models.model.UserViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("RememberReturnType") @SuppressLint("RememberReturnType")
@ -39,7 +39,7 @@ fun Home(navController: NavController, authViewModel: AuthViewModel, taskViewMod
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
TaskList(navController, authViewModel, taskViewModel, userViewModel, authViewModel.currentUser?.id ?: -1) TaskList(navController, authViewModel, taskViewModel, userViewModel, authViewModel.currentUser?.value?.uid ?: -1)
} }
} }

View File

@ -20,18 +20,21 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.todolisttask.composeui.navigation.Screen import com.example.todolisttask.composeui.navigation.Screen
import com.example.todolisttask.models.model.AuthViewModel import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.User import com.example.todolisttask.models.model.User
import com.example.todolisttask.models.model.ViewModels.UserViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun Login( fun Login(
navController: NavHostController, navController: NavHostController,
authViewModel: AuthViewModel, authViewModel: AuthViewModel
users: List<User>
) { ) {
var username by remember { mutableStateOf("") } var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") } var password by remember { mutableStateOf("") }
@ -67,12 +70,18 @@ fun Login(
Button( Button(
onClick = { onClick = {
val authenticatedUser = users.find { it.login == username && it.password == password } authViewModel.viewModelScope.launch {
if (authenticatedUser != null) { authViewModel.loginUser(username, password)
authViewModel.currentUser = authenticatedUser
navController.navigate(Screen.Home.route) // Добавляем небольшую задержку (например, 100 мс) для обеспечения завершения операции входа в систему
} else { delay(1000)
println("Authentication failed")
val authenticatedUser = authViewModel.currentUser.value
if (authenticatedUser != null) {
navController.navigate(Screen.Home.route)
} else {
println("Аутентификация не удалась")
}
} }
}, },
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()

View File

@ -1,4 +1,4 @@
package com.example.pmuapp.composeui package com.example.todolisttask.composeui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.net.Uri import android.net.Uri
@ -35,7 +35,7 @@ import kotlinx.coroutines.flow.callbackFlow
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("RememberReturnType") @SuppressLint("RememberReturnType")
@Composable @Composable
fun Profile(navController: NavController, currentUser: User?, onSaveClick: (User) -> Unit) { fun Profile(navController: NavController,currentUser: User?, onSaveClick: (User) -> Unit) {
val nameState = remember { mutableStateOf(currentUser?.name.orEmpty()) } val nameState = remember { mutableStateOf(currentUser?.name.orEmpty()) }
val loginState = remember { mutableStateOf(currentUser?.login.orEmpty()) } val loginState = remember { mutableStateOf(currentUser?.login.orEmpty()) }
val passwordState = remember { mutableStateOf(currentUser?.password.orEmpty()) } val passwordState = remember { mutableStateOf(currentUser?.password.orEmpty()) }
@ -76,12 +76,10 @@ fun Profile(navController: NavController, currentUser: User?, onSaveClick: (User
Button( Button(
onClick = { onClick = {
val updatedUser = User( val updatedUser = User(
currentUser?.id ?: 0, currentUser?.uid ?: 0,
nameState.value, nameState.value,
loginState.value, loginState.value,
passwordState.value, passwordState.value,
currentUser?.taskId ?: emptyList(),
currentUser?.favoritetask?: emptyList()
) )
onSaveClick(updatedUser) onSaveClick(updatedUser)
}, },
@ -90,4 +88,5 @@ fun Profile(navController: NavController, currentUser: User?, onSaveClick: (User
Text("Сохранить") Text("Сохранить")
} }
} }
} }

View File

@ -2,6 +2,7 @@ package com.example.todolisttask.composeui.navigation
import CreateTask import CreateTask
import android.annotation.SuppressLint
import android.os.Build import android.os.Build
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -19,12 +20,14 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
@ -34,15 +37,22 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.example.pmuapp.composeui.Profile import com.example.todolisttask.composeui.Profile
import com.example.todolisttask.AppDatabase
import com.example.todolisttask.R import com.example.todolisttask.R
import com.example.todolisttask.composeui.EditTask import com.example.todolisttask.composeui.EditTask
import com.example.todolisttask.composeui.Favorite import com.example.todolisttask.composeui.Favorite
import com.example.todolisttask.models.model.AuthViewModel import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.TaskViewModel
import com.example.todolisttask.models.model.UserViewModel
import com.example.todolisttask.composeui.Login import com.example.todolisttask.composeui.Login
import com.example.todolisttask.composeui.Home import com.example.todolisttask.composeui.Home
import com.example.todolisttask.models.dao.TaskDao
import com.example.todolisttask.models.dao.UserDao
import com.example.todolisttask.models.model.ViewModels.TaskViewModel
import com.example.todolisttask.models.model.ViewModels.UserViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -102,6 +112,7 @@ fun Navbar(
} }
} }
@SuppressLint("StateFlowValueCalledInComposition", "SuspiciousIndentation")
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
@Composable @Composable
fun NavHost( fun NavHost(
@ -117,41 +128,44 @@ fun NavHost(
modifier = Modifier.padding(innerPadding) modifier = Modifier.padding(innerPadding)
) { ) {
composable(Screen.Login.route) { composable(Screen.Login.route) {
Login(navController, authViewModel,userViewModel.getUsers()) } Login(navController, authViewModel) }
composable(Screen.Logout.route) { composable(Screen.Logout.route) {
Login(navController, authViewModel,userViewModel.getUsers()) } Login(navController, authViewModel) }
//
composable(Screen.CreateTask.route) { composable(Screen.CreateTask.route) {
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() val currentUser = authViewModel.currentUser
CreateTask ( navController, onSaveClick = { newTask -> val id: Int = currentUser.value?.uid?.toInt() ?: 0
var adedTask = taskViewModel.createTask(newTask) CreateTask ( navController, id , onSaveClick = { newTask ->
userViewModel.addPetToUser(currentUser?.id ?:0, adedTask) taskViewModel.createTask(newTask)
authViewModel.currentUser = userViewModel.getUser(currentUser?.id ?:0) //userViewModel.addTask(currentUser?.id ?:0, adedTask)
authViewModel.updateCurrentUset(id)
} }
) )
} }
//
composable(Screen.Favorite.route){ // composable(Screen.Favorite.route){
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() // val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull()
if (currentUser != null) { // if (currentUser != null) {
Favorite(navController, // Favorite(navController,
authViewModel, // authViewModel,
taskViewModel, // taskViewModel,
userViewModel // userViewModel
) // )
} else { // } else {
} // }
//
} // }
//
composable(Screen.Profile.route) { composable(Screen.Profile.route) {
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() val currentUser = authViewModel.currentUser.collectAsState()
if (currentUser != null) { if (currentUser != null) {
Profile(navController, Profile(navController,
currentUser = currentUser, currentUser = currentUser.value,
onSaveClick = {updatedUser -> onSaveClick = {updatedUser ->
userViewModel.updateUser(updatedUser) userViewModel.updateUser(updatedUser)
authViewModel.currentUser = updatedUser authViewModel.updateCurrentUset(currentUser?.value?.uid ?:-1)
navController.navigate(Screen.Profile.route) navController.navigate(Screen.Profile.route)
} }
) )
@ -160,7 +174,7 @@ fun NavHost(
} }
composable(Screen.Home.route){ composable(Screen.Home.route){
val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() val currentUser = authViewModel.currentUser
if (currentUser != null) { if (currentUser != null) {
Home(navController, Home(navController,
authViewModel, authViewModel,
@ -176,10 +190,13 @@ fun NavHost(
arguments = listOf(navArgument("id") { type = NavType.IntType }) arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry -> ) { backStackEntry ->
val petId = backStackEntry.arguments?.getInt("id") ?: -1 val petId = backStackEntry.arguments?.getInt("id") ?: -1
EditTask(navController,authViewModel, taskViewModel, userViewModel, petId) val task = taskViewModel.getTask(petId)
EditTask(navController,authViewModel, taskViewModel, userViewModel, task.value,
onSaveClick = {updatedTask ->
taskViewModel.viewModelScope.launch {
taskViewModel.updateTask(updatedTask)
authViewModel.updateCurrentUset(id)}})
} }
} }
} }
@ -188,9 +205,13 @@ fun NavHost(
@Composable @Composable
fun MainNavbar() { fun MainNavbar() {
val navController = rememberNavController() val navController = rememberNavController()
val authViewModel = remember { AuthViewModel() } val context = LocalContext.current
val userViewModel = remember {UserViewModel() } val database: AppDatabase = AppDatabase.getInstance(context)
val taskViewModel = remember {TaskViewModel()} val userDao: UserDao = database.userDao()
val taskDao: TaskDao = database.taskDao()
val authViewModel = remember { AuthViewModel(userDao) }
val userViewModel = remember { UserViewModel(userDao) }
val taskViewModel = remember { TaskViewModel(taskDao) }
val navBackStackEntry by navController.currentBackStackEntryAsState() val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination val currentDestination = navBackStackEntry?.destination
val currentScreen = currentDestination?.route?.let { Screen.getItem(it) } val currentScreen = currentDestination?.route?.let { Screen.getItem(it) }

View File

@ -1,52 +1,161 @@
package com.example.todolisttask.models.composeui package com.example.todolisttask.models.composeui
import android.annotation.SuppressLint
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowColumn
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface 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.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview 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.lifecycle.viewModelScope
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.todolisttask.AppDatabase import com.example.todolisttask.AppDatabase
import com.example.todolisttask.composeui.navigation.Screen import com.example.todolisttask.composeui.navigation.Screen
import com.example.todolisttask.models.model.AuthViewModel
import com.example.todolisttask.models.model.Task import com.example.todolisttask.models.model.Task
import com.example.todolisttask.models.model.ViewModels.TaskViewModel
import com.example.todolisttask.models.model.ViewModels.UserViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.forEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@SuppressLint("StateFlowValueCalledInComposition")
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
@Composable @Composable
fun TaskList(navController: NavController?) { fun TaskList(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, userId: Int, showFavorites: Boolean = false) {
val context = LocalContext.current
val tasks = remember { mutableStateListOf<Task>() }
LaunchedEffect(Unit) { val currentUser by userViewModel.user.collectAsState()
withContext(Dispatchers.IO) { taskViewModel.getTasksByUser(userId)
val taskList = AppDatabase.getInstance(context).taskDao().getAll() var tasks = taskViewModel.tasks.value
tasks.clear()
tasks.addAll(taskList) LazyColumn(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
if (userId != authViewModel.currentUser?.value?.uid ?: -1) {
item {
Text(
text = currentUser?.name + " (" + currentUser?.login + ")",
style = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Bold
),
modifier = Modifier.padding(16.dp)
)
}
} }
}
Column(Modifier.padding(all = 10.dp)) { item {
tasks.forEach { task -> FlowColumn() {
key(task.uid) { tasks.forEach { task ->
val taskId = Screen.Home.route.replace("{id}", task.uid.toString()) val taskName = task.name
Button( val taskDescription = task.description
modifier = Modifier
.fillMaxWidth() FlowRow(
.padding(all = 10.dp), modifier = Modifier
onClick = { navController?.navigate(taskId) }) { .padding(8.dp)
Text("${task.name} ${task.description}") .border(
1.dp,
Color.Black,
),
horizontalArrangement = Arrangement.SpaceBetween
) {
IconButton(
onClick = {
navController?.navigate(
Screen.EditTask.route.replace(
"{id}",
task.uid.toString()
)
)
},
) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = "Изменить"
)
}
Column(
modifier = Modifier
.weight(1f)
.padding(top = 4.dp)
) {
Text(
text = taskName,
style = TextStyle(
fontWeight = FontWeight.Bold
)
)
if (taskDescription.isNotBlank()) {
Text(
text = taskDescription
)
}
}
IconButton(
onClick = {
taskViewModel.viewModelScope.launch {
taskViewModel.deleteTask(task)
/* userViewModel.deleteTask(
currentUser?.id ?: 0,
task.id
)*/
authViewModel.updateCurrentUset(authViewModel.currentUser?.value?.uid ?:-1)
taskViewModel.updateTasks(taskViewModel.tasks.value)
}
}
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Удалить"
)
}
/* IconButton(
onClick = {
userViewModel.addFavoriteTaskToUser(userId, task)
}
) {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "Добавить в избранное"
)
}*/
}
} }
} }
} }

View File

@ -1,83 +0,0 @@
package com.example.todolisttask.models.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.todolisttask.AppDatabase
import com.example.todolisttask.R
import com.example.todolisttask.models.model.TaskWithUser
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TaskView(id: Int) {
val context = LocalContext.current
val (taskWithUser, setTaskWithUser) = remember { mutableStateOf<TaskWithUser?>(null) }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
setTaskWithUser(AppDatabase.getInstance(context).userDao().getByUid(id))
}
}
taskWithUser?.let { task ->
Column(
Modifier
.fillMaxWidth()
.padding(all = 10.dp)
) {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = task.user?.name ?: "",
onValueChange = {},
readOnly = true,
label = {
Text(stringResource(id = R.string.user_name))
}
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = task.user?.login ?: "",
onValueChange = {},
readOnly = true,
label = {
Text(stringResource(id = R.string.user_login))
}
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = task.taskName ?: "",
onValueChange = {},
readOnly = true,
label = {
Text(stringResource(id = R.string.task_name))
}
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = task.user?.password ?: "",
onValueChange = {},
readOnly = true,
label = {
Text(stringResource(id = R.string.password_name))
}
)
}
}
}

View File

@ -1,55 +0,0 @@
package com.example.todolisttask.models.composeui
import android.content.res.Configuration
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.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.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.todolisttask.AppDatabase
import com.example.todolisttask.composeui.navigation.Screen
import com.example.todolisttask.models.model.Task
import com.example.todolisttask.models.model.User
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun UserList(navController: NavController?) {
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
val userList = AppDatabase.getInstance(context).userDao().getAll()
users.clear()
users.add(userList)
}
}
Column(Modifier.padding(all = 10.dp)) {
users.forEach { task ->
key(task.uid) {
val taskId = Screen.Home.route.replace("{id}", task.uid.toString())
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
onClick = { navController?.navigate(taskId) }) {
Text("${task.name} ${task.login}")
}
}
}
}
}

View File

@ -6,11 +6,13 @@ import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import androidx.room.Update import androidx.room.Update
import com.example.todolisttask.models.model.Task import com.example.todolisttask.models.model.Task
import com.example.todolisttask.models.model.User
import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface TaskDao { interface TaskDao {
@Query("select * from tasks order by task_name collate nocase asc") @Query("select * from tasks order by task_name collate nocase asc")
suspend fun getAll(): List<Task> fun getAll(): Flow<List<Task>>
@Insert @Insert
suspend fun insert(group: Task) suspend fun insert(group: Task)
@ -20,4 +22,9 @@ interface TaskDao {
@Delete @Delete
suspend fun delete(group: Task) suspend fun delete(group: Task)
@Query("select * from tasks where tasks.user_id = :uid")
suspend fun getByUid(uid: Int): List<Task>
@Query("select * from tasks where tasks.uid = :uid ")
suspend fun getOne(uid: Int): Task
} }

View File

@ -15,7 +15,7 @@ interface UserDao {
fun getAll(): Flow<List<User>> fun getAll(): Flow<List<User>>
@Query("select * from users left join tasks on users.uid = tasks.user_id where users.uid = :uid") @Query("select * from users left join tasks on users.uid = tasks.user_id where users.uid = :uid")
suspend fun getByUid(uid: Int): TaskWithUser suspend fun getByUid(uid: Int): User
@Insert @Insert
suspend fun insert(user: User) suspend fun insert(user: User)
@ -26,6 +26,6 @@ interface UserDao {
@Delete @Delete
suspend fun delete(user: User) suspend fun delete(user: User)
@Query("SELECT * FROM users WHERE login = :username AND password = :password") @Query("SELECT * FROM users WHERE users.login = :username AND users.password = :password")
suspend fun getUserByUsernameAndPassword(username: String, password: String): User? suspend fun getUserByUsernameAndPassword(username: String, password: String): User?
} }

View File

@ -27,13 +27,13 @@ abstract class AppDatabase : RoomDatabase() {
private suspend fun populateDatabase() { private suspend fun populateDatabase() {
INSTANCE?.let { database -> INSTANCE?.let { database ->
// Groups // Groups
val taskDao = database.taskDao() // val taskDao = database.taskDao()
val task1 = Task(1, "Test1", "TestDesk",1) // val task1 = Task(1, "Test1", "TestDesk",1)
val task2 = Task(2, "Test2", "TestDesk",1) // val task2 = Task(2, "Test2", "TestDesk",1)
val task3 = Task(3, "Test3", "TestDesk",1) // val task3 = Task(3, "Test3", "TestDesk",1)
taskDao.insert(task1) // taskDao.insert(task1)
taskDao.insert(task2) // taskDao.insert(task2)
taskDao.insert(task3) // taskDao.insert(task3)
// Students // Students
val userDao = database.userDao() val userDao = database.userDao()
val user1 = User("Sergey", "User", "123456") val user1 = User("Sergey", "User", "123456")

View File

@ -0,0 +1,41 @@
package com.example.todolisttask.models.model
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.todolisttask.models.dao.UserDao
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AuthViewModel(private val userDao: UserDao) : ViewModel() {
private val _currentUser = MutableStateFlow<User?>(null)
val currentUser: StateFlow<User?> get() = _currentUser
fun loginUser(username: String, password: String) {
viewModelScope.launch {
try {
withContext(Dispatchers.IO) {
val user = userDao.getUserByUsernameAndPassword(username, password)
_currentUser.value = user
}
} catch (e: Exception) {
println("Error during login: ${e.message}")
}
}
}
fun updateCurrentUset(id:Int) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val user = userDao.getByUid(id)
// Обновляем _currentUser после успешной аутентификации
_currentUser.value = user
}
}
}
}

View File

@ -3,6 +3,7 @@ package com.example.todolisttask.models.model
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@ -25,6 +26,13 @@ data class Task(
@ColumnInfo(name = "user_id", index = true) @ColumnInfo(name = "user_id", index = true)
val userId: Int val userId: Int
) { ) {
@Ignore
constructor(
name: String,
description: String,
userId: Int
) : this(null, name, description, userId)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false

View File

@ -0,0 +1,97 @@
package com.example.todolisttask.models.model.ViewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.todolisttask.models.dao.TaskDao
import com.example.todolisttask.models.model.Task
import com.example.todolisttask.models.model.User
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.sql.RowId
class TaskViewModel(private val taskDao: TaskDao) : ViewModel() {
private val _task = MutableStateFlow<Task?>(null)
val task: StateFlow<Task?> get() = _task
private val _tasks = MutableStateFlow<List<Task>>(emptyList())
val tasks: StateFlow<List<Task>> get() = _tasks
// Метод для обновления списка пользователей
fun updateTasks(newUsers: List<Task>) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
_tasks.value = newUsers
}
}
}
fun updateTask(updatedTask: Task) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
Log.e("TAG", "111111111111111111111")
// Update the specific pet in the database
taskDao.update(updatedTask)
// Retrieve the updated list of pets as a Flow
val updatedTasksFlow = taskDao.getAll()
Log.e("TAG", "222222222222222222222222")
// Collect the values from the Flow and update _pets
updatedTasksFlow.collect { updatedTasks ->
// Convert java.util.List to kotlin.collections.List if needed
_tasks.value = updatedTasks.toList()
}
Log.e("TAG", "333333333333333333333333")
}
}
}
// Метод для создания новой задачи
fun createTask(task: Task) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
// Вставляем новую задачу в базу данных
taskDao.insert(task)
// Получаем актуальный список задач после вставки
val updatedTasksFlow = taskDao.getAll()
Log.e("TAG", "222222222222222222222222")
// Collect the values from the Flow and update _pets
updatedTasksFlow.collect { updatedTasks ->
// Convert java.util.List to kotlin.collections.List if needed
_tasks.value = updatedTasks.toList()
}
}
}
}
fun getTasksByUser(userId: Int) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
_tasks.value = taskDao.getByUid(userId)
}
}
}
fun getTask(Id: Int): StateFlow<Task?> {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val task = taskDao.getOne(Id)
_task.value = task
}
}
return _task
}
fun deleteTask(task: Task) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
taskDao.delete(task)
}
}
}
}

View File

@ -0,0 +1,71 @@
package com.example.todolisttask.models.model.ViewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.todolisttask.models.dao.UserDao
import com.example.todolisttask.models.model.User
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class UserViewModel(private val userDao: UserDao) : ViewModel() {
private val _user = MutableStateFlow<User?>(null)
val user: StateFlow<User?> get() = _user
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> get() = _users
// Метод для обновления списка пользователей
fun updateUsers(newUsers: List<User>) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
_users.value = newUsers
}
}
}
fun updateUser(updatedUser: User) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
Log.e("TAG", "111111111111111111111")
// Update the specific pet in the database
userDao.update(updatedUser)
// Retrieve the updated list of pets as a Flow
val updatedUsersFlow = userDao.getAll()
Log.e("TAG", "222222222222222222222222")
// Collect the values from the Flow and update _pets
updatedUsersFlow.collect { updatedUsers ->
// Convert java.util.List to kotlin.collections.List if needed
_users.value = updatedUsers.toList()
}
Log.e("TAG", "333333333333333333333333")
}
}
}
fun getUser(userId: Int): StateFlow<User?> {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val user = userDao.getByUid(userId)
_user.value = user
}
}
return _user
}
// Метод для входа пользователя
fun loginUser(login: String, password: String) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val user = userDao.getUserByUsernameAndPassword(login, password)
// Здесь должно быть обновление списка пользователей, но не _currentUser
// Также, вам, возможно, нужно вызвать метод updateUsers с обновленным списком пользователей
}
}
}
}