From aa2c281558c6f3ee730dbf521eb8bffd033774ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=91=D0=B0=D1=82=D1=8B?= =?UTF-8?q?=D0=BB=D0=BA=D0=B8=D0=BD?= Date: Tue, 28 Nov 2023 00:20:41 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A7=D0=81=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 5 + .../todolisttask/composeui/CreateTask.kt | 30 ++-- .../todolisttask/composeui/EditTask.kt | 43 +++-- .../todolisttask/composeui/Favorite.kt | 7 +- .../example/todolisttask/composeui/Home.kt | 8 +- .../example/todolisttask/composeui/Login.kt | 25 ++- .../example/todolisttask/composeui/Profile.kt | 9 +- .../composeui/navigation/MyPage.kt | 91 ++++++----- .../todolisttask/models/composeui/TaskList.kt | 147 +++++++++++++++--- .../todolisttask/models/composeui/TaskView.kt | 83 ---------- .../todolisttask/models/composeui/UserList.kt | 55 ------- .../todolisttask/models/dao/TaskDao.kt | 9 +- .../todolisttask/models/dao/UserDao.kt | 4 +- .../models/database/AppDatabase.kt | 14 +- .../models/model/AuthViewModel.kt | 41 +++++ .../example/todolisttask/models/model/Task.kt | 8 + .../models/model/ViewModels/TaskViewModel.kt | 97 ++++++++++++ .../models/model/ViewModels/UserViewModel.kt | 71 +++++++++ 18 files changed, 495 insertions(+), 252 deletions(-) delete mode 100644 app/src/main/java/com/example/todolisttask/models/composeui/TaskView.kt delete mode 100644 app/src/main/java/com/example/todolisttask/models/composeui/UserList.kt create mode 100644 app/src/main/java/com/example/todolisttask/models/model/AuthViewModel.kt create mode 100644 app/src/main/java/com/example/todolisttask/models/model/ViewModels/TaskViewModel.kt create mode 100644 app/src/main/java/com/example/todolisttask/models/model/ViewModels/UserViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e31609e..ce8541e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -83,4 +83,9 @@ dependencies { androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-tooling") 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") + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/composeui/CreateTask.kt b/app/src/main/java/com/example/todolisttask/composeui/CreateTask.kt index 204c523..bdb3db4 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/CreateTask.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/CreateTask.kt @@ -16,7 +16,7 @@ import com.example.todolisttask.models.model.Task @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreateTask(navController: NavController, onSaveClick: (Task) -> Unit) { +fun CreateTask(navController: NavController, userId: Int , onSaveClick: (Task) -> Unit) { var taskName 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)) -// Button( -// onClick = { -// if (taskName.isNotEmpty()) { -// val newTask = Task(0, taskName, taskDescription) -// onSaveClick(newTask) -// taskName = "" -// -// navController.popBackStack() -// } -// }, -// modifier = Modifier.fillMaxWidth() -// ) { -// Text("Сохранить") -// } + Button( + onClick = { + if (taskName.isNotEmpty()) { + val newTask = Task(taskName, taskDescription, userId) + onSaveClick(newTask) + taskName = "" + + navController.popBackStack() + } + }, + modifier = Modifier.fillMaxWidth() + ) { + Text("Сохранить") + } } } diff --git a/app/src/main/java/com/example/todolisttask/composeui/EditTask.kt b/app/src/main/java/com/example/todolisttask/composeui/EditTask.kt index 26fb033..32799ce 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/EditTask.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/EditTask.kt @@ -1,6 +1,12 @@ package com.example.todolisttask.composeui +import android.annotation.SuppressLint 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.compose.foundation.Image import androidx.compose.foundation.layout.Column @@ -29,17 +35,19 @@ import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.example.todolisttask.composeui.navigation.Screen 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.models.model.Task +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) @OptIn(ExperimentalMaterial3Api::class) +@SuppressLint("RememberReturnType") @Composable -fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, taskId : Int) { - val task = (authViewModel.currentUser?.taskId ?: emptyList()).find { it.id == taskId } - - var taskName by remember { mutableStateOf(task?.name ?: "") } - var taskDescriptions by remember { mutableStateOf(task?.description ?: "") } +fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, task : Task?, onSaveClick: (Task) -> Unit) { + var taskName = remember { mutableStateOf(task?.name.orEmpty()) } + var taskDescriptions = remember { mutableStateOf(task?.description.orEmpty()) } Column( modifier = Modifier @@ -48,8 +56,8 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie horizontalAlignment = Alignment.CenterHorizontally ) { OutlinedTextField( - value = taskName, - onValueChange = { taskName = it }, + value = taskName.value, + onValueChange = { taskName.value = it }, label = { Text("Название задания") }, modifier = Modifier .fillMaxWidth() @@ -57,8 +65,8 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie ) OutlinedTextField( - value = taskDescriptions, - onValueChange = { taskDescriptions = it }, + value = taskDescriptions.value, + onValueChange = { taskDescriptions.value = it }, label = { Text("Описание задания") }, modifier = Modifier .fillMaxWidth() @@ -75,11 +83,12 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie Button( onClick = { - val updatedTask = task?.copy(name = taskName, description = taskDescriptions) ?: return@Button - - taskViewModel.updateTask(updatedTask) - userViewModel.updateTaskOnUser(authViewModel.currentUser?.id ?: -1, updatedTask) - authViewModel.currentUser=userViewModel.getUser(authViewModel.currentUser?.id ?: -1) + val updatedTask = Task( + task?.uid ?:0, + taskName.value, + taskDescriptions.value, + task?.userId ?:0) + onSaveClick(updatedTask) navController.popBackStack() }, modifier = Modifier.padding(16.dp) @@ -88,4 +97,6 @@ fun EditTask(navController: NavController, authViewModel: AuthViewModel, taskVie } } + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/composeui/Favorite.kt b/app/src/main/java/com/example/todolisttask/composeui/Favorite.kt index 1847a75..ee70743 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/Favorite.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/Favorite.kt @@ -13,13 +13,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavController 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.models.model.ViewModels.TaskViewModel +import com.example.todolisttask.models.model.ViewModels.UserViewModel @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("RememberReturnType") @Composable fun Favorite(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel) { + /* Column( modifier = Modifier.fillMaxSize(), 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) } + + */ } \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/composeui/Home.kt b/app/src/main/java/com/example/todolisttask/composeui/Home.kt index 555f7af..0f98d99 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/Home.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/Home.kt @@ -1,6 +1,7 @@ -*/ 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 androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -16,9 +17,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.navigation.NavController 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.TaskViewModel -import com.example.todolisttask.models.model.UserViewModel @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("RememberReturnType") @@ -39,7 +39,7 @@ fun Home(navController: NavController, authViewModel: AuthViewModel, taskViewMod } 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) } } diff --git a/app/src/main/java/com/example/todolisttask/composeui/Login.kt b/app/src/main/java/com/example/todolisttask/composeui/Login.kt index 9e3f83b..498cead 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/Login.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/Login.kt @@ -20,18 +20,21 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewModelScope import androidx.navigation.NavHostController import com.example.todolisttask.composeui.navigation.Screen import com.example.todolisttask.models.model.AuthViewModel 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) @Composable fun Login( navController: NavHostController, - authViewModel: AuthViewModel, - users: List + authViewModel: AuthViewModel ) { var username by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } @@ -67,12 +70,18 @@ fun Login( Button( onClick = { - val authenticatedUser = users.find { it.login == username && it.password == password } - if (authenticatedUser != null) { - authViewModel.currentUser = authenticatedUser - navController.navigate(Screen.Home.route) - } else { - println("Authentication failed") + authViewModel.viewModelScope.launch { + authViewModel.loginUser(username, password) + + // Добавляем небольшую задержку (например, 100 мс) для обеспечения завершения операции входа в систему + delay(1000) + + val authenticatedUser = authViewModel.currentUser.value + if (authenticatedUser != null) { + navController.navigate(Screen.Home.route) + } else { + println("Аутентификация не удалась") + } } }, modifier = Modifier.fillMaxWidth() diff --git a/app/src/main/java/com/example/todolisttask/composeui/Profile.kt b/app/src/main/java/com/example/todolisttask/composeui/Profile.kt index b1c7d6a..81a74d5 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/Profile.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/Profile.kt @@ -1,4 +1,4 @@ -package com.example.pmuapp.composeui +package com.example.todolisttask.composeui import android.annotation.SuppressLint import android.net.Uri @@ -35,7 +35,7 @@ import kotlinx.coroutines.flow.callbackFlow @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("RememberReturnType") @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 loginState = remember { mutableStateOf(currentUser?.login.orEmpty()) } val passwordState = remember { mutableStateOf(currentUser?.password.orEmpty()) } @@ -76,12 +76,10 @@ fun Profile(navController: NavController, currentUser: User?, onSaveClick: (User Button( onClick = { val updatedUser = User( - currentUser?.id ?: 0, + currentUser?.uid ?: 0, nameState.value, loginState.value, passwordState.value, - currentUser?.taskId ?: emptyList(), - currentUser?.favoritetask?: emptyList() ) onSaveClick(updatedUser) }, @@ -90,4 +88,5 @@ fun Profile(navController: NavController, currentUser: User?, onSaveClick: (User Text("Сохранить") } } + } diff --git a/app/src/main/java/com/example/todolisttask/composeui/navigation/MyPage.kt b/app/src/main/java/com/example/todolisttask/composeui/navigation/MyPage.kt index 22e8ba7..deba64c 100644 --- a/app/src/main/java/com/example/todolisttask/composeui/navigation/MyPage.kt +++ b/app/src/main/java/com/example/todolisttask/composeui/navigation/MyPage.kt @@ -2,6 +2,7 @@ package com.example.todolisttask.composeui.navigation import CreateTask +import android.annotation.SuppressLint import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.PaddingValues @@ -19,12 +20,14 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.navigation.NavDestination - +import androidx.compose.ui.platform.LocalContext +import androidx.lifecycle.viewModelScope import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController @@ -34,15 +37,22 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController 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.composeui.EditTask import com.example.todolisttask.composeui.Favorite 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.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) @@ -102,6 +112,7 @@ fun Navbar( } } +@SuppressLint("StateFlowValueCalledInComposition", "SuspiciousIndentation") @RequiresApi(Build.VERSION_CODES.O) @Composable fun NavHost( @@ -117,41 +128,44 @@ fun NavHost( modifier = Modifier.padding(innerPadding) ) { composable(Screen.Login.route) { - Login(navController, authViewModel,userViewModel.getUsers()) } + Login(navController, authViewModel) } composable(Screen.Logout.route) { - Login(navController, authViewModel,userViewModel.getUsers()) } + Login(navController, authViewModel) } + +// composable(Screen.CreateTask.route) { - val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() - CreateTask ( navController, onSaveClick = { newTask -> - var adedTask = taskViewModel.createTask(newTask) - userViewModel.addPetToUser(currentUser?.id ?:0, adedTask) - authViewModel.currentUser = userViewModel.getUser(currentUser?.id ?:0) + val currentUser = authViewModel.currentUser + val id: Int = currentUser.value?.uid?.toInt() ?: 0 + CreateTask ( navController, id , onSaveClick = { newTask -> + taskViewModel.createTask(newTask) + //userViewModel.addTask(currentUser?.id ?:0, adedTask) + authViewModel.updateCurrentUset(id) } ) } - - composable(Screen.Favorite.route){ - val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() - if (currentUser != null) { - Favorite(navController, - authViewModel, - taskViewModel, - userViewModel - ) - } else { - } - - } - +// +// composable(Screen.Favorite.route){ +// val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() +// if (currentUser != null) { +// Favorite(navController, +// authViewModel, +// taskViewModel, +// userViewModel +// ) +// } else { +// } +// +// } +// composable(Screen.Profile.route) { - val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() + val currentUser = authViewModel.currentUser.collectAsState() if (currentUser != null) { Profile(navController, - currentUser = currentUser, + currentUser = currentUser.value, onSaveClick = {updatedUser -> userViewModel.updateUser(updatedUser) - authViewModel.currentUser = updatedUser + authViewModel.updateCurrentUset(currentUser?.value?.uid ?:-1) navController.navigate(Screen.Profile.route) } ) @@ -160,7 +174,7 @@ fun NavHost( } composable(Screen.Home.route){ - val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() + val currentUser = authViewModel.currentUser if (currentUser != null) { Home(navController, authViewModel, @@ -176,10 +190,13 @@ fun NavHost( arguments = listOf(navArgument("id") { type = NavType.IntType }) ) { backStackEntry -> 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 fun MainNavbar() { val navController = rememberNavController() - val authViewModel = remember { AuthViewModel() } - val userViewModel = remember {UserViewModel() } - val taskViewModel = remember {TaskViewModel()} + val context = LocalContext.current + val database: AppDatabase = AppDatabase.getInstance(context) + 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 currentDestination = navBackStackEntry?.destination val currentScreen = currentDestination?.route?.let { Screen.getItem(it) } diff --git a/app/src/main/java/com/example/todolisttask/models/composeui/TaskList.kt b/app/src/main/java/com/example/todolisttask/models/composeui/TaskList.kt index ec87655..959c127 100644 --- a/app/src/main/java/com/example/todolisttask/models/composeui/TaskList.kt +++ b/app/src/main/java/com/example/todolisttask/models/composeui/TaskList.kt @@ -1,52 +1,161 @@ package com.example.todolisttask.models.composeui +import android.annotation.SuppressLint 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.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowColumn +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.fillMaxWidth 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.Icon +import androidx.compose.material3.IconButton 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.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color 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.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewModelScope import androidx.navigation.NavController import com.example.todolisttask.AppDatabase 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.ViewModels.TaskViewModel +import com.example.todolisttask.models.model.ViewModels.UserViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.forEach +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +@SuppressLint("StateFlowValueCalledInComposition") +@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class) @Composable -fun TaskList(navController: NavController?) { - val context = LocalContext.current - val tasks = remember { mutableStateListOf() } +fun TaskList(navController: NavController, authViewModel: AuthViewModel, taskViewModel: TaskViewModel, userViewModel: UserViewModel, userId: Int, showFavorites: Boolean = false) { - LaunchedEffect(Unit) { - withContext(Dispatchers.IO) { - val taskList = AppDatabase.getInstance(context).taskDao().getAll() - tasks.clear() - tasks.addAll(taskList) + val currentUser by userViewModel.user.collectAsState() + taskViewModel.getTasksByUser(userId) + var tasks = taskViewModel.tasks.value + + 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)) { - tasks.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.description}") + item { + FlowColumn() { + tasks.forEach { task -> + val taskName = task.name + val taskDescription = task.description + + FlowRow( + modifier = Modifier + .padding(8.dp) + .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 = "Добавить в избранное" + ) + }*/ + } } } } diff --git a/app/src/main/java/com/example/todolisttask/models/composeui/TaskView.kt b/app/src/main/java/com/example/todolisttask/models/composeui/TaskView.kt deleted file mode 100644 index 7c3ff20..0000000 --- a/app/src/main/java/com/example/todolisttask/models/composeui/TaskView.kt +++ /dev/null @@ -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(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)) - } - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/composeui/UserList.kt b/app/src/main/java/com/example/todolisttask/models/composeui/UserList.kt deleted file mode 100644 index 91f0c8a..0000000 --- a/app/src/main/java/com/example/todolisttask/models/composeui/UserList.kt +++ /dev/null @@ -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() } - - 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}") - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/dao/TaskDao.kt b/app/src/main/java/com/example/todolisttask/models/dao/TaskDao.kt index 59d8ace..68d2766 100644 --- a/app/src/main/java/com/example/todolisttask/models/dao/TaskDao.kt +++ b/app/src/main/java/com/example/todolisttask/models/dao/TaskDao.kt @@ -6,11 +6,13 @@ import androidx.room.Insert import androidx.room.Query import androidx.room.Update import com.example.todolisttask.models.model.Task +import com.example.todolisttask.models.model.User +import kotlinx.coroutines.flow.Flow @Dao interface TaskDao { @Query("select * from tasks order by task_name collate nocase asc") - suspend fun getAll(): List + fun getAll(): Flow> @Insert suspend fun insert(group: Task) @@ -20,4 +22,9 @@ interface TaskDao { @Delete suspend fun delete(group: Task) + + @Query("select * from tasks where tasks.user_id = :uid") + suspend fun getByUid(uid: Int): List + @Query("select * from tasks where tasks.uid = :uid ") + suspend fun getOne(uid: Int): Task } \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/dao/UserDao.kt b/app/src/main/java/com/example/todolisttask/models/dao/UserDao.kt index 852aa08..969e94d 100644 --- a/app/src/main/java/com/example/todolisttask/models/dao/UserDao.kt +++ b/app/src/main/java/com/example/todolisttask/models/dao/UserDao.kt @@ -15,7 +15,7 @@ interface UserDao { fun getAll(): Flow> @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 suspend fun insert(user: User) @@ -26,6 +26,6 @@ interface UserDao { @Delete 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? } \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/database/AppDatabase.kt b/app/src/main/java/com/example/todolisttask/models/database/AppDatabase.kt index d50666c..f5c82c8 100644 --- a/app/src/main/java/com/example/todolisttask/models/database/AppDatabase.kt +++ b/app/src/main/java/com/example/todolisttask/models/database/AppDatabase.kt @@ -27,13 +27,13 @@ abstract class AppDatabase : RoomDatabase() { private suspend fun populateDatabase() { INSTANCE?.let { database -> // Groups - val taskDao = database.taskDao() - val task1 = Task(1, "Test1", "TestDesk",1) - val task2 = Task(2, "Test2", "TestDesk",1) - val task3 = Task(3, "Test3", "TestDesk",1) - taskDao.insert(task1) - taskDao.insert(task2) - taskDao.insert(task3) +// val taskDao = database.taskDao() +// val task1 = Task(1, "Test1", "TestDesk",1) +// val task2 = Task(2, "Test2", "TestDesk",1) +// val task3 = Task(3, "Test3", "TestDesk",1) +// taskDao.insert(task1) +// taskDao.insert(task2) +// taskDao.insert(task3) // Students val userDao = database.userDao() val user1 = User("Sergey", "User", "123456") diff --git a/app/src/main/java/com/example/todolisttask/models/model/AuthViewModel.kt b/app/src/main/java/com/example/todolisttask/models/model/AuthViewModel.kt new file mode 100644 index 0000000..4d6d8b4 --- /dev/null +++ b/app/src/main/java/com/example/todolisttask/models/model/AuthViewModel.kt @@ -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(null) + val currentUser: StateFlow 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 + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/model/Task.kt b/app/src/main/java/com/example/todolisttask/models/model/Task.kt index 272c92b..1b15556 100644 --- a/app/src/main/java/com/example/todolisttask/models/model/Task.kt +++ b/app/src/main/java/com/example/todolisttask/models/model/Task.kt @@ -3,6 +3,7 @@ package com.example.todolisttask.models.model import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey +import androidx.room.Ignore import androidx.room.PrimaryKey @@ -25,6 +26,13 @@ data class Task( @ColumnInfo(name = "user_id", index = true) val userId: Int ) { + @Ignore + constructor( + name: String, + description: String, + userId: Int + ) : this(null, name, description, userId) + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/app/src/main/java/com/example/todolisttask/models/model/ViewModels/TaskViewModel.kt b/app/src/main/java/com/example/todolisttask/models/model/ViewModels/TaskViewModel.kt new file mode 100644 index 0000000..1005ba8 --- /dev/null +++ b/app/src/main/java/com/example/todolisttask/models/model/ViewModels/TaskViewModel.kt @@ -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(null) + val task: StateFlow get() = _task + private val _tasks = MutableStateFlow>(emptyList()) + val tasks: StateFlow> get() = _tasks + + // Метод для обновления списка пользователей + fun updateTasks(newUsers: List) { + 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 { + 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) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/todolisttask/models/model/ViewModels/UserViewModel.kt b/app/src/main/java/com/example/todolisttask/models/model/ViewModels/UserViewModel.kt new file mode 100644 index 0000000..1051a97 --- /dev/null +++ b/app/src/main/java/com/example/todolisttask/models/model/ViewModels/UserViewModel.kt @@ -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(null) + val user: StateFlow get() = _user + private val _users = MutableStateFlow>(emptyList()) + val users: StateFlow> get() = _users + + // Метод для обновления списка пользователей + fun updateUsers(newUsers: List) { + 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 { + 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 с обновленным списком пользователей + } + } + } +} \ No newline at end of file