diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt index 1e7152e..cb9682a 100644 --- a/app/src/main/java/com/example/myapplication/MainActivity.kt +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -19,12 +19,14 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -41,11 +43,14 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.navigation.compose.NavHost import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import com.example.myapplication.database.MobileAppDataBase import com.example.myapplication.screens.Authorization -import com.example.myapplication.screens.CreateCard -import com.example.myapplication.screens.EditCard +import com.example.myapplication.screens.EditCardScreen +import com.example.myapplication.screens.EditUserScreen import com.example.myapplication.ui.theme.MyApplicationTheme import com.example.myapplication.screens.MainScreen import com.example.myapplication.screens.Registration @@ -69,11 +74,13 @@ class MainActivity : ComponentActivity() { } } +@OptIn(ExperimentalMaterial3Api::class) @Composable fun AppNavigation(navController: NavHostController){ NavHost( navController = navController, startDestination = "authorization" ) { + composable("authorization") { Authorization(navController = navController) } @@ -83,14 +90,22 @@ fun AppNavigation(navController: NavHostController){ composable("registration") { Registration(navController = navController) } - composable("createCard") { - CreateCard(navController = navController) - } composable("userSettings") { UserSettings(navController = navController) } - composable("editCard") { - EditCard(navController = navController) + composable("editcard") { + EditCardScreen(navController = navController) + } + composable( + "editcard/{id}", + arguments = listOf(navArgument("id") { type = NavType.IntType }) //С аргументом + ) { backStackEntry -> + backStackEntry.arguments?.let { + EditCardScreen(navController = navController, cardId = it.getInt("id")) + } + } + composable("edituser"){ + EditUserScreen(navController = navController) } } } diff --git a/app/src/main/java/com/example/myapplication/components/InputContent.kt b/app/src/main/java/com/example/myapplication/components/InputContent.kt new file mode 100644 index 0000000..5da51dd --- /dev/null +++ b/app/src/main/java/com/example/myapplication/components/InputContent.kt @@ -0,0 +1,69 @@ +package com.example.myapplication.components + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredHeight +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +val buttonHeightStandard = 72.dp + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PlaceholderInputField(label: String, startValue: String? = null, isSingleLine: Boolean, onTextChanged: (String) -> Unit){ + var text = remember { mutableStateOf("") } + startValue?.let{ + text.value = startValue + } + Text( + modifier = Modifier.padding(horizontal = 8.dp), + text = label, + fontSize = 20.sp + ) + OutlinedTextField( + value = text.value, + onValueChange = { + text.value = it + onTextChanged(it) + }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), + shape = RoundedCornerShape(10.dp), + singleLine = isSingleLine + ) +} + +@Composable +fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClickAction: () -> Unit){ + Button( + onClick = onClickAction, + modifier = Modifier + .fillMaxWidth() + .requiredHeight(buttonHeightStandard) + .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), + colors = ButtonDefaults.buttonColors( + containerColor = backgroundColor + ), + shape = RoundedCornerShape(10.dp) + ) { + Text( + text = label, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + color = textColor + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/components/navBar.kt b/app/src/main/java/com/example/myapplication/components/navBar.kt index 7fb396c..63c3261 100644 --- a/app/src/main/java/com/example/myapplication/components/navBar.kt +++ b/app/src/main/java/com/example/myapplication/components/navBar.kt @@ -41,7 +41,7 @@ fun navBar(navController: NavHostController) { verticalAlignment = Alignment.CenterVertically ) { navItem(navController = navController, ImageId = R.drawable.home_image, "mainScreen") - navItem(navController = navController, ImageId = R.drawable.note_image, "createCard") + navItem(navController = navController, ImageId = R.drawable.note_image, "editcard") navItem(navController = navController, ImageId = R.drawable.profile_image, "userSettings") } } diff --git a/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt b/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt index 88f64f3..5a38fa0 100644 --- a/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt +++ b/app/src/main/java/com/example/myapplication/database/MobileDatabase.kt @@ -83,32 +83,6 @@ abstract class MobileAppDataBase : RoomDatabase() { userId = 2 ) ) - cardDao.insert( - Card( - name = "Феррари Имба", - location = "г. Ульяновск", - image = BitmapFactory.decodeResource( - appContext.resources, - R.drawable.ferrari_laferrari_car2 - ), - mileage = 7322, - price = 125000, - userId = 1 - ) - ) - cardDao.insert( - Card( - name = "Феррари Два", - location = "г. Ульяновск", - image = BitmapFactory.decodeResource( - appContext.resources, - R.drawable.ferrari_laferrari_car2 - ), - mileage = 1233, - price = 15000, - userId = 2 - ) - ) } } } diff --git a/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt b/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt index baccba4..dd3ff98 100644 --- a/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt +++ b/app/src/main/java/com/example/myapplication/database/dao/CardDao.kt @@ -15,7 +15,7 @@ interface CardDao { fun getAll(): Flow> @Query("select * from cards where cards.id = :id") - fun getById(id: Int): Flow + fun getById(id: Int): Card? @Query("select * from cards where cards.user_id = :userId") fun getByUserId(userId: Int): Flow> diff --git a/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt b/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt index dbdcb09..c092ae7 100644 --- a/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt +++ b/app/src/main/java/com/example/myapplication/database/dao/UserDao.kt @@ -19,7 +19,7 @@ interface UserDao { fun getAll(): Flow> @Query("select * from users where users.id = :id") - fun getById(id: Int): Flow + fun getById(id: Int): User? @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(user: User) diff --git a/app/src/main/java/com/example/myapplication/screens/createcard.kt b/app/src/main/java/com/example/myapplication/screens/createcard.kt deleted file mode 100644 index 836fb46..0000000 --- a/app/src/main/java/com/example/myapplication/screens/createcard.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.myapplication.screens - -import android.view.Display.Mode -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material3.Button -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.navigation.NavController -import androidx.navigation.NavHostController -import com.example.myapplication.components.LoginField -import com.example.myapplication.components.navBar -import com.example.myapplication.components.navButton -import com.example.myapplication.ui.theme.SkyBlue - -@Composable -fun CreateCard(navController: NavHostController) { - Column { - Box (modifier = Modifier.fillMaxHeight(0.9f)) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Button(onClick = { /*TODO*/ }) { - Text("Добавить картинку") - } - LoginField(text = "Название/Марка") - LoginField(text = "Пробег") - LoginField(text = "Расположение") - LoginField(text = "Цена") - Button(onClick = { /*TODO*/ }) { - Text("Создать объявление") - } - } - } - Column(modifier = Modifier - .fillMaxSize() - .background(SkyBlue), - verticalArrangement = Arrangement.Center) { - navBar(navController = navController) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/screens/editcard.kt b/app/src/main/java/com/example/myapplication/screens/editcard.kt index 0242dfa..149f697 100644 --- a/app/src/main/java/com/example/myapplication/screens/editcard.kt +++ b/app/src/main/java/com/example/myapplication/screens/editcard.kt @@ -1,50 +1,223 @@ package com.example.myapplication.screens +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.ImageDecoder +import android.net.Uri +import android.os.Build +import android.provider.MediaStore import android.view.Display.Mode +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight 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.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Button 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.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.NavHostController +import com.example.myapplication.R +import com.example.myapplication.components.ActiveButton import com.example.myapplication.components.LoginField +import com.example.myapplication.components.PlaceholderInputField import com.example.myapplication.components.navBar import com.example.myapplication.components.navButton +import com.example.myapplication.database.MobileAppDataBase +import com.example.myapplication.database.entities.Card import com.example.myapplication.ui.theme.SkyBlue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable -fun EditCard(navController: NavHostController) { - Column { - Box (modifier = Modifier.fillMaxHeight(0.9f)) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Button(onClick = { /*TODO*/ }) { - Text("Добавить картинку") - } - LoginField(text = "Название/Марка") - LoginField(text = "Пробег") - LoginField(text = "Расположение") - LoginField(text = "Цена") - Button(onClick = { /*TODO*/ }) { - Text("Изменить объявление") +fun EditCardScreen(navController: NavHostController, cardId: Int? = null) { + val context = LocalContext.current + + val image = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.ferrari_laferrari_car2)) } + val name = remember { mutableStateOf("") } + val location = remember { mutableStateOf("") } + val price = remember { mutableStateOf(0) } + val mileage = remember { mutableStateOf(0) } + + val imageData = remember { mutableStateOf(null) } + val launcher = + rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> + imageData.value = uri + } + imageData.value?.let { + if (Build.VERSION.SDK_INT < 28) { + image.value = MediaStore.Images + .Media.getBitmap(context.contentResolver, imageData.value) + + } else { + val source = ImageDecoder + .createSource(context.contentResolver, imageData.value!!) + image.value = ImageDecoder.decodeBitmap(source) + } + } + + cardId?.let{ + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + val card = MobileAppDataBase.getInstance(context).cardDao().getById(cardId!!) + image.value = card!!.image + name.value = card!!.name + location.value = card!!.location + price.value = card!!.price + mileage.value = card!!.mileage + } + } + } + + val edit = remember { mutableStateOf(false) } + if (edit.value){ + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + cardId?.let { + MobileAppDataBase.getInstance(context).cardDao() + .update( + Card( + id = cardId, + name = name.value, + location = location.value, + price = price.value, + mileage = mileage.value, + image = image.value, + userId = 1) + ) + + } ?: run { + MobileAppDataBase.getInstance(context).cardDao() + .insert( + Card( + name = name.value, + location = location.value, + price = price.value, + mileage = mileage.value, + image = image.value, + userId = 1) + ) } } } - Column(modifier = Modifier + edit.value = !edit.value + navController.navigate("mainScreen") + } + + Column( + modifier = Modifier .fillMaxSize() - .background(SkyBlue), - verticalArrangement = Arrangement.Center) { - navBar(navController = navController) + .padding(bottom = 8.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.Bottom, + + ) { + Image( + bitmap = image.value.asImageBitmap(), + contentDescription = "editplaceholder", + contentScale = ContentScale.Crop, + modifier = Modifier + .size(384.dp) + .padding(8.dp) + .align(Alignment.CenterHorizontally)) + ActiveButton(label = "Выбрать обложку", backgroundColor = SkyBlue, textColor = Color.Black, onClickAction = { + launcher.launch("image/*") + }) + PlaceholderInputField(label = "Название", isSingleLine = true, + startValue = name.value, onTextChanged = { newName -> + name.value = newName + }) + PlaceholderInputField(label = "Расположение", isSingleLine = true, + startValue = location.value, onTextChanged = { newLocation -> + location.value = newLocation + }) + PlaceholderInputField(label = "Пробег", isSingleLine = true, + startValue = mileage.value.toString(), onTextChanged = { newMileage -> + mileage.value = newMileage.toIntOrNull() ?: 500 + }) + PlaceholderInputField(label = "Цена", isSingleLine = true, + startValue = price.value.toString(), onTextChanged = { newPrice -> + price.value = newPrice.toIntOrNull() ?: 10000 + }) + ActiveButton(label = "Сохранить", backgroundColor = SkyBlue, textColor = Color.Black, onClickAction = { + edit.value = !edit.value + }) + navButton(navController = navController, destination = "mainScreen", label = "Назад", backgroundColor = SkyBlue, textColor = Color.Black) + } +} + +@Composable +fun EditUserScreen(navController: NavHostController){ + val context = LocalContext.current + + val photo = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.login)) } + val name = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + + val imageData = remember { mutableStateOf(null) } + val launcher = + rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {uri: Uri? -> + imageData.value = uri + } + imageData.value?.let { + if (Build.VERSION.SDK_INT < 28) { + photo.value = MediaStore.Images + .Media.getBitmap(context.contentResolver, imageData.value) + + } else { + val source = ImageDecoder + .createSource(context.contentResolver, imageData.value!!) + photo.value = ImageDecoder.decodeBitmap(source) } } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 8.dp), + verticalArrangement = Arrangement.Bottom + ) { + Image( + bitmap = photo.value.asImageBitmap(), + contentDescription = "editplaceholder", + contentScale = ContentScale.Crop, + modifier = Modifier + .size(384.dp) + .padding(8.dp) + .align(Alignment.CenterHorizontally)) + ActiveButton(label = "Выбрать фото", backgroundColor = SkyBlue, textColor = Color.Black, onClickAction = { + launcher.launch("image/*") + }) + PlaceholderInputField(label = "Никнейм", isSingleLine = true, + startValue = name.value, onTextChanged = { newName -> + name.value = newName + }) + PlaceholderInputField(label = "Пароль", isSingleLine = true, + startValue = password.value, onTextChanged = { newPassword -> + password.value = newPassword + }) + ActiveButton(label = "Сохранить", backgroundColor = SkyBlue, textColor = Color.Black, onClickAction = { + //edit.value = !edit.value + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/screens/mainScreen.kt b/app/src/main/java/com/example/myapplication/screens/mainScreen.kt index e2d8c26..ede4d2f 100644 --- a/app/src/main/java/com/example/myapplication/screens/mainScreen.kt +++ b/app/src/main/java/com/example/myapplication/screens/mainScreen.kt @@ -70,7 +70,7 @@ fun MainScreen(navController: NavHostController) { } } } - + Column { Box(modifier = Modifier .padding(horizontal = 10.dp) @@ -122,10 +122,6 @@ inline fun List<*>.isListOf(): Boolean { fun CardListItem(item: Card, navController: NavHostController){ val context = LocalContext.current - val isExpanded = remember { - mutableStateOf(false) - } - val showDialog = remember { mutableStateOf(false) } @@ -158,24 +154,14 @@ fun CardListItem(item: Card, navController: NavHostController){ modifier = Modifier.padding(8.dp) ){ Text( - text = "${item.name} | ${item.location} | ${item.mileage} | ${item.price}", + text = "Название: ${item.name} \nРасположение: ${item.location} \nПробег: ${item.mileage} \nЦена: ${item.price}", fontSize = 20.sp, fontWeight = FontWeight.Bold ) - } - } - AnimatedVisibility( - visible = isExpanded.value, - modifier = Modifier.fillMaxWidth() - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End - ){ - DataListItemButton("Изменить", Color.Yellow, Color.White, onClickAction = { - navController.navigate("editstory/${item.id}") + DataListItemButton("Изменить", Color.LightGray, Color.White, onClickAction = { + navController.navigate("editcard/${item.id}") }) - DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = { + DataListItemButton("Удалить", Color.Black, Color.White, onClickAction = { showDialog.value = !showDialog.value }) } @@ -200,7 +186,7 @@ fun CardListItem(item: Card, navController: NavHostController){ } } delete.value = !delete.value - navController.navigate("story") + navController.navigate("mainScreen") } } @@ -272,7 +258,7 @@ fun addNewListItem(navController: NavHostController, destination: String){ }, shape = RoundedCornerShape(15.dp), colors = CardDefaults.cardColors( - containerColor = SkyBlue + containerColor = Color.White ), elevation = CardDefaults.cardElevation( defaultElevation = 8.dp @@ -285,7 +271,7 @@ fun addNewListItem(navController: NavHostController, destination: String){ modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ){ - Image(painter = painterResource(id = R.drawable.login), + Image(painter = painterResource(id = R.drawable.plus), contentDescription = "additem", contentScale = ContentScale.Crop, modifier = Modifier diff --git a/app/src/main/java/com/example/myapplication/screens/user.kt b/app/src/main/java/com/example/myapplication/screens/user.kt index 1c637cb..666389f 100644 --- a/app/src/main/java/com/example/myapplication/screens/user.kt +++ b/app/src/main/java/com/example/myapplication/screens/user.kt @@ -12,9 +12,15 @@ import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -22,10 +28,30 @@ import androidx.navigation.NavHostController import com.example.myapplication.R import com.example.myapplication.components.LoginField import com.example.myapplication.components.navBar +import com.example.myapplication.database.MobileAppDataBase +import com.example.myapplication.database.entities.User import com.example.myapplication.ui.theme.SkyBlue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable fun UserSettings(navController: NavHostController) { + val context = LocalContext.current + + val login = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + val userId = 1 + + userId?.let { + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + val user = MobileAppDataBase.getInstance(context).userDao().getById(userId!!) + login.value = user!!.login + password.value = user!!.password + } + } + } + Column { Box (modifier = Modifier.fillMaxHeight(0.9f)) { Column( @@ -39,10 +65,8 @@ fun UserSettings(navController: NavHostController) { modifier = Modifier .size(300.dp) ) - LoginField(text = "Логин пользователя") - LoginField(text = "Пароль пользователя") - LoginField(text = "Количество объявлений пользователя") - Button(onClick = {}) { Text("Посмотреть мои объявления") } + LoginField(text = "Логин пользователя: ${login.value}") + LoginField(text = "Пароль пользователя: ${password.value}") } } Column(modifier = Modifier @@ -52,5 +76,4 @@ fun UserSettings(navController: NavHostController) { navBar(navController = navController) } } - } \ No newline at end of file diff --git a/app/src/main/res/drawable/plus.png b/app/src/main/res/drawable/plus.png new file mode 100644 index 0000000..6372ce7 Binary files /dev/null and b/app/src/main/res/drawable/plus.png differ