Browse Source

feat: Добавлен аватар на страницу профиоя

k1rakato 4 days ago
parent
commit
c0a9e629bc
19 changed files with 473 additions and 160 deletions
  1. 0 9
      .idea/TomatoAndPotato.iml
  2. 0 6
      .idea/misc.xml
  3. 0 8
      .idea/modules.xml
  4. 0 6
      .idea/vcs.xml
  5. 0 51
      .idea/workspace.xml
  6. 1 1
      ProjectApp/TomatoAndPotatoAPP/.idea/kotlinc.xml
  7. 8 0
      ProjectApp/TomatoAndPotatoAPP/app/build.gradle.kts
  8. 6 3
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/AuthorizationScreen.kt
  9. 14 10
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/PLantsCatalogScreen.kt
  10. 355 42
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/ProfileScreen.kt
  11. 2 1
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/RegistrationScreen.kt
  12. 69 5
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/ViewModelsPack/SupabaseAuthViewModel.kt
  13. 2 1
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/data/models/UsersTable.kt
  14. 2 0
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/data/network/TomatAndPotatClient.kt
  15. 5 5
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/navigationPack/Navigation.kt
  16. 0 9
      ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/navigationPack/Screens.kt
  17. BIN
      ProjectApp/TomatoAndPotatoAPP/app/src/main/res/drawable/plugavatar.jpg
  18. 2 1
      ProjectApp/TomatoAndPotatoAPP/build.gradle.kts
  19. 7 2
      ProjectApp/TomatoAndPotatoAPP/gradle/libs.versions.toml

+ 0 - 9
.idea/TomatoAndPotato.iml

@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$" />
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>

+ 0 - 6
.idea/misc.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectRootManager">
-    <output url="file://$PROJECT_DIR$/out" />
-  </component>
-</project>

+ 0 - 8
.idea/modules.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/.idea/TomatoAndPotato.iml" filepath="$PROJECT_DIR$/.idea/TomatoAndPotato.iml" />
-    </modules>
-  </component>
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="Git" />
-  </component>
-</project>

+ 0 - 51
.idea/workspace.xml

@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="AutoImportSettings">
-    <option name="autoReloadType" value="NONE" />
-  </component>
-  <component name="ChangeListManager">
-    <list default="true" id="c34c075b-3556-450b-af90-7bfdf4c1994b" name="Changes" comment="" />
-    <option name="SHOW_DIALOG" value="false" />
-    <option name="HIGHLIGHT_CONFLICTS" value="true" />
-    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
-    <option name="LAST_RESOLUTION" value="IGNORE" />
-  </component>
-  <component name="ClangdSettings">
-    <option name="formatViaClangd" value="false" />
-  </component>
-  <component name="Git.Settings">
-    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
-  </component>
-  <component name="ProjectColorInfo"><![CDATA[{
-  "associatedIndex": 4
-}]]></component>
-  <component name="ProjectId" id="2pC8lS67Ppau0Jr28DH6HxJyQe5" />
-  <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
-  <component name="ProjectViewState">
-    <option name="hideEmptyMiddlePackages" value="true" />
-    <option name="showLibraryContents" value="true" />
-  </component>
-  <component name="PropertiesComponent"><![CDATA[{
-  "keyToString": {
-    "RunOnceActivity.ShowReadmeOnStart": "true",
-    "RunOnceActivity.cidr.known.project.marker": "true",
-    "RunOnceActivity.readMode.enableVisualFormatting": "true",
-    "cf.first.check.clang-format": "false",
-    "cidr.known.project.marker": "true",
-    "git-widget-placeholder": "master",
-    "kotlin-language-version-configured": "true",
-    "last_opened_file_path": "D:/41/TomatoAndPotato/ProjectApp"
-  }
-}]]></component>
-  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
-  <component name="TaskManager">
-    <task active="true" id="Default" summary="Default task">
-      <changelist id="c34c075b-3556-450b-af90-7bfdf4c1994b" name="Changes" comment="" />
-      <created>1732258848027</created>
-      <option name="number" value="Default" />
-      <option name="presentableId" value="Default" />
-      <updated>1732258848027</updated>
-    </task>
-    <servers />
-  </component>
-</project>

+ 1 - 1
ProjectApp/TomatoAndPotatoAPP/.idea/kotlinc.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="KotlinJpsPluginSettings">
-    <option name="version" value="1.9.0" />
+    <option name="version" value="2.0.0" />
   </component>
 </project>

+ 8 - 0
ProjectApp/TomatoAndPotatoAPP/app/build.gradle.kts

