Bobarik31p hai 1 mes
pai
achega
4a83fab01c

+ 7 - 16
app/src/main/java/com/example/tasks/MainActivity.kt

@@ -1,36 +1,27 @@
 package com.example.tasks
 
+import android.os.Build
 import android.os.Bundle
-import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateListOf
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import com.example.tasks.components.Constants
-import com.example.tasks.model.Gender
-import com.example.tasks.model.User
+import androidx.annotation.RequiresApi
 import com.example.tasks.navigation.Navigation
 import com.example.tasks.ui.theme.TasksTheme
 import com.example.tasks.viewModels.AuthViewModel
-import io.github.jan.supabase.postgrest.from
-import io.github.jan.supabase.postgrest.postgrest
-import io.github.jan.supabase.postgrest.query.Columns
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
+import com.example.tasks.viewModels.DatabaseViewModel
 
 class MainActivity : ComponentActivity() {
+    @RequiresApi(Build.VERSION_CODES.O)
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         enableEdgeToEdge()
         setContent {
             TasksTheme {
                 val viewModel = AuthViewModel()
-                Navigation(viewModel)
+                val databaseViewModel = DatabaseViewModel()
+
+                Navigation(viewModel, databaseViewModel)
 
 
             }

+ 1 - 0
app/src/main/java/com/example/tasks/components/CustomEmail.kt

@@ -1,5 +1,6 @@
 package com.example.tasks.components
 
+import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxWidth

+ 11 - 5
app/src/main/java/com/example/tasks/navigation/Navigation.kt

@@ -10,17 +10,23 @@ import androidx.navigation.compose.composable
 import androidx.navigation.compose.rememberNavController
 import androidx.navigation.navArgument
 import com.example.tasks.screens.EnterOTP
+import com.example.tasks.screens.Load
 import com.example.tasks.screens.Profile
 import com.example.tasks.screens.SignIn
 import com.example.tasks.screens.Start
 import com.example.tasks.viewModels.AuthViewModel
+import com.example.tasks.viewModels.DatabaseViewModel
 
 @RequiresApi(Build.VERSION_CODES.O)
 @Composable
-fun Navigation(viewModel: AuthViewModel) {
+fun Navigation(viewModel: AuthViewModel,databaseViewModel: DatabaseViewModel) {
     val navController = rememberNavController()
-    NavHost(navController = navController, startDestination = Screen.Start.route)
+    NavHost(navController = navController, startDestination = Screen.Load.route)
     {
+        composable(Screen.Load.route)
+        {
+            Load(viewModel,navController)
+        }
         composable(Screen.Start.route)
         {
             Start(navController)
@@ -37,18 +43,18 @@ fun Navigation(viewModel: AuthViewModel) {
         ))
         {
             val email = it.arguments!!.getString("email")
-            EnterOTP(navController = navController, email = email!!,viewModel)
+            EnterOTP(navController = navController, email = email!!,viewModel,databaseViewModel)
 
 
         }
         composable(Screen.CreateProfile.route)
         {
-            CreateProfile(navController,viewModel)
+            CreateProfile(navController,viewModel,databaseViewModel)
 
         }
         composable(Screen.Profile.route)
         {
-            Profile()
+            Profile(databaseViewModel,viewModel, navController )
 
         }
     }

+ 1 - 0
app/src/main/java/com/example/tasks/navigation/Screen.kt

@@ -7,6 +7,7 @@ sealed class Screen(val route:String) {
     object EnterOTP: Screen("enterOTP")
     object CreateProfile: Screen("createProfile")
     object Profile:Screen("profile")
+    object Load:Screen("load")
 
     fun withArg(vararg args: String): String {
         return buildString {

+ 3 - 1
app/src/main/java/com/example/tasks/screens/CreateProfile.kt

@@ -61,6 +61,7 @@ import com.example.tasks.model.UserState
 import com.example.tasks.navigation.Screen
 import com.example.tasks.screens.LoadingComponent
 import com.example.tasks.viewModels.AuthViewModel
+import com.example.tasks.viewModels.DatabaseViewModel
 import com.vanpra.composematerialdialogs.MaterialDialog
 import com.vanpra.composematerialdialogs.datetime.date.datepicker
 import com.vanpra.composematerialdialogs.rememberMaterialDialogState
@@ -70,7 +71,7 @@ import java.time.format.DateTimeFormatter
 
 @RequiresApi(Build.VERSION_CODES.O)
 @Composable
-fun CreateProfile(navController: NavController, viewModel: AuthViewModel) {
+fun CreateProfile(navController: NavController, viewModel: AuthViewModel,viewModelDatabase:DatabaseViewModel) {
     val context = LocalContext.current
     val enabled = remember { mutableStateOf(true) }
     val dateDialogState = rememberMaterialDialogState()
@@ -453,6 +454,7 @@ fun CreateProfile(navController: NavController, viewModel: AuthViewModel) {
                     currentUserState = message
 
                     navController.navigate(Screen.Profile.route)
+                    viewModelDatabase.profileData()
                     flag.value = false
                 }
 

+ 3 - 1
app/src/main/java/com/example/tasks/screens/EnterOTP.kt

@@ -65,6 +65,7 @@ import com.example.tasks.model.User
 import com.example.tasks.model.UserState
 import com.example.tasks.navigation.Screen
 import com.example.tasks.viewModels.AuthViewModel
+import com.example.tasks.viewModels.DatabaseViewModel
 import io.github.jan.supabase.postgrest.from
 import io.github.jan.supabase.postgrest.query.Columns
 import kotlinx.coroutines.Dispatchers
@@ -72,7 +73,7 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.withContext
 
 @Composable
-fun EnterOTP(navController: NavController, email: String, viewModel: AuthViewModel) {
+fun EnterOTP(navController: NavController, email: String, viewModel: AuthViewModel,viewModelDatabase:DatabaseViewModel) {
     val userState by viewModel.userState
     var currentUserState by remember { mutableStateOf("") }
     val focusManager = LocalFocusManager.current
@@ -266,6 +267,7 @@ fun EnterOTP(navController: NavController, email: String, viewModel: AuthViewMod
 
                     if (viewModel.users.isNotEmpty()) {
                         navController.navigate(Screen.Profile.route)
+                        viewModelDatabase.profileData()
                     } else {
                         navController.navigate(Screen.CreateProfile.route)
                     }

+ 55 - 0
app/src/main/java/com/example/tasks/screens/Load.kt

@@ -0,0 +1,55 @@
+package com.example.tasks.screens
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+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.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.navigation.NavController
+import com.example.tasks.model.UserState
+import com.example.tasks.navigation.Screen
+import com.example.tasks.viewModels.AuthViewModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+@Composable
+fun Load(viewModel: AuthViewModel, navController: NavController) {
+    val context = LocalContext.current
+    val userState by viewModel.userState
+    val flag = remember { mutableStateOf(true) }
+    LaunchedEffect(Unit) {
+        withContext(Dispatchers.IO) {
+            viewModel.isUserLoggedIn(context)
+        }
+    }
+    if (flag.value) {
+        when (userState) {
+            is UserState.Loading -> {
+                Column(
+                    Modifier.fillMaxSize(),
+                    horizontalAlignment = Alignment.CenterHorizontally,
+                    verticalArrangement = Arrangement.Center
+                ) {
+                    Text("Хай")
+                }
+            }
+
+            is UserState.Success -> {
+                navController.navigate(Screen.Profile.route)
+                flag.value = false
+            }
+
+            is UserState.Error -> {
+                navController.navigate(Screen.Start.route)
+                flag.value = false
+            }
+        }
+    }
+}

+ 222 - 28
app/src/main/java/com/example/tasks/screens/Profile.kt

@@ -1,45 +1,239 @@
 package com.example.tasks.screens
 
+import android.content.Context
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.layout.Row
+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.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ExitToApp
 import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Icon
 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 com.example.tasks.components.Constants
-import com.example.tasks.model.User
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import coil.compose.AsyncImagePainter
+import coil.compose.rememberAsyncImagePainter
+import coil.request.ImageRequest
+import coil.size.Size
+import com.example.tasks.model.UserState
+import com.example.tasks.navigation.Screen
+import com.example.tasks.viewModels.AuthViewModel
 import com.example.tasks.viewModels.DatabaseViewModel
-import io.github.jan.supabase.gotrue.auth
-import io.github.jan.supabase.postgrest.from
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
 
 @Composable
-fun Profile() {
-    val viewModel = DatabaseViewModel()
-    //viewModel.profileData()
-    var users by remember { mutableStateOf<List<User>>(listOf()) }
-    LaunchedEffect(Unit) {
-        withContext(Dispatchers.IO) {
-            users = Constants.supabase.from("Users").select {
-                filter {
-                    User::UID eq Constants.supabase.auth.currentUserOrNull()!!.id
+fun Profile(
+    viewModel: DatabaseViewModel,
+    viewModelAuth: AuthViewModel,
+    navController: NavController
+) {
+    val userState by viewModel.userState
+    val users by viewModel.users
+    val flag = remember { mutableStateOf(true) }
+    val context = LocalContext.current
+    if (flag.value) {
+        viewModel.profileData()
+        flag.value = false
+    }
+
+
+    if (users.isNotEmpty()) {
+        val avatar = rememberAsyncImagePainter(
+            model = ImageRequest.Builder(LocalContext.current).data(users.last().avatar)
+                .size(Size.ORIGINAL).build()
+        ).state
+        Column(
+            modifier = Modifier
+                .fillMaxSize()
+                .padding(30.dp)
+                .padding(top = 30.dp, bottom = 100.dp),
+            verticalArrangement = Arrangement.SpaceAround,
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            Row(
+                modifier = Modifier.fillMaxWidth(0.7f),
+                horizontalArrangement = Arrangement.SpaceBetween
+            ) {
+                Text(
+                    "Профиль",
+                    fontSize = 30.sp,
+                    fontWeight = FontWeight.W700,
+                    color = Color(0xFF4C2259)
+                )
+                Icon(Icons.Filled.ExitToApp, "",
+                    Modifier
+                        .background(Color.Red)
+                        .clickable {
+                            Logout(viewModelAuth, context,navController)
+                        })
+            }
+
+            if (avatar is AsyncImagePainter.State.Success) {
+                Box(
+                    modifier = Modifier
+                        .width(100.dp)
+                        .height(100.dp)
+                        .clip(RoundedCornerShape(50.dp))
+                ) {
+                    Image(
+                        modifier = Modifier
+                            .fillMaxWidth()
+                            .height(200.dp),
+                        painter = avatar.painter,
+                        contentDescription = "",
+                        contentScale = ContentScale.Crop
+                    )
                 }
-            }.decodeList<User>()
-        }
+            }
+            if (avatar is AsyncImagePainter.State.Error) {
+                Box(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .height(200.dp),
+                    contentAlignment = Alignment.Center
+                ) {
+                    CircularProgressIndicator()
+                }
+            }
 
-    }
-    if (users.size == 0) {
-        CircularProgressIndicator()
-    }
-        Column {
-            Text(text = viewModel.users.value.last().LastName)
-            Text(text = viewModel.users.value.last().FirstName)
-            Text(text = viewModel.users.value.last().DateOfBirth)
+            Box(
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .height(50.dp)
+                    .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                    .clip(RoundedCornerShape(10.dp))
+                    .background(
+                        Color(0xFFF2D6FA)
+                    )
+                    .padding(10.dp),
+                contentAlignment = Alignment.CenterStart
+            ) {
+                Text(users.last().LastName)
+            }
+            Box(
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .height(50.dp)
+                    .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                    .clip(RoundedCornerShape(10.dp))
+                    .background(
+                        Color(0xFFF2D6FA)
+                    )
+                    .padding(10.dp),
+                contentAlignment = Alignment.CenterStart
+            ) {
+                Text(users.last().FirstName)
+            }
+            if (users.last().Patronymic != "") {
+                Box(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .height(50.dp)
+                        .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                        .clip(RoundedCornerShape(10.dp))
+                        .background(
+                            Color(0xFFF2D6FA)
+                        )
+                        .padding(10.dp),
+                    contentAlignment = Alignment.CenterStart
+                ) {
+                    Text(users.last().Patronymic!!)
+                }
+            }
+            Box(
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .height(50.dp)
+                    .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                    .clip(RoundedCornerShape(10.dp))
+                    .background(
+                        Color(0xFFF2D6FA)
+                    )
+                    .padding(10.dp),
+                contentAlignment = Alignment.CenterStart
+            ) {
+                Text(users.last().DateOfBirth)
+            }
+            if (users.last().Gender == 1) {
+                Box(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .height(50.dp)
+                        .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                        .clip(RoundedCornerShape(10.dp))
+                        .background(
+                            Color(0xFFF2D6FA)
+                        )
+                        .padding(10.dp),
+                    contentAlignment = Alignment.CenterStart
+                ) {
+                    Text("Женский")
+                }
+            } else {
+                Box(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .height(50.dp)
+                        .border(1.dp, Color(0xFF4C2259), RoundedCornerShape(10.dp))
+                        .clip(RoundedCornerShape(10.dp))
+                        .background(
+                            Color(0xFFF2D6FA)
+                        )
+                        .padding(10.dp),
+                    contentAlignment = Alignment.CenterStart
+                ) {
+                    Text("Мужской")
+                }
+            }
 
+        }
+    } else {
+        Column(Modifier.fillMaxSize()) {
+            CircularProgressIndicator()
+        }
     }
+
+
 }
+
+private fun Logout(viewModelAuth: AuthViewModel, context: Context, navController: NavController) {
+    val userState by viewModelAuth.userState
+    viewModelAuth.logout(context)
+
+    when (userState) {
+        is UserState.Loading -> {
+        }
+
+        is UserState.Success -> {
+            navController.navigate(Screen.Start.route)
+        }
+
+
+        is UserState.Error -> {
+        }
+    }
+
+
+}

+ 16 - 1
app/src/main/java/com/example/tasks/viewModels/AuthViewModel.kt

@@ -164,7 +164,7 @@ class AuthViewModel : ViewModel() {
                             Gender = 2,
                             UID = Constants.supabase.auth.currentUserOrNull()!!.id,
                             Patronymic = patronymic,
-                            avatar = basket.createSignedUrl("${Constants.supabase.auth.currentUserOrNull()!!.email}.jpg", expiresIn = 20.minutes)
+                            avatar = basket.publicRenderUrl("${Constants.supabase.auth.currentUserOrNull()!!.email}.jpg")
                         )
                     )
                 }
@@ -197,4 +197,19 @@ class AuthViewModel : ViewModel() {
             }
         }
     }
+
+    fun logout(context: Context) {
+        val sharedPref = SharedPreferenceHelper(context)
+        viewModelScope.launch {
+            try {
+                _userState.value = UserState.Loading
+                Constants.supabase.auth.signOut()
+                sharedPref.clearPreferences()
+                _userState.value = UserState.Success("Logged out successfully!")
+            } catch (e: Exception) {
+                _userState.value = UserState.Error(e.message ?: "")
+                Log.d("my_tag",e.message!!)
+            }
+        }
+    }
 }

+ 5 - 0
app/src/main/java/com/example/tasks/viewModels/DatabaseViewModel.kt

@@ -13,19 +13,24 @@ import io.github.jan.supabase.postgrest.from
 import kotlinx.coroutines.launch
 
 class DatabaseViewModel : ViewModel() {
+    private val _userState = mutableStateOf<UserState>(UserState.Loading)
+    val userState: State<UserState> = _userState
     private val _users = mutableStateOf(listOf<User>())
     val users: State<List<User>> = _users
     fun profileData() {
         viewModelScope.launch {
             try {
+                _userState.value = UserState.Loading
                  _users.value = Constants.supabase.from("Users").select {
                     filter {
                         User::UID eq Constants.supabase.auth.currentUserOrNull()!!.id
                     }
                 }.decodeList<User>()
                 Log.d("my_tag","ГУУУУД")
+                _userState.value = UserState.Success("Профиль найден")
 
             } catch (e: Exception) {
+                _userState.value = UserState.Error("Профиль не найден")
                 Log.d("mu_tag",e.message!!)
             }
         }