diff --git a/.gradle/8.0/executionHistory/executionHistory.bin b/.gradle/8.0/executionHistory/executionHistory.bin index 0a8af53..9333db7 100644 Binary files a/.gradle/8.0/executionHistory/executionHistory.bin and b/.gradle/8.0/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.0/executionHistory/executionHistory.lock b/.gradle/8.0/executionHistory/executionHistory.lock index 29083f9..5035fea 100644 Binary files a/.gradle/8.0/executionHistory/executionHistory.lock and b/.gradle/8.0/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.0/fileHashes/fileHashes.bin b/.gradle/8.0/fileHashes/fileHashes.bin index 27e7475..e19e881 100644 Binary files a/.gradle/8.0/fileHashes/fileHashes.bin and b/.gradle/8.0/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.0/fileHashes/fileHashes.lock b/.gradle/8.0/fileHashes/fileHashes.lock index ec1657c..ab76f20 100644 Binary files a/.gradle/8.0/fileHashes/fileHashes.lock and b/.gradle/8.0/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.0/fileHashes/resourceHashesCache.bin b/.gradle/8.0/fileHashes/resourceHashesCache.bin index 13bf67c..16f0fa3 100644 Binary files a/.gradle/8.0/fileHashes/resourceHashesCache.bin and b/.gradle/8.0/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 77c210c..44904fc 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe index 980cb44..1c6b3a2 100644 Binary files a/.gradle/file-system.probe and b/.gradle/file-system.probe differ diff --git a/.idea/workspace.xml b/.idea/workspace.xml index a614296..d092f84 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -9,38 +9,28 @@ - - - - - - - - - - - - - - - - + + + + + - + - - + + + @@ -95,8 +85,8 @@ - + @@ -112,7 +102,7 @@ - + @@ -131,17 +121,20 @@ "SHARE_PROJECT_CONFIGURATION_FILES": "true", "cidr.known.project.marker": "true", "com.android.tools.idea.devicemanager.tab": "Physical", - "last_opened_file_path": "C:/Users/Kate/AndroidStudioProjects/Ihonkina_PIbd-31_PMU/app/src/main/java/com/example/pmuapp/models/user/composeui", + "last_opened_file_path": "C:/Users/Kate/AndroidStudioProjects/Ihonkina_PIbd-31_PMU/app/src/main/java/com/example/pmuapp/composeui/navigation", "settings.editor.selected.configurable": "experimental" } }]]> + - + + + @@ -255,7 +248,14 @@ 1697041852651 - + + 1697054812374 + + + + 1697054812374 + + @@ -287,17 +287,7 @@ - - - - - - - file://$PROJECT_DIR$/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt - 73 - - - - + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e011832..8a9f301 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,12 +5,13 @@ plugins { android { namespace = "com.example.pmuapp" - compileSdk = 33 + compileSdk = 34 + defaultConfig { applicationId = "com.example.pmuapp" minSdk = 24 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" @@ -50,6 +51,7 @@ android { } dependencies { + implementation ("io.coil-kt:coil-compose:1.4.0") implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") @@ -62,6 +64,7 @@ dependencies { implementation("androidx.compose.material3:material3") implementation("com.google.android.engage:engage-core:1.3.0") implementation("androidx.appcompat:appcompat:1.6.1") + implementation("androidx.compose.ui:ui-graphics-android:1.5.3") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") diff --git a/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt b/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt index f7f41bd..9ffc864 100644 --- a/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt +++ b/app/src/main/java/com/example/pmuapp/composeui/CreatePet.kt @@ -10,13 +10,14 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.navigation.NavController import com.example.pmuapp.R import com.example.pmuapp.models.user.model.Pet import com.example.pmuapp.models.user.model.User @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreatePet(onSaveClick: (Pet) -> Unit) { +fun CreatePet(navController: NavController, onSaveClick: (Pet) -> Unit) { var selectedImage by remember { mutableStateOf(R.drawable.pet1) } var petName by remember { mutableStateOf("") } @@ -72,10 +73,13 @@ fun CreatePet(onSaveClick: (Pet) -> Unit) { Button( onClick = { if (petName.isNotEmpty()) { - val newPet = Pet(0, petName, selectedImage) + val newPet = Pet(0, petName, selectedImage, "") onSaveClick(newPet) petName = "" selectedImage = R.drawable.pet1 + + // Навигация назад на предыдущую страницу + navController.popBackStack() } }, modifier = Modifier.fillMaxWidth() diff --git a/app/src/main/java/com/example/pmuapp/composeui/EditPet.kt b/app/src/main/java/com/example/pmuapp/composeui/EditPet.kt new file mode 100644 index 0000000..5eacbb2 --- /dev/null +++ b/app/src/main/java/com/example/pmuapp/composeui/EditPet.kt @@ -0,0 +1,117 @@ +package com.example.pmuapp.composeui + +import android.os.Build +import android.os.Build.* +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +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.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import com.example.pmuapp.composeui.navigation.Screen +import com.example.pmuapp.models.user.model.AuthViewModel +import com.example.pmuapp.models.user.model.PetViewModel +import com.example.pmuapp.models.user.model.UserViewModel + +@RequiresApi(VERSION_CODES.O) +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EditPet(navController: NavController ,authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, petId: Int) { + val pet = (authViewModel.currentUser?.petId ?: emptyList()).find { it.id == petId } + + var petName by remember { mutableStateOf(pet?.name ?: "") } + var petNotes by remember { mutableStateOf(pet?.notes ?: "") } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + // Отображение изображения (здесь предполагается, что у вас есть доступ к `availablePetImages` по индексу) + val imageResId = pet?.imageResId ?: 0 + Image( + painter = painterResource(id = imageResId), + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .height(200.dp) + ) + + // Поле ввода имени + OutlinedTextField( + value = petName, + onValueChange = { petName = it }, + label = { Text("Имя питомца") }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp) + ) + + // Текст "Заметка о питомце" + Text( + text = "Заметка о питомце", + style = TextStyle(fontSize = 16.sp), + modifier = Modifier.padding(top = 8.dp) + ) + + // Поле ввода заметок + TextField( + value = petNotes, + onValueChange = { petNotes = it }, + label = { Text("Заметки") }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp) + .heightIn(max = 200.dp) // Заметка будет растянута до конца экрана + .padding(16.dp), + readOnly = false // Сделаем его доступным для редактирования + ) + + Spacer(modifier = Modifier.weight(1f)) // Заполнитель для размещения кнопки внизу + + // Кнопка "Изменить" + // Кнопка "Сохранить" + val editedPetId = Screen.PlayPet.route.replace("{id}", pet?.id.toString()) + + Button( + onClick = { + // Создаем обновленную версию питомца с введенными данными + val updatedPet = pet?.copy(name = petName, notes = petNotes) ?: return@Button + + // Вызываем функцию для обновления питомца в вашей ViewModel (в данном случае, в petViewModel) + petViewModel.updatePet(updatedPet) + userViewModel.updatePetOnUser(authViewModel.currentUser?.id ?: -1, updatedPet) + authViewModel.currentUser=userViewModel.getUser(authViewModel.currentUser?.id ?: -1) + // Дополнительные действия после обновления, например, переход на другой экран + val petId = Screen.EditPet.route.replace("{id}", pet.id.toString()) + navController?.navigate(editedPetId) + }, + modifier = Modifier.padding(16.dp) + ) { + Text("Сохранить") + } + + } +} diff --git a/app/src/main/java/com/example/pmuapp/composeui/Home.kt b/app/src/main/java/com/example/pmuapp/composeui/Home.kt index 82be433..07a356c 100644 --- a/app/src/main/java/com/example/pmuapp/composeui/Home.kt +++ b/app/src/main/java/com/example/pmuapp/composeui/Home.kt @@ -1,39 +1,25 @@ package com.example.pmuapp.composeui -import android.content.Intent -import android.content.res.Configuration -import android.net.Uri -import android.provider.ContactsContract.Profile -import android.widget.TextView -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -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.ui.Alignment 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 androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavController -import com.example.pmuapp.R import com.example.pmuapp.composeui.navigation.Screen import com.example.pmuapp.models.user.composeui.PetList import com.example.pmuapp.models.user.model.AuthViewModel -import com.example.pmuapp.ui.theme.PMUappTheme +import com.example.pmuapp.models.user.model.PetViewModel +import com.example.pmuapp.models.user.model.UserViewModel @Composable -fun Home(navController: NavController, authViewModel: AuthViewModel) { +fun Home(navController: NavController, authViewModel: AuthViewModel, petViewModel:PetViewModel, userViewModel:UserViewModel) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, @@ -51,7 +37,7 @@ fun Home(navController: NavController, authViewModel: AuthViewModel) { Spacer(modifier = Modifier.height(16.dp)) // Вывод списка питомцев - PetList(navController, authViewModel) + PetList(navController,authViewModel, petViewModel, userViewModel, authViewModel.currentUser?.id ?: -1) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/pmuapp/composeui/PlayPet.kt b/app/src/main/java/com/example/pmuapp/composeui/PlayPet.kt new file mode 100644 index 0000000..c67decf --- /dev/null +++ b/app/src/main/java/com/example/pmuapp/composeui/PlayPet.kt @@ -0,0 +1,96 @@ +package com.example.pmuapp.composeui + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import com.example.pmuapp.composeui.navigation.Screen +import com.example.pmuapp.models.user.model.AuthViewModel +import com.example.pmuapp.models.user.model.PetViewModel +import com.example.pmuapp.models.user.model.UserViewModel + +@RequiresApi(Build.VERSION_CODES.O) +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PlayPet(navController: NavController,authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, petId: Int) { + val pet = (authViewModel.currentUser?.petId ?: emptyList()).find { it.id == petId } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(10.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + // Отображение изображения (здесь предполагается, что у вас есть доступ к `availablePetImages` по индексу) + val imageResId = pet?.imageResId ?: 0 + Image( + painter = painterResource(id = imageResId), + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .height(200.dp) + ) + + // Отображение имени + Text( + text = pet?.name ?: "", + style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 24.sp), + modifier = Modifier.padding(top = 8.dp) + ) + + // Текст "Заметка о питомце" + Text( + text = "Заметка о питомце", + style = TextStyle(fontSize = 16.sp), + modifier = Modifier.padding(top = 8.dp) + ) + + // Отображение заметок + TextField( + value = pet?.notes ?: "", + onValueChange = { /* Обработка изменения текста, если необходимо */ }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp) + .heightIn(max = 200.dp) // Заметка будет растянута до конца экрана + .padding(16.dp), + readOnly = true + ) + + Spacer(modifier = Modifier.weight(1f)) // Заполнитель для размещения кнопки внизу + val petId = Screen.EditPet.route.replace("{id}", pet?.id.toString()) + // Кнопка "Изменить" + Button( + + onClick = { + // Перейти на страницу "играть" с передачей petId как аргумент + navController?.navigate(petId) + + // Обработка нажатия кнопки "Изменить" + }, + modifier = Modifier.padding(16.dp) + ) { + Text("Изменить") + } + } +} diff --git a/app/src/main/java/com/example/pmuapp/composeui/Profile.kt b/app/src/main/java/com/example/pmuapp/composeui/Profile.kt index b3c6fc8..5a68db7 100644 --- a/app/src/main/java/com/example/pmuapp/composeui/Profile.kt +++ b/app/src/main/java/com/example/pmuapp/composeui/Profile.kt @@ -1,36 +1,26 @@ package com.example.pmuapp.composeui import android.annotation.SuppressLint -import android.content.Intent -import android.content.res.Configuration import android.net.Uri -import android.provider.ContactsContract.Profile -import android.widget.TextView -import androidx.compose.foundation.clickable +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable 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.text.input.PasswordVisualTransformation -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView -import com.example.pmuapp.R +import coil.compose.rememberImagePainter import com.example.pmuapp.models.user.model.User -import com.example.pmuapp.ui.theme.PMUappTheme @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("RememberReturnType") @@ -45,6 +35,38 @@ fun Profile(currentUser: User?, onSaveClick: (User) -> Unit) { .fillMaxSize() .padding(16.dp) ) { + currentUser?.let { user -> + Image( + painter = rememberImagePainter(data = user.imageResId), + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .height(200.dp) + ) + } + + // State to hold the selected image URI + val selectedImageUri = remember { mutableStateOf(null) } + + // Create an ActivityResultLauncher to handle image selection + val imagePickerLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { result: Uri? -> + result?.let { uri -> + selectedImageUri.value = uri + } + } + + // Button to open the image picker + Button( + onClick = { + // Request permission to access the device's storage + // Open the image picker + imagePickerLauncher.launch("image/*") + }, + modifier = Modifier.fillMaxWidth() + ) { + Text("Загрузить фото") + } + TextField( value = nameState.value, onValueChange = { nameState.value = it }, @@ -67,7 +89,6 @@ fun Profile(currentUser: User?, onSaveClick: (User) -> Unit) { value = passwordState.value, onValueChange = { passwordState.value = it }, label = { Text("Password") }, - visualTransformation = PasswordVisualTransformation(), modifier = Modifier .fillMaxWidth() .padding(bottom = 16.dp) @@ -80,7 +101,8 @@ fun Profile(currentUser: User?, onSaveClick: (User) -> Unit) { nameState.value, loginState.value, passwordState.value, - currentUser?.petId ?: emptyList() + currentUser?.petId ?: emptyList(), + selectedImageUri.value?.toString() ?: "", // Use the selected image URI ) onSaveClick(updatedUser) // Вызывает функцию updateUser в UserViewModel }, @@ -88,7 +110,5 @@ fun Profile(currentUser: User?, onSaveClick: (User) -> Unit) { ) { Text("Сохранить") } - } } - diff --git a/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt b/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt index 2488731..5fe8d5a 100644 --- a/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt +++ b/app/src/main/java/com/example/pmuapp/composeui/navigation/MyPage.kt @@ -2,7 +2,11 @@ package com.example.pmuapp.composeui.navigation import CreatePet import android.content.res.Configuration +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack @@ -20,6 +24,7 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -34,13 +39,15 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.example.pmuapp.R +import com.example.pmuapp.composeui.EditPet import com.example.pmuapp.composeui.Home import com.example.pmuapp.composeui.Login +import com.example.pmuapp.composeui.PlayPet import com.example.pmuapp.composeui.Profile -import com.example.pmuapp.models.user.composeui.StudentView +import com.example.pmuapp.models.user.composeui.PetList import com.example.pmuapp.models.user.composeui.UserList import com.example.pmuapp.models.user.model.AuthViewModel -import com.example.pmuapp.models.user.model.User +import com.example.pmuapp.models.user.model.PetViewModel import com.example.pmuapp.models.user.model.UserViewModel import com.example.pmuapp.ui.theme.PMUappTheme @@ -59,14 +66,27 @@ fun Topbar( Text(stringResource(currentScreen?.resourceId ?: R.string.app_name)) }, navigationIcon = { - if ( + if (currentScreen == Screen.PlayPet) { + IconButton( + onClick = { + // Перейти на главный экран + navController.navigate(Screen.Home.route) + } + ) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = "Back", + tint = MaterialTheme.colorScheme.onPrimary + ) + } + } else if ( navController.previousBackStackEntry != null && (currentScreen == null || !currentScreen.showInBottomBar) ) { IconButton(onClick = { navController.navigateUp() }) { Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = null, + imageVector = Icons.Default.ArrowBack, + contentDescription = "Back", tint = MaterialTheme.colorScheme.onPrimary ) } @@ -101,12 +121,14 @@ fun Navbar( } } +@RequiresApi(Build.VERSION_CODES.O) @Composable fun NavHost( navController: NavHostController, innerPadding: PaddingValues, authViewModel: AuthViewModel, // Передайте AuthViewModel как параметр -userViewModel: UserViewModel // Передайте UserViewModel как параметр +userViewModel: UserViewModel, +petViewModel: PetViewModel// Передайте UserViewModel как параметр ) { NavHost( navController = navController, @@ -124,6 +146,7 @@ userViewModel: UserViewModel // Передайте UserViewModel как пара onSaveClick = { updatedUser -> userViewModel.updateUser(updatedUser) authViewModel.currentUser = updatedUser + navController.navigate(Screen.Profile.route) } ) } else { @@ -132,11 +155,12 @@ userViewModel: UserViewModel // Передайте UserViewModel как пара } composable(Screen.UserList.route) { UserList(navController, userViewModel) } - composable(Screen.Home.route) { Home(navController, authViewModel) } + composable(Screen.Home.route) { Home(navController, authViewModel,petViewModel,userViewModel) } composable(Screen.CreatePet.route) { val currentUser = authViewModel.currentUser ?: userViewModel.getUsers().firstOrNull() - CreatePet ( onSaveClick = { newPet -> - userViewModel.addPetToUser(currentUser?.id ?:0, newPet) + CreatePet ( navController, onSaveClick = { newPet -> + var adedPet = petViewModel.createPet(newPet) + userViewModel.addPetToUser(currentUser?.id ?:0, adedPet) authViewModel.currentUser = userViewModel.getUser(currentUser?.id ?:0) } ) @@ -147,8 +171,32 @@ userViewModel: UserViewModel // Передайте UserViewModel как пара Screen.UserView.route, arguments = listOf(navArgument("id") { type = NavType.IntType }) ) { backStackEntry -> - backStackEntry.arguments?.let { StudentView(userViewModel.getUsers()[it.getInt("id")]) } + val userId = backStackEntry.arguments?.getInt("id") ?: -1 + + Box( + contentAlignment = Alignment.TopCenter, // Центрировать содержимое по горизонтали и сверху + modifier = Modifier.fillMaxSize() + ) { + PetList(navController,authViewModel, petViewModel, userViewModel, userId) + } } + composable( + Screen.PlayPet.route, + arguments = listOf(navArgument("id") { type = NavType.IntType }) + ) { backStackEntry -> + val petId = backStackEntry.arguments?.getInt("id") ?: -1 + + PlayPet(navController,authViewModel, petViewModel, userViewModel, petId) + } + composable( + Screen.EditPet.route, + arguments = listOf(navArgument("id") { type = NavType.IntType }) + ) { backStackEntry -> + val petId = backStackEntry.arguments?.getInt("id") ?: -1 + EditPet(navController,authViewModel, petViewModel, userViewModel, petId) + + } + } } @@ -158,6 +206,7 @@ fun MainNavbar() { val navController = rememberNavController() val authViewModel = remember { AuthViewModel() } val userViewModel =remember {UserViewModel() }// Создайте экземпляр AuthViewModel + val petViewModel = remember {PetViewModel()} val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination = navBackStackEntry?.destination val currentScreen = currentDestination?.route?.let { Screen.getItem(it) } @@ -172,7 +221,7 @@ fun MainNavbar() { } } ) { innerPadding -> - NavHost(navController, innerPadding, authViewModel, userViewModel) + NavHost(navController, innerPadding, authViewModel, userViewModel, petViewModel ) } } diff --git a/app/src/main/java/com/example/pmuapp/composeui/navigation/Screen.kt b/app/src/main/java/com/example/pmuapp/composeui/navigation/Screen.kt index cbb6249..2b0aff5 100644 --- a/app/src/main/java/com/example/pmuapp/composeui/navigation/Screen.kt +++ b/app/src/main/java/com/example/pmuapp/composeui/navigation/Screen.kt @@ -27,15 +27,22 @@ enum class Screen( "profile", R.string.user_my_title, Icons.Filled.Person ), UserView( - "student-view/{id}", R.string.user_view_title, showInBottomBar = false + "user-view/{id}", R.string.user_view_title, showInBottomBar = false ), Login( "login", R.string.login_title, showInBottomBar = false ), CreatePet( "createpet", R.string.create_pet_title, showInBottomBar = false + ), + PlayPet( + "playpet/{id}", R.string.play_pet_title,showInBottomBar = false + ), + EditPet( + "editpet/{id}", R.string.edit_pet_title,showInBottomBar = false ); + companion object { val bottomBarItems = listOf( UserList, diff --git a/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt b/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt index 3ca4a70..6938734 100644 --- a/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt +++ b/app/src/main/java/com/example/pmuapp/models/user/composeui/PetList.kt @@ -1,55 +1,72 @@ package com.example.pmuapp.models.user.composeui -import android.content.res.Configuration import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.example.pmuapp.composeui.navigation.Screen import com.example.pmuapp.models.user.model.AuthViewModel +import com.example.pmuapp.models.user.model.PetViewModel import com.example.pmuapp.models.user.model.User import com.example.pmuapp.models.user.model.UserViewModel -import com.example.pmuapp.ui.theme.PMUappTheme + @OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class) @Composable -fun PetList(navController: NavController?, authViewModel: AuthViewModel) { - val currentUser = authViewModel.currentUser - val pets = currentUser?.petId.orEmpty() +fun PetList(navController: NavController, authViewModel: AuthViewModel, petViewModel: PetViewModel, userViewModel: UserViewModel, userId: Int) { + + val currentUser = userViewModel.getUser(userId) + var pets = currentUser.petId + + LazyColumn( + verticalArrangement = Arrangement.Center, // Центрировать элементы по вертикали + horizontalAlignment = Alignment.CenterHorizontally // Центрировать элементы по горизонтали + ) { + if (userId != authViewModel.currentUser?.id ?: -1) { + item { + // Добавляем большой текст с именем пользователя + Text( + text = currentUser?.name + " (" + currentUser.login + ")", + style = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Bold + ), + modifier = Modifier.padding(16.dp) + ) + } + } - LazyColumn { item { - FlowRow( - ) { + FlowRow() { pets.forEach { pet -> val imageId = pet.imageResId val petName = pet.name Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .padding(8.dp) + modifier = Modifier.padding(8.dp) ) { Image( painter = painterResource(id = imageId), @@ -61,9 +78,46 @@ fun PetList(navController: NavController?, authViewModel: AuthViewModel) { text = petName, modifier = Modifier.padding(top = 4.dp) ) + + if (userId == authViewModel.currentUser?.id ?: -1) { + val petId = Screen.PlayPet.route.replace("{id}", pet.id.toString()) + Button( + onClick = { + // Перейти на страницу "играть" с передачей petId как аргумент + navController?.navigate(petId) + + }, + // modifier = Modifier.fillMaxWidth() + ) { + Text("Играть") + } + // Кнопка удаления питомца + IconButton( + onClick = { + // Вызывает функцию удаления питомца из PetViewModel + petViewModel.deletePet(pet) + userViewModel.deletePet( + currentUser?.id + ?: 0, + pet.id + ) + authViewModel.currentUser = + userViewModel.getUser( + currentUser?.id + ?: 0 + ) + } + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = "Удалить" + ) + } + + } } } } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/pmuapp/models/user/model/Pet.kt b/app/src/main/java/com/example/pmuapp/models/user/model/Pet.kt index 11934e5..75ee84c 100644 --- a/app/src/main/java/com/example/pmuapp/models/user/model/Pet.kt +++ b/app/src/main/java/com/example/pmuapp/models/user/model/Pet.kt @@ -4,13 +4,65 @@ import android.media.Image import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel +import com.example.pmuapp.R import java.io.Serializable data class Pet( - val id: Int, + var id: Int, val name: String, - val imageResId: Int + val imageResId: Int, + val notes: String ) : Serializable +class PetViewModel : ViewModel() { + var pets: MutableState> = mutableStateOf( + emptyList() + ) + val availablePetImages: List = listOf( + R.drawable.pet1, + R.drawable.pet2, + R.drawable.pet3, + R.drawable.pet4, + R.drawable.pet5, + R.drawable.pet6, + R.drawable.pet7, + R.drawable.pet8, + ) + + fun createPet(newPet: Pet): Pet { + newPet.id = pets.value.size.toInt() + val updatedPets = pets.value.toMutableList() + updatedPets.add(newPet) + pets.value = updatedPets + return newPet + } + + fun deletePet(pet: Pet) { + val updatedPets = pets.value.toMutableList() + updatedPets.remove(pet) + pets.value = updatedPets + } + + fun updatePet(updatedPet: Pet) { + val updatedPets = pets.value.toMutableList() + val index = updatedPets.indexOfFirst { it.id == updatedPet.id } + + if (index != -1) { + updatedPets[index] = updatedPet + pets.value = updatedPets + } + } +} + + + +// fun updateUser(updatedUser: User) { +// val updatedUsers = users.value.toMutableList() +// val index = updatedUsers.indexOfFirst { it.login == updatedUser.login } +// if (index != -1) { +// updatedUsers[index] = updatedUser +// users.value = updatedUsers +// } +// } diff --git a/app/src/main/java/com/example/pmuapp/models/user/model/User.kt b/app/src/main/java/com/example/pmuapp/models/user/model/User.kt index 109cdeb..f9f22a8 100644 --- a/app/src/main/java/com/example/pmuapp/models/user/model/User.kt +++ b/app/src/main/java/com/example/pmuapp/models/user/model/User.kt @@ -1,5 +1,6 @@ package com.example.pmuapp.models.user.model +import android.net.Uri import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel @@ -11,15 +12,19 @@ data class User( val name: String, val login: String, val password: String, - val petId: List + val petId: List, + val imageResId: String // Добавляем поле для хранения ID ресурса изображения пользователя ) : Serializable + class UserViewModel : ViewModel() { + val imageUri: Uri = Uri.parse("android.resource://com.example.pmuapp/${R.drawable.avatar}") + var users: MutableState> = mutableStateOf( listOf( - User(0,"Иван", "ivan", "111111", emptyList()), - User(1,"Анна", "ann", "111111", emptyList()), - User(2,"Лиза", "liza", "111111",emptyList()) + User(0,"Иван", "ivan", "111111", emptyList(),imageUri.toString()), + User(1,"Анна", "ann", "111111", emptyList(),imageUri.toString()), + User(2,"Лиза", "liza", "111111",emptyList(),imageUri.toString()) ) ) val availablePetImages: List = listOf( @@ -56,6 +61,58 @@ class UserViewModel : ViewModel() { users.value = updatedUsers } } + fun deletePet(userId: Int, petIdToDelete: Int) { + val updatedUsers = users.value.toMutableList() + + // Найдем пользователя по userId + val user = updatedUsers.find { it.id == userId } + + user?.let { user -> + val updatedPets = user.petId.toMutableList() + + // Найдем питомца по petId и удалим его из списка питомцев + val petToDelete = updatedPets.find { it.id == petIdToDelete } + + petToDelete?.let { pet -> + updatedPets.remove(pet) + } + + // Обновим пользователя с обновленным списком питомцев + val updatedUser = user.copy(petId = updatedPets) + + // Обновим список пользователей + val userIndex = updatedUsers.indexOf(user) + updatedUsers[userIndex] = updatedUser + users.value = updatedUsers + } + } + + fun updatePetOnUser(userId: Int, updatedPet: Pet) { + val updatedUsers = users.value.toMutableList() + + // Найдем пользователя по userId + val user = updatedUsers.find { it.id == userId } + + user?.let { user -> + val updatedPets = user.petId.toMutableList() + + // Найдем питомца по petId и обновим его + val petToUpdate = updatedPets.find { it.id == updatedPet.id } + + petToUpdate?.let { pet -> + val petIndex = updatedPets.indexOf(pet) + updatedPets[petIndex] = updatedPet + } + + // Обновим пользователя с обновленным списком питомцев + val updatedUser = user.copy(petId = updatedPets) + + // Обновим список пользователей + val userIndex = updatedUsers.indexOf(user) + updatedUsers[userIndex] = updatedUser + users.value = updatedUsers + } + } fun updateUser(updatedUser: User) { val updatedUsers = users.value.toMutableList() diff --git a/app/src/main/res/drawable/avatar.jpg b/app/src/main/res/drawable/avatar.jpg new file mode 100644 index 0000000..ac60efc Binary files /dev/null and b/app/src/main/res/drawable/avatar.jpg differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e824e8e..bb4e0f4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,12 +9,16 @@ Мой профиль Авторизация Создание питомца + Заметка питомца + Мой питомец + Изменение питомца Это текст о нас!\n\n Здесь могла быть Ваша реклама!\n\n Наш сайт ulstu.ru + @drawable/avatar @drawable/pet1 @drawable/pet2 @drawable/pet3 diff --git a/report/~$Lab1.docx b/report/~$Lab1.docx new file mode 100644 index 0000000..1d41244 Binary files /dev/null and b/report/~$Lab1.docx differ
Это текст о нас!
Здесь могла быть Ваша реклама!
Наш сайт ulstu.ru