@@ -1,6 +1,8 @@
 plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.jetbrains.kotlin.android)
+    alias(libs.plugins.compose.compiler)
+    id ("org.jetbrains.kotlin.plugin.serialization")
 }
 
 android {
@@ -68,6 +70,7 @@ dependencies {
     debugImplementation(libs.androidx.ui.test.manifest)
 
 
+
     implementation(platform(libs.bom))
     implementation(libs.postgrest.kt)
     implementation(libs.auth.kt)
@@ -77,5 +80,10 @@ dependencies {
 
     implementation(libs.androidx.navigation.compose)
 
+    implementation(libs.kotlinx.serialization.json)
+
+    implementation(libs.coil.compose)
+
+    implementation (libs.storage.kt)
 
 }

+ 6 - 3
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/AuthorizationScreen.kt

@@ -1,6 +1,7 @@
 package com.example.tomatoandpotatoapp.Screens
 
 import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -119,8 +120,10 @@ fun Authorization(
                         .fillMaxSize()
                         .padding(vertical = 90.dp)
                         .pointerInput(Unit) {
-                            keyboardController?.hide()
-                            focusManager.clearFocus()
+                            detectTapGestures(onTap = {
+                                keyboardController?.hide()
+                                focusManager.clearFocus()
+                            })
                         },
                     verticalArrangement = Arrangement.SpaceBetween,
                     horizontalAlignment = Alignment.CenterHorizontally
@@ -217,7 +220,7 @@ fun Authorization(
                 val message = (userState as UserState.Success).message
                 currentUserState = message
                 viewModel.selectPeople()
-                navController.navigate(Screens.AppNavigation.route)
+                navController.navigate(Screens.ProfileScreen.route)
                 f.value = false
             }
 

+ 14 - 10
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/PLantsCatalogScreen.kt

@@ -35,17 +35,17 @@ import androidx.navigation.NavController
 import com.example.tomatoandpotatoapp.ViewModelsPack.SupabaseAuthViewModel
 import androidx.lifecycle.viewmodel.compose.viewModel
 import com.example.tomatoandpotatoapp.R
+import com.example.tomatoandpotatoapp.navigationPack.Screens
 import com.example.tomatoandpotatoapp.utils.EditProfileString
 import io.github.jan.supabase.realtime.Column
 import io.ktor.http.ContentType
 import org.w3c.dom.Text
 
-@Preview
 
 @Composable
 fun ShowPlants(
-    //viewModel: SupabaseAuthViewModel = viewModel(),
-    // navController: NavController,
+    viewModel: SupabaseAuthViewModel = viewModel(),
+    navController: NavController,
 ) {
     Box(modifier = Modifier.fillMaxSize()) {
         Box(
@@ -62,17 +62,21 @@ fun ShowPlants(
                     )
                 )
         )
-        Column(modifier = Modifier.fillMaxSize()) {
+        Column(
+            modifier = Modifier.fillMaxSize()
+        ) {
             Row(
                 modifier = Modifier
                     .fillMaxWidth()
-                    .height(75.dp)
+                    .height(105.dp)
                     .background(color = Color(0xffD9D9D9)),
                 horizontalArrangement = Arrangement.Center,
                 verticalAlignment = Alignment.CenterVertically
             ) {
-                Column(modifier = Modifier
-                    .fillMaxHeight()){
+                Column(
+                    modifier = Modifier
+                        .fillMaxHeight(), verticalArrangement = Arrangement.Center
+                ) {
                     Text(
                         text = "Каталог",
                         fontWeight = FontWeight.W800,
@@ -106,13 +110,13 @@ fun ShowPlants(
             Row(
                 modifier = Modifier
                     .fillMaxWidth()
-                    .height(80.dp)
+                    .height(105.dp)
                     .align(Alignment.End)
                     .background(color = Color(0xff718588)),
                 horizontalArrangement = Arrangement.SpaceEvenly
             ) {
                 IconButton(
-                    onClick = { /*TODO*/ },
+                    onClick = { },
                     modifier = Modifier.size(120.dp)
                 ) {
                     Icon(
@@ -132,7 +136,7 @@ fun ShowPlants(
                     )
                 }
                 IconButton(
-                    onClick = { /*TODO*/ },
+                    onClick = { navController.navigate(Screens.ProfileScreen.route) },
                     modifier = Modifier.size(120.dp)
                 ) {
                     Icon(

+ 355 - 42
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/ProfileScreen.kt

@@ -1,17 +1,27 @@
 package com.example.tomatoandpotatoapp.Screens
 
-import android.widget.ImageButton
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.net.Uri
 import android.widget.Toast
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.PickVisualMediaRequest
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 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.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.shape.RoundedCornerShape
@@ -27,7 +37,6 @@ import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.OutlinedTextField
 import androidx.compose.material3.Text
-import androidx.compose.material3.TextFieldColors
 import androidx.compose.material3.TextFieldDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
@@ -36,30 +45,38 @@ import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.res.imageResource
+import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.unit.toSize
 import com.example.tomatoandpotatoapp.ViewModelsPack.SupabaseAuthViewModel
 import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavController
+import coil.compose.AsyncImagePainter
+import coil.compose.rememberAsyncImagePainter
+import coil.request.ImageRequest
 import com.example.tomatoandpotatoapp.R
 import com.example.tomatoandpotatoapp.data.models.UserState
 import com.example.tomatoandpotatoapp.navigationPack.Screens
 import com.example.tomatoandpotatoapp.utils.EditProfileString
+import java.io.ByteArrayOutputStream
 
 
-//@Preview
 @Composable
 fun MyProfile(
     viewModel: SupabaseAuthViewModel = viewModel(),
@@ -74,9 +91,14 @@ fun MyProfile(
     var mSelectedText by remember { mutableStateOf("") }
     var expanded by remember { mutableStateOf(false) }
     var mTextFieldSize by remember { mutableStateOf(Size.Zero) }
-
+    val keyboardController = LocalSoftwareKeyboardController.current
+    val focusManager = LocalFocusManager.current
     val genders = viewModel.genders
 
+    val save = remember { mutableStateOf(false) }
+
+    val addAvatar = remember { mutableStateOf(false) }
+
     val icon = if (expanded)
         Icons.Filled.KeyboardArrowUp
     else
@@ -88,17 +110,51 @@ fun MyProfile(
     }
 
     if (people.isNotEmpty()) {
+
+        val newAvatar = remember { mutableStateOf(byteArrayOf()) }
+
+        val avatarFrombase = rememberAsyncImagePainter(
+            model = ImageRequest.Builder(LocalContext.current).data(people.last().image)
+                .size(100, 100).build()
+        ).state
+
+        val launcher =
+            rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
+                if (uri == null) return@rememberLauncherForActivityResult
+                newAvatar.value = bitmapToByteArray(context, uri)
+
+            }
+
+
+        val newAvatarBitmap = remember { mutableStateOf<ImageBitmap?>(null) }
+
         val firstName = remember {
             mutableStateOf(people.last().firstName)
         }
         val genderId = remember {
-            mutableStateOf(people.last().genderId)
+            mutableStateOf(
+                if (people.last().genderId == null) {
+                    0
+                } else {
+                    people.last().genderId
+                }
+            )
         }
         val birthDate = remember {
-            mutableStateOf(people.last().birthDate)
+            mutableStateOf(
+                if (people.last().birthDate.isNullOrEmpty()) {
+                    ""
+                } else {
+                    people.last().birthDate
+                }
+            )
         }
 
-        Box(modifier = Modifier.fillMaxSize()) {
+        Box(
+            modifier = Modifier
+                .fillMaxSize()
+                .background(color = Color.White)
+        ) {
             Box(
                 modifier = Modifier
                     .fillMaxSize()
@@ -113,7 +169,16 @@ fun MyProfile(
                         )
                     )
             )
-            Column(modifier = Modifier.fillMaxSize()) {
+            Column(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .pointerInput(Unit) {
+                        detectTapGestures(onTap = {
+                            keyboardController?.hide()
+                            focusManager.clearFocus()
+                        })
+                    },
+            ) {
                 Row(
                     modifier = Modifier
                         .fillMaxWidth()
@@ -130,14 +195,143 @@ fun MyProfile(
                     )
                 }
 
+
+                Spacer(modifier = Modifier.height(60.dp))
+
+                Row(
+                    modifier = Modifier.fillMaxWidth(),
+                    horizontalArrangement = Arrangement.Center) {
+                    if (newAvatar.value.isEmpty()) {
+                        if (avatarFrombase is AsyncImagePainter.State.Success) {
+                            Box(
+                                modifier = Modifier
+                                    .width(100.dp)
+                                    .height(100.dp)
+                                    .clip(RoundedCornerShape(50.dp))
+                            ) {
+                                Button(
+                                    onClick = {
+                                        launcher.launch(
+                                            PickVisualMediaRequest(
+                                                ActivityResultContracts.PickVisualMedia.ImageOnly
+                                            )
+                                        )
+                                    },
+                                    colors = ButtonDefaults.buttonColors(
+                                        containerColor = Color.White,
+                                        disabledContainerColor = Color.White
+                                    ), modifier = Modifier
+                                        .width(100.dp)
+                                        .height(100.dp),
+                                    contentPadding = PaddingValues(0.dp)
+                                ) {
+                                    Image(
+                                        modifier = Modifier
+                                            .height(100.dp)
+                                            .width(100.dp),
+                                        painter = avatarFrombase.painter,
+                                        contentDescription = "",
+                                        contentScale = ContentScale.Crop
+                                    )
+                                }
+                            }
+                        }
+                        if (avatarFrombase is AsyncImagePainter.State.Loading) {
+                            Box(
+                                modifier = Modifier
+                                    .fillMaxWidth()
+                                    .height(200.dp),
+                                contentAlignment = Alignment.Center
+                            ) {
+                                CircularProgressIndicator()
+                            }
+                        }
+                        if (avatarFrombase is AsyncImagePainter.State.Error) {
+                            Box(
+                                modifier = Modifier
+                                    .width(100.dp)
+                                    .height(100.dp)
+                                    .clip(RoundedCornerShape(50.dp))
+                            ) {
+                                Button(
+                                    onClick = {
+                                        launcher.launch(
+                                            PickVisualMediaRequest(
+                                                ActivityResultContracts.PickVisualMedia.ImageOnly
+                                            )
+                                        )
+                                    },
+                                    colors = ButtonDefaults.buttonColors(
+                                        containerColor = Color.White,
+                                        disabledContainerColor = Color.White
+                                    ), modifier = Modifier
+                                        .width(100.dp)
+                                        .height(100.dp),
+                                    contentPadding = PaddingValues(0.dp)
+                                ) {
+                                    Image(
+                                        modifier = Modifier
+                                            .height(100.dp)
+                                            .width(100.dp),
+                                        painter = painterResource(R.drawable.plugavatar),
+                                        contentDescription = "",
+                                        contentScale = ContentScale.Crop
+                                    )
+                                }
+                            }
+                        }
+                    } else {
+                        newAvatarBitmap.value = ByteArrayImage(newAvatar.value)
+                        Box(
+                            modifier = Modifier
+                                .width(100.dp)
+                                .height(100.dp)
+                                .clip(RoundedCornerShape(50.dp))
+                        ) {
+                            Button(
+                                onClick = {
+                                    save.value = true
+                                    launcher.launch(
+                                        PickVisualMediaRequest(
+                                            ActivityResultContracts.PickVisualMedia.ImageOnly
+                                        )
+                                    )
+                                },
+                                colors = ButtonDefaults.buttonColors(
+                                    containerColor = Color.White,
+                                    disabledContainerColor = Color.White
+                                ), modifier = Modifier
+                                    .width(100.dp)
+                                    .height(100.dp),
+                                contentPadding = PaddingValues(0.dp)
+                            ) {
+                                Image(
+                                    modifier = Modifier
+                                        .height(100.dp)
+                                        .width(100.dp),
+                                    bitmap = newAvatarBitmap.value!!,
+                                    contentDescription = "",
+                                    contentScale = ContentScale.Crop
+                                )
+                            }
+                        }
+
+                    }
+                }
+
                 Spacer(modifier = Modifier.height(60.dp))
                 Row(
                     modifier = Modifier.fillMaxWidth(),
                     horizontalArrangement = Arrangement.Center
                 ) {
 
-                    EditProfileString(search = firstName.value,
-                        onValueChange = {firstName.value = it}, enabled = true)
+                    EditProfileString(
+                        search = firstName.value,
+                        onValueChange = {
+                            firstName.value = it
+                            save.value = true
+                        }, enabled = true
+                    )
                 }
 
                 Spacer(modifier = Modifier.height(30.dp))
@@ -147,31 +341,41 @@ fun MyProfile(
                     horizontalArrangement = Arrangement.Center
                 ) {
 
-                    EditProfileString(search = birthDate.value,
-                        onValueChange = {birthDate.value = it}, enabled = true)
+                    EditProfileString(
+                        search = birthDate.value!!,
+                        onValueChange = {
+                            birthDate.value = it
+                            save.value = true
+                        }, enabled = true
+                    )
                 }
 
                 Spacer(modifier = Modifier.height(30.dp))
 
-                Row(
+                Column(
                     modifier = Modifier.fillMaxWidth(),
-                    horizontalArrangement = Arrangement.Center
+                    verticalArrangement = Arrangement.Center,
+                    horizontalAlignment = Alignment.CenterHorizontally
                 ) {
 
                     OutlinedTextField(
                         value = mSelectedText,
-                        onValueChange = {  },
+                        onValueChange = { },
+
                         modifier = Modifier
                             .height(50.dp)
                             .width(316.dp)
                             .onGloballyPositioned { coordinates ->
                                 mTextFieldSize = coordinates.size.toSize()
+                            }
+                            .clickable {
+                                expanded = !expanded
                             },
                         shape = RoundedCornerShape(20),
+                        enabled = false,
                         colors = TextFieldDefaults.colors(
-                            focusedContainerColor = Color(0xFFF2D6FA),
-                            focusedIndicatorColor = Color(0xFF4C2259),
-                            focusedTextColor = Color.Black,
+                            disabledContainerColor = Color(0xFFF2D6FA),
+                            disabledTextColor = Color.Black,
                             disabledIndicatorColor = Color.Transparent,
                             unfocusedIndicatorColor = Color.Transparent,
                             cursorColor = Color.Black,
@@ -206,6 +410,7 @@ fun MyProfile(
                                     mSelectedText = label.genderTitle
                                     genderId.value = label.id
                                     expanded = false
+                                    save.value = true
                                 }
                             )
                         }
@@ -239,31 +444,53 @@ fun MyProfile(
 
                 Spacer(modifier = Modifier.height(110.dp))
 
-                Row(
-                    modifier = Modifier.fillMaxWidth(),
-                    horizontalArrangement = Arrangement.Center,
-                    verticalAlignment = Alignment.CenterVertically
-                ) {
-                    Button(
-                        onClick = { },
-                        modifier = Modifier
-                            .width(278.dp)
-                            .height(45.dp),
-                        shape = RoundedCornerShape(20),
-                        colors = ButtonDefaults
-                            .buttonColors(containerColor = Color(0xff78EE99))
-                    )
-                    {
-                        Text(
-                            text = "Сохранить",
-                            fontSize = 22.sp,
-                            fontWeight = FontWeight.W700,
-                            color = Color.White
+                if (save.value) {
+                    Row(
+                        modifier = Modifier.fillMaxWidth(),
+                        horizontalArrangement = Arrangement.Center,
+                        verticalAlignment = Alignment.CenterVertically
+                    ) {
+                        Button(
+                            onClick = {
+                                if (newAvatar.value.isEmpty()) {
+                                    if (genderId.value == 0) {
+                                        viewModel.updatePeople(
+                                            firstName.value,
+                                            null,
+                                            birthDate.value!!
+                                        )
+                                    } else {
+                                        viewModel.updatePeople(
+                                            firstName.value,
+                                            genderId.value!!,
+                                            birthDate.value!!
+                                        )
+                                    }
+                                    f.value = true
+                                } else {
+                                    viewModel.addAvatar(newAvatar.value)
+                                    addAvatar.value = true
+                                }
+                            },
+                            modifier = Modifier
+                                .width(278.dp)
+                                .height(45.dp),
+                            shape = RoundedCornerShape(20),
+                            colors = ButtonDefaults
+                                .buttonColors(containerColor = Color(0xff78EE99))
                         )
+                        {
+                            Text(
+                                text = "Сохранить",
+                                fontSize = 22.sp,
+                                fontWeight = FontWeight.W700,
+                                color = Color.White
+                            )
+                        }
                     }
                 }
 
-                Spacer(modifier = Modifier.height(25.dp))
+                Spacer(modifier = Modifier.height(5.dp))
 
                 Row(
                     modifier = Modifier.fillMaxWidth(),
@@ -271,7 +498,10 @@ fun MyProfile(
                     verticalAlignment = Alignment.CenterVertically
                 ) {
                     Button(
-                        onClick = {viewModel.singOut(context) },
+                        onClick = {
+                            viewModel.singOut(context)
+                            out.value = true
+                        },
                         modifier = Modifier
                             .width(278.dp)
                             .height(45.dp),
@@ -332,6 +562,45 @@ fun MyProfile(
                 }
             }
         }
+        if (addAvatar.value) {
+            when (userState) {
+                is UserState.Loading -> {
+                    CircularProgressIndicator()
+                }
+
+                is UserState.Success -> {
+                    if (genderId.value == 0) {
+                        viewModel.updatePeople(
+                            firstName.value,
+                            null,
+                            birthDate.value!!
+                        )
+                    } else {
+                        viewModel.updatePeople(
+                            firstName.value,
+                            genderId.value!!,
+                            birthDate.value!!
+                        )
+                    }
+                    addAvatar.value = false
+                    f.value = true
+                }
+
+                is UserState.Error -> {
+                    val message = (userState as UserState.Error).message
+                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
+                    addAvatar.value = false
+                }
+            }
+        }
+    }
+    else {
+        Box(
+            modifier = Modifier.fillMaxSize()
+        )
+        {
+            CircularProgressIndicator()
+        }
     }
     if (f.value) {
         when (userState) {
@@ -343,6 +612,7 @@ fun MyProfile(
                 val message = (userState as UserState.Success).message
                 Toast.makeText(context, "Данные успещно сохранены!", Toast.LENGTH_SHORT).show()
                 f.value = false
+                save.value = false
             }
 
             is UserState.Error -> {
@@ -371,3 +641,46 @@ fun MyProfile(
         }
     }
 }
+
+
+fun bitmapToByteArray(context: Context, uri: Uri): ByteArray {
+    val inputStream = context.contentResolver.openInputStream(uri)
+    val bitmap = BitmapFactory.decodeStream(inputStream)
+    val baos = ByteArrayOutputStream()
+    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos)
+    return baos.toByteArray()
+}
+
+fun ByteArrayImage(byteArray: ByteArray): ImageBitmap {
+    // Конвертируем массив байтов в Bitmap с уменьшением масштаба
+    val options = BitmapFactory.Options().apply {
+        inJustDecodeBounds = true // Сначала считываем только размеры изображения
+    }
+    BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
+
+    // Рассчитываем inSampleSize для уменьшения изображения
+    options.inSampleSize = calculateInSampleSize(options, reqWidth = 300, reqHeight = 200)
+    options.inJustDecodeBounds = false // Теперь декодируем само изображение
+
+    // Декодируем уменьшенное изображение
+    val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
+
+    // Преобразуем Bitmap в ImageBitmap
+    return bitmap.asImageBitmap()
+}
+
+fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
+    val (height: Int, width: Int) = options.outHeight to options.outWidth
+    var inSampleSize = 1
+
+    if (height > reqHeight || width > reqWidth) {
+        val halfHeight: Int = height / 2
+        val halfWidth: Int = width / 2
+
+        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
+            inSampleSize *= 2
+        }
+    }
+    return inSampleSize
+}
+

+ 2 - 1
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/Screens/RegistrationScreen.kt

@@ -208,8 +208,9 @@ fun Registration(
                     currentUserState = message
                     viewModel.addPeople()
                     viewModel.selectPeople()
-                    navController.navigate(Screens.AppNavigation.route)
+                    navController.navigate(Screens.ProfileScreen.route)
                     f.value = false
+
                 }
 
                 is UserState.Error -> {

+ 69 - 5
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/ViewModelsPack/SupabaseAuthViewModel.kt

@@ -2,6 +2,7 @@ package com.example.tomatoandpotatoapp.ViewModelsPack
 
 import android.content.Context
 import android.content.SharedPreferences
+import android.util.Log
 import androidx.compose.runtime.State
 import androidx.compose.runtime.mutableStateOf
 import androidx.lifecycle.ViewModel
@@ -18,6 +19,7 @@ import io.github.jan.supabase.auth.admin.AdminUserBuilder
 import io.github.jan.supabase.auth.auth
 import io.github.jan.supabase.auth.providers.builtin.Email
 import io.github.jan.supabase.postgrest.from
+import io.github.jan.supabase.storage.storage
 import kotlinx.coroutines.launch
 
 class SupabaseAuthViewModel : ViewModel() {
@@ -66,8 +68,10 @@ class SupabaseAuthViewModel : ViewModel() {
                 }
                 saveToken(context)
                 _userState.value = UserState.Success("Регистрация успешно пройдена!")
+                Log.d("ЧТо нибудь", "бла бла бла бебебе")
             } catch (e: Exception) {
                 _userState.value = UserState.Error("Error${e.message}")
+                Log.d("ЧТо нибудь", "${e.message}")
             }
         }
 
@@ -86,8 +90,11 @@ class SupabaseAuthViewModel : ViewModel() {
                 }
                 saveToken(context)
                 _userState.value = UserState.Success("Успешный вход!")
+
+                Log.d("ЧТо нибудь", "бла бла бла бебебе")
             } catch (e: Exception) {
                 _userState.value = UserState.Error("Error ${e.message}")
+                Log.d("ЧТо нибудь", "${e.message}")
             }
         }
     }
@@ -118,19 +125,69 @@ class SupabaseAuthViewModel : ViewModel() {
                         uid = client.auth.currentUserOrNull()!!.id
                     )
                 )
+                Log.d("ЧТо нибудь нужное и полезное нигер", "БЕЗУспешное получение дауна")
+            } catch (e: Exception) {
+                _userState.value = UserState.Error("Error ${e.message}")
+
+                Log.d("ЧТо нибудь", "${e.message}")
+            }
+        }
+    }
 
+    fun addAvatar(byteArray: ByteArray) {
+        viewModelScope.launch {
+            try {
 
+                _userState.value = UserState.Loading
+                val basket = client.storage["avatars"]
+                if(byteArray.isNotEmpty()){
+                    try {
+                        basket.upload(
+                            "${client.auth.currentUserOrNull()!!.email}.jpg",
+                            byteArray,
+                            options = { }
+                        )
+                        client.from("UsersTable").update(
+                            {
+                                UsersTable::image setTo basket.publicUrl("${client.auth.currentUserOrNull()!!.email}.jpg")
+
+                            }
+                        ) {
+                            filter {
+                                UsersTable::uid eq client.auth.currentUserOrNull()!!.id
+                            }
+                        }
+                    }catch (e: Exception){
+                        basket.update(
+                            "${client.auth.currentUserOrNull()!!.email}.jpg",
+                            byteArray,
+                            options = { }
+                        )
+                        client.from("UsersTable").update(
+                            {
+                                UsersTable::image setTo basket.publicUrl("${client.auth.currentUserOrNull()!!.email}.jpg")
+
+                            }
+                        ) {
+                            filter {
+                                UsersTable::uid eq client.auth.currentUserOrNull()!!.id
+                            }
+                        }
+                    }
+                }
+                _userState.value = UserState.Success("ВАУ КРУТО добавлена фото")
             } catch (e: Exception) {
-                _userState.value = UserState.Error("Error ${e.message}")
+                _userState.value = UserState.Error("Error: ${e.message}")
+                Log.d("Что-то надо там", e.message!!)
             }
         }
     }
 
-    fun updatePeople(firstname: String, genderId: Int, birthDate: String) {
+    fun updatePeople(firstname: String, genderId: Int?, birthDate: String) {
         viewModelScope.launch {
             try {
                 _userState.value = UserState.Loading
-                client.from("Users").update({
+                client.from("UsersTable").update({
                     UsersTable::firstName setTo firstname
                     UsersTable::genderId setTo genderId
                     UsersTable::birthDate setTo birthDate
@@ -138,10 +195,12 @@ class SupabaseAuthViewModel : ViewModel() {
                 {
                     filter { UsersTable::uid eq client.auth.currentUserOrNull()!!.id }
                 }
-
+                _userState.value = UserState.Success("УРА МЫ ОБНОВИЛИСЬ НЕГРЫ")
+                Log.d("ЧТо нибудь нужное и полезное нигер", "БЕЗУспешное обновление дауна")
 
             } catch (e: Exception) {
                 _userState.value = UserState.Error("Error ${e.message}")
+                Log.d("ЧТо нибудь", "${e.message}")
             }
         }
     }
@@ -150,15 +209,18 @@ class SupabaseAuthViewModel : ViewModel() {
         viewModelScope.launch {
             try {
                 _userState.value = UserState.Loading
-                _user.value = client.from("Users").select {
+                _user.value = client.from("UsersTable").select {
                     filter {
                         UsersTable::uid eq
                                 client.auth.currentUserOrNull()!!.id
                     }
                 }.decodeList<UsersTable>()
+                _userState.value = UserState.Success("Успешное получение дауна")
+                Log.d("ЧТо нибудь нужное и полезное нигер", "БЕЗУспешное получение дауна")
 
             } catch (e: Exception) {
                 _userState.value = UserState.Error("Error ${e.message}")
+                Log.d("ЧТо нибудь", "${e.message}")
             }
         }
     }
@@ -176,10 +238,12 @@ class SupabaseAuthViewModel : ViewModel() {
                     client.auth.refreshCurrentSession()
                     saveToken(context)
                     _userState.value = UserState.Success("Пользователь уже вошёл в систему")
+                    Log.d("ЧТо нибудь", "Какая-то ошибка")
                 }
 
             } catch (e: Exception) {
                 _userState.value = UserState.Error("Error${e.message}")
+                Log.d("ЧТо нибудь", "${e.message}")
             }
         }
     }

+ 2 - 1
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/data/models/UsersTable.kt

@@ -8,7 +8,8 @@ data class UsersTable (
     val id:Int? = null,
     val firstName:String = "",
     val genderId:Int? = null,
-    val birthDate:String = "",
+    val birthDate:String? = null,
     val idRole:Int,
+    val image: String = "",
     val uid:String = ""
 )

+ 2 - 0
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/data/network/TomatAndPotatClient.kt

@@ -4,6 +4,7 @@ import io.github.jan.supabase.auth.Auth
 import io.github.jan.supabase.createSupabaseClient
 import io.github.jan.supabase.postgrest.Postgrest
 import io.github.jan.supabase.postgrest.PropertyConversionMethod
+import io.github.jan.supabase.storage.Storage
 
 object TomatAndPotatClient {
     val client = createSupabaseClient(
@@ -11,6 +12,7 @@ object TomatAndPotatClient {
         supabaseKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhqYnBieW9ja255eHNtd2R2bHVlIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE5NDY5MzQsImV4cCI6MjA0NzUyMjkzNH0.HesTDGPfqxlMuRqecMCxCyJHsPKuYBpUfgJh9Nc-_00"
     ){
         install(Auth)
+        install(Storage)
         install(Postgrest){
             propertyConversionMethod = PropertyConversionMethod.SERIAL_NAME
         }

+ 5 - 5
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/navigationPack/Navigation.kt

@@ -32,15 +32,15 @@ fun Navigation(viewModel: SupabaseAuthViewModel) {
         composable(route = Screens.RegistrationScreen.route) {
             Registration(viewModel,navController)
         }
-        composable(route = Screens.AppNavigation.route)
-        {
-            AppNavigation(viewModel)
-        }
+//        composable(route = Screens.AppNavigation.route)
+//        {
+//            //AppNavigation(viewModel)
+//        }
         composable(route = Screens.ProfileScreen.route) {
             MyProfile(viewModel,navController)
         }
         composable(route = Screens.PlantsCatalogScreen.route) {
-            //ShowPlants(viewModel,navController)
+            ShowPlants(viewModel,navController)
         }
     }
 

+ 0 - 9
ProjectApp/TomatoAndPotatoAPP/app/src/main/java/com/example/tomatoandpotatoapp/navigationPack/Screens.kt

@@ -9,14 +9,5 @@ sealed class Screens(val route: String) {
     object RegistrationScreen : Screens("registration_screen")
     object ProfileScreen : Screens("profile_screen")
     object PlantsCatalogScreen : Screens("plants_catalog_screen")
-    object AppNavigation: Screens("app_navigation")
 
-    fun withArgs(vararg args: String): String {
-        return buildString {
-            append(route)
-            args.forEach { arg ->
-                append("/$arg")
-            }
-        }
-    }
 }

BIN
ProjectApp/TomatoAndPotatoAPP/app/src/main/res/drawable/plugavatar.jpg


+ 2 - 1
ProjectApp/TomatoAndPotatoAPP/build.gradle.kts

@@ -2,5 +2,6 @@
 plugins {
     alias(libs.plugins.android.application) apply false
     alias(libs.plugins.jetbrains.kotlin.android) apply false
-    kotlin("plugin.serialization") version "1.9.0"
+    kotlin("plugin.serialization") version "1.6.21"
+    kotlin("jvm") version "1.4.21"
 }

+ 7 - 2
ProjectApp/TomatoAndPotatoAPP/gradle/libs.versions.toml

@@ -1,11 +1,13 @@
 [versions]
 agp = "8.5.1"
 bom = "3.0.1"
-kotlin = "1.9.0"
+coilCompose = "2.2.2"
+kotlin = "2.0.0"
 coreKtx = "1.13.1"
 junit = "4.13.2"
 junitVersion = "1.2.1"
 espressoCore = "3.6.1"
+kotlinxSerializationJson = "1.7.3"
 ktorClientAndroid = "3.0.0"
 lifecycleRuntimeKtx = "2.8.6"
 activityCompose = "1.9.2"
@@ -17,6 +19,7 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
 androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
 auth-kt = { module = "io.github.jan-tennert.supabase:auth-kt" }
 bom = { module = "io.github.jan-tennert.supabase:bom", version.ref = "bom" }
+coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" }
 junit = { group = "junit", name = "junit", version.ref = "junit" }
 androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
 androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@@ -30,11 +33,13 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
 androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
 androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
 androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
 ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorClientAndroid" }
 postgrest-kt = { module = "io.github.jan-tennert.supabase:postgrest-kt" }
 realtime-kt = { module = "io.github.jan-tennert.supabase:realtime-kt" }
+storage-kt = { module = "io.github.jan-tennert.supabase:storage-kt", version.ref = "bom" }
 
 [plugins]
 android-application = { id = "com.android.application", version.ref = "agp" }
 jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
-
+compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }